[Goodies-commits] r5698 - in xfce4-dict/trunk: . lib

Enrico Troeger enrico at xfce.org
Sun Oct 19 11:30:05 CEST 2008


Author: enrico
Date: 2008-10-19 09:30:04 +0000 (Sun, 19 Oct 2008)
New Revision: 5698

Modified:
   xfce4-dict/trunk/ChangeLog
   xfce4-dict/trunk/lib/common.c
   xfce4-dict/trunk/lib/dictd.c
   xfce4-dict/trunk/lib/gui.c
   xfce4-dict/trunk/lib/gui.h
Log:
Add support for links (cross-references) in dictd responses.

Modified: xfce4-dict/trunk/ChangeLog
===================================================================
--- xfce4-dict/trunk/ChangeLog	2008-10-19 09:30:01 UTC (rev 5697)
+++ xfce4-dict/trunk/ChangeLog	2008-10-19 09:30:04 UTC (rev 5698)
@@ -1,3 +1,8 @@
+2008-10-15  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>
+
+ * Add support for links (cross-references) in dictd responses.
+
+
 2008-10-14  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>
 
  * Beautify the texview output a little bit.

Modified: xfce4-dict/trunk/lib/common.c
===================================================================
--- xfce4-dict/trunk/lib/common.c	2008-10-19 09:30:01 UTC (rev 5697)
+++ xfce4-dict/trunk/lib/common.c	2008-10-19 09:30:04 UTC (rev 5698)
@@ -365,6 +365,8 @@
 {
 	dict_write_rc_file(dd);
 
+	dict_gui_finalize(dd);
+
 	gtk_widget_destroy(dd->window);
 
 	g_free(dd->searched_word);

Modified: xfce4-dict/trunk/lib/dictd.c
===================================================================
--- xfce4-dict/trunk/lib/dictd.c	2008-10-19 09:30:01 UTC (rev 5697)
+++ xfce4-dict/trunk/lib/dictd.c	2008-10-19 09:30:04 UTC (rev 5698)
@@ -101,14 +101,78 @@
 }
 
 
+static GtkTextTag *create_tag(DictData *dd, const gchar *link_str)
+{
+	static GdkColor *link_color = NULL;
+	static GdkColor default_link_color = { 0, 0, 0, 0xeeee };
+	GtkTextTag *tag;
+
+	if (link_color == NULL)
+	{
+		gtk_widget_style_get(GTK_WIDGET(dd->main_textview), "link-color", &link_color, NULL);
+		if (link_color == NULL)
+			link_color = &default_link_color;
+	}
+
+	tag = gtk_text_buffer_create_tag(dd->main_textbuffer, NULL,
+		"underline", PANGO_UNDERLINE_SINGLE,
+		"foreground-gdk", link_color, NULL);
+
+	g_object_set_data_full(G_OBJECT(tag), "link", g_strdup(link_str), g_free);
+
+	return tag;
+}
+
+
+static void parse_line(DictData *dd, GString *buffer)
+{
+	gchar *start;
+	gchar *end;
+	gsize len;
+	GtkTextTag *tag;
+	gchar *found_link;
+
+	while (buffer->len > 0)
+	{
+		start = strchr(buffer->str, '{');
+		len = 0;
+
+		if (start == NULL)
+		{	/* no links at all, so add the text and go */
+			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, buffer->str, buffer->len);
+			return;
+		}
+		/* get length of text *before* the next '{' */
+		while (len < buffer->len && (buffer->str + len) != start)
+			len++;
+
+		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, buffer->str, len);
+		len++; /* skip the '{' */
+		g_string_erase(buffer, 0, len); /* remove already added text */
+
+		end = strchr(buffer->str, '}');
+		len = end - buffer->str; /* length of the link */
+		found_link = g_strndup(buffer->str, len);
+
+		tag = create_tag(dd, found_link);
+		gtk_text_buffer_insert_with_tags(dd->main_textbuffer, &dd->textiter,
+			buffer->str, len, tag, NULL);
+
+		g_free(found_link);
+		g_string_erase(buffer, 0, len + 1); /* remove already added text */
+	}
+}
+
+
 static gboolean process_server_response(DictData *dd)
 {
 	gint max_lines, i;
 	gint defs_found = 0;
-	gboolean first_line;
-	gchar *answer, *tmp, *stripped;
+	gchar *answer, *tmp;
 	gchar **lines, **dict_parts;
+	GString *body = g_string_sized_new(256);
 
+
 	if (dd->query_status == NO_CONNECTION)
 	{
 		dict_gui_status_add(dd, _("Could not connect to server."));
@@ -222,7 +286,6 @@
 
 		/* all following lines represents the translation */
 		i++;
-		first_line = TRUE;
 		while (lines[i] != NULL && lines[i][0] != '\r' && lines[i][0] != '\n')
 		{
 			/* check for a leading period indicating end of text response */
@@ -236,29 +299,20 @@
 				else
 					break; /* we reached the end of the test response */
 			}
-			stripped = g_strstrip(lines[i]);
-			if (strlen(stripped) > 0)
-			{
-				if (first_line)
-				{	/* do not indent the first line */
-					gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, stripped, -1);
-					first_line = FALSE;
-				}
-				else
-				{
-					gtk_text_buffer_insert_with_tags_by_name(dd->main_textbuffer, &dd->textiter,
-						stripped, -1, "indent", NULL);
-				}
-				if (i < (max_lines - 1) && lines[i + 1][0] != '.')
-					gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, "\n", 1);
-			}
+			g_string_append(body, lines[i]);
+			g_string_append_c(body, '\n');
+
 			i++;
 		}
