[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