setxkbmap.c revision 765486e8
17d5e3a19Smrg/************************************************************ 27d5e3a19Smrg Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. 37d5e3a19Smrg 47d5e3a19Smrg Permission to use, copy, modify, and distribute this 57d5e3a19Smrg software and its documentation for any purpose and without 67d5e3a19Smrg fee is hereby granted, provided that the above copyright 77d5e3a19Smrg notice appear in all copies and that both that copyright 87d5e3a19Smrg notice and this permission notice appear in supporting 97d5e3a19Smrg documentation, and that the name of Silicon Graphics not be 107d5e3a19Smrg used in advertising or publicity pertaining to distribution 117d5e3a19Smrg of the software without specific prior written permission. 127d5e3a19Smrg Silicon Graphics makes no representation about the suitability 137d5e3a19Smrg of this software for any purpose. It is provided "as is" 147d5e3a19Smrg without any express or implied warranty. 157d5e3a19Smrg 167d5e3a19Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 177d5e3a19Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 187d5e3a19Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 197d5e3a19Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 207d5e3a19Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 217d5e3a19Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 227d5e3a19Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 237d5e3a19Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 247d5e3a19Smrg 257d5e3a19Smrg ********************************************************/ 267d5e3a19Smrg 277d5e3a19Smrg#include <stdio.h> 287d5e3a19Smrg#include <stdlib.h> 297d5e3a19Smrg#include <locale.h> 307d5e3a19Smrg#include <limits.h> 317d5e3a19Smrg#include <ctype.h> 327d5e3a19Smrg#include <X11/Xlib.h> 337d5e3a19Smrg#include <X11/Xos.h> 347d5e3a19Smrg#include <X11/XKBlib.h> 357d5e3a19Smrg#include <X11/extensions/XKBfile.h> 367d5e3a19Smrg#include <X11/extensions/XKBconfig.h> 377d5e3a19Smrg#include <X11/extensions/XKBrules.h> 387d5e3a19Smrg 397d5e3a19Smrg#ifndef PATH_MAX 407d5e3a19Smrg#ifdef MAXPATHLEN 417d5e3a19Smrg#define PATH_MAX MAXPATHLEN 427d5e3a19Smrg#else 437d5e3a19Smrg#define PATH_MAX 1024 447d5e3a19Smrg#endif 457d5e3a19Smrg#endif 467d5e3a19Smrg 477d5e3a19Smrg#ifndef DFLT_XKB_CONFIG_ROOT 487d5e3a19Smrg#define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb" 497d5e3a19Smrg#endif 507d5e3a19Smrg#ifndef DFLT_XKB_RULES_FILE 51765486e8Smrg#define DFLT_XKB_RULES_FILE "base" 527d5e3a19Smrg#endif 537d5e3a19Smrg#ifndef DFLT_XKB_LAYOUT 547d5e3a19Smrg#define DFLT_XKB_LAYOUT "us" 557d5e3a19Smrg#endif 567d5e3a19Smrg#ifndef DFLT_XKB_MODEL 577d5e3a19Smrg#define DFLT_XKB_MODEL "pc105" 587d5e3a19Smrg#endif 597d5e3a19Smrg 601568b75bSmrg/* Values used in svSrc to state how a value was obtained. The order of these 611568b75bSmrg * is important, the bigger the higher the priority. 621568b75bSmrg * e.g. FROM_CONFIG overrides FROM_SERVER */ 637d5e3a19Smrg#define UNDEFINED 0 641568b75bSmrg#define FROM_SERVER 1 /* retrieved from server at runtime */ 651568b75bSmrg#define FROM_RULES 2 /* xkb rules file */ 661568b75bSmrg#define FROM_CONFIG 3 /* command-line specified config file */ 671568b75bSmrg#define FROM_CMD_LINE 4 /* specified at the cmdline */ 687d5e3a19Smrg#define NUM_SOURCES 5 697d5e3a19Smrg 701568b75bSmrg/* Indices used into svSrc, svNValue */ 711568b75bSmrg#define RULES_NDX 0 /* rules file */ 721568b75bSmrg#define CONFIG_NDX 1 /* config file (if used) */ 731568b75bSmrg#define DISPLAY_NDX 2 /* X display name */ 741568b75bSmrg#define LOCALE_NDX 3 /* machine's locale */ 757d5e3a19Smrg#define MODEL_NDX 4 767d5e3a19Smrg#define LAYOUT_NDX 5 777d5e3a19Smrg#define VARIANT_NDX 6 787d5e3a19Smrg#define KEYCODES_NDX 7 797d5e3a19Smrg#define TYPES_NDX 8 807d5e3a19Smrg#define COMPAT_NDX 9 817d5e3a19Smrg#define SYMBOLS_NDX 10 827d5e3a19Smrg#define GEOMETRY_NDX 11 837d5e3a19Smrg#define KEYMAP_NDX 12 847d5e3a19Smrg#define NUM_STRING_VALS 13 857d5e3a19Smrg 867d5e3a19Smrg/***====================================================================***/ 871568b75bSmrgstatic Bool print = False; 88765486e8Smrgstatic Bool query = False; 891568b75bSmrgstatic Bool synch = False; 901568b75bSmrgstatic int verbose = 5; 911568b75bSmrg 921568b75bSmrgstatic Display *dpy; 931568b75bSmrg 941568b75bSmrg/** 951568b75bSmrg * human-readable versions of FROM_CONFIG, FROM_SERVER, etc. Used for error 961568b75bSmrg * reporting. 971568b75bSmrg */ 981568b75bSmrgstatic char *srcName[NUM_SOURCES] = { 991568b75bSmrg "undefined", "X server", "rules file", "config file", "command line" 1007d5e3a19Smrg}; 1017d5e3a19Smrg 1021568b75bSmrg/** 1031568b75bSmrg * human-readable versions for RULES_NDX, CONFIG_NDX, etc. Used for error 1041568b75bSmrg * reporting. 1051568b75bSmrg */ 1061568b75bSmrgstatic char *svName[NUM_STRING_VALS] = { 1071568b75bSmrg "rules file", "config file", "X display", "locale", 1081568b75bSmrg "keyboard model", "keyboard layout", "layout variant", 1091568b75bSmrg "keycodes", "types", "compatibility map", "symbols", "geometry", 1101568b75bSmrg "keymap" 1117d5e3a19Smrg}; 1121568b75bSmrg/** 1131568b75bSmrg * Holds the source for each of RULES, CONFIG, DISPLAY, etc. 1141568b75bSmrg * i.e. if svSrc[LAYOUT_NDX] == FROM_SERVER, then the layout has been fetched 1151568b75bSmrg * from the server. 1161568b75bSmrg */ 1171568b75bSmrgstatic int svSrc[NUM_STRING_VALS]; 1181568b75bSmrg/** 1191568b75bSmrg * Holds the value for each of RULES, CONFIG, DISPLAY, etc. 1201568b75bSmrg */ 1211568b75bSmrgstatic char *svValue[NUM_STRING_VALS]; 1227d5e3a19Smrg 1231568b75bSmrgstatic XkbConfigRtrnRec cfgResult; 1247d5e3a19Smrg 1251568b75bSmrgstatic XkbRF_RulesPtr rules = NULL; 1261568b75bSmrgstatic XkbRF_VarDefsRec rdefs; 1277d5e3a19Smrg 1281568b75bSmrgstatic Bool clearOptions = False; 1291568b75bSmrgstatic int szOptions = 0; 1301568b75bSmrgstatic int numOptions = 0; 1311568b75bSmrgstatic char **options = NULL; 1327d5e3a19Smrg 1331568b75bSmrgstatic int szInclPath = 0; 1341568b75bSmrgstatic int numInclPath = 0; 1351568b75bSmrgstatic char **inclPath = NULL; 1367d5e3a19Smrg 1371568b75bSmrgstatic XkbDescPtr xkb = NULL; 1387d5e3a19Smrg 1391568b75bSmrgstatic int deviceSpec = XkbUseCoreKbd; 1407d5e3a19Smrg 1417d5e3a19Smrg/***====================================================================***/ 1427d5e3a19Smrg 1437d5e3a19Smrg#define streq(s1,s2) (strcmp(s1,s2)==0) 1447d5e3a19Smrg#define strpfx(s1,s2) (strncmp(s1,s2,strlen(s2))==0) 1457d5e3a19Smrg 1467d5e3a19Smrg#define MSG(s) printf(s) 1477d5e3a19Smrg#define MSG1(s,a) printf(s,a) 1487d5e3a19Smrg#define MSG2(s,a,b) printf(s,a,b) 1497d5e3a19Smrg#define MSG3(s,a,b,c) printf(s,a,b,c) 1507d5e3a19Smrg 1517d5e3a19Smrg#define VMSG(l,s) if (verbose>(l)) printf(s) 1527d5e3a19Smrg#define VMSG1(l,s,a) if (verbose>(l)) printf(s,a) 1537d5e3a19Smrg#define VMSG2(l,s,a,b) if (verbose>(l)) printf(s,a,b) 1547d5e3a19Smrg#define VMSG3(l,s,a,b,c) if (verbose>(l)) printf(s,a,b,c) 1557d5e3a19Smrg 1567d5e3a19Smrg#define ERR(s) fprintf(stderr,s) 1577d5e3a19Smrg#define ERR1(s,a) fprintf(stderr,s,a) 1587d5e3a19Smrg#define ERR2(s,a,b) fprintf(stderr,s,a,b) 1597d5e3a19Smrg#define ERR3(s,a,b,c) fprintf(stderr,s,a,b,c) 1607d5e3a19Smrg 1617d5e3a19Smrg/***====================================================================***/ 1627d5e3a19Smrg 1631568b75bSmrgBool addToList(int *sz, int *num, char ***listIn, char *newVal); 1641568b75bSmrgvoid usage(int argc, char **argv); 1651568b75bSmrgvoid dumpNames(Bool wantRules, Bool wantCNames); 1661568b75bSmrgvoid trySetString(int which, char *newVal, int src); 1671568b75bSmrgBool setOptString(int *arg, int argc, char **argv, int which, int src); 1681568b75bSmrgint parseArgs(int argc, char **argv); 1691568b75bSmrgBool getDisplay(int argc, char **argv); 1701568b75bSmrgBool getServerValues(void); 1711568b75bSmrgFILE *findFileInPath(char *name, char *subdir); 1721568b75bSmrgBool addStringToOptions(char *opt_str, int *sz_opts, int *num_opts, 1731568b75bSmrg char ***opts); 1741568b75bSmrgchar *stringFromOptions(char *orig, int numNew, char **newOpts); 1751568b75bSmrgBool applyConfig(char *name); 1761568b75bSmrgBool applyRules(void); 1771568b75bSmrgBool applyComponentNames(void); 1781568b75bSmrgvoid printKeymap(void); 1797d5e3a19Smrg 1807d5e3a19Smrg/***====================================================================***/ 1817d5e3a19Smrg 1827d5e3a19SmrgBool 1831568b75bSmrgaddToList(int *sz, int *num, char ***listIn, char *newVal) 1847d5e3a19Smrg{ 1851568b75bSmrg register int i; 1861568b75bSmrg char **list; 1871568b75bSmrg 1881568b75bSmrg if ((!newVal) || (!newVal[0])) 1891568b75bSmrg { 1901568b75bSmrg *num = 0; 1911568b75bSmrg return True; 1921568b75bSmrg } 1931568b75bSmrg list = *listIn; 1941568b75bSmrg for (i = 0; i < *num; i++) 1951568b75bSmrg { 1961568b75bSmrg if (streq(list[i], newVal)) 1971568b75bSmrg return True; 1981568b75bSmrg } 1991568b75bSmrg if ((list == NULL) || (*sz < 1)) 2001568b75bSmrg { 2011568b75bSmrg *num = 0; 2021568b75bSmrg *sz = 4; 2031568b75bSmrg list = (char **) calloc(*sz, sizeof(char *)); 2041568b75bSmrg *listIn = list; 2051568b75bSmrg } 2061568b75bSmrg else if (*num >= *sz) 2071568b75bSmrg { 2081568b75bSmrg *sz *= 2; 2091568b75bSmrg list = (char **) realloc(list, (*sz) * sizeof(char *)); 2101568b75bSmrg *listIn = list; 2111568b75bSmrg } 2121568b75bSmrg if (!list) 2131568b75bSmrg { 2141568b75bSmrg ERR("Internal Error! Allocation failure in add to list!\n"); 2151568b75bSmrg ERR(" Exiting.\n"); 2161568b75bSmrg exit(-1); 2171568b75bSmrg } 2181568b75bSmrg list[*num] = strdup(newVal); 2191568b75bSmrg (*num) = (*num) + 1; 2207d5e3a19Smrg return True; 2217d5e3a19Smrg} 2227d5e3a19Smrg 2237d5e3a19Smrg/***====================================================================***/ 2247d5e3a19Smrg 2257d5e3a19Smrgvoid 2261568b75bSmrgusage(int argc, char **argv) 2277d5e3a19Smrg{ 2281568b75bSmrg MSG1("Usage: %s [args] [<layout> [<variant> [<option> ... ]]]\n", 2291568b75bSmrg argv[0]); 2307d5e3a19Smrg MSG("Where legal args are:\n"); 2317d5e3a19Smrg MSG("-?,-help Print this message\n"); 2327d5e3a19Smrg MSG("-compat <name> Specifies compatibility map component name\n"); 2337d5e3a19Smrg MSG("-config <file> Specifies configuration file to use\n"); 2347d5e3a19Smrg MSG("-device <deviceid> Specifies the device ID to use\n"); 2357d5e3a19Smrg MSG("-display <dpy> Specifies display to use\n"); 2367d5e3a19Smrg MSG("-geometry <name> Specifies geometry component name\n"); 2377d5e3a19Smrg MSG("-I[<dir>] Add <dir> to list of directories to be used\n"); 2387d5e3a19Smrg MSG("-keycodes <name> Specifies keycodes component name\n"); 2397d5e3a19Smrg MSG("-keymap <name> Specifies name of keymap to load\n"); 2407d5e3a19Smrg MSG("-layout <name> Specifies layout used to choose component names\n"); 2417d5e3a19Smrg MSG("-model <name> Specifies model used to choose component names\n"); 2427d5e3a19Smrg MSG("-option <name> Adds an option used to choose component names\n"); 2437d5e3a19Smrg MSG("-print Print a complete xkb_keymap description and exit\n"); 244765486e8Smrg MSG("-query Print the current layout settings and exit\n"); 2457d5e3a19Smrg MSG("-rules <name> Name of rules file to use\n"); 2467d5e3a19Smrg MSG("-symbols <name> Specifies symbols component name\n"); 2477d5e3a19Smrg MSG("-synch Synchronize request w/X server\n"); 2487d5e3a19Smrg MSG("-types <name> Specifies types component name\n"); 2497d5e3a19Smrg MSG("-v[erbose] [<lvl>] Sets verbosity (1..10). Higher values yield\n"); 2507d5e3a19Smrg MSG(" more messages\n"); 2517d5e3a19Smrg MSG("-variant <name> Specifies layout variant used to choose component names\n"); 2527d5e3a19Smrg} 2537d5e3a19Smrg 2547d5e3a19Smrgvoid 2551568b75bSmrgdumpNames(Bool wantRules, Bool wantCNames) 2567d5e3a19Smrg{ 2571568b75bSmrg if (wantRules) 2581568b75bSmrg { 259765486e8Smrg if (svValue[RULES_NDX]) 260765486e8Smrg MSG1("rules: %s\n", svValue[RULES_NDX]); 2611568b75bSmrg if (svValue[MODEL_NDX]) 2621568b75bSmrg MSG1("model: %s\n", svValue[MODEL_NDX]); 2631568b75bSmrg if (svValue[LAYOUT_NDX]) 2641568b75bSmrg MSG1("layout: %s\n", svValue[LAYOUT_NDX]); 2651568b75bSmrg if (svValue[VARIANT_NDX]) 2661568b75bSmrg MSG1("variant: %s\n", svValue[VARIANT_NDX]); 2671568b75bSmrg if (options) 2681568b75bSmrg { 2691568b75bSmrg char *opt_str = stringFromOptions(NULL, numOptions, options); 2701568b75bSmrg MSG1("options: %s\n", opt_str); 2711568b75bSmrg free(opt_str); 2721568b75bSmrg } 2731568b75bSmrg } 2741568b75bSmrg if (wantCNames) 2751568b75bSmrg { 2761568b75bSmrg if (svValue[KEYMAP_NDX]) 2771568b75bSmrg MSG1("keymap: %s\n", svValue[KEYMAP_NDX]); 2781568b75bSmrg if (svValue[KEYCODES_NDX]) 2791568b75bSmrg MSG1("keycodes: %s\n", svValue[KEYCODES_NDX]); 2801568b75bSmrg if (svValue[TYPES_NDX]) 2811568b75bSmrg MSG1("types: %s\n", svValue[TYPES_NDX]); 2821568b75bSmrg if (svValue[COMPAT_NDX]) 2831568b75bSmrg MSG1("compat: %s\n", svValue[COMPAT_NDX]); 2841568b75bSmrg if (svValue[SYMBOLS_NDX]) 2851568b75bSmrg MSG1("symbols: %s\n", svValue[SYMBOLS_NDX]); 2861568b75bSmrg if (svValue[GEOMETRY_NDX]) 2871568b75bSmrg MSG1("geometry: %s\n", svValue[GEOMETRY_NDX]); 2887d5e3a19Smrg } 2897d5e3a19Smrg return; 2907d5e3a19Smrg} 2917d5e3a19Smrg 2927d5e3a19Smrg/***====================================================================***/ 2937d5e3a19Smrg 2941568b75bSmrg/** 2951568b75bSmrg * Set the given string (obtained from src) in the svValue/svSrc globals. 2961568b75bSmrg * If the given item is already set, it is overridden if the original source 2971568b75bSmrg * is less significant than the given one. 2981568b75bSmrg * 2991568b75bSmrg * @param which What value is it (one of RULES_NDX, CONFIG_NDX, ...) 3001568b75bSmrg */ 3017d5e3a19Smrgvoid 3021568b75bSmrgtrySetString(int which, char *newVal, int src) 3037d5e3a19Smrg{ 3041568b75bSmrg if (svValue[which] != NULL) 3051568b75bSmrg { 3061568b75bSmrg if (svSrc[which] == src) 3071568b75bSmrg { 3081568b75bSmrg VMSG2(0, "Warning! More than one %s from %s\n", 3091568b75bSmrg svName[which], srcName[src]); 3101568b75bSmrg VMSG2(0, " Using \"%s\", ignoring \"%s\"\n", 3111568b75bSmrg svValue[which], newVal); 3121568b75bSmrg return; 3131568b75bSmrg } 3141568b75bSmrg else if (svSrc[which] > src) 3151568b75bSmrg { 3161568b75bSmrg VMSG1(5, "Warning! Multiple definitions of %s\n", svName[which]); 3171568b75bSmrg VMSG2(5, " Using %s, ignoring %s\n", 3181568b75bSmrg srcName[svSrc[which]], srcName[src]); 3191568b75bSmrg return; 3201568b75bSmrg } 3211568b75bSmrg } 3221568b75bSmrg svSrc[which] = src; 3231568b75bSmrg svValue[which] = newVal; 3247d5e3a19Smrg return; 3257d5e3a19Smrg} 3267d5e3a19Smrg 3277d5e3a19SmrgBool 3281568b75bSmrgsetOptString(int *arg, int argc, char **argv, int which, int src) 3297d5e3a19Smrg{ 3301568b75bSmrg int ndx; 3311568b75bSmrg char *opt; 3321568b75bSmrg 3331568b75bSmrg ndx = *arg; 3341568b75bSmrg opt = argv[ndx]; 3351568b75bSmrg if (ndx >= argc - 1) 3361568b75bSmrg { 3371568b75bSmrg VMSG1(0, "No %s specified on the command line\n", svName[which]); 3381568b75bSmrg VMSG1(0, "Trailing %s option ignored\n", opt); 3391568b75bSmrg return True; 3407d5e3a19Smrg } 3417d5e3a19Smrg ndx++; 3421568b75bSmrg *arg = ndx; 3431568b75bSmrg if (svValue[which] != NULL) 3441568b75bSmrg { 3451568b75bSmrg if (svSrc[which] == src) 3461568b75bSmrg { 3471568b75bSmrg VMSG2(0, "More than one %s on %s\n", svName[which], srcName[src]); 3481568b75bSmrg VMSG2(0, "Using \"%s\", ignoring \"%s\"\n", svValue[which], 3491568b75bSmrg argv[ndx]); 3501568b75bSmrg return True; 3511568b75bSmrg } 3521568b75bSmrg else if (svSrc[which] > src) 3531568b75bSmrg { 3541568b75bSmrg VMSG1(5, "Multiple definitions of %s\n", svName[which]); 3551568b75bSmrg VMSG2(5, "Using %s, ignoring %s\n", srcName[svSrc[which]], 3561568b75bSmrg srcName[src]); 3571568b75bSmrg return True; 3581568b75bSmrg } 3591568b75bSmrg } 3601568b75bSmrg svSrc[which] = src; 3611568b75bSmrg svValue[which] = argv[ndx]; 3627d5e3a19Smrg return True; 3637d5e3a19Smrg} 3647d5e3a19Smrg 3657d5e3a19Smrg/***====================================================================***/ 3667d5e3a19Smrg 3671568b75bSmrg/** 3681568b75bSmrg * Parse commandline arguments. 3691568b75bSmrg * Return True on success or False if an unrecognized option has been 3701568b75bSmrg * specified. 3711568b75bSmrg */ 3727d5e3a19Smrgint 3731568b75bSmrgparseArgs(int argc, char **argv) 3747d5e3a19Smrg{ 3751568b75bSmrg int i; 3761568b75bSmrg Bool ok; 3771568b75bSmrg unsigned present; 3781568b75bSmrg 3791568b75bSmrg ok = True; 3801568b75bSmrg addToList(&szInclPath, &numInclPath, &inclPath, "."); 3811568b75bSmrg addToList(&szInclPath, &numInclPath, &inclPath, DFLT_XKB_CONFIG_ROOT); 3821568b75bSmrg for (i = 1; (i < argc) && ok; i++) 3831568b75bSmrg { 3841568b75bSmrg if (argv[i][0] != '-') 3851568b75bSmrg { 3861568b75bSmrg /* Allow a call like "setxkbmap us" to work. Layout is default, 3871568b75bSmrg if -layout is given, then try parsing variant, then options */ 3881568b75bSmrg if (!svSrc[LAYOUT_NDX]) 3891568b75bSmrg trySetString(LAYOUT_NDX, argv[i], FROM_CMD_LINE); 3901568b75bSmrg else if (!svSrc[VARIANT_NDX]) 3911568b75bSmrg trySetString(VARIANT_NDX, argv[i], FROM_CMD_LINE); 3921568b75bSmrg else 3931568b75bSmrg ok = addToList(&szOptions, &numOptions, &options, argv[i]); 3941568b75bSmrg } 3951568b75bSmrg else if (streq(argv[i], "-compat")) 3961568b75bSmrg ok = setOptString(&i, argc, argv, COMPAT_NDX, FROM_CMD_LINE); 3971568b75bSmrg else if (streq(argv[i], "-config")) 3981568b75bSmrg ok = setOptString(&i, argc, argv, CONFIG_NDX, FROM_CMD_LINE); 3991568b75bSmrg else if (streq(argv[i], "-device")) 4001568b75bSmrg deviceSpec = atoi(argv[++i]); /* only allow device IDs, not names */ 4011568b75bSmrg else if (streq(argv[i], "-display")) 4021568b75bSmrg ok = setOptString(&i, argc, argv, DISPLAY_NDX, FROM_CMD_LINE); 4031568b75bSmrg else if (streq(argv[i], "-geometry")) 4041568b75bSmrg ok = setOptString(&i, argc, argv, GEOMETRY_NDX, FROM_CMD_LINE); 4051568b75bSmrg else if (streq(argv[i], "-help") || streq(argv[i], "-?")) 4061568b75bSmrg { 4071568b75bSmrg usage(argc, argv); 4081568b75bSmrg exit(0); 4091568b75bSmrg } 4101568b75bSmrg else if (strpfx(argv[i], "-I")) 4111568b75bSmrg ok = addToList(&szInclPath, &numInclPath, &inclPath, &argv[i][2]); 4121568b75bSmrg else if (streq(argv[i], "-keycodes")) 4131568b75bSmrg ok = setOptString(&i, argc, argv, KEYCODES_NDX, FROM_CMD_LINE); 4141568b75bSmrg else if (streq(argv[i], "-keymap")) 4151568b75bSmrg ok = setOptString(&i, argc, argv, KEYMAP_NDX, FROM_CMD_LINE); 4161568b75bSmrg else if (streq(argv[i], "-layout")) 4171568b75bSmrg ok = setOptString(&i, argc, argv, LAYOUT_NDX, FROM_CMD_LINE); 4181568b75bSmrg else if (streq(argv[i], "-model")) 4191568b75bSmrg ok = setOptString(&i, argc, argv, MODEL_NDX, FROM_CMD_LINE); 4201568b75bSmrg else if (streq(argv[i], "-option")) 4211568b75bSmrg { 4221568b75bSmrg if ((i == argc - 1) || (argv[i + 1][0] == '\0') 4231568b75bSmrg || (argv[i + 1][0] == '-')) 4241568b75bSmrg { 4251568b75bSmrg clearOptions = True; 4261568b75bSmrg ok = addToList(&szOptions, &numOptions, &options, ""); 4271568b75bSmrg if (i < argc - 1 && argv[i + 1][0] == '\0') 4281568b75bSmrg i++; 4291568b75bSmrg } 4301568b75bSmrg else 4311568b75bSmrg { 4321568b75bSmrg ok = addToList(&szOptions, &numOptions, &options, argv[++i]); 4331568b75bSmrg } 4341568b75bSmrg } 4351568b75bSmrg else if (streq(argv[i], "-print")) 4361568b75bSmrg print = True; 437765486e8Smrg else if (streq(argv[i], "-query")) 438765486e8Smrg query = True; 4391568b75bSmrg else if (streq(argv[i], "-rules")) 4401568b75bSmrg ok = setOptString(&i, argc, argv, RULES_NDX, FROM_CMD_LINE); 4411568b75bSmrg else if (streq(argv[i], "-symbols")) 4421568b75bSmrg ok = setOptString(&i, argc, argv, SYMBOLS_NDX, FROM_CMD_LINE); 4431568b75bSmrg else if (streq(argv[i], "-synch")) 4441568b75bSmrg synch = True; 4451568b75bSmrg else if (streq(argv[i], "-types")) 4461568b75bSmrg ok = setOptString(&i, argc, argv, TYPES_NDX, FROM_CMD_LINE); 4471568b75bSmrg else if (streq(argv[i], "-verbose") || (streq(argv[i], "-v"))) 4481568b75bSmrg { 4491568b75bSmrg if ((i < argc - 1) && (isdigit(argv[i + 1][0]))) 4501568b75bSmrg verbose = atoi(argv[++i]); 4511568b75bSmrg else 4521568b75bSmrg verbose++; 4531568b75bSmrg if (verbose < 0) 4541568b75bSmrg { 4551568b75bSmrg ERR1("Illegal verbose level %d. Reset to 0\n", verbose); 4561568b75bSmrg verbose = 0; 4571568b75bSmrg } 4581568b75bSmrg else if (verbose > 10) 4591568b75bSmrg { 4601568b75bSmrg ERR1("Illegal verbose level %d. Reset to 10\n", verbose); 4611568b75bSmrg verbose = 10; 4621568b75bSmrg } 4631568b75bSmrg VMSG1(7, "Setting verbose level to %d\n", verbose); 4641568b75bSmrg } 4651568b75bSmrg else if (streq(argv[i], "-variant")) 4661568b75bSmrg ok = setOptString(&i, argc, argv, VARIANT_NDX, FROM_CMD_LINE); 4671568b75bSmrg else 4681568b75bSmrg { 4691568b75bSmrg ERR1("Error! Option \"%s\" not recognized\n", argv[i]); 4701568b75bSmrg ok = False; 4711568b75bSmrg } 4721568b75bSmrg } 4731568b75bSmrg 4741568b75bSmrg present = 0; 4751568b75bSmrg if (svValue[TYPES_NDX]) 4761568b75bSmrg present++; 4771568b75bSmrg if (svValue[COMPAT_NDX]) 4781568b75bSmrg present++; 4791568b75bSmrg if (svValue[SYMBOLS_NDX]) 4801568b75bSmrg present++; 4811568b75bSmrg if (svValue[KEYCODES_NDX]) 4821568b75bSmrg present++; 4831568b75bSmrg if (svValue[GEOMETRY_NDX]) 4841568b75bSmrg present++; 4851568b75bSmrg if (svValue[CONFIG_NDX]) 4861568b75bSmrg present++; 4871568b75bSmrg if (svValue[MODEL_NDX]) 4881568b75bSmrg present++; 4891568b75bSmrg if (svValue[LAYOUT_NDX]) 4901568b75bSmrg present++; 4911568b75bSmrg if (svValue[VARIANT_NDX]) 4921568b75bSmrg present++; 4931568b75bSmrg if (svValue[KEYMAP_NDX] && present) 4941568b75bSmrg { 4951568b75bSmrg ERR("No other components can be specified when a keymap is present\n"); 4961568b75bSmrg return False; 4977d5e3a19Smrg } 4987d5e3a19Smrg return ok; 4997d5e3a19Smrg} 5007d5e3a19Smrg 5011568b75bSmrg/** 5021568b75bSmrg * Open a connection to the display and print error if it fails. 5031568b75bSmrg * 5041568b75bSmrg * @return True on success or False otherwise. 5051568b75bSmrg */ 5067d5e3a19SmrgBool 5071568b75bSmrggetDisplay(int argc, char **argv) 5087d5e3a19Smrg{ 5091568b75bSmrg int major, minor, why; 5101568b75bSmrg 5111568b75bSmrg major = XkbMajorVersion; 5121568b75bSmrg minor = XkbMinorVersion; 5131568b75bSmrg dpy = 5141568b75bSmrg XkbOpenDisplay(svValue[DISPLAY_NDX], NULL, NULL, &major, &minor, 5151568b75bSmrg &why); 5161568b75bSmrg if (!dpy) 5171568b75bSmrg { 5181568b75bSmrg if (svValue[DISPLAY_NDX] == NULL) 5191568b75bSmrg svValue[DISPLAY_NDX] = getenv("DISPLAY"); 5201568b75bSmrg if (svValue[DISPLAY_NDX] == NULL) 5211568b75bSmrg svValue[DISPLAY_NDX] = "default display"; 5221568b75bSmrg switch (why) 5231568b75bSmrg { 5241568b75bSmrg case XkbOD_BadLibraryVersion: 5251568b75bSmrg ERR3("%s was compiled with XKB version %d.%02d\n", argv[0], 5261568b75bSmrg XkbMajorVersion, XkbMinorVersion); 5271568b75bSmrg ERR2("Xlib supports incompatible version %d.%02d\n", 5281568b75bSmrg major, minor); 5291568b75bSmrg break; 5301568b75bSmrg case XkbOD_ConnectionRefused: 5311568b75bSmrg ERR1("Cannot open display \"%s\"\n", svValue[DISPLAY_NDX]); 5321568b75bSmrg break; 5331568b75bSmrg case XkbOD_NonXkbServer: 5341568b75bSmrg ERR1("XKB extension not present on %s\n", svValue[DISPLAY_NDX]); 5351568b75bSmrg break; 5361568b75bSmrg case XkbOD_BadServerVersion: 5371568b75bSmrg ERR3("%s was compiled with XKB version %d.%02d\n", argv[0], 5381568b75bSmrg XkbMajorVersion, XkbMinorVersion); 5391568b75bSmrg ERR3("Server %s uses incompatible version %d.%02d\n", 5401568b75bSmrg svValue[DISPLAY_NDX], major, minor); 5411568b75bSmrg break; 5421568b75bSmrg default: 5431568b75bSmrg ERR1("Unknown error %d from XkbOpenDisplay\n", why); 5441568b75bSmrg break; 5451568b75bSmrg } 5461568b75bSmrg return False; 5477d5e3a19Smrg } 5487d5e3a19Smrg if (synch) 5491568b75bSmrg XSynchronize(dpy, True); 5507d5e3a19Smrg return True; 5517d5e3a19Smrg} 5527d5e3a19Smrg 5537d5e3a19Smrg/***====================================================================***/ 5547d5e3a19Smrg 5551568b75bSmrg/** 556765486e8Smrg * Retrieve xkb values from the XKB_RULES_NAMES property and store their 5571568b75bSmrg * contents in svValues. 5581568b75bSmrg * If the property cannot be read, the built-in defaults are used. 5591568b75bSmrg * 5601568b75bSmrg * @return True. 5611568b75bSmrg */ 5627d5e3a19SmrgBool 5637d5e3a19SmrggetServerValues(void) 5647d5e3a19Smrg{ 5651568b75bSmrg XkbRF_VarDefsRec vd; 5661568b75bSmrg char *tmp = NULL; 5677d5e3a19Smrg 5681568b75bSmrg if (!XkbRF_GetNamesProp(dpy, &tmp, &vd) || !tmp) 5691568b75bSmrg { 5701568b75bSmrg VMSG1(3, "Couldn't interpret %s property\n", _XKB_RF_NAMES_PROP_ATOM); 5717d5e3a19Smrg tmp = DFLT_XKB_RULES_FILE; 5727d5e3a19Smrg vd.model = DFLT_XKB_MODEL; 5737d5e3a19Smrg vd.layout = DFLT_XKB_LAYOUT; 5747d5e3a19Smrg vd.variant = NULL; 5757d5e3a19Smrg vd.options = NULL; 5761568b75bSmrg VMSG3(3, "Use defaults: rules - '%s' model - '%s' layout - '%s'\n", 5771568b75bSmrg tmp, vd.model, vd.layout); 5787d5e3a19Smrg } 5797d5e3a19Smrg if (tmp) 5801568b75bSmrg trySetString(RULES_NDX, tmp, FROM_SERVER); 5817d5e3a19Smrg if (vd.model) 5821568b75bSmrg trySetString(MODEL_NDX, vd.model, FROM_SERVER); 5837d5e3a19Smrg if (vd.layout) 5841568b75bSmrg trySetString(LAYOUT_NDX, vd.layout, FROM_SERVER); 5857d5e3a19Smrg if (vd.variant) 5861568b75bSmrg trySetString(VARIANT_NDX, vd.variant, FROM_SERVER); 5871568b75bSmrg if ((vd.options) && (!clearOptions)) 5881568b75bSmrg { 5891568b75bSmrg addStringToOptions(vd.options, &szOptions, &numOptions, &options); 5901568b75bSmrg XFree(vd.options); 5917d5e3a19Smrg } 5927d5e3a19Smrg return True; 5937d5e3a19Smrg} 5947d5e3a19Smrg 5957d5e3a19Smrg/***====================================================================***/ 5967d5e3a19Smrg 5977d5e3a19SmrgFILE * 5981568b75bSmrgfindFileInPath(char *name, char *subdir) 5997d5e3a19Smrg{ 6001568b75bSmrg register int i; 6011568b75bSmrg char buf[PATH_MAX]; 6021568b75bSmrg FILE *fp; 6031568b75bSmrg 6041568b75bSmrg if (name[0] == '/') 6051568b75bSmrg { 6061568b75bSmrg fp = fopen(name, "r"); 6071568b75bSmrg if ((verbose > 7) || ((!fp) && (verbose > 0))) 6081568b75bSmrg MSG2("%s file %s\n", (fp ? "Found" : "Didn't find"), name); 6091568b75bSmrg return fp; 6101568b75bSmrg } 6111568b75bSmrg for (i = 0; (i < numInclPath); i++) 6121568b75bSmrg { 6131568b75bSmrg if ((strlen(inclPath[i]) + strlen(subdir) + strlen(name) + 2) > 6141568b75bSmrg PATH_MAX) 6151568b75bSmrg { 6161568b75bSmrg VMSG3(0, "Path too long (%s/%s%s). Ignored.\n", inclPath[i], 6171568b75bSmrg subdir, name); 6181568b75bSmrg continue; 6191568b75bSmrg } 6201568b75bSmrg sprintf(buf, "%s/%s%s", inclPath[i], subdir, name); 6211568b75bSmrg fp = fopen(name, "r"); 6221568b75bSmrg if ((verbose > 7) || ((!fp) && (verbose > 5))) 6231568b75bSmrg MSG2("%s file %s\n", (fp ? "Found" : "Didn't find"), buf); 6241568b75bSmrg if (fp != NULL) 6251568b75bSmrg return fp; 6267d5e3a19Smrg } 6277d5e3a19Smrg return NULL; 6287d5e3a19Smrg} 6297d5e3a19Smrg 6307d5e3a19Smrg/***====================================================================***/ 6317d5e3a19Smrg 6327d5e3a19SmrgBool 6331568b75bSmrgaddStringToOptions(char *opt_str, int *sz_opts, int *num_opts, char ***opts) 6347d5e3a19Smrg{ 6351568b75bSmrg char *tmp, *str, *next; 6361568b75bSmrg Bool ok = True; 6377d5e3a19Smrg 6387d5e3a19Smrg if ((str = strdup(opt_str)) == NULL) 6391568b75bSmrg return False; 6401568b75bSmrg for (tmp = str, next = NULL; (tmp && *tmp != '\0') && ok; tmp = next) 6411568b75bSmrg { 6421568b75bSmrg next = strchr(str, ','); 6431568b75bSmrg if (next) 6441568b75bSmrg { 6451568b75bSmrg *next = '\0'; 6461568b75bSmrg next++; 6471568b75bSmrg } 6481568b75bSmrg ok = addToList(sz_opts, num_opts, opts, tmp) && ok; 6497d5e3a19Smrg } 6507d5e3a19Smrg free(str); 6517d5e3a19Smrg return ok; 6527d5e3a19Smrg} 6537d5e3a19Smrg 6547d5e3a19Smrg/***====================================================================***/ 6557d5e3a19Smrg 6567d5e3a19Smrgchar * 6571568b75bSmrgstringFromOptions(char *orig, int numNew, char **newOpts) 6587d5e3a19Smrg{ 6591568b75bSmrg int len, i, nOut; 6601568b75bSmrg 6611568b75bSmrg if (orig) 6621568b75bSmrg len = strlen(orig) + 1; 6631568b75bSmrg else 6641568b75bSmrg len = 0; 6651568b75bSmrg for (i = 0; i < numNew; i++) 6661568b75bSmrg { 6671568b75bSmrg if (newOpts[i]) 6681568b75bSmrg len += strlen(newOpts[i]) + 1; 6691568b75bSmrg } 6701568b75bSmrg if (len < 1) 6711568b75bSmrg return NULL; 6721568b75bSmrg if (orig) 6731568b75bSmrg { 6741568b75bSmrg orig = (char *) realloc(orig, len); 6751568b75bSmrg if (!orig) 6761568b75bSmrg { 6771568b75bSmrg ERR("OOM in stringFromOptions\n"); 6781568b75bSmrg return NULL; 6791568b75bSmrg } 6801568b75bSmrg nOut = 1; 6811568b75bSmrg } 6821568b75bSmrg else 6831568b75bSmrg { 6841568b75bSmrg orig = (char *) calloc(len, 1); 6851568b75bSmrg if (!orig) 6861568b75bSmrg { 6871568b75bSmrg ERR("OOM in stringFromOptions\n"); 6881568b75bSmrg return NULL; 6891568b75bSmrg } 6901568b75bSmrg nOut = 0; 6911568b75bSmrg } 6921568b75bSmrg for (i = 0; i < numNew; i++) 6931568b75bSmrg { 6941568b75bSmrg if (!newOpts[i]) 6951568b75bSmrg continue; 6961568b75bSmrg if (nOut > 0) 6971568b75bSmrg { 6981568b75bSmrg strcat(orig, ","); 6991568b75bSmrg strcat(orig, newOpts[i]); 7001568b75bSmrg } 7011568b75bSmrg else 7021568b75bSmrg strcpy(orig, newOpts[i]); 7031568b75bSmrg nOut++; 7047d5e3a19Smrg } 7057d5e3a19Smrg return orig; 7067d5e3a19Smrg} 7077d5e3a19Smrg 7087d5e3a19Smrg/***====================================================================***/ 7097d5e3a19Smrg 7107d5e3a19SmrgBool 7117d5e3a19SmrgapplyConfig(char *name) 7127d5e3a19Smrg{ 7131568b75bSmrg FILE *fp; 7141568b75bSmrg Bool ok; 7151568b75bSmrg 7161568b75bSmrg if ((fp = findFileInPath(name, "")) == NULL) 7171568b75bSmrg return False; 7181568b75bSmrg ok = XkbCFParse(fp, XkbCFDflts, NULL, &cfgResult); 7197d5e3a19Smrg fclose(fp); 7201568b75bSmrg if (!ok) 7211568b75bSmrg { 7221568b75bSmrg ERR1("Couldn't find configuration file \"%s\"\n", name); 7231568b75bSmrg return False; 7247d5e3a19Smrg } 7251568b75bSmrg if (cfgResult.rules_file) 7261568b75bSmrg { 7271568b75bSmrg trySetString(RULES_NDX, cfgResult.rules_file, FROM_CONFIG); 7281568b75bSmrg cfgResult.rules_file = NULL; 7297d5e3a19Smrg } 7301568b75bSmrg if (cfgResult.model) 7311568b75bSmrg { 7321568b75bSmrg trySetString(MODEL_NDX, cfgResult.model, FROM_CONFIG); 7331568b75bSmrg cfgResult.model = NULL; 7347d5e3a19Smrg } 7351568b75bSmrg if (cfgResult.layout) 7361568b75bSmrg { 7371568b75bSmrg trySetString(LAYOUT_NDX, cfgResult.layout, FROM_CONFIG); 7381568b75bSmrg cfgResult.layout = NULL; 7397d5e3a19Smrg } 7401568b75bSmrg if (cfgResult.variant) 7411568b75bSmrg { 7421568b75bSmrg trySetString(VARIANT_NDX, cfgResult.variant, FROM_CONFIG); 7431568b75bSmrg cfgResult.variant = NULL; 7447d5e3a19Smrg } 7451568b75bSmrg if (cfgResult.options) 7461568b75bSmrg { 7471568b75bSmrg addStringToOptions(cfgResult.options, &szOptions, &numOptions, 7481568b75bSmrg &options); 7491568b75bSmrg cfgResult.options = NULL; 7507d5e3a19Smrg } 7511568b75bSmrg if (cfgResult.keymap) 7521568b75bSmrg { 7531568b75bSmrg trySetString(KEYMAP_NDX, cfgResult.keymap, FROM_CONFIG); 7541568b75bSmrg cfgResult.keymap = NULL; 7557d5e3a19Smrg } 7561568b75bSmrg if (cfgResult.keycodes) 7571568b75bSmrg { 7581568b75bSmrg trySetString(KEYCODES_NDX, cfgResult.keycodes, FROM_CONFIG); 7591568b75bSmrg cfgResult.keycodes = NULL; 7607d5e3a19Smrg } 7611568b75bSmrg if (cfgResult.geometry) 7621568b75bSmrg { 7631568b75bSmrg trySetString(GEOMETRY_NDX, cfgResult.geometry, FROM_CONFIG); 7641568b75bSmrg cfgResult.geometry = NULL; 7657d5e3a19Smrg } 7661568b75bSmrg if (cfgResult.symbols) 7671568b75bSmrg { 7681568b75bSmrg trySetString(SYMBOLS_NDX, cfgResult.symbols, FROM_CONFIG); 7691568b75bSmrg cfgResult.symbols = NULL; 7707d5e3a19Smrg } 7711568b75bSmrg if (cfgResult.types) 7721568b75bSmrg { 7731568b75bSmrg trySetString(TYPES_NDX, cfgResult.types, FROM_CONFIG); 7741568b75bSmrg cfgResult.types = NULL; 7757d5e3a19Smrg } 7761568b75bSmrg if (cfgResult.compat) 7771568b75bSmrg { 7781568b75bSmrg trySetString(COMPAT_NDX, cfgResult.compat, FROM_CONFIG); 7791568b75bSmrg cfgResult.compat = NULL; 7807d5e3a19Smrg } 7811568b75bSmrg if (verbose > 5) 7821568b75bSmrg { 7831568b75bSmrg MSG("After config file:\n"); 7841568b75bSmrg dumpNames(True, True); 7857d5e3a19Smrg } 7867d5e3a19Smrg return True; 7877d5e3a19Smrg} 7887d5e3a19Smrg 7891568b75bSmrg/** 7901568b75bSmrg * If any of model, layout, variant or options is specified, then compile the 7911568b75bSmrg * options into the 7921568b75bSmrg * 7931568b75bSmrg * @return True on success or false otherwise. 7941568b75bSmrg */ 7957d5e3a19SmrgBool 7967d5e3a19SmrgapplyRules(void) 7977d5e3a19Smrg{ 7981568b75bSmrg int i; 7991568b75bSmrg char *rfName; 8007d5e3a19Smrg 8011568b75bSmrg if (svSrc[MODEL_NDX] || svSrc[LAYOUT_NDX] || svSrc[VARIANT_NDX] 8021568b75bSmrg || options) 8031568b75bSmrg { 8041568b75bSmrg char buf[PATH_MAX]; 8051568b75bSmrg XkbComponentNamesRec rnames; 8067d5e3a19Smrg 8071568b75bSmrg if (svSrc[VARIANT_NDX] < svSrc[LAYOUT_NDX]) 8087d5e3a19Smrg svValue[VARIANT_NDX] = NULL; 8097d5e3a19Smrg 8101568b75bSmrg rdefs.model = svValue[MODEL_NDX]; 8111568b75bSmrg rdefs.layout = svValue[LAYOUT_NDX]; 8121568b75bSmrg rdefs.variant = svValue[VARIANT_NDX]; 8131568b75bSmrg if (options) 8141568b75bSmrg rdefs.options = 8151568b75bSmrg stringFromOptions(rdefs.options, numOptions, options); 8161568b75bSmrg 8171568b75bSmrg if (svSrc[RULES_NDX]) 8181568b75bSmrg rfName = svValue[RULES_NDX]; 8191568b75bSmrg else 8201568b75bSmrg rfName = DFLT_XKB_RULES_FILE; 8211568b75bSmrg 8221568b75bSmrg if (rfName[0] == '/') 8231568b75bSmrg { 8241568b75bSmrg rules = XkbRF_Load(rfName, svValue[LOCALE_NDX], True, True); 8251568b75bSmrg } 8261568b75bSmrg else 8271568b75bSmrg { 8281568b75bSmrg /* try to load rules files from all include paths until the first 8291568b75bSmrg * we succeed with */ 8301568b75bSmrg for (i = 0; (i < numInclPath) && (!rules); i++) 8311568b75bSmrg { 8321568b75bSmrg if ((strlen(inclPath[i]) + strlen(rfName) + 8) > PATH_MAX) 8331568b75bSmrg { 8341568b75bSmrg VMSG2(0, "Path too long (%s/rules/%s). Ignored.\n", 8351568b75bSmrg inclPath[i], rfName); 8361568b75bSmrg continue; 8371568b75bSmrg } 8381568b75bSmrg sprintf(buf, "%s/rules/%s", inclPath[i], svValue[RULES_NDX]); 8391568b75bSmrg rules = XkbRF_Load(buf, svValue[LOCALE_NDX], True, True); 8401568b75bSmrg } 8411568b75bSmrg } 8421568b75bSmrg if (!rules) 8431568b75bSmrg { 8441568b75bSmrg ERR1("Couldn't find rules file (%s) \n", svValue[RULES_NDX]); 8451568b75bSmrg return False; 8461568b75bSmrg } 8471568b75bSmrg /* Let the rules file to the magic, then update the svValues with 8481568b75bSmrg * those returned after processing the rules */ 8491568b75bSmrg XkbRF_GetComponents(rules, &rdefs, &rnames); 8501568b75bSmrg if (rnames.keycodes) 8511568b75bSmrg { 8521568b75bSmrg trySetString(KEYCODES_NDX, rnames.keycodes, FROM_RULES); 8531568b75bSmrg rnames.keycodes = NULL; 8541568b75bSmrg } 8551568b75bSmrg if (rnames.symbols) 8561568b75bSmrg { 8571568b75bSmrg trySetString(SYMBOLS_NDX, rnames.symbols, FROM_RULES); 8581568b75bSmrg rnames.symbols = NULL; 8591568b75bSmrg } 8601568b75bSmrg if (rnames.types) 8611568b75bSmrg { 8621568b75bSmrg trySetString(TYPES_NDX, rnames.types, FROM_RULES); 8631568b75bSmrg rnames.types = NULL; 8641568b75bSmrg } 8651568b75bSmrg if (rnames.compat) 8661568b75bSmrg { 8671568b75bSmrg trySetString(COMPAT_NDX, rnames.compat, FROM_RULES); 8681568b75bSmrg rnames.compat = NULL; 8691568b75bSmrg } 8701568b75bSmrg if (rnames.geometry) 8711568b75bSmrg { 8721568b75bSmrg trySetString(GEOMETRY_NDX, rnames.geometry, FROM_RULES); 8731568b75bSmrg rnames.geometry = NULL; 8741568b75bSmrg } 8751568b75bSmrg if (rnames.keymap) 8761568b75bSmrg { 8771568b75bSmrg trySetString(KEYMAP_NDX, rnames.keymap, FROM_RULES); 8781568b75bSmrg rnames.keymap = NULL; 8791568b75bSmrg } 8801568b75bSmrg if (verbose > 6) 8811568b75bSmrg { 8821568b75bSmrg MSG1("Applied rules from %s:\n", svValue[RULES_NDX]); 8831568b75bSmrg dumpNames(True, False); 8841568b75bSmrg } 8851568b75bSmrg } 8861568b75bSmrg else if (verbose > 6) 8871568b75bSmrg { 8881568b75bSmrg MSG("No rules variables specified. Rules file ignored\n"); 8897d5e3a19Smrg } 8907d5e3a19Smrg return True; 8917d5e3a19Smrg} 8927d5e3a19Smrg 8937d5e3a19Smrg/* Primitive sanity check - filter out 'map names' (inside parenthesis) */ 8947d5e3a19Smrg/* that can confuse xkbcomp parser */ 8951568b75bSmrgstatic Bool 8961568b75bSmrgcheckName(char *name, char *string) 8977d5e3a19Smrg{ 8981568b75bSmrg char *i = name, *opar = NULL; 8991568b75bSmrg Bool ret = True; 9001568b75bSmrg 9011568b75bSmrg if (!name) 9021568b75bSmrg return True; 9031568b75bSmrg 9041568b75bSmrg while (*i) 9051568b75bSmrg { 9061568b75bSmrg if (opar == NULL) 9071568b75bSmrg { 9081568b75bSmrg if (*i == '(') 9091568b75bSmrg opar = i; 9101568b75bSmrg } 9111568b75bSmrg else 9121568b75bSmrg { 9131568b75bSmrg if ((*i == '(') || (*i == '|') || (*i == '+')) 9141568b75bSmrg { 9151568b75bSmrg ret = False; 9161568b75bSmrg break; 9171568b75bSmrg } 9181568b75bSmrg if (*i == ')') 9191568b75bSmrg opar = NULL; 9201568b75bSmrg } 9211568b75bSmrg i++; 9221568b75bSmrg } 9231568b75bSmrg if (opar) 9241568b75bSmrg ret = False; 9251568b75bSmrg if (!ret) 9261568b75bSmrg { 9271568b75bSmrg char c; 9281568b75bSmrg int n = 1; 9291568b75bSmrg for (i = opar + 1; *i && n; i++) 9301568b75bSmrg { 9311568b75bSmrg if (*i == '(') 9321568b75bSmrg n++; 9331568b75bSmrg if (*i == ')') 9341568b75bSmrg n--; 9351568b75bSmrg } 9361568b75bSmrg if (*i) 9371568b75bSmrg i++; 9381568b75bSmrg c = *i; 9391568b75bSmrg *i = '\0'; 9401568b75bSmrg ERR1("Illegal map name '%s' ", opar); 9411568b75bSmrg *i = c; 9421568b75bSmrg ERR2("in %s name '%s'\n", string, name); 9431568b75bSmrg } 9441568b75bSmrg return ret; 9457d5e3a19Smrg} 9467d5e3a19Smrg 9477d5e3a19Smrgvoid 9487d5e3a19SmrgprintKeymap(void) 9497d5e3a19Smrg{ 9507d5e3a19Smrg MSG("xkb_keymap {\n"); 9517d5e3a19Smrg if (svValue[KEYCODES_NDX]) 9521568b75bSmrg MSG1("\txkb_keycodes { include \"%s\"\t};\n", svValue[KEYCODES_NDX]); 9537d5e3a19Smrg if (svValue[TYPES_NDX]) 9541568b75bSmrg MSG1("\txkb_types { include \"%s\"\t};\n", svValue[TYPES_NDX]); 9557d5e3a19Smrg if (svValue[COMPAT_NDX]) 9561568b75bSmrg MSG1("\txkb_compat { include \"%s\"\t};\n", svValue[COMPAT_NDX]); 9577d5e3a19Smrg if (svValue[SYMBOLS_NDX]) 9581568b75bSmrg MSG1("\txkb_symbols { include \"%s\"\t};\n", svValue[SYMBOLS_NDX]); 9597d5e3a19Smrg if (svValue[GEOMETRY_NDX]) 9601568b75bSmrg MSG1("\txkb_geometry { include \"%s\"\t};\n", svValue[GEOMETRY_NDX]); 9617d5e3a19Smrg MSG("};\n"); 9627d5e3a19Smrg} 9637d5e3a19Smrg 9647d5e3a19SmrgBool 9657d5e3a19SmrgapplyComponentNames(void) 9667d5e3a19Smrg{ 9671568b75bSmrg if (!checkName(svValue[TYPES_NDX], "types")) 9681568b75bSmrg return False; 9691568b75bSmrg if (!checkName(svValue[COMPAT_NDX], "compat")) 9701568b75bSmrg return False; 9711568b75bSmrg if (!checkName(svValue[SYMBOLS_NDX], "symbols")) 9721568b75bSmrg return False; 9731568b75bSmrg if (!checkName(svValue[KEYCODES_NDX], "keycodes")) 9741568b75bSmrg return False; 9751568b75bSmrg if (!checkName(svValue[GEOMETRY_NDX], "geometry")) 9761568b75bSmrg return False; 9771568b75bSmrg if (!checkName(svValue[KEYMAP_NDX], "keymap")) 9781568b75bSmrg return False; 9791568b75bSmrg 9801568b75bSmrg if (verbose > 5) 9811568b75bSmrg { 9821568b75bSmrg MSG("Trying to build keymap using the following components:\n"); 9831568b75bSmrg dumpNames(False, True); 9841568b75bSmrg } 9851568b75bSmrg /* Upload the new description to the server. */ 986765486e8Smrg if (dpy && !print && !query) 9871568b75bSmrg { 9881568b75bSmrg XkbComponentNamesRec cmdNames; 9891568b75bSmrg cmdNames.types = svValue[TYPES_NDX]; 9901568b75bSmrg cmdNames.compat = svValue[COMPAT_NDX]; 9911568b75bSmrg cmdNames.symbols = svValue[SYMBOLS_NDX]; 9921568b75bSmrg cmdNames.keycodes = svValue[KEYCODES_NDX]; 9931568b75bSmrg cmdNames.geometry = svValue[GEOMETRY_NDX]; 9941568b75bSmrg cmdNames.keymap = svValue[KEYMAP_NDX]; 9951568b75bSmrg xkb = XkbGetKeyboardByName(dpy, deviceSpec, &cmdNames, 9961568b75bSmrg XkbGBN_AllComponentsMask, 9971568b75bSmrg XkbGBN_AllComponentsMask & 9981568b75bSmrg (~XkbGBN_GeometryMask), True); 9991568b75bSmrg if (!xkb) 10001568b75bSmrg { 10011568b75bSmrg ERR("Error loading new keyboard description\n"); 10021568b75bSmrg return False; 10031568b75bSmrg } 10041568b75bSmrg /* update the XKB root property */ 10051568b75bSmrg if (svValue[RULES_NDX] && (rdefs.model || rdefs.layout)) 10061568b75bSmrg { 10071568b75bSmrg if (!XkbRF_SetNamesProp(dpy, svValue[RULES_NDX], &rdefs)) 10081568b75bSmrg { 10091568b75bSmrg VMSG(0, "Error updating the XKB names property\n"); 10101568b75bSmrg } 10111568b75bSmrg } 10121568b75bSmrg } 10131568b75bSmrg if (print) 10141568b75bSmrg { 10157d5e3a19Smrg printKeymap(); 10167d5e3a19Smrg } 1017765486e8Smrg if (query) 1018765486e8Smrg { 1019765486e8Smrg dumpNames(True, False); 1020765486e8Smrg } 10217d5e3a19Smrg return True; 10227d5e3a19Smrg} 10237d5e3a19Smrg 10247d5e3a19Smrg 10257d5e3a19Smrgint 10261568b75bSmrgmain(int argc, char **argv) 10277d5e3a19Smrg{ 10281568b75bSmrg if ((!parseArgs(argc, argv)) || (!getDisplay(argc, argv))) 10291568b75bSmrg exit(-1); 10301568b75bSmrg svValue[LOCALE_NDX] = setlocale(LC_ALL, svValue[LOCALE_NDX]); 10311568b75bSmrg svSrc[LOCALE_NDX] = FROM_SERVER; 10321568b75bSmrg VMSG1(7, "locale is %s\n", svValue[LOCALE_NDX]); 10337d5e3a19Smrg if (dpy) 10347d5e3a19Smrg getServerValues(); 10357d5e3a19Smrg if (svValue[CONFIG_NDX] && (!applyConfig(svValue[CONFIG_NDX]))) 10361568b75bSmrg exit(-3); 10377d5e3a19Smrg if (!applyRules()) 10381568b75bSmrg exit(-4); 10397d5e3a19Smrg if (!applyComponentNames()) 10401568b75bSmrg exit(-5); 10417d5e3a19Smrg if (dpy) 10421568b75bSmrg XCloseDisplay(dpy); 10437d5e3a19Smrg exit(0); 10447d5e3a19Smrg} 1045