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

Enrico Troeger enrico at xfce.org
Fri Oct 24 19:30:25 CEST 2008


Author: enrico
Date: 2008-10-24 17:30:25 +0000 (Fri, 24 Oct 2008)
New Revision: 5793

Modified:
   xfce4-dict/trunk/ChangeLog
   xfce4-dict/trunk/lib/dictd.c
   xfce4-dict/trunk/lib/gui.c
Log:
When highlighting cross-references, ignore short ones like {n}, {f} and {m} as often found in translation dictionaries.
Highlight phonetic information provided by some dictionaries.

Modified: xfce4-dict/trunk/ChangeLog
===================================================================
--- xfce4-dict/trunk/ChangeLog	2008-10-24 17:30:22 UTC (rev 5792)
+++ xfce4-dict/trunk/ChangeLog	2008-10-24 17:30:25 UTC (rev 5793)
@@ -3,6 +3,9 @@
  * Bring the 'Search Term' string back, this time in the search
    entry to get auto cleared on click.
  * Use for the panel text entry also a SexyIconEntry.
+ * When highlighting cross-references, ignore short ones like
+   {n}, {f} and {m} as often found in translation dictionaries.
+ * Highlight phonetic information provided by some dictionaries.
 
 
 2008-10-19  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>

Modified: xfce4-dict/trunk/lib/dictd.c
===================================================================
--- xfce4-dict/trunk/lib/dictd.c	2008-10-24 17:30:22 UTC (rev 5792)
+++ xfce4-dict/trunk/lib/dictd.c	2008-10-24 17:30:25 UTC (rev 5793)
@@ -101,6 +101,66 @@
 }
 
 
