Ejemplo n.º 1
0
/* Update the cursor image if the pointer moved.
 */
static gboolean
motion_notify_event (GtkWidget      *text_view,
                     GdkEventMotion *event)
{
  gint x, y;

  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
                                         GTK_TEXT_WINDOW_WIDGET,
                                         event->x, event->y, &x, &y);

  set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);

  return FALSE;
}
Ejemplo n.º 2
0
/* Update the cursor image if the pointer moved. 
 */
static gboolean
motion_notify_event(GtkWidget * self, GdkEventMotion * event)
{
    gint x, y;

    gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(self),
					  GTK_TEXT_WINDOW_WIDGET,
					  event->x, event->y, &x, &y);

    set_cursor_if_appropriate(MARKDOWN_TEXTVIEW(self), x, y);

    gdk_window_get_pointer(self->window, NULL, NULL, NULL);
    return FALSE;
}
Ejemplo n.º 3
0
/* Links can also be activated by clicking or tapping.
 */
static gboolean
event_after (GtkWidget *text_view,
             GdkEvent  *ev)
{
  GtkTextIter start, end, iter;
  GtkTextBuffer *buffer;
  gdouble ex, ey;
  gint x, y;

  if (ev->type == GDK_BUTTON_RELEASE)
    {
      GdkEventButton *event;

      event = (GdkEventButton *)ev;
      if (event->button != GDK_BUTTON_PRIMARY)
        return FALSE;

      ex = event->x;
      ey = event->y;
    }
  else if (ev->type == GDK_TOUCH_END)
    {
      GdkEventTouch *event;

      event = (GdkEventTouch *)ev;

      ex = event->x;
      ey = event->y;
    }
  else
    return FALSE;

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));

  /* we shouldn't follow a link if the user has selected something */
  gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
  if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
    return FALSE;

  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
                                         GTK_TEXT_WINDOW_WIDGET,
                                         ex, ey, &x, &y);

  gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);

  follow_if_link (text_view, &iter);

  return TRUE;
}
/* Also update the cursor image if the window becomes visible
 * (e.g. when a window covering it got iconified).
 */
static gboolean
visibility_notify_event(GtkWidget * self, GdkEventVisibility * event)
{
    gint wx, wy, bx, by;

    gdk_window_get_pointer(self->window, &wx, &wy, NULL);

    gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(self),
					  GTK_TEXT_WINDOW_WIDGET,
					  wx, wy, &bx, &by);

    set_cursor_if_appropriate(MARKDOWN_TEXTVIEW(self), bx, by);

    return FALSE;
}
Ejemplo n.º 5
0
/* Links can also be activated by clicking.
 */
static gboolean
event_after (GtkWidget* text_view, GdkEvent* ev, UgBanner* banner)
{
	GtkTextIter start, end, iter;
	GtkTextBuffer *buffer;
	GdkEventButton *event;
	gint x, y;
	GSList* slist;

	if (ev->type != GDK_BUTTON_RELEASE)
		return FALSE;

	event = (GdkEventButton *)ev;

	if (event->button != GDK_BUTTON_PRIMARY)
		return FALSE;

	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));

	/* we shouldn't follow a link if the user has selected something */
	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
	if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
		return FALSE;

	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
                                         GTK_TEXT_WINDOW_WIDGET,
                                         event->x, event->y, &x, &y);

	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);

	slist = gtk_text_iter_get_tags (&iter);
	if (slist) {
		switch (banner->status) {
		case UG_BANNER_DONATION:
//			ug_launch_uri ("https://sourceforge.net/p/urlget/donate/?source=navbar");
			ug_launch_uri ("http://ugetdm.com/donate");
			break;

		case UG_BANNER_SURVEY:
			ug_launch_uri ("http://ugetdm.com/survey");
			break;
		}
	}
	if (slist)
		g_slist_free (slist);

	return FALSE;
}
Ejemplo n.º 6
0
static gboolean
textview_query_tooltip (GtkTextView *text_view,
                        gint x,
                        gint y,
                        gboolean keyboard_mode,
                        GtkTooltip *tooltip,
                        gpointer user_data)
{
	GtkTextBuffer *buffer;
	guint32 state;
	gboolean res = FALSE;

	if (keyboard_mode)
		return FALSE;

	buffer = gtk_text_view_get_buffer (text_view);
	g_return_val_if_fail (buffer != NULL, FALSE);

	state = get_state (buffer);

	if ((state & E_BUFFER_TAGGER_STATE_IS_HOVERING_TOOLTIP) != 0) {
		gchar *url;
		GtkTextIter iter;

		gtk_text_view_window_to_buffer_coords (
			text_view,
			GTK_TEXT_WINDOW_WIDGET,
			x, y, &x, &y);
		gtk_text_view_get_iter_at_location (text_view, &iter, x, y);

		url = get_url_at_iter (buffer, &iter);
		res = url && *url;

		if (res) {
			gchar *str;

			/* To Translators: The text is concatenated to a form: "Ctrl-click to open a link http://www.example.com" */
			str = g_strconcat (_("Ctrl-click to open a link"), " ", url, NULL);
			gtk_tooltip_set_text (tooltip, str);
			g_free (str);
		}

		g_free (url);
	}

	return res;
}
Ejemplo n.º 7
0
/* when the user right-clicks on a word, they want to check that word.
 * here, we move the cursor to the location of the clicked-upon word.
 * is this necessary?  we could maybe just check the word from its
 * existing location... */
