[gtksourceview] Improved gutter support



commit 494ec0ca9a066b7790dc6300d3db5270fe340686
Author: Jesse van den Kieboom <jesse icecrew nl>
Date:   Mon Oct 11 07:33:20 2010 +0200

    Improved gutter support
    
    We are no longer using GtkCellRenderer for rendering in the gutter since it
    had some limitations (in particular for sizing and accurate user control).

 gtksourceview/Makefile.am                     |   17 +-
 gtksourceview/gtksourcegutter.c               | 1631 ++++++++++++++++---------
 gtksourceview/gtksourcegutter.h               |   70 +-
 gtksourceview/gtksourcegutterrenderer.c       | 1227 +++++++++++++++++++
 gtksourceview/gtksourcegutterrenderer.h       |  218 ++++
 gtksourceview/gtksourcegutterrendererlines.c  |  344 ++++++
 gtksourceview/gtksourcegutterrendererlines.h  |   66 +
 gtksourceview/gtksourcegutterrenderermarks.c  |  454 +++++++
 gtksourceview/gtksourcegutterrenderermarks.h  |   66 +
 gtksourceview/gtksourcegutterrendererpixbuf.c |  477 ++++++++
 gtksourceview/gtksourcegutterrendererpixbuf.h |   95 ++
 gtksourceview/gtksourcegutterrenderertext.c   |  432 +++++++
 gtksourceview/gtksourcegutterrenderertext.h   |   83 ++
 gtksourceview/gtksourcemarkcategory.c         |  571 +++++++++
 gtksourceview/gtksourcemarkcategory.h         |  109 ++
 gtksourceview/gtksourcepixbufhelper.c         |  352 ++++++
 gtksourceview/gtksourcepixbufhelper.h         |   62 +
 gtksourceview/gtksourceview-marshal.list      |    5 +
 gtksourceview/gtksourceview.c                 | 1381 +++------------------
 gtksourceview/gtksourceview.h                 |   58 +-
 tests/test-widget.c                           |   58 +-
 21 files changed, 5855 insertions(+), 1921 deletions(-)
---
diff --git a/gtksourceview/Makefile.am b/gtksourceview/Makefile.am
index 77710c0..0b2f7b0 100644
--- a/gtksourceview/Makefile.am
+++ b/gtksourceview/Makefile.am
@@ -29,9 +29,13 @@ libgtksourceview_headers =			\
 	gtksourcecompletionproposal.h		\
 	gtksourcecompletionprovider.h		\
 	gtksourcegutter.h			\
+	gtksourcegutterrenderer.h		\
+	gtksourcegutterrenderertext.h		\
+	gtksourcegutterrendererpixbuf.h		\
 	gtksourcelanguage.h			\
 	gtksourcelanguagemanager.h		\
 	gtksourcemark.h				\
+	gtksourcemarkcategory.h			\
 	gtksourceprintcompositor.h		\
 	gtksourcestyle.h			\
 	gtksourcestylescheme.h			\
@@ -52,7 +56,11 @@ NOINST_H_FILES = \
 	gtksourceundomanagerdefault.h	\
 	gtksourceview-i18n.h		\
 	gtksourceview-utils.h		\
-	gtktextregion.h
+	gtktextregion.h			\
+	gtksourcepixbufhelper.h		\
+	gtksourcegutterrendererlines.h	\
+	gtksourcegutterrenderermarks.h	\
+	gtksourcemarkcategory.h
 
 libgtksourceview_c_files = \
 	gtksourcebuffer.c 		\
@@ -67,6 +75,13 @@ libgtksourceview_c_files = \
 	gtksourcecontextengine.c	\
 	gtksourceengine.c		\
 	gtksourcegutter.c		\
+	gtksourcegutterrenderer.c	\
+	gtksourcegutterrenderertext.c	\
+	gtksourcegutterrendererpixbuf.c	\
+	gtksourcegutterrendererlines.c	\
+	gtksourcegutterrenderermarks.c	\
+	gtksourcemarkcategory.c		\
+	gtksourcepixbufhelper.c		\
 	gtksourcelanguage.c 		\
 	gtksourcelanguagemanager.c 	\
 	gtksourcelanguage-parser-1.c	\
diff --git a/gtksourceview/gtksourcegutter.c b/gtksourceview/gtksourcegutter.c
index 72ad148..26e76c9 100644
--- a/gtksourceview/gtksourcegutter.c
+++ b/gtksourceview/gtksourcegutter.c
@@ -23,6 +23,9 @@
 #include "gtksourceview.h"
 #include "gtksourceview-i18n.h"
 #include "gtksourceview-marshal.h"
+#include "gtksourcegutterrenderer.h"
+
+#include <gobject/gvaluecollector.h>
 
 /**
  * SECTION:gutter
@@ -32,27 +35,17 @@
  *
  * The #GtkSourceGutter object represents the left and right gutters of the text
  * view. It is used by #GtkSourceView to draw the line numbers and category
- * marks that might be present on a line. By packing additional #GtkCellRenderer
+ * marks that might be present on a line. By packing additional #GtkSourceGutterRenderer
  * objects in the gutter, you can extend the gutter with your own custom 
  * drawings.
  *
  * The gutter works very much the same way as cells rendered in a #GtkTreeView.
  * The concept is similar, with the exception that the gutter does not have an
- * underlying #GtkTreeModel. Instead, you should use
- * #gtk_source_gutter_set_cell_data_func to set a callback to fill in any of the
- * cell renderers properties, given the line for which the cell is to be
- * rendered. Renderers are inserted into the gutter at a certain position. The
- * builtin line number renderer is at position 
-
+ * underlying #GtkTreeModel. The builtin line number renderer is at position
  * #GTK_SOURCE_VIEW_GUTTER_POSITION_LINES (-30) and the marks renderer is at
  * #GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS (-20). You can use these values to
- * position custom renderers accordingly. The width of a cell renderer can be
- * specified as either fixed (using
-
- * #gtk_cell_renderer_set_fixed_size) or dynamic, in which case you
- * <emphasis>must</emphasis> set #gtk_source_gutter_set_cell_size_func. This
- * callback is used to set the properties of the renderer such that
- * #gtk_cell_size_request_get_size yields the maximum width of the cell.
+ * position custom renderers accordingly.
+ *
  */
 
 #define GTK_SOURCE_GUTTER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER, GtkSourceGutterPrivate))
@@ -62,31 +55,22 @@ enum
 {
 	PROP_0,
 	PROP_VIEW,
-	PROP_WINDOW_TYPE
+	PROP_WINDOW_TYPE,
+	PROP_XPAD,
+	PROP_YPAD
 };
 
-/* Signals */
-enum
-{
-	CELL_ACTIVATED,
-	QUERY_TOOLTIP,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0,};
-
 typedef struct
 {
-	GtkCellRenderer *renderer;
-	gint position;
+	GtkSourceGutterRenderer *renderer;
 
-	GtkSourceGutterDataFunc data_func;
-	gpointer data_func_data;
-	GDestroyNotify data_func_destroy;
+	gint prelit;
+	gint position;
 
-	GtkSourceGutterSizeFunc size_func;
-	gpointer size_func_data;
-	GDestroyNotify size_func_destroy;
+	guint queue_draw_handler;
+	guint size_changed_handler;
+	guint notify_xpad_handler;
+	guint notify_ypad_handler;
 } Renderer;
 
 enum
@@ -97,6 +81,7 @@ enum
 	ENTER_NOTIFY_EVENT,
 	LEAVE_NOTIFY_EVENT,
 	QUERY_TOOLTIP_EVENT,
+	REALIZE,
 	LAST_EXTERNAL_SIGNAL
 };
 
@@ -104,9 +89,17 @@ struct _GtkSourceGutterPrivate
 {
 	GtkSourceView *view;
 	GtkTextWindowType window_type;
+	GtkOrientation orientation;
+
 	gint size;
 	GList *renderers;
+
+	gint xpad;
+	gint ypad;
+
 	guint signals[LAST_EXTERNAL_SIGNAL];
+
+	guint is_drawing : 1;
 };
 
 G_DEFINE_TYPE (GtkSourceGutter, gtk_source_gutter, G_TYPE_OBJECT)
@@ -139,21 +132,74 @@ static gboolean on_view_query_tooltip (GtkSourceView   *view,
                                        GtkTooltip      *tooltip,
                                        GtkSourceGutter *gutter);
 
+static void do_redraw (GtkSourceGutter *gutter);
+static void update_gutter_size (GtkSourceGutter *gutter);
+
 static void
-view_notify (GtkSourceGutter *gutter,
-             gpointer         where_the_object_was)
+on_renderer_size_changed (GtkSourceGutterRenderer *renderer,
+                          GParamSpec              *spec,
+                          GtkSourceGutter         *gutter)
 {
-	gutter->priv->view = NULL;
+	update_gutter_size (gutter);
+}
+
+static void
+on_renderer_queue_draw (GtkSourceGutterRenderer *renderer,
+                        GtkSourceGutter         *gutter)
+{
+	do_redraw (gutter);
+}
+
+static void
+on_renderer_notify_padding (GtkSourceGutterRenderer *renderer,
+                            GParamSpec              *spec,
+                            GtkSourceGutter         *gutter)
+{
+	update_gutter_size (gutter);
 }
 
 static Renderer *
-renderer_new (GtkCellRenderer  *renderer,
-              gint              position)
+renderer_new (GtkSourceGutter         *gutter,
+              GType                    gtype,
+              gint                     position,
+              guint                    num_parameters,
+              GParameter              *parameters)
 {
 	Renderer *ret = g_slice_new0 (Renderer);
 
-	ret->renderer = g_object_ref_sink (renderer);
+	ret->renderer = g_object_newv (gtype, num_parameters, parameters);
+
+	if (G_IS_INITIALLY_UNOWNED (ret->renderer))
+	{
+		g_object_ref_sink (ret->renderer);
+	}
+
 	ret->position = position;
+	ret->prelit = -1;
+
+	ret->size_changed_handler =
+		g_signal_connect (ret->renderer,
+		                  "notify::size",
+		                  G_CALLBACK (on_renderer_size_changed),
+		                  gutter);
+
+	ret->queue_draw_handler =
+		g_signal_connect (ret->renderer,
+		                  "queue-draw",
+		                  G_CALLBACK (on_renderer_queue_draw),
+		                  gutter);
+
+	ret->notify_xpad_handler =
+		g_signal_connect (ret->renderer,
+		                  "notify::xpad",
+		                  G_CALLBACK (on_renderer_notify_padding),
+		                  gutter);
+
+	ret->notify_ypad_handler =
+		g_signal_connect (ret->renderer,
+		                  "notify::ypad",
+		                  G_CALLBACK (on_renderer_notify_padding),
+		                  gutter);
 
 	return ret;
 }
@@ -161,15 +207,17 @@ renderer_new (GtkCellRenderer  *renderer,
 static void
 renderer_free (Renderer *renderer)
 {
-	if (renderer->data_func_destroy && renderer->data_func_data)
-	{
-		renderer->data_func_destroy (renderer->data_func_data);
-	}
+	g_signal_handler_disconnect (renderer->renderer,
+	                             renderer->queue_draw_handler);
 
-	if (renderer->size_func_destroy && renderer->size_func_data)
-	{
-		renderer->size_func_destroy (renderer->size_func_data);
-	}
+	g_signal_handler_disconnect (renderer->renderer,
+	                             renderer->size_changed_handler);
+
+	g_signal_handler_disconnect (renderer->renderer,
+	                             renderer->notify_xpad_handler);
+
+	g_signal_handler_disconnect (renderer->renderer,
+	                             renderer->notify_ypad_handler);
 
 	g_object_unref (renderer->renderer);
 	g_slice_free (Renderer, renderer);
@@ -198,10 +246,6 @@ gtk_source_gutter_dispose (GObject *object)
 				                     gutter->priv->signals[i]);
 		}
 
-		g_object_weak_unref (G_OBJECT (gutter->priv->view),
-		                     (GWeakNotify)view_notify,
-		                     gutter);
-
 		gutter->priv->view = NULL;
 	}
 
@@ -220,63 +264,76 @@ gtk_source_gutter_get_property (GObject    *object,
 	{
 		case PROP_VIEW:
 			g_value_set_object (value, self->priv->view);
-		break;
+			break;
 		case PROP_WINDOW_TYPE:
 			g_value_set_enum (value, self->priv->window_type);
-		break;
+			break;
+		case PROP_XPAD:
+			g_value_set_int (value, self->priv->xpad);
+			break;
+		case PROP_YPAD:
+			g_value_set_int (value, self->priv->ypad);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
+			break;
 	}
 }
 
 static void
+on_view_realize (GtkSourceView   *view,
+                 GtkSourceGutter *gutter)
+{
+	update_gutter_size (gutter);
+}
+
+static void
 set_view (GtkSourceGutter *gutter,
           GtkSourceView   *view)
 {
 	gutter->priv->view = view;
 
-	gutter->priv->size = -1;
-
-	g_object_weak_ref (G_OBJECT (view),
-	                   (GWeakNotify)view_notify,
-	                   gutter);
-
 	gutter->priv->signals[DRAW] =
 		g_signal_connect (view,
-	                  "draw",
-	                  G_CALLBACK (on_view_draw),
-	                  gutter);
+		                  "draw",
+		                  G_CALLBACK (on_view_draw),
+		                  gutter);
 
 	gutter->priv->signals[MOTION_NOTIFY_EVENT] =
 		g_signal_connect (view,
-	                  "motion-notify-event",
-	                  G_CALLBACK (on_view_motion_notify_event),
-	                  gutter);
+		                  "motion-notify-event",
+		                  G_CALLBACK (on_view_motion_notify_event),
+		                  gutter);
 
 	gutter->priv->signals[ENTER_NOTIFY_EVENT] =
 		g_signal_connect (view,
-	                  "enter-notify-event",
-	                  G_CALLBACK (on_view_enter_notify_event),
-	                  gutter);
+		                  "enter-notify-event",
+		                  G_CALLBACK (on_view_enter_notify_event),
+		                  gutter);
 
 	gutter->priv->signals[LEAVE_NOTIFY_EVENT] =
 		g_signal_connect (view,
-	                  "leave-notify-event",
-	                  G_CALLBACK (on_view_leave_notify_event),
-	                  gutter);
+		                  "leave-notify-event",
+		                  G_CALLBACK (on_view_leave_notify_event),
+		                  gutter);
 
 	gutter->priv->signals[BUTTON_PRESS_EVENT] =
 		g_signal_connect (view,
-	                  "button-press-event",
-	                  G_CALLBACK (on_view_button_press_event),
-	                  gutter);
+		                  "button-press-event",
+		                  G_CALLBACK (on_view_button_press_event),
+		                  gutter);
 
 	gutter->priv->signals[QUERY_TOOLTIP_EVENT] =
 		g_signal_connect (view,
-	                  "query-tooltip",
-	                  G_CALLBACK (on_view_query_tooltip),
-	                  gutter);
+		                  "query-tooltip",
+		                  G_CALLBACK (on_view_query_tooltip),
+		                  gutter);
+
+	gutter->priv->signals[REALIZE] =
+		g_signal_connect (view,
+		                  "realize",
+		                  G_CALLBACK (on_view_realize),
+		                  gutter);
 }
 
 static void
@@ -287,40 +344,109 @@ do_redraw (GtkSourceGutter *gutter)
 	window = gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->priv->view),
 	                                   gutter->priv->window_type);
 
-	if (window)
+	if (window && !gutter->priv->is_drawing)
 	{
 		gdk_window_invalidate_rect (window, NULL, FALSE);
 	}
 }
 
-static void
-revalidate_size (GtkSourceGutter *gutter)
+static gint
+calculate_gutter_size (GtkSourceGutter  *gutter,
+                       GArray           *sizes)
 {
-	GdkWindow *window;
+	GList *item;
+	gint total_width = 0;
 
-	window = gtk_source_gutter_get_window (gutter);
+	/* Calculate size */
+	for (item = gutter->priv->renderers; item; item = g_list_next (item))
+	{
+		Renderer *renderer = item->data;
+		gint width;
+
+		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
+		{
+			width = 0;
+		}
+		else
+		{
+			gint xpad;
+			gint size;
+
+			size = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+			gtk_source_gutter_renderer_get_padding (renderer->renderer,
+			                                        &xpad,
+			                                        NULL);
+
+			width = size + 2 * xpad;
+		}
+
+		if (sizes)
+		{
+			g_array_append_val (sizes, width);
+		}
+
+		total_width += width + gutter->priv->xpad;
+	}
 
-	if (!window && gutter->priv->renderers)
+	if (gutter->priv->renderers)
 	{
-		/* Make window visible by setting its size to minimum size,
-		   actual size will be calculated in draw */
-		gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
-		                                      gutter->priv->window_type,
-		                                      1);
-		gutter->priv->size = -1;
+		total_width += gutter->priv->xpad;
 	}
-	else if (window && !gutter->priv->renderers)
+
+	return total_width;
+}
+
+static void
+update_gutter_size (GtkSourceGutter *gutter)
+{
+	gint width;
+
+	width = calculate_gutter_size (gutter, NULL);
+
+	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
+	                                      gutter->priv->window_type,
+	                                      width);
+}
+
+static gboolean
+set_padding (GtkSourceGutter *gutter,
+             gint            *field,
+             gint             padding,
+             const gchar     *name,
+             gboolean         resize)
+{
+	if (*field == padding || padding < 0)
 	{
-		/* Make window invisible by setting size to 0 */
-		gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
-		                                      gutter->priv->window_type,
-		                                      0);
+		return FALSE;
 	}
-	else if (window)
+
+	*field = padding;
+
+	g_object_notify (G_OBJECT (gutter), name);
+
+	if (resize)
 	{
-		/* Redraw the window. Actual size will be calculated in draw */
-		do_redraw (gutter);
+		update_gutter_size (gutter);
 	}
+
+	return TRUE;
+}
+
+static gboolean
+set_xpad (GtkSourceGutter *gutter,
+          gint             xpad,
+          gboolean         resize)
+{
+	return set_padding (gutter, &gutter->priv->xpad, xpad, "xpad", resize);
+}
+
+static gboolean
+set_ypad (GtkSourceGutter *gutter,
+          gint             ypad,
+          gboolean         resize)
+{
+	return set_padding (gutter, &gutter->priv->ypad, ypad, "ypad", resize);
 }
 
 static void