+/* We parse the first line differently as there are usually no links
+ * but instead phonetic information */
+static void parse_header(DictData *dd, GString *buffer, GString *target)
+{
+	gchar *start;
+	gchar *end;
+	gsize len;
+	gchar end_char = '\\';
+
+	while (buffer->len > 0)
+	{
+		start = strchr(buffer->str, '\\');
+		len = 0;
+
+		if (start == NULL)
+		{
+			start = strchr(buffer->str, '['); /* alternative way of specifiying phonetics */
+			if (start != NULL)
+				end_char = ']';
+			else
+			{
+				/* no phonetics at all, so add the text to the body to get at least possible
+				 * links parsed and return */
+				g_string_prepend(target, buffer->str);
+				g_string_erase(buffer, 0, -1); /* remove already handled text */
+				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 handled text */
+
+		start = buffer->str; /* set new start */
+		end = strchr(start, end_char);
+		if (start > end)
+		{
+			/* slashes don't match, skip this part */
+			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter,
+				(end_char == ']') ? "\\" : "]", 1);
+			continue;
+		}
+		len = end - buffer->str; /* length of the link */
+
+		gtk_text_buffer_insert_with_tags_by_name(dd->main_textbuffer, &dd->textiter,
+				buffer->str, len, "phonetic", NULL);
+
+		/* we only highlight the first match, so add remaining add the remaining text
+		 * to the body to get at least possible links parsed and return */
+		g_string_prepend(target, buffer->str + len + 1);
+		g_string_erase(buffer, 0, -1); /* remove already handled text */
+
+		break;
+	}
+}
+
+
 static GtkTextTag *create_tag(DictData *dd, const gchar *link_str)
 {
 	static GdkColor *link_color = NULL;
@@ -124,8 +184,28 @@
 }
 
 
-static void parse_line(DictData *dd, GString *buffer)
+/* ignore links like {n} or {f} as they are often found in translation dictionaries and
+ * used for giving additional type information but not intended to link or reference something */
+static gboolean ignore_short_link(const gchar *str)
 {
+	if (str == NULL)
+		return TRUE;
+
+	/* ignore {n}, {f}, {m}  (surrounding braces are already stripped in 'str') */
+	if (strcmp("f", str) == 0 ||
+		strcmp("m", str) == 0 ||
+		strcmp("n", str) == 0)
+	{
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+/* Find any cross-references like {reference} and make them clickable */
+static void parse_body(DictData *dd, GString *buffer)
+{
 	gchar *start;
 	gchar *end;
 	gsize len;
@@ -148,9 +228,10 @@
 
 		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 */
+		g_string_erase(buffer, 0, len); /* remove already handled text */
 
-		end = strchr(buffer->str, '}');
+		start = buffer->str; /* set new start */
+		end = strchr(start, '}');
 		if (start > end)
 		{
 			/* braces don't match, skip this part, e.g. 'fd-deu-eng' returns
@@ -161,25 +242,106 @@
 		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);
-
+		/* ignore {n}, {f}, ... */
+		if (ignore_short_link(found_link))
+		{
+			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, "{", 1);
+			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, buffer->str, len);
+			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, "}", 1);
+		}
+		else
+		{
+			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 */
+		g_string_erase(buffer, 0, len + 1); /* remove already handled text */
 	}
 }
 
 
+static gint process_response_content(DictData *dd, gchar **lines, gint line_no, gint max_lines,
+									 GString *header, GString *body)
+{
+	gchar **dict_parts;
+	gboolean first_line;
+
+	line_no++;
+	if (strncmp(lines[line_no], "250", 3) == 0)
+		return max_lines; /* end of data */
+	if (strncmp(lines[line_no], "error:", 6) == 0) /* an error occurred */
+	{
+		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, lines[line_no], -1);
+		return max_lines;
+	}
+	if (strncmp(lines[line_no], "151", 3) != 0)
+		return line_no; /* unexpected line start, try next line */
+
+	/* get the used dictionary */
+	dict_parts = g_strsplit(lines[line_no], "\"", -1);
+
+	if (g_strv_length(dict_parts) > 3)
+	{	gtk_text_buffer_insert_with_tags_by_name(dd->main_textbuffer, &dd->textiter,
+			g_strstrip(dict_parts[3]), -1, "bold", NULL);
+
+		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, " (", 2);
+		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter,
+			g_strstrip(dict_parts[2]), -1);
+		gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, ")\n", 2);
+	}
+	g_strfreev(dict_parts);
+
+	if (line_no >= (max_lines - 2))
+		return max_lines;
+
+	/* all following lines represents the translation */
+	line_no++;
+	first_line = TRUE;
+
+	while (lines[line_no] != NULL && lines[line_no][0] != '\r' && lines[line_no][0] != '\n')
+	{
+		/* check for a leading period indicating end of text response */
+		if (lines[line_no][0] == '.')
+		{
+			/* a double period at line start is a masked period, cf. RFC 2229 */
+			if (strlen(lines[line_no]) > 1 && lines[line_no][1] == '.')
+				/* the RFC says we should coolapse the two periods into one but we go the
+				 * lazy way and simply replace the first period by a space */
+				lines[line_no][0] = ' ';
+			else
+				break; /* we reached the end of the test response */
+		}
+		if (first_line)
+		{
+			g_string_append(header, lines[line_no]);
+			first_line = FALSE;
+		}
+		else
+			g_string_append(body, lines[line_no]);
+		g_string_append_c(body, '\n');
+
+		line_no++;
+	}
+	parse_header(dd, header, body);
+	parse_body(dd, body);
+	gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, "\n\n", 2);
+	g_string_erase(header, 0, -1);
+	g_string_erase(body, 0, -1);
+
+	return line_no;
+}
+
+
 static gboolean process_server_response(DictData *dd)
 {
 	gint max_lines, i;
 	gint defs_found = 0;
 	gchar *answer, *tmp;
-	gchar **lines, **dict_parts;
-	GString *body = g_string_sized_new(256);
+	gchar **lines;
+	GString *header = g_string_sized_new(256);
+	GString *body = g_string_sized_new(512);
 
-
 	switch (dd->query_status)
 	{
 		case NO_CONNECTION:
@@ -247,7 +409,8 @@
                                      defs_found), defs_found);
 
 	/* go to next line */