static gboolean
button_press_event(GtkTextView *view, GdkEventButton *event, gpointer data) {
	if (event->button == 3) {
		gint x, y;
		GtkTextIter iter;

		gtk_text_view_window_to_buffer_coords(view, 
				GTK_TEXT_WINDOW_TEXT, 
				(int)event->x, (int)event->y,
				&x, &y);
		gtk_text_view_get_iter_at_location(view, &iter, x, y);
		gtk_text_buffer_place_cursor(gtk_text_view_get_buffer(view),
				&iter);
	}
	return FALSE; /* false: let gtk process this event, too.
					 we don't want to eat any events. */
}
Ejemplo n.º 8
0
gboolean
utl_gui_url_event_after (GtkWidget *textview, GdkEvent *ev, GSList **links_list)
{
	GtkTextIter start, end, iter;
	GtkTextBuffer *buffer;
	GdkEventButton *event;
	gint x, y;
	GSList *tags = NULL, *tagp = NULL;
	GtkTextTag *tag;
	gchar *link;
	gint slink;
	gchar tmpbuf[BUFFER_SIZE];

	if (ev->type != GDK_BUTTON_RELEASE)
		return FALSE;

	event = (GdkEventButton *) ev;
	if (event->button != 1)
		return FALSE;

	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
	if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
		return FALSE;

	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (textview), GTK_TEXT_WINDOW_WIDGET,
	                                       event->x, event->y, &x, &y);
	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (textview), &iter, x, y);

	tags = gtk_text_iter_get_tags (&iter);
	for (tagp = tags; tagp != NULL; tagp = tagp->next) {
		tag = tagp->data;
		slink = (gint) g_object_get_data (G_OBJECT (tag), "link");

		if (slink != 0) {
			link = g_slist_nth_data (*links_list, slink-1);
			g_snprintf (tmpbuf, BUFFER_SIZE, "\"%s\"", link);
			utl_run_helper (tmpbuf, utl_get_link_type (link));
			break;
		}
	}

	if (tags) g_slist_free (tags);

	return FALSE;
}
Ejemplo n.º 9
0
static gboolean
details_visibility_notify_event (GtkWidget *text_view,
                                 GdkEventVisibility *event,
                                 GucharmapCharmap *charmap)
{
  gint wx, wy, bx, by;

  gdk_window_get_pointer (gtk_widget_get_window (text_view), &wx, &wy, NULL);

  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
                                         GTK_TEXT_WINDOW_WIDGET,
                                         wx, wy, &bx, &by);

  set_cursor_if_appropriate (charmap, bx, by);

  return FALSE;
}
Ejemplo n.º 10
0
static gboolean
textview_motion_notify_event (GtkTextView *textview,
                              GdkEventMotion *event)
{
	gint x, y;

	g_return_val_if_fail (GTK_IS_TEXT_VIEW (textview), FALSE);

	gtk_text_view_window_to_buffer_coords (
		textview,
		GTK_TEXT_WINDOW_WIDGET,
		event->x, event->y, &x, &y);

	update_mouse_cursor (textview, x, y);

	return FALSE;
}
Ejemplo n.º 11
0
/*
 * Update the cursor image if the pointer moved. 
 */
