(file) Return to setxkbmap.c CVS log (file) (dir) Up to [XFree86 CVS] / xc / programs / setxkbmap

  1 dawes 3.0 /************************************************************
  2            Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
  3           
  4            Permission to use, copy, modify, and distribute this
  5            software and its documentation for any purpose and without
  6            fee is hereby granted, provided that the above copyright
  7            notice appear in all copies and that both that copyright
  8            notice and this permission notice appear in supporting
  9            documentation, and that the name of Silicon Graphics not be 
 10            used in advertising or publicity pertaining to distribution 
 11            of the software without specific prior written permission.
 12            Silicon Graphics makes no representation about the suitability 
 13            of this software for any purpose. It is provided "as is"
 14            without any express or implied warranty.
 15            
 16            SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
 17            SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
 18            AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 19            GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
 20            DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
 21            DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
 22 dawes 3.0  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 23            THE USE OR PERFORMANCE OF THIS SOFTWARE.
 24           
 25            ********************************************************/
 26 tsi   3.10 /* $XFree86: xc/programs/setxkbmap/setxkbmap.c,v 3.9tsi Exp $ */
 27 dawes 3.0  
 28            #include <stdio.h>
 29            #include <stdlib.h>
 30            #include <locale.h>
 31            #include <limits.h>
 32 hohndel 3.2  #include <ctype.h>
 33 dawes   3.0  #include <X11/Xlib.h>
 34 dawes   3.1  #include <X11/Xos.h>
 35 dawes   3.0  #include <X11/XKBlib.h>
 36              #include <X11/extensions/XKBfile.h>
 37              #include <X11/extensions/XKBconfig.h>
 38              #include <X11/extensions/XKBrules.h>
 39              
 40              #ifndef PATH_MAX
 41              #ifdef MAXPATHLEN
 42              #define PATH_MAX MAXPATHLEN
 43              #else
 44              #define PATH_MAX 1024
 45              #endif
 46              #endif
 47              
 48              #ifndef DFLT_XKB_CONFIG_ROOT
 49 dawes   3.4  #define	DFLT_XKB_CONFIG_ROOT "/usr/X11R6/lib/X11/xkb"
 50 dawes   3.0  #endif
 51              #ifndef DFLT_XKB_RULES_FILE
 52 dawes   3.4  #define	DFLT_XKB_RULES_FILE "xfree86"
 53              #endif
 54              #ifndef DFLT_XKB_LAYOUT
 55              #define	DFLT_XKB_LAYOUT "us"
 56              #endif
 57              #ifndef DFLT_XKB_MODEL
 58              #define	DFLT_XKB_MODEL "pc101"
 59 dawes   3.0  #endif
 60              
 61              #define	UNDEFINED	0
 62              #define	FROM_SERVER	1
 63              #define	FROM_RULES	2
 64              #define	FROM_CONFIG	3
 65              #define	FROM_CMD_LINE	4
 66              #define	NUM_SOURCES	5
 67              
 68              #define	RULES_NDX	0
 69              #define	CONFIG_NDX	1
 70              #define	DISPLAY_NDX	2
 71              #define	LOCALE_NDX	3
 72              #define	MODEL_NDX	4
 73              #define	LAYOUT_NDX	5
 74              #define	VARIANT_NDX	6
 75              #define KEYCODES_NDX	7
 76              #define	TYPES_NDX	8
 77              #define	COMPAT_NDX	9
 78              #define	SYMBOLS_NDX	10
 79              #define	GEOMETRY_NDX	11
 80 dawes   3.0  #define	KEYMAP_NDX	12
 81              #define	NUM_STRING_VALS	13
 82              
 83              /***====================================================================***/
 84 dawes   3.7  Bool			print= False;
 85 dawes   3.0  Bool			synch= False;
 86              int			verbose= 5;
 87              
 88              Display *		dpy;
 89              
 90              char *	srcName[NUM_SOURCES] = {
 91              	"undefined", "X server", "rules file", "config file", "command line"
 92              };
 93              
 94              char *	svName[NUM_STRING_VALS]= {
 95              	"rules file", "config file", "X display", "locale",
 96              	"keyboard model", "keyboard layout", "layout variant",
 97              	"keycodes", "types", "compatibility map", "symbols", "geometry",
 98              	"keymap"
 99              };
