xkbmisc.c revision 4cd6a3ae
1/************************************************************
2 Copyright (c) 1995 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 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#elif defined(HAVE_CONFIG_H)
30#include <config.h>
31#endif
32
33#include <stdio.h>
34#include <ctype.h>
35#include <stdlib.h>
36
37#include <X11/Xos.h>
38#include <X11/Xfuncs.h>
39
40#ifndef XKB_IN_SERVER
41
42#include <X11/Xlib.h>
43#include <X11/keysym.h>
44#include <X11/XKBlib.h>
45#include <X11/extensions/XKBgeom.h>
46#include "XKMformat.h"
47#include "XKBfileInt.h"
48
49#else
50
51#include <X11/X.h>
52#include <X11/keysym.h>
53#include <X11/Xproto.h>
54#include "misc.h"
55#include "inputstr.h"
56#include "dix.h"
57#include <X11/extensions/XKBstr.h>
58#define XKBSRV_NEED_FILE_FUNCS	1
59#include <X11/extensions/XKBsrv.h>
60#include <X11/extensions/XKBgeom.h>
61#include "xkb.h"
62
63#endif
64
65unsigned
66_XkbKSCheckCase(KeySym ks)
67{
68unsigned	set,rtrn;
69
70    set= (ks & (~0xff)) >> 8;
71    rtrn= 0;
72    switch (set) {
73	case 0:		/* latin 1 */
74	    if (((ks>=XK_A)&&(ks<=XK_Z))||
75		((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
76		rtrn|= _XkbKSUpper;
77	    }
78	    if (((ks>=XK_a)&&(ks<=XK_z))||
79		((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
80		rtrn|= _XkbKSLower;
81	    }
82	    break;
83	case 1:		/* latin 2 */
84	    if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
85		((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
86		rtrn|= _XkbKSUpper;
87	    }
88	    if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
89		((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
90		rtrn|= _XkbKSLower;
91	    }
92	    break;
93	case 2:		/* latin 3 */
94	    if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
95		((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
96		rtrn|= _XkbKSUpper;
97	    }
98	    if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
99		((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
100		rtrn|= _XkbKSLower;
101	    }
102	    break;
103	case 3:		/* latin 4 */
104	    if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
105	        (ks==XK_ENG)||
106		((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
107		rtrn|= _XkbKSUpper;
108	    }
109	    if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
110	        (ks==XK_eng)||
111		((ks>=XK_amacron)&&(ks<=XK_umacron))) {
112		rtrn|= _XkbKSLower;
113	    }
114	    break;
115	case 18:		/* latin 8 */
116	    if ((ks==XK_Babovedot)||
117                ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
118		((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
119	        (ks==XK_Mabovedot)||
120	        (ks==XK_Pabovedot)||
121	        (ks==XK_Sabovedot)||
122	        (ks==XK_Wdiaeresis)||
123		((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
124		rtrn|= _XkbKSUpper;
125	    }
126	    if ((ks==XK_babovedot)||
127	        (ks==XK_dabovedot)||
128	        (ks==XK_fabovedot)||
129	        (ks==XK_mabovedot)||
130                ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
131	        (ks==XK_ygrave)||
132		((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
133		rtrn|= _XkbKSLower;
134	    }
135	    break;
136	case 19:		/* latin 9 */
137	    if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
138		rtrn|= _XkbKSUpper;
139	    }
140	    if (ks==XK_oe) {
141		rtrn|= _XkbKSLower;
142	    }
143	    break;
144    }
145    return rtrn;
146}
147
148/***===================================================================***/
149
150Bool
151XkbLookupGroupAndLevel(	XkbDescPtr 	xkb,
152			int 		key,
153			int *		mods_inout,
154			int *		grp_inout,
155			int *		lvl_rtrn)
156{
157int		nG,eG;
158
159    if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout))
160	return False;
161
162    nG= XkbKeyNumGroups(xkb,key);
163    eG= *grp_inout;
164
165    if ( nG==0 ) {
166	*grp_inout= 0;
167	if (lvl_rtrn!=NULL)
168	    *lvl_rtrn= 0;
169	return False;
170    }
171    else if ( nG==1 ) {
172	eG= 0;
173    }
174    else if ( eG>=nG ) {
175	unsigned gI= XkbKeyGroupInfo(xkb,key);
176	switch (XkbOutOfRangeGroupAction(gI)) {
177	    default:
178		eG %= nG;
179		break;
180	    case XkbClampIntoRange:
181		eG = nG-1;
182		break;
183	    case XkbRedirectIntoRange:
184		eG = XkbOutOfRangeGroupNumber(gI);
185		if (eG>=nG)
186		    eG= 0;
187		break;
188	}
189    }
190    *grp_inout= eG;
191    if (mods_inout!=NULL) {
192	XkbKeyTypePtr	type;
193	int		preserve;
194
195	type = XkbKeyKeyType(xkb,key,eG);
196	if (lvl_rtrn!=NULL)
197	    *lvl_rtrn= 0;
198	preserve= 0;
199	if (type->map) { /* find the shift level */
200	    register int i;
201	    register XkbKTMapEntryPtr entry;
202	    for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
203		if ((entry->active)&&
204			(((*mods_inout)&type->mods.mask)==entry->mods.mask)){
205		    if (lvl_rtrn!=NULL)
206			*lvl_rtrn= entry->level;
207		    if (type->preserve)
208			preserve= type->preserve[i].mask;
209		    break;
210		}
211	    }
212	}
213	(*mods_inout)&= ~(type->mods.mask&(~preserve));
214    }
215    return True;
216}
217
218/***===================================================================***/
219
220static Bool
221XkbWriteSectionFromName(FILE *file, const char *sectionName, const char *name)
222{
223    fprintf(file,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
224    return True;
225}
226
227#define	NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
228#define	COMPLETE(n)  ((n)&&(!NEED_DESC(n)))
229
230/* ARGSUSED */
231static void
232_AddIncl(	FILE *		file,
233		XkbFileInfo *	result,
234		Bool 		topLevel,
235		Bool 		showImplicit,
236		int 		index,
237		void *		priv)
238{
239    if ((priv)&&(strcmp((char *)priv,"%")!=0))
240	fprintf(file,"    include \"%s\"\n",(char *)priv);
241    return;
242}
243
244Bool
245XkbWriteXKBKeymapForNames(	FILE *			file,
246				XkbComponentNamesPtr	names,
247				Display *		dpy,
248				XkbDescPtr		xkb,
249				unsigned		want,
250				unsigned		need)
251{
252char *		name,*tmp;
253unsigned	complete;
254XkbNamesPtr	old_names;
255int		multi_section;
256unsigned	wantNames,wantConfig,wantDflts;
257XkbFileInfo	finfo;
258
259    bzero(&finfo,sizeof(XkbFileInfo));
260
261    complete= 0;
262    if ((name=names->keymap)==NULL)	name= "default";
263    if (COMPLETE(names->keycodes))	complete|= XkmKeyNamesMask;
264    if (COMPLETE(names->types))		complete|= XkmTypesMask;
265    if (COMPLETE(names->compat))	complete|= XkmCompatMapMask;
266    if (COMPLETE(names->symbols))	complete|= XkmSymbolsMask;
267    if (COMPLETE(names->geometry))	complete|= XkmGeometryMask;
268    want|= (complete|need);
269    if (want&XkmSymbolsMask)
270	want|= XkmKeyNamesMask|XkmTypesMask;
271
272    if (want==0)
273	return False;
274
275    if (xkb!=NULL) {
276	 old_names= xkb->names;
277	 finfo.type= 0;
278	 finfo.defined= 0;
279	 finfo.xkb= xkb;
280	 if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL))
281	    return False;
282    }
283    else old_names= NULL;
284
285    wantConfig= want&(~complete);
286    if (xkb!=NULL) {
287	if (wantConfig&XkmTypesMask) {
288	    if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes))
289		wantConfig&= ~XkmTypesMask;
290	}
291	if (wantConfig&XkmCompatMapMask) {
292	    if ((!xkb->compat) || (xkb->compat->num_si<1))
293		wantConfig&= ~XkmCompatMapMask;
294	}
295	if (wantConfig&XkmSymbolsMask) {
296	    if ((!xkb->map) || (!xkb->map->key_sym_map))
297		wantConfig&= ~XkmSymbolsMask;
298	}
299	if (wantConfig&XkmIndicatorsMask) {
300	    if (!xkb->indicators)
301		wantConfig&= ~XkmIndicatorsMask;
302	}
303	if (wantConfig&XkmKeyNamesMask) {
304	    if ((!xkb->names)||(!xkb->names->keys))
305		wantConfig&= ~XkmKeyNamesMask;
306	}
307	if ((wantConfig&XkmGeometryMask)&&(!xkb->geom))
308	    wantConfig&= ~XkmGeometryMask;
309    }
310    else {
311	wantConfig= 0;
312    }
313    complete|= wantConfig;
314
315    wantDflts= 0;
316    wantNames= want&(~complete);
317    if ((xkb!=NULL) && (old_names!=NULL)) {
318	if (wantNames&XkmTypesMask) {
319	    if (old_names->types!=None) {
320		tmp= XkbAtomGetString(dpy,old_names->types);
321		names->types= tmp;
322	    }
323	    else {
324		wantDflts|= XkmTypesMask;
325	    }
326	    complete|= XkmTypesMask;
327	}
328	if (wantNames&XkmCompatMapMask) {
329	    if (old_names->compat!=None) {
330		tmp= XkbAtomGetString(dpy,old_names->compat);
331		names->compat= tmp;
332	    }
333	    else wantDflts|= XkmCompatMapMask;
334	    complete|= XkmCompatMapMask;
335	}
336	if (wantNames&XkmSymbolsMask) {
337	    if (old_names->symbols==None)
338		return False;
339	    tmp= XkbAtomGetString(dpy,old_names->symbols);
340	    names->symbols= tmp;
341	    complete|= XkmSymbolsMask;
342	}
343	if (wantNames&XkmKeyNamesMask) {
344	   if (old_names->keycodes!=None) {
345		tmp= XkbAtomGetString(dpy,old_names->keycodes);
346		names->keycodes= tmp;
347	    }
348	    else wantDflts|= XkmKeyNamesMask;
349	    complete|= XkmKeyNamesMask;
350	}
351	if (wantNames&XkmGeometryMask) {
352	    if (old_names->geometry==None)
353		return False;
354	    tmp= XkbAtomGetString(dpy,old_names->geometry);
355	    names->geometry= tmp;
356	    complete|= XkmGeometryMask;
357	    wantNames&= ~XkmGeometryMask;
358	}
359    }
360    if (complete&XkmCompatMapMask)
361	complete|= XkmIndicatorsMask|XkmVirtualModsMask;
362    else if (complete&(XkmSymbolsMask|XkmTypesMask))
363	complete|= XkmVirtualModsMask;
364    if (need & (~complete))
365	return False;
366    if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete)))
367	return False;
368
369    multi_section= 1;
370    if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
371	((complete&(~XkmKeymapLegal))==0)) {
372	fprintf(file,"xkb_keymap \"%s\" {\n",name);
373    }
374    else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
375	((complete&(~XkmSemanticsLegal))==0)) {
376	fprintf(file,"xkb_semantics \"%s\" {\n",name);
377    }
378    else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
379	((complete&(~XkmLayoutLegal))==0)) {
380	fprintf(file,"xkb_layout \"%s\" {\n",name);
381    }
382    else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
383	multi_section= 0;
384    }
385    else {
386	return False;
387    }
388
389    wantNames= complete&(~(wantConfig|wantDflts));
390    name= names->keycodes;
391    if (wantConfig&XkmKeyNamesMask)
392	XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name);
393    else if (wantDflts&XkmKeyNamesMask)
394	fprintf(stderr,"Default symbols not implemented yet!\n");
395    else if (wantNames&XkmKeyNamesMask)
396	XkbWriteSectionFromName(file,"keycodes",name);
397
398    name= names->types;
399    if (wantConfig&XkmTypesMask)
400	XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name);
401    else if (wantDflts&XkmTypesMask)
402	fprintf(stderr,"Default types not implemented yet!\n");
403    else if (wantNames&XkmTypesMask)
404	XkbWriteSectionFromName(file,"types",name);
405
406    name= names->compat;
407    if (wantConfig&XkmCompatMapMask)
408	XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name);
409    else if (wantDflts&XkmCompatMapMask)
410	fprintf(stderr,"Default interps not implemented yet!\n");
411    else if (wantNames&XkmCompatMapMask)
412	XkbWriteSectionFromName(file,"compatibility",name);
413
414    name= names->symbols;
415    if (wantConfig&XkmSymbolsMask)
416	XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name);
417    else if (wantNames&XkmSymbolsMask)
418	XkbWriteSectionFromName(file,"symbols",name);
419
420    name= names->geometry;
421    if (wantConfig&XkmGeometryMask)
422	XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name);
423    else if (wantNames&XkmGeometryMask)
424	XkbWriteSectionFromName(file,"geometry",name);
425
426    if (multi_section)
427	fprintf(file,"};\n");
428    return True;
429}
430
431/***====================================================================***/
432
433/*ARGSUSED*/
434Status
435XkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo)
436{
437    return BadImplementation;
438}
439
440/***====================================================================***/
441
442int
443XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases)
444{
445register int	i;
446
447    if ((!xkb)||(!xkb->names)||(!xkb->names->keys))
448	return 0;
449    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
450	if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0)
451	    return i;
452    }
453    if (!use_aliases)
454	return 0;
455    if (xkb->geom && xkb->geom->key_aliases) {
456	XkbKeyAliasPtr	a;
457	a= xkb->geom->key_aliases;
458	for (i=0;i<xkb->geom->num_key_aliases;i++,a++) {
459	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
460		return XkbFindKeycodeByName(xkb,a->real,False);
461	}
462    }
463    if (xkb->names && xkb->names->key_aliases) {
464	XkbKeyAliasPtr	a;
465	a= xkb->names->key_aliases;
466	for (i=0;i<xkb->names->num_key_aliases;i++,a++) {
467	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
468		return XkbFindKeycodeByName(xkb,a->real,False);
469	}
470    }
471    return 0;
472}
473
474
475unsigned
476XkbConvertGetByNameComponents(Bool toXkm,unsigned orig)
477{
478unsigned	rtrn;
479
480    rtrn= 0;
481    if (toXkm) {
482	if (orig&XkbGBN_TypesMask)		rtrn|= XkmTypesMask;
483	if (orig&XkbGBN_CompatMapMask)		rtrn|= XkmCompatMapMask;
484	if (orig&XkbGBN_SymbolsMask)		rtrn|= XkmSymbolsMask;
485	if (orig&XkbGBN_IndicatorMapMask)	rtrn|= XkmIndicatorsMask;
486	if (orig&XkbGBN_KeyNamesMask)		rtrn|= XkmKeyNamesMask;
487	if (orig&XkbGBN_GeometryMask)		rtrn|= XkmGeometryMask;
488    }
489    else {
490	if (orig&XkmTypesMask)			rtrn|= XkbGBN_TypesMask;
491	if (orig&XkmCompatMapMask)		rtrn|= XkbGBN_CompatMapMask;
492	if (orig&XkmSymbolsMask)		rtrn|= XkbGBN_SymbolsMask;
493	if (orig&XkmIndicatorsMask)		rtrn|= XkbGBN_IndicatorMapMask;
494	if (orig&XkmKeyNamesMask)		rtrn|= XkbGBN_KeyNamesMask;
495	if (orig&XkmGeometryMask)		rtrn|= XkbGBN_GeometryMask;
496	if (orig!=0)				rtrn|= XkbGBN_OtherNamesMask;
497    }
498    return rtrn;
499}
500
501unsigned
502XkbConvertXkbComponents(Bool toXkm,unsigned orig)
503{
504unsigned	rtrn;
505
506    rtrn= 0;
507    if (toXkm) {
508	if (orig&XkbClientMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
509	if (orig&XkbServerMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
510	if (orig&XkbCompatMapMask)	rtrn|= XkmCompatMapMask;
511	if (orig&XkbIndicatorMapMask)	rtrn|= XkmIndicatorsMask;
512	if (orig&XkbNamesMask)		rtrn|= XkmKeyNamesMask;
513	if (orig&XkbGeometryMask)	rtrn|= XkmGeometryMask;
514    }
515    else {
516	if (orig!=0)			rtrn|= XkbNamesMask;
517	if (orig&XkmTypesMask)		rtrn|= XkbClientMapMask;
518	if (orig&XkmCompatMapMask)
519		rtrn|= XkbCompatMapMask|XkbIndicatorMapMask;
520	if (orig&XkmSymbolsMask)	rtrn|=XkbClientMapMask|XkbServerMapMask;
521	if (orig&XkmIndicatorsMask)	rtrn|= XkbIndicatorMapMask;
522	if (orig&XkmKeyNamesMask)
523		rtrn|= XkbNamesMask|XkbIndicatorMapMask;
524	if (orig&XkmGeometryMask)	rtrn|= XkbGeometryMask;
525    }
526    return rtrn;
527}
528
529Bool
530XkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing)
531{
532unsigned	present;
533XkbDescPtr	xkb;
534
535    if ((!finfo)||(!finfo->xkb))
536	return False;
537    if (opts_missing)
538	*opts_missing= 0;
539    xkb= finfo->xkb;
540    present= 0;
541    if ((xkb->names)&&(xkb->names->keys))	present|= XkmKeyNamesMask;
542    if ((xkb->map)&&(xkb->map->types))		present|= XkmTypesMask;
543    if (xkb->compat)				present|= XkmCompatMapMask;
544    if ((xkb->map)&&(xkb->map->num_syms>1))	present|= XkmSymbolsMask;
545    if (xkb->indicators)			present|= XkmIndicatorsMask;
546    if (xkb->geom)				present|= XkmGeometryMask;
547    if (!present)
548	return False;
549    else switch (present) {
550	case XkmKeyNamesMask:
551	    finfo->type= 	XkmKeyNamesIndex;
552	    finfo->defined= 	present;
553	    return True;
554	case XkmTypesMask:
555	    finfo->type=	XkmTypesIndex;
556	    finfo->defined= 	present;
557	    return True;
558	case XkmCompatMapMask:
559	    finfo->type=	XkmCompatMapIndex;
560	    finfo->defined=	present;
561	    return True;
562	case XkmSymbolsMask:
563	    if (format!=XkbXKMFile) {
564		finfo->type= 	XkmSymbolsIndex;
565		finfo->defined=	present;
566		return True;
567	    }
568	    break;
569	case XkmGeometryMask:
570	    finfo->type=	XkmGeometryIndex;
571	    finfo->defined=	present;
572	    return True;
573    }
574    if ((present&(~XkmSemanticsLegal))==0) {
575	if ((XkmSemanticsRequired&present)==XkmSemanticsRequired) {
576	    if (opts_missing)
577		*opts_missing= XkmSemanticsOptional&(~present);
578	    finfo->type= 	XkmSemanticsFile;
579	    finfo->defined=	present;
580	    return True;
581	}
582    }
583    else if ((present&(~XkmLayoutLegal))==0) {
584	if ((XkmLayoutRequired&present)==XkmLayoutRequired) {
585	    if (opts_missing)
586		*opts_missing= XkmLayoutOptional&(~present);
587	    finfo->type=	XkmLayoutFile;
588	    finfo->defined=	present;
589	    return True;
590	}
591    }
592    else if ((present&(~XkmKeymapLegal))==0) {
593	if ((XkmKeymapRequired&present)==XkmKeymapRequired) {
594	    if (opts_missing)
595		*opts_missing= XkmKeymapOptional&(~present);
596	    finfo->type=	XkmKeymapFile;
597	    finfo->defined=	present;
598	    return True;
599	}
600    }
601    return False;
602}
603
604/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */
605/* wildcards */
606
607static unsigned char componentSpecLegal[] = {
608	0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
609	0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
610	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611	0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
612};
613
614void
615XkbEnsureSafeMapName(char *name)
616{
617   if (name==NULL)
618        return;
619    while (*name!='\0') {
620	if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0)
621	    *name= '_';
622        name++;
623    }
624    return;
625}
626
627/***====================================================================***/
628
629#define	UNMATCHABLE(c)	(((c)=='(')||((c)==')')||((c)=='/'))
630
631Bool
632XkbNameMatchesPattern(char *name,char *ptrn)
633{
634    while (ptrn[0]!='\0') {
635	if (name[0]=='\0') {
636	    if (ptrn[0]=='*') {
637		ptrn++;
638		continue;
639	    }
640	    return False;
641	}
642	if (ptrn[0]=='?') {
643	    if (UNMATCHABLE(name[0]))
644		return False;
645	}
646	else if (ptrn[0]=='*') {
647	    if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn))
648		return True;
649	    return XkbNameMatchesPattern(name,ptrn+1);
650	}
651	else if (ptrn[0]!=name[0])
652	    return False;
653	name++;
654	ptrn++;
655    }
656    /* if we get here, the pattern is exhausted (-:just like me:-) */
657    return (name[0]=='\0');
658}
659
660#ifdef NEED_STRCASECMP
661_X_HIDDEN int
662_XkbStrCaseCmp(char *str1,char *str2)
663{
664    const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2;
665
666    while (tolower(*us1) == tolower(*us2)) {
667        if (*us1++ == '\0')
668            return (0);
669        us2++;
670    }
671
672    return (tolower(*us1) - tolower(*us2));
673}
674#endif
675