diff options
author | Sergey Udaltsov <svu@gnome.org> | 2008-04-21 22:37:33 +0000 |
---|---|---|
committer | Sergey Udaltsov <svu@gnome.org> | 2008-04-21 22:37:33 +0000 |
commit | 068422e3a7a0aae5983cde5d57ce18e4fb5fa560 (patch) | |
tree | 10a9b45adc0bed36315c118235189d1587a78720 | |
parent | ae1528e30b7e0a50660a1c69e03b077ad1010dd9 (diff) | |
download | libxklavier-068422e3a7a0aae5983cde5d57ce18e4fb5fa560.tar.gz |
adding country/language functions, new dep on iso-codes
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | libxklavier/Makefile.am | 2 | ||||
-rw-r--r-- | libxklavier/xkl_config_registry.h | 67 | ||||
-rw-r--r-- | libxklavier/xklavier_config.c | 22 | ||||
-rw-r--r-- | libxklavier/xklavier_config_iso.c | 291 | ||||
-rw-r--r-- | libxklavier/xklavier_private.h | 32 | ||||
-rw-r--r-- | tests/test_config.c | 23 |
8 files changed, 441 insertions, 22 deletions
@@ -1,3 +1,11 @@ +2008-04-21 svu + + * configure.in, libxklavier/Makefile.am, + libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, + libxklavier/xklavier_config_iso.c, libxklavier/xklavier_private.h, + tests/test_config.c: adding country/language iteration functions, + introducing dependency on iso-codes + 2008-04-15 svu * libxklavier/xkl_config_item.h, libxklavier/xklavier_config.c, diff --git a/configure.in b/configure.in index 62e974e..1000e10 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ PACKAGE=libxklavier MAJOR_VERSION=3 MINOR_VERSION=6 VERSION=$MAJOR_VERSION.$MINOR_VERSION -VERSION_INFO=12:0:0 +VERSION_INFO=13:0:1 AC_SUBST(MAJOR_VERSION) AC_SUBST(MINOR_VERSION) @@ -158,6 +158,22 @@ AC_SUBST(GLIB_CFLAGS) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) +dnl ----------------------------------------------------------- +dnl ISO codes +dnl ----------------------------------------------------------- +AC_MSG_CHECKING([whether iso-codes exists]) +if $PKG_CONFIG iso-codes > /dev/null ; then + AC_MSG_RESULT([yes]) + iso_codes_prefix=`$PKG_CONFIG --variable=prefix iso-codes` + iso_codes_pkgconfig=iso-codes + have_iso_codes=yes +else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([You must have iso-codes.]) +fi + +AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["$iso_codes_prefix"],[ISO codes prefix]) + AC_OUTPUT([ Makefile libxklavier/Makefile diff --git a/libxklavier/Makefile.am b/libxklavier/Makefile.am index 4b0181f..f0a7b39 100644 --- a/libxklavier/Makefile.am +++ b/libxklavier/Makefile.am @@ -39,7 +39,7 @@ xklavierincdir = $(includedir)/libxklavier xklavierinc_HEADERS = xklavier.h xkl_config_registry.h xkl_engine.h \ xkl_config_rec.h xkl_config_item.h xkl_engine_marshal.h -libxklavier_la_SOURCES = xklavier.c xklavier_evt.c xklavier_config.c \ +libxklavier_la_SOURCES = xklavier.c xklavier_evt.c xklavier_config.c xklavier_config_iso.c \ xklavier_xkb.c xklavier_evt_xkb.c xklavier_config_xkb.c xklavier_toplevel.c \ xklavier_xmm.c xklavier_xmm_opts.c xklavier_evt_xmm.c xklavier_config_xmm.c \ xklavier_util.c xklavier_props.c xklavier_dump.c xkl_engine_marshal.c \ diff --git a/libxklavier/xkl_config_registry.h b/libxklavier/xkl_config_registry.h index e45cc67..28e27c5 100644 --- a/libxklavier/xkl_config_registry.h +++ b/libxklavier/xkl_config_registry.h @@ -264,6 +264,73 @@ extern "C" { option_group_name, XklConfigItem * item); + +/** + * xkl_config_registry_foreach_country: + * @config: the config registry + * @func: callback to call for every ISO 3166 country code + * @data: anything which can be stored into the pointer + * + * Enumerates countries for which layouts are available, + * from the XML configuration registry + */ + extern void xkl_config_registry_foreach_country(XklConfigRegistry * + config, + ConfigItemProcessFunc + func, + gpointer data); + +/** + * xkl_config_registry_foreach_country_variant: + * @config: the config registry + * @country_code: country ISO code for which variants will be listed + * @func: callback to call for every country variant + * @data: anything which can be stored into the pointer + * + * Enumerates keyboard layout variants for the country, + * from the XML configuration registry + */ + extern void + xkl_config_registry_foreach_country_variant(XklConfigRegistry * + config, + const gchar * + country_code, + ConfigItemProcessFunc + func, gpointer data); + +/** + * xkl_config_registry_foreach_language: + * @config: the config registry + * @func: callback to call for every ISO 639-2 country code + * @data: anything which can be stored into the pointer + * + * Enumerates languages for which layouts are available, + * from the XML configuration registry + */ + extern void xkl_config_registry_foreach_language(XklConfigRegistry + * config, + ConfigItemProcessFunc + func, + gpointer data); + +/** + * xkl_config_registry_foreach_language_variant: + * @config: the config registry + * @language_code: language ISO code for which variants will be listed + * @func: callback to call for every country variant + * @data: anything which can be stored into the pointer + * + * Enumerates keyboard layout variants for the language, + * from the XML configuration registry + */ + extern void + xkl_config_registry_foreach_country_variant(XklConfigRegistry * + config, + const gchar * + language_code, + ConfigItemProcessFunc + func, gpointer data); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libxklavier/xklavier_config.c b/libxklavier/xklavier_config.c index 6bdcb07..661b58e 100644 --- a/libxklavier/xklavier_config.c +++ b/libxklavier/xklavier_config.c @@ -35,21 +35,6 @@ static xmlXPathCompExprPtr models_xpath; static xmlXPathCompExprPtr layouts_xpath; static xmlXPathCompExprPtr option_groups_xpath; - -#define XKBCR_MODEL_PATH "/xkbConfigRegistry/modelList/model" -#define XKBCR_LAYOUT_PATH "/xkbConfigRegistry/layoutList/layout" -#define XKBCR_VARIANT_PATH XKBCR_LAYOUT_PATH "/variantList/variant" -#define XKBCR_GROUP_PATH "/xkbConfigRegistry/optionList/group" -#define XKBCR_OPTION_PATH XKBCR_GROUP_PATH "/option" - -#define XML_TAG_DESCR "description" -#define XML_TAG_SHORT_DESCR "shortDescription" -#define XML_TAG_VENDOR "vendor" -#define XML_TAG_COUNTRY_LIST "countryList" -#define XML_TAG_LANGUAGE_LIST "languageList" -#define XML_TAG_ISO3166ID "iso3166Id" -#define XML_TAG_ISO639ID "iso639Id" - // gettext domain for translations #define XKB_DOMAIN "xkeyboard-config" @@ -58,9 +43,6 @@ enum { PROP_ENGINE, }; -#define xkl_config_registry_is_initialized(config) \ - ( xkl_config_registry_priv(config,xpath_context) != NULL ) - static gboolean xkl_xml_find_config_item_child(xmlNodePtr iptr, xmlNodePtr * ptr) { @@ -252,7 +234,7 @@ xkl_config_registry_foreach_in_nodeset(XklConfigRegistry * config, } } -static void +void xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, xmlXPathCompExprPtr xpath_comp_expr, @@ -275,7 +257,7 @@ xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, } } -static void +void xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry * config, const gchar * diff --git a/libxklavier/xklavier_config_iso.c b/libxklavier/xklavier_config_iso.c new file mode 100644 index 0000000..04434ab --- /dev/null +++ b/libxklavier/xklavier_config_iso.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org> + * + * 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 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 <errno.h> +#include <locale.h> +#include <libintl.h> +#include <stdio.h> +#include <string.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include "config.h" + +#include "xklavier_private.h" + +#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes" +#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale" + +static GHashTable *country_code_names = NULL; +static GHashTable *lang_code_names = NULL; + +typedef struct { + const gchar *domain; + const gchar *attr_names[]; +} LookupParams; + +typedef struct { + GHashTable *code_names; + const gchar *tag_name; + LookupParams *params; +} CodeBuildStruct; + +static LookupParams countryLookup = { "iso_3166", {"alpha_2_code", NULL} }; +static LookupParams languageLookup = + { "iso_639", {"iso_639_2B_code", "iso_639_2T_code", NULL} }; + +static void +iso_codes_parse_start_tag(GMarkupParseContext * ctx, + const gchar * element_name, + const gchar ** attr_names, + const gchar ** attr_values, + gpointer user_data, GError ** error) +{ + const gchar *name; + const gchar **san = attr_names, **sav = attr_values; + CodeBuildStruct *cbs = (CodeBuildStruct *) user_data; + + /* Is this the tag we are looking for? */ + if (!g_str_equal(element_name, cbs->tag_name) || + attr_names == NULL || attr_values == NULL) { + return; + } + + name = NULL; + + /* What would be the value? */ + while (*attr_names && *attr_values) { + if (g_str_equal(*attr_names, "name")) { + name = *attr_values; + break; + } + + attr_names++; + attr_values++; + } + + if (!name) { + return; + } + + attr_names = san; + attr_values = sav; + + /* Walk again the attributes */ + while (*attr_names && *attr_values) { + const gchar **attr = cbs->params->attr_names; + /* Look through all the attributess we are interested in */ + while (*attr) { + if (g_str_equal(*attr_names, *attr)) { + if (**attr_values) { + g_hash_table_insert(cbs-> + code_names, + g_strdup + (*attr_values), + g_strdup + (name)); + } + } + attr++; + } + + attr_names++; + attr_values++; + } +} + +static GHashTable * +iso_code_names_init(LookupParams * params) +{ + GError *err = NULL; + gchar *buf, *filename, *tag_name; + gsize buf_len; + CodeBuildStruct cbs; + + GHashTable *ht = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + + tag_name = g_strdup_printf("%s_entry", params->domain); + + cbs.code_names = ht; + cbs.tag_name = tag_name; + cbs.params = params; + + bindtextdomain(params->domain, ISO_CODES_LOCALESDIR); + bind_textdomain_codeset(params->domain, "UTF-8"); + + filename = + g_strdup_printf("%s/%s.xml", ISO_CODES_DATADIR, + params->domain); + if (g_file_get_contents(filename, &buf, &buf_len, &err)) { + GMarkupParseContext *ctx; + GMarkupParser parser = { + iso_codes_parse_start_tag, + NULL, NULL, NULL, NULL + }; + + ctx = g_markup_parse_context_new(&parser, 0, &cbs, NULL); + if (!g_markup_parse_context_parse(ctx, buf, buf_len, &err)) { + g_warning("Failed to parse '%s/%s.xml': %s", + ISO_CODES_DATADIR, + params->domain, err->message); + g_error_free(err); + } + + g_markup_parse_context_free(ctx); + g_free(buf); + } else { + g_warning("Failed to load '%s/%s.xml': %s", + ISO_CODES_DATADIR, params->domain, err->message); + g_error_free(err); + } + g_free(filename); + g_free(tag_name); + + return ht; +} + +typedef const gchar *(*DescriptionGetterFunc) (const gchar * code); + +const gchar * +get_language_iso_code(const gchar * code) +{ + const gchar *name; + + if (!lang_code_names) { + lang_code_names = iso_code_names_init(&languageLookup); + } + + name = g_hash_table_lookup(lang_code_names, code); + if (!name) { + return NULL; + } + + return dgettext("iso_639", name); +} + +const gchar * +get_country_iso_code(const gchar * code) +{ + const gchar *name; + + if (!country_code_names) { + country_code_names = iso_code_names_init(&countryLookup); + } + + name = g_hash_table_lookup(country_code_names, code); + if (!name) { + return NULL; + } + + return dgettext("iso_3166", name); +} + +static void +xkl_config_registry_foreach_iso_code(XklConfigRegistry * config, + ConfigItemProcessFunc func, + const gchar * xpath_exprs[], + DescriptionGetterFunc dgf, + gpointer data) +{ + GHashTable *code_pairs; + GHashTableIter iter; + xmlXPathObjectPtr xpath_obj; + const gchar **xpath_expr; + gpointer key, value; + XklConfigItem *ci; + + if (!xkl_config_registry_is_initialized(config)) + return; + + code_pairs = g_hash_table_new(g_str_hash, g_str_equal); + + for (xpath_expr = xpath_exprs; *xpath_expr; xpath_expr++) { + xpath_obj = + xmlXPathEval((unsigned char *) *xpath_expr, + xkl_config_registry_priv(config, + xpath_context)); + if (xpath_obj != NULL) { + gint ni; + xmlNodeSetPtr nodes = xpath_obj->nodesetval; + if (nodes != NULL) { + xmlNodePtr *pnode = nodes->nodeTab; + for (ni = nodes->nodeNr; --ni >= 0;) { + const gchar *iso_code = + (const gchar *) (*pnode)-> + children->content; + const gchar *description = + dgf(iso_code); + if (description) + g_hash_table_insert + (code_pairs, + g_strdup + (iso_code), + g_strdup + (description)); + pnode++; + } + } + xmlXPathFreeObject(xpath_obj); + } + } + + g_hash_table_iter_init(&iter, code_pairs); + ci = xkl_config_item_new(); + while (g_hash_table_iter_next(&iter, &key, &value)) { + g_snprintf(ci->name, sizeof(ci->name), + (const gchar *) key); + g_snprintf(ci->description, sizeof(ci->description), + (const gchar *) value); + func(config, ci, data); + } + g_object_unref(G_OBJECT(ci)); + g_hash_table_unref(code_pairs); +} + +void +xkl_config_registry_foreach_country(XklConfigRegistry * + config, + ConfigItemProcessFunc + func, gpointer data) +{ + const gchar *xpath_exprs[] = { + XKBCR_LAYOUT_PATH "/configItem/countryList/iso3166Id", + XKBCR_LAYOUT_PATH "/configItem/name", + NULL + }; + + xkl_config_registry_foreach_iso_code(config, func, xpath_exprs, + get_country_iso_code, data); +} + +void +xkl_config_registry_foreach_language(XklConfigRegistry * + config, + ConfigItemProcessFunc + func, gpointer data) +{ + const gchar *xpath_exprs[] = { + XKBCR_LAYOUT_PATH "/configItem/languageList/iso639Id", + NULL + }; + + xkl_config_registry_foreach_iso_code(config, func, xpath_exprs, + get_language_iso_code, data); +} diff --git a/libxklavier/xklavier_private.h b/libxklavier/xklavier_private.h index f3e5208..df3baab 100644 --- a/libxklavier/xklavier_private.h +++ b/libxklavier/xklavier_private.h @@ -412,9 +412,41 @@ extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, #define xkl_engine_get_display(engine) (xkl_engine_priv(engine,display)) #define xkl_engine_vcall(engine,func) (*(engine)->priv->func) +#define xkl_config_registry_is_initialized(config) \ + ( xkl_config_registry_priv(config,xpath_context) != NULL ) + #define xkl_config_registry_priv(config,member) (config)->priv->member #define xkl_config_registry_get_engine(config) ((config)->priv->engine) +#define XKBCR_MODEL_PATH "/xkbConfigRegistry/modelList/model" +#define XKBCR_LAYOUT_PATH "/xkbConfigRegistry/layoutList/layout" +#define XKBCR_VARIANT_PATH XKBCR_LAYOUT_PATH "/variantList/variant" +#define XKBCR_GROUP_PATH "/xkbConfigRegistry/optionList/group" +#define XKBCR_OPTION_PATH XKBCR_GROUP_PATH "/option" + +#define XML_TAG_DESCR "description" +#define XML_TAG_SHORT_DESCR "shortDescription" +#define XML_TAG_VENDOR "vendor" +#define XML_TAG_COUNTRY_LIST "countryList" +#define XML_TAG_LANGUAGE_LIST "languageList" +#define XML_TAG_ISO3166ID "iso3166Id" +#define XML_TAG_ISO639ID "iso639Id" + +extern void xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry + * config, + const gchar * + format, + const gchar * + value, + ConfigItemProcessFunc + func, gpointer data); + +extern void xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, + xmlXPathCompExprPtr + xpath_comp_expr, + ConfigItemProcessFunc func, + gpointer data); + extern gint xkl_debug_level; extern const gchar *xkl_last_error_message; diff --git a/tests/test_config.c b/tests/test_config.c index 2ef07b7..c71b029 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -46,6 +46,8 @@ print_usage(void) printf(" -am - list all available models\n"); printf (" -ao - list all available options groups and options\n"); + printf(" -ac - list all available ISO country codes\n"); + printf(" -ag - list all available ISO language codes\n"); printf (" -g - Dump the current config, load original system settings and revert back\n"); printf @@ -129,6 +131,19 @@ print_layout(XklConfigRegistry * config, const XklConfigItem * item, print_variant, data); } +static void +print_country(XklConfigRegistry * config, const XklConfigItem * item, + gpointer data) +{ + print_xci(config, item, 0); +} + +static void +print_language(XklConfigRegistry * config, const XklConfigItem * item, + gpointer data) +{ + print_xci(config, item, 0); +} int main(int argc, char *const argv[]) @@ -243,6 +258,14 @@ main(int argc, char *const argv[]) xkl_config_registry_foreach_option_group (config, print_option_group, NULL); break; + case 'c': + xkl_config_registry_foreach_country + (config, print_country, NULL); + break; + case 'g': + xkl_config_registry_foreach_language + (config, print_language, NULL); + break; default: printf("Unknown list: %c\n", which_list); print_usage(); |