100              int	svSrc[NUM_STRING_VALS];
101              char *	svValue[NUM_STRING_VALS];
102              
103              XkbConfigFieldsRec	cfgDflts;
104              XkbConfigRtrnRec	cfgResult;
105              
106 dawes   3.0  XkbRF_RulesPtr		rules= NULL;
107              XkbRF_VarDefsRec	rdefs;
108              
109              Bool			clearOptions= False;
110              int			szOptions= 0;
111              int			numOptions= 0;
112              char **			options= NULL;
113              
114              int			szInclPath= 0;
115              int			numInclPath= 0;
116              char **			inclPath= NULL;
117              
118              XkbDescPtr		xkb= NULL;
119              
120              /***====================================================================***/
121              
122              #define	streq(s1,s2)	(strcmp(s1,s2)==0)
123              #define	strpfx(s1,s2)	(strncmp(s1,s2,strlen(s2))==0)
124              
125              #define	MSG(s)		printf(s)
126              #define	MSG1(s,a)	printf(s,a)
127 dawes   3.0  #define	MSG2(s,a,b)	printf(s,a,b)
128              #define	MSG3(s,a,b,c)	printf(s,a,b,c)
129              
130              #define	VMSG(l,s)	if (verbose>(l)) printf(s)
131              #define	VMSG1(l,s,a)	if (verbose>(l)) printf(s,a)
132              #define	VMSG2(l,s,a,b)	if (verbose>(l)) printf(s,a,b)
133              #define	VMSG3(l,s,a,b,c) if (verbose>(l)) printf(s,a,b,c)
134              
135              #define	ERR(s)		fprintf(stderr,s)
136              #define	ERR1(s,a)	fprintf(stderr,s,a)
137              #define	ERR2(s,a,b)	fprintf(stderr,s,a,b)
138              #define	ERR3(s,a,b,c)	fprintf(stderr,s,a,b,c)
139              
140              /***====================================================================***/
141              
142 hohndel 3.2  Bool addToList ( int *sz, int *num, char ***listIn, char *newVal );
143              void usage ( int argc, char ** argv );
144              void dumpNames ( Bool wantRules, Bool wantCNames );
145              void trySetString ( int which, char * newVal, int src );
146              Bool setOptString ( int *arg, int argc, char **argv, int which, int src );
147              int parseArgs ( int argc, char ** argv );
148              Bool getDisplay ( int argc, char ** argv );
149              Bool getServerValues ( void );
150              FILE * findFileInPath ( char * name, char * subdir );
151              Bool addStringToOptions ( char * opt_str, int * sz_opts, int * num_opts, char *** opts );
152              char * stringFromOptions ( char * orig, int numNew, char ** newOpts );
153              Bool applyConfig ( char * name );
154              Bool applyRules ( void );
155              Bool applyComponentNames ( void );
156 dawes   3.7  void printKeymap( void );
157 hohndel 3.2  
158              /***====================================================================***/
159              
160 dawes   3.0  Bool
161              addToList(int *sz,int *num,char ***listIn,char *newVal)
162              {
163              register int i;
164              char **list;
165              
166                  if ((!newVal)||(!newVal[0])) {
167              	*num= 0;
168              	return True;
169                  }
170                  list= *listIn;
171                  for (i=0;i<*num;i++) {
172              	if (streq(list[i],newVal))
173              	    return True;
174                  }
175                  if ((list==NULL)||(*sz<1)) {
176              	*num= 0;
177              	*sz= 4;
178              	list= (char **)calloc(*sz,sizeof(char *));
179              	*listIn= list;
180                  }
181 dawes   3.0      else if (*num>=*sz) {
182              	*sz*= 2;
183              	list= (char **)realloc(list,(*sz)*sizeof(char *));
184              	*listIn= list;
185                  }
186                  if (!list) {
187              	ERR("Internal Error! Allocation failure in add to list!\n");
188              	ERR("                Exiting.\n");
189              	exit(-1);
190                  }
191                  list[*num]= strdup(newVal);
192                  (*num)= (*num)+1;
193                  return True;
194              }
195              
196              /***====================================================================***/
197              
198              void
199              usage(int argc,char **argv)
200              {
201                  MSG1("Usage: %s [args] [<layout> [<variant> [<option> ... ]]]\n",argv[0]);
202 dawes   3.0      MSG("Where legal args are:\n");
203                  MSG("-?,-help            Print this message\n");
204                  MSG("-compat <name>      Specifies compatibility map component name\n");
205                  MSG("-config <file>      Specifies configuration file to use\n");
206                  MSG("-display <dpy>      Specifies display to use\n");
207                  MSG("-geometry <name>    Specifies geometry component name\n");
208                  MSG("-I[<dir>]           Add <dir> to list of directories to be used\n");
209                  MSG("-keycodes <name>    Specifies keycodes component name\n");
210                  MSG("-keymap <name>      Specifies name of keymap to load\n");
211                  MSG("-layout <name>      Specifies layout used to choose component names\n");
212                  MSG("-model <name>       Specifies model used to choose component names\n");
213                  MSG("-option <name>      Adds an option used to choose component names\n");
214 dawes   3.7      MSG("-print              Print a complete xkb_keymap description and exit\n");
215 dawes   3.0      MSG("-rules <name>       Name of rules file to use\n");
216                  MSG("-symbols <name>     Specifies symbols component name\n");
217                  MSG("-synch              Synchronize request w/X server\n");
218                  MSG("-types <name>       Specifies types component name\n");
219                  MSG("-v[erbose] [<lvl>]  Sets verbosity (1..10).  Higher values yield\n");
220                  MSG("                    more messages\n");
221                  MSG("-variant <name>     Specifies layout variant used to choose component names\n");
222              }
223              
224              void
225              dumpNames(Bool wantRules,Bool wantCNames)
226              {
227                  if (wantRules) {
228 paulo   3.5  	if (svValue[MODEL_NDX])	 MSG1("model:      %s\n",svValue[MODEL_NDX]);
229              	if (svValue[LAYOUT_NDX])  MSG1("layout:     %s\n",svValue[LAYOUT_NDX]);
230              	if (svValue[VARIANT_NDX]) MSG1("variant:    %s\n",svValue[VARIANT_NDX]);
231              	if (options) {
232              	   char *opt_str=stringFromOptions(NULL, numOptions, options);
233              	   MSG1("options:    %s\n", opt_str);
234              	   free(opt_str);
235              	}
236 dawes   3.0      }
237                  if (wantCNames) {
238              	if (svValue[KEYMAP_NDX])
239              	    MSG1("keymap:     %s\n",svValue[KEYMAP_NDX]);
240              	if (svValue[KEYCODES_NDX])
241              	    MSG1("keycodes:   %s\n",svValue[KEYCODES_NDX]);
242              	if (svValue[TYPES_NDX])
243              	    MSG1("types:      %s\n",svValue[TYPES_NDX]);
244              	if (svValue[COMPAT_NDX])
245              	    MSG1("compat:     %s\n",svValue[COMPAT_NDX]);
246              	if (svValue[SYMBOLS_NDX])
247              	    MSG1("symbols:    %s\n",svValue[SYMBOLS_NDX]);
248              	if (svValue[GEOMETRY_NDX])
249              	    MSG1("geometry:   %s\n",svValue[GEOMETRY_NDX]);
250                  }
251                  return;
252              }
253              
254              /***====================================================================***/
255              
256              void
257 dawes   3.0  trySetString(int which,char *newVal,int src)
258              {
259                  if (svValue[which]!=NULL) {
260              	if (svSrc[which]==src) {
261              	    VMSG2(0,"Warning! More than one %s from %s\n",
262              						svName[which],srcName[src]);
263              	    VMSG2(0,"         Using \"%s\", ignoring \"%s\"\n",
264              						svValue[which],newVal);
265              	    return;
266              	}
267              	else if (svSrc[which]>src) {
268              	    VMSG1(5,"Warning! Multiple definitions of %s\n",svName[which]);
269              	    VMSG2(5,"         Using %s, ignoring %s\n",srcName[svSrc[which]],
270              						srcName[src]);
271              	    return;
272              	}
273                  }
274                  svSrc[which]= src;
275                  svValue[which]= newVal;
276                  return;
277              }
278 dawes   3.0  
279              Bool
280              setOptString(int *arg,int argc,char **argv,int which,int src)
281              {
282              int	ndx;
283              char *	opt;
284              
285                  ndx= *arg;
286                  opt= argv[ndx];
287                  if (ndx>=argc-1) {
288              	VMSG1(0,"No %s specified on the command line\n",svName[which]);
289              	VMSG1(0,"Trailing %s option ignored\n",opt);
290              	return True;
291                  }
292                  ndx++;
293 paulo   3.5      *arg= ndx;
294 dawes   3.0      if (svValue[which]!=NULL) {
295              	if (svSrc[which]==src) {
296              	    VMSG2(0,"More than one %s on %s\n",svName[which],srcName[src]);
297              	    VMSG2(0,"Using \"%s\", ignoring \"%s\"\n",svValue[which],argv[ndx]);
298              	    return True;
299              	}
300              	else if (svSrc[which]>src) {
301              	    VMSG1(5,"Multiple definitions of %s\n",svName[which]);
302              	    VMSG2(5,"Using %s, ignoring %s\n",srcName[svSrc[which]],
303              						srcName[src]);
304              	    return True;
305              	}
306                  }
307                  svSrc[which]= src;
308                  svValue[which]= argv[ndx];
309                  return True;
310              }
311              
312              /***====================================================================***/
313              
314              int
315 dawes   3.0  parseArgs(int argc,char **argv)
316              {
317              int 	i;
318              Bool	ok;
319 dawes   3.4  unsigned	present;
320 dawes   3.0  
321                  ok= True;
322                  addToList(&szInclPath,&numInclPath,&inclPath,".");
323                  addToList(&szInclPath,&numInclPath,&inclPath,DFLT_XKB_CONFIG_ROOT);
324                  for (i=1;(i<argc)&&ok;i++) {
325              	if (argv[i][0]!='-') {
326              	    if (!svSrc[LAYOUT_NDX])
327              		 trySetString(LAYOUT_NDX,argv[i],FROM_CMD_LINE);
328              	    else if (!svSrc[VARIANT_NDX])
329              		 trySetString(VARIANT_NDX,argv[i],FROM_CMD_LINE);
330              	    else ok= addToList(&szOptions,&numOptions,&options,argv[i]);
331              	}
332              	else if (streq(argv[i],"-compat"))
333              	    ok= setOptString(&i,argc,argv,COMPAT_NDX,FROM_CMD_LINE);
334              	else if (streq(argv[i],"-config"))
335              	    ok= setOptString(&i,argc,argv,CONFIG_NDX,FROM_CMD_LINE);
336              	else if (streq(argv[i],"-display"))
337              	    ok= setOptString(&i,argc,argv,DISPLAY_NDX,FROM_CMD_LINE);
338              	else if (streq(argv[i],"-geometry"))
339              	    ok= setOptString(&i,argc,argv,GEOMETRY_NDX,FROM_CMD_LINE);
340              	else if (streq(argv[i],"-help")||streq(argv[i],"-?")) {
341 dawes   3.0  	    usage(argc,argv);
342              	    exit(0);
343              	}
344              	else if (strpfx(argv[i],"-I")) 
345              	    ok= addToList(&szInclPath,&numInclPath,&inclPath,&argv[i][2]);
346              	else if (streq(argv[i],"-keycodes"))
347              	    ok= setOptString(&i,argc,argv,KEYCODES_NDX,FROM_CMD_LINE);
348              	else if (streq(argv[i],"-keymap"))
349              	    ok= setOptString(&i,argc,argv,KEYMAP_NDX,FROM_CMD_LINE);
350              	else if (streq(argv[i],"-layout"))
351              	    ok= setOptString(&i,argc,argv,LAYOUT_NDX,FROM_CMD_LINE);
352              	else if (streq(argv[i],"-model"))
353              	    ok= setOptString(&i,argc,argv,MODEL_NDX,FROM_CMD_LINE);
354              	else if (streq(argv[i],"-option")) {
355 dawes   3.6  	    if ((i==argc-1)||(argv[i+1][0]=='\0')||(argv[i+1][0]=='-')) {
356 dawes   3.0  		clearOptions= True;
357              		ok= addToList(&szOptions,&numOptions,&options,"");
358 dawes   3.6                  if (i<argc-1 && argv[i+1][0]=='\0')
359 paulo   3.5                     i++;
360 dawes   3.0  	    }
361              	    else {
362              		ok= addToList(&szOptions,&numOptions,&options,argv[++i]);
363              	    }
364              	}
365 dawes   3.7  	else if (streq(argv[i],"-print"))
366              	    print= True;
367 dawes   3.0  	else if (streq(argv[i],"-rules"))
368              	    ok= setOptString(&i,argc,argv,RULES_NDX,FROM_CMD_LINE);
369              	else if (streq(argv[i],"-symbols"))
370              	    ok= setOptString(&i,argc,argv,SYMBOLS_NDX,FROM_CMD_LINE);
371              	else if (streq(argv[i],"-synch"))
372              	    synch= True;
373              	else if (streq(argv[i],"-types"))
374              	    ok= setOptString(&i,argc,argv,TYPES_NDX,FROM_CMD_LINE);
375              	else if (streq(argv[i],"-verbose")||(streq(argv[i],"-v"))) {
376              	    if ((i<argc-1)&&(isdigit(argv[i+1][0])))
377              	 	 verbose= atoi(argv[++i]);
378              	    else verbose++;
379              	    if (verbose<0) {
380              		ERR1("Illegal verbose level %d.  Reset to 0\n",verbose);
381              		verbose=0;
382              	    }
383              	    else if (verbose>10) {
384              		ERR1("Illegal verbose level %d.  Reset to 10\n",verbose);
385              		verbose= 10;
386              	    }
387              	    VMSG1(7,"Setting verbose level to %d\n",verbose);
388 dawes   3.0  	}
389              	else if (streq(argv[i],"-variant"))
390              	    ok= setOptString(&i,argc,argv,VARIANT_NDX,FROM_CMD_LINE);
391              	else {
392              	    ERR1("Error!   Option \"%s\" not recognized\n",argv[i]);
393              	    ok= False;
394              	}
395                  }
396 dawes   3.4  
397                  present= 0;
398                  if (svValue[TYPES_NDX])	present++;
399                  if (svValue[COMPAT_NDX])	present++;
400                  if (svValue[SYMBOLS_NDX])	present++;
401                  if (svValue[KEYCODES_NDX])	present++;
402                  if (svValue[GEOMETRY_NDX])	present++;
403                  if (svValue[CONFIG_NDX])	present++;
404                  if (svValue[MODEL_NDX])	present++;
405                  if (svValue[LAYOUT_NDX])	present++;
406                  if (svValue[VARIANT_NDX])	present++;
407                  if (svValue[KEYMAP_NDX] && present) {
408              	ERR("No other components can be specified when a keymap is present\n");
409              	return False;
410                  }
411 dawes   3.0      return ok;
412              }
413              
414              Bool
415              getDisplay(int argc,char **argv)
416              {
417              int	major,minor,why;
418              
419                  major= XkbMajorVersion;
420                  minor= XkbMinorVersion;
421                  dpy= XkbOpenDisplay(svValue[DISPLAY_NDX],NULL,NULL,&major,&minor,&why);
422                  if (!dpy) {
423              	if (svValue[DISPLAY_NDX]==NULL)	
424              	    svValue[DISPLAY_NDX]= getenv("DISPLAY");
425              	if (svValue[DISPLAY_NDX]==NULL)
426              	    svValue[DISPLAY_NDX]= "default display";
427              	switch (why) {
428              	    case XkbOD_BadLibraryVersion:
429              		ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
430              					XkbMajorVersion,XkbMinorVersion);
431              		ERR2("Xlib supports incompatible version %d.%02d\n",
432 dawes   3.0  					major,minor);
433              		break;
434              	    case XkbOD_ConnectionRefused:
435                              ERR1("Cannot open display \"%s\"\n",svValue[DISPLAY_NDX]);
436              		break;
437              	    case XkbOD_NonXkbServer:
438              		ERR1("XKB extension not present on %s\n",svValue[DISPLAY_NDX]);
439              		break;
440              	    case XkbOD_BadServerVersion:
441                              ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
442              				XkbMajorVersion,XkbMinorVersion);
443              		ERR3("Server %s uses incompatible version %d.%02d\n",
444              				svValue[DISPLAY_NDX],major,minor);
445              		break;
446              	    default:
447              		ERR1("Unknown error %d from XkbOpenDisplay\n",why);
448              		break;
449              	}
450              	return False;
451                  }
452                  if (synch)
453 dawes   3.0  	XSynchronize(dpy,True);
454                  return True;
455              }
456              
457              /***====================================================================***/
458              
459              Bool
460              getServerValues(void)
461              {
462              XkbRF_VarDefsRec 	vd;
463              char *			tmp= NULL;
464              
465 dawes   3.4      if (!XkbRF_GetNamesProp(dpy,&tmp,&vd) || !tmp) {
466 dawes   3.0  	VMSG1(3,"Couldn't interpret %s property\n",_XKB_RF_NAMES_PROP_ATOM);
467 dawes   3.4          tmp = DFLT_XKB_RULES_FILE;
468                      vd.model = DFLT_XKB_MODEL;
469                      vd.layout = DFLT_XKB_LAYOUT;
470 tsi     3.10 	vd.variant = NULL;
471              	vd.options = NULL;
472 dawes   3.4          VMSG3(3,"Use defaults: rules - '%s' model - '%s' layout - '%s'\n",
473                              tmp, vd.model, vd.layout);
474 dawes   3.0      }
475                  if (tmp)
476              	trySetString(RULES_NDX,tmp,FROM_SERVER);
477                  if (vd.model)
478              	trySetString(MODEL_NDX,vd.model,FROM_SERVER);
479                  if (vd.layout)
480              	trySetString(LAYOUT_NDX,vd.layout,FROM_SERVER);
481                  if (vd.variant)
482              	trySetString(VARIANT_NDX,vd.variant,FROM_SERVER);
483                  if ((vd.options)&&(!clearOptions)) {
484              	addStringToOptions(vd.options,&szOptions,&numOptions,&options);
485              	XFree(vd.options);
486                  }
487                  return True;
488              }
489              
490              /***====================================================================***/
491              
492              FILE *
493              findFileInPath(char *name,char *subdir)
494              {
495 dawes   3.0  register int	i;
496              char		buf[PATH_MAX];
497              FILE *		fp;
498              
499                  if (name[0]=='/') {
500              	fp= fopen(name,"r");
501              	if ((verbose>7)||((!fp)&&(verbose>0)))
502              	    MSG2("%s file %s\n",(fp?"Found":"Didn't find"),name);
503              	return fp;
504                  }
505                  for (i=0;(i<numInclPath);i++) {
506              	if ((strlen(inclPath[i])+strlen(subdir)+strlen(name)+2)>PATH_MAX) {
507              	    VMSG3(0,"Path too long (%s/%s%s). Ignored.\n",inclPath[i],subdir,
508              									name);
509              	    continue;
510              	}
511              	sprintf(buf,"%s/%s%s",inclPath[i],subdir,name);
512              	fp= fopen(name,"r");
513              	if ((verbose>7)||((!fp)&&(verbose>5)))
514              	    MSG2("%s file %s\n",(fp?"Found":"Didn't find"),buf);
515              	if (fp!=NULL)
516 dawes   3.0  	    return fp;
517                  }
518                  return NULL;
519              }
520              
521              /***====================================================================***/
522              
523              Bool
524              addStringToOptions(char *opt_str,int *sz_opts,int *num_opts,char ***opts)
525              {
526              char 	*tmp,*str,*next;
527              Bool	ok= True;
528              
529                  if ((str= malloc(strlen(opt_str)+1))!=NULL)
530              	 strcpy(str,opt_str);
531                  else return False;
532                  for (tmp= str,next=NULL;(tmp && *tmp!='\0')&&ok;tmp=next) {
533              	next= strchr(str,',');
534              	if (next) {
535              	    *next= '\0';
536              	    next++;
537 dawes   3.0  	}
538              	ok= addToList(sz_opts,num_opts,opts,tmp)&&ok;
539                  }
540                  free(str);
541                  return ok;
542              }
543              
544              /***====================================================================***/
545              
546              char *
547              stringFromOptions(char *orig,int numNew,char **newOpts)
548              {
549              int	len,i,nOut;
550              
551                  if (orig)	len= strlen(orig)+1;
552                  else	len= 0;
553                  for (i=0;i<numNew;i++) {
554              	if (newOpts[i])
555              	    len+= strlen(newOpts[i])+1;
556                  }
557                  if (len<1)
558 dawes   3.0  	return NULL;
559                  if (orig) {
560              	orig= (char *)realloc(orig,len);
561              	nOut= 1;
562                  }
563                  else {
564              	orig= (char *)calloc(len,1);
565              	nOut= 0;
566                  }
567                  for (i=0;i<numNew;i++) {
568              	if (!newOpts[i])
569              	    continue;
570              	if (nOut>0) {
571              	     strcat(orig,",");
572              	     strcat(orig,newOpts[i]);
573              	}
574              	else strcpy(orig,newOpts[i]);
575              	nOut++;
576                  }
577                  return orig;
578              }
579 dawes   3.0  
580              /***====================================================================***/
581              
582              Bool
583              applyConfig(char *name)
584              {
585              FILE *	fp;
586              Bool	ok;
587                  
588                  if ((fp=findFileInPath(name,""))==NULL)
589              	return False;
590                  ok= XkbCFParse(fp,XkbCFDflts,NULL,&cfgResult);
591                  fclose(fp);
592                  if (!ok) {
593 hohndel 3.2  	ERR1("Couldn't find configuration file \"%s\"\n", name);
594 dawes   3.0  	return False;
595                  }
596                  if (cfgResult.rules_file) {
597              	trySetString(RULES_NDX,cfgResult.rules_file,FROM_CONFIG);
598              	cfgResult.rules_file= NULL;
599                  }
600                  if (cfgResult.model) {
601              	trySetString(MODEL_NDX,cfgResult.model,FROM_CONFIG);
602              	cfgResult.model= NULL;
603                  }
604                  if (cfgResult.layout) {
605              	trySetString(LAYOUT_NDX,cfgResult.layout,FROM_CONFIG);
606              	cfgResult.layout= NULL;
607                  }
608                  if (cfgResult.variant) {
609              	trySetString(VARIANT_NDX,cfgResult.variant,FROM_CONFIG);
610              	cfgResult.variant= NULL;
611                  }
612                  if (cfgResult.options) {
613              	addStringToOptions(cfgResult.options,&szOptions,&numOptions,&options);
614              	cfgResult.options= NULL;
615 dawes   3.0      }
616                  if (cfgResult.keymap) {
617              	trySetString(KEYMAP_NDX,cfgResult.keymap,FROM_CONFIG);
618              	cfgResult.keymap= NULL;
619                  }
620                  if (cfgResult.keycodes) {
621              	trySetString(KEYCODES_NDX,cfgResult.keycodes,FROM_CONFIG);
622              	cfgResult.keycodes= NULL;
623                  }
624                  if (cfgResult.geometry) {
625              	trySetString(GEOMETRY_NDX,cfgResult.geometry,FROM_CONFIG);
626              	cfgResult.geometry= NULL;
627                  }
628                  if (cfgResult.symbols) {
629              	trySetString(SYMBOLS_NDX,cfgResult.symbols,FROM_CONFIG);
630              	cfgResult.symbols= NULL;
631                  }
632                  if (cfgResult.types) {
633              	trySetString(TYPES_NDX,cfgResult.types,FROM_CONFIG);
634              	cfgResult.types= NULL;
635                  }
636 dawes   3.0      if (cfgResult.compat) {
637              	trySetString(COMPAT_NDX,cfgResult.compat,FROM_CONFIG);
638              	cfgResult.compat= NULL;
639                  }
640                  if (verbose>5) {
641              	MSG("After config file:\n");
642              	dumpNames(True,True);
643                  }
644                  return True;
645              }
646              
647              Bool
648              applyRules(void)
649              {
650              int	i;
651              char *	rfName;
652              
653                  if (svSrc[MODEL_NDX]||svSrc[LAYOUT_NDX]||svSrc[VARIANT_NDX]||options) {
654              	char 			buf[PATH_MAX];
655              	XkbComponentNamesRec	rnames;
656              
657 paulo   3.5          if(svSrc[VARIANT_NDX] < svSrc[LAYOUT_NDX])
658                          svValue[VARIANT_NDX] = NULL;
659 dawes   3.0  
660              	rdefs.model= svValue[MODEL_NDX];
661              	rdefs.layout= svValue[LAYOUT_NDX];
662              	rdefs.variant= svValue[VARIANT_NDX];
663              	if (options)
664              	    rdefs.options=stringFromOptions(rdefs.options,numOptions,options);
665              
666              	if (svSrc[RULES_NDX])
667              	     rfName= svValue[RULES_NDX];
668              	else rfName= DFLT_XKB_RULES_FILE;
669              
670              	if (rfName[0]=='/') {
671              	    rules= XkbRF_Load(rfName,svValue[LOCALE_NDX],True,True);
672              	}
673              	else {
674              	    for (i=0;(i<numInclPath)&&(!rules);i++) {
675              		if ((strlen(inclPath[i])+strlen(rfName)+8)>PATH_MAX) {
676              		    VMSG2(0,"Path too long (%s/rules/%s). Ignored.\n",
677              						inclPath[i],rfName);
678              		    continue;
679              		}
680 dawes   3.0  		sprintf(buf,"%s/rules/%s",inclPath[i],svValue[RULES_NDX]);
681              		rules= XkbRF_Load(buf,svValue[LOCALE_NDX],True,True);
682              	    }
683              	}
684              	if (!rules) {
685              	    ERR1("Couldn't find rules file (%s) \n",svValue[RULES_NDX]);
686              	    return False;
687              	}
688              	XkbRF_GetComponents(rules,&rdefs,&rnames);
689              	if (rnames.keycodes) {
690              	    trySetString(KEYCODES_NDX,rnames.keycodes,FROM_RULES);
691              	    rnames.keycodes= NULL;
692              	}
693              	if (rnames.symbols) {
694              	    trySetString(SYMBOLS_NDX,rnames.symbols,FROM_RULES);
695              	    rnames.symbols= NULL;
696              	}
697              	if (rnames.types) {
698              	    trySetString(TYPES_NDX,rnames.types,FROM_RULES);
699              	    rnames.types= NULL;
700              	}
701 dawes   3.0  	if (rnames.compat) {
702              	    trySetString(COMPAT_NDX,rnames.compat,FROM_RULES);
703              	    rnames.compat= NULL;
704              	}
705              	if (rnames.geometry) {
706              	    trySetString(GEOMETRY_NDX,rnames.geometry,FROM_RULES);
707              	    rnames.geometry= NULL;
708              	}
709              	if (rnames.keymap) {
710              	    trySetString(KEYMAP_NDX,rnames.keymap,FROM_RULES);
711              	    rnames.keymap= NULL;
712              	}
713              	if (verbose>6) {
714              	    MSG1("Applied rules from %s:\n",svValue[RULES_NDX]);
715 paulo   3.5  	    dumpNames(True,False);
716 dawes   3.0  	}
717                  }
718                  else if (verbose>6) {
719              	MSG("No rules variables specified.  Rules file ignored\n");
720                  }
721                  return True;
722              }
723              
724 dawes   3.4  /* Primitive sanity check - filter out 'map names' (inside parenthesis) */
725              /* that can confuse xkbcomp parser */
726 dawes   3.9  static Bool
727 dawes   3.4  checkName(char *name, char* string)
728              {
729                 char *i = name, *opar = NULL;
730                 Bool ret = True;
731              
732                 if(!name)
733                    return True;
734              
735                 while (*i){
736                    if (opar == NULL) {
737                       if (*i == '(')
738                       opar = i;
739                    } else {
740                       if ((*i == '(') || (*i == '|') || (*i == '+')) {
741                           ret = False;
742                           break;
743                       }
744                       if (*i == ')')
745                           opar = NULL;
746                    }
747                    i++;
748 dawes   3.4     }
749                 if (opar)
750                    ret = False;
751                 if (!ret) {
752                    char c;
753                    int n = 1;
754                    for(i = opar+1; *i && n; i++) {
755                       if (*i == '(') n++;
756                       if (*i == ')') n--;
757                    }
758                    if (*i) i++;
759                    c = *i;
760                    *i = '\0';
761                    ERR1("Illegal map name '%s' ", opar);
762                    *i = c;
763                    ERR2("in %s name '%s'\n", string, name);
764                 }
765                 return ret;
766              }
767 dawes   3.0  
768 dawes   3.7  void
769              printKeymap(void)
770              {
771                  MSG("xkb_keymap {\n");
772                  if (svValue[KEYCODES_NDX])
773              	MSG1("\txkb_keycodes  { include \"%s\"\t};\n",svValue[KEYCODES_NDX]);
774                  if (svValue[TYPES_NDX])
775              	MSG1("\txkb_types     { include \"%s\"\t};\n",svValue[TYPES_NDX]);
776                  if (svValue[COMPAT_NDX])
777              	MSG1("\txkb_compat    { include \"%s\"\t};\n",svValue[COMPAT_NDX]);
778                  if (svValue[SYMBOLS_NDX])
779              	MSG1("\txkb_symbols   { include \"%s\"\t};\n",svValue[SYMBOLS_NDX]);
780                  if (svValue[GEOMETRY_NDX])
781              	MSG1("\txkb_geometry  { include \"%s\"\t};\n",svValue[GEOMETRY_NDX]);
782                  MSG("};\n");
783              }
784              
785 dawes   3.0  Bool
786              applyComponentNames(void)
787              {
788 dawes   3.4      if(!checkName(svValue[TYPES_NDX],    "types"))
789              	return False;
790                  if(!checkName(svValue[COMPAT_NDX],   "compat"))
791              	return False;
792                  if(!checkName(svValue[SYMBOLS_NDX],  "symbols"))
793              	return False;
794                  if(!checkName(svValue[KEYCODES_NDX], "keycodes"))
795              	return False;
796                  if(!checkName(svValue[GEOMETRY_NDX], "geometry"))
797 dawes   3.0  	return False;
798 dawes   3.4      if(!checkName(svValue[KEYMAP_NDX],   "keymap"))
799 dawes   3.0  	return False;
800 dawes   3.4  
801 dawes   3.0      if (verbose>5) {
802              	MSG("Trying to build keymap using the following components:\n");
803 paulo   3.5  	dumpNames(False,True);
804 dawes   3.0      }
805 dawes   3.7      if (dpy && !print) {
806 dawes   3.0  	XkbComponentNamesRec	cmdNames;
807              	cmdNames.types= svValue[TYPES_NDX];
808              	cmdNames.compat= svValue[COMPAT_NDX];
809              	cmdNames.symbols= svValue[SYMBOLS_NDX];
810              	cmdNames.keycodes= svValue[KEYCODES_NDX];
811              	cmdNames.geometry= svValue[GEOMETRY_NDX];
812              	cmdNames.keymap= svValue[KEYMAP_NDX];
813              	xkb= XkbGetKeyboardByName(dpy,XkbUseCoreKbd,&cmdNames,
814              			XkbGBN_AllComponentsMask, 
815              			XkbGBN_AllComponentsMask&(~XkbGBN_GeometryMask),
816              			True);
817              	if (!xkb) {
818              	    ERR("Error loading new keyboard description\n");
819              	    return False;
820              	}
821              	if (svValue[RULES_NDX] && (rdefs.model || rdefs.layout)) {
822              	    if (!XkbRF_SetNamesProp(dpy,svValue[RULES_NDX],&rdefs)) {
823              		VMSG(0,"Error updating the XKB names property\n");
824              	    }
825              	}
826 dawes   3.7      }
827                  if (print) {
828                      printKeymap();
829 dawes   3.0      }
830                  return True;
831              }
832              
833              
834              int
835              main(int argc,char **argv)
836              {
837                  if ((!parseArgs(argc,argv))||(!getDisplay(argc,argv)))
838              	exit(-1);
839                  svValue[LOCALE_NDX]= setlocale(LC_ALL,svValue[LOCALE_NDX]);
840                  svSrc[LOCALE_NDX]= FROM_SERVER;
841                  VMSG1(7,"locale is %s\n",svValue[LOCALE_NDX]);
842 dawes   3.4      if (dpy)
843                      getServerValues();
844 dawes   3.0      if (svValue[CONFIG_NDX] && (!applyConfig(svValue[CONFIG_NDX])))
845              	exit(-3);
846                  if (!applyRules())
847              	exit(-4);
848                  if (!applyComponentNames())
849              	exit(-5);
850                  if (dpy)
851              	XCloseDisplay(dpy);
852 hohndel 3.2      exit(0);
853 dawes   3.0  }

Powered by
ViewCVS 0.9.2