spell checker support for multiple languages

This commit is contained in:
berkeviktor@aol.com
2011-08-07 13:41:43 +02:00
parent 19b7e2f062
commit 08e5778b19
12 changed files with 4379 additions and 22 deletions

View File

@@ -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 \

301
src/fe-gtk/sexy-iso-codes.c Normal file
View File

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

View File

@@ -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

129
src/fe-gtk/sexy-marshal.c Normal file
View File

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

28
src/fe-gtk/sexy-marshal.h Normal file
View File

@@ -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__ */

View File

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

View File

@@ -9,7 +9,7 @@ LIBS = $(LIBS) gdi32.lib shell32.lib user32.lib advapi32.lib imm32.lib ole32.lib
GLIB = /I$(DEV)\include\glib-2.0 /I$(DEV)\lib\glib-2.0\include
GTK = /I$(DEV)\include\gtk-2.0 /I$(DEV)\lib\gtk-2.0\include /I$(DEV)\include\atk-1.0 /I$(DEV)\include\cairo /I$(DEV)\include\pango-1.0 /I$(DEV)\include\gdk-pixbuf-2.0
LIBS = $(LIBS) /libpath:$(DEV)\lib gtk-win32-2.0.lib gdk-win32-2.0.lib atk-1.0.lib gio-2.0.lib gdk_pixbuf-2.0.lib pangowin32-1.0.lib pangocairo-1.0.lib pango-1.0.lib cairo.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib intl.lib
LIBS = $(LIBS) /libpath:$(DEV)\lib gtk-win32-2.0.lib gdk-win32-2.0.lib atk-1.0.lib gio-2.0.lib gdk_pixbuf-2.0.lib pangowin32-1.0.lib pangocairo-1.0.lib pango-1.0.lib cairo.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib intl.lib libxml2.lib
LUALIB = lua51
LUAOUTPUT = xclua.dll