diff options
-rw-r--r-- | setxkbmap.c | 953 | ||||
-rw-r--r-- | setxkbmap.man | 120 |
2 files changed, 1073 insertions, 0 deletions
diff --git a/setxkbmap.c b/setxkbmap.c new file mode 100644 index 0000000..078a158 --- /dev/null +++ b/setxkbmap.c @@ -0,0 +1,953 @@ +/************************************************************ + 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. + + ********************************************************/ +/* $XFree86: xc/programs/setxkbmap/setxkbmap.c,v 3.7 2003/01/20 04:15:08 dawes Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <limits.h> +#include <ctype.h> +#include <X11/Xlib.h> +#include <X11/Xos.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBfile.h> +#include <X11/extensions/XKBconfig.h> +#include <X11/extensions/XKBrules.h> + +#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/X11R6/lib/X11/xkb" +#endif +#ifndef DFLT_XKB_RULES_FILE +#define DFLT_XKB_RULES_FILE "xfree86" +#endif +#ifndef DFLT_XKB_LAYOUT +#define DFLT_XKB_LAYOUT "us" +#endif +#ifndef DFLT_XKB_MODEL +#define DFLT_XKB_MODEL "pc101" +#endif + +#define UNDEFINED 0 +#define FROM_SERVER 1 +#define FROM_RULES 2 +#define FROM_CONFIG 3 +#define FROM_CMD_LINE 4 +#define NUM_SOURCES 5 + +#define RULES_NDX 0 +#define CONFIG_NDX 1 +#define DISPLAY_NDX 2 +#define LOCALE_NDX 3 +#define MODEL_NDX 4 +#define LAYOUT_NDX 5 +#define VARIANT_NDX 6 +#define KEYCODES_NDX 7 +#define TYPES_NDX 8 +#define COMPAT_NDX 9 +#define SYMBOLS_NDX 10 +#define GEOMETRY_NDX 11 +#define KEYMAP_NDX 12 +#define NUM_STRING_VALS 13 + +/***====================================================================***/ +Bool print= False; +Bool synch= False; +int verbose= 5; + +Display * dpy; + +char * srcName[NUM_SOURCES] = { + "undefined", "X server", "rules file", "config file", "command line" +}; + +char * svName[NUM_STRING_VALS]= { + "rules file", "config file", "X display", "locale", + "keyboard model", "keyboard layout", "layout variant", + "keycodes", "types", "compatibility map", "symbols", "geometry", + "keymap" +}; +int svSrc[NUM_STRING_VALS]; +char * svValue[NUM_STRING_VALS]; + +XkbConfigFieldsRec cfgDflts; +XkbConfigRtrnRec cfgResult; + +XkbRF_RulesPtr rules= NULL; +XkbRF_VarDefsRec rdefs; + +Bool clearOptions= False; +int szOptions= 0; +int numOptions= 0; +char ** options= NULL; + +int szInclPath= 0; +int numInclPath= 0; +char ** inclPath= NULL; + +XkbDescPtr xkb= NULL; + +/***====================================================================***/ + +#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) + +/***====================================================================***/ + +Bool addToList ( int *sz, int *num, char ***listIn, char *newVal ); +void usage ( int argc, char ** argv ); +void dumpNames ( Bool wantRules, Bool wantCNames ); +void trySetString ( int which, char * newVal, int src ); +Bool setOptString ( int *arg, int argc, char **argv, int which, int src ); +int parseArgs ( int argc, char ** argv ); +Bool getDisplay ( int argc, char ** argv ); +Bool getServerValues ( void ); +FILE * findFileInPath ( char * name, char * subdir ); +Bool addStringToOptions ( char * opt_str, int * sz_opts, int * num_opts, char *** opts ); +char * stringFromOptions ( char * orig, int numNew, char ** newOpts ); +Bool applyConfig ( char * name ); +Bool applyRules ( void ); +Bool applyComponentNames ( void ); +void printKeymap( void ); + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +addToList(int *sz,int *num,char ***listIn,char *newVal) +#else +addToList(sz,num,listIn,newVal) + int * sz; + int * num; + char *** listIn; + char * newVal; +#endif +{ +register int i; +char **list; + + if ((!newVal)||(!newVal[0])) { + *num= 0; + return True; + } + list= *listIn; + for (i=0;i<*num;i++) { + if (streq(list[i],newVal)) + return True; + } + if ((list==NULL)||(*sz<1)) { + *num= 0; + *sz= 4; + list= (char **)calloc(*sz,sizeof(char *)); + *listIn= list; + } + else if (*num>=*sz) { + *sz*= 2; + list= (char **)realloc(list,(*sz)*sizeof(char *)); + *listIn= list; + } + if (!list) { + ERR("Internal Error! Allocation failure in add to list!\n"); + ERR(" Exiting.\n"); + exit(-1); + } + list[*num]= strdup(newVal); + (*num)= (*num)+1; + return True; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +usage(int argc,char **argv) +#else +usage(argc,argv) + int argc; + char ** argv; +#endif +{ + MSG1("Usage: %s [args] [<layout> [<variant> [<option> ... ]]]\n",argv[0]); + MSG("Where legal args are:\n"); + MSG("-?,-help Print this message\n"); + MSG("-compat <name> Specifies compatibility map component name\n"); + MSG("-config <file> Specifies configuration file to use\n"); + MSG("-display <dpy> Specifies display to use\n"); + MSG("-geometry <name> Specifies geometry component name\n"); + MSG("-I[<dir>] Add <dir> to list of directories to be used\n"); + MSG("-keycodes <name> Specifies keycodes component name\n"); + MSG("-keymap <name> Specifies name of keymap to load\n"); + MSG("-layout <name> Specifies layout used to choose component names\n"); + MSG("-model <name> Specifies model used to choose component names\n"); + MSG("-option <name> Adds an option used to choose component names\n"); + MSG("-print Print a complete xkb_keymap description and exit\n"); + MSG("-rules <name> Name of rules file to use\n"); + MSG("-symbols <name> Specifies symbols component name\n"); + MSG("-synch Synchronize request w/X server\n"); + MSG("-types <name> Specifies types component name\n"); + MSG("-v[erbose] [<lvl>] Sets verbosity (1..10). Higher values yield\n"); + MSG(" more messages\n"); + MSG("-variant <name> Specifies layout variant used to choose component names\n"); +} + +void +#if NeedFunctionPrototypes +dumpNames(Bool wantRules,Bool wantCNames) +#else +dumpNames(wantRules,wantCNames) + Bool wantRules; + Bool wantCNames; +#endif +{ + if (wantRules) { + if (svValue[MODEL_NDX]) MSG1("model: %s\n",svValue[MODEL_NDX]); + if (svValue[LAYOUT_NDX]) MSG1("layout: %s\n",svValue[LAYOUT_NDX]); + if (svValue[VARIANT_NDX]) MSG1("variant: %s\n",svValue[VARIANT_NDX]); + if (options) { + char *opt_str=stringFromOptions(NULL, numOptions, options); + MSG1("options: %s\n", opt_str); + free(opt_str); + } + } + if (wantCNames) { + if (svValue[KEYMAP_NDX]) + MSG1("keymap: %s\n",svValue[KEYMAP_NDX]); + if (svValue[KEYCODES_NDX]) + MSG1("keycodes: %s\n",svValue[KEYCODES_NDX]); + if (svValue[TYPES_NDX]) + MSG1("types: %s\n",svValue[TYPES_NDX]); + if (svValue[COMPAT_NDX]) + MSG1("compat: %s\n",svValue[COMPAT_NDX]); + if (svValue[SYMBOLS_NDX]) + MSG1("symbols: %s\n",svValue[SYMBOLS_NDX]); + if (svValue[GEOMETRY_NDX]) + MSG1("geometry: %s\n",svValue[GEOMETRY_NDX]); + } + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +trySetString(int which,char *newVal,int src) +#else +trySetString(which,newVal,src) + int which; + char * newVal; + int src; +#endif +{ + if (svValue[which]!=NULL) { + if (svSrc[which]==src) { + VMSG2(0,"Warning! More than one %s from %s\n", + svName[which],srcName[src]); + VMSG2(0," Using \"%s\", ignoring \"%s\"\n", + svValue[which],newVal); + return; + } + else if (svSrc[which]>src) { + VMSG1(5,"Warning! Multiple definitions of %s\n",svName[which]); + VMSG2(5," Using %s, ignoring %s\n",srcName[svSrc[which]], + srcName[src]); + return; + } + } + svSrc[which]= src; + svValue[which]= newVal; + return; +} + +Bool +#if NeedFunctionPrototypes +setOptString(int *arg,int argc,char **argv,int which,int src) +#else +setOptString(arg,argc,argv,which,src) + int * arg; + int argc; + char ** argv; + int what; + int src; +#endif +{ +int ndx; +char * opt; + + ndx= *arg; + opt= argv[ndx]; + if (ndx>=argc-1) { + VMSG1(0,"No %s specified on the command line\n",svName[which]); + VMSG1(0,"Trailing %s option ignored\n",opt); + return True; + } + ndx++; + *arg= ndx; + if (svValue[which]!=NULL) { + if (svSrc[which]==src) { + VMSG2(0,"More than one %s on %s\n",svName[which],srcName[src]); + VMSG2(0,"Using \"%s\", ignoring \"%s\"\n",svValue[which],argv[ndx]); + return True; + } + else if (svSrc[which]>src) { + VMSG1(5,"Multiple definitions of %s\n",svName[which]); + VMSG2(5,"Using %s, ignoring %s\n",srcName[svSrc[which]], + srcName[src]); + return True; + } + } + svSrc[which]= src; + svValue[which]= argv[ndx]; + return True; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +parseArgs(int argc,char **argv) +#else +parseArgs(argc,argv) + int argc; + char ** argv; +#endif +{ +int i; +Bool ok; +unsigned present; + + ok= True; + addToList(&szInclPath,&numInclPath,&inclPath,"."); + addToList(&szInclPath,&numInclPath,&inclPath,DFLT_XKB_CONFIG_ROOT); + for (i=1;(i<argc)&&ok;i++) { + if (argv[i][0]!='-') { + if (!svSrc[LAYOUT_NDX]) + trySetString(LAYOUT_NDX,argv[i],FROM_CMD_LINE); + else if (!svSrc[VARIANT_NDX]) + trySetString(VARIANT_NDX,argv[i],FROM_CMD_LINE); + else ok= addToList(&szOptions,&numOptions,&options,argv[i]); + } + else if (streq(argv[i],"-compat")) + ok= setOptString(&i,argc,argv,COMPAT_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-config")) + ok= setOptString(&i,argc,argv,CONFIG_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-display")) + ok= setOptString(&i,argc,argv,DISPLAY_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-geometry")) + ok= setOptString(&i,argc,argv,GEOMETRY_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-help")||streq(argv[i],"-?")) { + usage(argc,argv); + exit(0); + } + else if (strpfx(argv[i],"-I")) + ok= addToList(&szInclPath,&numInclPath,&inclPath,&argv[i][2]); + else if (streq(argv[i],"-keycodes")) + ok= setOptString(&i,argc,argv,KEYCODES_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-keymap")) + ok= setOptString(&i,argc,argv,KEYMAP_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-layout")) + ok= setOptString(&i,argc,argv,LAYOUT_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-model")) + ok= setOptString(&i,argc,argv,MODEL_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-option")) { + if ((i==argc-1)||(argv[i+1][0]=='\0')||(argv[i+1][0]=='-')) { + clearOptions= True; + ok= addToList(&szOptions,&numOptions,&options,""); + if (i<argc-1 && argv[i+1][0]=='\0') + i++; + } + else { + ok= addToList(&szOptions,&numOptions,&options,argv[++i]); + } + } + else if (streq(argv[i],"-print")) + print= True; + else if (streq(argv[i],"-rules")) + ok= setOptString(&i,argc,argv,RULES_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-symbols")) + ok= setOptString(&i,argc,argv,SYMBOLS_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-synch")) + synch= True; + else if (streq(argv[i],"-types")) + ok= setOptString(&i,argc,argv,TYPES_NDX,FROM_CMD_LINE); + else if (streq(argv[i],"-verbose")||(streq(argv[i],"-v"))) { + if ((i<argc-1)&&(isdigit(argv[i+1][0]))) + verbose= atoi(argv[++i]); + else verbose++; + if (verbose<0) { + ERR1("Illegal verbose level %d. Reset to 0\n",verbose); + verbose=0; + } + else if (verbose>10) { + ERR1("Illegal verbose level %d. Reset to 10\n",verbose); + verbose= 10; + } + VMSG1(7,"Setting verbose level to %d\n",verbose); + } + else if (streq(argv[i],"-variant")) + ok= setOptString(&i,argc,argv,VARIANT_NDX,FROM_CMD_LINE); + else { + ERR1("Error! Option \"%s\" not recognized\n",argv[i]); + ok= False; + } + } + + present= 0; + if (svValue[TYPES_NDX]) present++; + if (svValue[COMPAT_NDX]) present++; + if (svValue[SYMBOLS_NDX]) present++; + if (svValue[KEYCODES_NDX]) present++; + if (svValue[GEOMETRY_NDX]) present++; + if (svValue[CONFIG_NDX]) present++; + if (svValue[MODEL_NDX]) present++; + if (svValue[LAYOUT_NDX]) present++; + if (svValue[VARIANT_NDX]) present++; + if (svValue[KEYMAP_NDX] && present) { + ERR("No other components can be specified when a keymap is present\n"); + return False; + } + return ok; +} + +Bool +#if NeedFunctionPrototypes +getDisplay(int argc,char **argv) +#else +getDisplay(argc,argv) + int argc; + char ** argv; +#endif +{ +int major,minor,why; + + major= XkbMajorVersion; + minor= XkbMinorVersion; + dpy= XkbOpenDisplay(svValue[DISPLAY_NDX],NULL,NULL,&major,&minor,&why); + if (!dpy) { + if (svValue[DISPLAY_NDX]==NULL) + svValue[DISPLAY_NDX]= getenv("DISPLAY"); + if (svValue[DISPLAY_NDX]==NULL) + svValue[DISPLAY_NDX]= "default display"; + switch (why) { + case XkbOD_BadLibraryVersion: + ERR3("%s was compiled with XKB version %d.%02d\n",argv[0], + XkbMajorVersion,XkbMinorVersion); + ERR2("Xlib supports incompatible version %d.%02d\n", + major,minor); + break; + case XkbOD_ConnectionRefused: + ERR1("Cannot open display \"%s\"\n",svValue[DISPLAY_NDX]); + break; + case XkbOD_NonXkbServer: + ERR1("XKB extension not present on %s\n",svValue[DISPLAY_NDX]); + break; + case XkbOD_BadServerVersion: + ERR3("%s was compiled with XKB version %d.%02d\n",argv[0], + XkbMajorVersion,XkbMinorVersion); + ERR3("Server %s uses incompatible version %d.%02d\n", + svValue[DISPLAY_NDX],major,minor); + break; + default: + ERR1("Unknown error %d from XkbOpenDisplay\n",why); + break; + } + return False; + } + if (synch) + XSynchronize(dpy,True); + return True; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +getServerValues(void) +#else +getServerValues() +#endif +{ +XkbRF_VarDefsRec vd; +char * tmp= NULL; + + if (!XkbRF_GetNamesProp(dpy,&tmp,&vd) || !tmp) { + VMSG1(3,"Couldn't interpret %s property\n",_XKB_RF_NAMES_PROP_ATOM); + tmp = DFLT_XKB_RULES_FILE; + vd.model = DFLT_XKB_MODEL; + vd.layout = DFLT_XKB_LAYOUT; + VMSG3(3,"Use defaults: rules - '%s' model - '%s' layout - '%s'\n", + tmp, vd.model, vd.layout); + } + if (tmp) + trySetString(RULES_NDX,tmp,FROM_SERVER); + if (vd.model) + trySetString(MODEL_NDX,vd.model,FROM_SERVER); + if (vd.layout) + trySetString(LAYOUT_NDX,vd.layout,FROM_SERVER); + if (vd.variant) + trySetString(VARIANT_NDX,vd.variant,FROM_SERVER); + if ((vd.options)&&(!clearOptions)) { + addStringToOptions(vd.options,&szOptions,&numOptions,&options); + XFree(vd.options); + } + return True; +} + +/***====================================================================***/ + +FILE * +#if NeedFunctionPrototypes +findFileInPath(char *name,char *subdir) +#else +findFileInPath(name,subdir) + char * name; + char * subdir; +#endif +{ +register int i; +char buf[PATH_MAX]; +FILE * fp; + + if (name[0]=='/') { + fp= fopen(name,"r"); + if ((verbose>7)||((!fp)&&(verbose>0))) + MSG2("%s file %s\n",(fp?"Found":"Didn't find"),name); + return fp; + } + for (i=0;(i<numInclPath);i++) { + if ((strlen(inclPath[i])+strlen(subdir)+strlen(name)+2)>PATH_MAX) { + VMSG3(0,"Path too long (%s/%s%s). Ignored.\n",inclPath[i],subdir, + name); + continue; + } + sprintf(buf,"%s/%s%s",inclPath[i],subdir,name); + fp= fopen(name,"r"); + if ((verbose>7)||((!fp)&&(verbose>5))) + MSG2("%s file %s\n",(fp?"Found":"Didn't find"),buf); + if (fp!=NULL) + return fp; + } + return NULL; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +addStringToOptions(char *opt_str,int *sz_opts,int *num_opts,char ***opts) +#else +addStringToOptions(opt_str,sz_opts,num_opts,opts) + char * opt_str; + int * sz_opts; + int * num_opts; + char *** opts; +#endif +{ +char *tmp,*str,*next; +Bool ok= True; + + if ((str= malloc(strlen(opt_str)+1))!=NULL) + strcpy(str,opt_str); + else return False; + for (tmp= str,next=NULL;(tmp && *tmp!='\0')&&ok;tmp=next) { + next= strchr(str,','); + if (next) { + *next= '\0'; + next++; + } + ok= addToList(sz_opts,num_opts,opts,tmp)&&ok; + } + free(str); + return ok; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +stringFromOptions(char *orig,int numNew,char **newOpts) +#else +stringFromOptions(orig,numNew,newOpts) + char * orig; + int numNew; + char ** newOpts; +#endif +{ +int len,i,nOut; + + if (orig) len= strlen(orig)+1; + else len= 0; + for (i=0;i<numNew;i++) { + if (newOpts[i]) + len+= strlen(newOpts[i])+1; + } + if (len<1) + return NULL; + if (orig) { + orig= (char *)realloc(orig,len); + nOut= 1; + } + else { + orig= (char *)calloc(len,1); + nOut= 0; + } + for (i=0;i<numNew;i++) { + if (!newOpts[i]) + continue; + if (nOut>0) { + strcat(orig,","); + strcat(orig,newOpts[i]); + } + else strcpy(orig,newOpts[i]); + nOut++; + } + return orig; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +applyConfig(char *name) +#else +applyConfig(name) + char * name; +#endif +{ +FILE * fp; +Bool ok; + + if ((fp=findFileInPath(name,""))==NULL) + return False; + ok= XkbCFParse(fp,XkbCFDflts,NULL,&cfgResult); + fclose(fp); + if (!ok) { + ERR1("Couldn't find configuration file \"%s\"\n", name); + return False; + } + if (cfgResult.rules_file) { + trySetString(RULES_NDX,cfgResult.rules_file,FROM_CONFIG); + cfgResult.rules_file= NULL; + } + if (cfgResult.model) { + trySetString(MODEL_NDX,cfgResult.model,FROM_CONFIG); + cfgResult.model= NULL; + } + if (cfgResult.layout) { + trySetString(LAYOUT_NDX,cfgResult.layout,FROM_CONFIG); + cfgResult.layout= NULL; + } + if (cfgResult.variant) { + trySetString(VARIANT_NDX,cfgResult.variant,FROM_CONFIG); + cfgResult.variant= NULL; + } + if (cfgResult.options) { + addStringToOptions(cfgResult.options,&szOptions,&numOptions,&options); + cfgResult.options= NULL; + } + if (cfgResult.keymap) { + trySetString(KEYMAP_NDX,cfgResult.keymap,FROM_CONFIG); + cfgResult.keymap= NULL; + } + if (cfgResult.keycodes) { + trySetString(KEYCODES_NDX,cfgResult.keycodes,FROM_CONFIG); + cfgResult.keycodes= NULL; + } + if (cfgResult.geometry) { + trySetString(GEOMETRY_NDX,cfgResult.geometry,FROM_CONFIG); + cfgResult.geometry= NULL; + } + if (cfgResult.symbols) { + trySetString(SYMBOLS_NDX,cfgResult.symbols,FROM_CONFIG); + cfgResult.symbols= NULL; + } + if (cfgResult.types) { + trySetString(TYPES_NDX,cfgResult.types,FROM_CONFIG); + cfgResult.types= NULL; + } + if (cfgResult.compat) { + trySetString(COMPAT_NDX,cfgResult.compat,FROM_CONFIG); + cfgResult.compat= NULL; + } + if (verbose>5) { + MSG("After config file:\n"); + dumpNames(True,True); + } + return True; +} + +Bool +#if NeedFunctionPrototypes +applyRules(void) +#else +applyRules() +#endif +{ +int i; +char * rfName; + + if (svSrc[MODEL_NDX]||svSrc[LAYOUT_NDX]||svSrc[VARIANT_NDX]||options) { + char buf[PATH_MAX]; + XkbComponentNamesRec rnames; + + if(svSrc[VARIANT_NDX] < svSrc[LAYOUT_NDX]) + svValue[VARIANT_NDX] = NULL; + + rdefs.model= svValue[MODEL_NDX]; + rdefs.layout= svValue[LAYOUT_NDX]; + rdefs.variant= svValue[VARIANT_NDX]; + if (options) + rdefs.options=stringFromOptions(rdefs.options,numOptions,options); + + if (svSrc[RULES_NDX]) + rfName= svValue[RULES_NDX]; + else rfName= DFLT_XKB_RULES_FILE; + + if (rfName[0]=='/') { + rules= XkbRF_Load(rfName,svValue[LOCALE_NDX],True,True); + } + else { + for (i=0;(i<numInclPath)&&(!rules);i++) { + if ((strlen(inclPath[i])+strlen(rfName)+8)>PATH_MAX) { + VMSG2(0,"Path too long (%s/rules/%s). Ignored.\n", + inclPath[i],rfName); + continue; + } + sprintf(buf,"%s/rules/%s",inclPath[i],svValue[RULES_NDX]); + rules= XkbRF_Load(buf,svValue[LOCALE_NDX],True,True); + } + } + if (!rules) { + ERR1("Couldn't find rules file (%s) \n",svValue[RULES_NDX]); + return False; + } + XkbRF_GetComponents(rules,&rdefs,&rnames); + if (rnames.keycodes) { + trySetString(KEYCODES_NDX,rnames.keycodes,FROM_RULES); + rnames.keycodes= NULL; + } + if (rnames.symbols) { + trySetString(SYMBOLS_NDX,rnames.symbols,FROM_RULES); + rnames.symbols= NULL; + } + if (rnames.types) { + trySetString(TYPES_NDX,rnames.types,FROM_RULES); + rnames.types= NULL; + } + if (rnames.compat) { + trySetString(COMPAT_NDX,rnames.compat,FROM_RULES); + rnames.compat= NULL; + } + if (rnames.geometry) { + trySetString(GEOMETRY_NDX,rnames.geometry,FROM_RULES); + rnames.geometry= NULL; + } + if (rnames.keymap) { + trySetString(KEYMAP_NDX,rnames.keymap,FROM_RULES); + rnames.keymap= NULL; + } + if (verbose>6) { + MSG1("Applied rules from %s:\n",svValue[RULES_NDX]); + dumpNames(True,False); + } + } + else if (verbose>6) { + MSG("No rules variables specified. Rules file ignored\n"); + } + return True; +} + +/* Primitive sanity check - filter out 'map names' (inside parenthesis) */ +/* that can confuse xkbcomp parser */ +Bool +#if NeedFunctionPrototypes +checkName(char *name, char* string) +#else +checkName() + char *name; + char *string; +#endif +{ + char *i = name, *opar = NULL; + Bool ret = True; + + if(!name) + return True; + + while (*i){ + if (opar == NULL) { + if (*i == '(') + opar = i; + } else { + if ((*i == '(') || (*i == '|') || (*i == '+')) { + ret = False; + break; + } + if (*i == ')') + opar = NULL; + } + i++; + } + if (opar) + ret = False; + if (!ret) { + char c; + int n = 1; + for(i = opar+1; *i && n; i++) { + if (*i == '(') n++; + if (*i == ')') n--; + } + if (*i) i++; + c = *i; + *i = '\0'; + ERR1("Illegal map name '%s' ", opar); + *i = c; + ERR2("in %s name '%s'\n", string, name); + } + return ret; +} + +void +#if NeedFunctionPrototypes +printKeymap(void) +#else +printKeymap() +#endif +{ + MSG("xkb_keymap {\n"); + if (svValue[KEYCODES_NDX]) + MSG1("\txkb_keycodes { include \"%s\"\t};\n",svValue[KEYCODES_NDX]); + if (svValue[TYPES_NDX]) + MSG1("\txkb_types { include \"%s\"\t};\n",svValue[TYPES_NDX]); + if (svValue[COMPAT_NDX]) + MSG1("\txkb_compat { include \"%s\"\t};\n",svValue[COMPAT_NDX]); + if (svValue[SYMBOLS_NDX]) + MSG1("\txkb_symbols { include \"%s\"\t};\n",svValue[SYMBOLS_NDX]); + if (svValue[GEOMETRY_NDX]) + MSG1("\txkb_geometry { include \"%s\"\t};\n",svValue[GEOMETRY_NDX]); + MSG("};\n"); +} + +Bool +#if NeedFunctionPrototypes +applyComponentNames(void) +#else +applyComponentNames() +#endif +{ + if(!checkName(svValue[TYPES_NDX], "types")) + return False; + if(!checkName(svValue[COMPAT_NDX], "compat")) + return False; + if(!checkName(svValue[SYMBOLS_NDX], "symbols")) + return False; + if(!checkName(svValue[KEYCODES_NDX], "keycodes")) + return False; + if(!checkName(svValue[GEOMETRY_NDX], "geometry")) + return False; + if(!checkName(svValue[KEYMAP_NDX], "keymap")) + return False; + + if (verbose>5) { + MSG("Trying to build keymap using the following components:\n"); + dumpNames(False,True); + } + if (dpy && !print) { + XkbComponentNamesRec cmdNames; + cmdNames.types= svValue[TYPES_NDX]; + cmdNames.compat= svValue[COMPAT_NDX]; + cmdNames.symbols= svValue[SYMBOLS_NDX]; + cmdNames.keycodes= svValue[KEYCODES_NDX]; + cmdNames.geometry= svValue[GEOMETRY_NDX]; + cmdNames.keymap= svValue[KEYMAP_NDX]; + xkb= XkbGetKeyboardByName(dpy,XkbUseCoreKbd,&cmdNames, + XkbGBN_AllComponentsMask, + XkbGBN_AllComponentsMask&(~XkbGBN_GeometryMask), + True); + if (!xkb) { + ERR("Error loading new keyboard description\n"); + return False; + } + if (svValue[RULES_NDX] && (rdefs.model || rdefs.layout)) { + if (!XkbRF_SetNamesProp(dpy,svValue[RULES_NDX],&rdefs)) { + VMSG(0,"Error updating the XKB names property\n"); + } + } + } + if (print) { + printKeymap(); + } + return True; +} + + +int +#if NeedFunctionPrototypes +main(int argc,char **argv) +#else +main(argc,argv) + int argc; + char ** argv; +#endif +{ + if ((!parseArgs(argc,argv))||(!getDisplay(argc,argv))) + exit(-1); + svValue[LOCALE_NDX]= setlocale(LC_ALL,svValue[LOCALE_NDX]); + svSrc[LOCALE_NDX]= FROM_SERVER; + VMSG1(7,"locale is %s\n",svValue[LOCALE_NDX]); + if (dpy) + getServerValues(); + if (svValue[CONFIG_NDX] && (!applyConfig(svValue[CONFIG_NDX]))) + exit(-3); + if (!applyRules()) + exit(-4); + if (!applyComponentNames()) + exit(-5); + if (dpy) + XCloseDisplay(dpy); + exit(0); +} diff --git a/setxkbmap.man b/setxkbmap.man new file mode 100644 index 0000000..398c732 --- /dev/null +++ b/setxkbmap.man @@ -0,0 +1,120 @@ +.\" +.\" $XFree86: xc/programs/setxkbmap/setxkbmap.man,v 3.6 2003/01/20 04:15:08 dawes Exp $ +.\" +.TH SETXKBMAP 1 __xorgversion__ +.SH NAME +setxkbmap +\- set the keyboard using the X Keyboard Extension +.SH SYNOPSIS +.B setxkbmap [ +.I args +.B ] [ +.I layout +.B [ +.I variant +.B [ +.I option ... +.B ] ] ] +.SH DESCRIPTION +The +.B setxkbmap +command maps the keyboard to use the layout determined by the options +specified on the command line. +.P +An XKB keymap is constructed from a number of components which are compiled +only as needed. The source for all of the components can be found in +.IR __projectroot__/lib/X11/xkb . +.SH OPTIONS +.TP 8 +.B \-help +Prints a message describing the valid input to \fIsetxkbmap\fP. +.TP 8 +.B \-compat \fIname\fP +Specifies the name of the compatibility map component used to construct +a keyboard layout. +.TP 8 +.B \-config \fIfile\fP +Specifies the name of an XKB configuration file which describes the +keyboard to be used. +.TP 8 +.B \-display \fIdisplay\fP +Specifies the display to be updated with the new keyboard layout. +.TP 8 +.B \-geometry \fIname\fP +Specifies the name of the geometry component used to construct +a keyboard layout. +.TP 8 +.B \-keymap \fIname\fP +Specifies the name of the keymap description used to construct +a keyboard layout. +.TP 8 +.B \-layout \fIname\fP +Specifies the name of the layout used to determine the components which +make up the keyboard description. Only one layout may be specified on +the command line. +.TP 8 +.B \-model \fIname\fP +Specifies the name of the keyboard model used to determine the components +which make up the keyboard description. Only one model may be specified +on the command line. +.TP 8 +.B \-option \fIname\fP +Specifies the name of an option to determine the components which make up +the keyboard description; multiple options may be specified, one per +\fI-option\fP flag. Note that +.B setxkbmap +summarize options specified in the command +line with options was set before (saved in root window properties). If you +want only specified options will be set use the \fI-option\fP flag with +an empty argument first. +.TP 8 +.B \-print +With this option the \fBsetxkbmap\fP just prints component names in a format +acceptable by an \fBxkbcomp\fP (an XKB keymap compiler) and exits. The option +can be used for tests instead of a verbose option and in case when one need +to run both the \fBsetxkbmap\fP and the \fBxkbcomp\fP in chain (see below). +.TP 8 +.B \-rules \fIfile\fP +Specifies the name of the rules file used to resolve the request layout +and model to a set of component names. +.TP 8 +.B \-symbols \fIname\fP +Specifies the name of the symbols component used to construct +a keyboard layout. +.TP 8 +.B \-synch +Force synchronization for X requests. +.TP 8 +.B \-types \fIname\fP +Specifies the name of the types component used to construct +a keyboard layout. +.TP 8 +.B \-variant \fIname\fP +Specifies which variant of the keyboard layout should be used to determine +the components which make up the keyboard description. Only one variant +may be specified on the command line. +.SH USING WITH xkbcomp +If you have an Xserver and a client shell running on differnt computers and +XKB configuration files sets on those machines are different you can get +problems specifying a keyboard map by model, layout, options names. +The thing is the \fBsetxkbcomp\fP converts these names to names of XKB +configuration files according to files that are on the client side computer. +Then it sends the file names to the server where the \fBxkbcomp\fP has to +compose a complete keyboard map using files which the server has. +Thus if the sets of files differ significantly the names that the +\fBsetxkbmap\fP generates can be unacceptable on the server side. You can +solve this problem running the \fBxkbcomp\fP on the client side too. +With the \fI-print\fP option \fBsetxkbmap\fP just prints the files names +in an appropriate format to its stdout and this output can be piped +directly to the \fBxkbcomp\fP input. For example, a command + +\fBsetxkbmap us -print | xkbcomp - $DISPLAY\fP + +makes both step on the same (client) machine and loads a keyboard map into +the server. +.ig +.SH SEE ALSO +keyboards(1) +.. +.SH FILES +.I __projectroot__/lib/X11/xkb |