summary refs log tree commit diff stats
path: root/src/fe-gtk
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-gtk')
-rw-r--r--src/fe-gtk/makefile.mak2
-rw-r--r--src/fe-gtk/sexy-iso-codes.c301
-rw-r--r--src/fe-gtk/sexy-iso-codes.h37
-rw-r--r--src/fe-gtk/sexy-marshal.c129
-rw-r--r--src/fe-gtk/sexy-marshal.h28
-rw-r--r--src/fe-gtk/sexy-spell-entry.c27
6 files changed, 503 insertions, 21 deletions
diff --git a/src/fe-gtk/makefile.mak b/src/fe-gtk/makefile.mak
index f210181a..27922405 100644
--- a/src/fe-gtk/makefile.mak
+++ b/src/fe-gtk/makefile.mak
@@ -25,6 +25,8 @@ rawlog.obj \
 search.obj \
 servlistgui.obj \
 setup.obj \
+sexy-iso-codes.obj \
+sexy-marshal.obj \
 sexy-spell-entry.obj \
 textgui.obj \
 urlgrab.obj \
diff --git a/src/fe-gtk/sexy-iso-codes.c b/src/fe-gtk/sexy-iso-codes.c
new file mode 100644
index 00000000..3477cc30
--- /dev/null
+++ b/src/fe-gtk/sexy-iso-codes.c
@@ -0,0 +1,301 @@
+/*
+ *  Copyright (C) 2005 Nathan Fredrickson
+ *  Borrowed from Galeon, renamed, and simplified to only use iso-codes with no
+ *  fallback method.
+ *
+ *  Copyright (C) 2004 Christian Persch
+ *  Copyright (C) 2004 Crispin Flowerday
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include "../../config.h"
+
+#include "sexy-iso-codes.h"
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#include <libxml/xmlreader.h>
+
+static GHashTable *iso_639_table = NULL;
+static GHashTable *iso_3166_table = NULL;
+
+#define ISO_639_DOMAIN	"iso_639"
+#define ISO_3166_DOMAIN	"iso_3166"
+
+#ifdef HAVE_ISO_CODES
+
+#define ISOCODESLOCALEDIR "/share/locale"
+
+static void
+read_iso_639_entry (xmlTextReaderPtr reader,
+		    GHashTable *table)
+{
+	xmlChar *code, *name;
+
+	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
+	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
+
+	/* Get iso-639-2 code */
+	if (code == NULL || code[0] == '\0')
+	{
+		xmlFree (code);
+		/* FIXME: use the 2T or 2B code? */
+		code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
+	}
+
+	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
+	{
+		g_hash_table_insert (table, code, name);
+	}
+	else
+	{
+		xmlFree (code);
+		xmlFree (name);
+	}
+}
+
+static void
+read_iso_3166_entry (xmlTextReaderPtr reader,
+		     GHashTable *table)
+{
+	xmlChar *code, *name;
+
+	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
+	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
+
+	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
+	{
+		char *lcode;
+
+		lcode = g_ascii_strdown ((char *) code, -1);
+		xmlFree (code);
+
+		g_hash_table_insert (table, lcode, name);
+	}
+	else
+	{
+		xmlFree (code);
+		xmlFree (name);
+	}
+
+}
+
+typedef enum
+{
+	STATE_START,
+	STATE_STOP,
+	STATE_ENTRIES,
+} ParserState;
+
+static gboolean
+load_iso_entries (int iso,
+		  GFunc read_entry_func,
+		  gpointer user_data)
+{
+	xmlTextReaderPtr reader;
+	ParserState state = STATE_START;
+	xmlChar iso_entries[32], iso_entry[32];
+	char *filename;
+	int ret = -1;
+
+	filename = g_strdup_printf (".\\share\\xml\\iso-codes\\iso_%d.xml", iso);
+	reader = xmlNewTextReaderFilename (filename);
+	if (reader == NULL) goto out;
+
+	xmlStrPrintf (iso_entries, sizeof (iso_entries),
+				  (xmlChar *)"iso_%d_entries", iso);
+	xmlStrPrintf (iso_entry, sizeof (iso_entry),
+				  (xmlChar *)"iso_%d_entry", iso);
+
+	ret = xmlTextReaderRead (reader);
+
+	while (ret == 1)
+	{
+		const xmlChar *tag;
+		xmlReaderTypes type;
+
+		tag = xmlTextReaderConstName (reader);
+		type = xmlTextReaderNodeType (reader);
+
+		if (state == STATE_ENTRIES &&
+		    type == XML_READER_TYPE_ELEMENT &&
+		    xmlStrEqual (tag, iso_entry))
+		{
+			read_entry_func (reader, user_data);
+		}
+		else if (state == STATE_START &&
+			 type == XML_READER_TYPE_ELEMENT &&
+			 xmlStrEqual (tag, iso_entries))
+		{
+			state = STATE_ENTRIES;
+		}
+		else if (state == STATE_ENTRIES &&
+			 type == XML_READER_TYPE_END_ELEMENT &&
+			 xmlStrEqual (tag, iso_entries))
+		{
+			state = STATE_STOP;
+		}
+		else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
+			 type == XML_READER_TYPE_WHITESPACE ||
+			 type == XML_READER_TYPE_TEXT ||
+			 type == XML_READER_TYPE_COMMENT)
+		{
+			/* eat it */
+		}
+		else
+		{
+			/* ignore it */
+		}
+
+		ret = xmlTextReaderRead (reader);
+	}
+
+	xmlFreeTextReader (reader);
+
+out:
+	if (ret < 0 || state != STATE_STOP)
+	{
+		/* This is not critical, we will fallback to our own code */
+		g_free (filename);
+		return FALSE;
+	}
+
+	g_free (filename);
+
+	return TRUE;
+}
+
+#endif /* HAVE_ISO_CODES */
+
+
+static void
+ensure_iso_codes_initialised (void)
+{
+	static gboolean initialised = FALSE;
+
+	if (initialised == TRUE)
+	{
+		return;
+	}
+	initialised = TRUE;
+
+#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
+	bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR);
+	bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
+
+	bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR);
+	bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
+#endif
+
+	iso_639_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+					       (GDestroyNotify) xmlFree,
+					       (GDestroyNotify) xmlFree);
+
+	iso_3166_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+						(GDestroyNotify) g_free,
+						(GDestroyNotify) xmlFree);
+	
+#ifdef HAVE_ISO_CODES
+	load_iso_entries (639, (GFunc) read_iso_639_entry, iso_639_table);
+	load_iso_entries (3166, (GFunc) read_iso_3166_entry, iso_3166_table);
+#endif
+}
+
+
+static char *
+get_iso_name_for_lang_code (const char *code)
+{
+	char **str;
+	char *name = NULL;
+	const char *langname, *localename;
+	int len;
+
+	str = g_strsplit (code, "_", -1);
+
+	/* count the entries */
+	for (len = 0; str[len]; len++ ) /* empty */;
+
+	g_return_val_if_fail (len != 0, NULL);
+
+	langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);
+
+	if (len == 1 && langname != NULL)
+	{
+		name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
+	}
+	else if (len == 2 && langname != NULL)
+	{
+		localename = (const char *) g_hash_table_lookup (iso_3166_table, str[1]);
+
+		if (localename != NULL)
+		{
+			/* translators: the first %s is the language name, and the
+			 * second %s is the locale name. Example:
+			 * "French (France)
+			 *
+			 * Also: The text before the "|" is context to help you decide on
+                         * the correct translation. You MUST OMIT it in the translated string.
+			 */
+			name = g_strdup_printf (Q_("language|%s (%s)"),
+						dgettext (ISO_639_DOMAIN, langname),
+						dgettext (ISO_3166_DOMAIN, localename));
+		}
+		else
+		{
+			name = g_strdup_printf (Q_("language|%s (%s)"),
+						dgettext (ISO_639_DOMAIN, langname), str[1]);
+		}
+	}
+
+	g_strfreev (str);
+
+	return name;
+}
+
+/**
+ * gtkspell_iso_codes_lookup_name_for_code:
+ * @code: A language code, e.g. en_CA
+ *
+ * Looks up a name to display to the user for a language code,
+ * this might use the iso-codes package if support was compiled
+ * in, and it is available
+ *
+ * Returns: the UTF-8 string to display to the user, or NULL if 
+ * a name for the code could not be found
+ */
+char *
+gtkspell_iso_codes_lookup_name_for_code (const char *code)
+{
+	char * lcode;
+	char * ret;
+
+	g_return_val_if_fail (code != NULL, NULL);
+
+	ensure_iso_codes_initialised ();
+
+	lcode = g_ascii_strdown (code, -1);
+
+	ret = get_iso_name_for_lang_code (lcode);
+
+	g_free (lcode);
+
+	return ret;
+}
+
diff --git a/src/fe-gtk/sexy-iso-codes.h b/src/fe-gtk/sexy-iso-codes.h
new file mode 100644
index 00000000..e5f37162
--- /dev/null
+++ b/src/fe-gtk/sexy-iso-codes.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2005 Nathan Fredrickson
+ *  Borrowed from Galeon, renamed, and simplified to only use iso-codes with no
+ *  fallback method.
+ *
+ *  Copyright (C) 2004 Christian Persch
+ *  Copyright (C) 2004 Crispin Flowerday
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef GTKSPELL_ISO_CODES_H
+#define GTKSPELL_ISO_CODES_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+char *  gtkspell_iso_codes_lookup_name_for_code (const char *code);
+
+G_END_DECLS
+
+#endif
diff --git a/src/fe-gtk/sexy-marshal.c b/src/fe-gtk/sexy-marshal.c
new file mode 100644
index 00000000..10a629f2
--- /dev/null
+++ b/src/fe-gtk/sexy-marshal.c
@@ -0,0 +1,129 @@
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:STRING (./marshal.list:1) */
+void
+sexy_marshal_BOOLEAN__STRING (GClosure     *closure,
+                              GValue       *return_value,
+                              guint         n_param_values,
+                              const GValue *param_values,
+                              gpointer      invocation_hint,
+                              gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__STRING) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     data2);
+  register GMarshalFunc_BOOLEAN__STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__STRING) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_string (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* OBJECT:OBJECT,OBJECT (./marshal.list:2) */
+void
+sexy_marshal_OBJECT__OBJECT_OBJECT (GClosure     *closure,
+                                    GValue       *return_value,
+                                    guint         n_param_values,
+                                    const GValue *param_values,
+                                    gpointer      invocation_hint,
+                                    gpointer      marshal_data)
+{
+  typedef GObject* (*GMarshalFunc_OBJECT__OBJECT_OBJECT) (gpointer     data1,
+                                                          gpointer     arg_1,
+                                                          gpointer     arg_2,
+                                                          gpointer     data2);
+  register GMarshalFunc_OBJECT__OBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  GObject* v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_OBJECT__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_object (param_values + 1),
+                       g_marshal_value_peek_object (param_values + 2),
+                       data2);
+
+  g_value_take_object (return_value, v_return);
+}
+
diff --git a/src/fe-gtk/sexy-marshal.h b/src/fe-gtk/sexy-marshal.h
new file mode 100644
index 00000000..f41eccbe
--- /dev/null
+++ b/src/fe-gtk/sexy-marshal.h
@@ -0,0 +1,28 @@
+
+#ifndef __sexy_marshal_MARSHAL_H__
+#define __sexy_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* BOOLEAN:STRING (./marshal.list:1) */
+extern void sexy_marshal_BOOLEAN__STRING (GClosure     *closure,
+                                          GValue       *return_value,
+                                          guint         n_param_values,
+                                          const GValue *param_values,
+                                          gpointer      invocation_hint,
+                                          gpointer      marshal_data);
+
+/* OBJECT:OBJECT,OBJECT (./marshal.list:2) */
+extern void sexy_marshal_OBJECT__OBJECT_OBJECT (GClosure     *closure,
+                                                GValue       *return_value,
+                                                guint         n_param_values,
+                                                const GValue *param_values,
+                                                gpointer      invocation_hint,
+                                                gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __sexy_marshal_MARSHAL_H__ */
+
diff --git a/src/fe-gtk/sexy-spell-entry.c b/src/fe-gtk/sexy-spell-entry.c
index 6bc4f0b5..4977a567 100644
--- a/src/fe-gtk/sexy-spell-entry.c
+++ b/src/fe-gtk/sexy-spell-entry.c
@@ -30,8 +30,8 @@
 #include <glib/gi18n.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-/*#include "gtkspell-iso-codes.h"
-#include "sexy-marshal.h"*/
+#include "sexy-iso-codes.h"
+#include "sexy-marshal.h"
 
 #include "typedef.h"
 
@@ -211,14 +211,14 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass)
 	 * Returns: %FALSE to indicate that the word should be marked as
 	 * correct.
 	 */