+		parse_line(dd, body);
 		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, "\n\n", 2);
+		g_string_erase(body, 0, -1);
 	}
 	g_strfreev(lines);
 	g_free(dd->query_buffer);
 
+	g_string_free(body, TRUE);
+
 	return FALSE;
 }
 

Modified: xfce4-dict/trunk/lib/gui.c
===================================================================
--- xfce4-dict/trunk/lib/gui.c	2008-10-19 09:30:01 UTC (rev 5697)
+++ xfce4-dict/trunk/lib/gui.c	2008-10-19 09:30:04 UTC (rev 5698)
@@ -36,6 +36,159 @@
 
 
 
+static gboolean hovering_over_link = FALSE;
+static GdkCursor *hand_cursor = NULL;
+static GdkCursor *regular_cursor = NULL;
+
+
+/* all textview_* functions are from the gtk-demo app to get links in the textview working */
+static void textview_follow_if_link(GtkWidget *text_view, GtkTextIter *iter, DictData *dd)
+{
+	GSList *tags = NULL, *tagp = NULL;
+
+	tags = gtk_text_iter_get_tags(iter);
+	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
+	{
+		GtkTextTag *tag = tagp->data;
+		gchar *found_link;
+
+		found_link = g_object_get_data(G_OBJECT(tag), "link");
+		if (found_link != NULL)
+		{
+			gtk_entry_set_text(GTK_ENTRY(dd->main_entry), found_link);
+			dict_search_word(dd, found_link);
+
+			break;
+		}
+	}
+	if (tags)
+		g_slist_free(tags);
+}
+
+
+static gboolean textview_key_press_event(GtkWidget *text_view, GdkEventKey *event, DictData *dd)
+{
+	GtkTextIter iter;
+	GtkTextBuffer *buffer;
+
+	switch (event->keyval)
+	{
+		case GDK_Return:
+		case GDK_KP_Enter:
+		{
+			buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
+			gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
+			textview_follow_if_link(text_view, &iter, dd);
+			break;
+		}
+		default:
+			break;
+	}
+
+	return FALSE;
+}
+
+
+static gboolean textview_event_after(GtkWidget *text_view, GdkEvent *ev, DictData *dd)
+{
+	GtkTextIter start, end, iter;
+	GtkTextBuffer *buffer;
+	GdkEventButton *event;
+	gint x, y;
+
+	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(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);
+
+	textview_follow_if_link(text_view, &iter, dd);
+
+	return FALSE;
+}
+
+
+static void textview_set_cursor_if_appropriate(GtkTextView *text_view, gint x, gint y)
+{
+	GSList *tags = NULL, *tagp = NULL;
+	GtkTextIter iter;
+	gboolean hovering = FALSE;
+
+	gtk_text_view_get_iter_at_location(text_view, &iter, x, y);
+
+	tags = gtk_text_iter_get_tags(&iter);
+	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
+	{
+		GtkTextTag *tag = tagp->data;
+
+		if (g_object_get_data(G_OBJECT(tag), "link") != NULL)
+		{
+			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(
+				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 (tags)
+		g_slist_free(tags);
+}
+
+
+static gboolean textview_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);
+
+	textview_set_cursor_if_appropriate(GTK_TEXT_VIEW(text_view), x, y);
+
+	gdk_window_get_pointer(text_view->window, NULL, NULL, NULL);
+
+	return FALSE;
+}
+
+
+static gboolean textview_visibility_notify_event(GtkWidget *text_view, GdkEventVisibility *event)
+{
+	gint wx, wy, bx, by;
+
+	gdk_window_get_pointer(text_view->window, &wx, &wy, NULL);
+
+	gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(text_view),
+		GTK_TEXT_WINDOW_WIDGET, wx, wy, &bx, &by);
+
+	textview_set_cursor_if_appropriate(GTK_TEXT_VIEW(text_view), bx, by);
+
+	return FALSE;
+}
+
+
 void dict_gui_set_panel_entry_text(DictData *dd, const gchar *text)
 {
 	if (dd->panel_entry != NULL)
@@ -177,6 +330,16 @@
 }
 
 
