static gboolean
set_tooltip_widget_from_marks (GtkSourceView *view,
                               GtkTooltip    *tooltip,
                               GSList        *marks)
{
	GtkGrid *grid = NULL;
	gint row_num = 0;
	gint icon_size;

	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size);

	for (; marks; marks = g_slist_next (marks))
	{
		const gchar *category;
		GtkSourceMark *mark;
		GtkSourceMarkAttributes *attrs;
		gchar *text;
		gboolean ismarkup = FALSE;
		GtkWidget *label;
		const GdkPixbuf *pixbuf;

		mark = marks->data;
		category = gtk_source_mark_get_category (mark);

		attrs = gtk_source_view_get_mark_attributes (view, category, NULL);

		if (attrs == NULL)
		{
			continue;
		}

		text = gtk_source_mark_attributes_get_tooltip_markup (attrs, mark);

		if (text == NULL)
		{
			text = gtk_source_mark_attributes_get_tooltip_text (attrs, mark);
		}
		else
		{
			ismarkup = TRUE;
		}

		if (text == NULL)
		{
			continue;
		}

		if (grid == NULL)
		{
			grid = GTK_GRID (gtk_grid_new ());
			gtk_grid_set_column_spacing (grid, 4);
			gtk_widget_show (GTK_WIDGET (grid));
		}

		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_widget_set_halign (label, GTK_ALIGN_START);
		gtk_widget_set_valign (label, GTK_ALIGN_START);
		gtk_widget_show (label);

		pixbuf = gtk_source_mark_attributes_render_icon (attrs,
		                                                 GTK_WIDGET (view),
		                                                 icon_size);

		if (pixbuf == NULL)
		{
			gtk_grid_attach (grid, label, 0, row_num, 2, 1);
		}
		else
		{
			GtkWidget *image;
			GdkPixbuf *copy;

			/* FIXME why a copy is needed? */
			copy = gdk_pixbuf_copy (pixbuf);
			image = gtk_image_new_from_pixbuf (copy);
			g_object_unref (copy);

			gtk_widget_set_halign (image, GTK_ALIGN_START);
			gtk_widget_set_valign (image, GTK_ALIGN_START);
			gtk_widget_show (image);

			gtk_grid_attach (grid, image, 0, row_num, 1, 1);
			gtk_grid_attach (grid, label, 1, row_num, 1, 1);
		}

		row_num++;

		if (marks->next != NULL)
		{
			GtkWidget *separator;

			separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);

			gtk_widget_show (separator);

			gtk_grid_attach (grid, separator, 0, row_num, 2, 1);
			row_num++;
		}

		g_free (text);
	}

	if (grid == NULL)
	{
		return FALSE;
	}

	gtk_tooltip_set_custom (tooltip, GTK_WIDGET (grid));

	return TRUE;
}
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;
		GtkSourceMarkAttributes *attrs;
		gchar *text;
		gboolean ismarkup = FALSE;
		GtkWidget *label;
		GtkWidget *hbox;
		const GdkPixbuf *pixbuf;
		gint size;

		mark = marks->data;
		category = gtk_source_mark_get_category (mark);

		attrs = gtk_source_view_get_mark_attributes (view,
		                                             category,
		                                             NULL);

		if (attrs == NULL)
		{
			continue;
		}

		text = gtk_source_mark_attributes_get_tooltip_markup (attrs,
		                                                      mark);

		if (text == NULL)
		{
			text = gtk_source_mark_attributes_get_tooltip_text (attrs,
			                                                    mark);
		}
		else
		{
			ismarkup = TRUE;
		}

		if (text == NULL)
		{
			continue;
		}

		if (vbox == NULL)
		{
			vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
			gtk_widget_show (vbox);
		}

		hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 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_attributes_render_icon (attrs,
		                                                 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_separator_new (GTK_ORIENTATION_HORIZONTAL);

			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;
}