static gboolean
motion_notify_event (GtkWidget *text_view, GdkEventMotion *event, EntryProperties *eprop)
{
	gint x, y;

	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
					       GTK_TEXT_WINDOW_WIDGET,
					       event->x, event->y, &x, &y);
	
	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y, eprop);

	/* store coordinates */
	eprop->priv->bx = x;
	eprop->priv->by = y;

	return FALSE;
}
Ejemplo n.º 12
0
static void
update_ctrl_state (GtkTextView *textview,
                   gboolean ctrl_is_down)
{
	GtkTextBuffer *buffer;
	gint x, y;

	buffer = gtk_text_view_get_buffer (textview);
	if (buffer) {
		if (((get_state (buffer) & E_BUFFER_TAGGER_STATE_CTRL_DOWN) != 0) != (ctrl_is_down != FALSE)) {
			update_state (buffer, E_BUFFER_TAGGER_STATE_CTRL_DOWN, ctrl_is_down != FALSE);
		}

		get_pointer_position (textview, &x, &y);
		gtk_text_view_window_to_buffer_coords (textview, GTK_TEXT_WINDOW_WIDGET, x, y, &x, &y);
		update_mouse_cursor (textview, x, y);
	}
}
Ejemplo n.º 13
0
CAMLprim value ml_gtk_text_view_window_to_buffer_coords (value tv, 
							 value tt,
							 value x,
							 value y)
{
  CAMLparam4(tv,tt,x,y);
  CAMLlocal1(res);
  int bx,by = 0;
  gtk_text_view_window_to_buffer_coords(GtkTextView_val(tv),
					Text_window_type_val(tt),
					Int_val(x),Int_val(y),
					&bx,&by);

  res = alloc_tuple(2);
  Store_field(res,0,Val_int(bx));
  Store_field(res,1,Val_int(by));
  CAMLreturn(res);
}
Ejemplo n.º 14
0
static gboolean cb_button_press_event(GtkWidget *view, GdkEventButton *event)
{
	GtkTextIter iter, start, end;
	gint x, y;
	
	GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
	
	if ((event->button) == 3 && (event->type == GDK_BUTTON_PRESS)) {
		gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(view),
			gtk_text_view_get_window_type(GTK_TEXT_VIEW(view), event->window),
			(gint)event->x, (gint)event->y, &x, &y);
		gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(view), &iter, x, y);
		gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
		if (!gtk_text_iter_in_range(&iter, &start, &end))
			gtk_text_buffer_place_cursor(buffer, &iter);
	}
	
	return FALSE;
}
Ejemplo n.º 15
0
Archivo: text.c Proyecto: polarcat/yad
static gboolean
motion_cb (GtkWidget *w, GdkEventMotion *ev, gpointer d)
{
  gint x, y;
  GSList *tags = NULL, *tagp = NULL;
  GtkTextIter iter;
  gboolean hovering = FALSE;

  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (w), GTK_TEXT_WINDOW_WIDGET,
                                         ev->x, ev->y, &x, &y);

  gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (w), &iter, x, y);

  tags = gtk_text_iter_get_tags (&iter);
  for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
    {
      GtkTextTag *tag = tagp->data;
      gint link = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "is_link"));

      if (link)
        {
          hovering = TRUE;
          break;
        }
    }

  if (hovering != hovering_over_link)
    {
      hovering_over_link = hovering;

      if (hovering_over_link)
        gdk_window_set_cursor (gtk_text_view_get_window (GTK_TEXT_VIEW (w), GTK_TEXT_WINDOW_TEXT), hand);
      else
        gdk_window_set_cursor (gtk_text_view_get_window (GTK_TEXT_VIEW (w), GTK_TEXT_WINDOW_TEXT), normal);
    }

  if (tags)
    g_slist_free (tags);

  gdk_window_get_pointer (gtk_widget_get_window (w), NULL, NULL, NULL);

  return FALSE;
}
Ejemplo n.º 16
0
static gboolean
textview_visibility_notify_event (GtkTextView *textview,
                                  GdkEventVisibility *event)
{
	gint wx, wy, bx, by;

	g_return_val_if_fail (GTK_IS_TEXT_VIEW (textview), FALSE);

	get_pointer_position (textview, &wx, &wy);

	gtk_text_view_window_to_buffer_coords (
		textview,
		GTK_TEXT_WINDOW_WIDGET,
		wx, wy, &bx, &by);

	update_mouse_cursor (textview, bx, by);

	return FALSE;
}
Ejemplo n.º 17
0
/* 
 * Also update the cursor image if the window becomes visible
 * (e.g. when a window covering it got iconified).
 */
