Blame libxklavier/xklavier_config.c

Packit Service 93d855
/*
Packit Service 93d855
 * Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org>
Packit Service 93d855
 *
Packit Service 93d855
 * This library is free software; you can redistribute it and/or
Packit Service 93d855
 * modify it under the terms of the GNU Lesser General Public
Packit Service 93d855
 * License as published by the Free Software Foundation; either
Packit Service 93d855
 * version 2 of the License, or (at your option) any later version.
Packit Service 93d855
 *
Packit Service 93d855
 * This library is distributed in the hope that it will be useful,
Packit Service 93d855
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 93d855
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 93d855
 * Lesser General Public License for more details.
Packit Service 93d855
 *
Packit Service 93d855
 * You should have received a copy of the GNU Lesser General Public
Packit Service 93d855
 * License along with this library; if not, write to the
Packit Service 93d855
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit Service 93d855
 * Boston, MA 02111-1307, USA.
Packit Service 93d855
 */
Packit Service 93d855
Packit Service 93d855
#include <errno.h>
Packit Service 93d855
#include <locale.h>
Packit Service 93d855
#include <libintl.h>
Packit Service 93d855
#include <stdio.h>
Packit Service 93d855
#include <string.h>
Packit Service 93d855
#include <sys/param.h>
Packit Service 93d855
#include <sys/stat.h>
Packit Service 93d855
Packit Service 93d855
#include "config.h"
Packit Service 93d855
Packit Service 93d855
#include "xklavier_private.h"
Packit Service 93d855
Packit Service 93d855
static GObjectClass *parent_class = NULL;
Packit Service 93d855
Packit Service 93d855
static xmlXPathCompExprPtr models_xpath;
Packit Service 93d855
static xmlXPathCompExprPtr layouts_xpath;
Packit Service 93d855
static xmlXPathCompExprPtr option_groups_xpath;
Packit Service 93d855
Packit Service 93d855
static GRegex **xml_encode_regexen = NULL;
Packit Service 93d855
static GRegex **xml_decode_regexen = NULL;
Packit Service 93d855
static const char *xml_decode_regexen_str[] = { "<", ">", "&" };
Packit Service 93d855
static const char *xml_encode_regexen_str[] = { "<", ">", "&" };
Packit Service 93d855
Packit Service 93d855
/* gettext domain for translations */
Packit Service 93d855
#define XKB_DOMAIN "xkeyboard-config"
Packit Service 93d855
Packit Service 93d855
enum {
Packit Service 93d855
	PROP_0,
Packit Service 93d855
	PROP_ENGINE
Packit Service 93d855
};
Packit Service 93d855
Packit Service 93d855
typedef struct {
Packit Service 93d855
	gchar **patterns;
Packit Service 93d855
	XklTwoConfigItemsProcessFunc func;
Packit Service 93d855
	gpointer data;
Packit Service 93d855
	gboolean country_matched;
Packit Service 93d855
	gboolean language_matched;
Packit Service 93d855
	const XklConfigItem *layout_item;
Packit Service 93d855
} SearchParamType;
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
xkl_xml_find_config_item_child(xmlNodePtr iptr, xmlNodePtr * ptr)
Packit Service 93d855
{
Packit Service 93d855
	/* 
Packit Service 93d855
	 * Walking through the 1st level children of iptr
Packit Service 93d855
	 * looking for the configItem
Packit Service 93d855
	 */
Packit Service 93d855
	if (iptr->type != XML_ELEMENT_NODE)
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	*ptr = iptr->children;
Packit Service 93d855
	while (*ptr != NULL) {
Packit Service 93d855
		switch ((*ptr)->type) {
Packit Service 93d855
		case XML_ELEMENT_NODE:
Packit Service 93d855
			return !g_ascii_strcasecmp
Packit Service 93d855
			    ((char *) (*ptr)->name, "configItem");
Packit Service 93d855
		case XML_TEXT_NODE:
Packit Service 93d855
		case XML_COMMENT_NODE:
Packit Service 93d855
			(*ptr) = (*ptr)->next;
Packit Service 93d855
			continue;
Packit Service 93d855
		default:
Packit Service 93d855
			return FALSE;
Packit Service 93d855
		}
Packit Service 93d855
		break;
Packit Service 93d855
	}
Packit Service 93d855
	return FALSE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static xmlNodePtr
Packit Service 93d855
xkl_find_element(xmlNodePtr ptr, const gchar * tag_name)
Packit Service 93d855
{
Packit Service 93d855
	xmlNodePtr found_element = NULL;
Packit Service 93d855
Packit Service 93d855
	/* Look through all siblings, trying to find a node with proper name */
Packit Service 93d855
	while (ptr != NULL) {
Packit Service 93d855
		char *node_name = (char *) ptr->name;
Packit Service 93d855
		if (ptr->type != XML_TEXT_NODE) {
Packit Service 93d855
			if (!g_ascii_strcasecmp(node_name, tag_name)) {
Packit Service 93d855
				found_element = ptr;
Packit Service 93d855
				break;
Packit Service 93d855
			}
Packit Service 93d855
		}
Packit Service 93d855
		ptr = ptr->next;
Packit Service 93d855
	}
Packit Service 93d855
	return found_element;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
xkl_item_populate_optional_array(XklConfigItem * item, xmlNodePtr ptr,
Packit Service 93d855
				 const gchar list_tag[],
Packit Service 93d855
				 const gchar element_tag[],
Packit Service 93d855
				 const gchar property_name[])
Packit Service 93d855
{
Packit Service 93d855
	xmlNodePtr top_list_element =
Packit Service 93d855
	    xkl_find_element(ptr, list_tag), element_ptr;
Packit Service 93d855
	gint n_elements, idx;
Packit Service 93d855
	gchar **elements = NULL;
Packit Service 93d855
Packit Service 93d855
	if (top_list_element == NULL || top_list_element->children == NULL)
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	n_elements = 0;
Packit Service 93d855
Packit Service 93d855
	/* First, count countries */
Packit Service 93d855
	element_ptr = top_list_element->children;
Packit Service 93d855
	while (NULL !=
Packit Service 93d855
	       (element_ptr =
Packit Service 93d855
		xkl_find_element(element_ptr, element_tag))) {
Packit Service 93d855
		n_elements++;
Packit Service 93d855
		element_ptr = element_ptr->next;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (n_elements == 0)
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	elements = g_new0(gchar *, n_elements + 1);
Packit Service 93d855
	/* Then, actually, populate the list */
Packit Service 93d855
	element_ptr = top_list_element->children;
Packit Service 93d855
	for (idx = 0;
Packit Service 93d855
	     NULL != (element_ptr =
Packit Service 93d855
		      xkl_find_element(element_ptr, element_tag));
Packit Service 93d855
	     element_ptr = element_ptr->next, idx++) {
Packit Service 93d855
		elements[idx] =
Packit Service 93d855
		    g_strdup((const char *) element_ptr->
Packit Service 93d855
			     children->content);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	g_object_set_data_full(G_OBJECT(item),
Packit Service 93d855
			       property_name, elements, (GDestroyNotify)
Packit Service 93d855
			       g_strfreev);
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
#include "libxml/parserInternals.h"
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_read_config_item(XklConfigRegistry * config, gint doc_index,
Packit Service 93d855
		     xmlNodePtr iptr, XklConfigItem * item)
Packit Service 93d855
{
Packit Service 93d855
	xmlNodePtr name_element, ptr;
Packit Service 93d855
	xmlNodePtr desc_element = NULL, short_desc_element =
Packit Service 93d855
	    NULL, vendor_element = NULL;
Packit Service 93d855
Packit Service 93d855
	gchar *vendor = NULL, *translated = NULL, *escaped =
Packit Service 93d855
	    NULL, *unescaped = NULL;
Packit Service 93d855
Packit Service 93d855
	gint i;
Packit Service 93d855
Packit Service 93d855
	*item->name = 0;
Packit Service 93d855
	*item->short_description = 0;
Packit Service 93d855
	*item->description = 0;
Packit Service 93d855
Packit Service 93d855
	g_object_set_data(G_OBJECT(item), XCI_PROP_VENDOR, NULL);
Packit Service 93d855
	g_object_set_data(G_OBJECT(item), XCI_PROP_COUNTRY_LIST, NULL);
Packit Service 93d855
	g_object_set_data(G_OBJECT(item), XCI_PROP_LANGUAGE_LIST, NULL);
Packit Service 93d855
Packit Service 93d855
	if (!xkl_xml_find_config_item_child(iptr, &ptr))
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	if (doc_index > 0)
Packit Service 93d855
		g_object_set_data(G_OBJECT(item), XCI_PROP_EXTRA_ITEM,
Packit Service 93d855
				  GINT_TO_POINTER(TRUE));
Packit Service 93d855
Packit Service 93d855
	ptr = ptr->children;
Packit Service 93d855
Packit Service 93d855
	if (ptr->type == XML_TEXT_NODE)
Packit Service 93d855
		ptr = ptr->next;
Packit Service 93d855
	name_element = ptr;
Packit Service 93d855
	ptr = ptr->next;
Packit Service 93d855
Packit Service 93d855
	short_desc_element = xkl_find_element(ptr, XML_TAG_SHORT_DESCR);
Packit Service 93d855
	desc_element = xkl_find_element(ptr, XML_TAG_DESCR);
Packit Service 93d855
	vendor_element = xkl_find_element(ptr, XML_TAG_VENDOR);
Packit Service 93d855
Packit Service 93d855
	if (name_element != NULL && name_element->children != NULL)
Packit Service 93d855
		strncat(item->name,
Packit Service 93d855
			(char *) name_element->children->content,
Packit Service 93d855
			XKL_MAX_CI_NAME_LENGTH - 1);
Packit Service 93d855
Packit Service 93d855
	if (short_desc_element != NULL
Packit Service 93d855
	    && short_desc_element->children != NULL) {
Packit Service 93d855
		strncat(item->short_description,
Packit Service 93d855
			dgettext(XKB_DOMAIN, (const char *)
Packit Service 93d855
				 short_desc_element->children->content),
Packit Service 93d855
			XKL_MAX_CI_SHORT_DESC_LENGTH - 1);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (desc_element != NULL && desc_element->children != NULL) {
Packit Service 93d855
		/* Convert all xml-related characters to XML form, otherwise dgettext won't find the translation 
Packit Service 93d855
		 * The conversion is not using libxml2, because there are no handy functions in API */
Packit Service 93d855
		translated =
Packit Service 93d855
		    g_strdup((gchar *) desc_element->children->content);
Packit Service 93d855
		for (i =
Packit Service 93d855
		     sizeof(xml_encode_regexen_str) /
Packit Service 93d855
		     sizeof(xml_encode_regexen_str[0]); --i >= 0;) {
Packit Service 93d855
			escaped =
Packit Service 93d855
			    g_regex_replace(xml_encode_regexen[i],
Packit Service 93d855
					    translated, -1, 0,
Packit Service 93d855
					    xml_decode_regexen_str[i], 0,
Packit Service 93d855
					    NULL);
Packit Service 93d855
			g_free(translated);
Packit Service 93d855
			translated = escaped;
Packit Service 93d855
		}
Packit Service 93d855
		escaped = translated;
Packit Service 93d855
Packit Service 93d855
		/* Do the translation! */
Packit Service 93d855
		translated =
Packit Service 93d855
		    g_strdup(dgettext(XKB_DOMAIN, (const char *) escaped));
Packit Service 93d855
		g_free(escaped);
Packit Service 93d855
Packit Service 93d855
		/* Convert all XML entities back to normal form */
Packit Service 93d855
		for (i =
Packit Service 93d855
		     sizeof(xml_decode_regexen_str) /
Packit Service 93d855
		     sizeof(xml_decode_regexen_str[0]); --i >= 0;) {
Packit Service 93d855
			unescaped =
Packit Service 93d855
			    g_regex_replace(xml_decode_regexen[i],
Packit Service 93d855
					    translated, -1, 0,
Packit Service 93d855
					    xml_encode_regexen_str[i], 0,
Packit Service 93d855
					    NULL);
Packit Service 93d855
			g_free(translated);
Packit Service 93d855
			translated = unescaped;
Packit Service 93d855
		}
Packit Service 93d855
		strncat(item->description,
Packit Service 93d855
			translated, XKL_MAX_CI_DESC_LENGTH - 1);
Packit Service 93d855
		g_free(translated);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (vendor_element != NULL && vendor_element->children != NULL) {
Packit Service 93d855
		vendor =
Packit Service 93d855
		    g_strdup((const char *) vendor_element->children->
Packit Service 93d855
			     content);
Packit Service 93d855
		g_object_set_data_full(G_OBJECT(item), XCI_PROP_VENDOR,
Packit Service 93d855
				       vendor, g_free);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_item_populate_optional_array(item, ptr, XML_TAG_COUNTRY_LIST,
Packit Service 93d855
					 XML_TAG_ISO3166ID,
Packit Service 93d855
					 XCI_PROP_COUNTRY_LIST);
Packit Service 93d855
	xkl_item_populate_optional_array(item, ptr, XML_TAG_LANGUAGE_LIST,
Packit Service 93d855
					 XML_TAG_ISO639ID,
Packit Service 93d855
					 XCI_PROP_LANGUAGE_LIST);
Packit Service 93d855
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_foreach_in_nodeset(XklConfigRegistry * config,
Packit Service 93d855
				       GSList ** processed_ids,
Packit Service 93d855
				       gint doc_index, xmlNodeSetPtr nodes,
Packit Service 93d855
				       XklConfigItemProcessFunc func,
Packit Service 93d855
				       gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	gint i;
Packit Service 93d855
	if (nodes != NULL) {
Packit Service 93d855
		xmlNodePtr *pnode = nodes->nodeTab;
Packit Service 93d855
		XklConfigItem *ci = xkl_config_item_new();
Packit Service 93d855
		for (i = nodes->nodeNr; --i >= 0;) {
Packit Service 93d855
			if (xkl_read_config_item
Packit Service 93d855
			    (config, doc_index, *pnode, ci)) {
Packit Service 93d855
				if (g_slist_find_custom
Packit Service 93d855
				    (*processed_ids, ci->name,
Packit Service 93d855
				     (GCompareFunc) g_ascii_strcasecmp) ==
Packit Service 93d855
				    NULL) {
Packit Service 93d855
					func(config, ci, data);
Packit Service 93d855
					*processed_ids =
Packit Service 93d855
					    g_slist_append(*processed_ids,
Packit Service 93d855
							   g_strdup
Packit Service 93d855
							   (ci->name));
Packit Service 93d855
				}
Packit Service 93d855
			}
Packit Service 93d855
Packit Service 93d855
			pnode++;
Packit Service 93d855
		}
Packit Service 93d855
		g_object_unref(G_OBJECT(ci));
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config,
Packit Service 93d855
				     xmlXPathCompExprPtr
Packit Service 93d855
				     xpath_comp_expr,
Packit Service 93d855
				     XklConfigItemProcessFunc func,
Packit Service 93d855
				     gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xmlXPathObjectPtr xpath_obj;
Packit Service 93d855
	gint di;
Packit Service 93d855
	GSList *processed_ids = NULL;
Packit Service 93d855
Packit Service 93d855
	if (!xkl_config_registry_is_initialized(config))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) {
Packit Service 93d855
		xmlXPathContextPtr xmlctxt =
Packit Service 93d855
		    xkl_config_registry_priv(config, xpath_contexts[di]);
Packit Service 93d855
		if (xmlctxt == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xpath_obj = xmlXPathCompiledEval(xpath_comp_expr, xmlctxt);
Packit Service 93d855
		if (xpath_obj == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xkl_config_registry_foreach_in_nodeset(config,
Packit Service 93d855
						       &processed_ids, di,
Packit Service 93d855
						       xpath_obj->
Packit Service 93d855
						       nodesetval, func,
Packit Service 93d855
						       data);
Packit Service 93d855
		xmlXPathFreeObject(xpath_obj);
Packit Service 93d855
	}
Packit Service 93d855
	g_slist_foreach(processed_ids, (GFunc) g_free, NULL);
Packit Service 93d855
	g_slist_free(processed_ids);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry
Packit Service 93d855
						* config,
Packit Service 93d855
						const gchar *
Packit Service 93d855
						format,
Packit Service 93d855
						const gchar *
Packit Service 93d855
						value,
Packit Service 93d855
						XklConfigItemProcessFunc
Packit Service 93d855
						func, gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	char xpath_expr[1024];
Packit Service 93d855
	xmlXPathObjectPtr xpath_obj;
Packit Service 93d855
	gint di;
Packit Service 93d855
	GSList *processed_ids = NULL;
Packit Service 93d855
Packit Service 93d855
	if (!xkl_config_registry_is_initialized(config))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	g_snprintf(xpath_expr, sizeof xpath_expr, format, value);
Packit Service 93d855
Packit Service 93d855
	for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) {
Packit Service 93d855
		xmlXPathContextPtr xmlctxt =
Packit Service 93d855
		    xkl_config_registry_priv(config, xpath_contexts[di]);
Packit Service 93d855
		if (xmlctxt == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xpath_obj =
Packit Service 93d855
		    xmlXPathEval((unsigned char *) xpath_expr, xmlctxt);
Packit Service 93d855
		if (xpath_obj == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xkl_config_registry_foreach_in_nodeset(config,
Packit Service 93d855
						       &processed_ids, di,
Packit Service 93d855
						       xpath_obj->
Packit Service 93d855
						       nodesetval, func,
Packit Service 93d855
						       data);
Packit Service 93d855
		xmlXPathFreeObject(xpath_obj);
Packit Service 93d855
	}
Packit Service 93d855
	g_slist_foreach(processed_ids, (GFunc) g_free, NULL);
Packit Service 93d855
	g_slist_free(processed_ids);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
xkl_config_registry_find_object(XklConfigRegistry * config,
Packit Service 93d855
				const gchar * format,
Packit Service 93d855
				const gchar * arg1,
Packit Service 93d855
				XklConfigItem * pitem /* in/out */ ,
Packit Service 93d855
				xmlNodePtr * pnode /* out */ )
Packit Service 93d855
{
Packit Service 93d855
	xmlXPathObjectPtr xpath_obj;
Packit Service 93d855
	xmlNodeSetPtr nodes;
Packit Service 93d855
	gboolean rv = FALSE;
Packit Service 93d855
	gchar xpath_expr[1024];
Packit Service 93d855
	gint di;
Packit Service 93d855
Packit Service 93d855
	if (!xkl_config_registry_is_initialized(config))
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	g_snprintf(xpath_expr, sizeof xpath_expr, format, arg1,
Packit Service 93d855
		   pitem->name);
Packit Service 93d855
Packit Service 93d855
	for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) {
Packit Service 93d855
		xmlXPathContextPtr xmlctxt =
Packit Service 93d855
		    xkl_config_registry_priv(config, xpath_contexts[di]);
Packit Service 93d855
		if (xmlctxt == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xpath_obj =
Packit Service 93d855
		    xmlXPathEval((unsigned char *) xpath_expr, xmlctxt);
Packit Service 93d855
		if (xpath_obj == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		nodes = xpath_obj->nodesetval;
Packit Service 93d855
		if (nodes != NULL && nodes->nodeTab != NULL
Packit Service 93d855
		    && nodes->nodeNr > 0) {
Packit Service 93d855
			rv = xkl_read_config_item(config, di,
Packit Service 93d855
						  nodes->nodeTab[0],
Packit Service 93d855
						  pitem);
Packit Service 93d855
			if (pnode != NULL) {
Packit Service 93d855
				*pnode = *nodes->nodeTab;
Packit Service 93d855
			}
Packit Service 93d855
		}
Packit Service 93d855
Packit Service 93d855
		xmlXPathFreeObject(xpath_obj);
Packit Service 93d855
	}
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gchar *
Packit Service 93d855
xkl_config_rec_merge_layouts(const XklConfigRec * data)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_strings_concat_comma_separated(data->layouts);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gchar *
Packit Service 93d855
xkl_config_rec_merge_variants(const XklConfigRec * data)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_strings_concat_comma_separated(data->variants);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gchar *
Packit Service 93d855
xkl_config_rec_merge_options(const XklConfigRec * data)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_strings_concat_comma_separated(data->options);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gchar *
Packit Service 93d855
xkl_strings_concat_comma_separated(gchar ** array)
Packit Service 93d855
{
Packit Service 93d855
	if (array) {
Packit Service 93d855
		return g_strjoinv(",", array);
Packit Service 93d855
	} else {
Packit Service 93d855
		return g_strdup("");
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_rec_split_layouts(XklConfigRec * data, const gchar * merged)
Packit Service 93d855
{
Packit Service 93d855
	xkl_strings_split_comma_separated(&data->layouts, merged);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_rec_split_variants(XklConfigRec * data, const gchar * merged)
Packit Service 93d855
{
Packit Service 93d855
	xkl_strings_split_comma_separated(&data->variants, merged);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_rec_split_options(XklConfigRec * data, const gchar * merged)
Packit Service 93d855
{
Packit Service 93d855
	xkl_strings_split_comma_separated(&data->options, merged);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_strings_split_comma_separated(gchar *** array, const gchar * merged)
Packit Service 93d855
{
Packit Service 93d855
	*array = g_strsplit(merged, ",", 0);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gchar *
Packit Service 93d855
xkl_engine_get_ruleset_name(XklEngine * engine,
Packit Service 93d855
			    const gchar default_ruleset[])
Packit Service 93d855
{
Packit Service 93d855
	static gchar rules_set_name[1024] = "";
Packit Service 93d855
	if (!rules_set_name[0]) {
Packit Service 93d855
		/* first call */
Packit Service 93d855
		gchar *rf = NULL;
Packit Service 93d855
		if (!xkl_config_rec_get_from_root_window_property
Packit Service 93d855
		    (NULL,
Packit Service 93d855
		     xkl_engine_priv(engine, base_config_atom),
Packit Service 93d855
		     &rf, engine) || (rf == NULL)) {
Packit Service 93d855
			g_strlcpy(rules_set_name, default_ruleset,
Packit Service 93d855
				  sizeof rules_set_name);
Packit Service 93d855
			xkl_debug(100,
Packit Service 93d855
				  "Using default rules set: [%s]\n",
Packit Service 93d855
				  rules_set_name);
Packit Service 93d855
			return rules_set_name;
Packit Service 93d855
		}
Packit Service 93d855
		g_strlcpy(rules_set_name, rf, sizeof rules_set_name);
Packit Service 93d855
		g_free(rf);
Packit Service 93d855
	}
Packit Service 93d855
	xkl_debug(100, "Rules set: [%s]\n", rules_set_name);
Packit Service 93d855
	return rules_set_name;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
XklConfigRegistry *
Packit Service 93d855
xkl_config_registry_get_instance(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	XklConfigRegistry *config;
Packit Service 93d855
Packit Service 93d855
	if (!engine) {
Packit Service 93d855
		xkl_debug(10,
Packit Service 93d855
			  "xkl_config_registry_get_instance : engine is NULL ?\n");
Packit Service 93d855
		return NULL;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	config =
Packit Service 93d855
	    XKL_CONFIG_REGISTRY(g_object_new
Packit Service 93d855
				(xkl_config_registry_get_type(),
Packit Service 93d855
				 "engine", engine, NULL));
Packit Service 93d855
Packit Service 93d855
	return config;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/* We process descriptions as "leaf" elements - this is ok for base.xml*/
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_load_from_file(XklConfigRegistry * config,
Packit Service 93d855
				   const gchar * file_name, gint docidx)
Packit Service 93d855
{
Packit Service 93d855
	xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
Packit Service 93d855
	xmlDocPtr doc;
Packit Service 93d855
Packit Service 93d855
	xkl_debug(100, "Loading XML registry from file %s\n", file_name);
Packit Service 93d855
Packit Service 93d855
	xmlSAX2InitDefaultSAXHandler(ctxt->sax, TRUE);
Packit Service 93d855
Packit Service 93d855
	doc = xkl_config_registry_priv(config, docs[docidx]) =
Packit Service 93d855
	    xmlCtxtReadFile(ctxt, file_name, NULL, XML_PARSE_NOBLANKS);
Packit Service 93d855
	xmlFreeParserCtxt(ctxt);
Packit Service 93d855
Packit Service 93d855
	if (doc == NULL) {
Packit Service 93d855
		xkl_config_registry_priv(config, xpath_contexts[docidx]) =
Packit Service 93d855
		    NULL;
Packit Service 93d855
		xkl_last_error_message =
Packit Service 93d855
		    "Could not parse primary XKB configuration registry";
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_config_registry_priv(config, xpath_contexts[docidx]) =
Packit Service 93d855
	    xmlXPathNewContext(doc);
Packit Service 93d855
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_load_helper(XklConfigRegistry * config,
Packit Service 93d855
				const char default_ruleset[],
Packit Service 93d855
				const char base_dir[],
Packit Service 93d855
				gboolean if_extras_needed)
Packit Service 93d855
{
Packit Service 93d855
	struct stat stat_buf;
Packit Service 93d855
	gchar file_name[MAXPATHLEN] = "";
Packit Service 93d855
	XklEngine *engine = xkl_config_registry_get_engine(config);
Packit Service 93d855
	gchar *rf = xkl_engine_get_ruleset_name(engine, default_ruleset);
Packit Service 93d855
Packit Service 93d855
	if (rf == NULL || rf[0] == '\0')
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	g_snprintf(file_name, sizeof file_name, "%s/%s.xml", base_dir, rf);
Packit Service 93d855
Packit Service 93d855
	if (stat(file_name, &stat_buf) != 0) {
Packit Service 93d855
		xkl_debug(0, "Missing registry file %s\n", file_name);
Packit Service 93d855
		xkl_last_error_message = "Missing registry file";
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (!xkl_config_registry_load_from_file(config, file_name, 0))
Packit Service 93d855
		return FALSE;
Packit Service 93d855
Packit Service 93d855
	if (!if_extras_needed)
Packit Service 93d855
		return TRUE;
Packit Service 93d855
Packit Service 93d855
	g_snprintf(file_name, sizeof file_name, "%s/%s.extras.xml",
Packit Service 93d855
		   base_dir, rf);
Packit Service 93d855
Packit Service 93d855
	/* no extras - ok, no problem */
Packit Service 93d855
	if (stat(file_name, &stat_buf) != 0)
Packit Service 93d855
		return TRUE;
Packit Service 93d855
Packit Service 93d855
	return xkl_config_registry_load_from_file(config, file_name, 1);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_free(XklConfigRegistry * config)
Packit Service 93d855
{
Packit Service 93d855
	if (xkl_config_registry_is_initialized(config)) {
Packit Service 93d855
		gint di;
Packit Service 93d855
		for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) {
Packit Service 93d855
			xmlXPathContextPtr xmlctxt =
Packit Service 93d855
			    xkl_config_registry_priv(config,
Packit Service 93d855
						     xpath_contexts[di]);
Packit Service 93d855
			if (xmlctxt == NULL)
Packit Service 93d855
				continue;
Packit Service 93d855
Packit Service 93d855
			xmlXPathFreeContext(xmlctxt);
Packit Service 93d855
			xmlFreeDoc(xkl_config_registry_priv
Packit Service 93d855
				   (config, docs[di]));
Packit Service 93d855
			xkl_config_registry_priv(config,
Packit Service 93d855
						 xpath_contexts[di]) =
Packit Service 93d855
			    NULL;
Packit Service 93d855
			xkl_config_registry_priv(config, docs[di]) = NULL;
Packit Service 93d855
		}
Packit Service 93d855
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_model(XklConfigRegistry * config,
Packit Service 93d855
				  XklConfigItemProcessFunc func,
Packit Service 93d855
				  gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xkl_config_registry_foreach_in_xpath(config, models_xpath,
Packit Service 93d855
					     func, data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_layout(XklConfigRegistry * config,
Packit Service 93d855
				   XklConfigItemProcessFunc func,
Packit Service 93d855
				   gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xkl_config_registry_foreach_in_xpath(config, layouts_xpath,
Packit Service 93d855
					     func, data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_layout_variant(XklConfigRegistry *
Packit Service 93d855
					   config,
Packit Service 93d855
					   const gchar *
Packit Service 93d855
					   layout_name,
Packit Service 93d855
					   XklConfigItemProcessFunc
Packit Service 93d855
					   func, gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xkl_config_registry_foreach_in_xpath_with_param(config,
Packit Service 93d855
							XKBCR_VARIANT_PATH
Packit Service 93d855
							"[../../configItem/name = '%s']",
Packit Service 93d855
							layout_name,
Packit Service 93d855
							func, data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_option_group(XklConfigRegistry *
Packit Service 93d855
					 config,
Packit Service 93d855
					 XklConfigItemProcessFunc
Packit Service 93d855
					 func, gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xmlXPathObjectPtr xpath_obj;
Packit Service 93d855
	gint di, j;
Packit Service 93d855
	GSList *processed_ids = NULL;
Packit Service 93d855
Packit Service 93d855
	if (!xkl_config_registry_is_initialized(config))
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) {
Packit Service 93d855
		xmlNodeSetPtr nodes;
Packit Service 93d855
		xmlNodePtr *pnode;
Packit Service 93d855
		XklConfigItem *ci;
Packit Service 93d855
Packit Service 93d855
		xmlXPathContextPtr xmlctxt =
Packit Service 93d855
		    xkl_config_registry_priv(config, xpath_contexts[di]);
Packit Service 93d855
		if (xmlctxt == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		xpath_obj =
Packit Service 93d855
		    xmlXPathCompiledEval(option_groups_xpath, xmlctxt);
Packit Service 93d855
		if (xpath_obj == NULL)
Packit Service 93d855
			continue;
Packit Service 93d855
Packit Service 93d855
		nodes = xpath_obj->nodesetval;
Packit Service 93d855
		pnode = nodes->nodeTab;
Packit Service 93d855
		ci = xkl_config_item_new();
Packit Service 93d855
		for (j = nodes->nodeNr; --j >= 0;) {
Packit Service 93d855
Packit Service 93d855
			if (xkl_read_config_item(config, di, *pnode, ci)) {
Packit Service 93d855
				if (g_slist_find_custom
Packit Service 93d855
				    (processed_ids, ci->name,
Packit Service 93d855
				     (GCompareFunc) g_ascii_strcasecmp) ==
Packit Service 93d855
				    NULL) {
Packit Service 93d855
					gboolean allow_multisel = TRUE;
Packit Service 93d855
					xmlChar *sallow_multisel =
Packit Service 93d855
					    xmlGetProp(*pnode,
Packit Service 93d855
						       (unsigned char *)
Packit Service 93d855
						       XCI_PROP_ALLOW_MULTIPLE_SELECTION);
Packit Service 93d855
					if (sallow_multisel != NULL) {
Packit Service 93d855
						allow_multisel =
Packit Service 93d855
						    !g_ascii_strcasecmp
Packit Service 93d855
						    ("true", (char *)
Packit Service 93d855
						     sallow_multisel);
Packit Service 93d855
						xmlFree(sallow_multisel);
Packit Service 93d855
						g_object_set_data(G_OBJECT
Packit Service 93d855
								  (ci),
Packit Service 93d855
								  XCI_PROP_ALLOW_MULTIPLE_SELECTION,
Packit Service 93d855
								  GINT_TO_POINTER
Packit Service 93d855
								  (allow_multisel));
Packit Service 93d855
					}
Packit Service 93d855
Packit Service 93d855
					func(config, ci, data);
Packit Service 93d855
					processed_ids =
Packit Service 93d855
					    g_slist_append(processed_ids,
Packit Service 93d855
							   g_strdup
Packit Service 93d855
							   (ci->name));
Packit Service 93d855
				}
Packit Service 93d855
			}
Packit Service 93d855
Packit Service 93d855
			pnode++;
Packit Service 93d855
		}
Packit Service 93d855
		g_object_unref(G_OBJECT(ci));
Packit Service 93d855
		xmlXPathFreeObject(xpath_obj);
Packit Service 93d855
	}
Packit Service 93d855
	g_slist_foreach(processed_ids, (GFunc) g_free, NULL);
Packit Service 93d855
	g_slist_free(processed_ids);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_foreach_option(XklConfigRegistry * config,
Packit Service 93d855
				   const gchar *
Packit Service 93d855
				   option_group_name,
Packit Service 93d855
				   XklConfigItemProcessFunc func,
Packit Service 93d855
				   gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xkl_config_registry_foreach_in_xpath_with_param(config,
Packit Service 93d855
							XKBCR_OPTION_PATH
Packit Service 93d855
							"[../configItem/name = '%s']",
Packit Service 93d855
							option_group_name,
Packit Service 93d855
							func, data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
search_all(const gchar * haystack, gchar ** needles)
Packit Service 93d855
{
Packit Service 93d855
	/* match anything */
Packit Service 93d855
	if (!needles || !*needles)
Packit Service 93d855
		return TRUE;
Packit Service 93d855
Packit Service 93d855
	gchar *uchs = g_utf8_strup(haystack, -1);
Packit Service 93d855
	do {
Packit Service 93d855
		if (g_strstr_len(uchs, -1, *needles) == NULL) {
Packit Service 93d855
			g_free(uchs);
Packit Service 93d855
			return FALSE;
Packit Service 93d855
		}
Packit Service 93d855
		needles++;
Packit Service 93d855
	} while (*needles);
Packit Service 93d855
Packit Service 93d855
	g_free(uchs);
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
if_country_matches_pattern(const XklConfigItem * item,
Packit Service 93d855
			   gchar ** patterns, const gboolean check_name)
Packit Service 93d855
{
Packit Service 93d855
	const gchar *country_desc;
Packit Service 93d855
	if (check_name) {
Packit Service 93d855
		gchar *upper_name = g_ascii_strup(item->name, -1);
Packit Service 93d855
		country_desc = xkl_get_country_name(upper_name);
Packit Service 93d855
		g_free(upper_name);
Packit Service 93d855
		xkl_debug(200, "Checking layout country: [%s]\n",
Packit Service 93d855
			  country_desc);
Packit Service 93d855
		if ((country_desc != NULL)
Packit Service 93d855
		    && search_all(country_desc, patterns))
Packit Service 93d855
			return TRUE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	gchar **countries = g_object_get_data(G_OBJECT(item),
Packit Service 93d855
					      XCI_PROP_COUNTRY_LIST);
Packit Service 93d855
	for (; countries && *countries; countries++) {
Packit Service 93d855
		country_desc = xkl_get_country_name(*countries);
Packit Service 93d855
		xkl_debug(200, "Checking country: [%s][%s]\n",
Packit Service 93d855
			  *countries, country_desc);
Packit Service 93d855
		if ((country_desc != NULL)
Packit Service 93d855
		    && search_all(country_desc, patterns)) {
Packit Service 93d855
			return TRUE;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return FALSE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gboolean
Packit Service 93d855
if_language_matches_pattern(const XklConfigItem * item,
Packit Service 93d855
			    gchar ** patterns, const gboolean check_name)
Packit Service 93d855
{
Packit Service 93d855
	const gchar *language_desc;
Packit Service 93d855
	if (check_name) {
Packit Service 93d855
		language_desc = xkl_get_language_name(item->name);
Packit Service 93d855
		xkl_debug(200, "Checking layout language: [%s]\n",
Packit Service 93d855
			  language_desc);
Packit Service 93d855
		if ((language_desc != NULL)
Packit Service 93d855
		    && search_all(language_desc, patterns))
Packit Service 93d855
			return TRUE;
Packit Service 93d855
	}
Packit Service 93d855
	gchar **languages = g_object_get_data(G_OBJECT(item),
Packit Service 93d855
					      XCI_PROP_LANGUAGE_LIST);
Packit Service 93d855
	for (; languages && *languages; languages++) {
Packit Service 93d855
		language_desc = xkl_get_language_name(*languages);
Packit Service 93d855
		xkl_debug(200, "Checking language: [%s][%s]\n",
Packit Service 93d855
			  *languages, language_desc);
Packit Service 93d855
		if ((language_desc != NULL)
Packit Service 93d855
		    && search_all(language_desc, patterns)) {
Packit Service 93d855
			return TRUE;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return FALSE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_search_by_pattern_in_variant(XklConfigRegistry *
Packit Service 93d855
						 config,
Packit Service 93d855
						 const XklConfigItem *
Packit Service 93d855
						 item,
Packit Service 93d855
						 SearchParamType *
Packit Service 93d855
						 search_param)
Packit Service 93d855
{
Packit Service 93d855
	gboolean variant_matched = FALSE;
Packit Service 93d855
	gchar *full_desc = g_strdup_printf("%s - %s",
Packit Service 93d855
					   search_param->
Packit Service 93d855
					   layout_item->description,
Packit Service 93d855
					   item->description);
Packit Service 93d855
Packit Service 93d855
	xkl_debug(200, "Variant to check: [%s][%s]\n", item->name,
Packit Service 93d855
		  item->description);
Packit Service 93d855
Packit Service 93d855
	if (search_all(full_desc, search_param->patterns))
Packit Service 93d855
		variant_matched = TRUE;
Packit Service 93d855
Packit Service 93d855
	g_free(full_desc);
Packit Service 93d855
Packit Service 93d855
	if (!variant_matched) {
Packit Service 93d855
		gchar **countries = g_object_get_data(G_OBJECT(item),
Packit Service 93d855
						      XCI_PROP_COUNTRY_LIST);
Packit Service 93d855
		if (countries && g_strv_length(countries) > 0) {
Packit Service 93d855
			if (if_country_matches_pattern
Packit Service 93d855
			    (item, search_param->patterns, FALSE))
Packit Service 93d855
				variant_matched = TRUE;
Packit Service 93d855
		} else {
Packit Service 93d855
			if (search_param->country_matched)
Packit Service 93d855
				variant_matched = TRUE;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (!variant_matched) {
Packit Service 93d855
		gchar **languages = g_object_get_data(G_OBJECT(item),
Packit Service 93d855
						      XCI_PROP_LANGUAGE_LIST);
Packit Service 93d855
		if (languages && g_strv_length(languages) > 0) {
Packit Service 93d855
			if (if_language_matches_pattern
Packit Service 93d855
			    (item, search_param->patterns, FALSE))
Packit Service 93d855
				variant_matched = TRUE;
Packit Service 93d855
		} else {
Packit Service 93d855
			if (search_param->language_matched)
Packit Service 93d855
				variant_matched = TRUE;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (variant_matched)
Packit Service 93d855
		(search_param->func) (config, search_param->layout_item,
Packit Service 93d855
				      item, search_param->data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_search_by_pattern_in_layout(XklConfigRegistry * config,
Packit Service 93d855
						const XklConfigItem * item,
Packit Service 93d855
						SearchParamType *
Packit Service 93d855
						search_param)
Packit Service 93d855
{
Packit Service 93d855
	gchar *upper_name = g_ascii_strup(item->name, -1);
Packit Service 93d855
Packit Service 93d855
	xkl_debug(200, "Layout to check: [%s][%s]\n", item->name,
Packit Service 93d855
		  item->description);
Packit Service 93d855
Packit Service 93d855
	search_param->country_matched =
Packit Service 93d855
	    search_param->language_matched = FALSE;
Packit Service 93d855
Packit Service 93d855
	if (if_country_matches_pattern(item, search_param->patterns, TRUE))
Packit Service 93d855
		search_param->country_matched = TRUE;
Packit Service 93d855
	else if (if_language_matches_pattern
Packit Service 93d855
		 (item, search_param->patterns, TRUE))
Packit Service 93d855
		search_param->language_matched = TRUE;
Packit Service 93d855
	else if (search_all(item->description, search_param->patterns))
Packit Service 93d855
		search_param->language_matched = TRUE;
Packit Service 93d855
Packit Service 93d855
	if (search_param->country_matched
Packit Service 93d855
	    || search_param->language_matched)
Packit Service 93d855
		(search_param->func) (config, item, NULL,
Packit Service 93d855
				      search_param->data);
Packit Service 93d855
Packit Service 93d855
	search_param->layout_item = item;
Packit Service 93d855
Packit Service 93d855
	xkl_config_registry_foreach_layout_variant(config, item->name,
Packit Service 93d855
						   (XklConfigItemProcessFunc)
Packit Service 93d855
						   xkl_config_registry_search_by_pattern_in_variant,
Packit Service 93d855
						   search_param);
Packit Service 93d855
Packit Service 93d855
	g_free(upper_name);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_registry_search_by_pattern(XklConfigRegistry
Packit Service 93d855
				      * config,
Packit Service 93d855
				      const gchar *
Packit Service 93d855
				      pattern,
Packit Service 93d855
				      XklTwoConfigItemsProcessFunc
Packit Service 93d855
				      func, gpointer data)
Packit Service 93d855
{
Packit Service 93d855
	xkl_debug(200, "Searching by pattern: [%s]\n", pattern);
Packit Service 93d855
	gchar *upattern = pattern ? g_utf8_strup(pattern, -1) : NULL;
Packit Service 93d855
	gchar **patterns = pattern ? g_strsplit(upattern, " ", -1) : NULL;
Packit Service 93d855
	SearchParamType search_param = {
Packit Service 93d855
		patterns, func, data
Packit Service 93d855
	};
Packit Service 93d855
	xkl_config_registry_foreach_layout(config, (XklConfigItemProcessFunc)
Packit Service 93d855
					   xkl_config_registry_search_by_pattern_in_layout,
Packit Service 93d855
					   &search_param);
Packit Service 93d855
	g_strfreev(patterns);
Packit Service 93d855
	g_free(upattern);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_find_model(XklConfigRegistry *
Packit Service 93d855
			       config, XklConfigItem * pitem /* in/out */ )
Packit Service 93d855
{
Packit Service 93d855
	return xkl_config_registry_find_object(config,
Packit Service 93d855
					       XKBCR_MODEL_PATH
Packit Service 93d855
					       "[configItem/name = '%s%s']",
Packit Service 93d855
					       "", pitem, NULL);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_find_layout(XklConfigRegistry *
Packit Service 93d855
				config,
Packit Service 93d855
				XklConfigItem * pitem /* in/out */ )
Packit Service 93d855
{
Packit Service 93d855
	return xkl_config_registry_find_object(config,
Packit Service 93d855
					       XKBCR_LAYOUT_PATH
Packit Service 93d855
					       "[configItem/name = '%s%s']",
Packit Service 93d855
					       "", pitem, NULL);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_find_variant(XklConfigRegistry *
Packit Service 93d855
				 config,
Packit Service 93d855
				 const char
Packit Service 93d855
				 *layout_name,
Packit Service 93d855
				 XklConfigItem * pitem /* in/out */ )
Packit Service 93d855
{
Packit Service 93d855
	return xkl_config_registry_find_object(config,
Packit Service 93d855
					       XKBCR_VARIANT_PATH
Packit Service 93d855
					       "[../../configItem/name = '%s' and configItem/name = '%s']",
Packit Service 93d855
					       layout_name, pitem, NULL);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_find_option_group(XklConfigRegistry * config, XklConfigItem * pitem	/* in/out */
Packit Service 93d855
    )
Packit Service 93d855
{
Packit Service 93d855
	xmlNodePtr node = NULL;
Packit Service 93d855
	gboolean rv = xkl_config_registry_find_object(config,
Packit Service 93d855
						      XKBCR_GROUP_PATH
Packit Service 93d855
						      "[configItem/name = '%s%s']",
Packit Service 93d855
						      "", pitem, &node);
Packit Service 93d855
	if (rv) {
Packit Service 93d855
		xmlChar *val = xmlGetProp(node, (unsigned char *)
Packit Service 93d855
					  XCI_PROP_ALLOW_MULTIPLE_SELECTION);
Packit Service 93d855
		if (val != NULL) {
Packit Service 93d855
			gboolean allow_multisel =
Packit Service 93d855
			    !g_ascii_strcasecmp("true",
Packit Service 93d855
						(char *) val);
Packit Service 93d855
			g_object_set_data(G_OBJECT(pitem),
Packit Service 93d855
					  XCI_PROP_ALLOW_MULTIPLE_SELECTION,
Packit Service 93d855
					  GINT_TO_POINTER(allow_multisel));
Packit Service 93d855
			xmlFree(val);
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_find_option(XklConfigRegistry *
Packit Service 93d855
				config,
Packit Service 93d855
				const char
Packit Service 93d855
				*option_group_name,
Packit Service 93d855
				XklConfigItem * pitem /* in/out */ )
Packit Service 93d855
{
Packit Service 93d855
	return xkl_config_registry_find_object(config,
Packit Service 93d855
					       XKBCR_OPTION_PATH
Packit Service 93d855
					       "[../configItem/name = '%s' and configItem/name = '%s']",
Packit Service 93d855
					       option_group_name,
Packit Service 93d855
					       pitem, NULL);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/*
Packit Service 93d855
 * Calling through vtable
Packit Service 93d855
 */
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_rec_activate(const XklConfigRec * data, XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	xkl_engine_ensure_vtable_inited(engine);
Packit Service 93d855
	return xkl_engine_vcall(engine,
Packit Service 93d855
				activate_config_rec) (engine, data);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_registry_load(XklConfigRegistry * config,
Packit Service 93d855
			 gboolean if_extras_needed)
Packit Service 93d855
{
Packit Service 93d855
	XklEngine *engine;
Packit Service 93d855
	xkl_config_registry_free(config);
Packit Service 93d855
	engine = xkl_config_registry_get_engine(config);
Packit Service 93d855
	xkl_engine_ensure_vtable_inited(engine);
Packit Service 93d855
	return xkl_engine_vcall(engine,
Packit Service 93d855
				load_config_registry) (config,
Packit Service 93d855
						       if_extras_needed);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_config_rec_write_to_file(XklEngine * engine,
Packit Service 93d855
			     const gchar * file_name,
Packit Service 93d855
			     const XklConfigRec * data,
Packit Service 93d855
			     const gboolean binary)
Packit Service 93d855
{
Packit Service 93d855
	if ((!binary
Packit Service 93d855
	     && !(xkl_engine_priv(engine, features) &
Packit Service 93d855
		  XKLF_CAN_OUTPUT_CONFIG_AS_ASCII))
Packit Service 93d855
	    || (binary
Packit Service 93d855
		&& !(xkl_engine_priv(engine, features) &
Packit Service 93d855
		     XKLF_CAN_OUTPUT_CONFIG_AS_BINARY))) {
Packit Service 93d855
		xkl_last_error_message =
Packit Service 93d855
		    "Function not supported at backend";
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
	xkl_engine_ensure_vtable_inited(engine);
Packit Service 93d855
	return xkl_engine_vcall(engine, write_config_rec_to_file)
Packit Service 93d855
	    (engine, file_name, data, binary);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_config_rec_dump(FILE * file, XklConfigRec * data)
Packit Service 93d855
{
Packit Service 93d855
	int j;
Packit Service 93d855
	fprintf(file, "  model: [%s]\n", data->model);
Packit Service 93d855
	fprintf(file, "  layouts:\n");
Packit Service 93d855
#define OUTPUT_ARRZ(arrz) \
Packit Service 93d855
  { \
Packit Service 93d855
    gchar **p = data->arrz; \
Packit Service 93d855
    fprintf( file, "  " #arrz ":\n" ); \
Packit Service 93d855
    if ( p != NULL ) \
Packit Service 93d855
      for( j = 0; *p != NULL; ) \
Packit Service 93d855
        fprintf( file, "  %d: [%s]\n", j++, *p++ ); \
Packit Service 93d855
  }
Packit Service 93d855
	OUTPUT_ARRZ(layouts);
Packit Service 93d855
	OUTPUT_ARRZ(variants);
Packit Service 93d855
	OUTPUT_ARRZ(options);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
G_DEFINE_TYPE(XklConfigRegistry, xkl_config_registry, G_TYPE_OBJECT)
Packit Service 93d855
static GObject *
Packit Service 93d855
xkl_config_registry_constructor(GType type,
Packit Service 93d855
				guint
Packit Service 93d855
				n_construct_properties,
Packit Service 93d855
				GObjectConstructParam *
Packit Service 93d855
				construct_properties)
Packit Service 93d855
{
Packit Service 93d855
	GObject *obj;
Packit Service 93d855
	XklConfigRegistry *config;
Packit Service 93d855
	XklEngine *engine; {
Packit Service 93d855
		/* Invoke parent constructor. */
Packit Service 93d855
		g_type_class_peek(XKL_TYPE_CONFIG_REGISTRY);
Packit Service 93d855
		obj =
Packit Service 93d855
		    parent_class->constructor(type,
Packit Service 93d855
					      n_construct_properties,
Packit Service 93d855
					      construct_properties);
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	config = XKL_CONFIG_REGISTRY(obj);
Packit Service 93d855
	engine = XKL_ENGINE(g_value_peek_pointer
Packit Service 93d855
			    (construct_properties[0].value));
Packit Service 93d855
	xkl_config_registry_get_engine(config) = engine;
Packit Service 93d855
	xkl_engine_ensure_vtable_inited(engine);
Packit Service 93d855
	xkl_engine_vcall(engine, init_config_registry) (config);
Packit Service 93d855
	return obj;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_init(XklConfigRegistry * config)
Packit Service 93d855
{
Packit Service 93d855
	config->priv = g_new0(XklConfigRegistryPrivate, 1);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_set_property(GObject * object,
Packit Service 93d855
				 guint property_id,
Packit Service 93d855
				 const GValue * value, GParamSpec * pspec)
Packit Service 93d855
{
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_get_property(GObject * object,
Packit Service 93d855
				 guint property_id,
Packit Service 93d855
				 GValue * value, GParamSpec * pspec)
Packit Service 93d855
{
Packit Service 93d855
	XklConfigRegistry *config = XKL_CONFIG_REGISTRY(object);
Packit Service 93d855
	switch (property_id) {
Packit Service 93d855
	case PROP_ENGINE:
Packit Service 93d855
		g_value_set_pointer(value,
Packit Service 93d855
				    xkl_config_registry_get_engine
Packit Service 93d855
				    (config));
Packit Service 93d855
		break;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_finalize(GObject * obj)
Packit Service 93d855
{
Packit Service 93d855
	XklConfigRegistry *config = (XklConfigRegistry *) obj;
Packit Service 93d855
	xkl_config_registry_free(config);
Packit Service 93d855
	g_free(config->priv);
Packit Service 93d855
	G_OBJECT_CLASS(parent_class)->finalize(obj);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
/* 
Packit Service 93d855
 * This function is actually NEVER called.
Packit Service 93d855
 * It is 'extern' just to avoid the compilation warnings
Packit Service 93d855
 * TODO: add class cleanup
Packit Service 93d855
 */
Packit Service 93d855
extern void
Packit Service 93d855
xkl_config_registry_class_term(XklConfigRegistryClass * klass)
Packit Service 93d855
{
Packit Service 93d855
	gint i;
Packit Service 93d855
	if (models_xpath != NULL) {
Packit Service 93d855
		xmlXPathFreeCompExpr(models_xpath);
Packit Service 93d855
		models_xpath = NULL;
Packit Service 93d855
	}
Packit Service 93d855
	if (layouts_xpath != NULL) {
Packit Service 93d855
		xmlXPathFreeCompExpr(layouts_xpath);
Packit Service 93d855
		layouts_xpath = NULL;
Packit Service 93d855
	}
Packit Service 93d855
	if (option_groups_xpath != NULL) {
Packit Service 93d855
		xmlXPathFreeCompExpr(option_groups_xpath);
Packit Service 93d855
		option_groups_xpath = NULL;
Packit Service 93d855
	}
Packit Service 93d855
	if (xml_encode_regexen != NULL) {
Packit Service 93d855
		for (i =
Packit Service 93d855
		     sizeof(xml_encode_regexen_str) /
Packit Service 93d855
		     sizeof(xml_encode_regexen_str[0]); --i >= 0;) {
Packit Service 93d855
			g_regex_unref(xml_encode_regexen[i]);
Packit Service 93d855
		}
Packit Service 93d855
		g_free(xml_encode_regexen);
Packit Service 93d855
		xml_encode_regexen = NULL;
Packit Service 93d855
	}
Packit Service 93d855
	if (xml_decode_regexen != NULL) {
Packit Service 93d855
		for (i =
Packit Service 93d855
		     sizeof(xml_decode_regexen_str) /
Packit Service 93d855
		     sizeof(xml_decode_regexen_str[0]); --i >= 0;) {
Packit Service 93d855
			g_regex_unref(xml_decode_regexen[i]);
Packit Service 93d855
		}
Packit Service 93d855
		g_free(xml_decode_regexen);
Packit Service 93d855
		xml_decode_regexen = NULL;
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_registry_class_init(XklConfigRegistryClass * klass)
Packit Service 93d855
{
Packit Service 93d855
	GObjectClass *object_class;
Packit Service 93d855
	GParamSpec *engine_param_spec;
Packit Service 93d855
	gint i;
Packit Service 93d855
	object_class = (GObjectClass *) klass;
Packit Service 93d855
	parent_class = g_type_class_peek_parent(object_class);
Packit Service 93d855
	object_class->constructor = xkl_config_registry_constructor;
Packit Service 93d855
	object_class->finalize = xkl_config_registry_finalize;
Packit Service 93d855
	object_class->set_property = xkl_config_registry_set_property;
Packit Service 93d855
	object_class->get_property = xkl_config_registry_get_property;
Packit Service 93d855
	bind_textdomain_codeset(XKB_DOMAIN, "UTF-8");
Packit Service 93d855
	engine_param_spec =
Packit Service 93d855
	    g_param_spec_object("engine", "Engine", "XklEngine",
Packit Service 93d855
				XKL_TYPE_ENGINE,
Packit Service 93d855
				G_PARAM_CONSTRUCT_ONLY |
Packit Service 93d855
				G_PARAM_READWRITE);
Packit Service 93d855
	g_object_class_install_property(object_class, PROP_ENGINE,
Packit Service 93d855
					engine_param_spec);
Packit Service 93d855
	/* static stuff initialized */
Packit Service 93d855
	xmlXPathInit();
Packit Service 93d855
	models_xpath = xmlXPathCompile((unsigned char *)
Packit Service 93d855
				       XKBCR_MODEL_PATH);
Packit Service 93d855
	layouts_xpath = xmlXPathCompile((unsigned char *)
Packit Service 93d855
					XKBCR_LAYOUT_PATH);
Packit Service 93d855
	option_groups_xpath = xmlXPathCompile((unsigned char *)
Packit Service 93d855
					      XKBCR_GROUP_PATH);
Packit Service 93d855
	xml_encode_regexen =
Packit Service 93d855
	    g_new0(GRegex *,
Packit Service 93d855
		   sizeof(xml_encode_regexen_str) /
Packit Service 93d855
		   sizeof(xml_encode_regexen_str[0]));
Packit Service 93d855
	xml_decode_regexen =
Packit Service 93d855
	    g_new0(GRegex *,
Packit Service 93d855
		   sizeof(xml_decode_regexen_str) /
Packit Service 93d855
		   sizeof(xml_decode_regexen_str[0]));
Packit Service 93d855
	for (i =
Packit Service 93d855
	     sizeof(xml_encode_regexen_str) /
Packit Service 93d855
	     sizeof(xml_encode_regexen_str[0]); --i >= 0;) {
Packit Service 93d855
		xml_encode_regexen[i] =
Packit Service 93d855
		    g_regex_new(xml_encode_regexen_str[i], 0, 0, NULL);
Packit Service 93d855
		xml_decode_regexen[i] =
Packit Service 93d855
		    g_regex_new(xml_decode_regexen_str[i], 0, 0, NULL);
Packit Service 93d855
	}
Packit Service 93d855
}