From 1d6bfa19ee0019c27f026f5d7f1dd5cef4aeadda Mon Sep 17 00:00:00 2001 From: Sergey Udaltsov Date: Fri, 19 Jun 2009 14:20:55 +0000 Subject: retrieve exotic layouts from xk-c xml files --- ChangeLog | 5 ++ libxklavier/xklavier_config.c | 158 ++++++++++++++++++++++++++------------ libxklavier/xklavier_config_iso.c | 111 ++++++++++++++++---------- libxklavier/xklavier_private.h | 17 ++-- 4 files changed, 194 insertions(+), 97 deletions(-) diff --git a/ChangeLog b/ChangeLog index 501c865..b4a5d90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-06-19 svu + + * libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c, + libxklavier/xklavier_private.h: use xml files with exotic layouts + 2009-06-02 svu * libxklavier/xklavier_config_iso.c: changed g_snprintf to more diff --git a/libxklavier/xklavier_config.c b/libxklavier/xklavier_config.c index 0607939..5d95b79 100644 --- a/libxklavier/xklavier_config.c +++ b/libxklavier/xklavier_config.c @@ -37,16 +37,15 @@ static xmlXPathCompExprPtr option_groups_xpath; static GRegex **xml_encode_regexen = NULL; static GRegex **xml_decode_regexen = NULL; -static const char const *xml_decode_regexen_str[] = - { "<", ">", "&" }; -static const char const *xml_encode_regexen_str[] = { "<", ">", "&" }; +static const char *xml_decode_regexen_str[] = { "<", ">", "&" }; +static const char *xml_encode_regexen_str[] = { "<", ">", "&" }; /* gettext domain for translations */ #define XKB_DOMAIN "xkeyboard-config" enum { PROP_0, - PROP_ENGINE, + PROP_ENGINE }; static gboolean @@ -285,13 +284,21 @@ xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, gpointer data) { xmlXPathObjectPtr xpath_obj; + gint i; if (!xkl_config_registry_is_initialized(config)) return; - xpath_obj = xmlXPathCompiledEval(xpath_comp_expr, - xkl_config_registry_priv - (config, xpath_context)); - if (xpath_obj != NULL) { + + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = xmlXPathCompiledEval(xpath_comp_expr, xmlctxt); + if (xpath_obj == NULL) + continue; + xkl_config_registry_foreach_in_nodeset(config, xpath_obj->nodesetval, func, data); @@ -311,14 +318,23 @@ xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry { char xpath_expr[1024]; xmlXPathObjectPtr xpath_obj; + gint i; if (!xkl_config_registry_is_initialized(config)) return; g_snprintf(xpath_expr, sizeof xpath_expr, format, value); - xpath_obj = xmlXPathEval((unsigned char *) xpath_expr, - xkl_config_registry_priv(config, - xpath_context)); - if (xpath_obj != NULL) { + + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathEval((unsigned char *) xpath_expr, xmlctxt); + if (xpath_obj == NULL) + continue; + xkl_config_registry_foreach_in_nodeset(config, xpath_obj->nodesetval, func, data); @@ -337,28 +353,38 @@ xkl_config_registry_find_object(XklConfigRegistry * config, xmlNodeSetPtr nodes; gboolean rv = FALSE; gchar xpath_expr[1024]; + gint i; if (!xkl_config_registry_is_initialized(config)) return FALSE; g_snprintf(xpath_expr, sizeof xpath_expr, format, arg1, pitem->name); - xpath_obj = - xmlXPathEval((unsigned char *) xpath_expr, - xkl_config_registry_priv(config, xpath_context)); - if (xpath_obj == NULL) - return FALSE; - nodes = xpath_obj->nodesetval; - if (nodes != NULL && nodes->nodeTab != NULL && nodes->nodeNr > 0) { - rv = xkl_read_config_item(config, nodes->nodeTab[0], - pitem); - if (pnode != NULL) { - *pnode = *nodes->nodeTab; + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathEval((unsigned char *) xpath_expr, xmlctxt); + if (xpath_obj == NULL) + continue; + + nodes = xpath_obj->nodesetval; + if (nodes != NULL && nodes->nodeTab != NULL + && nodes->nodeNr > 0) { + rv = xkl_read_config_item(config, + nodes->nodeTab[0], + pitem); + if (pnode != NULL) { + *pnode = *nodes->nodeTab; + } } - } - xmlXPathFreeObject(xpath_obj); + xmlXPathFreeObject(xpath_obj); + } return rv; } @@ -518,9 +544,11 @@ xkl_xml_sax_end_element_ns(void *ctx, gboolean xkl_config_registry_load_from_file(XklConfigRegistry * config, - const gchar * file_name) + const gchar * file_name, gint docidx) { xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + xmlDocPtr doc; + xkl_debug(100, "Loading XML registry from file %s\n", file_name); /* Filter out all unneeded languages! */ @@ -529,18 +557,20 @@ xkl_config_registry_load_from_file(XklConfigRegistry * config, ctxt->sax->endElementNs = xkl_xml_sax_end_element_ns; ctxt->sax->characters = xkl_xml_sax_characters; - xkl_config_registry_priv(config, doc) = + doc = xkl_config_registry_priv(config, docs[docidx]) = xmlCtxtReadFile(ctxt, file_name, NULL, XML_PARSE_NOBLANKS); xmlFreeParserCtxt(ctxt); - if (xkl_config_registry_priv(config, doc) == NULL) { - xkl_config_registry_priv(config, xpath_context) = NULL; + if (doc == NULL) { + xkl_config_registry_priv(config, xpath_contexts[docidx]) = + NULL; xkl_last_error_message = - "Could not parse XKB configuration registry"; + "Could not parse primary XKB configuration registry"; return FALSE; } - xkl_config_registry_priv(config, xpath_context) = - xmlXPathNewContext(xkl_config_registry_priv(config, doc)); + + xkl_config_registry_priv(config, xpath_contexts[docidx]) = + xmlXPathNewContext(doc); return TRUE; } @@ -566,18 +596,39 @@ xkl_config_registry_load_helper(XklConfigRegistry * config, return FALSE; } - return xkl_config_registry_load_from_file(config, file_name); + if (!xkl_config_registry_load_from_file(config, file_name, 0)) + return FALSE; + + g_snprintf(file_name, sizeof file_name, "%s/%s.extras.xml", + base_dir, rf); + + /* no extras - ok, no problem */ + if (stat(file_name, &stat_buf) != 0) + return TRUE; + + return xkl_config_registry_load_from_file(config, file_name, 1); } void xkl_config_registry_free(XklConfigRegistry * config) { + gint i; if (xkl_config_registry_is_initialized(config)) { - xmlXPathFreeContext(xkl_config_registry_priv - (config, xpath_context)); - xmlFreeDoc(xkl_config_registry_priv(config, doc)); - xkl_config_registry_priv(config, xpath_context) = NULL; - xkl_config_registry_priv(config, doc) = NULL; + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, + xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xmlXPathFreeContext(xmlctxt); + xmlFreeDoc(xkl_config_registry_priv + (config, docs[i])); + xkl_config_registry_priv(config, + xpath_contexts[i]) = NULL; + xkl_config_registry_priv(config, docs[i]) = NULL; + } + } } @@ -621,19 +672,30 @@ xkl_config_registry_foreach_option_group(XklConfigRegistry * func, gpointer data) { xmlXPathObjectPtr xpath_obj; - gint i; + gint i, j; if (!xkl_config_registry_is_initialized(config)) return; - xpath_obj = - xmlXPathCompiledEval(option_groups_xpath, - xkl_config_registry_priv(config, - xpath_context)); - if (xpath_obj != NULL) { - xmlNodeSetPtr nodes = xpath_obj->nodesetval; - xmlNodePtr *pnode = nodes->nodeTab; - XklConfigItem *ci = xkl_config_item_new(); - for (i = nodes->nodeNr; --i >= 0;) { + + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlNodeSetPtr nodes; + xmlNodePtr *pnode; + XklConfigItem *ci; + + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathCompiledEval(option_groups_xpath, xmlctxt); + if (xpath_obj == NULL) + continue; + + nodes = xpath_obj->nodesetval; + pnode = nodes->nodeTab; + ci = xkl_config_item_new(); + for (j = nodes->nodeNr; --j >= 0;) { if (xkl_read_config_item(config, *pnode, ci)) { gboolean allow_multisel = TRUE; diff --git a/libxklavier/xklavier_config_iso.c b/libxklavier/xklavier_config_iso.c index 07d32b1..aac978a 100644 --- a/libxklavier/xklavier_config_iso.c +++ b/libxklavier/xklavier_config_iso.c @@ -211,6 +211,7 @@ xkl_config_registry_foreach_iso_code(XklConfigRegistry * config, const gchar **xpath_expr; gpointer key, value; XklConfigItem *ci; + gint i; if (!xkl_config_registry_is_initialized(config)) return; @@ -218,38 +219,50 @@ xkl_config_registry_foreach_iso_code(XklConfigRegistry * config, 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) { + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { gint ni; - xmlNodeSetPtr nodes = xpath_obj->nodesetval; - if (nodes != NULL) { - xmlNodePtr *node = nodes->nodeTab; - for (ni = nodes->nodeNr; --ni >= 0;) { - gchar *iso_code = - (gchar *) (*node)->children-> - content; - const gchar *description; - iso_code = - to_upper ? - g_ascii_strup(iso_code, - -1) : - g_strdup(iso_code); - description = dgf(iso_code); + xmlNodePtr *node; + xmlNodeSetPtr nodes; + + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, + xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathEval((unsigned char *) *xpath_expr, + xmlctxt); + if (xpath_obj == NULL) + continue; + + nodes = xpath_obj->nodesetval; + if (nodes == NULL) { + xmlXPathFreeObject(xpath_obj); + continue; + } + + node = nodes->nodeTab; + for (ni = nodes->nodeNr; --ni >= 0;) { + gchar *iso_code = + (gchar *) (*node)->children->content; + const gchar *description; + iso_code = + to_upper ? + g_ascii_strup(iso_code, + -1) : g_strdup(iso_code); + description = dgf(iso_code); /* If there is a mapping to some ISO description - consider it as ISO code (well, it is just an assumption) */ - if (description) - g_hash_table_insert - (code_pairs, - g_strdup - (iso_code), - g_strdup - (description)); - g_free(iso_code); - node++; - } + if (description) + g_hash_table_insert + (code_pairs, + g_strdup + (iso_code), + g_strdup(description)); + g_free(iso_code); + node++; } + xmlXPathFreeObject(xpath_obj); } } @@ -316,9 +329,11 @@ xkl_config_registry_foreach_iso_variant(XklConfigRegistry * should_code_be_lowered2[]) { xmlXPathObjectPtr xpath_obj; + xmlNodeSetPtr nodes; const gchar **xpath_expr; const gboolean *is_low_id = should_code_be_lowered1; gchar *low_iso_code; + gint i; if (!xkl_config_registry_is_initialized(config)) return; @@ -329,12 +344,19 @@ xkl_config_registry_foreach_iso_variant(XklConfigRegistry * xpath_expr++, is_low_id++) { const gchar *aic = *is_low_id ? low_iso_code : iso_code; gchar *xpe = g_strdup_printf(*xpath_expr, aic); - xpath_obj = - xmlXPathEval((unsigned char *) xpe, - xkl_config_registry_priv(config, - xpath_context)); - if (xpath_obj != NULL) { - xmlNodeSetPtr nodes = xpath_obj->nodesetval; + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, + xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathEval((unsigned char *) xpe, xmlctxt); + if (xpath_obj == NULL) + continue; + + nodes = xpath_obj->nodesetval; if (nodes != NULL) { gint ni; xmlNodePtr *node = nodes->nodeTab; @@ -358,12 +380,19 @@ xkl_config_registry_foreach_iso_variant(XklConfigRegistry * xpath_expr++, is_low_id++) { const gchar *aic = *is_low_id ? low_iso_code : iso_code; gchar *xpe = g_strdup_printf(*xpath_expr, aic); - xpath_obj = - xmlXPathEval((unsigned char *) xpe, - xkl_config_registry_priv(config, - xpath_context)); - if (xpath_obj != NULL) { - xmlNodeSetPtr nodes = xpath_obj->nodesetval; + for (i = XKL_NUMBER_OF_REGISTRY_DOCS; --i >= 0;) { + xmlXPathContextPtr xmlctxt = + xkl_config_registry_priv(config, + xpath_contexts[i]); + if (xmlctxt == NULL) + continue; + + xpath_obj = + xmlXPathEval((unsigned char *) xpe, xmlctxt); + if (xpath_obj == NULL) + continue; + + nodes = xpath_obj->nodesetval; if (nodes != NULL) { gint ni; xmlNodePtr *node = nodes->nodeTab; diff --git a/libxklavier/xklavier_private.h b/libxklavier/xklavier_private.h index 7e1b4a8..5bcd24b 100644 --- a/libxklavier/xklavier_private.h +++ b/libxklavier/xklavier_private.h @@ -34,6 +34,8 @@ enum { WM_NAME, TOTAL_ATOMS }; +#define XKL_NUMBER_OF_REGISTRY_DOCS 2 + struct _XklEnginePrivate { gboolean group_per_toplevel_window; @@ -245,9 +247,8 @@ extern XklEngine *xkl_get_the_engine(void); struct _XklConfigRegistryPrivate { XklEngine *engine; - xmlDocPtr doc; - - xmlXPathContextPtr xpath_context; + xmlDocPtr docs[XKL_NUMBER_OF_REGISTRY_DOCS]; + xmlXPathContextPtr xpath_contexts[XKL_NUMBER_OF_REGISTRY_DOCS]; }; extern void xkl_engine_ensure_vtable_inited(XklEngine * engine); @@ -388,16 +389,15 @@ extern void xkl_engine_one_switch_to_secondary_group_performed(XklEngine * extern gboolean xkl_config_registry_load_from_file(XklConfigRegistry * config, - const gchar * - file_name); + const gchar * file_name, + gint docidx); extern void xkl_config_registry_free(XklConfigRegistry * config); extern gchar *xkl_locale_from_utf8(XklConfigRegistry * config, const gchar * utf8string); -extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, - const char +extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, const char default_ruleset[], const char base_dir[]); @@ -414,7 +414,7 @@ extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, #define xkl_engine_vcall(engine,func) (*(engine)->priv->func) #define xkl_config_registry_is_initialized(config) \ - ( xkl_config_registry_priv(config,xpath_context) != NULL ) + ( xkl_config_registry_priv(config,xpath_contexts[0]) != NULL ) #define xkl_config_registry_priv(config,member) (config)->priv->member #define xkl_config_registry_get_engine(config) ((config)->priv->engine) @@ -434,6 +434,7 @@ extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, #define XML_TAG_ISO639ID "iso639Id" extern void + xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry * config, const gchar * format, const gchar * value, -- cgit v1.2.1