Blame libxklavier/xklavier_config_xkb.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 <string.h>
Packit Service 93d855
#include <unistd.h>
Packit Service 93d855
#include <sys/param.h>
Packit Service 93d855
#include <sys/stat.h>
Packit Service 93d855
#include <sys/wait.h>
Packit Service 93d855
Packit Service 93d855
#include <sys/types.h>
Packit Service 93d855
#include <fcntl.h>
Packit Service 93d855
Packit Service 93d855
#include <libxml/xpath.h>
Packit Service 93d855
Packit Service 93d855
#include "config.h"
Packit Service 93d855
Packit Service 93d855
#include "xklavier_private.h"
Packit Service 93d855
#include "xklavier_private_xkb.h"
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
#include <X11/extensions/XKBfile.h>
Packit Service 93d855
#include <X11/extensions/XKM.h>
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
#define XKBCOMP ( XKB_BIN_BASE "/xkbcomp" )
Packit Service 93d855
Packit Service 93d855
#define XK_XKB_KEYS
Packit Service 93d855
#include <X11/keysymdef.h>
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
static XkbRF_RulesPtr xkl_rules;
Packit Service 93d855
Packit Service 93d855
static XkbRF_RulesPtr
Packit Service 93d855
xkl_rules_set_load(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	XkbRF_RulesPtr rules_set = NULL;
Packit Service 93d855
	char file_name[MAXPATHLEN] = "";
Packit Service 93d855
	char *rf =
Packit Service 93d855
	    xkl_engine_get_ruleset_name(engine, XKB_DEFAULT_RULESET);
Packit Service 93d855
	char *locale = NULL;
Packit Service 93d855
Packit Service 93d855
	if (rf == NULL) {
Packit Service 93d855
		xkl_last_error_message =
Packit Service 93d855
		    "Could not find the XKB rules set";
Packit Service 93d855
		return NULL;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	locale = setlocale(LC_ALL, NULL);
Packit Service 93d855
Packit Service 93d855
	g_snprintf(file_name, sizeof file_name, XKB_BASE "/rules/%s", rf);
Packit Service 93d855
	xkl_debug(160, "Loading rules from [%s]\n", file_name);
Packit Service 93d855
Packit Service 93d855
	rules_set = XkbRF_Load(file_name, locale, True, True);
Packit Service 93d855
Packit Service 93d855
	if (rules_set == NULL) {
Packit Service 93d855
		xkl_last_error_message = "Could not load rules";
Packit Service 93d855
		return NULL;
Packit Service 93d855
	}
Packit Service 93d855
	return rules_set;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_rules_set_free(void)
Packit Service 93d855
{
Packit Service 93d855
	if (xkl_rules)
Packit Service 93d855
		XkbRF_Free(xkl_rules, True);
Packit Service 93d855
	xkl_rules = NULL;
Packit Service 93d855
}
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_init_config_registry(XklConfigRegistry * config)
Packit Service 93d855
{
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
	XkbInitAtoms(NULL);
Packit Service 93d855
#endif
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_load_config_registry(XklConfigRegistry * config,
Packit Service 93d855
			     gboolean if_extras_needed)
Packit Service 93d855
{
Packit Service 93d855
	return xkl_config_registry_load_helper(config,
Packit Service 93d855
					       XKB_DEFAULT_RULESET,
Packit Service 93d855
					       XKB_BASE "/rules",
Packit Service 93d855
					       if_extras_needed);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_config_native_prepare(XklEngine * engine,
Packit Service 93d855
			      const XklConfigRec * data,
Packit Service 93d855
			      XkbComponentNamesPtr component_names_ptr)
Packit Service 93d855
{
Packit Service 93d855
	XkbRF_VarDefsRec xkl_var_defs;
Packit Service 93d855
	gboolean got_components;
Packit Service 93d855
Packit Service 93d855
	memset(&xkl_var_defs, 0, sizeof(xkl_var_defs));
Packit Service 93d855
Packit Service 93d855
	xkl_rules = xkl_rules_set_load(engine);
Packit Service 93d855
	if (!xkl_rules) {
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	xkl_var_defs.model = (char *) data->model;
Packit Service 93d855
Packit Service 93d855
	if (data->layouts != NULL)
Packit Service 93d855
		xkl_var_defs.layout = xkl_config_rec_merge_layouts(data);
Packit Service 93d855
Packit Service 93d855
	if (data->variants != NULL)
Packit Service 93d855
		xkl_var_defs.variant = xkl_config_rec_merge_variants(data);
Packit Service 93d855
Packit Service 93d855
	if (data->options != NULL)
Packit Service 93d855
		xkl_var_defs.options = xkl_config_rec_merge_options(data);
Packit Service 93d855
Packit Service 93d855
	got_components =
Packit Service 93d855
	    XkbRF_GetComponents(xkl_rules, &xkl_var_defs,
Packit Service 93d855
				component_names_ptr);
Packit Service 93d855
Packit Service 93d855
	g_free(xkl_var_defs.layout);
Packit Service 93d855
	g_free(xkl_var_defs.variant);
Packit Service 93d855
	g_free(xkl_var_defs.options);
Packit Service 93d855
Packit Service 93d855
	if (!got_components) {
Packit Service 93d855
		xkl_last_error_message =
Packit Service 93d855
		    "Could not translate rules into components";
Packit Service 93d855
		/* Just cleanup the stuff in case of failure */
Packit Service 93d855
		xkl_xkb_config_native_cleanup(engine, component_names_ptr);
Packit Service 93d855
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	if (xkl_debug_level >= 200) {
Packit Service 93d855
		xkl_debug(200, "keymap: %s\n",
Packit Service 93d855
			  component_names_ptr->keymap);
Packit Service 93d855
		xkl_debug(200, "keycodes: %s\n",
Packit Service 93d855
			  component_names_ptr->keycodes);
Packit Service 93d855
		xkl_debug(200, "compat: %s\n",
Packit Service 93d855
			  component_names_ptr->compat);
Packit Service 93d855
		xkl_debug(200, "types: %s\n", component_names_ptr->types);
Packit Service 93d855
		xkl_debug(200, "symbols: %s\n",
Packit Service 93d855
			  component_names_ptr->symbols);
Packit Service 93d855
		xkl_debug(200, "geometry: %s\n",
Packit Service 93d855
			  component_names_ptr->geometry);
Packit Service 93d855
	}
Packit Service 93d855
	return TRUE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_config_native_cleanup(XklEngine * engine,
Packit Service 93d855
			      XkbComponentNamesPtr component_names_ptr)
Packit Service 93d855
{
Packit Service 93d855
	xkl_rules_set_free();
Packit Service 93d855
Packit Service 93d855
	g_free(component_names_ptr->keymap);
Packit Service 93d855
	g_free(component_names_ptr->keycodes);
Packit Service 93d855
	g_free(component_names_ptr->compat);
Packit Service 93d855
	g_free(component_names_ptr->types);
Packit Service 93d855
	g_free(component_names_ptr->symbols);
Packit Service 93d855
	g_free(component_names_ptr->geometry);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static gchar *
Packit Service 93d855
xkl_config_get_current_group_description(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	XklState state;
Packit Service 93d855
Packit Service 93d855
	xkl_xkb_get_server_state(engine, &state);
Packit Service 93d855
Packit Service 93d855
	int group = state.group;
Packit Service 93d855
	if ((group < 0) ||
Packit Service 93d855
	    (group >=
Packit Service 93d855
	     xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
				cached_desc)->ctrls->num_groups))
Packit Service 93d855
		return NULL;
Packit Service 93d855
Packit Service 93d855
	return g_strdup(xkl_engine_backend(engine, XklXkb, group_names)
Packit Service 93d855
			[group]);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static void
Packit Service 93d855
xkl_config_set_group_by_description(XklEngine * engine, gchar * descr)
Packit Service 93d855
{
Packit Service 93d855
	int group, n_groups;
Packit Service 93d855
	gchar **group_names;
Packit Service 93d855
Packit Service 93d855
	if (descr == NULL)
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	// perhaps could be made mode lightweight?
Packit Service 93d855
	xkl_engine_reset_all_info(engine, FALSE,
Packit Service 93d855
				  "Direct reload on activation");
Packit Service 93d855
Packit Service 93d855
	n_groups =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXkb,
Packit Service 93d855
			       cached_desc)->ctrls->num_groups;
Packit Service 93d855
	group_names = xkl_engine_backend(engine, XklXkb, group_names);
Packit Service 93d855
Packit Service 93d855
	for (group = 0; group < n_groups; group++, group_names++) {
Packit Service 93d855
		if (!g_ascii_strcasecmp(descr, *group_names)) {
Packit Service 93d855
			xkl_debug(150,
Packit Service 93d855
				  "Found the group with the same description, %d: [%s]\n",
Packit Service 93d855
				  group, *group_names);
Packit Service 93d855
			xkl_engine_lock_group(engine, group);
Packit Service 93d855
			break;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	g_free(descr);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
static XkbDescPtr
Packit Service 93d855
xkl_config_get_keyboard(XklEngine * engine,
Packit Service 93d855
			XkbComponentNamesPtr component_names_ptr,
Packit Service 93d855
			gboolean activate)
Packit Service 93d855
{
Packit Service 93d855
	XkbDescPtr xkb = NULL;
Packit Service 93d855
Packit Service 93d855
	char xkm_fn[L_tmpnam];
Packit Service 93d855
	char xkb_fn[L_tmpnam];
Packit Service 93d855
	FILE *tmpxkm;
Packit Service 93d855
	XkbFileInfo result;
Packit Service 93d855
	int xkmloadres;
Packit Service 93d855
Packit Service 93d855
	Display *display = xkl_engine_get_display(engine);
Packit Service 93d855
Packit Service 93d855
	gchar *preactivation_group_description = activate ?
Packit Service 93d855
	    xkl_config_get_current_group_description(engine) : NULL;
Packit Service 93d855
Packit Service 93d855
	if (tmpnam(xkm_fn) != NULL && tmpnam(xkb_fn) != NULL) {
Packit Service 93d855
		pid_t cpid, pid;
Packit Service 93d855
		int status = 0;
Packit Service 93d855
		FILE *tmpxkb;
Packit Service 93d855
Packit Service 93d855
		xkl_debug(150, "tmp XKB/XKM file names: [%s]/[%s]\n",
Packit Service 93d855
			  xkb_fn, xkm_fn);
Packit Service 93d855
		if ((tmpxkb = fopen(xkb_fn, "w")) != NULL) {
Packit Service 93d855
			fprintf(tmpxkb, "xkb_keymap {\n");
Packit Service 93d855
			fprintf(tmpxkb,
Packit Service 93d855
				"        xkb_keycodes  { include \"%s\" };\n",
Packit Service 93d855
				component_names_ptr->keycodes);
Packit Service 93d855
			fprintf(tmpxkb,
Packit Service 93d855
				"        xkb_types     { include \"%s\" };\n",
Packit Service 93d855
				component_names_ptr->types);
Packit Service 93d855
			fprintf(tmpxkb,
Packit Service 93d855
				"        xkb_compat    { include \"%s\" };\n",
Packit Service 93d855
				component_names_ptr->compat);
Packit Service 93d855
			fprintf(tmpxkb,
Packit Service 93d855
				"        xkb_symbols   { include \"%s\" };\n",
Packit Service 93d855
				component_names_ptr->symbols);
Packit Service 93d855
			fprintf(tmpxkb,
Packit Service 93d855
				"        xkb_geometry  { include \"%s\" };\n",
Packit Service 93d855
				component_names_ptr->geometry);
Packit Service 93d855
			fprintf(tmpxkb, "};\n");
Packit Service 93d855
			fclose(tmpxkb);
Packit Service 93d855
Packit Service 93d855
			xkl_debug(150, "xkb_keymap {\n"
Packit Service 93d855
				  "        xkb_keycodes  { include \"%s\" };\n"
Packit Service 93d855
				  "        xkb_types     { include \"%s\" };\n"
Packit Service 93d855
				  "        xkb_compat    { include \"%s\" };\n"
Packit Service 93d855
				  "        xkb_symbols   { include \"%s\" };\n"
Packit Service 93d855
				  "        xkb_geometry  { include \"%s\" };\n};\n",
Packit Service 93d855
				  component_names_ptr->keycodes,
Packit Service 93d855
				  component_names_ptr->types,
Packit Service 93d855
				  component_names_ptr->compat,
Packit Service 93d855
				  component_names_ptr->symbols,
Packit Service 93d855
				  component_names_ptr->geometry);
Packit Service 93d855
Packit Service 93d855
			XSync(display, False);
Packit Service 93d855
			/* From this point, ALL errors should be intercepted only by libxklavier */
Packit Service 93d855
			xkl_engine_priv(engine, critical_section) = TRUE;
Packit Service 93d855
Packit Service 93d855
			cpid = fork();
Packit Service 93d855
			switch (cpid) {
Packit Service 93d855
			case -1:
Packit Service 93d855
				xkl_debug(0, "Could not fork: %d\n",
Packit Service 93d855
					  errno);
Packit Service 93d855
				break;
Packit Service 93d855
			case 0:
Packit Service 93d855
				/* child */
Packit Service 93d855
				xkl_debug(160, "Executing %s\n", XKBCOMP);
Packit Service 93d855
				xkl_debug(160, "%s %s %s %s %s %s %s %s\n",
Packit Service 93d855
					  XKBCOMP, XKBCOMP, "-w0", "-I",
Packit Service 93d855
					  "-I" XKB_BASE, "-xkm", xkb_fn,
Packit Service 93d855
					  xkm_fn);
Packit Service 93d855
				execl(XKBCOMP, XKBCOMP, "-w0", "-I",
Packit Service 93d855
				      "-I" XKB_BASE, "-xkm", xkb_fn,
Packit Service 93d855
				      xkm_fn, NULL);
Packit Service 93d855
				xkl_debug(0, "Could not exec %s: %d\n",
Packit Service 93d855
					  XKBCOMP, errno);
Packit Service 93d855
				exit(1);
Packit Service 93d855
			default:
Packit Service 93d855
				/* parent */
Packit Service 93d855
				pid = waitpid(cpid, &status, 0);
Packit Service 93d855
				xkl_debug(150,
Packit Service 93d855
					  "Return status of %d (well, started %d): %d\n",
Packit Service 93d855
					  pid, cpid, status);
Packit Service 93d855
				memset((char *) &result, 0,
Packit Service 93d855
				       sizeof(result));
Packit Service 93d855
				result.xkb = XkbAllocKeyboard();
Packit Service 93d855
Packit Service 93d855
				if (Success ==
Packit Service 93d855
				    XkbChangeKbdDisplay(display,
Packit Service 93d855
							&result)) {
Packit Service 93d855
					xkl_debug(150,
Packit Service 93d855
						  "Hacked the kbddesc - set the display...\n");
Packit Service 93d855
					if ((tmpxkm =
Packit Service 93d855
					     fopen(xkm_fn, "r")) != NULL) {
Packit Service 93d855
						xkmloadres =
Packit Service 93d855
						    XkmReadFile(tmpxkm,
Packit Service 93d855
								XkmKeymapLegal,
Packit Service 93d855
								XkmKeymapLegal,
Packit Service 93d855
								&result);
Packit Service 93d855
						xkl_debug(150,
Packit Service 93d855
							  "Loaded %s output as XKM file, got %d (comparing to %d)\n",
Packit Service 93d855
							  XKBCOMP,
Packit Service 93d855
							  (int) xkmloadres,
Packit Service 93d855
							  (int)
Packit Service 93d855
							  XkmKeymapLegal);
Packit Service 93d855
						if ((int) xkmloadres !=
Packit Service 93d855
						    (int) XkmKeymapLegal) {
Packit Service 93d855
							xkl_debug(150,
Packit Service 93d855
								  "Loaded legal keymap\n");
Packit Service 93d855
							if (activate) {
Packit Service 93d855
								xkl_debug
Packit Service 93d855
								    (150,
Packit Service 93d855
								     "Activating it...\n");
Packit Service 93d855
								if (XkbWriteToServer(&result)) {
Packit Service 93d855
									xkl_debug
Packit Service 93d855
									    (150,
Packit Service 93d855
									     "Updating the keyboard...\n");
Packit Service 93d855
									xkb = result.xkb;
Packit Service 93d855
								} else {
Packit Service 93d855
									xkl_debug
Packit Service 93d855
									    (0,
Packit Service 93d855
									     "Could not write keyboard description to the server\n");
Packit Service 93d855
								}
Packit Service 93d855
							} else	/* no activate, just load */
Packit Service 93d855
								xkb =
Packit Service 93d855
								    result.xkb;
Packit Service 93d855
						} else {	/* could not load properly */
Packit Service 93d855
Packit Service 93d855
							xkl_debug(0,
Packit Service 93d855
								  "Could not load %s output as XKM file, got %d (asked %d)\n",
Packit Service 93d855
								  XKBCOMP,
Packit Service 93d855
								  (int)
Packit Service 93d855
								  xkmloadres,
Packit Service 93d855
								  (int)
Packit Service 93d855
								  XkmKeymapLegal);
Packit Service 93d855
						}
Packit Service 93d855
						fclose(tmpxkm);
Packit Service 93d855
						xkl_debug(160,
Packit Service 93d855
							  "Unlinking the temporary xkm file %s\n",
Packit Service 93d855
							  xkm_fn);
Packit Service 93d855
						if (xkl_debug_level < 500) {	/* don't remove on high debug levels! */
Packit Service 93d855
							if (remove(xkm_fn)
Packit Service 93d855
							    == -1)
Packit Service 93d855
								xkl_debug
Packit Service 93d855
								    (0,
Packit Service 93d855
								     "Could not unlink the temporary xkm file %s: %d\n",
Packit Service 93d855
								     xkm_fn,
Packit Service 93d855
								     errno);
Packit Service 93d855
						} else
Packit Service 93d855
							xkl_debug(500,
Packit Service 93d855
								  "Well, not really - the debug level is too high: %d\n",
Packit Service 93d855
								  xkl_debug_level);
Packit Service 93d855
					} else {	/* could not open the file */
Packit Service 93d855
Packit Service 93d855
						xkl_debug(0,
Packit Service 93d855
							  "Could not open the temporary xkm file %s\n",
Packit Service 93d855
							  xkm_fn);
Packit Service 93d855
					}
Packit Service 93d855
				} else {	/* could not assign to display */
Packit Service 93d855
Packit Service 93d855
					xkl_debug(0,
Packit Service 93d855
						  "Could not change the keyboard description to display\n");
Packit Service 93d855
				}
Packit Service 93d855
				if (xkb == NULL)
Packit Service 93d855
					XkbFreeKeyboard(result.xkb,
Packit Service 93d855
							XkbAllComponentsMask,
Packit Service 93d855
							True);
Packit Service 93d855
				break;
Packit Service 93d855
			}
Packit Service 93d855
			XSync(display, False);
Packit Service 93d855
			/* Return to normal X error processing */
Packit Service 93d855
			xkl_engine_priv(engine, critical_section) = FALSE;
Packit Service 93d855
Packit Service 93d855
			if (activate)
Packit Service 93d855
				xkl_config_set_group_by_description(engine,
Packit Service 93d855
								    preactivation_group_description);
Packit Service 93d855
Packit Service 93d855
			xkl_debug(160,
Packit Service 93d855
				  "Unlinking the temporary xkb file %s\n",
Packit Service 93d855
				  xkb_fn);
Packit Service 93d855
			if (xkl_debug_level < 500) {	/* don't remove on high debug levels! */
Packit Service 93d855
				if (remove(xkb_fn) == -1)
Packit Service 93d855
					xkl_debug(0,
Packit Service 93d855
						  "Could not unlink the temporary xkb file %s: %d\n",
Packit Service 93d855
						  xkb_fn, errno);
Packit Service 93d855
			} else
Packit Service 93d855
				xkl_debug(500,
Packit Service 93d855
					  "Well, not really - the debug level is too high: %d\n",
Packit Service 93d855
					  xkl_debug_level);
Packit Service 93d855
		} else {	/* could not open input tmp file */
Packit Service 93d855
Packit Service 93d855
			xkl_debug(0,
Packit Service 93d855
				  "Could not open tmp XKB file [%s]: %d\n",
Packit Service 93d855
				  xkb_fn, errno);
Packit Service 93d855
		}
Packit Service 93d855
	} else {
Packit Service 93d855
		xkl_debug(0, "Could not get tmp names\n");
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	return xkb;
Packit Service 93d855
}
Packit Service 93d855
#else				/* no XKB headers */
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_config_native_prepare(XklEngine * engine,
Packit Service 93d855
			      const XklConfigRec * data,
Packit Service 93d855
			      gpointer componentNamesPtr)
Packit Service 93d855
{
Packit Service 93d855
	return FALSE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xkb_config_native_cleanup(XklEngine * engine,
Packit Service 93d855
			      gpointer component_names_ptr)
Packit Service 93d855
{
Packit Service 93d855
}
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
/* check only client side support */
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_multiple_layouts_supported(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	enum { NON_SUPPORTED, SUPPORTED, UNCHECKED };
Packit Service 93d855
Packit Service 93d855
	static int support_state = UNCHECKED;
Packit Service 93d855
Packit Service 93d855
	if (support_state == UNCHECKED) {
Packit Service 93d855
		XklConfigRec *data = xkl_config_rec_new();
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
		XkbComponentNamesRec component_names;
Packit Service 93d855
		memset(&component_names, 0, sizeof(component_names));
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
		data->model = g_strdup("pc105");
Packit Service 93d855
		data->layouts = g_strsplit_set("us:de", ":", -1);
Packit Service 93d855
		data->variants = g_strsplit_set(":", ":", -1);
Packit Service 93d855
		data->options = NULL;
Packit Service 93d855
Packit Service 93d855
		xkl_debug(100, "!!! Checking multiple layouts support\n");
Packit Service 93d855
		support_state = NON_SUPPORTED;
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
		if (xkl_xkb_config_native_prepare
Packit Service 93d855
		    (engine, data, &component_names)) {
Packit Service 93d855
			xkl_debug(100,
Packit Service 93d855
				  "!!! Multiple layouts ARE supported\n");
Packit Service 93d855
			support_state = SUPPORTED;
Packit Service 93d855
			xkl_xkb_config_native_cleanup(engine,
Packit Service 93d855
						      &component_names);
Packit Service 93d855
		} else {
Packit Service 93d855
			xkl_debug(100,
Packit Service 93d855
				  "!!! Multiple layouts ARE NOT supported\n");
Packit Service 93d855
		}
Packit Service 93d855
#endif
Packit Service 93d855
		g_object_unref(G_OBJECT(data));
Packit Service 93d855
	}
Packit Service 93d855
	return support_state == SUPPORTED;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_activate_config_rec(XklEngine * engine, const XklConfigRec * data)
Packit Service 93d855
{
Packit Service 93d855
	gboolean rv = FALSE;
Packit Service 93d855
#if 0
Packit Service 93d855
	{
Packit Service 93d855
		int i;
Packit Service 93d855
		xkl_debug(150, "New model: [%s]\n", data->model);
Packit Service 93d855
		xkl_debug(150, "New layouts: %p\n", data->layouts);
Packit Service 93d855
		for (i = 0; i < g_strv_length(data->layouts); i++)
Packit Service 93d855
			xkl_debug(150, "New layout[%d]: [%s]\n", i,
Packit Service 93d855
				  data->layouts[i]);
Packit Service 93d855
		xkl_debug(150, "New variants: %p\n", data->variants);
Packit Service 93d855
		for (i = 0; i < g_strv_length(data->variants); i++)
Packit Service 93d855
			xkl_debug(150, "New variant[%d]: [%s]\n", i,
Packit Service 93d855
				  data->variants[i]);
Packit Service 93d855
		xkl_debug(150, "New options: %p\n", data->options);
Packit Service 93d855
		for (i = 0; i < g_strv_length(data->options); i++)
Packit Service 93d855
			xkl_debug(150, "New option[%d]: [%s]\n", i,
Packit Service 93d855
				  data->options[i]);
Packit Service 93d855
	}
Packit Service 93d855
#endif
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
	XkbComponentNamesRec component_names;
Packit Service 93d855
	memset(&component_names, 0, sizeof(component_names));
Packit Service 93d855
Packit Service 93d855
	if (xkl_xkb_config_native_prepare(engine, data, &component_names)) {
Packit Service 93d855
		XkbDescPtr xkb;
Packit Service 93d855
		xkb =
Packit Service 93d855
		    xkl_config_get_keyboard(engine, &component_names,
Packit Service 93d855
					    TRUE);
Packit Service 93d855
		if (xkb != NULL) {
Packit Service 93d855
			if (xkl_config_rec_set_to_root_window_property
Packit Service 93d855
			    (data,
Packit Service 93d855
			     xkl_engine_priv(engine, base_config_atom),
Packit Service 93d855
			     xkl_engine_get_ruleset_name(engine,
Packit Service 93d855
							 XKB_DEFAULT_RULESET),
Packit Service 93d855
			     engine))
Packit Service 93d855
				/* We do not need to check the result of _XklGetRulesSetName - 
Packit Service 93d855
				   because PrepareBeforeKbd did it for us */
Packit Service 93d855
				rv = TRUE;
Packit Service 93d855
			else
Packit Service 93d855
				xkl_last_error_message =
Packit Service 93d855
				    "Could not set names property";
Packit Service 93d855
			XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
Packit Service 93d855
		} else {
Packit Service 93d855
			xkl_last_error_message =
Packit Service 93d855
			    "Could not load keyboard description";
Packit Service 93d855
		}
Packit Service 93d855
		xkl_xkb_config_native_cleanup(engine, &component_names);
Packit Service 93d855
	}
Packit Service 93d855
#endif
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xkb_write_config_rec_to_file(XklEngine * engine, const char *file_name,
Packit Service 93d855
				 const XklConfigRec * data,
Packit Service 93d855
				 const gboolean binary)
Packit Service 93d855
{
Packit Service 93d855
	gboolean rv = FALSE;
Packit Service 93d855
Packit Service 93d855
#ifdef LIBXKBFILE_PRESENT
Packit Service 93d855
	XkbComponentNamesRec component_names;
Packit Service 93d855
	FILE *output = fopen(file_name, "w");
Packit Service 93d855
	XkbFileInfo dump_info;
Packit Service 93d855
Packit Service 93d855
	if (output == NULL) {
Packit Service 93d855
		xkl_last_error_message = "Could not open the XKB file";
Packit Service 93d855
		return FALSE;
Packit Service 93d855
	}
Packit Service 93d855
Packit Service 93d855
	memset(&component_names, 0, sizeof(component_names));
Packit Service 93d855
Packit Service 93d855
	if (xkl_xkb_config_native_prepare(engine, data, &component_names)) {
Packit Service 93d855
		XkbDescPtr xkb;
Packit Service 93d855
		xkb =
Packit Service 93d855
		    xkl_config_get_keyboard(engine, &component_names,
Packit Service 93d855
					    FALSE);
Packit Service 93d855
		if (xkb != NULL) {
Packit Service 93d855
			dump_info.defined = 0;
Packit Service 93d855
			dump_info.xkb = xkb;
Packit Service 93d855
			dump_info.type = XkmKeymapFile;
Packit Service 93d855
			if (binary)
Packit Service 93d855
				rv = XkbWriteXKMFile(output, &dump_info);
Packit Service 93d855
			else
Packit Service 93d855
				rv = XkbWriteXKBFile(output, &dump_info,
Packit Service 93d855
						     True, NULL, NULL);
Packit Service 93d855
Packit Service 93d855
			XkbFreeKeyboard(xkb, XkbGBN_AllComponentsMask,
Packit Service 93d855
					True);
Packit Service 93d855
		} else
Packit Service 93d855
			xkl_last_error_message =
Packit Service 93d855
			    "Could not load keyboard description";
Packit Service 93d855
		xkl_xkb_config_native_cleanup(engine, &component_names);
Packit Service 93d855
	}
Packit Service 93d855
	fclose(output);
Packit Service 93d855
#endif
Packit Service 93d855
	return rv;
Packit Service 93d855
}