-/*	signals[WORD_CHECK] = g_signal_new("word_check",
+	signals[WORD_CHECK] = g_signal_new("word_check",
 					   G_TYPE_FROM_CLASS(object_class),
 					   G_SIGNAL_RUN_LAST,
 					   G_STRUCT_OFFSET(SexySpellEntryClass, word_check),
 					   (GSignalAccumulator) spell_accumulator, NULL,
 					   sexy_marshal_BOOLEAN__STRING,
 					   G_TYPE_BOOLEAN,
-					   1, G_TYPE_STRING);*/
+					   1, G_TYPE_STRING);
 }
 
 static void
@@ -495,10 +495,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 	if (entry->priv->dict_list == NULL)
 		return topmenu;
 
-#if 1
-	dict = (struct EnchantDict *) entry->priv->dict_list->data;
-	build_suggestion_menu(entry, topmenu, dict, word);
-#else
 	/* Suggestions */
 	if (g_slist_length(entry->priv->dict_list) == 1) {
 		dict = (struct EnchantDict *) entry->priv->dict_list->data;
@@ -527,7 +523,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 			build_suggestion_menu(entry, menu, dict, word);
 		}
 	}
-#endif
 
 	/* Separator */
 	mi = gtk_separator_menu_item_new ();
@@ -541,11 +536,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 
 	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
 