static gboolean
visibility_notify_event (GtkWidget *text_view, G_GNUC_UNUSED GdkEventVisibility *event, GdauiCloud *cloud)
{
	gint wx, wy, bx, by;
	GdkDeviceManager *manager;
        GdkDevice *pointer;

        manager = gdk_display_get_device_manager (gtk_widget_get_display (text_view));
        pointer = gdk_device_manager_get_client_pointer (manager);
	gdk_window_get_device_position (gtk_widget_get_window (text_view), pointer, &wx, &wy, NULL);
	
	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
					       GTK_TEXT_WINDOW_WIDGET,
					       wx, wy, &bx, &by);
	
	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), bx, by, cloud);
	
	return FALSE;
}
Ejemplo n.º 18
0
/* on_view_event_after */
static gboolean _on_view_event_after(GtkWidget * widget, GdkEvent * event,
		gpointer data)
{
	GHtml * ghtml = data;
	GdkEventButton * eb;
	GtkTextIter start;
	GtkTextIter end;
	gint x;
	gint y;
	GtkTextIter iter;
	GSList * tags;
	GSList * p;
	char * link = NULL;
	gchar * url;

	if(event->type != GDK_BUTTON_RELEASE || event->button.button != 1)
		return FALSE;
	eb = &event->button;
	gtk_text_buffer_get_selection_bounds(ghtml->tbuffer, &start, &end);
	if(gtk_text_iter_get_offset(&start) != gtk_text_iter_get_offset(&end))
		return FALSE;
	gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget),
			GTK_TEXT_WINDOW_WIDGET, eb->x, eb->y, &x, &y);
	gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &iter, x, y);
	tags = gtk_text_iter_get_tags(&iter);
	for(p = tags; p != NULL; p = p->next)
		if((link = g_object_get_data(G_OBJECT(p->data), "link"))
				!= NULL)
			break;
	if(tags != NULL)
		g_slist_free(tags);
	if(link == NULL)
		return FALSE;
	url = (ghtml->base != NULL) ? ghtml->base : _history_get_location(
			ghtml->current);
	if((url = _ghtml_make_url(url, link)) != NULL)
		surfer_open(ghtml->surfer, url);
	else
		surfer_open(ghtml->surfer, link);
	g_free(url);
	return FALSE;
}
Ejemplo n.º 19
0
static gboolean _text_view_click_handler(GtkWidget *widget, GdkEvent *event)
{
	GtkTextView *text_view = GTK_TEXT_VIEW(widget);

	if (event->type == GDK_BUTTON_RELEASE)
	{
		GdkEventButton *button_event = GDK_EVENT_BUTTON(event);

		if (button_event->button == 1)
		{
			GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(text_view);
			gint x;
			gint y;
			GtkTextIter text_iter;

			gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_WIDGET, button_event->x, button_event->y, &x, &y);
			gtk_text_view_get_iter_at_location(text_view, &text_iter, x, y);

			{
				GSList *text_tag_list = gtk_text_iter_get_tags(&text_iter);
				GSList *text_tag_list_item;

				for (text_tag_list_item = text_tag_list; text_tag_list_item != NULL; text_tag_list_item = text_tag_list_item->next)
				{
					GtkTextTag *text_tag = GTK_TEXT_TAG(text_tag_list_item->data);

					if (g_object_get_data(G_OBJECT(text_tag), "column_type") != NULL)
					{
						gtk_text_buffer_place_cursor(text_buffer);
						break;
					}
				}

				if (text_tag_list != NULL) g_slist_free(text_tag_list);
			}

			return TRUE;
		}
	}

	return FALSE;
}
Ejemplo n.º 20
0
static gboolean mouse_click_callback(GtkWidget *text_view,
	GdkEventButton *event)
{
	gint x, y;
	gchar *url = NULL;

	if (event->type != GDK_2BUTTON_PRESS)
		return FALSE;

	gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(text_view),
		GTK_TEXT_WINDOW_WIDGET, event->x, event->y, &x, &y);

	get_url_at_location(&url, GTK_TEXT_VIEW(text_view), x, y);

	if (url != NULL) {
		open_url(text_view, url);
	}

	return TRUE;
}
Ejemplo n.º 21
0
static gboolean chatroom_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
	gint wx, wy, bx, by;
	GtkTextView *chatroom = GTK_TEXT_VIEW(widget);
	GtkTextBuffer *buffer = gtk_text_view_get_buffer(chatroom);
	GtkTextTag *link_tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "link");
	GdkWindow *window = gtk_text_view_get_window(chatroom, GTK_TEXT_WINDOW_TEXT);
	GtkTextIter iter;
	if(event->type == GDK_MOTION_NOTIFY) {
		GdkEventMotion *motion_ev = (GdkEventMotion *)event;
		wx = motion_ev->x;
		wy = motion_ev->y;
		gtk_text_view_window_to_buffer_coords(chatroom, GTK_TEXT_WINDOW_TEXT, wx, wy, &bx, &by);
		gtk_text_view_get_iter_at_location(chatroom, &iter, bx, by);
		if(gtk_text_iter_has_tag(&iter, link_tag)) {
			chatroom_enable_hand_cursor(window, TRUE);
		} else {
			chatroom_enable_hand_cursor(window, FALSE);
		}
	}
	return FALSE;
}
Ejemplo n.º 22
0
/* Looks at all tags covering the position (x, y) in the text view,
 * and if one of them is a link, change the cursor to the "hands" cursor
 * typically used by web browsers.
 */
