setxkbmap.c revision 7d5e3a19
17d5e3a19Smrg/* $XdotOrg: app/setxkbmap/setxkbmap.c,v 1.2 2004/04/23 19:54:37 eich Exp $ */
27d5e3a19Smrg/************************************************************
37d5e3a19Smrg Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
47d5e3a19Smrg
57d5e3a19Smrg Permission to use, copy, modify, and distribute this
67d5e3a19Smrg software and its documentation for any purpose and without
77d5e3a19Smrg fee is hereby granted, provided that the above copyright
87d5e3a19Smrg notice appear in all copies and that both that copyright
97d5e3a19Smrg notice and this permission notice appear in supporting
107d5e3a19Smrg documentation, and that the name of Silicon Graphics not be
117d5e3a19Smrg used in advertising or publicity pertaining to distribution
127d5e3a19Smrg of the software without specific prior written permission.
137d5e3a19Smrg Silicon Graphics makes no representation about the suitability
147d5e3a19Smrg of this software for any purpose. It is provided "as is"
157d5e3a19Smrg without any express or implied warranty.
167d5e3a19Smrg
177d5e3a19Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
187d5e3a19Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
197d5e3a19Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
207d5e3a19Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
217d5e3a19Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
227d5e3a19Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
237d5e3a19Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
247d5e3a19Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
257d5e3a19Smrg
267d5e3a19Smrg ********************************************************/
277d5e3a19Smrg/* $XFree86: xc/programs/setxkbmap/setxkbmap.c,v 3.7 2003/01/20 04:15:08 dawes Exp $ */
287d5e3a19Smrg
297d5e3a19Smrg#include <stdio.h>
307d5e3a19Smrg#include <stdlib.h>
317d5e3a19Smrg#include <locale.h>
327d5e3a19Smrg#include <limits.h>
337d5e3a19Smrg#include <ctype.h>
347d5e3a19Smrg#include <X11/Xlib.h>
357d5e3a19Smrg#include <X11/Xos.h>
367d5e3a19Smrg#include <X11/XKBlib.h>
377d5e3a19Smrg#include <X11/extensions/XKBfile.h>
387d5e3a19Smrg#include <X11/extensions/XKBconfig.h>
397d5e3a19Smrg#include <X11/extensions/XKBrules.h>
407d5e3a19Smrg
417d5e3a19Smrg#ifndef PATH_MAX
427d5e3a19Smrg#ifdef MAXPATHLEN
437d5e3a19Smrg#define PATH_MAX MAXPATHLEN
447d5e3a19Smrg#else
457d5e3a19Smrg#define PATH_MAX 1024
467d5e3a19Smrg#endif
477d5e3a19Smrg#endif
487d5e3a19Smrg
497d5e3a19Smrg#ifndef DFLT_XKB_CONFIG_ROOT
507d5e3a19Smrg#define	DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb"
517d5e3a19Smrg#endif
527d5e3a19Smrg#ifndef DFLT_XKB_RULES_FILE
537d5e3a19Smrg#define	DFLT_XKB_RULES_FILE __XKBDEFRULES__
547d5e3a19Smrg#endif
557d5e3a19Smrg#ifndef DFLT_XKB_LAYOUT
567d5e3a19Smrg#define	DFLT_XKB_LAYOUT "us"
577d5e3a19Smrg#endif
587d5e3a19Smrg#ifndef DFLT_XKB_MODEL
597d5e3a19Smrg#define	DFLT_XKB_MODEL "pc105"
607d5e3a19Smrg#endif
617d5e3a19Smrg
627d5e3a19Smrg#define	UNDEFINED	0
637d5e3a19Smrg#define	FROM_SERVER	1
647d5e3a19Smrg#define	FROM_RULES	2
657d5e3a19Smrg#define	FROM_CONFIG	3
667d5e3a19Smrg#define	FROM_CMD_LINE	4
677d5e3a19Smrg#define	NUM_SOURCES	5
687d5e3a19Smrg
697d5e3a19Smrg#define	RULES_NDX	0
707d5e3a19Smrg#define	CONFIG_NDX	1
717d5e3a19Smrg#define	DISPLAY_NDX	2
727d5e3a19Smrg#define	LOCALE_NDX	3
737d5e3a19Smrg#define	MODEL_NDX	4
747d5e3a19Smrg#define	LAYOUT_NDX	5
757d5e3a19Smrg#define	VARIANT_NDX	6
767d5e3a19Smrg#define KEYCODES_NDX	7
777d5e3a19Smrg#define	TYPES_NDX	8
787d5e3a19Smrg#define	COMPAT_NDX	9
797d5e3a19Smrg#define	SYMBOLS_NDX	10
807d5e3a19Smrg#define	GEOMETRY_NDX	11
817d5e3a19Smrg#define	KEYMAP_NDX	12
827d5e3a19Smrg#define	NUM_STRING_VALS	13
837d5e3a19Smrg
847d5e3a19Smrg/***====================================================================***/
857d5e3a19SmrgBool			print= False;
867d5e3a19SmrgBool			synch= False;
877d5e3a19Smrgint			verbose= 5;
887d5e3a19Smrg
897d5e3a19SmrgDisplay *		dpy;
907d5e3a19Smrg
917d5e3a19Smrgchar *	srcName[NUM_SOURCES] = {
927d5e3a19Smrg	"undefined", "X server", "rules file", "config file", "command line"
937d5e3a19Smrg};
947d5e3a19Smrg
957d5e3a19Smrgchar *	svName[NUM_STRING_VALS]= {
967d5e3a19Smrg	"rules file", "config file", "X display", "locale",
977d5e3a19Smrg	"keyboard model", "keyboard layout", "layout variant",
987d5e3a19Smrg	"keycodes", "types", "compatibility map", "symbols", "geometry",
997d5e3a19Smrg	"keymap"
1007d5e3a19Smrg};
1017d5e3a19Smrgint	svSrc[NUM_STRING_VALS];
1027d5e3a19Smrgchar *	svValue[NUM_STRING_VALS];
1037d5e3a19Smrg
1047d5e3a19SmrgXkbConfigRtrnRec	cfgResult;
1057d5e3a19Smrg
1067d5e3a19SmrgXkbRF_RulesPtr		rules= NULL;
1077d5e3a19SmrgXkbRF_VarDefsRec	rdefs;
1087d5e3a19Smrg
1097d5e3a19SmrgBool			clearOptions= False;
1107d5e3a19Smrgint			szOptions= 0;
1117d5e3a19Smrgint			numOptions= 0;
1127d5e3a19Smrgchar **			options= NULL;
1137d5e3a19Smrg
1147d5e3a19Smrgint			szInclPath= 0;
1157d5e3a19Smrgint			numInclPath= 0;
1167d5e3a19Smrgchar **			inclPath= NULL;
1177d5e3a19Smrg
1187d5e3a19SmrgXkbDescPtr		xkb= NULL;
1197d5e3a19Smrg
1207d5e3a19Smrgint                     deviceSpec = XkbUseCoreKbd;
1217d5e3a19Smrg
1227d5e3a19Smrg/***====================================================================***/
1237d5e3a19Smrg
1247d5e3a19Smrg#define	streq(s1,s2)	(strcmp(s1,s2)==0)
1257d5e3a19Smrg#define	strpfx(s1,s2)	(strncmp(s1,s2,strlen(s2))==0)
1267d5e3a19Smrg
1277d5e3a19Smrg#define	MSG(s)		printf(s)
1287d5e3a19Smrg#define	MSG1(s,a)	printf(s,a)
1297d5e3a19Smrg#define	MSG2(s,a,b)	printf(s,a,b)
1307d5e3a19Smrg#define	MSG3(s,a,b,c)	printf(s,a,b,c)
1317d5e3a19Smrg
1327d5e3a19Smrg#define	VMSG(l,s)	if (verbose>(l)) printf(s)
1337d5e3a19Smrg#define	VMSG1(l,s,a)	if (verbose>(l)) printf(s,a)
1347d5e3a19Smrg#define	VMSG2(l,s,a,b)	if (verbose>(l)) printf(s,a,b)
1357d5e3a19Smrg#define	VMSG3(l,s,a,b,c) if (verbose>(l)) printf(s,a,b,c)
1367d5e3a19Smrg
1377d5e3a19Smrg#define	ERR(s)		fprintf(stderr,s)
1387d5e3a19Smrg#define	ERR1(s,a)	fprintf(stderr,s,a)
1397d5e3a19Smrg#define	ERR2(s,a,b)	fprintf(stderr,s,a,b)
1407d5e3a19Smrg#define	ERR3(s,a,b,c)	fprintf(stderr,s,a,b,c)
1417d5e3a19Smrg
1427d5e3a19Smrg/***====================================================================***/
1437d5e3a19Smrg
1447d5e3a19SmrgBool addToList ( int *sz, int *num, char ***listIn, char *newVal );
1457d5e3a19Smrgvoid usage ( int argc, char ** argv );
1467d5e3a19Smrgvoid dumpNames ( Bool wantRules, Bool wantCNames );
1477d5e3a19Smrgvoid trySetString ( int which, char * newVal, int src );
1487d5e3a19SmrgBool setOptString ( int *arg, int argc, char **argv, int which, int src );
1497d5e3a19Smrgint parseArgs ( int argc, char ** argv );
1507d5e3a19SmrgBool getDisplay ( int argc, char ** argv );
1517d5e3a19SmrgBool getServerValues ( void );
1527d5e3a19SmrgFILE * findFileInPath ( char * name, char * subdir );
1537d5e3a19SmrgBool addStringToOptions ( char * opt_str, int * sz_opts, int * num_opts, char *** opts );
1547d5e3a19Smrgchar * stringFromOptions ( char * orig, int numNew, char ** newOpts );
1557d5e3a19SmrgBool applyConfig ( char * name );
1567d5e3a19SmrgBool applyRules ( void );
1577d5e3a19SmrgBool applyComponentNames ( void );
1587d5e3a19Smrgvoid printKeymap( void );
1597d5e3a19Smrg
1607d5e3a19Smrg/***====================================================================***/
1617d5e3a19Smrg
1627d5e3a19SmrgBool
1637d5e3a19SmrgaddToList(int *sz,int *num,char ***listIn,char *newVal)
1647d5e3a19Smrg{
1657d5e3a19Smrgregister int i;
1667d5e3a19Smrgchar **list;
1677d5e3a19Smrg
1687d5e3a19Smrg    if ((!newVal)||(!newVal[0])) {
1697d5e3a19Smrg	*num= 0;
1707d5e3a19Smrg	return True;
1717d5e3a19Smrg    }
1727d5e3a19Smrg    list= *listIn;
1737d5e3a19Smrg    for (i=0;i<*num;i++) {
1747d5e3a19Smrg	if (streq(list[i],newVal))
1757d5e3a19Smrg	    return True;
1767d5e3a19Smrg    }
1777d5e3a19Smrg    if ((list==NULL)||(*sz<1)) {
1787d5e3a19Smrg	*num= 0;
1797d5e3a19Smrg	*sz= 4;
1807d5e3a19Smrg	list= (char **)calloc(*sz,sizeof(char *));
1817d5e3a19Smrg	*listIn= list;
1827d5e3a19Smrg    }
1837d5e3a19Smrg    else if (*num>=*sz) {
1847d5e3a19Smrg	*sz*= 2;
1857d5e3a19Smrg	list= (char **)realloc(list,(*sz)*sizeof(char *));
1867d5e3a19Smrg	*listIn= list;
1877d5e3a19Smrg    }
1887d5e3a19Smrg    if (!list) {
1897d5e3a19Smrg	ERR("Internal Error! Allocation failure in add to list!\n");
1907d5e3a19Smrg	ERR("                Exiting.\n");
1917d5e3a19Smrg	exit(-1);
1927d5e3a19Smrg    }
1937d5e3a19Smrg    list[*num]= strdup(newVal);
1947d5e3a19Smrg    (*num)= (*num)+1;
1957d5e3a19Smrg    return True;
1967d5e3a19Smrg}
1977d5e3a19Smrg
1987d5e3a19Smrg/***====================================================================***/
1997d5e3a19Smrg
2007d5e3a19Smrgvoid
2017d5e3a19Smrgusage(int argc,char **argv)
2027d5e3a19Smrg{
2037d5e3a19Smrg    MSG1("Usage: %s [args] [<layout> [<variant> [<option> ... ]]]\n",argv[0]);
2047d5e3a19Smrg    MSG("Where legal args are:\n");
2057d5e3a19Smrg    MSG("-?,-help            Print this message\n");
2067d5e3a19Smrg    MSG("-compat <name>      Specifies compatibility map component name\n");
2077d5e3a19Smrg    MSG("-config <file>      Specifies configuration file to use\n");
2087d5e3a19Smrg    MSG("-device <deviceid>  Specifies the device ID to use\n");
2097d5e3a19Smrg    MSG("-display <dpy>      Specifies display to use\n");
2107d5e3a19Smrg    MSG("-geometry <name>    Specifies geometry component name\n");
2117d5e3a19Smrg    MSG("-I[<dir>]           Add <dir> to list of directories to be used\n");
2127d5e3a19Smrg    MSG("-keycodes <name>    Specifies keycodes component name\n");
2137d5e3a19Smrg    MSG("-keymap <name>      Specifies name of keymap to load\n");
2147d5e3a19Smrg    MSG("-layout <name>      Specifies layout used to choose component names\n");
2157d5e3a19Smrg    MSG("-model <name>       Specifies model used to choose component names\n");
2167d5e3a19Smrg    MSG("-option <name>      Adds an option used to choose component names\n");
2177d5e3a19Smrg    MSG("-print              Print a complete xkb_keymap description and exit\n");
2187d5e3a19Smrg    MSG("-rules <name>       Name of rules file to use\n");
2197d5e3a19Smrg    MSG("-symbols <name>     Specifies symbols component name\n");
2207d5e3a19Smrg    MSG("-synch              Synchronize request w/X server\n");
2217d5e3a19Smrg    MSG("-types <name>       Specifies types component name\n");
2227d5e3a19Smrg    MSG("-v[erbose] [<lvl>]  Sets verbosity (1..10).  Higher values yield\n");
2237d5e3a19Smrg    MSG("                    more messages\n");
2247d5e3a19Smrg    MSG("-variant <name>     Specifies layout variant used to choose component names\n");
2257d5e3a19Smrg}
2267d5e3a19Smrg
2277d5e3a19Smrgvoid
2287d5e3a19SmrgdumpNames(Bool wantRules,Bool wantCNames)
2297d5e3a19Smrg{
2307d5e3a19Smrg    if (wantRules) {
2317d5e3a19Smrg	if (svValue[MODEL_NDX])	 MSG1("model:      %s\n",svValue[MODEL_NDX]);
2327d5e3a19Smrg	if (svValue[LAYOUT_NDX])  MSG1("layout:     %s\n",svValue[LAYOUT_NDX]);
2337d5e3a19Smrg	if (svValue[VARIANT_NDX]) MSG1("variant:    %s\n",svValue[VARIANT_NDX]);
2347d5e3a19Smrg	if (options) {
2357d5e3a19Smrg	   char *opt_str=stringFromOptions(NULL, numOptions, options);
2367d5e3a19Smrg	   MSG1("options:    %s\n", opt_str);
2377d5e3a19Smrg	   free(opt_str);
2387d5e3a19Smrg	}
2397d5e3a19Smrg    }
2407d5e3a19Smrg    if (wantCNames) {
2417d5e3a19Smrg	if (svValue[KEYMAP_NDX])
2427d5e3a19Smrg	    MSG1("keymap:     %s\n",svValue[KEYMAP_NDX]);
2437d5e3a19Smrg	if (svValue[KEYCODES_NDX])
2447d5e3a19Smrg	    MSG1("keycodes:   %s\n",svValue[KEYCODES_NDX]);
2457d5e3a19Smrg	if (svValue[TYPES_NDX])
2467d5e3a19Smrg	    MSG1("types:      %s\n",svValue[TYPES_NDX]);
2477d5e3a19Smrg	if (svValue[COMPAT_NDX])
2487d5e3a19Smrg	    MSG1("compat:     %s\n",svValue[COMPAT_NDX]);
2497d5e3a19Smrg	if (svValue[SYMBOLS_NDX])
2507d5e3a19Smrg	    MSG1("symbols:    %s\n",svValue[SYMBOLS_NDX]);
2517d5e3a19Smrg	if (svValue[GEOMETRY_NDX])
2527d5e3a19Smrg	    MSG1("geometry:   %s\n",svValue[GEOMETRY_NDX]);
2537d5e3a19Smrg    }
2547d5e3a19Smrg    return;
2557d5e3a19Smrg}
2567d5e3a19Smrg
2577d5e3a19Smrg/***====================================================================***/
2587d5e3a19Smrg
2597d5e3a19Smrgvoid
2607d5e3a19SmrgtrySetString(int which,char *newVal,int src)
2617d5e3a19Smrg{
2627d5e3a19Smrg    if (svValue[which]!=NULL) {
2637d5e3a19Smrg	if (svSrc[which]==src) {
2647d5e3a19Smrg	    VMSG2(0,"Warning! More than one %s from %s\n",
2657d5e3a19Smrg						svName[which],srcName[src]);
2667d5e3a19Smrg	    VMSG2(0,"         Using \"%s\", ignoring \"%s\"\n",
2677d5e3a19Smrg						svValue[which],newVal);
2687d5e3a19Smrg	    return;
2697d5e3a19Smrg	}
2707d5e3a19Smrg	else if (svSrc[which]>src) {
2717d5e3a19Smrg	    VMSG1(5,"Warning! Multiple definitions of %s\n",svName[which]);
2727d5e3a19Smrg	    VMSG2(5,"         Using %s, ignoring %s\n",srcName[svSrc[which]],
2737d5e3a19Smrg						srcName[src]);
2747d5e3a19Smrg	    return;
2757d5e3a19Smrg	}
2767d5e3a19Smrg    }
2777d5e3a19Smrg    svSrc[which]= src;
2787d5e3a19Smrg    svValue[which]= newVal;
2797d5e3a19Smrg    return;
2807d5e3a19Smrg}
2817d5e3a19Smrg
2827d5e3a19SmrgBool
2837d5e3a19SmrgsetOptString(int *arg,int argc,char **argv,int which,int src)
2847d5e3a19Smrg{
2857d5e3a19Smrgint	ndx;
2867d5e3a19Smrgchar *	opt;
2877d5e3a19Smrg
2887d5e3a19Smrg    ndx= *arg;
2897d5e3a19Smrg    opt= argv[ndx];
2907d5e3a19Smrg    if (ndx>=argc-1) {
2917d5e3a19Smrg	VMSG1(0,"No %s specified on the command line\n",svName[which]);
2927d5e3a19Smrg	VMSG1(0,"Trailing %s option ignored\n",opt);
2937d5e3a19Smrg	return True;
2947d5e3a19Smrg    }
2957d5e3a19Smrg    ndx++;
2967d5e3a19Smrg    *arg= ndx;
2977d5e3a19Smrg    if (svValue[which]!=NULL) {
2987d5e3a19Smrg	if (svSrc[which]==src) {
2997d5e3a19Smrg	    VMSG2(0,"More than one %s on %s\n",svName[which],srcName[src]);
3007d5e3a19Smrg	    VMSG2(0,"Using \"%s\", ignoring \"%s\"\n",svValue[which],argv[ndx]);
3017d5e3a19Smrg	    return True;
3027d5e3a19Smrg	}
3037d5e3a19Smrg	else if (svSrc[which]>src) {
3047d5e3a19Smrg	    VMSG1(5,"Multiple definitions of %s\n",svName[which]);
3057d5e3a19Smrg	    VMSG2(5,"Using %s, ignoring %s\n",srcName[svSrc[which]],
3067d5e3a19Smrg						srcName[src]);
3077d5e3a19Smrg	    return True;
3087d5e3a19Smrg	}
3097d5e3a19Smrg    }
3107d5e3a19Smrg    svSrc[which]= src;
3117d5e3a19Smrg    svValue[which]= argv[ndx];
3127d5e3a19Smrg    return True;
3137d5e3a19Smrg}
3147d5e3a19Smrg
3157d5e3a19Smrg/***====================================================================***/
3167d5e3a19Smrg
3177d5e3a19Smrgint
3187d5e3a19SmrgparseArgs(int argc,char **argv)
3197d5e3a19Smrg{
3207d5e3a19Smrgint 	i;
3217d5e3a19SmrgBool	ok;
3227d5e3a19Smrgunsigned	present;
3237d5e3a19Smrg
3247d5e3a19Smrg    ok= True;
3257d5e3a19Smrg    addToList(&szInclPath,&numInclPath,&inclPath,".");
3267d5e3a19Smrg    addToList(&szInclPath,&numInclPath,&inclPath,DFLT_XKB_CONFIG_ROOT);
3277d5e3a19Smrg    for (i=1;(i<argc)&&ok;i++) {
3287d5e3a19Smrg	if (argv[i][0]!='-') {
3297d5e3a19Smrg	    if (!svSrc[LAYOUT_NDX])
3307d5e3a19Smrg		 trySetString(LAYOUT_NDX,argv[i],FROM_CMD_LINE);
3317d5e3a19Smrg	    else if (!svSrc[VARIANT_NDX])
3327d5e3a19Smrg		 trySetString(VARIANT_NDX,argv[i],FROM_CMD_LINE);
3337d5e3a19Smrg	    else ok= addToList(&szOptions,&numOptions,&options,argv[i]);
3347d5e3a19Smrg	}
3357d5e3a19Smrg	else if (streq(argv[i],"-compat"))
3367d5e3a19Smrg	    ok= setOptString(&i,argc,argv,COMPAT_NDX,FROM_CMD_LINE);
3377d5e3a19Smrg	else if (streq(argv[i],"-config"))
3387d5e3a19Smrg	    ok= setOptString(&i,argc,argv,CONFIG_NDX,FROM_CMD_LINE);
3397d5e3a19Smrg        else if (streq(argv[i],"-device"))
3407d5e3a19Smrg            deviceSpec= atoi(argv[++i]);
3417d5e3a19Smrg	else if (streq(argv[i],"-display"))
3427d5e3a19Smrg	    ok= setOptString(&i,argc,argv,DISPLAY_NDX,FROM_CMD_LINE);
3437d5e3a19Smrg	else if (streq(argv[i],"-geometry"))
3447d5e3a19Smrg	    ok= setOptString(&i,argc,argv,GEOMETRY_NDX,FROM_CMD_LINE);
3457d5e3a19Smrg	else if (streq(argv[i],"-help")||streq(argv[i],"-?")) {
3467d5e3a19Smrg	    usage(argc,argv);
3477d5e3a19Smrg	    exit(0);
3487d5e3a19Smrg	}
3497d5e3a19Smrg	else if (strpfx(argv[i],"-I"))
3507d5e3a19Smrg	    ok= addToList(&szInclPath,&numInclPath,&inclPath,&argv[i][2]);
3517d5e3a19Smrg	else if (streq(argv[i],"-keycodes"))
3527d5e3a19Smrg	    ok= setOptString(&i,argc,argv,KEYCODES_NDX,FROM_CMD_LINE);
3537d5e3a19Smrg	else if (streq(argv[i],"-keymap"))
3547d5e3a19Smrg	    ok= setOptString(&i,argc,argv,KEYMAP_NDX,FROM_CMD_LINE);
3557d5e3a19Smrg	else if (streq(argv[i],"-layout"))
3567d5e3a19Smrg	    ok= setOptString(&i,argc,argv,LAYOUT_NDX,FROM_CMD_LINE);
3577d5e3a19Smrg	else if (streq(argv[i],"-model"))
3587d5e3a19Smrg	    ok= setOptString(&i,argc,argv,MODEL_NDX,FROM_CMD_LINE);
3597d5e3a19Smrg	else if (streq(argv[i],"-option")) {
3607d5e3a19Smrg	    if ((i==argc-1)||(argv[i+1][0]=='\0')||(argv[i+1][0]=='-')) {
3617d5e3a19Smrg		clearOptions= True;
3627d5e3a19Smrg		ok= addToList(&szOptions,&numOptions,&options,"");
3637d5e3a19Smrg                if (i<argc-1 && argv[i+1][0]=='\0')
3647d5e3a19Smrg                   i++;
3657d5e3a19Smrg	    }
3667d5e3a19Smrg	    else {
3677d5e3a19Smrg		ok= addToList(&szOptions,&numOptions,&options,argv[++i]);
3687d5e3a19Smrg	    }
3697d5e3a19Smrg	}
3707d5e3a19Smrg	else if (streq(argv[i],"-print"))
3717d5e3a19Smrg	    print= True;
3727d5e3a19Smrg	else if (streq(argv[i],"-rules"))
3737d5e3a19Smrg	    ok= setOptString(&i,argc,argv,RULES_NDX,FROM_CMD_LINE);
3747d5e3a19Smrg	else if (streq(argv[i],"-symbols"))
3757d5e3a19Smrg	    ok= setOptString(&i,argc,argv,SYMBOLS_NDX,FROM_CMD_LINE);
3767d5e3a19Smrg	else if (streq(argv[i],"-synch"))
3777d5e3a19Smrg	    synch= True;
3787d5e3a19Smrg	else if (streq(argv[i],"-types"))
3797d5e3a19Smrg	    ok= setOptString(&i,argc,argv,TYPES_NDX,FROM_CMD_LINE);
3807d5e3a19Smrg	else if (streq(argv[i],"-verbose")||(streq(argv[i],"-v"))) {
3817d5e3a19Smrg	    if ((i<argc-1)&&(isdigit(argv[i+1][0])))
3827d5e3a19Smrg	 	 verbose= atoi(argv[++i]);
3837d5e3a19Smrg	    else verbose++;
3847d5e3a19Smrg	    if (verbose<0) {
3857d5e3a19Smrg		ERR1("Illegal verbose level %d.  Reset to 0\n",verbose);
3867d5e3a19Smrg		verbose=0;
3877d5e3a19Smrg	    }
3887d5e3a19Smrg	    else if (verbose>10) {
3897d5e3a19Smrg		ERR1("Illegal verbose level %d.  Reset to 10\n",verbose);
3907d5e3a19Smrg		verbose= 10;
3917d5e3a19Smrg	    }
3927d5e3a19Smrg	    VMSG1(7,"Setting verbose level to %d\n",verbose);
3937d5e3a19Smrg	}
3947d5e3a19Smrg	else if (streq(argv[i],"-variant"))
3957d5e3a19Smrg	    ok= setOptString(&i,argc,argv,VARIANT_NDX,FROM_CMD_LINE);
3967d5e3a19Smrg	else {
3977d5e3a19Smrg	    ERR1("Error!   Option \"%s\" not recognized\n",argv[i]);
3987d5e3a19Smrg	    ok= False;
3997d5e3a19Smrg	}
4007d5e3a19Smrg    }
4017d5e3a19Smrg
4027d5e3a19Smrg    present= 0;
4037d5e3a19Smrg    if (svValue[TYPES_NDX])	present++;
4047d5e3a19Smrg    if (svValue[COMPAT_NDX])	present++;
4057d5e3a19Smrg    if (svValue[SYMBOLS_NDX])	present++;
4067d5e3a19Smrg    if (svValue[KEYCODES_NDX])	present++;
4077d5e3a19Smrg    if (svValue[GEOMETRY_NDX])	present++;
4087d5e3a19Smrg    if (svValue[CONFIG_NDX])	present++;
4097d5e3a19Smrg    if (svValue[MODEL_NDX])	present++;
4107d5e3a19Smrg    if (svValue[LAYOUT_NDX])	present++;
4117d5e3a19Smrg    if (svValue[VARIANT_NDX])	present++;
4127d5e3a19Smrg    if (svValue[KEYMAP_NDX] && present) {
4137d5e3a19Smrg	ERR("No other components can be specified when a keymap is present\n");
4147d5e3a19Smrg	return False;
4157d5e3a19Smrg    }
4167d5e3a19Smrg    return ok;
4177d5e3a19Smrg}
4187d5e3a19Smrg
4197d5e3a19SmrgBool
4207d5e3a19SmrggetDisplay(int argc,char **argv)
4217d5e3a19Smrg{
4227d5e3a19Smrgint	major,minor,why;
4237d5e3a19Smrg
4247d5e3a19Smrg    major= XkbMajorVersion;
4257d5e3a19Smrg    minor= XkbMinorVersion;
4267d5e3a19Smrg    dpy= XkbOpenDisplay(svValue[DISPLAY_NDX],NULL,NULL,&major,&minor,&why);
4277d5e3a19Smrg    if (!dpy) {
4287d5e3a19Smrg	if (svValue[DISPLAY_NDX]==NULL)
4297d5e3a19Smrg	    svValue[DISPLAY_NDX]= getenv("DISPLAY");
4307d5e3a19Smrg	if (svValue[DISPLAY_NDX]==NULL)
4317d5e3a19Smrg	    svValue[DISPLAY_NDX]= "default display";
4327d5e3a19Smrg	switch (why) {
4337d5e3a19Smrg	    case XkbOD_BadLibraryVersion:
4347d5e3a19Smrg		ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
4357d5e3a19Smrg					XkbMajorVersion,XkbMinorVersion);
4367d5e3a19Smrg		ERR2("Xlib supports incompatible version %d.%02d\n",
4377d5e3a19Smrg					major,minor);
4387d5e3a19Smrg		break;
4397d5e3a19Smrg	    case XkbOD_ConnectionRefused:
4407d5e3a19Smrg                ERR1("Cannot open display \"%s\"\n",svValue[DISPLAY_NDX]);
4417d5e3a19Smrg		break;
4427d5e3a19Smrg	    case XkbOD_NonXkbServer:
4437d5e3a19Smrg		ERR1("XKB extension not present on %s\n",svValue[DISPLAY_NDX]);
4447d5e3a19Smrg		break;
4457d5e3a19Smrg	    case XkbOD_BadServerVersion:
4467d5e3a19Smrg                ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
4477d5e3a19Smrg				XkbMajorVersion,XkbMinorVersion);
4487d5e3a19Smrg		ERR3("Server %s uses incompatible version %d.%02d\n",
4497d5e3a19Smrg				svValue[DISPLAY_NDX],major,minor);
4507d5e3a19Smrg		break;
4517d5e3a19Smrg	    default:
4527d5e3a19Smrg		ERR1("Unknown error %d from XkbOpenDisplay\n",why);
4537d5e3a19Smrg		break;
4547d5e3a19Smrg	}
4557d5e3a19Smrg	return False;
4567d5e3a19Smrg    }
4577d5e3a19Smrg    if (synch)
4587d5e3a19Smrg	XSynchronize(dpy,True);
4597d5e3a19Smrg    return True;
4607d5e3a19Smrg}
4617d5e3a19Smrg
4627d5e3a19Smrg/***====================================================================***/
4637d5e3a19Smrg
4647d5e3a19SmrgBool
4657d5e3a19SmrggetServerValues(void)
4667d5e3a19Smrg{
4677d5e3a19SmrgXkbRF_VarDefsRec 	vd;
4687d5e3a19Smrgchar *			tmp= NULL;
4697d5e3a19Smrg
4707d5e3a19Smrg    if (!XkbRF_GetNamesProp(dpy,&tmp,&vd) || !tmp) {
4717d5e3a19Smrg	VMSG1(3,"Couldn't interpret %s property\n",_XKB_RF_NAMES_PROP_ATOM);
4727d5e3a19Smrg        tmp = DFLT_XKB_RULES_FILE;
4737d5e3a19Smrg        vd.model = DFLT_XKB_MODEL;
4747d5e3a19Smrg        vd.layout = DFLT_XKB_LAYOUT;
4757d5e3a19Smrg        vd.variant = NULL;
4767d5e3a19Smrg        vd.options = NULL;
4777d5e3a19Smrg        VMSG3(3,"Use defaults: rules - '%s' model - '%s' layout - '%s'\n",
4787d5e3a19Smrg                tmp, vd.model, vd.layout);
4797d5e3a19Smrg    }
4807d5e3a19Smrg    if (tmp)
4817d5e3a19Smrg	trySetString(RULES_NDX,tmp,FROM_SERVER);
4827d5e3a19Smrg    if (vd.model)
4837d5e3a19Smrg	trySetString(MODEL_NDX,vd.model,FROM_SERVER);
4847d5e3a19Smrg    if (vd.layout)
4857d5e3a19Smrg	trySetString(LAYOUT_NDX,vd.layout,FROM_SERVER);
4867d5e3a19Smrg    if (vd.variant)
4877d5e3a19Smrg	trySetString(VARIANT_NDX,vd.variant,FROM_SERVER);
4887d5e3a19Smrg    if ((vd.options)&&(!clearOptions)) {
4897d5e3a19Smrg	addStringToOptions(vd.options,&szOptions,&numOptions,&options);
4907d5e3a19Smrg	XFree(vd.options);
4917d5e3a19Smrg    }
4927d5e3a19Smrg    return True;
4937d5e3a19Smrg}
4947d5e3a19Smrg
4957d5e3a19Smrg/***====================================================================***/
4967d5e3a19Smrg
4977d5e3a19SmrgFILE *
4987d5e3a19SmrgfindFileInPath(char *name,char *subdir)
4997d5e3a19Smrg{
5007d5e3a19Smrgregister int	i;
5017d5e3a19Smrgchar		buf[PATH_MAX];
5027d5e3a19SmrgFILE *		fp;
5037d5e3a19Smrg
5047d5e3a19Smrg    if (name[0]=='/') {
5057d5e3a19Smrg	fp= fopen(name,"r");
5067d5e3a19Smrg	if ((verbose>7)||((!fp)&&(verbose>0)))
5077d5e3a19Smrg	    MSG2("%s file %s\n",(fp?"Found":"Didn't find"),name);
5087d5e3a19Smrg	return fp;
5097d5e3a19Smrg    }
5107d5e3a19Smrg    for (i=0;(i<numInclPath);i++) {
5117d5e3a19Smrg	if ((strlen(inclPath[i])+strlen(subdir)+strlen(name)+2)>PATH_MAX) {
5127d5e3a19Smrg	    VMSG3(0,"Path too long (%s/%s%s). Ignored.\n",inclPath[i],subdir,
5137d5e3a19Smrg									name);
5147d5e3a19Smrg	    continue;
5157d5e3a19Smrg	}
5167d5e3a19Smrg	sprintf(buf,"%s/%s%s",inclPath[i],subdir,name);
5177d5e3a19Smrg	fp= fopen(name,"r");
5187d5e3a19Smrg	if ((verbose>7)||((!fp)&&(verbose>5)))
5197d5e3a19Smrg	    MSG2("%s file %s\n",(fp?"Found":"Didn't find"),buf);
5207d5e3a19Smrg	if (fp!=NULL)
5217d5e3a19Smrg	    return fp;
5227d5e3a19Smrg    }
5237d5e3a19Smrg    return NULL;
5247d5e3a19Smrg}
5257d5e3a19Smrg
5267d5e3a19Smrg/***====================================================================***/
5277d5e3a19Smrg
5287d5e3a19SmrgBool
5297d5e3a19SmrgaddStringToOptions(char *opt_str,int *sz_opts,int *num_opts,char ***opts)
5307d5e3a19Smrg{
5317d5e3a19Smrgchar 	*tmp,*str,*next;
5327d5e3a19SmrgBool	ok= True;
5337d5e3a19Smrg
5347d5e3a19Smrg    if ((str = strdup(opt_str)) == NULL)
5357d5e3a19Smrg	return False;
5367d5e3a19Smrg    for (tmp= str,next=NULL;(tmp && *tmp!='\0')&&ok;tmp=next) {
5377d5e3a19Smrg	next= strchr(str,',');
5387d5e3a19Smrg	if (next) {
5397d5e3a19Smrg	    *next= '\0';
5407d5e3a19Smrg	    next++;
5417d5e3a19Smrg	}
5427d5e3a19Smrg	ok= addToList(sz_opts,num_opts,opts,tmp)&&ok;
5437d5e3a19Smrg    }
5447d5e3a19Smrg    free(str);
5457d5e3a19Smrg    return ok;
5467d5e3a19Smrg}
5477d5e3a19Smrg
5487d5e3a19Smrg/***====================================================================***/
5497d5e3a19Smrg
5507d5e3a19Smrgchar *
5517d5e3a19SmrgstringFromOptions(char *orig,int numNew,char **newOpts)
5527d5e3a19Smrg{
5537d5e3a19Smrgint	len,i,nOut;
5547d5e3a19Smrg
5557d5e3a19Smrg    if (orig)	len= strlen(orig)+1;
5567d5e3a19Smrg    else	len= 0;
5577d5e3a19Smrg    for (i=0;i<numNew;i++) {
5587d5e3a19Smrg	if (newOpts[i])
5597d5e3a19Smrg	    len+= strlen(newOpts[i])+1;
5607d5e3a19Smrg    }
5617d5e3a19Smrg    if (len<1)
5627d5e3a19Smrg	return NULL;
5637d5e3a19Smrg    if (orig) {
5647d5e3a19Smrg	orig= (char *)realloc(orig,len);
5657d5e3a19Smrg	nOut= 1;
5667d5e3a19Smrg    }
5677d5e3a19Smrg    else {
5687d5e3a19Smrg	orig= (char *)calloc(len,1);
5697d5e3a19Smrg	nOut= 0;
5707d5e3a19Smrg    }
5717d5e3a19Smrg    for (i=0;i<numNew;i++) {
5727d5e3a19Smrg	if (!newOpts[i])
5737d5e3a19Smrg	    continue;
5747d5e3a19Smrg	if (nOut>0) {
5757d5e3a19Smrg	     strcat(orig,",");
5767d5e3a19Smrg	     strcat(orig,newOpts[i]);
5777d5e3a19Smrg	}
5787d5e3a19Smrg	else strcpy(orig,newOpts[i]);
5797d5e3a19Smrg	nOut++;
5807d5e3a19Smrg    }
5817d5e3a19Smrg    return orig;
5827d5e3a19Smrg}
5837d5e3a19Smrg
5847d5e3a19Smrg/***====================================================================***/
5857d5e3a19Smrg
5867d5e3a19SmrgBool
5877d5e3a19SmrgapplyConfig(char *name)
5887d5e3a19Smrg{
5897d5e3a19SmrgFILE *	fp;
5907d5e3a19SmrgBool	ok;
5917d5e3a19Smrg
5927d5e3a19Smrg    if ((fp=findFileInPath(name,""))==NULL)
5937d5e3a19Smrg	return False;
5947d5e3a19Smrg    ok= XkbCFParse(fp,XkbCFDflts,NULL,&cfgResult);
5957d5e3a19Smrg    fclose(fp);
5967d5e3a19Smrg    if (!ok) {
5977d5e3a19Smrg	ERR1("Couldn't find configuration file \"%s\"\n", name);
5987d5e3a19Smrg	return False;
5997d5e3a19Smrg    }
6007d5e3a19Smrg    if (cfgResult.rules_file) {
6017d5e3a19Smrg	trySetString(RULES_NDX,cfgResult.rules_file,FROM_CONFIG);
6027d5e3a19Smrg	cfgResult.rules_file= NULL;
6037d5e3a19Smrg    }
6047d5e3a19Smrg    if (cfgResult.model) {
6057d5e3a19Smrg	trySetString(MODEL_NDX,cfgResult.model,FROM_CONFIG);
6067d5e3a19Smrg	cfgResult.model= NULL;
6077d5e3a19Smrg    }
6087d5e3a19Smrg    if (cfgResult.layout) {
6097d5e3a19Smrg	trySetString(LAYOUT_NDX,cfgResult.layout,FROM_CONFIG);
6107d5e3a19Smrg	cfgResult.layout= NULL;
6117d5e3a19Smrg    }
6127d5e3a19Smrg    if (cfgResult.variant) {
6137d5e3a19Smrg	trySetString(VARIANT_NDX,cfgResult.variant,FROM_CONFIG);
6147d5e3a19Smrg	cfgResult.variant= NULL;
6157d5e3a19Smrg    }
6167d5e3a19Smrg    if (cfgResult.options) {
6177d5e3a19Smrg	addStringToOptions(cfgResult.options,&szOptions,&numOptions,&options);
6187d5e3a19Smrg	cfgResult.options= NULL;
6197d5e3a19Smrg    }
6207d5e3a19Smrg    if (cfgResult.keymap) {
6217d5e3a19Smrg	trySetString(KEYMAP_NDX,cfgResult.keymap,FROM_CONFIG);
6227d5e3a19Smrg	cfgResult.keymap= NULL;
6237d5e3a19Smrg    }
6247d5e3a19Smrg    if (cfgResult.keycodes) {
6257d5e3a19Smrg	trySetString(KEYCODES_NDX,cfgResult.keycodes,FROM_CONFIG);
6267d5e3a19Smrg	cfgResult.keycodes= NULL;
6277d5e3a19Smrg    }
6287d5e3a19Smrg    if (cfgResult.geometry) {
6297d5e3a19Smrg	trySetString(GEOMETRY_NDX,cfgResult.geometry,FROM_CONFIG);
6307d5e3a19Smrg	cfgResult.geometry= NULL;
6317d5e3a19Smrg    }
6327d5e3a19Smrg    if (cfgResult.symbols) {
6337d5e3a19Smrg	trySetString(SYMBOLS_NDX,cfgResult.symbols,FROM_CONFIG);
6347d5e3a19Smrg	cfgResult.symbols= NULL;
6357d5e3a19Smrg    }
6367d5e3a19Smrg    if (cfgResult.types) {
6377d5e3a19Smrg	trySetString(TYPES_NDX,cfgResult.types,FROM_CONFIG);
6387d5e3a19Smrg	cfgResult.types= NULL;
6397d5e3a19Smrg    }
6407d5e3a19Smrg    if (cfgResult.compat) {
6417d5e3a19Smrg	trySetString(COMPAT_NDX,cfgResult.compat,FROM_CONFIG);
6427d5e3a19Smrg	cfgResult.compat= NULL;
6437d5e3a19Smrg    }
6447d5e3a19Smrg    if (verbose>5) {
6457d5e3a19Smrg	MSG("After config file:\n");
6467d5e3a19Smrg	dumpNames(True,True);
6477d5e3a19Smrg    }
6487d5e3a19Smrg    return True;
6497d5e3a19Smrg}
6507d5e3a19Smrg
6517d5e3a19SmrgBool
6527d5e3a19SmrgapplyRules(void)
6537d5e3a19Smrg{
6547d5e3a19Smrgint	i;
6557d5e3a19Smrgchar *	rfName;
6567d5e3a19Smrg
6577d5e3a19Smrg    if (svSrc[MODEL_NDX]||svSrc[LAYOUT_NDX]||svSrc[VARIANT_NDX]||options) {
6587d5e3a19Smrg	char 			buf[PATH_MAX];
6597d5e3a19Smrg	XkbComponentNamesRec	rnames;
6607d5e3a19Smrg
6617d5e3a19Smrg        if(svSrc[VARIANT_NDX] < svSrc[LAYOUT_NDX])
6627d5e3a19Smrg            svValue[VARIANT_NDX] = NULL;
6637d5e3a19Smrg
6647d5e3a19Smrg	rdefs.model= svValue[MODEL_NDX];
6657d5e3a19Smrg	rdefs.layout= svValue[LAYOUT_NDX];
6667d5e3a19Smrg	rdefs.variant= svValue[VARIANT_NDX];
6677d5e3a19Smrg	if (options)
6687d5e3a19Smrg	    rdefs.options=stringFromOptions(rdefs.options,numOptions,options);
6697d5e3a19Smrg
6707d5e3a19Smrg	if (svSrc[RULES_NDX])
6717d5e3a19Smrg	     rfName= svValue[RULES_NDX];
6727d5e3a19Smrg	else rfName= DFLT_XKB_RULES_FILE;
6737d5e3a19Smrg
6747d5e3a19Smrg	if (rfName[0]=='/') {
6757d5e3a19Smrg	    rules= XkbRF_Load(rfName,svValue[LOCALE_NDX],True,True);
6767d5e3a19Smrg	}
6777d5e3a19Smrg	else {
6787d5e3a19Smrg	    for (i=0;(i<numInclPath)&&(!rules);i++) {
6797d5e3a19Smrg		if ((strlen(inclPath[i])+strlen(rfName)+8)>PATH_MAX) {
6807d5e3a19Smrg		    VMSG2(0,"Path too long (%s/rules/%s). Ignored.\n",
6817d5e3a19Smrg						inclPath[i],rfName);
6827d5e3a19Smrg		    continue;
6837d5e3a19Smrg		}
6847d5e3a19Smrg		sprintf(buf,"%s/rules/%s",inclPath[i],svValue[RULES_NDX]);
6857d5e3a19Smrg		rules= XkbRF_Load(buf,svValue[LOCALE_NDX],True,True);
6867d5e3a19Smrg	    }
6877d5e3a19Smrg	}
6887d5e3a19Smrg	if (!rules) {
6897d5e3a19Smrg	    ERR1("Couldn't find rules file (%s) \n",svValue[RULES_NDX]);
6907d5e3a19Smrg	    return False;
6917d5e3a19Smrg	}
6927d5e3a19Smrg	XkbRF_GetComponents(rules,&rdefs,&rnames);
6937d5e3a19Smrg	if (rnames.keycodes) {
6947d5e3a19Smrg	    trySetString(KEYCODES_NDX,rnames.keycodes,FROM_RULES);
6957d5e3a19Smrg	    rnames.keycodes= NULL;
6967d5e3a19Smrg	}
6977d5e3a19Smrg	if (rnames.symbols) {
6987d5e3a19Smrg	    trySetString(SYMBOLS_NDX,rnames.symbols,FROM_RULES);
6997d5e3a19Smrg	    rnames.symbols= NULL;
7007d5e3a19Smrg	}
7017d5e3a19Smrg	if (rnames.types) {
7027d5e3a19Smrg	    trySetString(TYPES_NDX,rnames.types,FROM_RULES);
7037d5e3a19Smrg	    rnames.types= NULL;
7047d5e3a19Smrg	}
7057d5e3a19Smrg	if (rnames.compat) {
7067d5e3a19Smrg	    trySetString(COMPAT_NDX,rnames.compat,FROM_RULES);
7077d5e3a19Smrg	    rnames.compat= NULL;
7087d5e3a19Smrg	}
7097d5e3a19Smrg	if (rnames.geometry) {
7107d5e3a19Smrg	    trySetString(GEOMETRY_NDX,rnames.geometry,FROM_RULES);
7117d5e3a19Smrg	    rnames.geometry= NULL;
7127d5e3a19Smrg	}
7137d5e3a19Smrg	if (rnames.keymap) {
7147d5e3a19Smrg	    trySetString(KEYMAP_NDX,rnames.keymap,FROM_RULES);
7157d5e3a19Smrg	    rnames.keymap= NULL;
7167d5e3a19Smrg	}
7177d5e3a19Smrg	if (verbose>6) {
7187d5e3a19Smrg	    MSG1("Applied rules from %s:\n",svValue[RULES_NDX]);
7197d5e3a19Smrg	    dumpNames(True,False);
7207d5e3a19Smrg	}
7217d5e3a19Smrg    }
7227d5e3a19Smrg    else if (verbose>6) {
7237d5e3a19Smrg	MSG("No rules variables specified.  Rules file ignored\n");
7247d5e3a19Smrg    }
7257d5e3a19Smrg    return True;
7267d5e3a19Smrg}
7277d5e3a19Smrg
7287d5e3a19Smrg/* Primitive sanity check - filter out 'map names' (inside parenthesis) */
7297d5e3a19Smrg/* that can confuse xkbcomp parser */
7307d5e3a19SmrgBool
7317d5e3a19SmrgcheckName(char *name, char* string)
7327d5e3a19Smrg{
7337d5e3a19Smrg   char *i = name, *opar = NULL;
7347d5e3a19Smrg   Bool ret = True;
7357d5e3a19Smrg
7367d5e3a19Smrg   if(!name)
7377d5e3a19Smrg      return True;
7387d5e3a19Smrg
7397d5e3a19Smrg   while (*i){
7407d5e3a19Smrg      if (opar == NULL) {
7417d5e3a19Smrg         if (*i == '(')
7427d5e3a19Smrg         opar = i;
7437d5e3a19Smrg      } else {
7447d5e3a19Smrg         if ((*i == '(') || (*i == '|') || (*i == '+')) {
7457d5e3a19Smrg             ret = False;
7467d5e3a19Smrg             break;
7477d5e3a19Smrg         }
7487d5e3a19Smrg         if (*i == ')')
7497d5e3a19Smrg             opar = NULL;
7507d5e3a19Smrg      }
7517d5e3a19Smrg      i++;
7527d5e3a19Smrg   }
7537d5e3a19Smrg   if (opar)
7547d5e3a19Smrg      ret = False;
7557d5e3a19Smrg   if (!ret) {
7567d5e3a19Smrg      char c;
7577d5e3a19Smrg      int n = 1;
7587d5e3a19Smrg      for(i = opar+1; *i && n; i++) {
7597d5e3a19Smrg         if (*i == '(') n++;
7607d5e3a19Smrg         if (*i == ')') n--;
7617d5e3a19Smrg      }
7627d5e3a19Smrg      if (*i) i++;
7637d5e3a19Smrg      c = *i;
7647d5e3a19Smrg      *i = '\0';
7657d5e3a19Smrg      ERR1("Illegal map name '%s' ", opar);
7667d5e3a19Smrg      *i = c;
7677d5e3a19Smrg      ERR2("in %s name '%s'\n", string, name);
7687d5e3a19Smrg   }
7697d5e3a19Smrg   return ret;
7707d5e3a19Smrg}
7717d5e3a19Smrg
7727d5e3a19Smrgvoid
7737d5e3a19SmrgprintKeymap(void)
7747d5e3a19Smrg{
7757d5e3a19Smrg    MSG("xkb_keymap {\n");
7767d5e3a19Smrg    if (svValue[KEYCODES_NDX])
7777d5e3a19Smrg	MSG1("\txkb_keycodes  { include \"%s\"\t};\n",svValue[KEYCODES_NDX]);
7787d5e3a19Smrg    if (svValue[TYPES_NDX])
7797d5e3a19Smrg	MSG1("\txkb_types     { include \"%s\"\t};\n",svValue[TYPES_NDX]);
7807d5e3a19Smrg    if (svValue[COMPAT_NDX])
7817d5e3a19Smrg	MSG1("\txkb_compat    { include \"%s\"\t};\n",svValue[COMPAT_NDX]);
7827d5e3a19Smrg    if (svValue[SYMBOLS_NDX])
7837d5e3a19Smrg	MSG1("\txkb_symbols   { include \"%s\"\t};\n",svValue[SYMBOLS_NDX]);
7847d5e3a19Smrg    if (svValue[GEOMETRY_NDX])
7857d5e3a19Smrg	MSG1("\txkb_geometry  { include \"%s\"\t};\n",svValue[GEOMETRY_NDX]);
7867d5e3a19Smrg    MSG("};\n");
7877d5e3a19Smrg}
7887d5e3a19Smrg
7897d5e3a19SmrgBool
7907d5e3a19SmrgapplyComponentNames(void)
7917d5e3a19Smrg{
7927d5e3a19Smrg    if(!checkName(svValue[TYPES_NDX],    "types"))
7937d5e3a19Smrg	return False;
7947d5e3a19Smrg    if(!checkName(svValue[COMPAT_NDX],   "compat"))
7957d5e3a19Smrg	return False;
7967d5e3a19Smrg    if(!checkName(svValue[SYMBOLS_NDX],  "symbols"))
7977d5e3a19Smrg	return False;
7987d5e3a19Smrg    if(!checkName(svValue[KEYCODES_NDX], "keycodes"))
7997d5e3a19Smrg	return False;
8007d5e3a19Smrg    if(!checkName(svValue[GEOMETRY_NDX], "geometry"))
8017d5e3a19Smrg	return False;
8027d5e3a19Smrg    if(!checkName(svValue[KEYMAP_NDX],   "keymap"))
8037d5e3a19Smrg	return False;
8047d5e3a19Smrg
8057d5e3a19Smrg    if (verbose>5) {
8067d5e3a19Smrg	MSG("Trying to build keymap using the following components:\n");
8077d5e3a19Smrg	dumpNames(False,True);
8087d5e3a19Smrg    }
8097d5e3a19Smrg    if (dpy && !print) {
8107d5e3a19Smrg	XkbComponentNamesRec	cmdNames;
8117d5e3a19Smrg	cmdNames.types= svValue[TYPES_NDX];
8127d5e3a19Smrg	cmdNames.compat= svValue[COMPAT_NDX];
8137d5e3a19Smrg	cmdNames.symbols= svValue[SYMBOLS_NDX];
8147d5e3a19Smrg	cmdNames.keycodes= svValue[KEYCODES_NDX];
8157d5e3a19Smrg	cmdNames.geometry= svValue[GEOMETRY_NDX];
8167d5e3a19Smrg	cmdNames.keymap= svValue[KEYMAP_NDX];
8177d5e3a19Smrg	xkb= XkbGetKeyboardByName(dpy,deviceSpec,&cmdNames,
8187d5e3a19Smrg			XkbGBN_AllComponentsMask,
8197d5e3a19Smrg			XkbGBN_AllComponentsMask&(~XkbGBN_GeometryMask),
8207d5e3a19Smrg			True);
8217d5e3a19Smrg	if (!xkb) {
8227d5e3a19Smrg	    ERR("Error loading new keyboard description\n");
8237d5e3a19Smrg	    return False;
8247d5e3a19Smrg	}
8257d5e3a19Smrg	if (svValue[RULES_NDX] && (rdefs.model || rdefs.layout)) {
8267d5e3a19Smrg	    if (!XkbRF_SetNamesProp(dpy,svValue[RULES_NDX],&rdefs)) {
8277d5e3a19Smrg		VMSG(0,"Error updating the XKB names property\n");
8287d5e3a19Smrg	    }
8297d5e3a19Smrg	}
8307d5e3a19Smrg    }
8317d5e3a19Smrg    if (print) {
8327d5e3a19Smrg        printKeymap();
8337d5e3a19Smrg    }
8347d5e3a19Smrg    return True;
8357d5e3a19Smrg}
8367d5e3a19Smrg
8377d5e3a19Smrg
8387d5e3a19Smrgint
8397d5e3a19Smrgmain(int argc,char **argv)
8407d5e3a19Smrg{
8417d5e3a19Smrg    if ((!parseArgs(argc,argv))||(!getDisplay(argc,argv)))
8427d5e3a19Smrg	exit(-1);
8437d5e3a19Smrg    svValue[LOCALE_NDX]= setlocale(LC_ALL,svValue[LOCALE_NDX]);
8447d5e3a19Smrg    svSrc[LOCALE_NDX]= FROM_SERVER;
8457d5e3a19Smrg    VMSG1(7,"locale is %s\n",svValue[LOCALE_NDX]);
8467d5e3a19Smrg    if (dpy)
8477d5e3a19Smrg        getServerValues();
8487d5e3a19Smrg    if (svValue[CONFIG_NDX] && (!applyConfig(svValue[CONFIG_NDX])))
8497d5e3a19Smrg	exit(-3);
8507d5e3a19Smrg    if (!applyRules())
8517d5e3a19Smrg	exit(-4);
8527d5e3a19Smrg    if (!applyComponentNames())
8537d5e3a19Smrg	exit(-5);
8547d5e3a19Smrg    if (dpy)
8557d5e3a19Smrg	XCloseDisplay(dpy);
8567d5e3a19Smrg    exit(0);
8577d5e3a19Smrg}
858