-#if 1
-	dict = (struct EnchantDict *) entry->priv->dict_list->data;
-	g_object_set_data(G_OBJECT(mi), "enchant-dict", dict);
-	g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(add_to_dictionary), entry);
-#else
 	if (g_slist_length(entry->priv->dict_list) == 1) {
 		dict = (struct EnchantDict *) entry->priv->dict_list->data;
 		g_object_set_data(G_OBJECT(mi), "enchant-dict", dict);
@@ -577,7 +567,6 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word)
 			gtk_menu_shell_append(GTK_MENU_SHELL(menu), submi);
 		}
 	}
-#endif
 
 	gtk_widget_show_all(mi);
 	gtk_menu_shell_append(GTK_MENU_SHELL(topmenu), mi);
@@ -759,11 +748,7 @@ word_misspelled(SexySpellEntry *entry, int start, int end)
 
 	g_strlcpy(word, text + start, end - start + 1);
 
-#if 0
 	g_signal_emit(entry, signals[WORD_CHECK], 0, word, &ret);
-#else
-	ret = default_word_check (entry, word);
-#endif
 
 	g_free(word);
 	return ret;
@@ -1121,8 +1106,8 @@ gchar *
 sexy_spell_entry_get_language_name(const SexySpellEntry *entry,
 								   const gchar *lang)
 {
-	/*if (have_enchant)
-		return gtkspell_iso_codes_lookup_name_for_code(lang);*/
+	if (have_enchant)
+		return gtkspell_iso_codes_lookup_name_for_code(lang);
 	return NULL;
 }