static gboolean
motion_notify_event (GtkWidget* tv_widget, GdkEventMotion* event, UgBanner* banner)
{
	GtkTextView* text_view;
	gint x, y;
	gboolean  hovering = FALSE;
	GSList* slist;
	GtkTextIter iter;

	text_view = GTK_TEXT_VIEW (tv_widget);
	gtk_text_view_window_to_buffer_coords (text_view,
			GTK_TEXT_WINDOW_WIDGET, event->x, event->y, &x, &y);

	// set cursor if appropriate
	gtk_text_view_get_iter_at_location (text_view, &iter, x, y);

	slist = gtk_text_iter_get_tags (&iter);
	if (slist)
		hovering = TRUE;
	if (banner->hovering_over_link != hovering) {
		banner->hovering_over_link = hovering;

		if (banner->hovering_over_link) {
			gdk_window_set_cursor (gtk_text_view_get_window (text_view,
					GTK_TEXT_WINDOW_TEXT), hand_cursor);
		}
		else {
			gdk_window_set_cursor (gtk_text_view_get_window (text_view,
					GTK_TEXT_WINDOW_TEXT), regular_cursor);
		}
	}
	if (slist)
		g_slist_free (slist);

	return FALSE;
}
Ejemplo n.º 23
0
static gboolean
query_tooltip_text_view_cb (GtkWidget  *widget,
			    gint        x,
			    gint        y,
			    gboolean    keyboard_tip,
			    GtkTooltip *tooltip,
			    gpointer    data)
{
  GtkTextTag *tag = data;
  GtkTextIter iter;
  GtkTextView *text_view = GTK_TEXT_VIEW (widget);
  GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);

  if (keyboard_tip)
    {
      gint offset;

      g_object_get (buffer, "cursor-position", &offset, NULL);
      gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
    }
  else
    {
      gint bx, by, trailing;

      gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_TEXT,
					     x, y, &bx, &by);
      gtk_text_view_get_iter_at_position (text_view, &iter, &trailing, bx, by);
    }

  if (gtk_text_iter_has_tag (&iter, tag))
    gtk_tooltip_set_text (tooltip, "Tooltip on text tag");
  else
   return FALSE;

  return TRUE;
}
Ejemplo n.º 24
0
Archivo: about.c Proyecto: Mortal/claws
static void about_textview_uri_update(GtkWidget *textview, gint x, gint y)
{
	GtkTextBuffer *buffer;
	GtkTextIter start_iter, end_iter;
	gchar *uri = NULL;
	gboolean same;
	
	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));

	if (x != -1 && y != -1) {
		gint bx, by;
		GtkTextIter iter;
		GSList *tags;
		GSList *cur;
	    
		gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(textview), 
				GTK_TEXT_WINDOW_WIDGET,
				x, y, &bx, &by);
		gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(textview),
				&iter, bx, by);

		tags = gtk_text_iter_get_tags(&iter);
		for (cur = tags; cur != NULL; cur = cur->next) {
			GtkTextTag *tag = cur->data;
			char *name;

			g_object_get(G_OBJECT(tag), "name", &name, NULL);
			if (strcmp(name, "link") == 0
			    && get_tag_range(&iter, tag, &start_iter, &end_iter)) {
				uri = gtk_text_iter_get_text(&start_iter, &end_iter);
			}
			g_free(name);

			if (uri) {
				break;
			}
		}
		g_slist_free(tags);
	}

	/* compare previous hovered link and this one
	   (here links must be unique in text buffer otherwise ClickableText structures should be
	   used as in textview.c) */
	same = (uri != NULL && uri_hover != NULL
		&& strcmp((char*)uri, (char*)uri_hover) == 0);

	if (same == FALSE) {
		GdkWindow *window;

		if (uri_hover) {
			gtk_text_buffer_remove_tag_by_name(buffer,
					"link-hover",
					&uri_hover_start_iter,
					&uri_hover_end_iter);
		}
		    
		uri_hover = uri;
		if (uri) {
			uri_hover_start_iter = start_iter;
			uri_hover_end_iter = end_iter;

			gtk_text_buffer_apply_tag_by_name(buffer,
					"link-hover",
					&start_iter,
					&end_iter);
		}
		
		window = gtk_text_view_get_window(GTK_TEXT_VIEW(textview),
						GTK_TEXT_WINDOW_TEXT);
		if (!hand_cursor)
			hand_cursor = gdk_cursor_new(GDK_HAND2);
		if (!text_cursor)
			text_cursor = gdk_cursor_new(GDK_XTERM);
		gdk_window_set_cursor(window, uri ? hand_cursor : text_cursor);
	}
}
Ejemplo n.º 25
0
static void
chat_text_view_populate_popup (EmpathyChatTextView *view,
			  GtkMenu        *menu,
			  gpointer        user_data)
{
	EmpathyChatTextViewPriv *priv;
	GtkTextTagTable    *table;
	GtkTextTag         *tag;
	gint                x, y;
	GtkTextIter         iter, start, end;
	GtkWidget          *item;
	gchar              *str = NULL;
	
	priv = GET_PRIV (view);
	
	/* Clear menu item */
	if (gtk_text_buffer_get_char_count (priv->buffer) > 0) {
		item = gtk_menu_item_new ();
		gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
		gtk_widget_show (item);
		
		item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
		gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
		gtk_widget_show (item);
		
		g_signal_connect (item,
				  "activate",
				  G_CALLBACK (chat_text_view_clear_view_cb),
				  view);
	}
	
	/* Link context menu items */
	table = gtk_text_buffer_get_tag_table (priv->buffer);
	tag = gtk_text_tag_table_lookup (table, EMPATHY_CHAT_TEXT_VIEW_TAG_LINK);
	
	gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
	
	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
					       GTK_TEXT_WINDOW_WIDGET,
					       x, y,
					       &x, &y);
	
	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, x, y);
	
	start = end = iter;
	
	if (gtk_text_iter_backward_to_tag_toggle (&start, tag) &&
	    gtk_text_iter_forward_to_tag_toggle (&end, tag)) {
		    str = gtk_text_buffer_get_text (priv->buffer,
						    &start, &end, FALSE);
	    }
	
	if (EMP_STR_EMPTY (str)) {
		g_free (str);
		return;
	}
	
	/* NOTE: Set data just to get the string freed when not needed. */
	g_object_set_data_full (G_OBJECT (menu),
				"url", str,
				(GDestroyNotify) g_free);
	
	item = gtk_menu_item_new ();
	gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);
	
	item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
	g_signal_connect (item,
			  "activate",
			  G_CALLBACK (chat_text_view_copy_address_cb),
			  str);
	gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);
	
	item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
	g_signal_connect (item,
			  "activate",
			  G_CALLBACK (chat_text_view_open_address_cb),
			  str);
	gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);
}
Ejemplo n.º 26
0
/**************************************************************************
  Click a link.
**************************************************************************/
static gboolean event_after(GtkWidget *text_view, GdkEventButton *event)
{
  GtkTextIter start, end, iter;
  GtkTextBuffer *buffer;
  GSList *tags, *tagp;
  gint x, y;
  struct tile *ptile = NULL;

  if (event->type != GDK_BUTTON_RELEASE || event->button != 1) {
    return FALSE;
  }

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));

  /* We shouldn't follow a link if the user has selected something. */
  gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
  if (gtk_text_iter_get_offset(&start) != gtk_text_iter_get_offset(&end)) {
    return FALSE;
  }

  gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW (text_view), 
                                        GTK_TEXT_WINDOW_WIDGET,
                                        event->x, event->y, &x, &y);

  gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(text_view), &iter, x, y);

  if ((tags = gtk_text_iter_get_tags(&iter))) {
    for (tagp = tags; tagp; tagp = tagp->next) {
      GtkTextTag *tag = tagp->data;
      enum text_link_type type =
        GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tag), "type"));

      if (type != 0) {
        /* This is a link. */
        int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tag), "id"));
        ptile = NULL;

        /* Real type is type - 1.
         * See comment in apply_text_tag() for g_object_set_data(). */
        type--;

        switch (type) {
        case TLT_CITY:
          {
            struct city *pcity = game_city_by_number(id);

            if (pcity) {
              ptile = client_city_tile(pcity);
            } else {
              output_window_append(ftc_client, _("This city isn't known!"));
            }
          }
          break;
        case TLT_TILE:
          ptile = index_to_tile(id);

          if (!ptile) {
            output_window_append(ftc_client,
                                 _("This tile doesn't exist in this game!"));
          }
          break;
        case TLT_UNIT:
          {
            struct unit *punit = game_unit_by_number(id);

            if (punit) {
              ptile = unit_tile(punit);
            } else {
              output_window_append(ftc_client, _("This unit isn't known!"));
            }
          }
          break;
        }

        if (ptile) {
          center_tile_mapcanvas(ptile);
          link_mark_restore(type, id);
          gtk_widget_grab_focus(GTK_WIDGET(map_canvas));
        }
      }
    }
    g_slist_free(tags);
  }

  return FALSE;
}
Ejemplo n.º 27
0
gint motion_notify_event(GtkWidget *widget, GdkEventMotion *event)
{
	gint x, y;
	GdkModifierType mask;
	GtkTextIter iter;
	guint offset;
	gint buffer_x, buffer_y;
	GdkRectangle location;
	gboolean too_far=FALSE;
	
#ifdef __WIN32__
	HCURSOR hCursor;
#else
	GdkCursor *cursor;
#endif

//	LOG(LOG_DEBUG, "IN : motion_notify_event(x=%f,y=%f (%d %d))", event->x, event->y, buffer_x, buffer_y);

	// If you don't convert position as buffer origin, 
	// position will be invalid when scrolling
	gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget),
					      GTK_TEXT_WINDOW_TEXT,
					      (gint)(event->x),
					      (gint)(event->y),
					      &buffer_x,
					      &buffer_y);

	gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget),
					   &iter,
					   buffer_x,
					   buffer_y);
	offset = gtk_text_iter_get_offset(&iter);

	gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget),
					&iter,
					&location);
	if((buffer_x > location.x + font_width) || (buffer_x < location.x - font_width))
		too_far = TRUE;
	else
		too_far = FALSE;
	
