? line.patch
? take3.patch
Index: gtksourceview/gtksourcebuffer.c
===================================================================
RCS file: /cvs/gnome/gtksourceview/gtksourceview/gtksourcebuffer.c,v
retrieving revision 1.39
diff -u -p -r1.39 gtksourcebuffer.c
--- gtksourceview/gtksourcebuffer.c	21 Jun 2005 17:29:28 -0000	1.39
+++ gtksourceview/gtksourcebuffer.c	19 Jul 2005 20:34:39 -0000
@@ -90,6 +90,8 @@ enum {
 	PROP_ESCAPE_CHAR,
 	PROP_CHECK_BRACKETS,
 	PROP_HIGHLIGHT,
+	PROP_HIGHLIGHT_CURRENT_LINE,
+	PROP_HIGHLIGHT_CURRENT_LINE_COLOR,
 	PROP_MAX_UNDO_LEVELS,
 	PROP_LANGUAGE
 };
@@ -110,8 +112,11 @@ struct _PatternMatch
 struct _GtkSourceBufferPrivate 
 {
 	gint                   highlight:1;
+	gint                   highlight_current_line:1;
 	gint                   check_brackets:1;
 
+	GdkColor              *highlight_current_line_color;
+
 	GtkTextTag            *bracket_match_tag;
 	GtkTextMark           *bracket_mark;
 	guint                  bracket_found:1;
@@ -301,6 +306,24 @@ gtk_source_buffer_class_init (GtkSourceB
 							       G_PARAM_READWRITE));
 	
 	g_object_class_install_property (object_class,
+					 PROP_HIGHLIGHT_CURRENT_LINE,
+					 g_param_spec_boolean ("highlight_current_line",
+							       _("Highlight Current Line"),
+							       _("Whether to highlight the "
+								 "active line in the buffer"),
+							       FALSE,
+							       G_PARAM_READWRITE));
+	
+	g_object_class_install_property (object_class,
+					 PROP_HIGHLIGHT_CURRENT_LINE_COLOR,
+					 g_param_spec_boxed ("highlight_current_line_color",
+							     _("Highlight Current Line Color"),
+							     _("The color used to highlight the "
+							       "active line in the buffer"),
+							     GDK_TYPE_COLOR,
+							     G_PARAM_READWRITE));
+	
+	g_object_class_install_property (object_class,
 					 PROP_MAX_UNDO_LEVELS,
 					 g_param_spec_int ("max_undo_levels",
 							   _("Maximum Undo Levels"),
@@ -375,6 +398,8 @@ gtk_source_buffer_init (GtkSourceBuffer 
 
 	buffer->priv = priv;
 
+	priv->highlight_current_line_color = NULL;
+
 	priv->undo_manager = gtk_source_undo_manager_new (GTK_TEXT_BUFFER (buffer));
 
 	priv->check_brackets = TRUE;
@@ -480,6 +505,10 @@ gtk_source_buffer_constructor (GType    
 
 		gtk_source_tag_style_free (tag_style);
 
+		/* Create paragraph-background tag for highlighting lines. */
+		gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (source_buffer),
+					    "highlightline", NULL);
+
 		if (GTK_IS_SOURCE_TAG_TABLE (GTK_TEXT_BUFFER (source_buffer)->tag_table))
 		{
 			g_signal_connect (GTK_TEXT_BUFFER (source_buffer)->tag_table ,
@@ -526,6 +555,11 @@ gtk_source_buffer_finalize (GObject *obj
 	if (buffer->priv->worker_handler) {
 		g_source_remove (buffer->priv->worker_handler);
 	}
+	
+	if (buffer->priv->highlight_current_line_color) {
+		gdk_color_free (buffer->priv->highlight_current_line_color);
+		buffer->priv->highlight_current_line_color = NULL;
+	}
 
 	/* we can't delete marks if we're finalizing the buffer */
 	gtk_text_region_destroy (buffer->priv->refresh_region, FALSE);
@@ -593,6 +627,16 @@ gtk_source_buffer_set_property (GObject 
 							 g_value_get_boolean (value));
 			break;
 			
+		case PROP_HIGHLIGHT_CURRENT_LINE:
+			gtk_source_buffer_set_highlight_current_line (source_buffer,
+								      g_value_get_boolean (value));
+			break;
+			
+		case PROP_HIGHLIGHT_CURRENT_LINE_COLOR:
+			gtk_source_buffer_set_highlight_current_line_color (source_buffer,
+									    g_value_get_boxed (value));
+			break;
+			
 		case PROP_MAX_UNDO_LEVELS:
 			gtk_source_buffer_set_max_undo_levels (source_buffer,
 							       g_value_get_int (value));
@@ -635,6 +679,14 @@ gtk_source_buffer_get_property (GObject 
 			g_value_set_boolean (value, source_buffer->priv->highlight);
 			break;
 			
+		case PROP_HIGHLIGHT_CURRENT_LINE:
+			g_value_set_boolean (value, source_buffer->priv->highlight_current_line);
+			break;
+			
+		case PROP_HIGHLIGHT_CURRENT_LINE_COLOR:
+			g_value_set_boxed (value, source_buffer->priv->highlight_current_line_color);
+			break;
+			
 		case PROP_MAX_UNDO_LEVELS:
 			g_value_set_int (value,
 					 gtk_source_buffer_get_max_undo_levels (source_buffer));
@@ -738,6 +790,82 @@ get_tags_func (GtkTextTag *tag, gpointer
 }
 
 static void
+add_highlight_to_line (GtkTextBuffer *buffer, GtkTextIter *lineiter)
+{
+	GtkTextIter start, end;
+
+	/* Don't highlight the active line when the user has selected 1 or more lines. */
+	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+	if (!gtk_text_iter_equal (&start, &end) &&
+	    gtk_text_iter_starts_line (&start) &&
+	    gtk_text_iter_ends_line (&end))
+		return;
+	else if (gtk_text_iter_get_line (&start) != gtk_text_iter_get_line (&end))
+		return;
+
+	start = end = *lineiter;
+	
+	/* Highlight from the start of the current line to the end of the line. */
+	/* If the line is empty, highlight to the start of the next line. */
+	gtk_text_iter_set_line_index (&start, 0);
+	if (!gtk_text_iter_ends_line (&end))
+		gtk_text_iter_forward_to_line_end (&end);
+	else if (gtk_text_iter_starts_line (&end))
+		gtk_text_iter_forward_visible_line (&end);
+
+	gtk_text_buffer_apply_tag_by_name (buffer, "highlightline", &start, &end);
+	gtk_text_buffer_move_mark_by_name (buffer, "highlightline", lineiter);
+}
+
+static void
+remove_highlight_from_line (GtkTextBuffer *buffer, GtkTextIter *lineiter)
+{
+	GtkTextIter start, end;
+	GtkTextTagTable *table;
+	GtkTextTag *tag;
+
+	start = end = *lineiter;
+	table = gtk_text_buffer_get_tag_table (buffer);
+	tag = gtk_text_tag_table_lookup (table, "highlightline");
+
+	gtk_text_iter_set_line_index (&start, 0);
+	gtk_text_iter_forward_to_tag_toggle (&end, tag);
+	
+	gtk_text_buffer_remove_tag_by_name (buffer, "highlightline", &start, &end);
+}
+
+static void
+update_highlighted_line (GtkTextBuffer *buffer, GtkTextIter *iter, gboolean enable)
+{
+	GtkTextMark *mark;
+	GtkTextTagTable *table;
+	GtkTextTag *tag;
+	GtkTextIter hliter;
+
+	mark = gtk_text_buffer_get_mark (buffer, "highlightline");
+	table = gtk_text_buffer_get_tag_table (buffer);
+	tag = gtk_text_tag_table_lookup (table, "highlightline");
+	
+	if (!mark && enable) {
+		gtk_text_buffer_create_mark (buffer, "highlightline", iter, FALSE);
+		add_highlight_to_line (buffer, iter);
+	} else if (enable) {
+		gtk_text_buffer_get_iter_at_mark (buffer, &hliter, mark);
+
+		/* Check if the current line isn't already highlighted. */
+		if (!gtk_text_iter_has_tag (iter, tag))
+		{
+			remove_highlight_from_line (buffer, &hliter);
+			add_highlight_to_line (buffer, iter);
+		}
+	} else {
+		gtk_text_buffer_get_iter_at_mark (buffer, &hliter, mark);
+		remove_highlight_from_line (buffer, &hliter);
+		gtk_text_buffer_delete_mark (buffer, mark);
+	}
+}
+
+static void
 gtk_source_buffer_move_cursor (GtkTextBuffer *buffer,
 			       GtkTextIter   *iter, 
 			       GtkTextMark   *mark, 
@@ -753,6 +881,9 @@ gtk_source_buffer_move_cursor (GtkTextBu
 	if (mark != gtk_text_buffer_get_insert (buffer))
 		return;
 
+	if (GTK_SOURCE_BUFFER (buffer)->priv->highlight_current_line)
+		update_highlighted_line (buffer, iter, TRUE);
+
 	if (GTK_SOURCE_BUFFER (buffer)->priv->bracket_found) 
 	{
 		gtk_text_buffer_get_iter_at_mark (buffer,
@@ -1504,6 +1635,89 @@ gtk_source_buffer_set_highlight (GtkSour
 							  &iter2);
 	}
 	g_object_notify (G_OBJECT (buffer), "highlight");
+}
+
+/**
+ * gtk_source_buffer_get_highlight_current_line:
+ * @buffer: a #GtkSourceBuffer
+ *
+ * Returns whether the current line is highlighted
+ *
+ * Return value: TRUE if the current line is highlighted
+ **/
+gboolean 
+gtk_source_buffer_get_highlight_current_line (GtkSourceBuffer *buffer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_BUFFER (buffer), FALSE);
+
+	return buffer->priv->highlight_current_line;
+}
+
+/**
+ * gtk_source_buffer_set_highlight_current_line:
+ * @buffer: a #GtkSourceBuffer
+ * @hl: whether to highlight the current line
+ **/
+void 
+gtk_source_buffer_set_highlight_current_line (GtkSourceBuffer *buffer, gboolean hl)
+{
+	GtkTextIter iter;
+
+	g_return_if_fail (GTK_IS_SOURCE_BUFFER (buffer));
+
+	hl = (hl != FALSE);
+
+	if (buffer->priv->highlight_current_line == hl)
+		return;
+
+	buffer->priv->highlight_current_line = hl;
+	
+	gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter,
+					  gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (buffer)));
+	update_highlighted_line (GTK_TEXT_BUFFER (buffer), &iter, hl);
+
+	g_object_notify (G_OBJECT (buffer), "highlight_current_line");
+}
+
+/**
+ * gtk_source_buffer_get_highlight_current_line_color:
+ * @buffer: a #GtkSourceBuffer
+ *
+ * Returns the color with which the current line will be highlighted
+ *
+ * Return value: GdkColor
+ **/
+const GdkColor *
+gtk_source_buffer_get_highlight_current_line_color (GtkSourceBuffer *buffer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_BUFFER (buffer), FALSE);
+
+	return buffer->priv->highlight_current_line_color;
+}
+
+/**
+ * gtk_source_buffer_set_highlight_current_line_color:
+ * @buffer: a #GtkSourceBuffer
+ * @color: the background color to be used for highlighting the current line
+ **/
+void
+gtk_source_buffer_set_highlight_current_line_color (GtkSourceBuffer *buffer, GdkColor *color)
+{
+	GtkTextTagTable *table;
+	GtkTextTag *tag;
+
+	g_return_if_fail (GTK_IS_SOURCE_BUFFER (buffer));
+	g_return_if_fail (color != NULL);
+	
+	if (buffer->priv->highlight_current_line_color)
+		gdk_color_free (buffer->priv->highlight_current_line_color);
+	buffer->priv->highlight_current_line_color = gdk_color_copy (color);
+	
+	table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (buffer));
+	tag = gtk_text_tag_table_lookup (table, "highlightline");
+	g_object_set (tag, "paragraph-background-gdk", color, NULL);
+	
+	g_object_notify (G_OBJECT (buffer), "highlight_current_line_color");
 }
 
 /* Idle worker code ------------ */
Index: gtksourceview/gtksourcebuffer.h
===================================================================
RCS file: /cvs/gnome/gtksourceview/gtksourceview/gtksourcebuffer.h,v
retrieving revision 1.18
diff -u -p -r1.18 gtksourcebuffer.h
--- gtksourceview/gtksourcebuffer.h	6 Jun 2003 08:54:36 -0000	1.18
+++ gtksourceview/gtksourcebuffer.h	19 Jul 2005 20:34:39 -0000
@@ -92,6 +92,18 @@ gboolean		 gtk_source_buffer_get_highlig
 void			 gtk_source_buffer_set_highlight	(GtkSourceBuffer        *buffer,
 								 gboolean                highlight);
 
+void			 gtk_source_buffer_set_highlight_current_line 	
+								(GtkSourceBuffer        *buffer,
+								 gboolean                show);
+gboolean		 gtk_source_buffer_get_highlight_current_line 	
+								(GtkSourceBuffer        *buffer);
+
+const GdkColor          *gtk_source_buffer_get_highlight_current_line_color
+								(GtkSourceBuffer        *buffer);
+void			 gtk_source_buffer_set_highlight_current_line_color
+								(GtkSourceBuffer        *buffer,
+								 GdkColor               *color);
+
 gint			 gtk_source_buffer_get_max_undo_levels	(GtkSourceBuffer        *buffer);
 void			 gtk_source_buffer_set_max_undo_levels	(GtkSourceBuffer        *buffer,
 							    	 gint                    max_undo_levels);
Index: gtksourceview/gtksourceview.c
===================================================================
RCS file: /cvs/gnome/gtksourceview/gtksourceview/gtksourceview.c,v
retrieving revision 1.37
diff -u -p -r1.37 gtksourceview.c
--- gtksourceview/gtksourceview.c	1 Mar 2005 10:44:01 -0000	1.37
+++ gtksourceview/gtksourceview.c	19 Jul 2005 20:34:40 -0000
@@ -87,7 +87,6 @@ struct _GtkSourceViewPrivate
 	gboolean	 auto_indent;
 	gboolean	 insert_spaces;
 	gboolean	 show_margin;
-	gboolean	 highlight_current_line;
 	guint		 margin;
 	gint             cached_margin_width;
 	gboolean	 smart_home_end;
@@ -321,6 +320,7 @@ gtk_source_view_set_property (GObject   
 			      GParamSpec   *pspec)
 {
 	GtkSourceView *view;
+	GtkSourceBuffer *buffer;
 	
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (object));
 
@@ -370,8 +370,9 @@ gtk_source_view_set_property (GObject   
 			break;
 
 		case PROP_HIGHLIGHT_CURRENT_LINE:
-			gtk_source_view_set_highlight_current_line (view,
-								    g_value_get_boolean (value));
+			buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+			gtk_source_buffer_set_highlight_current_line (buffer,
+								      g_value_get_boolean (value));
 			break;
 
 		
@@ -388,6 +389,7 @@ gtk_source_view_get_property (GObject   
 			      GParamSpec *pspec)
 {
 	GtkSourceView *view;
+	GtkSourceBuffer *buffer;
 	
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (object));
 
@@ -441,8 +443,9 @@ gtk_source_view_get_property (GObject   
 			break;
 			
 		case PROP_HIGHLIGHT_CURRENT_LINE:
+			buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
 			g_value_set_boolean (value,
-					     gtk_source_view_get_highlight_current_line (view));
+					     gtk_source_buffer_get_highlight_current_line (buffer));
 
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1246,50 +1249,6 @@ gtk_source_view_expose (GtkWidget      *
 				gdk_window_invalidate_rect (w, NULL, FALSE);
 		}
 
-		if (view->priv->highlight_current_line && 
-		    (event->window == gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT)))
-		{
-			GdkRectangle visible_rect;
-			GdkRectangle redraw_rect;
-			GtkTextIter cur;
-			gint y;
-			gint height;
-			gint win_y;
-			
-			gtk_text_buffer_get_iter_at_mark (text_view->buffer, 
-							  &cur, 
-							  gtk_text_buffer_get_insert (text_view->buffer));
-
-			gtk_text_view_get_line_yrange (text_view, &cur, &y, &height);
-							
-			gtk_text_view_get_visible_rect (text_view, &visible_rect);
-			
-			gtk_text_view_buffer_to_window_coords (text_view,
-						       GTK_TEXT_WINDOW_TEXT,
-						       visible_rect.x,
-						       visible_rect.y,
-						       &redraw_rect.x,
-						       &redraw_rect.y);
-
-			gtk_text_view_buffer_to_window_coords (text_view,
-						       GTK_TEXT_WINDOW_TEXT,
-						       0,
-						       y,
-						       NULL,
-						       &win_y);
-
-			redraw_rect.width = visible_rect.width;
-			redraw_rect.height = visible_rect.height;
-
-			gdk_draw_rectangle (event->window,
-					    widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
-					    TRUE,
-					    redraw_rect.x + MAX (0, gtk_text_view_get_left_margin (text_view) - 1),
-					    win_y,
-					    redraw_rect.width,
-					    height);
-		}
-
 		if (view->priv->show_margin && 
 		    (event->window == gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT)))
 		{
@@ -2036,6 +1995,7 @@ gtk_source_view_set_show_margin (GtkSour
 	g_object_notify (G_OBJECT (view), "show_margin");
 }
 
+#ifndef GTK_SOURCE_VIEW_DISABLE_DEPRECATED
 /**
  * gtk_source_view_get_highlight_current_line:
  * @view: a #GtkSourceView
@@ -2043,13 +2003,19 @@ gtk_source_view_set_show_margin (GtkSour
  * Returns whether the current line is highlighted
  *
  * Return value: TRUE if the current line is highlighted
+ *
+ * Deprecated: Use gtk_source_buffer_get_highlight_current_line() instead.
  **/
 gboolean 
 gtk_source_view_get_highlight_current_line (GtkSourceView *view)
 {
+	GtkSourceBuffer *buffer;
+	
 	g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), FALSE);
 
-	return view->priv->highlight_current_line;
+	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+	
+	return gtk_source_buffer_get_highlight_current_line (buffer);
 }
 
 /**
@@ -2058,23 +2024,28 @@ gtk_source_view_get_highlight_current_li
  * @show: whether to highlight the current line
  *
  * If TRUE the current line is highlighted
+ *
+ * Deprecated: Use gtk_source_buffer_set_highlight_current_line() instead.
  **/
 void 
 gtk_source_view_set_highlight_current_line (GtkSourceView *view, gboolean hl)
 {
+	GtkSourceBuffer *buffer;
+	
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
 
+	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+	
 	hl = (hl != FALSE);
 
-	if (view->priv->highlight_current_line == hl)
+	if (gtk_source_buffer_get_highlight_current_line (buffer) == hl)
 		return;
 
-	view->priv->highlight_current_line = hl;
-
-	gtk_widget_queue_draw (GTK_WIDGET (view));
+	gtk_source_buffer_set_highlight_current_line (buffer, hl);
 
 	g_object_notify (G_OBJECT (view), "highlight_current_line");
 }
+#endif /* GTK_SOURCE_VIEW_DISABLE_DEPRECATED */
 
 /**
  * gtk_source_view_get_margin:
@@ -2171,6 +2142,7 @@ static void 
 gtk_source_view_style_set (GtkWidget *widget, GtkStyle *previous_style)
 {
 	GtkSourceView *view;
+	GtkSourceBuffer *buffer;
 	
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (widget));
 	
@@ -2189,6 +2161,13 @@ gtk_source_view_style_set (GtkWidget *wi
 		set_tab_stops_internal (view);
 		/* make sure the margin width is recalculated on next expose */
 		view->priv->cached_margin_width = -1;
+		
+		/* set the default highlight line color in the buffer. */
+		buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+		if (!gtk_source_buffer_get_highlight_current_line_color (buffer)) {
+			gtk_source_buffer_set_highlight_current_line_color (buffer,
+				&widget->style->bg[GTK_WIDGET_STATE (widget)]);
+		}
 	}
 }
 
