summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Udaltsov <svu@gnome.org>2008-04-21 22:37:33 +0000
committerSergey Udaltsov <svu@gnome.org>2008-04-21 22:37:33 +0000
commit068422e3a7a0aae5983cde5d57ce18e4fb5fa560 (patch)
tree10a9b45adc0bed36315c118235189d1587a78720
parentae1528e30b7e0a50660a1c69e03b077ad1010dd9 (diff)
downloadlibxklavier-068422e3a7a0aae5983cde5d57ce18e4fb5fa560.tar.gz
adding country/language functions, new dep on iso-codes
-rw-r--r--ChangeLog8
-rw-r--r--configure.in18
-rw-r--r--libxklavier/Makefile.am2
-rw-r--r--libxklavier/xkl_config_registry.h67
-rw-r--r--libxklavier/xklavier_config.c22
-rw-r--r--libxklavier/xklavier_config_iso.c291
-rw-r--r--libxklavier/xklavier_private.h32
-rw-r--r--tests/test_config.c23
8 files changed, 441 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index b6be0b8..9851f78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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();