#ifdef __WIN32__
	if(scan_link(offset) && !too_far){
		hCursor = LoadCursor(NULL, IDC_HAND);
		// Because IDC_HAND can not be used in NT
		if(hCursor == 0)
			hCursor = LoadCursor(NULL, IDC_ARROW);
	} else {
		hCursor = LoadCursor(NULL, IDC_IBEAM);
	}
	SetCursor(hCursor);
#else
	if(scan_link(offset) && !too_far){
		cursor = gdk_cursor_new (CURSOR_LINK);
	} else {
		cursor = gdk_cursor_new(CURSOR_NORMAL);
	}
	gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT), cursor);
	gdk_cursor_unref(cursor);

	gdk_window_get_pointer(widget->window, &x, &y, &mask);
#endif

//	LOG(LOG_DEBUG, "OUT : motion_notify_event()");

	if(event->state & GDK_BUTTON1_MASK)
		return(FALSE);
	else 
		return(TRUE);
}
Ejemplo n.º 28
0
static void
dma_sparse_view_paint_margin (DmaSparseView *view,
			      GdkEventExpose *event)
{
	GtkTextView *text_view;
	GdkWindow *win;
	PangoLayout *layout;
	gint y1, y2;
	gint y, height;
	gchar str [16];
	gint margin_width;
	gint margin_length;
	gint text_width;
	DmaSparseIter buf_iter;
	GtkTextIter text_iter;
	guint prev_address = G_MAXUINT;

	
	text_view = GTK_TEXT_VIEW (view);

	if (!view->priv->show_line_numbers && !view->priv->show_line_markers)
	{
		gtk_text_view_set_border_window_size (text_view,
						      GTK_TEXT_WINDOW_LEFT,
						      0);

		return;
	}
	
	win = gtk_text_view_get_window (text_view,
					GTK_TEXT_WINDOW_LEFT);	

	y1 = event->area.y;
	y2 = y1 + event->area.height;

	/* get the extents of the line printing */
	gtk_text_view_window_to_buffer_coords (text_view,
					       GTK_TEXT_WINDOW_LEFT,
					       0,
					       y1,
					       NULL,
					       &y1);

	gtk_text_view_window_to_buffer_coords (text_view,
					       GTK_TEXT_WINDOW_LEFT,
					       0,
					       y2,
					       NULL,
					       &y2);

	/* set size. */
	g_snprintf (str, sizeof (str), "0x%X", G_MAXUINT);
	margin_length = strlen(str) - 2;
	layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), str);

	pango_layout_get_pixel_size (layout, &text_width, NULL);
	
	pango_layout_set_width (layout, text_width);
	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);

	/* determine the width of the left margin. */
	if (view->priv->show_line_numbers)
		margin_width = text_width + 4;
	else
		margin_width = 0;
	
	if (view->priv->show_line_markers)
		margin_width += GUTTER_PIXMAP;

	g_return_if_fail (margin_width != 0);
	
	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (text_view),
					      GTK_TEXT_WINDOW_LEFT,
					      margin_width);

	/* Display all addresses */
	dma_sparse_iter_copy (&buf_iter, &view->priv->start);
	gtk_text_buffer_get_start_iter (gtk_text_view_get_buffer (text_view), &text_iter);
	

	
	/* Skip line while position doesn't need to be repaint */
	gtk_text_view_get_line_yrange (text_view, &text_iter, &y, &height);
	if (y < y1)
	{
		do
		{
			if (!dma_sparse_iter_forward_lines (&buf_iter, 1)) return;
			if (!gtk_text_iter_forward_line (&text_iter)) return;
			gtk_text_view_get_line_yrange (text_view, &text_iter, &y, &height);
		} while (y < y1);
	}
		

	/* Display address */
	do
	{
		gint pos;
		guint address;
		
		gtk_text_view_buffer_to_window_coords (text_view,
						       GTK_TEXT_WINDOW_LEFT,
						       0,
						       y,
						       NULL,
						       &pos);

		address = dma_sparse_iter_get_address (&buf_iter);
		
		if (view->priv->show_line_numbers) 
		{
			g_snprintf (str, sizeof (str),"0x%0*lX", margin_length, (long unsigned int)address);
			pango_layout_set_markup (layout, str, -1);

			gtk_paint_layout (gtk_widget_get_style (GTK_WIDGET (view)),
					  win,
					  gtk_widget_get_state (GTK_WIDGET (view)),
					  FALSE,
					  NULL,
					  GTK_WIDGET (view),
					  NULL,
					  text_width + 2, 
					  pos,
					  layout);
		}

		/* Display marker */
		if ((prev_address != address) && (view->priv->show_line_markers)) 
		{
			gint current_marker = dma_sparse_buffer_get_marks (view->priv->buffer, address);

			if (current_marker)
			{
				gint x;
				
				if (view->priv->show_line_numbers)
					x = text_width + 4;
				else
					x = 0;
				
				draw_line_markers (view, current_marker, x, pos);
				prev_address = address;
			}
		}
		
		if (!dma_sparse_iter_forward_lines (&buf_iter, 1)) return;
		if (!gtk_text_iter_forward_line (&text_iter)) return;
		gtk_text_view_get_line_yrange (text_view, &text_iter, &y, &height);
		
	} while (y < y2);
		
	g_object_unref (G_OBJECT (layout));	
}
Ejemplo n.º 29
0
static gint
line_numbers_expose (GtkWidget      *widget,
                     GdkEventExpose *event)
{
	GtkTextView *text_view;
	GdkWindow *win;
//	GtkStyle *style;
	PangoLayout *layout;
	PangoAttrList *alist;
	PangoAttribute *attr;
	GArray *numbers;
	GArray *pixels;
	gint y1, y2;
	gint count;
	gint layout_width;
	gint justify_width = 0;
	gint i;
//	gchar *str;
	gchar str [8];  /* we don't expect more than ten million lines */
	GdkGC *gc;
	gint height;
	
	if (line_number_visible){{{{{	// omit calculation
	
	text_view = GTK_TEXT_VIEW (widget);
	
	/* See if this expose is on the line numbers window */
/*	left_win = gtk_text_view_get_window (text_view,
	                                     GTK_TEXT_WINDOW_LEFT);
	right_win = gtk_text_view_get_window (text_view,
	                                      GTK_TEXT_WINDOW_RIGHT);
	
	if (event->window == left_win)
	{
		type = GTK_TEXT_WINDOW_LEFT;
		target = event->window;
	}
	else if (event->window == right_win)
	{
		type = GTK_TEXT_WINDOW_RIGHT;
		target = right_win;
	}
	else
		return FALSE;
*/	
	win = gtk_text_view_get_window (text_view,
	                                GTK_TEXT_WINDOW_LEFT);
	if (event->window != win)
		return FALSE;
	
//	style = gtk_style_copy (widget->style);
//	style = gtk_style_copy (gtk_widget_get_default_style());
	
	y1 = event->area.y;
	y2 = y1 + event->area.height;
	
	gtk_text_view_window_to_buffer_coords (text_view,
	                                       GTK_TEXT_WINDOW_LEFT,
	                                       0,
	                                       y1,
	                                       NULL,
	                                       &y1);
	
	gtk_text_view_window_to_buffer_coords (text_view,
	                                       GTK_TEXT_WINDOW_LEFT,
	                                       0,
	                                       y2,
	                                       NULL,
	                                       &y2);
	
	numbers = g_array_new (FALSE, FALSE, sizeof (gint));
	pixels = g_array_new (FALSE, FALSE, sizeof (gint));
	
	get_lines (text_view,
	           y1,
	           y2,
	           pixels,
	           numbers,
	           &count);
	
	/* a zero-lined document should display a "1"; we don't need to worry about
	scrolling effects of the text widget in this special case */
	
	if (count == 0)
	{
		gint y = 0;
		gint n = 0;
		count = 1;
		g_array_append_val (pixels, y);
		g_array_append_val (numbers, n);
	}
	
DV({g_print("Painting line numbers %d - %d\n",
			g_array_index(numbers, gint, 0),
			g_array_index(numbers, gint, count - 1));	});
	
	layout = gtk_widget_create_pango_layout (widget, "");
	
//	str = g_strdup_printf ("%d", gtk_text_buffer_get_line_count(text_view->buffer));
	g_snprintf (str, sizeof (str),
			"%d", MAX (99, gtk_text_buffer_get_line_count(text_view->buffer)));
	pango_layout_set_text (layout, str, -1);
//	g_free (str);
	
	pango_layout_get_pixel_size (layout, &layout_width, NULL);
	
	min_number_window_width = calculate_min_number_window_width(widget);
	if (layout_width > min_number_window_width)
		gtk_text_view_set_border_window_size (text_view,
			GTK_TEXT_WINDOW_LEFT, layout_width + margin + submargin);
	else {
//		if ((gtk_text_view_get_border_window_size (text_view, GTK_TEXT_WINDOW_LEFT) - 5) > layout_width) {
			gtk_text_view_set_border_window_size (text_view,
				GTK_TEXT_WINDOW_LEFT, min_number_window_width + margin + submargin);
//		}
		justify_width = min_number_window_width - layout_width;
	}
	
	pango_layout_set_width (layout, layout_width);
	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
	
	alist = pango_attr_list_new();
	attr = pango_attr_foreground_new(
		widget->style->text_aa->red,
		widget->style->text_aa->green,
		widget->style->text_aa->blue);
	attr->start_index = 0;
	attr->end_index = G_MAXUINT;
	pango_attr_list_insert(alist, attr);
	pango_layout_set_attributes(layout, alist);
	pango_attr_list_unref(alist);
	
	/* Draw fully internationalized numbers! */
	
	i = 0;
	while (i < count)
	{
		gint pos;
		
		gtk_text_view_buffer_to_window_coords (text_view,
		                                       GTK_TEXT_WINDOW_LEFT,
		                                       0,
		                                       g_array_index (pixels, gint, i),
		                                       NULL,
		                                       &pos);
		
//		str = g_strdup_printf ("%d", g_array_index (numbers, gint, i) + 1);
		g_snprintf (str, sizeof (str),
				"%d", g_array_index (numbers, gint, i) + 1);
		
		pango_layout_set_text (layout, str, -1);
		
		gtk_paint_layout (widget->style,
		                  win,
		                  GTK_WIDGET_STATE (widget),
		                  FALSE,
		                  NULL,
		                  widget,
		                  NULL,
#if GTK_CHECK_VERSION(2, 6, 0)  // Is this solution???
		                  layout_width + justify_width + margin / 2 + 1,
#else
		                  layout_width + justify_width + margin / 2,
#endif
		                  pos,
		                  layout);
//		g_free (str);
		
		++i;
	}
	
	g_array_free (pixels, TRUE);
	g_array_free (numbers, TRUE);
	
	g_object_unref (G_OBJECT (layout));
//	g_object_ref (G_OBJECT (style));
	
	/* don't stop emission, need to draw children */
	
	}}}}}
Ejemplo n.º 30
0
static gboolean
on_view_draw (GtkSourceView   *view,
              cairo_t         *cr,
              GtkSourceGutter *gutter)
{
	GdkWindow *window;
	GtkTextView *text_view;
	GArray *sizes;
	GdkRectangle clip;
	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;
	GtkStyleContext *style_context;
	GdkRGBA fg_color;

	window = gtk_source_gutter_get_window (gutter);

	if (window == NULL || !gtk_cairo_should_draw_window (cr, window))
	{
		return FALSE;
	}

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

	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;

	style_context = gtk_widget_get_style_context (GTK_WIDGET (view));

	gtk_style_context_get_color (style_context,
	                             gtk_widget_get_state (GTK_WIDGET (view)),
	                             &fg_color);

	gdk_cairo_set_source_rgba (cr, &fg_color);

	while (item)
	{
		Renderer *renderer = item->data;
		gint xpad;
		gint width;

		width = g_array_index (sizes, gint, idx++);

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

	gtk_text_buffer_get_selection_bounds (buffer,
	                                      &selection_start,
	                                      &selection_end);

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

	for (i = 0; i < count; ++i)
	{
		gint pos;
		gint line_to_paint;

		end = start;

		if (!gtk_text_iter_ends_line (&end))
		{
			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);

		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;

		idx = 0;

		for (item = gutter->priv->renderers; item; item = g_list_next (item))
		{
			Renderer *renderer;
			gint width;
			GtkSourceGutterRendererState state;
			gint xpad;
			gint ypad;

			renderer = item->data;
			width = g_array_index (sizes, gint, idx++);

			if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
			{
				continue;
			}

			gtk_source_gutter_renderer_get_padding (renderer->renderer,
			                                        &xpad,
			                                        &ypad);

			background_area.width = width;

			cell_area.y = background_area.y + ypad;
			cell_area.height = background_area.height - 2 * ypad;

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

	for (item = gutter->priv->renderers; item; item = g_list_next (item))
	{
		Renderer *renderer = item->data;

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

	g_array_free (sizes, TRUE);

	gutter->priv->is_drawing = FALSE;

	return FALSE;
}