-	while (*answer != '\n') answer++;
+	while (*answer != '\n')
+		answer++;
 	answer++;
 
 	/* parse output */
@@ -265,61 +428,12 @@
 	i = -1;
 	while (i < max_lines)
 	{
-		i++;
-		if (strncmp(lines[i], "250", 3) == 0)
-			break; /* end of data */
-		if (strncmp(lines[i], "error:", 6) == 0) /* an error occurred */
-		{
-			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, lines[i], -1);
-			break;
-		}
-		if (strncmp(lines[i], "151", 3) != 0)
-			continue; /* unexpected line start, try next line */
-
-		/* get the used dictionary */
-		dict_parts = g_strsplit(lines[i], "\"", -1);
-
-		if (g_strv_length(dict_parts) > 3)
-		{	gtk_text_buffer_insert_with_tags_by_name(dd->main_textbuffer, &dd->textiter,
-				g_strstrip(dict_parts[3]), -1, "bold", NULL);
-
-			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, " (", 2);
-			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter,
-				g_strstrip(dict_parts[2]), -1);
-			gtk_text_buffer_insert(dd->main_textbuffer, &dd->textiter, ")\n", 2);
-		}
-		g_strfreev(dict_parts);
-
-		if (i >= (max_lines - 2))
-			break;
-
-		/* all following lines represents the translation */
-		i++;
-		while (lines[i] != NULL && lines[i][0] != '\r' && lines[i][0] != '\n')
-		{
-			/* check for a leading period indicating end of text response */
-			if (lines[i][0] == '.')
-			{
-				/* a double period at line start is a masked period, cf. RFC 2229 */
-				if (strlen(lines[i]) > 1 && lines[i][1] == '.')
-					/* the RFC says we should coolapse the two periods into one but we go the
-					 * lazy way and simply replace the first period by a space */
-					lines[i][0] = ' ';
-				else
-					break; /* we reached the end of the test response */
-			}
-			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);
+		i = process_response_content(dd, lines, i, max_lines, header, body);
 	}
 	g_strfreev(lines);
 	g_free(dd->query_buffer);
 
+	g_string_free(header, TRUE);
 	g_string_free(body, TRUE);
 
 	return FALSE;

Modified: xfce4-dict/trunk/lib/gui.c
===================================================================
--- xfce4-dict/trunk/lib/gui.c	2008-10-24 17:30:22 UTC (rev 5792)
+++ xfce4-dict/trunk/lib/gui.c	2008-10-24 17:30:25 UTC (rev 5793)
@@ -41,6 +41,8 @@
 static GdkCursor *hand_cursor = NULL;
 static GdkCursor *regular_cursor = NULL;
 static gboolean entry_is_dirty = FALSE;
+/** TODO make colours (phonecitc, link colour) configurable */
+static const GdkColor phon_color = { 0, 0, 0x6363, 0 };
 
 
 /* all textview_* functions are from the gtk-demo app to get links in the textview working */
@@ -498,6 +500,7 @@
 	gtk_widget_show(label);
 	gtk_box_pack_start(GTK_BOX(method_chooser), label, FALSE, FALSE, 6);
 
+	/* TODO: add mnemonics, add 'Search $web_dictionary link when nothing found */
 	radio = gtk_radio_button_new_with_label(NULL, _("Dict"));
 	gtk_widget_show(radio);
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), (dd->mode_in_use == DICTMODE_DICT));
@@ -539,7 +542,11 @@
 			"weight", PANGO_WEIGHT_BOLD,
 			"style", PANGO_STYLE_ITALIC,
 			"indent", 10,
-			"pixels-below-lines", 3, NULL);
+			"pixels-below-lines", 5, NULL);
+	gtk_text_buffer_create_tag(dd->main_textbuffer,
+		"phonetic",
+		"style", PANGO_STYLE_ITALIC,
+		"foreground-gdk", &phon_color, NULL);
 
 	/* support for links (cross-references) for dictd responses */
 	{




More information about the Goodies-commits mailing list