+void dict_gui_finalize(DictData *dd)
+{
+	if (hand_cursor)
+		gdk_cursor_unref(hand_cursor);
+
+	if (regular_cursor)
+		gdk_cursor_unref(regular_cursor);
+}
+
+
 void dict_gui_create_main_window(DictData *dd)
 {
 	GtkWidget *main_box;
@@ -188,6 +351,7 @@
 	dd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 	gtk_window_set_title(GTK_WINDOW(dd->window), _("Xfce4 Dictionary"));
 	gtk_window_set_default_size(GTK_WINDOW(dd->window), 500, 300);
+	gtk_widget_set_name(dd->window, "Xfce4Dict");
 
 	icon = gdk_pixbuf_new_from_inline(-1, dict_icon_data, FALSE, NULL);
 	gtk_window_set_icon(GTK_WINDOW(dd->window), icon);
@@ -289,6 +453,7 @@
 
 	/* searched words textview stuff */
 	dd->main_textview = gtk_text_view_new();
+	gtk_widget_set_name(dd->window, "Xfce4DictTextView");
 	gtk_text_view_set_editable(GTK_TEXT_VIEW(dd->main_textview), FALSE);
 	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(dd->main_textview), 5);
 	gtk_text_view_set_right_margin(GTK_TEXT_VIEW(dd->main_textview), 5);
@@ -298,10 +463,24 @@
 			"bold",
 			"weight", PANGO_WEIGHT_BOLD,
 			"style", PANGO_STYLE_ITALIC,
+			"indent", 10,
 			"pixels-below-lines", 3, NULL);
-	gtk_text_buffer_create_tag(dd->main_textbuffer,
-			"indent", "indent", 10, NULL);
 
+	/* support for links (cross-references) for dictd responses */
+	{
+		hand_cursor = gdk_cursor_new(GDK_HAND2);
+		regular_cursor = gdk_cursor_new(GDK_XTERM);
+
+		g_signal_connect(dd->main_textview, "key-press-event",
+			G_CALLBACK(textview_key_press_event), dd);
+		g_signal_connect(dd->main_textview, "event-after",
+			G_CALLBACK(textview_event_after), dd);
+		g_signal_connect(dd->main_textview, "motion-notify-event",
+			G_CALLBACK(textview_motion_notify_event), NULL);
+		g_signal_connect(dd->main_textview, "visibility-notify-event",
+			G_CALLBACK(textview_visibility_notify_event), NULL);
+	}
+
 	gtk_widget_show(dd->main_textview);
 	gtk_container_add(GTK_CONTAINER(scrolledwindow_results), dd->main_textview);
 
@@ -312,7 +491,7 @@
 
 	/* DnD */
 	g_signal_connect(dd->main_entry, "drag-data-received", G_CALLBACK(dict_drag_data_received), dd);
-	/* TODO: find a way to get this working, the treeview doesn't receive anything as long as it isn't
+	/* TODO: find a way to get this working, the textview doesn't receive anything as long as it isn't
 	 * editable. scrolledwindow_results and a surrounding event box as receivers also don't work. */
 	g_signal_connect(dd->main_textview, "drag-data-received", G_CALLBACK(dict_drag_data_received), dd);
 

Modified: xfce4-dict/trunk/lib/gui.h
===================================================================
--- xfce4-dict/trunk/lib/gui.h	2008-10-19 09:30:01 UTC (rev 5697)
+++ xfce4-dict/trunk/lib/gui.h	2008-10-19 09:30:04 UTC (rev 5698)
@@ -29,6 +29,7 @@
 void dict_gui_set_panel_entry_text(DictData *dd, const gchar *text);
 void dict_gui_show_main_window(DictData *dd);
 void dict_gui_query_geometry(DictData *dd);
+void dict_gui_finalize(DictData *dd);
 const guint8 *dict_gui_get_icon_data(void);
 
 




More information about the Goodies-commits mailing list