@@ -335,14 +461,37 @@ gtk_source_gutter_set_property (GObject       *object,
 	{
 		case PROP_VIEW:
 			set_view (self, GTK_SOURCE_VIEW (g_value_get_object (value)));
-
-		break;
+			break;
 		case PROP_WINDOW_TYPE:
 			self->priv->window_type = g_value_get_enum (value);
-		break;
+			break;
+		case PROP_XPAD:
+			set_xpad (self, g_value_get_int (value), TRUE);
+			break;
+		case PROP_YPAD:
+			set_ypad (self, g_value_get_int (value), TRUE);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_constructed (GObject *object)
+{
+	GtkSourceGutter *gutter;
+
+	gutter = GTK_SOURCE_GUTTER (object);
+
+	if (gutter->priv->window_type == GTK_TEXT_WINDOW_LEFT ||
+	    gutter->priv->window_type == GTK_TEXT_WINDOW_RIGHT)
+	{
+		gutter->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+	}
+	else
+	{
+		gutter->priv->orientation = GTK_ORIENTATION_VERTICAL;
 	}
 }
 
@@ -356,6 +505,7 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
 
 	object_class->finalize = gtk_source_gutter_finalize;
 	object_class->dispose = gtk_source_gutter_dispose;
+	object_class->constructed = gtk_source_gutter_constructed;
 
 	/**
 	 * GtkSourceGutter:view:
@@ -363,12 +513,12 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
 	 * The #GtkSourceView of the gutter
 	 */
 	g_object_class_install_property (object_class,
-					 PROP_VIEW,
-					 g_param_spec_object ("view",
-							      _("View"),
-							      _("The gutters' GtkSourceView"),
-							      GTK_TYPE_SOURCE_VIEW,
-							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	                                 PROP_VIEW,
+	                                 g_param_spec_object ("view",
+	                                                      _("View"),
+	                                                      _("The gutters' GtkSourceView"),
+	                                                      GTK_TYPE_SOURCE_VIEW,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	/**
 	 * GtkSourceGutter:window-type:
@@ -376,73 +526,43 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
 	 * The text window type on which the window is placed
 	 */
 	g_object_class_install_property (object_class,
-					 PROP_WINDOW_TYPE,
-					 g_param_spec_enum ("window_type",
-							      _("Window Type"),
-							      _("The gutters text window type"),
-							      GTK_TYPE_TEXT_WINDOW_TYPE,
-							      0,
-							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	                                 PROP_WINDOW_TYPE,
+	                                 g_param_spec_enum ("window_type",
+	                                                    _("Window Type"),
+	                                                    _("The gutters text window type"),
+	                                                    GTK_TYPE_TEXT_WINDOW_TYPE,
+	                                                    0,
+	                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+	g_type_class_add_private (object_class, sizeof(GtkSourceGutterPrivate));
 
-	/**
-	 * GtkSourceGutter::cell-activated:
-	 * @gutter: the #GtkSourceGutter
-	 * @renderer: the #GtkCellRenderer which was activated
-	 * @iter: the #GtkTextIter at which the cell was activated
-	 * @event: the #GdkEvent with which the cell was activated
-	 *
-	 * Emitted when a cell has been activated (for instance when there was
-	 * a button press on the cell). The signal is only emitted for cells
-	 * that have the #activatable property set to %TRUE.
-	 */
-	signals [CELL_ACTIVATED] =
-		g_signal_new ("cell-activated",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (GtkSourceGutterClass, cell_activated),
-			      NULL,
-			      NULL,
-			      _gtksourceview_marshal_VOID__OBJECT_BOXED_POINTER,
-			      G_TYPE_NONE,
-			      3,
-			      GTK_TYPE_CELL_RENDERER,
-			      GTK_TYPE_TEXT_ITER,
-			      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
-	/**
-	 * GtkSourceGutter::query-tooltip:
-	 * @gutter: the #GtkSourceGutter
-	 * @renderer: the #GtkCellRenderer which was activated
-	 * @iter: the #GtkTextIter at which the cell was activated
-	 * @tooltip: the #GtkTooltip
-	 *
-	 * Emitted when a tooltip is requested for a specific cell. Signal
-	 * handlers can return %TRUE to notify the tooltip has been handled.
-	 */
-	signals [QUERY_TOOLTIP] =
-		g_signal_new ("query-tooltip",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (GtkSourceGutterClass, query_tooltip),
-			      g_signal_accumulator_true_handled,
-			      NULL,
-			      _gtksourceview_marshal_BOOL__OBJECT_BOXED_OBJECT,
-			      G_TYPE_BOOLEAN,
-			      3,
-			      GTK_TYPE_CELL_RENDERER,
-			      GTK_TYPE_TEXT_ITER,
-			      GTK_TYPE_TOOLTIP);
+	g_object_class_install_property (object_class,
+	                                 PROP_XPAD,
+	                                 g_param_spec_int ("xpad",
+	                                                   _("X Padding"),
+	                                                   _("The x-padding"),
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
-	g_type_class_add_private (object_class, sizeof(GtkSourceGutterPrivate));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_YPAD,
+	                                 g_param_spec_int ("ypad",
+	                                                   _("Y Padding"),
+	                                                   _("The y-padding"),
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
 static void
 gtk_source_gutter_init (GtkSourceGutter *self)
 {
 	self->priv = GTK_SOURCE_GUTTER_GET_PRIVATE (self);
-
-	self->priv->size = -1;
 }
 
 static gint
@@ -468,12 +588,13 @@ static void
 append_renderer (GtkSourceGutter *gutter,
                  Renderer        *renderer)
 {
-	gutter->priv->renderers = 
+	gutter->priv->renderers =
 		g_list_insert_sorted_with_data (gutter->priv->renderers,
-			                        renderer,
-			                        (GCompareDataFunc)sort_by_position,
-			                        NULL);
-	revalidate_size (gutter);
+		                                renderer,
+		                                (GCompareDataFunc)sort_by_position,
+		                                NULL);
+
+	update_gutter_size (gutter);
 }
 
 GtkSourceGutter *
@@ -513,35 +634,208 @@ gtk_source_gutter_get_window (GtkSourceGutter *gutter)
 /**
  * gtk_source_gutter_insert:
  * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
  * @position: the renderers position.
  *
  * Inserts @renderer into @gutter at @position.
  *
- * Since: 2.8
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
  */
-void
+GtkSourceGutterRenderer *
 gtk_source_gutter_insert (GtkSourceGutter *gutter,
-                          GtkCellRenderer *renderer,
-                          gint             position)
+                          GType            gtype,
+                          gint             position,
+                          ...)
 {
-	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
-	g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+	va_list ap;
+	GtkSourceGutterRenderer *ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+	g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+	va_start (ap, position);
+	ret = gtk_source_gutter_insert_valist (gutter, gtype, position, ap);
+	va_end (ap);
 
-	append_renderer (gutter, renderer_new (renderer, position));
+	return ret;
+}
+
+/**
+ * gtk_source_gutter_insert_valist:
+ * @gutter: a #GtkSourceGutter.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
+ * @position: the renderer position.
+ * @ap: the parameters.
+ *
+ * Create and insert a new gutter renderer in the gutter. This function is
+ * mostly useful for bindings. Applications should normally use
+ * #gtk_source_gutter_renderer_insert
+ *
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_insert_valist (GtkSourceGutter *gutter,
+                                 GType            gtype,
+                                 gint             position,
+                                 va_list          ap)
+{
+	const gchar *name;
+	GArray *parameters;
+	GObjectClass *klass;
+	GParameter *params;
+	guint num_parameters;
+	GtkSourceGutterRenderer *ret;
+	guint i;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+	g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+	parameters = g_array_new (FALSE, TRUE, sizeof (GParameter));
+	klass = g_type_class_ref (gtype);
+
+	num_parameters = 0;
+
+	while ((name = va_arg (ap, const gchar *)) != NULL)
+	{
+		GParameter parameter;
+		GParamSpec *spec;
+		gchar *error = NULL;
+
+		spec = g_object_class_find_property (klass, name);
+
+		if (!spec)
+		{
+			g_warning ("%s: object class `%s' has no property named `%s'",
+			           G_STRFUNC,
+			           g_type_name (gtype),
+			           name);
+
+			break;
+		}
+
+		parameter.name = name;
+
+		G_VALUE_COLLECT_INIT (&parameter.value,
+		                      spec->value_type,
+		                      ap,
+		                      0,
+		                      &error);
+
+		if (error)
+		{
+			g_warning ("%s: %s", G_STRFUNC, error);
+			g_free (error);
+			g_value_unset (&parameter.value);
+
+			break;
+		}
+
+		g_array_append_val (parameters, parameter);
+		++num_parameters;
+	}
+
+	params = (GParameter *)g_array_free (parameters, FALSE);
+
+	ret = gtk_source_gutter_insertv (gutter,
+	                                 gtype,
+	                                 position,
+	                                 num_parameters,
+	                                 params);
+
+	for (i = 0; i < num_parameters; ++i)
+	{
+		g_value_unset (&params[i].value);
+	}
+
+	g_free (params);
+
+	return ret;
+}
+
+/**
+ * gtk_source_gutter_insertv:
+ * @gutter: a #GtkSourceGutter.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
+ * @position: the renderer position.
+ * @num_parameters: the number of parameters.
+ * @parameters: the parameters.
+ *
+ * Create and insert a new gutter renderer in the gutter. This function is
+ * mostly useful for bindings. Applications should normally use
+ * #gtk_source_gutter_renderer_insert
+ *
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_insertv (GtkSourceGutter *gutter,
+                           GType            gtype,
+                           gint             position,
+                           guint            num_parameters,
+                           GParameter      *parameters)
+{
+	GParameter *extended;
+	guint i;
+	gint len;
+	GValue *view;
+	GValue *window_type;
+	Renderer *renderer;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+	g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+	len = sizeof (GParameter) * (num_parameters + 2);
+	extended = g_slice_alloc0 (len);
+
+	for (i = 0; i < num_parameters; ++i)
+	{
+		extended[i] = parameters[i];
+	}
+
+	extended[num_parameters].name = "view";
+	view = &(extended[num_parameters].value);
+	g_value_init (view, GTK_TYPE_TEXT_VIEW);
+	g_value_set_object (view, gutter->priv->view);
+
+	extended[num_parameters + 1].name = "window-type";
+	window_type = &(extended[num_parameters + 1].value);
+	g_value_init (window_type, GTK_TYPE_TEXT_WINDOW_TYPE);
+	g_value_set_enum (window_type, gutter->priv->window_type);
+
+	renderer = renderer_new (gutter,
+	                         gtype,
+	                         position,
+	                         num_parameters + 2,
+	                         extended);
+
+	append_renderer (gutter, renderer);
+
+	g_value_unset (view);
+	g_value_unset (window_type);
+
+	g_slice_free1 (len, extended);
+
+	return renderer->renderer;
 }
 
 static gboolean
-renderer_find (GtkSourceGutter  *gutter,
-               GtkCellRenderer  *renderer,
-               Renderer        **ret,
-               GList           **retlist)
+renderer_find (GtkSourceGutter          *gutter,
+               GtkSourceGutterRenderer  *renderer,
+               Renderer                **ret,
+               GList                   **retlist)
 {
 	GList *list;
 
 	for (list = gutter->priv->renderers; list; list = g_list_next (list))
 	{
-		*ret = (Renderer *)list->data;
+		*ret = list->data;
 
 		if ((*ret)->renderer == renderer)
 		{
@@ -557,10 +851,9 @@ renderer_find (GtkSourceGutter  *gutter,
 	return FALSE;
 }
 
-
 /**
  * gtk_source_gutter_reorder:
- * @gutter: a #GtkSourceGutter.
+ * @gutter: a #GtkSourceGutterRenderer.
  * @renderer: a #GtkCellRenderer.
  * @position: the new renderer position.
  *
@@ -569,19 +862,22 @@ renderer_find (GtkSourceGutter  *gutter,
  * Since: 2.8
  */
 void
-gtk_source_gutter_reorder (GtkSourceGutter *gutter,
-                           GtkCellRenderer *renderer,
-                           gint             position)
+gtk_source_gutter_reorder (GtkSourceGutter         *gutter,
+                           GtkSourceGutterRenderer *renderer,
+                           gint                     position)
 {
 	Renderer *ret;
 	GList *retlist;
 
 	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
-	g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
 
 	if (renderer_find (gutter, renderer, &ret, &retlist))
 	{
-		gutter->priv->renderers = g_list_remove_link (gutter->priv->renderers, retlist);
+		gutter->priv->renderers =
+			g_list_remove_link (gutter->priv->renderers,
+			                    retlist);
+
 		ret->position = position;
 		append_renderer (gutter, ret);
 	}
@@ -590,114 +886,33 @@ gtk_source_gutter_reorder (GtkSourceGutter *gutter,
 /**
  * gtk_source_gutter_remove:
  * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
+ * @renderer: a #GtkSourceGutterRenderer.
  *
  * Removes @renderer from @gutter.
  *
  * Since: 2.8
  */
 void
-gtk_source_gutter_remove (GtkSourceGutter *gutter,
-                          GtkCellRenderer *renderer)
+gtk_source_gutter_remove (GtkSourceGutter         *gutter,
+                          GtkSourceGutterRenderer *renderer)
 {
 	Renderer *ret;
 	GList *retlist;
 
 	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
-	g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
 
 	if (renderer_find (gutter, renderer, &ret, &retlist))
 	{
-		gutter->priv->renderers = g_list_remove_link (gutter->priv->renderers, retlist);
+		gutter->priv->renderers =
+			g_list_remove_link (gutter->priv->renderers,
+			                    retlist);
 
-		revalidate_size (gutter);
-		renderer_free (ret);
-	}
-}
+		g_object_set (ret->renderer, "view", NULL, NULL);
 
-/**
- * gtk_source_gutter_set_cell_data_func:
- * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
- * @func: (allow-none): the #GtkSourceGutterDataFunc to use.
- * @func_data: (allow-none): the user data for @func.
- * @destroy: (allow-none): the destroy notification for @func_data.
- *
- * Sets the #GtkSourceGutterDataFunc to use for @renderer. This function is
- * used to setup the cell renderer properties for rendering the current cell.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_set_cell_data_func (GtkSourceGutter         *gutter,
-                                      GtkCellRenderer         *renderer,
-                                      GtkSourceGutterDataFunc  func,
-                                      gpointer                 func_data,
-                                      GDestroyNotify           destroy)
-{
-	Renderer *ret;
-
-	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
-	g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
-	if (!renderer_find (gutter, renderer, &ret, NULL))
-	{
-		return;
-	}
-
-	if (ret->data_func_data && ret->data_func_destroy)
-	{
-		ret->data_func_destroy (ret->data_func_data);
-	}
-
-	ret->data_func = func;
-	ret->data_func_data = func_data;
-	ret->data_func_destroy = destroy;
-
-	revalidate_size (gutter);
-}
-
-/**
- * gtk_source_gutter_set_cell_size_func:
- * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
- * @func: (allow-none): the #GtkSourceGutterSizeFunc to use.
- * @func_data: (allow-none): the user data for @func.
- * @destroy: (allow-none): the destroy notification for @func_data.
- *
- * Sets the #GtkSourceGutterSizeFunc to use for @renderer. This function is
- * used to setup the cell renderer properties for measuring the maximum size
- * of the cell.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_set_cell_size_func (GtkSourceGutter         *gutter,
-                                      GtkCellRenderer         *renderer,
-                                      GtkSourceGutterSizeFunc  func,
-                                      gpointer                 func_data,
-                                      GDestroyNotify           destroy)
-{
-	Renderer *ret;
-
-	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
-	g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
-	if (!renderer_find (gutter, renderer, &ret, NULL))
-	{
-		return;
-	}
-
-	if (ret->size_func_data && ret->size_func_destroy)
-	{
-		ret->size_func_destroy (ret->size_func_data);
+		update_gutter_size (gutter);
+		renderer_free (ret);
 	}
-
-	ret->size_func = func;
-	ret->size_func_data = func_data;
-	ret->size_func_destroy = destroy;
-
-	revalidate_size (gutter);
 }
 
 /**
@@ -714,72 +929,33 @@ gtk_source_gutter_queue_draw (GtkSourceGutter *gutter)
 {
 	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
 
-	revalidate_size (gutter);
-}
-
-static gint
-calculate_size (GtkSourceGutter  *gutter,
-                Renderer         *renderer)
-{
-	gint width = -1;
-
-	gtk_cell_renderer_get_fixed_size (renderer->renderer, &width, NULL);
-
-	if (width == -1 && renderer->size_func)
-	{
-                GtkRequisition req;
-		renderer->size_func (gutter, renderer->renderer, renderer->size_func_data);
-
-		gtk_cell_renderer_get_preferred_size (renderer->renderer,
-                                                      GTK_WIDGET (gutter->priv->view),
-                                                      &req, NULL);
-                width = req.width;
-	}
-
-	return width == -1 ? 1 : width;
-}
-
-static gint
-calculate_sizes (GtkSourceGutter  *gutter,
-                 GArray           *sizes)
-{
-	GList *item;
-	gint total_width = 0;
-
-	/* Calculate size */
-	for (item = gutter->priv->renderers; item; item = g_list_next (item))
-	{
-		Renderer *renderer = (Renderer *)item->data;
-		gint width;
-
-		width = calculate_size (gutter, renderer);
-		g_array_append_val (sizes, width);
-
-		total_width += width;
-	}
-
-	return total_width;
+	do_redraw (gutter);
 }
 
 /* This function is taken from gtk+/tests/testtext.c */
-static void
+static gint
 get_lines (GtkTextView  *text_view,
            gint          first_y,
            gint          last_y,
            GArray       *buffer_coords,
            GArray       *line_heights,
            GArray       *numbers,
-           gint         *countp)
+           gint         *countp,
+           GtkTextIter  *start,
+           GtkTextIter  *end)
 {
 	GtkTextIter iter;
 	gint count;
 	gint last_line_num = -1;
+	gint total_height = 0;
 
 	g_array_set_size (buffer_coords, 0);
 	g_array_set_size (numbers, 0);
 
 	if (line_heights != NULL)
+	{
 		g_array_set_size (line_heights, 0);
+	}
 
 	/* Get iter at first y */
 	gtk_text_view_get_line_at_y (text_view, &iter, first_y, NULL);
@@ -788,6 +964,8 @@ get_lines (GtkTextView  *text_view,
 	 * Stop when we pass last_y */
 	count = 0;
 
+	*start = iter;
+
 	while (!gtk_text_iter_is_end (&iter))
 	{
 		gint y, height;
@@ -801,13 +979,17 @@ get_lines (GtkTextView  *text_view,
 			g_array_append_val (line_heights, height);
 		}
 
+		total_height += height;
+
 		last_line_num = gtk_text_iter_get_line (&iter);
 		g_array_append_val (numbers, last_line_num);
 
 		++count;
 
 		if ((y + height) >= last_y)
+		{
 			break;
+		}
 
 		gtk_text_iter_forward_line (&iter);
 	}
@@ -830,6 +1012,8 @@ get_lines (GtkTextView  *text_view,
 				g_array_append_val (line_heights, height);
 			}
 
+			total_height += height;
+
 			g_array_append_val (numbers, line_num);
 			++count;
 		}
@@ -852,8 +1036,14 @@ get_lines (GtkTextView  *text_view,
 		{
 			gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
 			g_array_append_val (line_heights, height);
+
+			total_height += height;
 		}
 	}
+
+	*end = iter;
+
+	return total_height;
 }
 
 static gboolean
@@ -864,8 +1054,27 @@ on_view_draw (GtkSourceView   *view,
 	GdkWindow *window;
 	GtkTextView *text_view;
 	GArray *sizes;
-        GdkRectangle clip;
+	GdkRectangle clip;
 	gint size;
+	gint x, y;
+	gint y1, y2;
+	GArray *numbers;
+	GArray *pixels;
+	GArray *heights;
+	GtkTextIter cur;
+	gint cur_line;
+	gint count;
+	gint i;
+	GList *item;
+	GtkTextIter start;
+	GtkTextIter end;
+	GtkTextBuffer *buffer;
+	GdkRectangle background_area;
+	GdkRectangle cell_area;
+	GtkTextIter selection_start;
+	GtkTextIter selection_end;
+	gboolean has_selection;
+	gint idx;
 
 	window = gtk_source_gutter_get_window (gutter);
 
@@ -874,195 +1083,261 @@ on_view_draw (GtkSourceView   *view,
 		return FALSE;
 	}
 
-        gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
+	gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
 
 	text_view = GTK_TEXT_VIEW (view);
+
+	if (!gdk_cairo_get_clip_rectangle (cr, &clip))
+	{
+		return FALSE;
+	}
+
+	gutter->priv->is_drawing = TRUE;
+
+	buffer = gtk_text_view_get_buffer (text_view);
+
+	gdk_window_get_pointer (window, &x, &y, NULL);
+
+	y1 = clip.y;
+	y2 = y1 + clip.height;
+
+	/* get the extents of the line printing */
+	gtk_text_view_window_to_buffer_coords (text_view,
+	                                       gutter->priv->window_type,
+	                                       0,
+	                                       y1,
+	                                       NULL,
+	                                       &y1);
+
+	gtk_text_view_window_to_buffer_coords (text_view,
+	                                       gutter->priv->window_type,
+	                                       0,
+	                                       y2,
+	                                       NULL,
+	                                       &y2);
+
+	numbers = g_array_new (FALSE, FALSE, sizeof (gint));
+	pixels = g_array_new (FALSE, FALSE, sizeof (gint));
+	heights = g_array_new (FALSE, FALSE, sizeof (gint));
 	sizes = g_array_new (FALSE, FALSE, sizeof (gint));
 
-	/* This is fairly ugly, but we could not find a better way to
-	 * do it: renderers could have changed size and they do not have
-	 * a way to signal it. So on draw we revalidate the size and
-	 * requeue another draw.
-	 * To see if the size has changed we test the size of only the
-	 * gutter itself since the full border window size is not under
-	 * our control (see e.g bug #589382).
-	 * This also means that if the user manually forces the
-	 * border_window_size to a value smaller than the gutter, things
-	 * will not be drawn properly. */
-	size = calculate_sizes (gutter, sizes);
-	if (gutter->priv->size != size)
+	size = calculate_gutter_size (gutter, sizes);
+
+	i = 0;
+	x = 0;
+
+	background_area.x = 0;
+	background_area.height = get_lines (text_view,
+	                                    y1,
+	                                    y2,
+	                                    pixels,
+	                                    heights,
+	                                    numbers,
+	                                    &count,
+	                                    &start,
+	                                    &end);
+
+	cell_area.x = gutter->priv->xpad;
+	cell_area.height = background_area.height;
+
+	gtk_text_view_buffer_to_window_coords (text_view,
+	                                       gutter->priv->window_type,
+	                                       0,
+	                                       g_array_index (pixels, gint, 0),
+	                                       NULL,
+	                                       &background_area.y);
+
+	cell_area.y = background_area.y;
+
+	item = gutter->priv->renderers;
+	idx = 0;
+
+	while (item)
 	{
-		gint border_size;
+		Renderer *renderer = item->data;
+		gint xpad;
+		gint width;
 
-		border_size = gtk_text_view_get_border_window_size (text_view, gutter->priv->window_type);
+		width = g_array_index (sizes, gint, idx++);
 
-		if (gutter->priv->size < 0)
-			border_size += size;
-		else
-			border_size = MAX (0, border_size - gutter->priv->size) + size;
+		if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
+		{
+			gtk_source_gutter_renderer_get_padding (renderer->renderer,
+			                                        &xpad,
+			                                        NULL);
+
+			background_area.width = width;
+
+			cell_area.width = width - 2 * xpad;
+			cell_area.x = background_area.x + xpad;
+
+			cairo_save (cr);
+
+			gdk_cairo_rectangle (cr, &background_area);
+			cairo_clip (cr);
+
+			gtk_source_gutter_renderer_begin (renderer->renderer,
+			                                  cr,
+			                                  &background_area,
+			                                  &cell_area,
+			                                  &start,
+			                                  &end);
+
+			cairo_restore (cr);
+
+			background_area.x += background_area.width;
+		}
+
+		item = g_list_next (item);
+	}
+
+	gtk_text_buffer_get_iter_at_mark (buffer,
+	                                  &cur,
+	                                  gtk_text_buffer_get_insert (buffer));
+
+	cur_line = gtk_text_iter_get_line (&cur);
 
-		gutter->priv->size = size;
+	gtk_text_buffer_get_selection_bounds (buffer,
+	                                      &selection_start,
+	                                      &selection_end);
 
-		/* Will trigger a new draw */
-		gtk_text_view_set_border_window_size (text_view, gutter->priv->window_type, border_size);
+	has_selection = !gtk_text_iter_equal (&selection_start, &selection_end);
+
+	if (has_selection)
+	{
+		if (!gtk_text_iter_starts_line (&selection_start))
+		{
+			gtk_text_iter_set_line_offset (&selection_start, 0);
+		}
+
+		if (!gtk_text_iter_ends_line (&selection_end))
+		{
+			gtk_text_iter_forward_to_line_end (&selection_end);
+		}
 	}
-	else if (gdk_cairo_get_clip_rectangle (cr, &clip))
+
+	for (i = 0; i < count; ++i)
 	{
-		GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
-		gint x, y;
-		gint y1, y2;
-		GArray *numbers;
-		GArray *pixels;
-		GArray *heights;
-		GtkTextIter cur;
-		gint cur_line;
-		gint count;
-		gint i;
-		GList *item;
-
-		gdk_window_get_pointer (window, &x, &y, NULL);
-
-		y1 = clip.y;
-		y2 = y1 + clip.height;
-
-		/* get the extents of the line printing */
-		gtk_text_view_window_to_buffer_coords (text_view,
-						       gutter->priv->window_type,
-						       0,
-						       y1,
-						       NULL,
-						       &y1);
-
-		gtk_text_view_window_to_buffer_coords (text_view,
-						       gutter->priv->window_type,
-						       0,
-						       y2,
-						       NULL,
-						       &y2);
-
-		numbers = g_array_new (FALSE, FALSE, sizeof (gint));
-		pixels = g_array_new (FALSE, FALSE, sizeof (gint));
-		heights = g_array_new (FALSE, FALSE, sizeof (gint));
-
-		/* get the line numbers and y coordinates. */
-		get_lines (text_view, y1, y2, pixels, heights, numbers, &count);
-
-		gtk_text_buffer_get_iter_at_mark (buffer,
-						  &cur,
-						  gtk_text_buffer_get_insert (buffer));
-
-		cur_line = gtk_text_iter_get_line (&cur);
-
-		for (i = 0; i < count; ++i)
+		gint pos;
+		gint line_to_paint;
+
+		end = start;
+
+		if (!gtk_text_iter_ends_line (&end))
 		{
-			gint pos;
-			gint line_to_paint;
-			GdkRectangle cell_area;
-			gint idx = 0;
+			gtk_text_iter_forward_to_line_end (&end);
+		}
+
+		gtk_text_view_buffer_to_window_coords (text_view,
+		                                       gutter->priv->window_type,
+		                                       0,
+		                                       g_array_index (pixels, gint, i),
+		                                       NULL,
+		                                       &pos);
 
-			gtk_text_view_buffer_to_window_coords (text_view,
-							       gutter->priv->window_type,
-							       0,
-							       g_array_index (pixels, gint, i),
-							       NULL,
-							       &pos);
+		line_to_paint = g_array_index (numbers, gint, i);
 
-			line_to_paint = g_array_index (numbers, gint, i);
+		background_area.y = pos;
+		background_area.height = g_array_index (heights, gint, i);
+		background_area.x = 0;
 
-			cell_area.x = 0;
-			cell_area.y = pos;
-			cell_area.height = g_array_index (heights, gint, i);
+		idx = 0;
+
+		for (item = gutter->priv->renderers; item; item = g_list_next (item))
+		{
+			Renderer *renderer;
+			gint width;
+			GtkSourceGutterRendererState state;
+			gint xpad;
+			gint ypad;
 
-			for (item = gutter->priv->renderers; item; item = g_list_next (item))
+			renderer = item->data;
+			width = g_array_index (sizes, gint, idx++);
+
+			if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
 			{
-				Renderer *renderer = (Renderer *)item->data;
-				gint width = g_array_index (sizes, gint, idx++);
-				GtkCellRendererState state = 0;
-
-				cell_area.width = width;
-
-				/* Call data func if needed */
-				if (renderer->data_func)
-				{
-					renderer->data_func (gutter,
-						             renderer->renderer,
-						             line_to_paint,
-						             line_to_paint == cur_line,
-						             renderer->data_func_data);
-				}
-
-				if (x >= cell_area.x && x < cell_area.x + cell_area.width &&
-				    y >= cell_area.y && y < cell_area.y + cell_area.height)
-				{
-					GtkCellRendererMode mode;
-
-					g_object_get (G_OBJECT (renderer->renderer),
-						      "mode", &mode,
-						      NULL);
-
-					if (mode & GTK_CELL_RENDERER_MODE_ACTIVATABLE)
-						state = GTK_CELL_RENDERER_PRELIT;
-				}
-
-				/* Call render with correct area */
-				gtk_cell_renderer_render (renderer->renderer,
-					                  cr,
-					                  GTK_WIDGET (view),
-					                  &cell_area,
-					                  &cell_area,
-					                  state);
-
-				cell_area.x += cell_area.width;
+				continue;
 			}
-		}
 
-		g_array_free (numbers, TRUE);
-		g_array_free (pixels, TRUE);
-		g_array_free (heights, TRUE);
-	}
+			gtk_source_gutter_renderer_get_padding (renderer->renderer,
+			                                        &xpad,
+			                                        &ypad);
 
-	g_array_free (sizes, TRUE);
+			background_area.width = width;
 
-	return FALSE;
-}
+			cell_area.y = background_area.y + ypad;
+			cell_area.height = background_area.height - 2 * ypad;
 
-static gboolean
-redraw_for_window (GtkSourceGutter *gutter,
-                   GdkEventAny     *event,
-                   gboolean         act_on_window)
-{
-	if (event->window == gtk_source_gutter_get_window (gutter) || !act_on_window)
-	{
-		gtk_source_gutter_queue_draw (gutter);
+			cell_area.x = background_area.x + xpad;
+			cell_area.width = background_area.width - 2 * xpad;
+
+			state = GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL;
+
+			if (line_to_paint == cur_line)
+			{
+				state |= GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR;
+			}
+
+			if (has_selection &&
+			    gtk_text_iter_in_range (&start,
+			                            &selection_start,
+			                            &selection_end))
+			{
+				state |= GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED;
+			}
+
+			if (renderer->prelit >= 0 && cell_area.y <= renderer->prelit && cell_area.y + cell_area.height >= renderer->prelit)
+			{
+				state |= GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
+			}
+
+			gtk_source_gutter_renderer_query_data (renderer->renderer,
+			                                       &start,
+			                                       &end,
+			                                       state);
+
+			cairo_save (cr);
+
+			gdk_cairo_rectangle (cr, &background_area);
+
+			cairo_clip (cr);
+
+			/* Call render with correct area */
+			gtk_source_gutter_renderer_draw (renderer->renderer,
+			                                 cr,
+			                                 &background_area,
+			                                 &cell_area,
+			                                 &start,
+			                                 &end,
+			                                 state);
+
+			cairo_restore (cr);
+
+			background_area.x += background_area.width;
+		}
+
+		gtk_text_iter_forward_line (&start);
 	}
 
-	return FALSE;
-}
+	for (item = gutter->priv->renderers; item; item = g_list_next (item))
+	{
+		Renderer *renderer = item->data;
 
-static gboolean
-on_view_motion_notify_event (GtkSourceView    *view,
-                             GdkEventMotion   *event,
-                             GtkSourceGutter  *gutter)
-{
-	return redraw_for_window (gutter, (GdkEventAny *)event, TRUE);
-}
+		if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
+		{
+			gtk_source_gutter_renderer_end (renderer->renderer);
+		}
+	}
 
+	g_array_free (numbers, TRUE);
+	g_array_free (pixels, TRUE);
+	g_array_free (heights, TRUE);
 
-static gboolean
-on_view_enter_notify_event (GtkSourceView     *view,
-                            GdkEventCrossing  *event,
-                            GtkSourceGutter   *gutter)
-{
-	return redraw_for_window (gutter, (GdkEventAny *)event, TRUE);
-}
+	g_array_free (sizes, TRUE);
 
+	gutter->priv->is_drawing = FALSE;
 
-static gboolean
-on_view_leave_notify_event (GtkSourceView     *view,
-                            GdkEventCrossing  *event,
-                            GtkSourceGutter   *gutter)
-{
-	return redraw_for_window (gutter, (GdkEventAny *)event, FALSE);
+	return FALSE;
 }
 
 static Renderer *
@@ -1072,61 +1347,113 @@ renderer_at_x (GtkSourceGutter *gutter,
                gint            *width)
 {
 	GList *item;
+	gint s;
+	gint w;
+
+	update_gutter_size (gutter);
+
+	s = 0;
 
 	for (item = gutter->priv->renderers; item; item = g_list_next (item))
 	{
-		Renderer *renderer = (Renderer *)item->data;
+		Renderer *renderer = item->data;
+		gint xpad;
+
+		w = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+		gtk_source_gutter_renderer_get_padding (renderer->renderer,
+		                                        &xpad,
+		                                        NULL);
 
-		*width = calculate_size (gutter, renderer);
+		s += xpad;
 
-		if (x >= *start && x < *start + *width)
+		if (w > 0 && x >= s && x < s + w)
 		{
+			if (width)
+			{
+				*width = w;
+			}
+
+			if (start)
+			{
+				*start = s;
+			}
+
 			return renderer;
 		}
 
-		*start += *width;
+		s += w + xpad;
 	}
 
 	return NULL;
 }
 
-static gboolean
-on_view_button_press_event (GtkSourceView    *view,
-                            GdkEventButton   *event,
-                            GtkSourceGutter  *gutter)
+static void
+get_renderer_rect (GtkSourceGutter *gutter,
+                   Renderer        *renderer,
+                   GtkTextIter     *iter,
+                   gint             line,
+                   GdkRectangle    *rectangle,
+                   gint             start)
 {
-	Renderer *renderer;
-	gint yline;
-	GtkTextIter line_iter;
-	GtkTextIter cur;
-	gint cur_line;
-	gint line;
-	gint y_buf;
-	gint start = 0;
-	gint width = 0;
-	GtkTextBuffer *buffer;
-	GtkCellRendererMode mode;
+	GList *item;
+	gint y;
+	gint ypad;
 
-	if (event->window != gtk_source_gutter_get_window (gutter))
-	{
-		return FALSE;
-	}
+	item = gutter->priv->renderers;
+	rectangle->x = start;
 
-	/* Check cell renderer */
-	renderer = renderer_at_x (gutter, event->x, &start, &width);
+	gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (gutter->priv->view),
+	                               iter,
+	                               &y,
+	                               &rectangle->height);
+
+	rectangle->width = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+	gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (gutter->priv->view),
+	                                       gutter->priv->window_type,
+	                                       0,
+	                                       y,
+	                                       NULL,
+	                                       &rectangle->y);
+
+	gtk_source_gutter_renderer_get_padding (renderer->renderer,
+	                                        NULL,
+	                                        &ypad);
+
+	rectangle->y += ypad;
+	rectangle->height -= 2 * ypad;
+}
+
+static gboolean
+renderer_query_activatable (GtkSourceGutter *gutter,
+                            Renderer        *renderer,
+                            GdkEvent        *event,
+                            gint             x,
+                            gint             y,
+                            GtkTextIter     *line_iter,
+                            GdkRectangle    *rect,
+                            gint             start)
+{
+	gint y_buf;
+	gint yline;
+	GtkTextIter iter;
+	GdkRectangle r;
 
 	if (!renderer)
 	{
 		return FALSE;
 	}
 
-	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
+	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (gutter->priv->view),
 	                                       gutter->priv->window_type,
-	                                       event->x, event->y,
-	                                       NULL, &y_buf);
+	                                       x,
+	                                       y,
+	                                       NULL,
+	                                       &y_buf);
 
-	gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (view),
-	                             &line_iter,
+	gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (gutter->priv->view),
+	                             &iter,
 	                             y_buf,
 	                             &yline);
 
@@ -1135,73 +1462,172 @@ on_view_button_press_event (GtkSourceView    *view,
 		return FALSE;
 	}
 
-	line = gtk_text_iter_get_line (&line_iter);
-	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+	get_renderer_rect (gutter, renderer, &iter, yline, &r, start);
 
-	gtk_text_buffer_get_iter_at_mark (buffer,
-					  &cur,
-					  gtk_text_buffer_get_insert (buffer));
+	if (line_iter)
+	{
+		*line_iter = iter;
+	}
 
-	cur_line = gtk_text_iter_get_line (&cur);
+	if (rect)
+	{
+		*rect = r;
+	}
+
+	if (y < r.y || y > r.y + r.height)
+	{
+		return FALSE;
+	}
+
+	return gtk_source_gutter_renderer_query_activatable (renderer->renderer,
+	                                                     &iter,
+	                                                     &r,
+	                                                     event);
+}
+
+static gboolean
+redraw_for_window (GtkSourceGutter *gutter,
+                   GdkEventAny     *event,
+                   gboolean         act_on_window,
+                   gint             x,
+                   gint             y)
+{
+	Renderer *at_x = NULL;
+	GList *item;
+	gboolean redraw;
+	gint start;
+
+	if (event->window != gtk_source_gutter_get_window (gutter) && act_on_window)
+	{
+		return FALSE;
+	}
 
-	if (renderer->data_func)
+	if (act_on_window)
 	{
-		renderer->data_func (gutter,
-		                     renderer->renderer,
-		                     line,
-		                     line == cur_line,
-		                     renderer->data_func_data);
+		at_x = renderer_at_x (gutter, x, &start, NULL);
 	}
 
-	g_object_get (G_OBJECT (renderer->renderer),
-	              "mode", &mode,
-	              NULL);
+	redraw = FALSE;
 
-	if (mode & GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+	for (item = gutter->priv->renderers; item; item = g_list_next (item))
 	{
-		GdkRectangle area;
-		gchar *path;
-		gboolean ret;
-
-		gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (view),
-		                               &line_iter,
-		                               &area.y,
-		                               &area.height);
-		area.x = start;
-		area.width = width;
-
-		path = g_strdup_printf ("%d", line);
-
-		ret = gtk_cell_renderer_activate (renderer->renderer,
-		                                  (GdkEvent *)event,
-		                                  GTK_WIDGET (gutter->priv->view),
-		                                  path,
-		                                  &area,
-		                                  &area,
-		                                  0);
-
-		g_signal_emit (gutter,
-		               signals[CELL_ACTIVATED],
-		               0,
-		               renderer->renderer,
-		               &line_iter,
-		               (GdkEvent *)event);
-
-		g_free (path);
+		Renderer *renderer = item->data;
+		gint prelit = renderer->prelit;
+
+		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
+		{
+			renderer->prelit = -1;
+		}
+		else
+		{
+			if (renderer != at_x || !act_on_window)
+			{
+				renderer->prelit = -1;
+			}
+			else if (renderer_query_activatable (gutter,
+			                                     renderer,
+			                                     (GdkEvent *)event,
+			                                     x,
+			                                     y,
+			                                     NULL,
+			                                     NULL,
+			                                     start))
+			{
+				renderer->prelit = y;
+			}
+			else
+			{
+				renderer->prelit = -1;
+			}
+		}
+
+		redraw |= (renderer->prelit != prelit);
+	}
+
+	if (redraw)
+	{
+		do_redraw (gutter);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+on_view_motion_notify_event (GtkSourceView    *view,
+                             GdkEventMotion   *event,
+                             GtkSourceGutter  *gutter)
+{
+	return redraw_for_window (gutter,
+	                          (GdkEventAny *)event,
+	                          TRUE,
+	                          (gint)event->x,
+	                          (gint)event->y);
+}
+
+static gboolean
+on_view_enter_notify_event (GtkSourceView     *view,
+                            GdkEventCrossing  *event,
+                            GtkSourceGutter   *gutter)
+{
+	return redraw_for_window (gutter,
+	                          (GdkEventAny *)event,
+	                          TRUE,
+	                          (gint)event->x,
+	                          (gint)event->y);
+}
+
+static gboolean
+on_view_leave_notify_event (GtkSourceView     *view,
+                            GdkEventCrossing  *event,
+                            GtkSourceGutter   *gutter)
+{
+	return redraw_for_window (gutter,
+	                          (GdkEventAny *)event,
+	                          FALSE,
+	                          (gint)event->x,
+	                          (gint)event->y);
+}
+
+static gboolean
+on_view_button_press_event (GtkSourceView    *view,
+                            GdkEventButton   *event,
+                            GtkSourceGutter  *gutter)
+{
+	Renderer *renderer;
+	GtkTextIter line_iter;
+	gint start = -1;
+	GdkRectangle rect;
+
+	if (event->window != gtk_source_gutter_get_window (gutter))
+	{
+		return FALSE;
+	}
+
+	if (event->type != GDK_BUTTON_PRESS)
+	{
+		return FALSE;
+	}
+
+	/* Check cell renderer */
+	renderer = renderer_at_x (gutter, event->x, &start, NULL);
+
+	if (renderer_query_activatable (gutter,
+	                                renderer,
+	                                (GdkEvent *)event,
+	                                (gint)event->x,
+	                                (gint)event->y,
+	                                &line_iter,
+	                                &rect,
+	                                start))
+	{
+		gtk_source_gutter_renderer_activate (renderer->renderer,
+		                                     &line_iter,
+		                                     &rect,
+		                                     (GdkEvent *)event);
+
 		do_redraw (gutter);
 
-		/* WARNING, DANGER, DANGER:
-		 * FIXME: this is really just a hack because we lack a return
-		 * value in the CELL_ACTIVATED signal, so handlers of cell
-		 * activating have no way to consume the button event. A left
-		 * click in the gutter will by default remove the selection
-		 * in the textview, which is bad because we implement some
-		 * selection stuff in GtkSourceView when clicking on the line
-		 * renderer. Anyway, for 3.0 we should change the
-		 * cell-activated signal to allow a return value and remove
-		 * this hack
-		 */
-		return ret || event->button == 1;
+		return TRUE;
 	}
 
 	return FALSE;
@@ -1222,7 +1648,7 @@ on_view_query_tooltip (GtkSourceView   *view,
 	gint y_buf;
 	gint yline;
 	GtkTextIter line_iter;
-	gboolean ret;
+	GdkRectangle rect;
 
 	if (keyboard_mode)
 	{
@@ -1252,15 +1678,48 @@ on_view_query_tooltip (GtkSourceView   *view,
 		return FALSE;
 	}
 
-	g_signal_emit (gutter,
-	               signals[QUERY_TOOLTIP],
-	               0,
-	               renderer->renderer,
-	               &line_iter,
-	               tooltip,
-	               &ret);
+	get_renderer_rect (gutter,
+	                   renderer,
+	                   &line_iter,
+	                   yline,
+	                   &rect,
+	                   start);
+
+	return gtk_source_gutter_renderer_query_tooltip (renderer->renderer,
+	                                                 &line_iter,
+	                                                 &rect,
+	                                                 x,
+	                                                 y,
+	                                                 tooltip);
+}
+
+void
+gtk_source_gutter_set_padding (GtkSourceGutter *gutter,
+                               gint             xpad,
+                               gint             ypad)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
 
-	return ret;
+	if (set_xpad (gutter, xpad, FALSE) || set_ypad (gutter, ypad, FALSE))
+	{
+		update_gutter_size (gutter);
+	}
 }
 
-/* vi:ts=8 */
+void
+gtk_source_gutter_get_padding (GtkSourceGutter *gutter,
+                               gint            *xpad,
+                               gint            *ypad)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
+
+	if (xpad)
+	{
+		*xpad = gutter->priv->xpad;
+	}
+
+	if (ypad)
+	{
+		*ypad = gutter->priv->ypad;
+	}
+}
diff --git a/gtksourceview/gtksourcegutter.h b/gtksourceview/gtksourcegutter.h
index 4dda080..0b4beec 100644
--- a/gtksourceview/gtksourcegutter.h
+++ b/gtksourceview/gtksourcegutter.h
@@ -26,6 +26,7 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
+#include <gtksourceview/gtksourcegutterrenderer.h>
 
 G_BEGIN_DECLS
 
@@ -40,64 +41,57 @@ typedef struct _GtkSourceGutter			GtkSourceGutter;
 typedef struct _GtkSourceGutterClass	GtkSourceGutterClass;
 typedef struct _GtkSourceGutterPrivate	GtkSourceGutterPrivate;
 
-struct _GtkSourceGutter {
+struct _GtkSourceGutter
+{
 	GObject parent;
 
 	GtkSourceGutterPrivate *priv;
 };
 
-struct _GtkSourceGutterClass {
+struct _GtkSourceGutterClass
+{
 	GObjectClass parent_class;
-
-	void (*cell_activated) 			(GtkSourceGutter *gutter,
-						 GtkCellRenderer *renderer,
-						 GtkTextIter     *iter,
-						 GdkEvent        *event);
-
-	gboolean (*query_tooltip) 		(GtkSourceGutter *gutter,
-						 GtkCellRenderer *renderer,
-						 GtkTextIter     *iter,
-						 GtkTooltip      *tooltip);
 };
 
-typedef void (*GtkSourceGutterDataFunc)		(GtkSourceGutter         *gutter,
-						 GtkCellRenderer         *cell,
-						 gint                     line_number,
-						 gboolean                 current_line,
-						 gpointer                 data);
-
-typedef void (*GtkSourceGutterSizeFunc)		(GtkSourceGutter         *gutter,
-						 GtkCellRenderer         *cell,
-						 gpointer                 data);
-
 GType gtk_source_gutter_get_type 		(void) G_GNUC_CONST;
 
 GdkWindow *gtk_source_gutter_get_window 	(GtkSourceGutter         *gutter);
 
-void gtk_source_gutter_insert			(GtkSourceGutter         *gutter,
-						 GtkCellRenderer         *renderer,
-						 gint                     position);
+GtkSourceGutterRenderer *
+	gtk_source_gutter_insert		(GtkSourceGutter         *gutter,
+                                                 GType                    gtype,
+                                                 gint                     position,
+                                                 ...) G_GNUC_NULL_TERMINATED;
+
+GtkSourceGutterRenderer *
+	gtk_source_gutter_insert_valist         (GtkSourceGutter         *gutter,
+                                                 GType                    gtype,
+                                                 gint                     position,
+                                                 va_list                  ap);
+
+GtkSourceGutterRenderer *
+	gtk_source_gutter_insertv               (GtkSourceGutter         *gutter,
+                                                 GType                    gtype,
+                                                 gint                     position,
+                                                 guint                    num_parameters,
+                                                 GParameter              *parameters);
 
 void gtk_source_gutter_reorder			(GtkSourceGutter	 *gutter,
-                                                 GtkCellRenderer         *renderer,
+                                                 GtkSourceGutterRenderer *renderer,
                                                  gint                     position);
 
 void gtk_source_gutter_remove			(GtkSourceGutter         *gutter,
-						 GtkCellRenderer         *renderer);
+                                                 GtkSourceGutterRenderer *renderer);
 
-void gtk_source_gutter_set_cell_data_func	(GtkSourceGutter         *gutter,
-						 GtkCellRenderer         *renderer,
-						 GtkSourceGutterDataFunc  func,
-						 gpointer                 func_data,
-						 GDestroyNotify           destroy);
+void gtk_source_gutter_queue_draw		(GtkSourceGutter         *gutter);
 
-void gtk_source_gutter_set_cell_size_func	(GtkSourceGutter         *gutter,
-                                                 GtkCellRenderer         *renderer,
-                                                 GtkSourceGutterSizeFunc  func,
-                                                 gpointer                 func_data,
-                                                 GDestroyNotify           destroy);
+void gtk_source_gutter_set_padding              (GtkSourceGutter         *gutter,
+                                                 gint                     xpad,
+                                                 gint                     ypad);
 
-void gtk_source_gutter_queue_draw		(GtkSourceGutter         *gutter);
+void gtk_source_gutter_get_padding              (GtkSourceGutter         *gutter,
+                                                 gint                    *xpad,
+                                                 gint                    *ypad);
 
 G_END_DECLS
 
diff --git a/gtksourceview/gtksourcegutterrenderer.c b/gtksourceview/gtksourcegutterrenderer.c
new file mode 100644
index 0000000..fd8fbff
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderer.c
@@ -0,0 +1,1227 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderer.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gtksourcegutterrenderer.h"
+#include "gtksourceview-marshal.h"
+#include "gtksourceview-typebuiltins.h"
+#include "gtksourceview-i18n.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererPrivate))
+
+enum
+{
+	ACTIVATE,
+	SIZE_CHANGED,
+	QUEUE_DRAW,
+	QUERY_TOOLTIP,
+	QUERY_DATA,
+	QUERY_ACTIVATABLE,
+	NUM_SIGNALS
+};
+
+struct _GtkSourceGutterRendererPrivate
+{
+	GtkTextView *view;
+	GtkTextWindowType window_type;
+
+	gint xpad;
+	gint ypad;
+
+	gfloat xalign;
+	gfloat yalign;
+
+	gint size;
+
+	GdkColor background_gdk;
+	gboolean background_set;
+
+	GtkSourceGutterRendererAlignmentMode alignment_mode;
+
+	guint visible : 1;
+};
+
+static guint signals[NUM_SIGNALS] = {0,};
+
+G_DEFINE_ABSTRACT_TYPE (GtkSourceGutterRenderer,
+                        gtk_source_gutter_renderer,
+                        G_TYPE_INITIALLY_UNOWNED)
+
+enum
+{
+	PROP_0,
+	PROP_VISIBLE,
+	PROP_XPAD,
+	PROP_YPAD,
+	PROP_XALIGN,
+	PROP_YALIGN,
+	PROP_VIEW,
+	PROP_ALIGNMENT_MODE,
+	PROP_WINDOW_TYPE,
+	PROP_SIZE,
+	PROP_BACKGROUND_GDK,
+	PROP_BACKGROUND_SET
+};
+
+static void
+gtk_source_gutter_renderer_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_parent_class)->finalize (object);
+}
+
+static gboolean
+set_visible (GtkSourceGutterRenderer *renderer,
+             gboolean                 visible)
+{
+	if (renderer->priv->visible == visible)
+	{
+		return FALSE;
+	}
+
+	renderer->priv->visible = visible;
+	g_object_notify (G_OBJECT (renderer), "visible");
+
+	gtk_source_gutter_renderer_queue_draw (renderer);
+
+	return TRUE;
+}
+
+
+static gboolean
+set_padding (GtkSourceGutterRenderer *renderer,
+             gint                    *field,
+             gint                     padding,
+             const gchar             *name)
+{
+	if (*field == padding || padding < 0)
+	{
+		return FALSE;
+	}
+
+	*field = padding;
+	g_object_notify (G_OBJECT (renderer), name);
+
+	return TRUE;
+}
+
+static gboolean
+set_xpad (GtkSourceGutterRenderer *renderer,
+          gint                     xpad)
+{
+	return set_padding (renderer,
+	                    &renderer->priv->xpad,
+	                    xpad,
+	                    "xpad");
+}
+
+static gboolean
+set_ypad (GtkSourceGutterRenderer *renderer,
+          gint                     ypad)
+{
+	return set_padding (renderer,
+	                    &renderer->priv->ypad,
+	                    ypad,
+	                    "ypad");
+}
+
+static gboolean
+set_alignment (GtkSourceGutterRenderer *renderer,
+               gfloat                  *field,
+               gfloat                   align,
+               const gchar             *name,
+               gboolean                 emit)
+{
+	if (*field == align || align < 0)
+	{
+		return FALSE;
+	}
+
+	*field = align;
+	g_object_notify (G_OBJECT (renderer), name);
+
+	if (emit)
+	{
+		gtk_source_gutter_renderer_queue_draw (renderer);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+set_xalign (GtkSourceGutterRenderer *renderer,
+            gfloat                   xalign,
+            gboolean                 emit)
+{
+	return set_alignment (renderer,
+	                      &renderer->priv->xalign,
+	                      xalign,
+	                      "xalign",
+	                      emit);
+}
+
+static gboolean
+set_yalign (GtkSourceGutterRenderer *renderer,
+            gfloat                   yalign,
+            gboolean                 emit)
+{
+	return set_alignment (renderer,
+	                      &renderer->priv->yalign,
+	                      yalign,
+	                      "yalign",
+	                      emit);
+}
+
+static void
+set_alignment_mode (GtkSourceGutterRenderer              *renderer,
+                    GtkSourceGutterRendererAlignmentMode  mode)
+{
+	if (renderer->priv->alignment_mode == mode)
+	{
+		return;
+	}
+
+	renderer->priv->alignment_mode = mode;
+	g_object_notify (G_OBJECT (renderer), "alignment-mode");
+
+	gtk_source_gutter_renderer_queue_draw (renderer);
+}
+
+static void
+set_size (GtkSourceGutterRenderer *renderer,
+          gint                     value)
+{
+	if (renderer->priv->size == value)
+	{
+		return;
+	}
+
+	renderer->priv->size = value;
+	g_object_notify (G_OBJECT (renderer), "size");
+}
+
+static void
+set_background_gdk_set (GtkSourceGutterRenderer *renderer,
+                        gboolean                 isset)
+{
+	if (isset == renderer->priv->background_set)
+	{
+		return;
+	}
+
+	renderer->priv->background_set = isset;
+	gtk_source_gutter_renderer_queue_draw (renderer);
+}
+
+static void
+set_background_gdk (GtkSourceGutterRenderer *renderer,
+                    const GdkColor          *color)
+{
+	if (!color)
+	{
+		set_background_gdk_set (renderer, FALSE);
+	}
+	else
+	{
+		renderer->priv->background_gdk = *color;
+		renderer->priv->background_set = TRUE;
+
+		gtk_source_gutter_renderer_queue_draw (renderer);
+	}
+}
+
+static void
+gtk_source_gutter_renderer_set_property (GObject      *object,
+                                         guint         prop_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
+{
+	GtkSourceGutterRenderer *self = GTK_SOURCE_GUTTER_RENDERER (object);
+
+	switch (prop_id)
+	{
+		case PROP_VISIBLE:
+			set_visible (self, g_value_get_boolean (value));
+			break;
+		case PROP_XPAD:
+			set_xpad (self, g_value_get_int (value));
+			break;
+		case PROP_YPAD:
+			set_ypad (self, g_value_get_int (value));
+			break;
+		case PROP_XALIGN:
+			set_xalign (self, g_value_get_float (value), TRUE);
+			break;
+		case PROP_YALIGN:
+			set_yalign (self, g_value_get_float (value), TRUE);
+			break;
+		case PROP_ALIGNMENT_MODE:
+			set_alignment_mode (self, g_value_get_enum (value));
+			break;
+		case PROP_VIEW:
+			self->priv->view = g_value_get_object (value);
+			break;
+		case PROP_WINDOW_TYPE:
+			self->priv->window_type = g_value_get_enum (value);
+			break;
+		case PROP_SIZE:
+			set_size (self, g_value_get_int (value));
+			break;
+		case PROP_BACKGROUND_GDK:
+			set_background_gdk (self,
+			                    g_value_get_boxed (value));
+			break;
+		case PROP_BACKGROUND_SET:
+			set_background_gdk_set (self,
+			                        g_value_get_boolean (value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_renderer_get_property (GObject    *object,
+                                         guint       prop_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
+{
+	GtkSourceGutterRenderer *self = GTK_SOURCE_GUTTER_RENDERER (object);
+
+	switch (prop_id)
+	{
+		case PROP_VISIBLE:
+			g_value_set_boolean (value, self->priv->visible);
+			break;
+		case PROP_XPAD:
+			g_value_set_int (value, self->priv->xpad);
+			break;
+		case PROP_YPAD:
+			g_value_set_int (value, self->priv->ypad);
+			break;
+		case PROP_XALIGN:
+			g_value_set_float (value, self->priv->xalign);
+			break;
+		case PROP_YALIGN:
+			g_value_set_float (value, self->priv->yalign);
+			break;
+		case PROP_VIEW:
+			g_value_set_object (value, self->priv->view);
+			break;
+		case PROP_ALIGNMENT_MODE:
+			g_value_set_enum (value, self->priv->alignment_mode);
+			break;
+		case PROP_WINDOW_TYPE:
+			g_value_set_enum (value, self->priv->window_type);
+			break;
+		case PROP_SIZE:
+			g_value_set_int (value, self->priv->size);
+			break;
+		case PROP_BACKGROUND_GDK:
+			g_value_set_boxed (value, &self->priv->background_gdk);
+			break;
+		case PROP_BACKGROUND_SET:
+			g_value_set_boolean (value, self->priv->background_set);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+renderer_draw_impl (GtkSourceGutterRenderer      *renderer,
+                    cairo_t                      *cr,
+                    const GdkRectangle           *background_area,
+                    const GdkRectangle           *cell_area,
+                    GtkTextIter                  *start,
+                    GtkTextIter                  *end,
+                    GtkSourceGutterRendererState  state)
+{
+	if (!renderer->priv->background_set)
+	{
+		return;
+	}
+
+	cairo_save (cr);
+
+	gdk_cairo_rectangle (cr, background_area);
+	gdk_cairo_set_source_color (cr, &renderer->priv->background_gdk);
+
+	cairo_fill (cr);
+	cairo_restore (cr);
+}
+
+static void
+gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gtk_source_gutter_renderer_finalize;
+
+	object_class->get_property = gtk_source_gutter_renderer_get_property;
+	object_class->set_property = gtk_source_gutter_renderer_set_property;
+
+	klass->draw = renderer_draw_impl;
+
+	g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererPrivate));
+
+	/**
+	 * GtkSourceGutterRenderer:visible:
+	 *
+	 * The visibility of the renderer.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_VISIBLE,
+	                                 g_param_spec_boolean ("visible",
+	                                                       _("Visible"),
+	                                                       _("Visible"),
+	                                                       TRUE,
+	                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer:xpad:
+	 *
+	 * The x-padding of the renderer.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_XPAD,
+	                                 g_param_spec_int ("xpad",
+	                                                   _("X Padding"),
+	                                                   _("The x-padding"),
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer:ypad:
+	 *
+	 * The y-padding of the renderer.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_YPAD,
+	                                 g_param_spec_int ("ypad",
+	                                                   _("Y Padding"),
+	                                                   _("The y-padding"),
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer:xalign:
+	 *
+	 * The x-alignment of the renderer.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_XALIGN,
+	                                 g_param_spec_float ("xalign",
+	                                                     _("X Alignment"),
+	                                                     _("The x-alignment"),
+	                                                     -1,
+	                                                     1,
+	                                                     0,
+	                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer:yalign:
+	 *
+	 * The y-alignment of the renderer.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_YALIGN,
+	                                 g_param_spec_float ("yalign",
+	                                                     _("Y Alignment"),
+	                                                     _("The y-alignment"),
+	                                                     -1,
+	                                                     1,
+	                                                     0,
+	                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer::activate:
+	 * @renderer: the #GtkSourceGutterRenderer who emits the signal
+	 * @iter: a #GtkTextIter
+	 * @area: a #GdkRectangle
+	 * @event: the event that caused the activation
+	 *
+	 * The ::activate signal is emitted when the renderer is
+	 * activated.
+	 *
+	 */
+	signals[ACTIVATE] =
+		g_signal_new ("activate",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GtkSourceGutterRendererClass, activate),
+		              NULL,
+		              NULL,
+		              _gtksourceview_marshal_VOID__BOXED_BOXED_BOXED,
+		              G_TYPE_NONE,
+		              3,
+		              GTK_TYPE_TEXT_ITER,
+		              GDK_TYPE_RECTANGLE,
+		              GDK_TYPE_EVENT);
+
+	/**
+	 * GtkSourceGutterRenderer::queue-draw:
+	 * @renderer: the #GtkSourceGutterRenderer who emits the signal
+	 *
+	 * The ::queue-draw signal is emitted when the renderer needs
+	 * to be redrawn. Use #gtk_source_gutter_renderer_queue_draw
+	 * to emit this signal from an implementation of the
+	 * #GtkSourceGutterRenderer interface.
+	 *
+	 */
+	signals[QUEUE_DRAW] =
+		g_signal_new ("queue-draw",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GtkSourceGutterRendererClass, queue_draw),
+		              NULL,
+		              NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE,
+		              0);
+
+	/**
+	 * GtkSourceGutterRenderer::query-tooltip:
+	 * @renderer: the #GtkSourceGutterRenderer who emits the signal
+	 * @iter: a #GtkTextIter
+	 * @area: a #GdkRectangle
+	 * @x: the x position (in window coordinates)
+	 * @y: the y position (in window coordinates)
+	 * @tooltip: a #GtkTooltip
+	 *
+	 * The ::query-tooltip signal is emitted when the renderer can
+	 * show a tooltip.
+	 *
+	 */
+	signals[QUERY_TOOLTIP] =
+		g_signal_new ("query-tooltip",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_tooltip),
+		              g_signal_accumulator_true_handled,
+		              NULL,
+		              _gtksourceview_marshal_BOOLEAN__BOXED_BOXED_INT_INT_OBJECT,
+		              G_TYPE_BOOLEAN,
+		              5,
+		              GTK_TYPE_TEXT_ITER,
+		              GDK_TYPE_RECTANGLE,
+		              G_TYPE_INT,
+		              G_TYPE_INT,
+		              GTK_TYPE_TOOLTIP);
+
+	/**
+	 * GtkSourceGutterRenderer::query-data:
+	 * @renderer: the #GtkSourceGutterRenderer who emits the signal
+	 * @start: a #GtkTextIter
+	 * @end: a #GtkTextIter
+	 * @state: the renderer state
+	 *
+	 * The ::query-data signal is emitted when the renderer needs
+	 * to be filled with data just before a cell is drawn. This can
+	 * be used by general renderer implementations to allow render
+	 * data to be filled in externally.
+	 *
+	 */
+	signals[QUERY_DATA] =
+		g_signal_new ("query-data",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_data),
+		              NULL,
+		              NULL,
+		              _gtksourceview_marshal_VOID__BOXED_BOXED_FLAGS,
+		              G_TYPE_NONE,
+		              3,
+		              GTK_TYPE_TEXT_ITER,
+		              GTK_TYPE_TEXT_ITER,
+		              GTK_TYPE_SOURCE_GUTTER_RENDERER_STATE);
+
+	/**
+	 * GtkSourceGutterRenderer::query-activatable:
+	 * @renderer: the #GtkSourceGutterRenderer who emits the signal
+	 * @iter: a #GtkTextIter
+	 * @area: a #GdkRectangle
+	 * @event: the #GdkEvent that is causing the activatable query
+	 *
+	 * The ::query-activatable signal is emitted when the renderer
+	 * can possibly be activated.
+	 *
+	 */
+	signals[QUERY_ACTIVATABLE] =
+		g_signal_new ("query-activatable",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_activatable),
+		              g_signal_accumulator_true_handled,
+		              NULL,
+		              _gtksourceview_marshal_BOOLEAN__BOXED_BOXED_BOXED,
+		              G_TYPE_BOOLEAN,
+		              3,
+		              GTK_TYPE_TEXT_ITER,
+		              GDK_TYPE_RECTANGLE,
+		              GDK_TYPE_EVENT);
+
+	/**
+	 * GtkSourceGutterRenderer:view:
+	 *
+	 * The view on which the renderer is placed.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_VIEW,
+	                                 g_param_spec_object ("view",
+	                                                      _("The View"),
+	                                                      _("The view"),
+	                                                      GTK_TYPE_TEXT_VIEW,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	/**
+	 * GtkSourceGutterRenderer:alignment-mode:
+	 *
+	 * The alignment mode of the renderer. This can be used to indicate
+	 * that in the case a cell spans multiple lines (due to text wrapping)
+	 * the alignment should work on either the full cell, the first line
+	 * or the last line.
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_ALIGNMENT_MODE,
+	                                 g_param_spec_enum ("alignment-mode",
+	                                                    _("Alignment Mode"),
+	                                                    _("The alignment mode"),
+	                                                    GTK_TYPE_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE,
+	                                                    GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+	                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * GtkSourceGutterRenderer:window-type:
+	 *
+	 * The window type of the view on which the renderer is placed (left,
+	 * or right).
+	 *
+	 **/
+	g_object_class_install_property (object_class,
+	                                 PROP_WINDOW_TYPE,
+	                                 g_param_spec_enum ("window-type",
+	                                                    _("Window Type"),
+	                                                    _("The window type"),
+	                                                    GTK_TYPE_TEXT_WINDOW_TYPE,
+	                                                    GTK_TEXT_WINDOW_PRIVATE,
+	                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_SIZE,
+	                                 g_param_spec_int ("size",
+	                                                   _("Size"),
+	                                                   _("The size"),
+	                                                   0,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_BACKGROUND_GDK,
+	                                 g_param_spec_boxed ("background-gdk",
+	                                                     "Background GDK",
+	                                                     "The background color",
+	                                                     GDK_TYPE_COLOR,
+	                                                     G_PARAM_READWRITE));
+
+
+	g_object_class_install_property (object_class,
+	                                 PROP_BACKGROUND_SET,
+	                                 g_param_spec_boolean ("background-set",
+	                                                       "Background Set",
+	                                                       "Whether the background color is set",
+	                                                       FALSE,
+	                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+gtk_source_gutter_renderer_init (GtkSourceGutterRenderer *self)
+{
+	self->priv = GTK_SOURCE_GUTTER_RENDERER_GET_PRIVATE (self);
+}
+
+/**
+ * gtk_source_gutter_renderer_begin:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @cr: a #cairo_t
+ * @background_area: a #GdkRectangle
+ * @cell_area: a #GdkRectangle
+ * @start: a #GtkTextIter
+ * @end: a #GtkTextIter
+ *
+ * Called when drawing a region begins. The region to be drawn is indicated
+ * by @start and @end. The purpose is to allow the implementation to precompute
+ * some state before the ::draw method is called for each cell.
+ *
+ **/
+void
+gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+                                  cairo_t                 *cr,
+                                  const GdkRectangle      *background_area,
+                                  const GdkRectangle      *cell_area,
+                                  GtkTextIter             *start,
+                                  GtkTextIter             *end)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+	g_return_if_fail (cr != NULL);
+	g_return_if_fail (background_area != NULL);
+	g_return_if_fail (cell_area != NULL);
+	g_return_if_fail (start != NULL);
+	g_return_if_fail (end != NULL);
+
+	if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->begin)
+	{
+		GTK_SOURCE_GUTTER_RENDERER_CLASS (
+			G_OBJECT_GET_CLASS (renderer))->begin (renderer,
+			                                       cr,
+			                                       background_area,
+			                                       cell_area,
+			                                       start,
+			                                       end);
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_draw:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @cr: the cairo render context
+ * @background_area: a #GdkRectangle indicating the total area to be drawn
+ * @cell_area: a #GdkRectangle indicating the area to draw content
+ * @start: a #GtkTextIter
+ * @end: a #GtkTextIter
+ * @state: a #GtkSourceGutterRendererState
+ *
+ * Main renderering method. Implementations should implement this method to
+ * draw onto the cairo context. The @background_area indicates total area of
+ * the cell (without padding or margin) to be drawn. The @cell_area indicates
+ * the area where content can be drawn (text, images, etc).
+ *
+ * The @state argument indicates the current state of the renderer and should
+ * be taken into account to properly draw the different possible states
+ * (cursor, prelit, selected) if appropriate.
+ *
+ **/
+void
+gtk_source_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
+                                 cairo_t                      *cr,
+                                 const GdkRectangle           *background_area,
+                                 const GdkRectangle           *cell_area,
+                                 GtkTextIter                  *start,
+                                 GtkTextIter                  *end,
+                                 GtkSourceGutterRendererState  state)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+	g_return_if_fail (cr != NULL);
+	g_return_if_fail (background_area != NULL);
+	g_return_if_fail (cell_area != NULL);
+	g_return_if_fail (start != NULL);
+	g_return_if_fail (end != NULL);
+
+	if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->draw)
+	{
+		GTK_SOURCE_GUTTER_RENDERER_CLASS (
+			G_OBJECT_GET_CLASS (renderer))->draw (renderer,
+			                                      cr,
+			                                      background_area,
+			                                      cell_area,
+			                                      start,
+			                                      end,
+			                                      state);
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_end:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Called when drawing a region of lines has ended.
+ *
+ **/
+void
+gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->end)
+	{
+		GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->end (renderer);
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_query_activatable:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @iter: a #GtkTextIter at the start of the line to be activated
+ * @area: a #GdkRectangle of the cell area to be activated
+ * @event: the event that triggered the query
+ *
+ * Get whether the renderer is activatable at the location in @event. This is
+ * called from #GtkSourceGutter to determine whether a renderer is activatable
+ * using the mouse pointer.
+ *
+ * Returns: %TRUE if the renderer can be activated, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+                                              GtkTextIter             *iter,
+                                              const GdkRectangle      *area,
+                                              GdkEvent                *event)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (area != NULL, FALSE);
+	g_return_val_if_fail (event != NULL, FALSE);
+
+	ret = FALSE;
+
+	g_signal_emit (renderer,
+	               signals[QUERY_ACTIVATABLE],
+	               0,
+	               iter,
+	               area,
+	               event,
+	               &ret);
+
+	return ret;
+}
+
+/**
+ * gtk_source_gutter_renderer_activate:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @iter: a #GtkTextIter at the start of the line where the renderer is activated
+ * @area: a #GdkRectangle of the cell area where the renderer is activated
+ * @event: the event that triggered the activation
+ *
+ * Emits the ::activate signal of the renderer. This is called from
+ * #GtkSourceGutter and should never have to be called manually.
+ *
+ */
+void
+gtk_source_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+                                     GtkTextIter             *iter,
+                                     const GdkRectangle      *area,
+                                     GdkEvent                *event)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+	g_return_if_fail (iter != NULL);
+	g_return_if_fail (area != NULL);
+	g_return_if_fail (event != NULL);
+
+	g_signal_emit (renderer, signals[ACTIVATE], 0, iter, area, event);
+}
+
+/**
+ * gtk_source_gutter_renderer_queue_draw:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Emits the ::queue-draw signal of the renderer. Call this from an
+ * implementation to inform that the renderer has changed such that it needs
+ * to redraw.
+ *
+ **/
+void
+gtk_source_gutter_renderer_queue_draw (GtkSourceGutterRenderer *renderer)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	g_signal_emit (renderer, signals[QUEUE_DRAW], 0);
+}
+
+/**
+ * gtk_source_gutter_renderer_query_tooltip:
+ * @renderer: a #GtkSourceGutterRenderer.
+ * @iter: a #GtkTextIter.
+ * @area: a #GdkRectangle.
+ * @x: The x position of the tooltip.
+ * @y: The y position of the tooltip.
+ * @tooltip: a #GtkTooltip.
+ *
+ * Emits the ::query-tooltip signal. This function is called from
+ * #GtkSourceGutter. Implementations can override the default signal handler
+ * or can connect to the signal externally.
+ *
+ * Returns: %TRUE if the tooltip has been set, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
+                                          GtkTextIter             *iter,
+                                          const GdkRectangle      *area,
+                                          gint                     x,
+                                          gint                     y,
+                                          GtkTooltip              *tooltip)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (area != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_TOOLTIP (tooltip), FALSE);
+
+	ret = FALSE;
+
+	g_signal_emit (renderer,
+	               signals[QUERY_TOOLTIP],
+	               0,
+	               iter,
+	               area,
+	               x,
+	               y,
+	               tooltip,
+	               &ret);
+
+	return ret;
+}
+
+/**
+ * gtk_source_gutter_renderer_query_data:
+ * @renderer: a #GtkSourceGutterRenderer.
+ * @start: a #GtkTextIter.
+ * @end: a #GtkTextIter.
+ * @state: a #GtkSourceGutterRendererState.
+ *
+ * Emit the ::query-data signal. This function is called to query for data
+ * just before rendering a cell. This is called from the #GtkSourceGutter.
+ * Implementations can override the default signal handler or can connect
+ * a signal handler externally to the ::query-data signal.
+ *
+ **/
+void
+gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer      *renderer,
+                                       GtkTextIter                  *start,
+                                       GtkTextIter                  *end,
+                                       GtkSourceGutterRendererState  state)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+	g_return_if_fail (start != NULL);
+	g_return_if_fail (end != NULL);
+
+	g_signal_emit (renderer, signals[QUERY_DATA], 0, start, end, state);
+}
+
+/**
+ * gtk_source_gutter_renderer_set_visible:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @visible: the visibility
+ *
+ * Set whether the gutter renderer is visible.
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_visible (GtkSourceGutterRenderer *renderer,
+                                        gboolean                 visible)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	if (visible != renderer->priv->visible)
+	{
+		renderer->priv->visible = visible;
+
+		g_object_notify (G_OBJECT (renderer), "visible");
+
+		gtk_source_gutter_renderer_queue_draw (renderer);
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_get_visible:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get whether the gutter renderer is visible.
+ *
+ * Returns: %TRUE if the renderer is visible, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_get_visible (GtkSourceGutterRenderer *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+
+	return renderer->priv->visible;
+}
+
+/**
+ * gtk_source_gutter_renderer_set_padding:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xpad: the x-padding
+ * @ypad: the y-padding
+ *
+ * Set the padding of the gutter renderer. Both @xpad and @ypad can be
+ * -1, which means the values will not be changed (this allows changing only
+ * one of the values).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_padding (GtkSourceGutterRenderer *renderer,
+                                        gint                     xpad,
+                                        gint                     ypad)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	set_xpad (renderer, xpad);
+	set_ypad (renderer, ypad);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_padding:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xpad: (out caller-allocates) (allow-none): return location for the x-padding (can be %NULL)
+ * @ypad: (out caller-allocates) (allow-none): return location for the y-padding (can be %NULL)
+ *
+ * Get the x-padding and y-padding of the gutter renderer.
+ *
+ **/
+void
+gtk_source_gutter_renderer_get_padding (GtkSourceGutterRenderer *renderer,
+                                        gint                    *xpad,
+                                        gint                    *ypad)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	if (xpad)
+	{
+		*xpad = renderer->priv->xpad;
+	}
+
+	if (ypad)
+	{
+		*ypad = renderer->priv->ypad;
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_set_alignment:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xalign: the x-alignment
+ * @yalign: the y-alignment
+ *
+ * Set the alignment of the gutter renderer. Both @xalign and @yalign can be
+ * -1, which means the values will not be changed (this allows changing only
+ * one of the values).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_alignment (GtkSourceGutterRenderer *renderer,
+                                          gfloat                   xalign,
+                                          gfloat                   yalign)
+{
+	gboolean changed_x;
+	gboolean changed_y;
+
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	changed_x = set_xalign (renderer, xalign, FALSE);
+	changed_y = set_yalign (renderer, yalign, FALSE);
+
+	if (changed_x || changed_y)
+	{
+		gtk_source_gutter_renderer_queue_draw (renderer);
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_get_alignment:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xalign: (out caller-allocates) (allow-none): return location for the x-alignment (can be %NULL)
+ * @yalign: (out caller-allocates) (allow-none): return location for the y-alignment (can be %NULL)
+ *
+ * Get the x-alignment and y-alignment of the gutter renderer.
+ *
+ **/
+void
+gtk_source_gutter_renderer_get_alignment (GtkSourceGutterRenderer *renderer,
+                                          gfloat                  *xalign,
+                                          gfloat                  *yalign)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	if (xalign)
+	{
+		*xalign = renderer->priv->xalign;
+	}
+
+	if (yalign)
+	{
+		*yalign = renderer->priv->yalign;
+	}
+}
+
+/**
+ * gtk_source_gutter_renderer_set_alignment_mode:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @mode: a #GtkSourceGutterRendererAlignmentMode
+ *
+ * Set the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see :xalign and :yalign).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer              *renderer,
+                                               GtkSourceGutterRendererAlignmentMode  mode)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	set_alignment_mode (renderer, mode);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_alignment_mode:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see :xalign and :yalign).
+ *
+ * Returns: a #GtkSourceGutterRendererAlignmentMode
+ *
+ **/
+GtkSourceGutterRendererAlignmentMode
+gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), 0);
+
+	return renderer->priv->alignment_mode;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_window_type:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the #GtkTextWindowType associated with the gutter renderer.
+ *
+ * Returns: a #GtkTextWindowType
+ *
+ **/
+GtkTextWindowType
+gtk_source_gutter_renderer_get_window_type (GtkSourceGutterRenderer *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), GTK_TEXT_WINDOW_PRIVATE);
+
+	return renderer->priv->window_type;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_view:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the view associated to the gutter renderer
+ *
+ * Returns: (transfer none): a #GtkTextView
+ *
+ **/
+GtkTextView *
+gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), NULL);
+
+	return renderer->priv->view;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_size:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the size of the renderer.
+ *
+ * Returns: the size of the renderer.
+ *
+ **/
+gint
+gtk_source_gutter_renderer_get_size (GtkSourceGutterRenderer *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), 0);
+
+	return renderer->priv->size;
+}
+
+/**
+ * gtk_source_gutter_renderer_set_size:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @size: the size
+ *
+ * Sets the size of the renderer. A value of -1 specifies that the size
+ * is to be determined dynamically.
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_size (GtkSourceGutterRenderer *renderer,
+                                     gint                     size)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	set_size (renderer, size);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_background:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @color: (out caller-allocates) (allow-none): return value for a #GdkColor
+ *
+ * Get the background color of the renderer.
+ *
+ * Returns: %TRUE if the background color is set, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_get_background (GtkSourceGutterRenderer *renderer,
+                                           GdkColor                *color)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+
+	if (color)
+	{
+		*color = renderer->priv->background_gdk;
+	}
+
+	return renderer->priv->background_set;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_background:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @color: (allow-none): a #GdkColor or %NULL
+ *
+ * Set the background color of the renderer. If @color is set to %NULL, the
+ * renderer will not have a background color.
+ *
+ */
+void
+gtk_source_gutter_renderer_set_background (GtkSourceGutterRenderer *renderer,
+                                           const GdkColor          *color)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+	set_background_gdk (renderer, color);
+}
diff --git a/gtksourceview/gtksourcegutterrenderer.h b/gtksourceview/gtksourcegutterrenderer.h
new file mode 100644
index 0000000..862bd4f
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderer.h
@@ -0,0 +1,218 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- *
+ * gtksourcegutterrenderer.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER			(gtk_source_gutter_renderer_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRenderer))
+#define GTK_SOURCE_GUTTER_RENDERER_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRenderer const))
+#define GTK_SOURCE_GUTTER_RENDERER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER))
+#define GTK_SOURCE_GUTTER_RENDERER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererClass))
+
+typedef struct _GtkSourceGutterRenderer		GtkSourceGutterRenderer;
+typedef struct _GtkSourceGutterRendererClass	GtkSourceGutterRendererClass;
+typedef struct _GtkSourceGutterRendererPrivate	GtkSourceGutterRendererPrivate;
+
+/**
+ * GtkSourceGutterRendererState:
+ *
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL: normal state
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR: area in the renderer represents the
+ * line on which the insert cursor is currently positioned
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT: the mouse pointer is currently
+ * over the activatable area of the renderer
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED: area in the renderer represents
+ * a line in the buffer which contains part of the selection
+ **/
+typedef enum
+{
+	GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL = 0,
+	GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR = 1 << 0,
+	GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT = 1 << 1,
+	GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED = 1 << 2
+} GtkSourceGutterRendererState;
+
+typedef enum
+{
+	GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+	GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+	GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST,
+} GtkSourceGutterRendererAlignmentMode;
+
+struct _GtkSourceGutterRenderer
+{
+	/*< private >*/
+	GInitiallyUnowned parent;
+
+	GtkSourceGutterRendererPrivate *priv;
+};
+
+struct _GtkSourceGutterRendererClass
+{
+	/*< private >*/
+	GInitiallyUnownedClass parent_class;
+
+	/*< public >*/
+	void (*begin)               (GtkSourceGutterRenderer     *renderer,
+	                             cairo_t                     *cr,
+	                             const GdkRectangle          *background_area,
+	                             const GdkRectangle          *cell_area,
+	                             GtkTextIter                 *start,
+	                             GtkTextIter                 *end);
+
+	void (*draw)                (GtkSourceGutterRenderer      *renderer,
+	                             cairo_t                      *cr,
+	                             const GdkRectangle           *background_area,
+	                             const GdkRectangle           *cell_area,
+	                             GtkTextIter                  *start,
+	                             GtkTextIter                  *end,
+	                             GtkSourceGutterRendererState  state);
+
+	void (*end)                 (GtkSourceGutterRenderer      *renderer);
+
+	/* Signal handlers */
+	gboolean (*query_activatable) (GtkSourceGutterRenderer      *renderer,
+	                               GtkTextIter                  *iter,
+	                               const GdkRectangle           *area,
+	                               GdkEvent                     *event);
+
+	void (*activate)            (GtkSourceGutterRenderer      *renderer,
+	                             GtkTextIter                  *iter,
+	                             const GdkRectangle           *area,
+	                             GdkEvent                     *event);
+
+	void (*queue_draw)          (GtkSourceGutterRenderer      *renderer);
+
+	gboolean (*query_tooltip)   (GtkSourceGutterRenderer      *renderer,
+	                             GtkTextIter                  *iter,
+	                             const GdkRectangle           *area,
+	                             gint                          x,
+	                             gint                          y,
+	                             GtkTooltip                   *tooltip);
+
+	void (*query_data)          (GtkSourceGutterRenderer      *renderer,
+	                             GtkTextIter                  *start,
+	                             GtkTextIter                  *end,
+	                             GtkSourceGutterRendererState  state);
+};
+
+GType gtk_source_gutter_renderer_get_type (void) G_GNUC_CONST;
+
+void     gtk_source_gutter_renderer_begin           (GtkSourceGutterRenderer      *renderer,
+                                                     cairo_t                      *cr,
+                                                     const GdkRectangle           *background_area,
+                                                     const GdkRectangle           *cell_area,
+                                                     GtkTextIter                  *start,
+                                                     GtkTextIter                  *end);
+
+void     gtk_source_gutter_renderer_draw            (GtkSourceGutterRenderer      *renderer,
+                                                     cairo_t                      *cr,
+                                                     const GdkRectangle           *background_area,
+                                                     const GdkRectangle           *cell_area,
+                                                     GtkTextIter                  *start,
+                                                     GtkTextIter                  *end,
+                                                     GtkSourceGutterRendererState  state);
+
+void     gtk_source_gutter_renderer_end             (GtkSourceGutterRenderer      *renderer);
+
+gint     gtk_source_gutter_renderer_get_size        (GtkSourceGutterRenderer      *renderer);
+void    gtk_source_gutter_renderer_set_size         (GtkSourceGutterRenderer      *renderer,
+                                                     gint                          size);
+
+void     gtk_source_gutter_renderer_set_visible     (GtkSourceGutterRenderer      *renderer,
+                                                     gboolean                      visible);
+
+gboolean gtk_source_gutter_renderer_get_visible     (GtkSourceGutterRenderer      *renderer);
+
+void     gtk_source_gutter_renderer_get_padding     (GtkSourceGutterRenderer      *renderer,
+                                                     gint                         *xpad,
+                                                     gint                         *ypad);
+
+void     gtk_source_gutter_renderer_set_padding     (GtkSourceGutterRenderer      *renderer,
+                                                     gint                          xpad,
+                                                     gint                          ypad);
+
+void     gtk_source_gutter_renderer_get_alignment   (GtkSourceGutterRenderer      *renderer,
+                                                     gfloat                       *xalign,
+                                                     gfloat                       *yalign);
+
+void     gtk_source_gutter_renderer_set_alignment   (GtkSourceGutterRenderer      *renderer,
+                                                     gfloat                        xalign,
+                                                     gfloat                        yalign);
+
+void     gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer              *renderer,
+                                                        GtkSourceGutterRendererAlignmentMode  mode);
+
+GtkTextWindowType
+	gtk_source_gutter_renderer_get_window_type  (GtkSourceGutterRenderer      *renderer);
+
+GtkTextView *gtk_source_gutter_renderer_get_view    (GtkSourceGutterRenderer      *renderer);
+
+GtkSourceGutterRendererAlignmentMode
+	gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer    *renderer);
+
+gboolean gtk_source_gutter_renderer_get_background  (GtkSourceGutterRenderer      *renderer,
+                                                     GdkColor                     *color);
+
+void     gtk_source_gutter_renderer_set_background  (GtkSourceGutterRenderer      *renderer,
+                                                     const GdkColor               *color);
+
+/* Emits the 'activate' signal */
+void     gtk_source_gutter_renderer_activate        (GtkSourceGutterRenderer      *renderer,
+                                                     GtkTextIter                  *iter,
+                                                     const GdkRectangle           *area,
+                                                     GdkEvent                     *event);
+
+/* Emits the 'query-activatable' signal */
+gboolean gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer      *renderer,
+                                                       GtkTextIter                  *iter,
+                                                       const GdkRectangle           *area,
+                                                       GdkEvent                     *event);
+
+/* Emits the 'queue-draw' signal */
+void     gtk_source_gutter_renderer_queue_draw      (GtkSourceGutterRenderer      *renderer);
+
+/* Emits the 'query-tooltip' signal */
+gboolean gtk_source_gutter_renderer_query_tooltip   (GtkSourceGutterRenderer      *renderer,
+                                                     GtkTextIter                  *iter,
+                                                     const GdkRectangle           *area,
+                                                     gint                          x,
+                                                     gint                          y,
+                                                     GtkTooltip                   *tooltip);
+
+/* Emits the 'query-data' signal */
+void     gtk_source_gutter_renderer_query_data      (GtkSourceGutterRenderer      *renderer,
+                                                     GtkTextIter                  *start,
+                                                     GtkTextIter                  *end,
+                                                     GtkSourceGutterRendererState  state);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_H__ */
diff --git a/gtksourceview/gtksourcegutterrendererlines.c b/gtksourceview/gtksourcegutterrendererlines.c
new file mode 100644
index 0000000..b5a1030
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererlines.c
@@ -0,0 +1,344 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererlines.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gtksourcegutterrendererlines.h"
+#include "gtksourceview.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesPrivate))
+
+struct _GtkSourceGutterRendererLinesPrivate
+{
+	GtkTextBuffer *buffer;
+
+	gint num_line_digits;
+
+	guint changed_handler_id;
+	guint buffer_notify_handler_id;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererLines, gtk_source_gutter_renderer_lines, GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT)
+
+static void
+gtk_source_gutter_renderer_lines_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_lines_parent_class)->finalize (object);
+}
+
+static void
+recalculate_size (GtkSourceGutterRendererLines *renderer)
+{
+	gint num_lines;
+	gint num_digits = 0;
+	gint num;
+
+	num_lines = gtk_text_buffer_get_line_count (renderer->priv->buffer);
+
+	num = num_lines;
+
+	while (num > 0)
+	{
+		num /= 10;
+		++num_digits;
+	}
+
+	num_digits = MAX (num_digits, 2);
+
+	if (num_digits != renderer->priv->num_line_digits)
+	{
+		gchar *markup;
+		gint size;
+
+		renderer->priv->num_line_digits = num_digits;
+
+		num_lines = MAX (num_lines, 99);
+
+		markup = g_strdup_printf ("<b>%d</b>", num_lines);
+		gtk_source_gutter_renderer_text_measure_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
+		                                                markup,
+		                                                &size,
+		                                                NULL);
+		g_free (markup);
+
+		gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (renderer),
+		                                     size);
+	}
+}
+
+static void
+on_buffer_changed (GtkSourceBuffer              *buffer,
+                   GtkSourceGutterRendererLines *renderer)
+{
+	recalculate_size (renderer);
+}
+
+static void
+buffer_notify (GtkSourceGutterRendererLines *renderer,
+               gpointer                      where_the_object_was)
+{
+	renderer->priv->buffer = NULL;
+}
+
+static void
+set_buffer (GtkSourceGutterRendererLines *renderer,
+            GtkTextBuffer                *buffer)
+{
+	if (renderer->priv->buffer)
+	{
+		g_signal_handler_disconnect (renderer->priv->buffer,
+		                             renderer->priv->changed_handler_id);
+
+		g_object_weak_unref (G_OBJECT (renderer->priv->buffer),
+		                     (GWeakNotify)buffer_notify,
+		                     renderer);
+
+		renderer->priv->buffer = NULL;
+	}
+
+	if (buffer)
+	{
+		renderer->priv->buffer = buffer;
+
+		renderer->priv->changed_handler_id =
+			g_signal_connect (renderer->priv->buffer,
+			                  "changed",
+			                  G_CALLBACK (on_buffer_changed),
+			                  renderer);
+
+		g_object_weak_ref (G_OBJECT (renderer->priv->buffer),
+		                   (GWeakNotify)buffer_notify,
+		                   renderer);
+
+		recalculate_size (renderer);
+	}
+}
+
+static void
+gutter_renderer_query_data (GtkSourceGutterRenderer      *renderer,
+                            GtkTextIter                  *start,
+                            GtkTextIter                  *end,
+                            GtkSourceGutterRendererState  state)
+{
+	gchar *text;
+	gint line;
+	gboolean current_line;
+
+	line = gtk_text_iter_get_line (start) + 1;
+
+	current_line = (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR) &&
+	               gtk_text_view_get_cursor_visible (gtk_source_gutter_renderer_get_view (renderer));
+
+	if (current_line)
+	{
+		text = g_strdup_printf ("<b>%d</b>", line);
+	}
+	else
+	{
+		text = g_strdup_printf ("%d", line);
+	}
+
+	gtk_source_gutter_renderer_text_set_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
+	                                            text,
+	                                            -1);
+
+	g_free (text);
+}
+
+static void
+on_buffer_notify (GtkTextView                  *view,
+                  GParamSpec                   *spec,
+                  GtkSourceGutterRendererLines *renderer)
+{
+	set_buffer (renderer, gtk_text_view_get_buffer (view));
+}
+
+static void
+gtk_source_gutter_renderer_lines_dispose (GObject *object)
+{
+	GtkSourceGutterRenderer *renderer;
+	GtkSourceGutterRendererLines *lines;
+	GtkTextView *view;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER (object);
+	lines = GTK_SOURCE_GUTTER_RENDERER_LINES (object);
+
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	if (view != NULL && lines->priv->buffer_notify_handler_id != 0)
+	{
+		g_signal_handler_disconnect (view,
+		                             lines->priv->buffer_notify_handler_id);
+
+		lines->priv->buffer_notify_handler_id = 0;
+	}
+
+	set_buffer (lines, NULL);
+
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_lines_parent_class)->dispose (object);
+}
+
+static void
+extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
+                          GtkTextIter                  *line_start)
+{
+	GtkTextIter start;
+	GtkTextIter end;
+	GtkTextIter line_end;
+
+	gtk_text_buffer_get_selection_bounds (renderer->priv->buffer, &start, &end);
+
+	line_end = *line_start;
+
+	if (!gtk_text_iter_ends_line (&line_end))
+	{
+		gtk_text_iter_forward_to_line_end (&line_end);
+	}
+
+	if (gtk_text_iter_compare (&start, line_start) < 0)
+	{
+		gtk_text_buffer_select_range (renderer->priv->buffer,
+		                              &start,
+		                              &line_end);
+	}
+	else if (gtk_text_iter_compare (&end, &line_end) < 0)
+	{
+		/* if the selection is in this line, extend
+		 * the selection to the whole line */
+		gtk_text_buffer_select_range (renderer->priv->buffer,
+		                              &line_end,
+		                              line_start);
+	}
+	else
+	{
+		gtk_text_buffer_select_range (renderer->priv->buffer,
+		                              &end,
+		                              line_start);
+	}
+}
+
+static void
+select_line (GtkSourceGutterRendererLines *renderer,
+             GtkTextIter                  *line_start)
+{
+	GtkTextIter iter;
+
+	iter = *line_start;
+
+	if (!gtk_text_iter_ends_line (&iter))
+	{
+		gtk_text_iter_forward_to_line_end (&iter);
+	}
+
+	/* Select the line, put the cursor at the end of the line */
+	gtk_text_buffer_select_range (renderer->priv->buffer, &iter, line_start);
+}
+
+static void
+gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+                          GtkTextIter             *iter,
+                          const GdkRectangle      *rect,
+                          GdkEvent                *event)
+{
+	GtkSourceGutterRendererLines *lines;
+
+	lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
+
+	if (event->type == GDK_BUTTON_PRESS && (event->button.button == 1))
+	{
+		if ((event->button.state & GDK_CONTROL_MASK) != 0)
+		{
+			/* Single click + Ctrl -> select the line */
+			select_line (lines, iter);
+		}
+		else if ((event->button.state & GDK_SHIFT_MASK) != 0)
+		{
+			/* Single click + Shift -> extended current
+			   selection to include the clicked line */
+			extend_selection_to_line (lines, iter);
+		}
+		else
+		{
+			gtk_text_buffer_place_cursor (lines->priv->buffer, iter);
+		}
+	}
+	else if (event->type == GDK_2BUTTON_PRESS && (event->button.button == 1))
+	{
+		select_line (lines, iter);
+	}
+}
+
+static gboolean
+gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+                                   GtkTextIter             *iter,
+                                   const GdkRectangle      *area,
+                                   GdkEvent                *event)
+{
+	return GTK_SOURCE_GUTTER_RENDERER_LINES (renderer)->priv->buffer != NULL;
+}
+
+static void
+gtk_source_gutter_renderer_lines_constructed (GObject *gobject)
+{
+	GtkSourceGutterRendererLines *lines;
+	GtkSourceGutterRenderer *renderer;
+	GtkTextView *view;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER (gobject);
+	lines = GTK_SOURCE_GUTTER_RENDERER_LINES (gobject);
+
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	lines->priv->buffer_notify_handler_id =
+		g_signal_connect (view,
+		                  "notify::buffer",
+		                  G_CALLBACK (on_buffer_notify),
+		                  lines);
+
+	set_buffer (lines, gtk_text_view_get_buffer (view));
+}
+
+static void
+gtk_source_gutter_renderer_lines_class_init (GtkSourceGutterRendererLinesClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+	object_class->finalize = gtk_source_gutter_renderer_lines_finalize;
+	object_class->dispose = gtk_source_gutter_renderer_lines_dispose;
+	object_class->constructed = gtk_source_gutter_renderer_lines_constructed;
+
+	renderer_class->query_data = gutter_renderer_query_data;
+	renderer_class->query_activatable = gutter_renderer_query_activatable;
+	renderer_class->activate = gutter_renderer_activate;
+
+	g_type_class_add_private (object_class, sizeof(GtkSourceGutterRendererLinesPrivate));
+}
+
+static void
+gtk_source_gutter_renderer_lines_init (GtkSourceGutterRendererLines *self)
+{
+	self->priv = GTK_SOURCE_GUTTER_RENDERER_LINES_GET_PRIVATE (self);
+}
+
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_lines_new ()
+{
+	return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, NULL);
+}
diff --git a/gtksourceview/gtksourcegutterrendererlines.h b/gtksourceview/gtksourcegutterrendererlines.h
new file mode 100644
index 0000000..eb7b265
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererlines.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererlines.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_LINES_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_LINES_H__
+
+#include <gtksourceview/gtksourcegutterrenderertext.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES		(gtk_source_gutter_renderer_lines_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_LINES(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLines))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_CONST(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLines const))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_LINES(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_LINES_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesClass))
+
+typedef struct _GtkSourceGutterRendererLines		GtkSourceGutterRendererLines;
+typedef struct _GtkSourceGutterRendererLinesClass	GtkSourceGutterRendererLinesClass;
+typedef struct _GtkSourceGutterRendererLinesPrivate	GtkSourceGutterRendererLinesPrivate;
+
+struct _GtkSourceGutterRendererLines
+{
+	/*< private >*/
+	GtkSourceGutterRendererText parent;
+
+	GtkSourceGutterRendererLinesPrivate *priv;
+
+	/*< public >*/
+};
+
+struct _GtkSourceGutterRendererLinesClass
+{
+	/*< private >*/
+	GtkSourceGutterRendererTextClass parent_class;
+
+	/*< public >*/
+};
+
+GType gtk_source_gutter_renderer_lines_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_lines_new (void);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_LINES_H__ */
diff --git a/gtksourceview/gtksourcegutterrenderermarks.c b/gtksourceview/gtksourcegutterrenderermarks.c
new file mode 100644
index 0000000..bdd4018
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderermarks.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderermarks.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gtksourcegutterrenderermarks.h"
+#include "gtksourceview.h"
+#include "gtksourcemarkcategory.h"
+
+#define COMPOSITE_ALPHA                 225
+
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksPrivate))
+
+struct _GtkSourceGutterRendererMarksPrivate
+{
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererMarks, gtk_source_gutter_renderer_marks, GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF)
+
+static void
+gtk_source_gutter_renderer_marks_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_marks_parent_class)->finalize (object);
+}
+
+static gint
+sort_marks_by_priority (gconstpointer m1,
+			gconstpointer m2,
+			gpointer data)
+{
+	GtkSourceMark *mark1 = GTK_SOURCE_MARK (m1);
+	GtkSourceMark *mark2 = GTK_SOURCE_MARK (m2);
+	GtkSourceView *view = GTK_SOURCE_VIEW (data);
+	GtkTextIter iter1, iter2;
+	gint line1;
+	gint line2;
+
+	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark1)),
+	                                  &iter1,
+	                                  GTK_TEXT_MARK (mark1));
+
+	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark2)),
+	                                  &iter2,
+	                                  GTK_TEXT_MARK (mark2));
+
+	line1 = gtk_text_iter_get_line (&iter1);
+	line2 = gtk_text_iter_get_line (&iter2);
+
+	if (line1 == line2)
+	{
+		guint priority1;
+		guint priority2;
+
+		GtkSourceMarkCategory *c1;
+		GtkSourceMarkCategory *c2;
+
+		c1 = gtk_source_view_get_mark_category (view,
+		                                        gtk_source_mark_get_category (mark1));
+
+		c2 = gtk_source_view_get_mark_category (view,
+		                                        gtk_source_mark_get_category (mark2));
+
+		priority1 = gtk_source_mark_category_get_priority (c1);
+		priority2 = gtk_source_mark_category_get_priority (c2);
+
+		return priority1 - priority2;
+	}
+	else
+	{
+		return line2 - line1;
+	}
+}
+
+static int
+measure_line_height (GtkSourceView *view)
+{
+	PangoLayout *layout;
+	gint height = 12;
+
+	layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "QWERTY");
+
+	if (layout)
+	{
+		pango_layout_get_pixel_size (layout, NULL, &height);
+		g_object_unref (layout);
+	}
+
+	return height - 2;
+}
+
+static GdkPixbuf *
+composite_marks (GtkSourceView *view,
+                 GSList        *marks,
+                 gint           size)
+{
+	GdkPixbuf *composite;
+	gint mark_width;
+	gint mark_height;
+
+	/* Draw the mark with higher priority */
+	marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
+
+	composite = NULL;
+	mark_width = 0;
+	mark_height = 0;
+
+	/* composite all the pixbufs for the marks present at the line */
+	do
+	{
+		GtkSourceMark *mark;
+		GtkSourceMarkCategory *category;
+
+		const GdkPixbuf *pixbuf;
+
+		mark = marks->data;
+		category = gtk_source_view_get_mark_category (view,
+		                                              gtk_source_mark_get_category (mark));
+
+		pixbuf = gtk_source_mark_category_render_icon (category,
+		                                               GTK_WIDGET (view),
+		                                               size);
+
+		if (pixbuf != NULL)
+		{
+			if (composite == NULL)
+			{
+				composite = gdk_pixbuf_copy (pixbuf);
+				mark_width = gdk_pixbuf_get_width (composite);
+				mark_height = gdk_pixbuf_get_height (composite);
+			}
+			else
+			{
+				gint pixbuf_w;
+				gint pixbuf_h;
+
+				pixbuf_w = gdk_pixbuf_get_width (pixbuf);
+				pixbuf_h = gdk_pixbuf_get_height (pixbuf);
+
+				gdk_pixbuf_composite (pixbuf,
+				                      composite,
+				                      0, 0,
+				                      mark_width, mark_height,
+				                      0, 0,
+				                      (gdouble) pixbuf_w / mark_width,
+				                      (gdouble) pixbuf_h / mark_height,
+				                      GDK_INTERP_BILINEAR,
+				                      COMPOSITE_ALPHA);
+			}
+		}
+
+		marks = g_slist_next (marks);
+	}
+	while (marks);
+
+	return composite;
+}
+
+static void
+gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+                            GtkTextIter             *start,
+                            GtkTextIter             *end,
+                            GtkSourceGutterRendererState state)
+{
+	GSList *marks;
+	GdkPixbuf *pixbuf = NULL;
+	gint size = 0;
+	GtkSourceView *view;
+	GtkSourceBuffer *buffer;
+
+	view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+	marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
+	                                                    start,
+	                                                    NULL);
+
+	if (marks != NULL)
+	{
+		size = measure_line_height (view);
+		pixbuf = composite_marks (view, marks, size);
+
+		g_slist_free (marks);
+	}
+
+	g_object_set (G_OBJECT (renderer),
+	              "pixbuf", pixbuf,
+	              "xpad", 2,
+	              "ypad", 1,
+	              "yalign", 0.0,
+	              "xalign", 0.5,
+	              NULL);
+}
+
+static gboolean
+set_tooltip_widget_from_marks (GtkSourceView *view,
+                               GtkTooltip    *tooltip,
+                               GSList        *marks)
+{
+	GtkWidget *vbox = NULL;
+
+	for (; marks; marks = g_slist_next (marks))
+	{
+		const gchar *category;
+		GtkSourceMark *mark;
+		GtkSourceMarkCategory *cat;
+		gchar *text;
+		gboolean ismarkup = FALSE;
+		GtkWidget *label;
+		GtkWidget *hbox;
+		const GdkPixbuf *pixbuf;
+		gint size;
+
+		mark = marks->data;
+		category = gtk_source_mark_get_category (mark);
+
+		cat = gtk_source_view_get_mark_category (view, category);
+
+		if (cat == NULL)
+		{
+			continue;
+		}
+
+		text = gtk_source_mark_category_get_tooltip_markup (cat,
+		                                                    mark);
+
+		if (text == NULL)
+		{
+			text = gtk_source_mark_category_get_tooltip_text (cat,
+			                                                  mark);
+		}
+		else
+		{
+			ismarkup = TRUE;
+		}
+
+		if (text == NULL)
+		{
+			continue;
+		}
+
+		if (vbox == NULL)
+		{
+			vbox = gtk_vbox_new (FALSE, 0);
+			gtk_widget_show (vbox);
+		}
+
+		hbox = gtk_hbox_new (FALSE, 4);
+		gtk_widget_show (hbox);
+		gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+		label = gtk_label_new (NULL);
+
+		if (ismarkup)
+		{
+			gtk_label_set_markup (GTK_LABEL (label), text);
+		}
+		else
+		{
+			gtk_label_set_text (GTK_LABEL (label), text);
+		}
+
+		gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+		gtk_widget_show (label);
+
+		gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &size);
+		pixbuf = gtk_source_mark_category_render_icon (cat,
+		                                               GTK_WIDGET (view),
+		                                               size);
+
+		if (pixbuf != NULL)
+		{
+			GtkWidget *image;
+			PangoLayoutLine *line;
+			PangoRectangle rect;
+			GtkWidget *align;
+			GdkPixbuf *copy;
+
+			align = gtk_alignment_new (0, 0, 0, 0);
+			gtk_widget_show (align);
+
+			copy = gdk_pixbuf_copy (pixbuf);
+			image = gtk_image_new_from_pixbuf (copy);
+			g_object_unref (copy);
+
+			gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
+			gtk_widget_show (image);
+
+			/* Measure up to align exact */
+			line = pango_layout_get_line (gtk_label_get_layout (GTK_LABEL (label)), 0);
+			pango_layout_line_get_pixel_extents (line, NULL, &rect);
+
+			gtk_alignment_set_padding (GTK_ALIGNMENT (align),
+				                   (rect.height > size ? rect.height - size : size - rect.height) - 1,
+				                   0, 0, 0);
+			if (rect.height > size)
+			{
+				gtk_container_add (GTK_CONTAINER (align),
+				                   image);
+
+				image = align;
+			}
+			else if (size > rect.height)
+			{
+				gtk_container_add (GTK_CONTAINER (align),
+				                   label);
+				label = align;
+			}
+			else
+			{
+				gtk_widget_destroy (align);
+			}
+
+			gtk_box_pack_start (GTK_BOX (hbox),
+			                    image,
+			                    FALSE,
+			                    FALSE,
+			                    0);
+		}
+
+		gtk_box_pack_end (GTK_BOX (hbox),
+		                  label,
+		                  TRUE,
+		                  TRUE,
+		                  0);
+
+		if (g_slist_length (marks) != 1)
+		{
+			GtkWidget *separator;
+
+			separator = gtk_hseparator_new ();
+
+			gtk_widget_show (separator);
+
+			gtk_box_pack_start (GTK_BOX (vbox),
+			                    separator,
+			                    FALSE,
+			                    FALSE,
+			                    0);
+		}
+
+		g_free (text);
+	}
+
+	if (vbox == NULL)
+	{
+		return FALSE;
+	}
+
+	gtk_tooltip_set_custom (tooltip, vbox);
+
+	return TRUE;
+}
+
+static gboolean
+gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
+                               GtkTextIter             *iter,
+                               const GdkRectangle      *area,
+                               gint                     x,
+                               gint                     y,
+                               GtkTooltip              *tooltip)
+{
+	GSList *marks;
+	GtkSourceView *view;
+	GtkSourceBuffer *buffer;
+
+	view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+	marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
+	                                                    iter,
+	                                                    NULL);
+
+	if (marks != NULL)
+	{
+		marks = g_slist_sort_with_data (marks,
+		                                sort_marks_by_priority,
+		                                view);
+
+		marks = g_slist_reverse (marks);
+
+		return set_tooltip_widget_from_marks (view, tooltip, marks);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+                                   GtkTextIter             *iter,
+                                   const GdkRectangle      *area,
+                                   GdkEvent                *event)
+{
+	return TRUE;
+}
+
+static void
+gtk_source_gutter_renderer_marks_constructed (GObject *object)
+{
+	GtkSourceGutterRendererMarks *renderer;
+	GtkSourceView *view;
+	GtkSourceGutterRenderer *r;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER_MARKS (object);
+	r = GTK_SOURCE_GUTTER_RENDERER (renderer);
+
+	view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (r));
+
+	gtk_source_gutter_renderer_set_size (r,
+	                                     measure_line_height (view));
+}
+
+static void
+gtk_source_gutter_renderer_marks_class_init (GtkSourceGutterRendererMarksClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+	object_class->finalize = gtk_source_gutter_renderer_marks_finalize;
+	object_class->constructed = gtk_source_gutter_renderer_marks_constructed;
+
+	renderer_class->query_data = gutter_renderer_query_data;
+	renderer_class->query_tooltip = gutter_renderer_query_tooltip;
+	renderer_class->query_activatable = gutter_renderer_query_activatable;
+
+	/*g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererMarksPrivate));*/
+}
+
+static void
+gtk_source_gutter_renderer_marks_init (GtkSourceGutterRendererMarks *self)
+{
+	/*self->priv = GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_PRIVATE (self);*/
+}
+
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_marks_new ()
+{
+	return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, NULL);
+}
diff --git a/gtksourceview/gtksourcegutterrenderermarks.h b/gtksourceview/gtksourcegutterrenderermarks.h
new file mode 100644
index 0000000..80d063e
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderermarks.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderermarks.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__
+
+#include <gtksourceview/gtksourcegutterrendererpixbuf.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS		(gtk_source_gutter_renderer_marks_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarks))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_CONST(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarks const))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_MARKS(obj)	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_MARKS_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksClass))
+
+typedef struct _GtkSourceGutterRendererMarks		GtkSourceGutterRendererMarks;
+typedef struct _GtkSourceGutterRendererMarksClass	GtkSourceGutterRendererMarksClass;
+typedef struct _GtkSourceGutterRendererMarksPrivate	GtkSourceGutterRendererMarksPrivate;
+
+struct _GtkSourceGutterRendererMarks
+{
+	/*< private >*/
+	GtkSourceGutterRendererPixbuf parent;
+
+	GtkSourceGutterRendererMarksPrivate *priv;
+
+	/*< public >*/
+};
+
+struct _GtkSourceGutterRendererMarksClass
+{
+	/*< private >*/
+	GtkSourceGutterRendererPixbufClass parent_class;
+
+	/*< public >*/
+};
+
+GType gtk_source_gutter_renderer_marks_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_marks_new (void);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__ */
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.c b/gtksourceview/gtksourcegutterrendererpixbuf.c
new file mode 100644
index 0000000..1b20b29
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.c
@@ -0,0 +1,477 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererpixbuf.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "gtksourcegutterrendererpixbuf.h"
+#include "gtksourceview-i18n.h"
+#include "gtksourcepixbufhelper.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufPrivate))
+
+struct _GtkSourceGutterRendererPixbufPrivate
+{
+	GtkSourcePixbufHelper *helper;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererPixbuf, gtk_source_gutter_renderer_pixbuf, GTK_TYPE_SOURCE_GUTTER_RENDERER)
+
+enum
+{
+	PROP_0,
+	PROP_PIXBUF,
+	PROP_STOCK_ID,
+	PROP_ICON_NAME,
+	PROP_GICON,
+	PROP_STOCK_DETAIL
+};
+
+static void
+center_on (GtkSourceGutterRenderer *renderer,
+           const GdkRectangle      *cell_area,
+           GtkTextIter             *iter,
+           gint                     width,
+           gint                     height,
+           gfloat                   xalign,
+           gfloat                   yalign,
+           gint                    *x,
+           gint                    *y)
+{
+	GdkRectangle location;
+	GtkTextView *view;
+
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	gtk_text_view_get_iter_location (view, iter, &location);
+
+	*x = cell_area->x + (cell_area->width - width) * xalign;
+	*y = cell_area->y + (location.height - height) * yalign;
+}
+
+static void
+gutter_renderer_pixbuf_draw (GtkSourceGutterRenderer      *renderer,
+                             cairo_t                      *cr,
+                             const GdkRectangle           *background_area,
+                             const GdkRectangle           *cell_area,
+                             GtkTextIter                  *start,
+                             GtkTextIter                  *end,
+                             GtkSourceGutterRendererState  state)
+{
+	GtkSourceGutterRendererPixbuf *pix;
+	gint width;
+	gint height;
+	gfloat xalign;
+	gfloat yalign;
+	GtkSourceGutterRendererAlignmentMode mode;
+	GtkTextView *view;
+	gint x = 0;
+	gint y = 0;
+	GdkPixbuf *pixbuf;
+
+	/* Chain up to draw background */
+	GTK_SOURCE_GUTTER_RENDERER_CLASS (
+		gtk_source_gutter_renderer_pixbuf_parent_class)->draw (renderer,
+		                                                       cr,
+		                                                       background_area,
+		                                                       cell_area,
+		                                                       start,
+		                                                       end,
+		                                                       state);
+
+	pix = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (renderer);
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	pixbuf = gtk_source_pixbuf_helper_render (pix->priv->helper,
+	                                          GTK_WIDGET (view),
+	                                          cell_area->width);
+
+	if (!pixbuf)
+	{
+		return;
+	}
+
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_width (pixbuf);
+
+	gtk_source_gutter_renderer_get_alignment (renderer,
+	                                          &xalign,
+	                                          &yalign);
+
+	mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
+
+	switch (mode)
+	{
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL:
+			x = cell_area->x + (cell_area->width - width) * xalign;
+			y = cell_area->y + (cell_area->height - height) * yalign;
+			break;
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST:
+			center_on (renderer,
+			           cell_area,
+			           start,
+			           width,
+			           height,
+			           xalign,
+			           yalign,
+			           &x,
+			           &y);
+			break;
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
+			center_on (renderer,
+			           cell_area,
+			           end,
+			           width,
+			           height,
+			           xalign,
+			           yalign,
+			           &x,
+			           &y);
+			break;
+	}
+
+	gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
+	cairo_paint (cr);
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_finalize (GObject *object)
+{
+	GtkSourceGutterRendererPixbuf *renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+	gtk_source_pixbuf_helper_free (renderer->priv->helper);
+
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_pixbuf_parent_class)->finalize (object);
+}
+
+static void
+set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
+            GdkPixbuf                     *pixbuf)
+{
+	gtk_source_pixbuf_helper_set_pixbuf (renderer->priv->helper,
+	                                     pixbuf);
+
+	g_object_notify (G_OBJECT (renderer), "pixbuf");
+
+	gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_stock_id (GtkSourceGutterRendererPixbuf *renderer,
+              const gchar                   *stock_id)
+{
+	gtk_source_pixbuf_helper_set_stock_id (renderer->priv->helper,
+	                                       stock_id);
+
+	g_object_notify (G_OBJECT (renderer), "stock-id");
+
+	gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+                  const gchar                   *stock_detail)
+{
+	gtk_source_pixbuf_helper_set_stock_detail (renderer->priv->helper,
+	                                           stock_detail);
+
+	g_object_notify (G_OBJECT (renderer), "stock-detail");
+
+	gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_gicon (GtkSourceGutterRendererPixbuf *renderer,
+           GIcon                         *icon)
+{
+	gtk_source_pixbuf_helper_set_gicon (renderer->priv->helper,
+	                                    icon);
+
+	g_object_notify (G_OBJECT (renderer), "gicon");
+
+	gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
+               const gchar                   *icon_name)
+{
+	gtk_source_pixbuf_helper_set_icon_name (renderer->priv->helper,
+	                                        icon_name);
+
+	g_object_notify (G_OBJECT (renderer), "icon-name");
+
+	gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+
+static void
+gtk_source_gutter_renderer_pixbuf_set_property (GObject      *object,
+                                                guint         prop_id,
+                                                const GValue *value,
+                                                GParamSpec   *pspec)
+{
+	GtkSourceGutterRendererPixbuf *renderer;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+	switch (prop_id)
+	{
+		case PROP_PIXBUF:
+			set_pixbuf (renderer, g_value_get_object (value));
+			break;
+		case PROP_STOCK_ID:
+			set_stock_id (renderer, g_value_get_string (value));
+			break;
+		case PROP_STOCK_DETAIL:
+			set_stock_detail (renderer, g_value_get_string (value));
+			break;
+		case PROP_ICON_NAME:
+			set_icon_name (renderer, g_value_get_string (value));
+			break;
+		case PROP_GICON:
+			set_gicon (renderer, g_value_get_object (value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_get_property (GObject    *object,
+                                                guint       prop_id,
+                                                GValue     *value,
+                                                GParamSpec *pspec)
+{
+	GtkSourceGutterRendererPixbuf *renderer;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+	switch (prop_id)
+	{
+		case PROP_PIXBUF:
+			g_value_set_object (value,
+			                    gtk_source_pixbuf_helper_get_pixbuf (renderer->priv->helper));
+			break;
+		case PROP_STOCK_ID:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_stock_id (renderer->priv->helper));
+			break;
+		case PROP_STOCK_DETAIL:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_stock_detail (renderer->priv->helper));
+			break;
+		case PROP_ICON_NAME:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_icon_name (renderer->priv->helper));
+			break;
+		case PROP_GICON:
+			g_value_set_object (value,
+			                    gtk_source_pixbuf_helper_get_gicon (renderer->priv->helper));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+	object_class->finalize = gtk_source_gutter_renderer_pixbuf_finalize;
+
+	object_class->get_property = gtk_source_gutter_renderer_pixbuf_get_property;
+	object_class->set_property = gtk_source_gutter_renderer_pixbuf_set_property;
+
+	renderer_class->draw = gutter_renderer_pixbuf_draw;
+
+	g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererPixbufPrivate));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_PIXBUF,
+	                                 g_param_spec_object ("pixbuf",
+	                                                      _("Pixbuf"),
+	                                                      _("The pixbuf"),
+	                                                      GDK_TYPE_PIXBUF,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_STOCK_ID,
+	                                 g_param_spec_string ("stock-id",
+	                                                      _("Stock Id"),
+	                                                      _("The stock id"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_STOCK_DETAIL,
+	                                 g_param_spec_string ("stock-detail",
+	                                                      _("Stock Detail"),
+	                                                      _("The stock detail"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_ICON_NAME,
+	                                 g_param_spec_string ("icon-name",
+	                                                      _("Icon Name"),
+	                                                      _("The icon name"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_GICON,
+	                                 g_param_spec_object ("gicon",
+	                                                      _("GIcon"),
+	                                                      _("The gicon"),
+	                                                      G_TYPE_ICON,
+	                                                      G_PARAM_READWRITE));
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_init (GtkSourceGutterRendererPixbuf *self)
+{
+	self->priv = GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_PRIVATE (self);
+
+	self->priv->helper = gtk_source_pixbuf_helper_new ();
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_new:
+ *
+ * Create a new #GtkSourceGutterRendererPixbuf.
+ *
+ * Returns: (transfer full): A #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_pixbuf_new ()
+{
+	return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, NULL);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
+                                              GdkPixbuf                     *pixbuf)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+	g_return_if_fail (renderer == NULL || GDK_IS_PIXBUF (pixbuf));
+
+	set_pixbuf (renderer, pixbuf);
+}
+
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_get_pixbuf:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ *
+ * Get the pixbuf of the renderer.
+ *
+ * Returns: (transfer none): a #GdkPixbuf
+ *
+ **/
+GdkPixbuf *
+gtk_source_gutter_renderer_pixbuf_get_pixbuf (GtkSourceGutterRendererPixbuf *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+	return gtk_source_pixbuf_helper_get_pixbuf (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_stock_id (GtkSourceGutterRendererPixbuf *renderer,
+                                                const gchar                   *stock_id)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS (renderer));
+
+	set_stock_id (renderer, stock_id);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_stock_id (GtkSourceGutterRendererPixbuf *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+	return gtk_source_pixbuf_helper_get_stock_id (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+                                                    const gchar                   *stock_detail)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+
+	set_stock_detail (renderer, stock_detail);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_stock_detail (GtkSourceGutterRendererPixbuf *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+	return gtk_source_pixbuf_helper_get_stock_detail (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_gicon (GtkSourceGutterRendererPixbuf *renderer,
+                                             GIcon                         *icon)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+	g_return_if_fail (icon == NULL || G_IS_ICON (icon));
+
+	set_gicon (renderer, icon);
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_get_gicon:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ *
+ * Get the gicon of the renderer
+ *
+ * Returns: (transfer none): a #GIcon
+ *
+ **/
+GIcon *
+gtk_source_gutter_renderer_pixbuf_get_gicon (GtkSourceGutterRendererPixbuf *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+	return gtk_source_pixbuf_helper_get_gicon (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
+                                                 const gchar                   *icon_name)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+
+	set_icon_name (renderer, icon_name);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf *renderer)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+	return gtk_source_pixbuf_helper_get_icon_name (renderer->priv->helper);
+}
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.h b/gtksourceview/gtksourcegutterrendererpixbuf.h
new file mode 100644
index 0000000..e4c1c74
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderertext.h
+ * This file is part of GtkSourceView 
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_PIXBUF_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_PIXBUF_H__
+
+#include <gtksourceview/gtksourcegutterrenderer.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF			(gtk_source_gutter_renderer_pixbuf_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbuf))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbuf const))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufClass))
+
+typedef struct _GtkSourceGutterRendererPixbuf		GtkSourceGutterRendererPixbuf;
+typedef struct _GtkSourceGutterRendererPixbufClass	GtkSourceGutterRendererPixbufClass;
+typedef struct _GtkSourceGutterRendererPixbufPrivate	GtkSourceGutterRendererPixbufPrivate;
+
+struct _GtkSourceGutterRendererPixbuf
+{
+	/*< private >*/
+	GtkSourceGutterRenderer parent;
+
+	GtkSourceGutterRendererPixbufPrivate *priv;
+
+	/*< public >*/
+};
+
+struct _GtkSourceGutterRendererPixbufClass
+{
+	/*< private >*/
+	GtkSourceGutterRendererClass parent_class;
+
+	/*< public >*/
+};
+
+GType gtk_source_gutter_renderer_pixbuf_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_pixbuf_new (void);
+
+void         gtk_source_gutter_renderer_pixbuf_set_pixbuf       (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 GdkPixbuf                     *pixbuf);
+
+GdkPixbuf   *gtk_source_gutter_renderer_pixbuf_get_pixbuf       (GtkSourceGutterRendererPixbuf *renderer);
+
+void         gtk_source_gutter_renderer_pixbuf_set_stock_id     (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 const gchar                   *stock_id);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_stock_id     (GtkSourceGutterRendererPixbuf *renderer);
+
+void         gtk_source_gutter_renderer_pixbuf_set_icon_size    (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 GtkIconSize                    size);
+
+GtkIconSize  gtk_source_gutter_renderer_pixbuf_get_icon_size    (GtkSourceGutterRendererPixbuf *renderer);
+
+void         gtk_source_gutter_renderer_pixbuf_set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 const gchar                   *stock_detail);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_stock_detail (GtkSourceGutterRendererPixbuf *renderer);
+
+void         gtk_source_gutter_renderer_pixbuf_set_gicon        (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 GIcon                         *icon);
+
+GIcon       *gtk_source_gutter_renderer_pixbuf_get_gicon        (GtkSourceGutterRendererPixbuf *renderer);
+
+void         gtk_source_gutter_renderer_pixbuf_set_icon_name    (GtkSourceGutterRendererPixbuf *renderer,
+                                                                 const gchar                   *icon_name);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_icon_name    (GtkSourceGutterRendererPixbuf *renderer);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__ */
diff --git a/gtksourceview/gtksourcegutterrenderertext.c b/gtksourceview/gtksourcegutterrenderertext.c
new file mode 100644
index 0000000..a36ef40
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderertext.c
@@ -0,0 +1,432 @@
+#include "gtksourcegutterrenderertext.h"
+#include "gtksourceview-i18n.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextPrivate))
+
+struct _GtkSourceGutterRendererTextPrivate
+{
+	gchar *text;
+
+	PangoLayout *cached_layout;
+	PangoAttribute *fg_attr;
+	PangoAttrList *cached_attr_list;
+
+	guint is_markup : 1;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererText, gtk_source_gutter_renderer_text, GTK_TYPE_SOURCE_GUTTER_RENDERER)
+
+enum
+{
+	PROP_0,
+	PROP_MARKUP,
+	PROP_TEXT,
+};
+
+static void
+create_layout (GtkSourceGutterRendererText *renderer,
+               GtkWidget                   *widget)
+{
+	PangoLayout *layout;
+	PangoAttribute *attr;
+	GdkColor color;
+	GtkStyle *style;
+	PangoAttrList *attr_list;
+
+	layout = gtk_widget_create_pango_layout (widget, NULL);
+
+	style = gtk_widget_get_style (widget);
+	color = style->fg[GTK_STATE_NORMAL];
+
+	attr = pango_attr_foreground_new (color.red, color.green, color.blue);
+
+	attr->start_index = 0;
+	attr->end_index = G_MAXINT;
+
+	attr_list = pango_attr_list_new ();
+	pango_attr_list_insert (attr_list, attr);
+
+	renderer->priv->fg_attr = attr;
+	renderer->priv->cached_layout = layout;
+	renderer->priv->cached_attr_list = attr_list;
+}
+
+static void
+gutter_renderer_text_begin (GtkSourceGutterRenderer      *renderer,
+                            cairo_t                      *cr,
+                            const GdkRectangle           *background_area,
+                            const GdkRectangle           *cell_area,
+                            GtkTextIter                  *start,
+                            GtkTextIter                  *end)
+{
+	GtkSourceGutterRendererText *text;
+
+	text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+
+	create_layout (text, GTK_WIDGET (gtk_source_gutter_renderer_get_view (renderer)));
+}
+
+static void
+center_on (GtkSourceGutterRenderer *renderer,
+           const GdkRectangle      *cell_area,
+           GtkTextIter             *iter,
+           gint                     width,
+           gint                     height,
+           gfloat                   xalign,
+           gfloat                   yalign,
+           gint                    *x,
+           gint                    *y)
+{
+	GdkRectangle location;
+	GtkTextView *view;
+
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	gtk_text_view_get_iter_location (view, iter, &location);
+
+	*x = cell_area->x + (cell_area->width - width) * xalign;
+	*y = cell_area->y + (location.height - height) * yalign;
+}
+
+static void
+gutter_renderer_text_draw (GtkSourceGutterRenderer      *renderer,
+                           cairo_t                      *cr,
+                           const GdkRectangle           *background_area,
+                           const GdkRectangle           *cell_area,
+                           GtkTextIter                  *start,
+                           GtkTextIter                  *end,
+                           GtkSourceGutterRendererState  state)
+{
+	GtkSourceGutterRendererText *text;
+	gint width;
+	gint height;
+	PangoAttrList *attr_list;
+	gfloat xalign;
+	gfloat yalign;
+	GtkSourceGutterRendererAlignmentMode mode;
+	GtkTextView *view;
+	gint x = 0;
+	gint y = 0;
+
+	/* Chain up to draw background */
+	GTK_SOURCE_GUTTER_RENDERER_CLASS (
+		gtk_source_gutter_renderer_text_parent_class)->draw (renderer,
+		                                                     cr,
+		                                                     background_area,
+		                                                     cell_area,
+		                                                     start,
+		                                                     end,
+		                                                     state);
+
+	text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	if (text->priv->is_markup)
+	{
+		pango_layout_set_markup (text->priv->cached_layout,
+		                         text->priv->text,
+		                         -1);
+	}
+	else
+	{
+		pango_layout_set_text (text->priv->cached_layout,
+		                       text->priv->text,
+		                       -1);
+	}
+
+	attr_list = pango_layout_get_attributes (text->priv->cached_layout);
+
+	if (!attr_list)
+	{
+		pango_layout_set_attributes (text->priv->cached_layout,
+		                             pango_attr_list_copy (text->priv->cached_attr_list));
+	}
+	else
+	{
+		pango_attr_list_insert (attr_list,
+		                        pango_attribute_copy (text->priv->fg_attr));
+	}
+
+	pango_layout_get_size (text->priv->cached_layout, &width, &height);
+
+	width /= PANGO_SCALE;
+	height /= PANGO_SCALE;
+
+	gtk_source_gutter_renderer_get_alignment (renderer,
+	                                          &xalign,
+	                                          &yalign);
+
+	mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
+
+	switch (mode)
+	{
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL:
+			x = cell_area->x + (cell_area->width - width) * xalign;
+			y = cell_area->y + (cell_area->height - height) * yalign;
+		break;
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST:
+			center_on (renderer,
+			           cell_area,
+			           start,
+			           width,
+			           height,
+			           xalign,
+			           yalign,
+			           &x,
+			           &y);
+		break;
+		case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
+			center_on (renderer,
+			           cell_area,
+			           end,
+			           width,
+			           height,
+			           xalign,
+			           yalign,
+			           &x,
+			           &y);
+		break;
+	}
+
+	gtk_paint_layout (gtk_widget_get_style (GTK_WIDGET (view)),
+	                  cr,
+	                  gtk_widget_get_state (GTK_WIDGET (view)),
+	                  TRUE,
+	                  GTK_WIDGET (view),
+	                  "gtksourcegutterrenderertext",
+	                  x,
+	                  y,
+	                  text->priv->cached_layout);
+}
+
+static void
+gutter_renderer_text_end (GtkSourceGutterRenderer *renderer)
+{
+	GtkSourceGutterRendererText *text;
+
+	text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+
+	g_object_unref (text->priv->cached_layout);
+	text->priv->cached_layout = NULL;
+
+	pango_attr_list_unref (text->priv->cached_attr_list);
+	text->priv->cached_attr_list = NULL;
+
+	text->priv->fg_attr = NULL;
+}
+
+static void
+measure_text (GtkSourceGutterRendererText *renderer,
+              const gchar                 *markup,
+              const gchar                 *text,
+              gint                        *width,
+              gint                        *height)
+{
+	PangoLayout *layout;
+	gint w;
+	gint h;
+	GtkSourceGutterRenderer *r;
+	GtkTextView *view;
+
+	r = GTK_SOURCE_GUTTER_RENDERER (renderer);
+	view = gtk_source_gutter_renderer_get_view (r);
+
+	layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
+
+	if (markup)
+	{
+		pango_layout_set_markup (layout,
+		                         markup,
+		                         -1);
+	}
+	else
+	{
+		pango_layout_set_text (layout,
+		                       text,
+		                       -1);
+	}
+
+	pango_layout_get_size (layout, &w, &h);
+
+	if (width)
+	{
+		*width = w / PANGO_SCALE;
+	}
+
+	if (height)
+	{
+		*height = h / PANGO_SCALE;
+	}
+
+	g_object_unref (layout);
+}
+
+void
+gtk_source_gutter_renderer_text_measure (GtkSourceGutterRendererText *renderer,
+                                         const gchar                 *text,
+                                         gint                        *width,
+                                         gint                        *height)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+	g_return_if_fail (text != NULL);
+
+	measure_text (renderer, NULL, text, width, height);
+}
+
+void
+gtk_source_gutter_renderer_text_measure_markup (GtkSourceGutterRendererText *renderer,
+                                                const gchar                 *markup,
+                                                gint                        *width,
+                                                gint                        *height)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+	g_return_if_fail (markup != NULL);
+
+	measure_text (renderer, markup, NULL, width, height);
+}
+
+static void
+gtk_source_gutter_renderer_text_finalize (GObject *object)
+{
+	GtkSourceGutterRendererText *renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+	g_free (renderer->priv->text);
+
+	G_OBJECT_CLASS (gtk_source_gutter_renderer_text_parent_class)->finalize (object);
+}
+
+static void
+set_text (GtkSourceGutterRendererText *renderer,
+          const gchar                 *text,
+          gint                         length,
+          gboolean                     is_markup)
+{
+	g_free (renderer->priv->text);
+
+	renderer->priv->text = length >= 0 ? g_strndup (text, length) : g_strdup (text);
+	renderer->priv->is_markup = is_markup;
+}
+
+static void
+gtk_source_gutter_renderer_text_set_property (GObject      *object,
+                                              guint         prop_id,
+                                              const GValue *value,
+                                              GParamSpec   *pspec)
+{
+	GtkSourceGutterRendererText *renderer;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+	switch (prop_id)
+	{
+		case PROP_MARKUP:
+			set_text (renderer, g_value_get_string (value), -1, TRUE);
+			break;
+		case PROP_TEXT:
+			set_text (renderer, g_value_get_string (value), -1, FALSE);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_renderer_text_get_property (GObject    *object,
+                                              guint       prop_id,
+                                              GValue     *value,
+                                              GParamSpec *pspec)
+{
+	GtkSourceGutterRendererText *renderer;
+
+	renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+	switch (prop_id)
+	{
+		case PROP_MARKUP:
+			g_value_set_string (value, renderer->priv->is_markup ? renderer->priv->text : NULL);
+			break;
+		case PROP_TEXT:
+			g_value_set_string (value, !renderer->priv->is_markup ? renderer->priv->text : NULL);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_gutter_renderer_text_class_init (GtkSourceGutterRendererTextClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+	object_class->finalize = gtk_source_gutter_renderer_text_finalize;
+
+	object_class->get_property = gtk_source_gutter_renderer_text_get_property;
+	object_class->set_property = gtk_source_gutter_renderer_text_set_property;
+
+	renderer_class->begin = gutter_renderer_text_begin;
+	renderer_class->draw = gutter_renderer_text_draw;
+	renderer_class->end = gutter_renderer_text_end;
+
+	g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererTextPrivate));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_MARKUP,
+	                                 g_param_spec_string ("markup",
+	                                                      _("Markup"),
+	                                                      _("The markup"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_TEXT,
+	                                 g_param_spec_string ("text",
+	                                                      _("Text"),
+	                                                      _("The text"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+gtk_source_gutter_renderer_text_init (GtkSourceGutterRendererText *self)
+{
+	self->priv = GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_PRIVATE (self);
+
+	self->priv->is_markup = TRUE;
+}
+
+/**
+ * gtk_source_gutter_renderer_text_new:
+ *
+ * Create a new #GtkSourceGutterRendererText.
+ *
+ * Returns: (transfer full): A #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_text_new ()
+{
+	return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, NULL);
+}
+
+void
+gtk_source_gutter_renderer_text_set_markup (GtkSourceGutterRendererText *renderer,
+                                            const gchar                 *markup,
+                                            gint                         length)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+
+	set_text (renderer, markup, length, TRUE);
+}
+
+void
+gtk_source_gutter_renderer_text_set_text (GtkSourceGutterRendererText *renderer,
+                                          const gchar                 *text,
+                                          gint                         length)
+{
+	g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+
+	set_text (renderer, text, length, FALSE);
+}
diff --git a/gtksourceview/gtksourcegutterrenderertext.h b/gtksourceview/gtksourcegutterrenderertext.h
new file mode 100644
index 0000000..0bb5791
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderertext.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderertext.h
+ * This file is part of GtkSourceView 
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__
+
+#include <gtksourceview/gtksourcegutterrenderer.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT		(gtk_source_gutter_renderer_text_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererText))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_CONST(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererText const))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_TEXT(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_TEXT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextClass))
+
+typedef struct _GtkSourceGutterRendererText		GtkSourceGutterRendererText;
+typedef struct _GtkSourceGutterRendererTextClass	GtkSourceGutterRendererTextClass;
+typedef struct _GtkSourceGutterRendererTextPrivate	GtkSourceGutterRendererTextPrivate;
+
+struct _GtkSourceGutterRendererText
+{
+	/*< private >*/
+	GtkSourceGutterRenderer parent;
+
+	GtkSourceGutterRendererTextPrivate *priv;
+
+	/*< public >*/
+};
+
+struct _GtkSourceGutterRendererTextClass
+{
+	/*< private >*/
+	GtkSourceGutterRendererClass parent_class;
+
+	/*< public >*/
+};
+
+GType gtk_source_gutter_renderer_text_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_text_new (void);
+
+void gtk_source_gutter_renderer_text_set_markup (GtkSourceGutterRendererText *renderer,
+                                                 const gchar                 *markup,
+                                                 gint                         length);
+
+void gtk_source_gutter_renderer_text_set_text (GtkSourceGutterRendererText *renderer,
+                                               const gchar                 *text,
+                                               gint                         length);
+
+void gtk_source_gutter_renderer_text_measure (GtkSourceGutterRendererText *renderer,
+                                              const gchar                 *text,
+                                              gint                        *width,
+                                              gint                        *height);
+
+void gtk_source_gutter_renderer_text_measure_markup (GtkSourceGutterRendererText *renderer,
+                                                     const gchar                 *markup,
+                                                     gint                        *width,
+                                                     gint                        *height);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__ */
diff --git a/gtksourceview/gtksourcemarkcategory.c b/gtksourceview/gtksourcemarkcategory.c
new file mode 100644
index 0000000..1caaa77
--- /dev/null
+++ b/gtksourceview/gtksourcemarkcategory.c
@@ -0,0 +1,571 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcemarkcategory.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "gtksourcemarkcategory.h"
+#include "gtksourceview-i18n.h"
+#include "gtksourcepixbufhelper.h"
+#include "gtksourceview-marshal.h"
+
+#define GTK_SOURCE_MARK_CATEGORY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryPrivate))
+
+struct _GtkSourceMarkCategoryPrivate
+{
+	gchar *id;
+	GdkColor background;
+	gint priority;
+
+	GtkSourcePixbufHelper *helper;
+
+	guint background_set : 1;
+};
+
+G_DEFINE_TYPE (GtkSourceMarkCategory, gtk_source_mark_category, G_TYPE_OBJECT)
+
+enum
+{
+	PROP_0,
+	PROP_ID,
+	PROP_BACKGROUND,
+	PROP_PRIORITY,
+	PROP_STOCK_ID,
+	PROP_STOCK_DETAIL,
+	PROP_PIXBUF,
+	PROP_ICON_NAME,
+	PROP_GICON
+};
+
+enum
+{
+	QUERY_TOOLTIP_TEXT,
+	QUERY_TOOLTIP_MARKUP,
+	NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS] = {0,};
+
+static void
+gtk_source_mark_category_finalize (GObject *object)
+{
+	GtkSourceMarkCategory *category = GTK_SOURCE_MARK_CATEGORY (object);
+
+	gtk_source_pixbuf_helper_free (category->priv->helper);
+
+	G_OBJECT_CLASS (gtk_source_mark_category_parent_class)->finalize (object);
+}
+
+static void
+set_background (GtkSourceMarkCategory *category,
+                const GdkColor        *color)
+{
+	if (color)
+	{
+		category->priv->background = *color;
+	}
+
+	category->priv->background_set = color != NULL;
+
+	g_object_notify (G_OBJECT (category), "background");
+}
+
+static void
+set_priority (GtkSourceMarkCategory *category,
+              gint                   priority)
+{
+	if (category->priv->priority == priority)
+	{
+		return;
+	}
+
+	category->priv->priority = priority;
+	g_object_notify (G_OBJECT (category), "priority");
+}
+
+static void
+set_stock_id (GtkSourceMarkCategory *category,
+              const gchar           *stock_id)
+{
+	if (g_strcmp0 (gtk_source_pixbuf_helper_get_stock_id (category->priv->helper),
+	                                                      stock_id) == 0)
+	{
+		return;
+	}
+
+	gtk_source_pixbuf_helper_set_stock_id (category->priv->helper,
+	                                       stock_id);
+
+	g_object_notify (G_OBJECT (category), "stock-id");
+}
+
+static void
+set_stock_detail (GtkSourceMarkCategory *category,
+                  const gchar           *stock_detail)
+{
+	if (g_strcmp0 (gtk_source_pixbuf_helper_get_stock_detail (category->priv->helper),
+	                                                          stock_detail) == 0)
+	{
+		return;
+	}
+
+	gtk_source_pixbuf_helper_set_stock_detail (category->priv->helper,
+	                                           stock_detail);
+
+	g_object_notify (G_OBJECT (category), "stock-detail");
+}
+
+static void
+set_icon_name (GtkSourceMarkCategory *category,
+               const gchar           *icon_name)
+{
+	if (g_strcmp0 (gtk_source_pixbuf_helper_get_icon_name (category->priv->helper),
+	                                                       icon_name) == 0)
+	{
+		return;
+	}
+
+	gtk_source_pixbuf_helper_set_icon_name (category->priv->helper,
+	                                        icon_name);
+
+	g_object_notify (G_OBJECT (category), "icon-name");
+}
+
+static void
+set_pixbuf (GtkSourceMarkCategory *category,
+            const GdkPixbuf       *pixbuf)
+{
+	if (gtk_source_pixbuf_helper_get_pixbuf (category->priv->helper) == pixbuf)
+	{
+		return;
+	}
+
+	gtk_source_pixbuf_helper_set_pixbuf (category->priv->helper,
+	                                     pixbuf);
+
+	g_object_notify (G_OBJECT (category), "pixbuf");
+}
+
+static void
+set_gicon (GtkSourceMarkCategory *category,
+           GIcon                 *gicon)
+{
+	if (gtk_source_pixbuf_helper_get_gicon (category->priv->helper) == gicon)
+	{
+		return;
+	}
+
+	gtk_source_pixbuf_helper_set_gicon (category->priv->helper,
+	                                    gicon);
+
+	g_object_notify (G_OBJECT (category), "gicon");
+}
+
+static void
+gtk_source_mark_category_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+	GtkSourceMarkCategory *self = GTK_SOURCE_MARK_CATEGORY (object);
+
+	switch (prop_id)
+	{
+		case PROP_ID:
+			self->priv->id = g_value_dup_string (value);
+			break;
+		case PROP_BACKGROUND:
+			set_background (self, g_value_get_boxed (value));
+			break;
+		case PROP_PRIORITY:
+			set_priority (self, g_value_get_int (value));
+			break;
+		case PROP_STOCK_ID:
+			set_stock_id (self, g_value_get_string (value));
+			break;
+		case PROP_STOCK_DETAIL:
+			set_stock_detail (self, g_value_get_string (value));
+			break;
+		case PROP_PIXBUF:
+			set_pixbuf (self, g_value_get_object (value));
+			break;
+		case PROP_ICON_NAME:
+			set_icon_name (self, g_value_get_string (value));
+			break;
+		case PROP_GICON:
+			set_gicon (self, g_value_get_object (value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_mark_category_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+	GtkSourceMarkCategory *self = GTK_SOURCE_MARK_CATEGORY (object);
+
+	switch (prop_id)
+	{
+		case PROP_ID:
+			g_value_set_string (value, self->priv->id);
+			break;
+		case PROP_BACKGROUND:
+			if (self->priv->background_set)
+			{
+				g_value_set_boxed (value, &self->priv->background);
+			}
+			else
+			{
+				g_value_set_boxed (value, NULL);
+			}
+			break;
+		case PROP_PRIORITY:
+			g_value_set_int (value, self->priv->priority);
+			break;
+		case PROP_STOCK_ID:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_stock_id (self->priv->helper));
+			break;
+		case PROP_PIXBUF:
+			g_value_set_object (value,
+			                    gtk_source_pixbuf_helper_get_pixbuf (self->priv->helper));
+			break;
+		case PROP_ICON_NAME:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_icon_name (self->priv->helper));
+			break;
+		case PROP_GICON:
+			g_value_set_object (value,
+			                    gtk_source_pixbuf_helper_get_gicon (self->priv->helper));
+			break;
+		case PROP_STOCK_DETAIL:
+			g_value_set_string (value,
+			                    gtk_source_pixbuf_helper_get_stock_detail (self->priv->helper));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_mark_category_class_init (GtkSourceMarkCategoryClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gtk_source_mark_category_finalize;
+
+	object_class->get_property = gtk_source_mark_category_get_property;
+	object_class->set_property = gtk_source_mark_category_set_property;
+
+	g_type_class_add_private (object_class, sizeof(GtkSourceMarkCategoryPrivate));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_ID,
+	                                 g_param_spec_string ("id",
+	                                                      _("Id"),
+	                                                      _("The id"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_BACKGROUND,
+	                                 g_param_spec_boxed ("background",
+	                                                     _("Background"),
+	                                                     _("The background"),
+	                                                     GDK_TYPE_COLOR,
+	                                                     G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_PRIORITY,
+	                                 g_param_spec_int ("priority",
+	                                                   _("Priority"),
+	                                                   _("The priority"),
+	                                                   0,
+	                                                   G_MAXINT,
+	                                                   0,
+	                                                   G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_STOCK_ID,
+	                                 g_param_spec_string ("stock-id",
+	                                                      _("Stock Id"),
+	                                                      _("The stock id"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_PIXBUF,
+	                                 g_param_spec_object ("pixbuf",
+	                                                      _("Pixbuf"),
+	                                                      _("The pixbuf"),
+	                                                      GDK_TYPE_PIXBUF,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_ICON_NAME,
+	                                 g_param_spec_string ("icon-name",
+	                                                      _("Icon Name"),
+	                                                      _("The icon name"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_GICON,
+	                                 g_param_spec_object ("gicon",
+	                                                      _("GIcon"),
+	                                                      _("The GIcon"),
+	                                                      G_TYPE_ICON,
+	                                                      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_STOCK_DETAIL,
+	                                 g_param_spec_string ("stock-detail",
+	                                                      _("Stock Detail"),
+	                                                      _("The stock detail"),
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE));
+
+	signals[QUERY_TOOLTIP_TEXT] =
+		g_signal_new ("query-tooltip-text",
+		              G_TYPE_FROM_CLASS (klass),
+		              G_SIGNAL_RUN_LAST,
+		              0,
+		              NULL,
+		              NULL,
+		              _gtksourceview_marshal_STRING__OBJECT,
+		              G_TYPE_STRING,
+		              1,
+		              GTK_TYPE_SOURCE_MARK);
+
+	signals[QUERY_TOOLTIP_MARKUP] =
+		g_signal_new ("query-tooltip-markup",
+		              G_TYPE_FROM_CLASS (klass),
+		              G_SIGNAL_RUN_LAST,
+		              0,
+		              NULL,
+		              NULL,
+		              _gtksourceview_marshal_STRING__OBJECT,
+		              G_TYPE_STRING,
+		              1,
+		              GTK_TYPE_SOURCE_MARK);
+}
+
+static void
+gtk_source_mark_category_init (GtkSourceMarkCategory *self)
+{
+	self->priv = GTK_SOURCE_MARK_CATEGORY_GET_PRIVATE (self);
+
+	self->priv->helper = gtk_source_pixbuf_helper_new ();
+}
+
+GtkSourceMarkCategory *
+gtk_source_mark_category_new (const gchar *id)
+{
+	return g_object_new (GTK_TYPE_SOURCE_MARK_CATEGORY,
+	                     "id", id,
+	                     NULL);
+}
+
+const gchar *
+gtk_source_mark_category_get_id (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return category->priv->id;
+}
+
+void
+gtk_source_mark_category_set_background (GtkSourceMarkCategory *category,
+                                         const GdkColor        *background)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_background (category, background);
+}
+
+gboolean
+gtk_source_mark_category_get_background (GtkSourceMarkCategory *category,
+                                         GdkColor              *background)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), FALSE);
+
+	*background = category->priv->background;
+	return category->priv->background_set;
+}
+
+void
+gtk_source_mark_category_set_priority (GtkSourceMarkCategory *category,
+                                       gint                   priority)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_priority (category, priority);
+}
+
+gint
+gtk_source_mark_category_get_priority (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), 0);
+
+	return category->priv->priority;
+}
+
+void
+gtk_source_mark_category_set_stock_id (GtkSourceMarkCategory *category,
+                                       const gchar           *stock_id)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_stock_id (category, stock_id);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_id (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return gtk_source_pixbuf_helper_get_stock_id (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_stock_detail (GtkSourceMarkCategory *category,
+                                           const gchar           *stock_detail)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_stock_detail (category, stock_detail);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_detail (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return gtk_source_pixbuf_helper_get_stock_detail (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_icon_name (GtkSourceMarkCategory *category,
+                                        const gchar           *icon_name)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_icon_name (category, icon_name);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_icon_name (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return gtk_source_pixbuf_helper_get_icon_name (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_gicon (GtkSourceMarkCategory *category,
+                                    GIcon                 *gicon)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_gicon (category, gicon);
+}
+
+/**
+ * gtk_source_mark_category_get_gicon:
+ * @category: a #GtkSourceMarkCategory
+ *
+ * Get the #GIcon associated with the mark category.
+ *
+ * Returns: (transfer none): A #GIcon
+ *
+ **/
+GIcon *
+gtk_source_mark_category_get_gicon (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return gtk_source_pixbuf_helper_get_gicon (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_pixbuf (GtkSourceMarkCategory *category,
+                                     const GdkPixbuf       *pixbuf)
+{
+	g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+	set_pixbuf (category, pixbuf);
+}
+
+const GdkPixbuf *
+gtk_source_mark_category_get_pixbuf (GtkSourceMarkCategory *category)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+	return gtk_source_pixbuf_helper_get_pixbuf (category->priv->helper);
+}
+
+const GdkPixbuf *
+gtk_source_mark_category_render_icon (GtkSourceMarkCategory *category,
+                                      GtkWidget             *widget,
+                                      gint                   size)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+	g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+	g_return_val_if_fail (size > 0, NULL);
+
+	return gtk_source_pixbuf_helper_render (category->priv->helper,
+	                                        widget,
+	                                        size);
+}
+
+gchar *
+gtk_source_mark_category_get_tooltip_text (GtkSourceMarkCategory *category,
+                                           GtkSourceMark         *mark)
+{
+	gchar *ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK (mark), NULL);
+
+	ret = NULL;
+	g_signal_emit (category, signals[QUERY_TOOLTIP_TEXT], 0, mark, &ret);
+
+	return ret;
+}
+
+gchar *
+gtk_source_mark_category_get_tooltip_markup (GtkSourceMarkCategory *category,
+                                             GtkSourceMark         *mark)
+{
+	gchar *ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_MARK (mark), NULL);
+
+	ret = NULL;
+	g_signal_emit (category, signals[QUERY_TOOLTIP_MARKUP], 0, mark, &ret);
+
+	return ret;
+}
+
diff --git a/gtksourceview/gtksourcemarkcategory.h b/gtksourceview/gtksourcemarkcategory.h
new file mode 100644
index 0000000..1249f9f
--- /dev/null
+++ b/gtksourceview/gtksourcemarkcategory.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcemarkcategory.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_MARK_CATEGORY_H__
+#define __GTK_SOURCE_MARK_CATEGORY_H__
+
+#include <gtk/gtk.h>
+#include <gtksourceview/gtksourcemark.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_MARK_CATEGORY			(gtk_source_mark_category_get_type ())
+#define GTK_SOURCE_MARK_CATEGORY(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategory))
+#define GTK_SOURCE_MARK_CATEGORY_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategory const))
+#define GTK_SOURCE_MARK_CATEGORY_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryClass))
+#define GTK_IS_SOURCE_MARK_CATEGORY(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY))
+#define GTK_IS_SOURCE_MARK_CATEGORY_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_MARK_CATEGORY))
+#define GTK_SOURCE_MARK_CATEGORY_GET_CLASS(obj)		(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryClass))
+
+typedef struct _GtkSourceMarkCategory		GtkSourceMarkCategory;
+typedef struct _GtkSourceMarkCategoryClass	GtkSourceMarkCategoryClass;
+typedef struct _GtkSourceMarkCategoryPrivate	GtkSourceMarkCategoryPrivate;
+
+struct _GtkSourceMarkCategory
+{
+	/*< private >*/
+	GObject parent;
+
+	GtkSourceMarkCategoryPrivate *priv;
+
+	/*< public >*/
+};
+
+struct _GtkSourceMarkCategoryClass
+{
+	/*< private >*/
+	GObjectClass parent_class;
+
+	/*< public >*/
+};
+
+GType gtk_source_mark_category_get_type (void) G_GNUC_CONST;
+
+GtkSourceMarkCategory *gtk_source_mark_category_new (const gchar *id);
+
+const gchar     *gtk_source_mark_category_get_id              (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_background      (GtkSourceMarkCategory *category,
+                                                               const GdkColor        *background);
+
+gboolean         gtk_source_mark_category_get_background      (GtkSourceMarkCategory *category,
+                                                               GdkColor              *background);
+
+void             gtk_source_mark_category_set_priority        (GtkSourceMarkCategory *category,
+                                                               gint                   priority);
+
+gint             gtk_source_mark_category_get_priority        (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_stock_id        (GtkSourceMarkCategory *category,
+                                                               const gchar           *stock_id);
+const gchar     *gtk_source_mark_category_get_stock_id        (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_stock_detail    (GtkSourceMarkCategory *category,
+                                                               const gchar           *stock_detail);
+const gchar     *gtk_source_mark_category_get_stock_detail    (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_icon_name       (GtkSourceMarkCategory *category,
+                                                               const gchar           *icon_name);
+const gchar     *gtk_source_mark_category_get_stock_icon_name (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_gicon            (GtkSourceMarkCategory *category,
+                                                                GIcon                 *gicon);
+GIcon           *gtk_source_mark_category_get_gicon            (GtkSourceMarkCategory *category);
+
+void             gtk_source_mark_category_set_pixbuf           (GtkSourceMarkCategory *category,
+                                                                const GdkPixbuf       *pixbuf);
+const GdkPixbuf *gtk_source_mark_category_get_pixbuf           (GtkSourceMarkCategory *category);
+
+const GdkPixbuf *gtk_source_mark_category_render_icon          (GtkSourceMarkCategory *category,
+                                                                GtkWidget             *widget,
+                                                                gint                   size);
+
+gchar           *gtk_source_mark_category_get_tooltip_text     (GtkSourceMarkCategory *category,
+                                                                GtkSourceMark         *mark);
+
+gchar           *gtk_source_mark_category_get_tooltip_markup   (GtkSourceMarkCategory *category,
+                                                                GtkSourceMark         *mark);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_MARK_CATEGORY_H__ */
diff --git a/gtksourceview/gtksourcepixbufhelper.c b/gtksourceview/gtksourcepixbufhelper.c
new file mode 100644
index 0000000..6c5413b
--- /dev/null
+++ b/gtksourceview/gtksourcepixbufhelper.c
@@ -0,0 +1,352 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcepixbufhelper.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "gtksourcepixbufhelper.h"
+
+typedef enum
+{
+	ICON_TYPE_PIXBUF,
+	ICON_TYPE_STOCK,
+	ICON_TYPE_GICON,
+	ICON_TYPE_NAME
+} IconType;
+
+struct _GtkSourcePixbufHelper
+{
+	GdkPixbuf *cached_pixbuf;
+	IconType type;
+
+	GdkPixbuf *pixbuf;
+	gchar *icon_name;
+	gchar *stock_id;
+	gchar *stock_detail;
+	GIcon *gicon;
+};
+
+GtkSourcePixbufHelper *
+gtk_source_pixbuf_helper_new (void)
+{
+	return g_slice_new0 (GtkSourcePixbufHelper);
+}
+
+void
+gtk_source_pixbuf_helper_free (GtkSourcePixbufHelper *helper)
+{
+	if (helper->pixbuf)
+	{
+		g_object_unref (helper->pixbuf);
+	}
+
+	if (helper->cached_pixbuf)
+	{
+		g_object_unref (helper->cached_pixbuf);
+	}
+
+	if (helper->gicon)
+	{
+		g_object_unref (helper->gicon);
+	}
+
+	g_free (helper->stock_id);
+	g_free (helper->stock_detail);
+	g_free (helper->icon_name);
+
+	g_slice_free (GtkSourcePixbufHelper, helper);
+}
+
+static void
+set_cache (GtkSourcePixbufHelper *helper,
+           GdkPixbuf             *pixbuf)
+{
+	if (helper->cached_pixbuf)
+	{
+		g_object_unref (helper->cached_pixbuf);
+		helper->cached_pixbuf = NULL;
+	}
+
+	if (pixbuf)
+	{
+		helper->cached_pixbuf = pixbuf;
+	}
+}
+
+static void
+clear_cache (GtkSourcePixbufHelper *helper)
+{
+	set_cache (helper, NULL);
+}
+
+void
+gtk_source_pixbuf_helper_set_pixbuf (GtkSourcePixbufHelper *helper,
+                                     const GdkPixbuf       *pixbuf)
+{
+	helper->type = ICON_TYPE_PIXBUF;
+
+	if (helper->pixbuf)
+	{
+		g_object_unref (helper->pixbuf);
+		helper->pixbuf = NULL;
+	}
+
+	if (pixbuf)
+	{
+		helper->pixbuf = gdk_pixbuf_copy (pixbuf);
+	}
+
+	clear_cache (helper);
+}
+
+GdkPixbuf *
+gtk_source_pixbuf_helper_get_pixbuf (GtkSourcePixbufHelper *helper)
+{
+	return helper->pixbuf;
+}
+
+void
+gtk_source_pixbuf_helper_set_stock_id (GtkSourcePixbufHelper *helper,
+                                       const gchar           *stock_id)
+{
+	helper->type = ICON_TYPE_STOCK;
+
+	if (helper->stock_id)
+	{
+		g_free (helper->stock_id);
+	}
+
+	helper->stock_id = g_strdup (stock_id);
+
+	clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_stock_id (GtkSourcePixbufHelper *helper)
+{
+	return helper->stock_id;
+}
+
+void
+gtk_source_pixbuf_helper_set_stock_detail (GtkSourcePixbufHelper *helper,
+                                           const gchar           *detail)
+{
+	helper->type = ICON_TYPE_STOCK;
+
+	if (helper->stock_detail)
+	{
+		g_free (helper->stock_detail);
+	}
+
+	helper->stock_detail = g_strdup (detail);
+
+	clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_stock_detail (GtkSourcePixbufHelper *helper)
+{
+	return helper->stock_detail;
+}
+
+void
+gtk_source_pixbuf_helper_set_icon_name (GtkSourcePixbufHelper *helper,
+                                        const gchar           *icon_name)
+{
+	helper->type = ICON_TYPE_STOCK;
+
+	if (helper->icon_name)
+	{
+		g_free (helper->icon_name);
+	}
+
+	helper->icon_name = g_strdup (icon_name);
+
+	clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_icon_name (GtkSourcePixbufHelper *helper)
+{
+	return helper->icon_name;
+}
+
+void
+gtk_source_pixbuf_helper_set_gicon (GtkSourcePixbufHelper *helper,
+                                    GIcon                 *gicon)
+{
+	helper->type = ICON_TYPE_GICON;
+
+	if (helper->gicon)
+	{
+		g_object_unref (helper->gicon);
+		helper->gicon = NULL;
+	}
+
+	if (gicon)
+	{
+		helper->gicon = g_object_ref (gicon);
+	}
+
+	clear_cache (helper);
+}
+
+GIcon *
+gtk_source_pixbuf_helper_get_gicon (GtkSourcePixbufHelper *helper)
+{
+	return helper->gicon;
+}
+
+static void
+from_pixbuf (GtkSourcePixbufHelper *helper,
+             GtkWidget             *widget,
+             gint                   size)
+{
+	if (helper->pixbuf == NULL)
+	{
+		return;
+	}
+
+	if (gdk_pixbuf_get_width (helper->pixbuf) <= size)
+	{
+		if (!helper->cached_pixbuf)
+		{
+			set_cache (helper, gdk_pixbuf_copy (helper->pixbuf));
+		}
+
+		return;
+	}
+
+	/* Make smaller */
+	set_cache (helper, gdk_pixbuf_scale_simple (helper->pixbuf,
+	                                            size,
+	                                            size,
+	                                            GDK_INTERP_BILINEAR));
+}
+
+static void
+from_stock (GtkSourcePixbufHelper *helper,
+            GtkWidget             *widget,
+            gint                   size)
+{
+	GtkIconSize icon_size;
+	gchar *name;
+
+	name = g_strdup_printf ("GtkSourcePixbufHelper%d", size);
+
+	icon_size = gtk_icon_size_from_name (name);
+
+	if (icon_size == GTK_ICON_SIZE_INVALID)
+	{
+		icon_size = gtk_icon_size_register (name, size, size);
+	}
+
+	g_free (name);
+
+	set_cache (helper, gtk_widget_render_icon (widget,
+	                                           helper->stock_id,
+	                                           icon_size,
+	                                           helper->stock_detail));
+}
+static void
+from_gicon (GtkSourcePixbufHelper *helper,
+            GtkWidget             *widget,
+            gint                   size)
+{
+	GdkScreen *screen;
+	GtkIconTheme *icon_theme;
+	GtkSettings *settings;
+	GtkIconInfo *info;
+	GtkIconLookupFlags flags;
+
+	screen = gtk_widget_get_screen (widget);
+	icon_theme = gtk_icon_theme_get_for_screen (screen);
+	settings = gtk_settings_get_for_screen (screen);
+
+	flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
+	info = gtk_icon_theme_lookup_by_gicon (icon_theme,
+	                                       helper->gicon,
+	                                       size,
+	                                       flags);
+
+	if (info)
+	{
+		set_cache (helper, gtk_icon_info_load_icon (info, NULL));
+	}
+}
+
+static void
+from_name (GtkSourcePixbufHelper *helper,
+           GtkWidget             *widget,
+           gint                   size)
+{
+	GdkScreen *screen;
+	GtkIconTheme *icon_theme;
+	GtkSettings *settings;
+	GtkIconInfo *info;
+	GtkIconLookupFlags flags;
+
+	screen = gtk_widget_get_screen (widget);
+	icon_theme = gtk_icon_theme_get_for_screen (screen);
+	settings = gtk_settings_get_for_screen (screen);
+
+	flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
+	info = gtk_icon_theme_lookup_icon (icon_theme,
+	                                   helper->icon_name,
+	                                   size,
+	                                   flags);
+
+	if (info)
+	{
+		set_cache (helper, gtk_icon_info_load_icon (info, NULL));
+	}
+}
+
+GdkPixbuf *
+gtk_source_pixbuf_helper_render (GtkSourcePixbufHelper *helper,
+                                 GtkWidget             *widget,
+                                 gint                   size)
+{
+	if (helper->cached_pixbuf &&
+	    gdk_pixbuf_get_width (helper->cached_pixbuf) == size)
+	{
+		return helper->cached_pixbuf;
+	}
+
+	switch (helper->type)
+	{
+		case ICON_TYPE_PIXBUF:
+			from_pixbuf (helper, widget, size);
+			break;
+		case ICON_TYPE_STOCK:
+			from_stock (helper, widget, size);
+			break;
+		case ICON_TYPE_GICON:
+			from_gicon (helper, widget, size);
+			break;
+		case ICON_TYPE_NAME:
+			from_name (helper, widget, size);
+			break;
+	}
+
+	return helper->cached_pixbuf;
+}
+
diff --git a/gtksourceview/gtksourcepixbufhelper.h b/gtksourceview/gtksourcepixbufhelper.h
new file mode 100644
index 0000000..c78c34b
--- /dev/null
+++ b/gtksourceview/gtksourcepixbufhelper.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcepixbufhelper.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_PIXBUF_HELPER_H__
+#define __GTK_SOURCE_PIXBUF_HELPER_H__
+
+#include <gtk/gtk.h>
+
+typedef struct _GtkSourcePixbufHelper GtkSourcePixbufHelper;
+
+GtkSourcePixbufHelper *gtk_source_pixbuf_helper_new (void);
+void gtk_source_pixbuf_helper_free (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_pixbuf (GtkSourcePixbufHelper *helper,
+                                          const GdkPixbuf       *pixbuf);
+
+GdkPixbuf *gtk_source_pixbuf_helper_get_pixbuf (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_stock_id (GtkSourcePixbufHelper *helper,
+                                            const gchar           *stock_id);
+
+const gchar *gtk_source_pixbuf_helper_get_stock_id (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_stock_detail (GtkSourcePixbufHelper *helper,
+                                                const gchar           *stock_id);
+
+const gchar *gtk_source_pixbuf_helper_get_stock_detail (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_icon_name (GtkSourcePixbufHelper *helper,
+                                             const gchar           *icon_name);
+
+const gchar *gtk_source_pixbuf_helper_get_icon_name (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_gicon (GtkSourcePixbufHelper *helper,
+                                         GIcon                 *gicon);
+
+GIcon *gtk_source_pixbuf_helper_get_gicon (GtkSourcePixbufHelper *helper);
+
+GdkPixbuf *gtk_source_pixbuf_helper_render (GtkSourcePixbufHelper *helper,
+                                            GtkWidget             *widget,
+                                            gint                   size);
+
+#endif /* __GTK_SOURCE_PIXBUF_HELPER_H__ */
+
diff --git a/gtksourceview/gtksourceview-marshal.list b/gtksourceview/gtksourceview-marshal.list
index ee06a8a..1ef9b81 100644
--- a/gtksourceview/gtksourceview-marshal.list
+++ b/gtksourceview/gtksourceview-marshal.list
@@ -16,3 +16,8 @@ BOOL:OBJECT,BOXED,OBJECT
 VOID:BOXED,POINTER
 VOID:INT
 VOID:BOXED,INT
+VOID:BOXED,BOXED,BOXED
+BOOLEAN:BOXED,BOXED,INT,INT,OBJECT
+VOID:BOXED,BOXED,FLAGS
+BOOLEAN:BOXED,BOXED,BOXED
+STRING:OBJECT
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 92c2677..79bfc7c 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -41,6 +41,8 @@
 #include "gtksourcecompletion-private.h"
 #include "gtksourcecompletionutils.h"
 #include "gtksourcegutter-private.h"
+#include "gtksourcegutterrendererlines.h"
+#include "gtksourcegutterrenderermarks.h"
 
 /**
  * SECTION:view
@@ -75,7 +77,6 @@
 #define PROFILE(x)
 #endif
 
-#define COMPOSITE_ALPHA                 225
 #define GUTTER_PIXMAP 			16
 #define DEFAULT_TAB_WIDTH 		8
 #define MAX_TAB_WIDTH			32
@@ -149,14 +150,15 @@ struct _GtkSourceViewPrivate
 	GtkSourceGutter *left_gutter;
 	GtkSourceGutter *right_gutter;
 
-	GtkCellRenderer *line_renderer;
-	GtkCellRenderer *marks_renderer;
+	GtkSourceGutterRenderer *line_renderer;
+	GtkSourceGutterRenderer *marks_renderer;
 
 	GdkColor         current_line_color;
 
 	GtkSourceCompletion	*completion;
 
 	gulong           notify_buffer_id;
+	gint             num_line_digits;
 
 	guint            current_line_color_set : 1;
 };
@@ -184,26 +186,6 @@ typedef enum
 	ICON_TYPE_NAME
 } IconType;
 
-typedef struct
-{
-	gint priority;
-
-	IconType icon_type;
-	GdkPixbuf *icon_pixbuf;
-	gchar *icon_stock;
-	gchar *icon_name;
-
-	GdkPixbuf *cached_icon;
-
-	GtkSourceViewMarkTooltipFunc tooltip_func;
-	gpointer tooltip_data;
-	GDestroyNotify tooltip_data_notify;
-
-	GdkColor background;
-	guint background_set : 1;
-	guint tooltip_markup : 1;
-} MarkCategory;
-
 /* Prototypes. */
 static GObject *gtk_source_view_constructor		(GType               type,
 							 guint               n_construct_properties,
@@ -272,17 +254,6 @@ static void     gtk_source_view_style_set               (GtkWidget         *widg
 static void	gtk_source_view_realize			(GtkWidget         *widget);
 static void	gtk_source_view_update_style_scheme	(GtkSourceView     *view);
 
-static MarkCategory *
-		gtk_source_view_get_mark_category	(GtkSourceView     *view,
-							 GtkSourceMark     *mark);
-
-static MarkCategory *
-		gtk_source_view_ensure_category		(GtkSourceView     *view,
-							 const gchar       *name);
-static MarkCategory *
-		mark_category_new			(gint               priority);
-static void	mark_category_free			(MarkCategory      *cat);
-
 /* Private functions. */
 static void
 gtk_source_view_class_init (GtkSourceViewClass *klass)
@@ -948,633 +919,18 @@ notify_buffer (GtkSourceView *view)
 		gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
 }
 
-static gint
-sort_marks_by_priority (gconstpointer m1,
-			gconstpointer m2,
-			gpointer data)
-{
-	GtkSourceMark *mark1 = GTK_SOURCE_MARK (m1);
-	GtkSourceMark *mark2 = GTK_SOURCE_MARK (m2);
-	GtkSourceView *view = GTK_SOURCE_VIEW (data);
-	GtkTextIter iter1, iter2;
-	gint line1;
-	gint line2;
-
-	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark1)),
-					  &iter1,
-					  GTK_TEXT_MARK (mark1));
-	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark2)),
-					  &iter2,
-					  GTK_TEXT_MARK (mark2));
-
-	line1 = gtk_text_iter_get_line (&iter1);
-	line2 = gtk_text_iter_get_line (&iter2);
-
-	if (line1 == line2)
-	{
-		guint priority1 = gtk_source_view_get_mark_category_priority (view,
-						gtk_source_mark_get_category (mark1));
-		guint priority2 = gtk_source_view_get_mark_category_priority (view,
-						gtk_source_mark_get_category (mark2));
-
-		return priority1 - priority2;
-	}
-	else
-	{
-		return line2 - line1;
-	}
-}
-
-static GdkPixbuf *
-get_icon_from_stock (GtkSourceView *view,
-                     const gchar   *stock_id,
-                     gint           size)
-{
-	gchar *sizename;
-	GtkIconSize iconsize;
-
-	/* Check special icon size */
-	sizename = g_strdup_printf ("GtkSourceMarkCategoryIcon%d", size);
-	iconsize = gtk_icon_size_from_name (sizename);
-
-	if (iconsize == GTK_ICON_SIZE_INVALID)
-	{
-		iconsize = gtk_icon_size_register (sizename, size, size);
-	}
-
-	g_free (sizename);
-
-	if (iconsize == GTK_ICON_SIZE_INVALID)
-	{
-		return NULL;
-	}
-
-	return gtk_widget_render_icon (GTK_WIDGET (view),
-	                               stock_id,
-	                               iconsize,
-	                               NULL);
-}
-
-static GdkPixbuf *
-get_icon_from_name (GtkSourceView *view,
-                    const gchar   *name,
-                    gint           size)
-{
-	GtkIconTheme *theme;
-
-	theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (view)));
-
-	return gtk_icon_theme_load_icon (theme,
-	                                 name,
-	                                 size,
-	                                 GTK_ICON_LOOKUP_USE_BUILTIN |
-	                                 GTK_ICON_LOOKUP_FORCE_SIZE,
-	                                 NULL);
-}
-
 static void
-remove_cached_category_icon (MarkCategory *category)
+gutter_renderer_marks_activate (GtkSourceGutterRenderer *renderer,
+                                GtkTextIter             *iter,
+                                const GdkRectangle      *area,
+                                GdkEvent                *event,
+                                GtkSourceView           *view)
 {
-	if (category->cached_icon != NULL)
-	{
-		g_object_unref (category->cached_icon);
-		category->cached_icon = NULL;
-	}
-}
-
-static GdkPixbuf *
-get_mark_category_pixbuf (GtkSourceView *view,
-                          const gchar   *category,
-                          gint           size)
-{
-	MarkCategory *cat;
-
-	cat = g_hash_table_lookup (view->priv->mark_categories, category);
-
-	if (cat == NULL)
-	{
-		return NULL;
-	}
-
-	if (cat->cached_icon &&
-	    (gdk_pixbuf_get_height (cat->cached_icon) == size ||
-	     gdk_pixbuf_get_width (cat->cached_icon) == size))
-	{
-		return cat->cached_icon;
-	}
-
-	/* Regenerate icon */
-	remove_cached_category_icon (cat);
-
-	switch (cat->icon_type)
-	{
-		case ICON_TYPE_NONE:
-			break;
-		case ICON_TYPE_PIXBUF:
-			if (cat->icon_pixbuf == NULL)
-			{
-				return NULL;
-			}
-
-			if (gdk_pixbuf_get_width (cat->icon_pixbuf) <= size &&
-			    gdk_pixbuf_get_height (cat->icon_pixbuf) <= size)
-			{
-				cat->cached_icon = g_object_ref (cat->icon_pixbuf);
-			}
-			else
-			{
-				cat->cached_icon = gdk_pixbuf_scale_simple (cat->icon_pixbuf,
-					                                    size,
-					                                    size,
-					                                    GDK_INTERP_BILINEAR);
-			}
-			break;
-		case ICON_TYPE_STOCK:
-			cat->cached_icon = get_icon_from_stock (view,
-			                                        cat->icon_stock,
-			                                        size);
-			break;
-		case ICON_TYPE_NAME:
-			cat->cached_icon = get_icon_from_name (view,
-			                                       cat->icon_name,
-			                                       size);
-			break;
-		default:
-			g_return_val_if_reached (NULL);
-	}
-
-	return cat->cached_icon;
-}
-
-static GdkPixbuf *
-composite_marks (GtkSourceView *view,
-		 GSList        *marks,
-		 gint           size)
-{
-	GdkPixbuf *composite;
-	gint mark_width, mark_height;
-
-	/* Draw the mark with higher priority */
-	marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
-
-	composite = NULL;
-	mark_width = mark_height = 0;
-
-	/* composite all the pixbufs for the marks present at the line */
-	do
-	{
-		GtkSourceMark *mark;
-		GdkPixbuf *pixbuf;
-
-		mark = marks->data;
-
-		pixbuf = get_mark_category_pixbuf (view,
-					           gtk_source_mark_get_category (mark),
-					           size);
-
-		if (pixbuf != NULL)
-		{
-			if (composite == NULL)
-			{
-				composite = gdk_pixbuf_copy (pixbuf);
-				mark_width = gdk_pixbuf_get_width (composite);
-				mark_height = gdk_pixbuf_get_height (composite);
-			}
-			else
-			{
-				gint pixbuf_w;
-				gint pixbuf_h;
-
-				pixbuf_w = gdk_pixbuf_get_width (pixbuf);
-				pixbuf_h = gdk_pixbuf_get_height (pixbuf);
-
-				gdk_pixbuf_composite (pixbuf,
-						      composite,
-						      0, 0,
-						      mark_width, mark_height,
-						      0, 0,
-						      (double) pixbuf_w / mark_width,
-						      (double) pixbuf_h / mark_height,
-						      GDK_INTERP_BILINEAR,
-						      COMPOSITE_ALPHA);
-			}
-		}
-
-		marks = g_slist_next (marks);
-	}
-	while (marks);
-
-	return composite;
-}
-
-static int
-measure_line_height (GtkSourceView *view)
-{
-	PangoLayout *layout;
-	gint height = 12;
-
-	layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "QWERTY");
-
-	if (layout)
-	{
-		pango_layout_get_pixel_size (layout, NULL, &height);
-		g_object_unref (layout);
-	}
-
-	return height - 2;
-}
-
-static void
-marks_renderer_data_func (GtkSourceGutter *gutter,
-                          GtkCellRenderer *renderer,
-                          gint             line_number,
-                          gboolean         current_line,
-                          GtkSourceView   *view)
-{
-	GSList *marks;
-	GdkPixbuf *pixbuf = NULL;
-	int size = 0;
-
-	if (view->priv->source_buffer)
-	{
-		marks = gtk_source_buffer_get_source_marks_at_line (view->priv->source_buffer,
-								    line_number,
-								    NULL);
-
-		if (marks != NULL)
-		{
-			GtkTextIter iter;
-
-			gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (view->priv->source_buffer),
-							  &iter,
-							  line_number);
-
-			if (size == 0)
-			{
-				size = measure_line_height (view);
-			}
-
-			/* draw marks for the line */
-			pixbuf = composite_marks (view, marks, size);
-			g_slist_free (marks);
-		}
-	}
-
-	g_object_set (G_OBJECT (renderer),
-	              "pixbuf", pixbuf,
-	              "xpad", 2,
-	              "ypad", 1,
-	              "yalign", 0.0,
-	              "xalign", 0.5,
-	              "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
-	              NULL);
-}
-
-static void
-line_renderer_data_func (GtkSourceGutter *gutter,
-                         GtkCellRenderer *renderer,
-                         gint             line_number,
-                         gboolean         current_line,
-                         GtkSourceView   *view)
-{
-	int weight;
-	gchar *text;
-	GtkStyle *style;
-
-	if (current_line && gtk_text_view_get_cursor_visible (GTK_TEXT_VIEW (view)))
-	{
-		weight = PANGO_WEIGHT_BOLD;
-	}
-	else
-	{
-		weight = PANGO_WEIGHT_NORMAL;
-	}
-
-	text = g_strdup_printf ("%d", line_number + 1);
-	g_object_set (G_OBJECT (renderer),
-	              "text", text,
-	              "xalign", 1.0,
-	              "yalign", 0.0,
-	              "xpad", 2,
-	              "ypad", 0,
-	              "weight", weight,
-	              "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
-	              NULL);
-
-	style = gtk_widget_get_style (GTK_WIDGET (view));
-	if (style != NULL)
-	{
-		g_object_set (G_OBJECT (renderer),
-			      "foreground-gdk", &style->fg[GTK_STATE_NORMAL],
-			      NULL);
-	}
-
-	g_object_set (G_OBJECT (renderer),
-	              "background-set", FALSE,
-	              NULL);
-
-	g_free (text);
-}
-
-static void
-line_renderer_size_func (GtkSourceGutter *gutter,
-                         GtkCellRenderer *renderer,
-                         GtkSourceView   *view)
-{
-	gchar *text;
-	gint count;
-
-	count = gtk_text_buffer_get_line_count (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-	text = g_strdup_printf ("%d", MAX(99, count));
-
-	/* measure with bold, just in case font is rendered larger */
-	g_object_set (G_OBJECT (renderer),
-	              "text", text,
-	              "xpad", 2,
-	              "ypad", 0,
-	              "weight", PANGO_WEIGHT_BOLD,
-	               NULL);
-
-	g_free (text);
-}
-
-static void
-extend_selection_to_line (GtkTextBuffer *buf, GtkTextIter *line_start)
-{
-	GtkTextIter start;
-	GtkTextIter end;
-	GtkTextIter line_end;
-
-	gtk_text_buffer_get_selection_bounds (buf, &start, &end);
-
-	line_end = *line_start;
-
-	if (!gtk_text_iter_ends_line (&line_end))
-		gtk_text_iter_forward_to_line_end (&line_end);
-
-	if (gtk_text_iter_compare (&start, line_start) < 0)
-	{
-		gtk_text_buffer_select_range (buf, &start, &line_end);
-	}
-	else if (gtk_text_iter_compare (&end, &line_end) < 0)
-	{
-		/* if the selection is in this line, extend
-		 * the selection to the whole line */
-		gtk_text_buffer_select_range (buf, &line_end, line_start);
-	}
-	else
-	{
-		gtk_text_buffer_select_range (buf, &end, line_start);
-	}
-}
-
-static void
-select_line (GtkTextBuffer *buf, GtkTextIter *line_start)
-{
-	GtkTextIter iter;
-
-	iter = *line_start;
-
-	if (!gtk_text_iter_ends_line (&iter))
-		gtk_text_iter_forward_to_line_end (&iter);
-
-	/* Select the line, put the cursor at the end of the line */
-	gtk_text_buffer_select_range (buf, &iter, line_start);
-}
-
-static void
-marks_renderer_size_func (GtkSourceGutter *gutter,
-                          GtkCellRenderer *renderer,
-                          GtkSourceView   *view)
-{
-	gint size;
-	GdkPixbuf *pixbuf;
-
-	size = measure_line_height (view);
-
-	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-	                         TRUE,
-	                         8,
-	                         size,
-	                         size);
-
-	g_object_set (G_OBJECT (renderer),
-	              "pixbuf", pixbuf,
-	              "xpad", 2,
-	              "ypad", 1,
-	              NULL);
-
-	g_object_unref (pixbuf);
-}
-
-static void
-renderer_activated (GtkSourceGutter *gutter,
-                    GtkCellRenderer *renderer,
-                    GtkTextIter     *iter,
-                    GdkEvent        *event,
-                    GtkSourceView   *view)
-{
-	if (renderer == view->priv->marks_renderer)
-	{
-		g_signal_emit (view,
-		               signals[LINE_MARK_ACTIVATED],
-		               0,
-		               iter,
-		               event);
-	}
-	else if (renderer == view->priv->line_renderer)
-	{
-		GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
-		if (event->type == GDK_BUTTON_PRESS && (event->button.button == 1))
-		{
-			if ((event->button.state & GDK_CONTROL_MASK) != 0)
-			{
-				/* Single click + Ctrl -> select the line */
-				select_line (buf, iter);
-			}
-			else if ((event->button.state & GDK_SHIFT_MASK) != 0)
-			{
-				/* Single click + Shift -> extended current
-				   selection to include the clicked line */
-				extend_selection_to_line (buf, iter);
-			}
-			else
-			{
-				gtk_text_buffer_place_cursor (buf, iter);
-			}
-		}
-		else if (event->type == GDK_2BUTTON_PRESS && (event->button.button == 1))
-		{
-			select_line (buf, iter);
-		}
-	}
-}
-
-static gboolean
-set_tooltip_widget_from_marks (GtkSourceView *view,
-			       GtkTooltip *tooltip,
-			       GSList *marks)
-{
-	GtkWidget *vbox = NULL;
-
-	while (marks != NULL)
-	{
-		const gchar *category;
-		GtkSourceMark *mark;
-		MarkCategory *cat;
-
-		mark = marks->data;
-		category = gtk_source_mark_get_category (mark);
-
-		cat = gtk_source_view_get_mark_category (view, mark);
-
-		if (cat != NULL && cat->tooltip_func != NULL)
-		{
-			gchar *text;
-
-			text = cat->tooltip_func (mark, cat->tooltip_data);
-			if (text != NULL)
-			{
-				GtkWidget *label;
-				GtkWidget *hbox;
-
-				if (vbox == NULL)
-				{
-					vbox = gtk_vbox_new (FALSE, 0);
-					gtk_widget_show (vbox);
-				}
-
-				hbox = gtk_hbox_new (FALSE, 4);
-				gtk_widget_show (hbox);
-				gtk_box_pack_start (GTK_BOX (vbox), hbox,
-				    FALSE, FALSE, 0);
-
-				GdkPixbuf *pixbuf;
-				gint size;
-
-				label = gtk_label_new (NULL);
-
-				if (cat->tooltip_markup)
-					gtk_label_set_markup (GTK_LABEL (label), text);
-				else
-					gtk_label_set_text (GTK_LABEL (label), text);
-
-				gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
-				gtk_widget_show (label);
-
-				gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &size);
-				pixbuf = get_mark_category_pixbuf (view, category, size);
-
-				if (pixbuf != NULL)
-				{
-					GtkWidget *image;
-					PangoLayoutLine *line;
-					PangoRectangle rect;
-					GtkWidget *align;
-
-					align = gtk_alignment_new (0, 0, 0, 0);
-					gtk_widget_show (align);
-
-					image = gtk_image_new_from_pixbuf (pixbuf);
-					gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
-					gtk_widget_show (image);
-
-					/* Measure up to align exact */
-					line = pango_layout_get_line (gtk_label_get_layout (GTK_LABEL (label)), 0);
-					pango_layout_line_get_pixel_extents (line, NULL, &rect);
-
-					gtk_alignment_set_padding (GTK_ALIGNMENT (align),
-						                   (rect.height > size ? rect.height - size : size - rect.height) - 1,
-						                   0, 0, 0);
-					if (rect.height > size)
-					{
-						gtk_container_add (GTK_CONTAINER (align),
-						                   image);
-
-						image = align;
-					}
-					else if (size > rect.height)
-					{
-						gtk_container_add (GTK_CONTAINER (align),
-						                   label);
-						label = align;
-					}
-					else
-					{
-						gtk_widget_destroy (align);
-					}
-
-					gtk_box_pack_start (GTK_BOX (hbox),
-					                    image,
-					                    FALSE,
-					                    FALSE,
-					                    0);
-				}
-
-				gtk_box_pack_end (GTK_BOX (hbox),
-				                  label,
-				                  TRUE,
-				                  TRUE,
-				                  0);
-
-				if (g_slist_length (marks) != 1)
-				{
-					GtkWidget *separator;
-
-					separator = gtk_hseparator_new ();
-					gtk_widget_show (separator);
-					gtk_box_pack_start (GTK_BOX (vbox), separator,
-							    FALSE, FALSE, 0);
-				}
-
-				g_free (text);
-			}
-		}
-
-		marks = g_slist_delete_link (marks, marks);
-	}
-
-	if (vbox == NULL)
-		return FALSE;
-
-	gtk_tooltip_set_custom (tooltip, vbox);
-
-	return TRUE;
-}
-
-static gboolean
-renderer_query_tooltip (GtkSourceGutter *gutter,
-                        GtkCellRenderer *renderer,
-                        GtkTextIter     *iter,
-                        GtkTooltip      *tooltip,
-                        GtkSourceView   *view)
-{
-	GSList *marks;
-	GtkSourceBuffer *buffer;
-	gint line;
-
-	if (renderer != view->priv->marks_renderer)
-	{
-		return FALSE;
-	}
-
-	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-	line = gtk_text_iter_get_line (iter);
-
-	marks = gtk_source_buffer_get_source_marks_at_line (buffer,
-							    line,
-							    NULL);
-
-	if (marks != NULL)
-	{
-		marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
-		marks = g_slist_reverse (marks);
-
-		return set_tooltip_widget_from_marks (view, tooltip, marks);
-	}
-
-	return FALSE;
+	g_signal_emit (view,
+	               signals[LINE_MARK_ACTIVATED],
+	               0,
+	               iter,
+	               event);
 }
 
 static void
@@ -1582,54 +938,30 @@ init_left_gutter (GtkSourceView *view)
 {
 	GtkSourceGutter *gutter;
 
-	view->priv->line_renderer = gtk_cell_renderer_text_new ();
-	view->priv->marks_renderer = gtk_cell_renderer_pixbuf_new ();
-
 	gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
 
-	gtk_source_gutter_insert (gutter,
-	                          view->priv->line_renderer,
-	                          GTK_SOURCE_VIEW_GUTTER_POSITION_LINES);
-
-	gtk_source_gutter_insert (gutter,
-	                          view->priv->marks_renderer,
-	                          GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS);
-
-	gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, 0, 0);
-	gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, 0, 0);
-
-	gtk_source_gutter_set_cell_data_func (gutter,
-	                                      view->priv->line_renderer,
-	                                      (GtkSourceGutterDataFunc)line_renderer_data_func,
-	                                      view,
-	                                      NULL);
-
-	gtk_source_gutter_set_cell_size_func (gutter,
-	                                      view->priv->line_renderer,
-	                                      (GtkSourceGutterSizeFunc)line_renderer_size_func,
-	                                      view,
-	                                      NULL);
-
-	gtk_source_gutter_set_cell_data_func (gutter,
-	                                      view->priv->marks_renderer,
-	                                      (GtkSourceGutterDataFunc)marks_renderer_data_func,
-	                                      view,
-	                                      NULL);
-
-	gtk_source_gutter_set_cell_size_func (gutter,
-	                                      view->priv->marks_renderer,
-	                                      (GtkSourceGutterSizeFunc)marks_renderer_size_func,
-	                                      view,
-	                                      NULL);
-
-	g_signal_connect (gutter,
-	                  "cell-activated",
-	                  G_CALLBACK (renderer_activated),
-	                  view);
-
-	g_signal_connect (gutter,
-	                  "query-tooltip",
-	                  G_CALLBACK (renderer_query_tooltip),
+	view->priv->line_renderer =
+		gtk_source_gutter_insert (gutter,
+		                          GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES,
+		                          GTK_SOURCE_VIEW_GUTTER_POSITION_LINES,
+		                          "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+		                          "yalign", 0.5,
+		                          "xalign", 1.0,
+		                          "xpad", 3,
+		                          NULL);
+
+	view->priv->marks_renderer =
+		gtk_source_gutter_insert (gutter,
+		                          GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS,
+		                          GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS,
+		                          "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+		                          "yalign", 0.5,
+		                          "xalign", 0.5,
+		                          NULL);
+
+	g_signal_connect (view->priv->marks_renderer,
+	                  "activate",
+	                  G_CALLBACK (gutter_renderer_marks_activate),
 	                  view);
 }
 
@@ -1656,9 +988,10 @@ gtk_source_view_init (GtkSourceView *view)
 	view->priv->right_margin_overlay_color = NULL;
 	view->priv->spaces_color = NULL;
 
-	view->priv->mark_categories = g_hash_table_new_full (g_str_hash, g_str_equal,
-							     (GDestroyNotify) g_free,
-							     (GDestroyNotify) mark_category_free);
+	view->priv->mark_categories = g_hash_table_new_full (g_str_hash,
+	                                                     g_str_equal,
+	                                                     (GDestroyNotify) g_free,
+	                                                     (GDestroyNotify) g_object_unref);
 
 	init_left_gutter (view);
 
@@ -1667,6 +1000,8 @@ gtk_source_view_init (GtkSourceView *view)
 
 	gtk_target_list_add_table (tl, drop_types, G_N_ELEMENTS (drop_types));
 
+	gtk_widget_set_has_tooltip (GTK_WIDGET (view), TRUE);
+
 	g_signal_connect (view,
 			  "drag_data_received",
 			  G_CALLBACK (view_dnd_drop),
@@ -1716,6 +1051,18 @@ gtk_source_view_dispose (GObject *object)
 		view->priv->completion = NULL;
 	}
 
+	if (view->priv->left_gutter)
+	{
+		g_object_unref (view->priv->left_gutter);
+		view->priv->left_gutter = NULL;
+	}
+
+	if (view->priv->right_gutter)
+	{
+		g_object_unref (view->priv->right_gutter);
+		view->priv->right_gutter = NULL;
+	}
+
 	G_OBJECT_CLASS (gtk_source_view_parent_class)->dispose (object);
 }
 
@@ -1730,25 +1077,29 @@ gtk_source_view_finalize (GObject *object)
 	view = GTK_SOURCE_VIEW (object);
 
 	if (view->priv->style_scheme)
+	{
 		g_object_unref (view->priv->style_scheme);
+	}
 
 	if (view->priv->right_margin_line_color != NULL)
+	{
 		gdk_color_free (view->priv->right_margin_line_color);
+	}
 
 	if (view->priv->right_margin_overlay_color != NULL)
+	{
 		gdk_color_free (view->priv->right_margin_overlay_color);
+	}
 
 	if (view->priv->spaces_color != NULL)
+	{
 		gdk_color_free (view->priv->spaces_color);
+	}
 
 	if (view->priv->mark_categories)
+	{
 		g_hash_table_destroy (view->priv->mark_categories);
-
-	if (view->priv->left_gutter)
-		g_object_unref (view->priv->left_gutter);
-
-	if (view->priv->right_gutter)
-		g_object_unref (view->priv->right_gutter);
+	}
 
 	G_OBJECT_CLASS (gtk_source_view_parent_class)->finalize (object);
 }
@@ -1855,6 +1206,7 @@ set_source_buffer (GtkSourceView *view,
 		g_signal_handlers_disconnect_by_func (view->priv->source_buffer,
 						      buffer_style_scheme_changed_cb,
 						      view);
+
 		g_object_unref (view->priv->source_buffer);
 	}
 
@@ -1884,7 +1236,9 @@ set_source_buffer (GtkSourceView *view,
 	 * gtk_source_view_update_style_scheme(), that will check whether it's
 	 * a GtkSourceBuffer or not */
 	if (buffer)
+	{
 		gtk_source_view_update_style_scheme (view);
+	}
 }
 
 static void
@@ -2462,7 +1816,7 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
 					cairo_t       *cr)
 {
 	GtkTextView *text_view;
-        GdkRectangle clip;
+	GdkRectangle clip;
 	GArray *numbers;
 	GArray *pixels;
 	GArray *heights;
@@ -2471,8 +1825,10 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
 	gint i;
 
 	if (view->priv->source_buffer == NULL ||
-            !gdk_cairo_get_clip_rectangle (cr, &clip))
+	    !gdk_cairo_get_clip_rectangle (cr, &clip))
+	{
 		return;
+	}
 
 	text_view = GTK_TEXT_VIEW (view);
 
@@ -2481,18 +1837,18 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
 
 	/* get the extents of the line printing */
 	gtk_text_view_window_to_buffer_coords (text_view,
-					       GTK_TEXT_WINDOW_TEXT,
-					       0,
-					       y1,
-					       NULL,
-					       &y1);
+	                                       GTK_TEXT_WINDOW_TEXT,
+	                                       0,
+	                                       y1,
+	                                       NULL,
+	                                       &y1);
 
 	gtk_text_view_window_to_buffer_coords (text_view,
-					       GTK_TEXT_WINDOW_TEXT,
-					       0,
-					       y2,
-					       NULL,
-					       &y2);
+	                                       GTK_TEXT_WINDOW_TEXT,
+	                                       0,
+	                                       y2,
+	                                       NULL,
+	                                       &y2);
 
 	numbers = g_array_new (FALSE, FALSE, sizeof (gint));
 	pixels = g_array_new (FALSE, FALSE, sizeof (gint));
@@ -2500,12 +1856,12 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
 
 	/* get the line numbers and y coordinates. */
 	gtk_source_view_get_lines (text_view,
-				   y1,
-				   y2,
-				   pixels,
-				   heights,
-				   numbers,
-				   &count);
+	                           y1,
+	                           y2,
+	                           pixels,
+	                           heights,
+	                           numbers,
+	                           &count);
 
 	if (count == 0)
 	{
@@ -2525,46 +1881,54 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
 
 	DEBUG ({
 		g_message ("Painting marks background for line numbers %d - %d",
-			   g_array_index (numbers, gint, 0),
-			   g_array_index (numbers, gint, count - 1));
+		           g_array_index (numbers, gint, 0),
+		           g_array_index (numbers, gint, count - 1));
 	});
 
 	for (i = 0; i < count; ++i)
 	{
 		gint line_to_paint;
 		GSList *marks;
-		GdkColor *background;
+		GdkColor background;
 		int priority;
 
 		line_to_paint = g_array_index (numbers, gint, i);
 
 		marks = gtk_source_buffer_get_source_marks_at_line (view->priv->source_buffer,
-								    line_to_paint,
-								    NULL);
+		                                                    line_to_paint,
+		                                                    NULL);
 
-		background = NULL;
 		priority = -1;
 
 		while (marks != NULL)
 		{
-			MarkCategory *cat = NULL;
+			GtkSourceMarkCategory *cat;
+			gint prio;
+			GdkColor bg;
 
-			cat = gtk_source_view_get_mark_category (view, marks->data);
+			cat = gtk_source_view_get_mark_category (view,
+			                                         gtk_source_mark_get_category (marks->data));
 
-			if (cat != NULL && cat->background_set && cat->priority > priority)
+			prio = gtk_source_mark_category_get_priority (cat);
+
+			if (prio > priority &&
+			    gtk_source_mark_category_get_background (cat, &bg))
 			{
-				background = &cat->background;
-				priority = cat->priority;
+				priority = prio;
+				background = bg;
 			}
 
 			marks = g_slist_delete_link (marks, marks);
 		}
 
-		if (background != NULL)
-			gtk_source_view_paint_line_background (text_view, cr,
-							       g_array_index (pixels, gint, i),
-							       g_array_index (heights, gint, i),
-							       background);
+		if (priority != -1)
+		{
+			gtk_source_view_paint_line_background (text_view,
+			                                       cr,
+			                                       g_array_index (pixels, gint, i),
+			                                       g_array_index (heights, gint, i),
+			                                       &background);
+		}
 	}
 
 	g_array_free (heights, TRUE);
@@ -3016,8 +2380,8 @@ gtk_source_view_draw (GtkWidget *widget,
 
 	window = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT);
 
-        cairo_save (cr);
-        gtk_cairo_transform_to_window (cr, widget, window);
+	cairo_save (cr);
+	gtk_cairo_transform_to_window (cr, widget, window);
 
 	event_handled = FALSE;
 
@@ -3079,19 +2443,21 @@ gtk_source_view_draw (GtkWidget *widget,
 	}
 
 	if (gtk_cairo_should_draw_window (cr, window))
+	{
 		gtk_source_view_paint_marks_background (view, cr);
+	}
 
 	/* Have GtkTextView draw the text first. */
 	if (GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw)
 	{
-            /* Need to restore to original state here so the parent draw func
-             * gets the correct context. */
+		/* Need to restore to original state here so the parent draw func
+		* gets the correct context. */
 		cairo_restore (cr);
 
 		cairo_save (cr);
 
 		event_handled =
-                    GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw (widget, cr);
+			GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw (widget, cr);
 
 		cairo_restore (cr);
 
@@ -3116,7 +2482,7 @@ gtk_source_view_draw (GtkWidget *widget,
 		g_print ("> gtk_source_view_draw end\n");
 	});
 
-        cairo_restore (cr);
+	cairo_restore (cr);
 
 	return event_handled;
 }
@@ -3231,10 +2597,8 @@ gtk_source_view_get_show_line_numbers (GtkSourceView *view)
  **/
 void
 gtk_source_view_set_show_line_numbers (GtkSourceView *view,
-				       gboolean       show)
+                                       gboolean       show)
 {
-	GtkSourceGutter *gutter;
-
 	g_return_if_fail (view != NULL);
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
 
@@ -3245,20 +2609,11 @@ gtk_source_view_set_show_line_numbers (GtkSourceView *view,
 		return;
 	}
 
-	if (show)
-	{
-		gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, -1, -1);
-	}
-	else
-	{
-		gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, 0, 0);
-	}
+	gtk_source_gutter_renderer_set_visible (view->priv->line_renderer,
+	                                        show);
 
 	view->priv->show_line_numbers = show;
 
-	gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
-	gtk_source_gutter_queue_draw (gutter);
-
 	g_object_notify (G_OBJECT (view), "show_line_numbers");
 }
 
@@ -3293,8 +2648,6 @@ void
 gtk_source_view_set_show_line_marks (GtkSourceView *view,
 				     gboolean       show)
 {
-	GtkSourceGutter *gutter;
-
 	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
 
 	show = (show != FALSE);
@@ -3305,20 +2658,11 @@ gtk_source_view_set_show_line_marks (GtkSourceView *view,
 	}
 
 
-	if (show)
-	{
-		gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, -1, -1);
-	}
-	else
-	{
-		gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, 0, 0);
-	}
+	gtk_source_gutter_renderer_set_visible (view->priv->marks_renderer,
+	                                        show);
 
 	view->priv->show_line_marks = show;
 
-	gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
-	gtk_source_gutter_queue_draw (gutter);
-
 	g_object_notify (G_OBJECT (view), "show_line_marks");
 }
 
@@ -3435,446 +2779,6 @@ gtk_source_view_get_indent_width (GtkSourceView *view)
 	return view->priv->indent_width;
 }
 
-static void
-mark_category_set_background (MarkCategory *cat, const GdkColor *background)
-{
-	if (background != NULL)
-	{
-		cat->background_set = TRUE;
-		cat->background = *background;
-	}
-	else
-	{
-		cat->background_set = FALSE;
-	}
-}
-
-static MarkCategory *
-mark_category_new (gint priority)
-{
-	MarkCategory *cat;
-
-	cat = g_slice_new0 (MarkCategory);
-	cat->priority = priority;
-
-	return cat;
-}
-
-static void
-mark_category_free (MarkCategory *cat)
-{
-	if (cat->tooltip_data_notify != NULL)
-	{
-		cat->tooltip_data_notify (cat->tooltip_data);
-	}
-
-	if (cat->icon_pixbuf)
-	{
-		g_object_unref (cat->icon_pixbuf);
-	}
-
-	if (cat->cached_icon)
-	{
-		g_object_unref (cat->cached_icon);
-	}
-
-	g_free (cat->icon_stock);
-	g_free (cat->icon_name);
-
-	g_slice_free (MarkCategory, cat);
-}
-
-static MarkCategory *
-gtk_source_view_get_mark_category (GtkSourceView *view,
-				   GtkSourceMark *mark)
-{
-	const gchar *category;
-	category = gtk_source_mark_get_category (mark);
-	if (category)
-		return g_hash_table_lookup (view->priv->mark_categories,
-					    category);
-	else
-		return NULL;
-}
-
-static MarkCategory *
-gtk_source_view_ensure_category (GtkSourceView *view,
-				 const gchar   *name)
-{
-	MarkCategory *cat;
-
-	cat = g_hash_table_lookup (view->priv->mark_categories, name);
-
-	if (cat == NULL)
-	{
-		cat = mark_category_new (0);
-		g_hash_table_insert (view->priv->mark_categories,
-				     g_strdup (name),
-				     cat);
-	}
-
-	return cat;
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_pixbuf:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL.
- *
- * Sets the icon to be used for @category to @pixbuf.
- * If @pixbuf is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_pixbuf (GtkSourceView  *view,
-                                                    const gchar    *category,
-                                                    GdkPixbuf      *pixbuf)
-{
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-	g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
-
-	cat = gtk_source_view_ensure_category (view, category);
-
-	if (cat->icon_pixbuf != NULL)
-	{
-		g_object_unref (cat->icon_pixbuf);
-		cat->icon_pixbuf = NULL;
-	}
-
-	remove_cached_category_icon (cat);
-
-	if (pixbuf != NULL)
-	{
-		cat->icon_pixbuf = g_object_ref (pixbuf);
-	}
-
-	cat->icon_type = ICON_TYPE_PIXBUF;
-
-	/* We may need to redraw the margin now */
-	gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_icon_name:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @name: (allow-none): the themed icon name, or %NULL.
- *
- * Sets the icon to be used for @category to the named theme item @name.
- * If @name is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_icon_name (GtkSourceView  *view,
-                                                       const gchar    *category,
-                                                       const gchar    *name)
-{
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-
-	cat = gtk_source_view_ensure_category (view, category);
-
-	if (cat->icon_name != NULL)
-	{
-		g_free (cat->icon_name);
-		cat->icon_name = NULL;
-	}
-
-	remove_cached_category_icon (cat);
-
-	if (name != NULL)
-	{
-		cat->icon_name = g_strdup (name);
-	}
-
-	cat->icon_type = ICON_TYPE_NAME;
-
-	/* We may need to redraw the margin now */
-	gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_stock:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @stock_id: (allow-none): the stock id, or %NULL.
- *
- * Sets the icon to be used for @category to the stock item @stock_id.
- * If @stock_id is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_stock (GtkSourceView  *view,
-                                                   const gchar    *category,
-                                                   const gchar    *stock_id)
-{
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-
-	cat = gtk_source_view_ensure_category (view, category);
-
-	if (cat->icon_stock != NULL)
-	{
-		g_free (cat->icon_stock);
-		cat->icon_stock = NULL;
-	}
-
-	remove_cached_category_icon (cat);
-
-	if (stock_id != NULL)
-	{
-		cat->icon_stock = g_strdup (stock_id);
-	}
-
-	cat->icon_type = ICON_TYPE_STOCK;
-
-	/* We may need to redraw the margin now */
-	gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-static void
-set_mark_category_tooltip_func (GtkSourceView   *view,
-				const gchar     *category,
-				GtkSourceViewMarkTooltipFunc func,
-				gpointer	 user_data,
-				GDestroyNotify   user_data_notify,
-				gboolean markup)
-{
-	GtkWidget *widget;
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-
-	widget = GTK_WIDGET (view);
-	cat = gtk_source_view_ensure_category (view, category);
-
-	if (cat->tooltip_data_notify)
-		cat->tooltip_data_notify (cat->tooltip_data);
-
-	cat->tooltip_func = func;
-	cat->tooltip_markup = markup;
-	cat->tooltip_data = user_data;
-	cat->tooltip_data_notify = user_data_notify;
-
-	if (func != NULL)
-	{
-		gtk_widget_set_has_tooltip (widget, TRUE);
-		if (gtk_widget_get_realized (widget))
-		{
-			gtk_widget_trigger_tooltip_query (widget);
-		}
-	}
-}
-
-/**
- * gtk_source_view_set_mark_category_tooltip_func:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @func: (allow-none): a #GtkSourceViewMarkTooltipFunc or %NULL.
- * @user_data: (allow-none): user data which will be passed to @func.
- * @user_data_notify: (allow-none):a function to free the memory allocated
- * for @user_data or %NULL if you do not want to supply such a function.
- *
- * Set a #GtkSourceViewMarkTooltipFunc used to set tooltip on marks from the
- * given mark @category.
- * If you also specified a function with
- * gtk_source_view_set_mark_category_tooltip_markup_func()  the markup
- * variant takes precedence.
- *
- * <informalexample><programlisting><![CDATA[
- * static gchar *
- * tooltip_func (GtkSourceMark *mark,
- *               gpointer       user_data)
- * {
- *   gchar *text;
- *
- *   text = get_tooltip_for_mark (mark, user_data);
- *
- *   return text;
- * }
- *
- * ...
- *
- * GtkSourceView *view;
- *
- * gtk_source_view_set_mark_category_tooltip_func (view, "other-mark",
- *                                                 tooltip_func,
- *                                                 NULL, NULL);
- * ]]></programlisting></informalexample>
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_tooltip_func (GtkSourceView   *view,
-						const gchar     *category,
-						GtkSourceViewMarkTooltipFunc func,
-						gpointer	 user_data,
-						GDestroyNotify   user_data_notify)
-{
-	set_mark_category_tooltip_func (view, category, func, user_data,
-					user_data_notify, FALSE);
-}
-
-/**
- * gtk_source_view_set_mark_category_tooltip_markup_func:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @markup_func: (allow-none): a #GtkSourceViewMarkTooltipFunc or %NULL.
- * @user_data: (allow-none): user data which will be passed to @func.
- * @user_data_notify: (allow-none):a function to free the memory allocated
- * for @user_data or %NULL if you do not want to supply such a function.
- *
- * See gtk_source_view_set_mark_category_tooltip_func() for more information.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_tooltip_markup_func (GtkSourceView   *view,
-						       const gchar     *category,
-						       GtkSourceViewMarkTooltipFunc markup_func,
-						       gpointer         user_data,
-						       GDestroyNotify   user_data_notify)
-{
-	set_mark_category_tooltip_func (view, category, markup_func, user_data,
-					user_data_notify, TRUE);
-}
-
-/**
- * gtk_source_view_set_mark_category_background:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @color: (allow-none): background color or %NULL to unset it.
- *
- * Sets given background @color for mark @category.
- * If @color is %NULL, the background color is unset.
- *
- * Since: 2.4
- */
-void
-gtk_source_view_set_mark_category_background (GtkSourceView  *view,
-					      const gchar    *category,
-					      const GdkColor *color)
-{
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-
-	cat = gtk_source_view_ensure_category (view, category);
-	mark_category_set_background (cat, color);
-
-	/* We may need to redraw the text background now */
-	gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_get_mark_category_background:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @dest: destination #GdkColor structure to fill in.
- *
- * Gets the background color associated with given @category.
- *
- * Return value: %TRUE if background color for @category was set
- * and @dest is set to a valid color, or %FALSE otherwise.
- *
- * Since: 2.4
- */
-gboolean
-gtk_source_view_get_mark_category_background (GtkSourceView *view,
-					      const gchar   *category,
-					      GdkColor      *dest)
-{
-	MarkCategory *cat;
-
-	g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), FALSE);
-	g_return_val_if_fail (category != NULL, FALSE);
-	g_return_val_if_fail (dest != NULL, FALSE);
-
-	cat = g_hash_table_lookup (view->priv->mark_categories, category);
-	if (cat != NULL && cat->background_set)
-	{
-		*dest = cat->background;
-		return TRUE;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
-/**
- * gtk_source_view_set_mark_category_priority:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @priority: the priority for the category
- *
- * Set the @priority for the given mark @category. When there are
- * multiple marks on the same line, marks of categories with
- * higher priorities will be drawn on top.
- *
- * Since: 2.2
- */
-void
-gtk_source_view_set_mark_category_priority (GtkSourceView *view,
-					    const gchar   *category,
-					    gint          priority)
-{
-	MarkCategory *cat;
-
-	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
-	g_return_if_fail (category != NULL);
-
-	cat = gtk_source_view_ensure_category (view, category);
-	cat->priority = priority;
-
-	/* We may need to redraw now, if the priorities affect appearance */
-	gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_get_mark_category_priority:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- *
- * Gets the priority which is associated with the given @category.
- *
- * Return value: the priority or if @category
- * exists but no priority was set, it defaults to 0.
- *
- * Since: 2.2
- */
-gint
-gtk_source_view_get_mark_category_priority (GtkSourceView *view,
-					    const gchar   *category)
-{
-	MarkCategory *cat;
-
-	g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), 0);
-	g_return_val_if_fail (category != NULL, 0);
-
-	cat = g_hash_table_lookup (view->priv->mark_categories, category);
-	if (cat != NULL)
-		return cat->priority;
-	else
-	{
-		g_warning ("Marker Category %s does not exist!", category);
-		return 0;
-	}
-}
-
 static gchar *
 compute_indentation (GtkSourceView *view,
 		     GtkTextIter   *cur)
@@ -5302,3 +4206,38 @@ gtk_source_view_get_gutter (GtkSourceView     *view,
 		return view->priv->right_gutter;
 	}
 }
+
+/**
+ * gtk_source_view_get_mark_category:
+ * @view: a #GtkSourceView
+ * @category: the category
+ *
+ * Get the source mark category object for @category. A
+ * #GtkSourceMarkCategory is automatically created for the given category
+ * if it does not exist yet.
+ *
+ * Returns: (transfer none): the #GtkSourceMarkCategory object
+ *
+ */
+GtkSourceMarkCategory *
+gtk_source_view_get_mark_category (GtkSourceView *view,
+                                   const gchar   *category)
+{
+	GtkSourceMarkCategory *ret;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), NULL);
+	g_return_val_if_fail (category != NULL, NULL);
+
+	ret = g_hash_table_lookup (view->priv->mark_categories, category);
+
+	if (!ret)
+	{
+		ret = gtk_source_mark_category_new (category);
+
+		g_hash_table_insert (view->priv->mark_categories,
+		                     g_strdup (category),
+		                     ret);
+	}
+
+	return ret;
+}
diff --git a/gtksourceview/gtksourceview.h b/gtksourceview/gtksourceview.h
index 2e3b87c..57a1da2 100644
--- a/gtksourceview/gtksourceview.h
+++ b/gtksourceview/gtksourceview.h
@@ -29,6 +29,7 @@
 #include <gtksourceview/gtksourcebuffer.h>
 #include <gtksourceview/gtksourcecompletion.h>
 #include <gtksourceview/gtksourcegutter.h>
+#include <gtksourceview/gtksourcemarkcategory.h>
 
 G_BEGIN_DECLS
 
@@ -192,60 +193,9 @@ void 		 gtk_source_view_set_show_line_marks    (GtkSourceView   *view,
 							 gboolean         show);
 gboolean	 gtk_source_view_get_show_line_marks    (GtkSourceView   *view);
 
-void             gtk_source_view_set_mark_category_icon_from_pixbuf
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 GdkPixbuf       *pixbuf);
-
-void             gtk_source_view_set_mark_category_icon_from_stock
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 const gchar     *stock_id);
-
-void             gtk_source_view_set_mark_category_icon_from_icon_name
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 const gchar     *name);
-
-void             gtk_source_view_set_mark_category_background
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 const GdkColor  *color);
-gboolean         gtk_source_view_get_mark_category_background
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 GdkColor        *dest);
-
-/**
- * GtkSourceViewMarkTooltipFunc:
- * @mark: the #GtkSourceMark
- * @user_data: user data pointer which was passed to gtk_source_view_set_mark_category_tooltip_func()
- *
- * Function type for setting up a tooltip for #GtkSourceMark.
- * Returns: a newly-allocated string that is going to be shown as tooltip text.
- */
-typedef gchar *  (*GtkSourceViewMarkTooltipFunc)	(GtkSourceMark	*mark,
-							 gpointer	 user_data);
-void             gtk_source_view_set_mark_category_tooltip_func
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 GtkSourceViewMarkTooltipFunc func,
-							 gpointer	  user_data,
-							 GDestroyNotify   user_data_notify);
-void		 gtk_source_view_set_mark_category_tooltip_markup_func
-							(GtkSourceView   *view,
-							const gchar     *category,
-							GtkSourceViewMarkTooltipFunc markup_func,
-							gpointer         user_data,
-							GDestroyNotify   user_data_notify);
-
-void             gtk_source_view_set_mark_category_priority
-							(GtkSourceView   *view,
-							 const gchar     *category,
-							 gint priority);
-gint		 gtk_source_view_get_mark_category_priority
-							(GtkSourceView   *view,
-				       			 const gchar     *category);
+GtkSourceMarkCategory *
+                 gtk_source_view_get_mark_category      (GtkSourceView   *view,
+                                                         const gchar     *category);
 
 void		 gtk_source_view_set_smart_home_end	(GtkSourceView             *view,
 							 GtkSourceSmartHomeEndType  smart_he);
diff --git a/tests/test-widget.c b/tests/test-widget.c
index 43709ec..0511edc 100644
--- a/tests/test-widget.c
+++ b/tests/test-widget.c
@@ -1217,9 +1217,13 @@ line_mark_activated (GtkSourceGutter *gutter,
 	const gchar *mark_type;
 
 	if (ev->button == 1)
+	{
 		mark_type = MARK_TYPE_1;
+	}
 	else
+	{
 		mark_type = MARK_TYPE_2;
+	}
 
 	buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
 
@@ -1276,49 +1280,61 @@ bracket_matched (GtkSourceBuffer           *buffer G_GNUC_UNUSED,
 /* Window creation functions -------------------------------------------------------- */
 
 static gchar *
-mark_tooltip_func (GtkSourceMark *mark,
-		   gpointer	  user_data)
+mark_tooltip_func (GtkSourceMarkCategory *category,
+                   GtkSourceMark         *mark,
+                   GtkSourceView         *view)
 {
 	GtkTextBuffer *buf;
 	GtkTextIter iter;
 	gint line, column;
-	
+
 	buf = gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark));
-	
+
 	gtk_text_buffer_get_iter_at_mark (buf, &iter, GTK_TEXT_MARK (mark));
 	line = gtk_text_iter_get_line (&iter) + 1;
 	column = gtk_text_iter_get_line_offset (&iter);
 
-	if (strcmp (gtk_source_mark_get_category (mark), MARK_TYPE_1) == 0)
+	if (g_strcmp0 (gtk_source_mark_category_get_id (category), MARK_TYPE_1) == 0)
+	{
 		return g_strdup_printf ("Line: %d, Column: %d", line, column);
+	}
 	else
+	{
 		return g_strdup_printf ("<b>Line</b>: %d\n<i>Column</i>: %d", line, column);
+	}
 }
 
 static void
 add_source_mark_pixbufs (GtkSourceView *view)
 {
 	GdkColor color;
+	GtkSourceMarkCategory *cat;
 
 	gdk_color_parse ("lightgreen", &color);
-	gtk_source_view_set_mark_category_background (view, MARK_TYPE_1, &color);
-	gtk_source_view_set_mark_category_icon_from_stock (view, MARK_TYPE_1, GTK_STOCK_YES);
-	gtk_source_view_set_mark_category_priority (view, MARK_TYPE_1, 1);
-	gtk_source_view_set_mark_category_tooltip_func (view,
-							MARK_TYPE_1,
-							mark_tooltip_func,
-							NULL,
-							NULL);
+
+	cat = gtk_source_view_get_mark_category (view, MARK_TYPE_1);
+
+	gtk_source_mark_category_set_background (cat, &color);
+	gtk_source_mark_category_set_stock_id (cat, GTK_STOCK_YES);
+	gtk_source_mark_category_set_priority (cat, 1);
+
+	g_signal_connect (cat,
+	                  "query-tooltip-markup",
+	                  G_CALLBACK (mark_tooltip_func),
+	                  view);
 
 	gdk_color_parse ("pink", &color);
-	gtk_source_view_set_mark_category_background (view, MARK_TYPE_2, &color);
-	gtk_source_view_set_mark_category_icon_from_stock (view, MARK_TYPE_2, GTK_STOCK_NO);
-	gtk_source_view_set_mark_category_priority (view, MARK_TYPE_2, 2);
-	gtk_source_view_set_mark_category_tooltip_markup_func (view,
-							       MARK_TYPE_2,
-							       mark_tooltip_func,
-							       NULL,
-							       NULL);
+
+	cat = gtk_source_view_get_mark_category (view, MARK_TYPE_2);
+
+	gtk_source_mark_category_set_background (cat, &color);
+	gtk_source_mark_category_set_stock_id (cat, GTK_STOCK_NO);
+	gtk_source_mark_category_set_priority (cat, 2);
+
+	g_signal_connect (cat,
+	                  "query-tooltip-markup",
+	                  G_CALLBACK (mark_tooltip_func),
+	                  view);
 }
 
 static GtkWidget *



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