Index: gtksourceview/gtksourceview.h
===================================================================
RCS file: /cvs/gnome/gtksourceview/gtksourceview/gtksourceview.h,v
retrieving revision 1.10
diff -u -p -r1.10 gtksourceview.h
--- gtksourceview/gtksourceview.h	8 Jan 2005 22:02:30 -0000	1.10
+++ gtksourceview/gtksourceview.h	19 Jul 2005 20:34:40 -0000
@@ -98,11 +98,13 @@ void		 gtk_source_view_set_show_margin 	
 							 gboolean         show);
 gboolean 	 gtk_source_view_get_show_margin 	(GtkSourceView   *view);
 
+#ifndef GTK_SOURCE_VIEW_DISABLE_DEPRECATED
 void		 gtk_source_view_set_highlight_current_line 	
 							(GtkSourceView   *view,
 							 gboolean         show);
 gboolean 	 gtk_source_view_get_highlight_current_line 	
 							(GtkSourceView   *view);
+#endif /* GTK_SOURCE_VIEW_DISABLE_DEPRECATED */
 
 void		 gtk_source_view_set_margin 		(GtkSourceView   *view,
 							 guint            margin);
Index: tests/test-widget.c
===================================================================
RCS file: /cvs/gnome/gtksourceview/tests/test-widget.c,v
retrieving revision 1.11
diff -u -p -r1.11 test-widget.c
--- tests/test-widget.c	8 Jan 2005 22:02:30 -0000	1.11
+++ tests/test-widget.c	19 Jul 2005 20:34:40 -0000
@@ -431,8 +431,9 @@ static void
 hl_line_toggled_cb (GtkAction *action, gpointer user_data)
 {
 	g_return_if_fail (GTK_IS_TOGGLE_ACTION (action) && GTK_IS_SOURCE_VIEW (user_data));
-	gtk_source_view_set_highlight_current_line (
-		GTK_SOURCE_VIEW (user_data),
+
+	gtk_source_buffer_set_highlight_current_line (
+		GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (user_data))),
 		gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
 }
 
