/************************************************************ Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Silicon Graphics not be used in advertising or publicity pertaining to distribution of the software without specific prior written permission. Silicon Graphics makes no representation about the suitability of this software for any purpose. It is provided "as is" without any express or implied warranty. SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ********************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifndef PATH_MAX #ifdef MAXPATHLEN #define PATH_MAX MAXPATHLEN #else #define PATH_MAX 1024 #endif #endif #ifndef DFLT_XKB_CONFIG_ROOT #define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb" #endif #ifndef DFLT_XKB_RULES_FILE #define DFLT_XKB_RULES_FILE "base" #endif #ifndef DFLT_XKB_LAYOUT #define DFLT_XKB_LAYOUT "us" #endif #ifndef DFLT_XKB_MODEL #define DFLT_XKB_MODEL "pc105" #endif /* Constants to state how a value was obtained. The order of these * is important, the bigger the higher the priority. * e.g. FROM_CONFIG overrides FROM_SERVER */ enum source { UNDEFINED = 0, FROM_SERVER, /* Retrieved from server at runtime. */ FROM_RULES, /* Xkb rules file. */ FROM_CONFIG, /* Command-line specified config file. */ FROM_CMD_LINE, /* Specified at the cmdline. */ NUM_SOURCES }; /***====================================================================***/ static Bool print = False; static Bool query = False; static Bool synch = False; static int verbose = 5; static Display *dpy; /** * human-readable versions of FROM_CONFIG, FROM_SERVER, etc. Used for error * reporting. */ static const char *srcName[NUM_SOURCES] = { "undefined", "X server", "rules file", "config file", "command line" }; struct setting { char const *name; /* Human-readable setting name. Used for error reporting. */ char *value; /* Holds the value. */ enum source src; /* Holds the source. */ }; typedef struct setting setting_t; struct settings { setting_t rules; /* Rules file */ setting_t config; /* Config file (if used) */ setting_t display; /* X display name */ setting_t locale; /* Machine's locale */ setting_t model; setting_t layout; setting_t variant; setting_t keycodes; setting_t types; setting_t compat; setting_t symbols; setting_t geometry; setting_t keymap; }; typedef struct settings settings_t; static settings_t settings = { { "rules file", NULL, UNDEFINED }, { "config file", NULL, UNDEFINED }, { "X display", NULL, UNDEFINED }, { "locale", NULL, UNDEFINED }, { "keyboard model", NULL, UNDEFINED }, { "keyboard layout", NULL, UNDEFINED }, { "layout variant", NULL, UNDEFINED }, { "keycodes", NULL, UNDEFINED }, { "types", NULL, UNDEFINED }, { "compatibility map", NULL, UNDEFINED }, { "symbols", NULL, UNDEFINED }, { "geometry", NULL, UNDEFINED }, { "keymap", NULL, UNDEFINED } }; static XkbConfigRtrnRec cfgResult; static XkbRF_VarDefsRec rdefs; static Bool clearOptions = False; struct list { char **item; /* Array of items. */ int sz; /* Size of array. */ int num; /* Number of used elements. */ }; typedef struct list list_t; static list_t options = { NULL, 0, 0 }; static list_t inclPath = { NULL, 0, 0 }; static XkbDescPtr xkb = NULL; static int deviceSpec = XkbUseCoreKbd; /***====================================================================***/ #define streq(s1,s2) (strcmp(s1,s2)==0) #define strpfx(s1,s2) (strncmp(s1,s2,strlen(s2))==0) #define MSG(s) printf(s) #define MSG1(s,a) printf(s,a) #define MSG2(s,a,b) printf(s,a,b) #define MSG3(s,a,b,c) printf(s,a,b,c) #define VMSG(l,s) if (verbose>(l)) printf(s) #define VMSG1(l,s,a) if (verbose>(l)) printf(s,a) #define VMSG2(l,s,a,b) if (verbose>(l)) printf(s,a,b) #define VMSG3(l,s,a,b,c) if (verbose>(l)) printf(s,a,b,c) #define ERR(s) fprintf(stderr,s) #define ERR1(s,a) fprintf(stderr,s,a) #define ERR2(s,a,b) fprintf(stderr,s,a,b) #define ERR3(s,a,b,c) fprintf(stderr,s,a,b,c) #define OOM(ptr) do { if ((ptr) == NULL) { ERR("Out of memory.\n"); exit(1); } } while (0) /***====================================================================***/ static Bool addToList(list_t *list, const char *newVal); static void usage(int argc, char **argv); static void dumpNames(Bool wantRules, Bool wantCNames); static void trySetString(setting_t * setting, char *newVal, enum source src); static Bool setOptString(int *arg, int argc, char **argv, setting_t *setting, enum source src); static int parseArgs(int argc, char **argv); static Bool getDisplay(int argc, char **argv); static Bool getServerValues(void); static FILE *findFileInPath(char *name); static Bool addStringToOptions(char *opt_str, list_t *opts); static char *stringFromOptions(char *orig, list_t *newOpts); static Bool applyConfig(char *name); static XkbRF_RulesPtr tryLoadRules(char *name, char *locale, Bool wantDesc, Bool wantRules); static Bool applyRules(void); static Bool applyComponentNames(void); static void printKeymap(void); /***====================================================================***/ /* If newVal is NULL or empty string, the list is cleared. Otherwise newVal is added to the end of the list (if it is not present in the list yet). */ static Bool addToList(list_t *list, const char *newVal) { register int i; if ((!newVal) || (!newVal[0])) { list->num = 0; return True; } for (i = 0; i < list->num; i++) { if (streq(list->item[i], newVal)) return True; } if ((list->item == NULL) || (list->sz < 1)) { list->num = 0; list->sz = 4; list->item = (char **) calloc(list->sz, sizeof(char *)); OOM(list->item); } else if (list->num >= list->sz) { list->sz *= 2; list->item = (char **) realloc(list->item, (list->sz) * sizeof(char *)); OOM(list->item); } list->item[list->num] = strdup(newVal); OOM(list->item[list->num]); list->num += 1; return True; } /***====================================================================***/ static void usage(int argc, char **argv) { MSG1( "Usage: %s [options] [ [ [