xkbmisc.c revision 4cd6a3ae
18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
38c9fbc29Smrg
48c9fbc29Smrg Permission to use, copy, modify, and distribute this
58c9fbc29Smrg software and its documentation for any purpose and without
68c9fbc29Smrg fee is hereby granted, provided that the above copyright
78c9fbc29Smrg notice appear in all copies and that both that copyright
88c9fbc29Smrg notice and this permission notice appear in supporting
94cd6a3aeSmrg documentation, and that the name of Silicon Graphics not be
104cd6a3aeSmrg used in advertising or publicity pertaining to distribution
118c9fbc29Smrg of the software without specific prior written permission.
124cd6a3aeSmrg Silicon Graphics makes no representation about the suitability
138c9fbc29Smrg of this software for any purpose. It is provided "as is"
148c9fbc29Smrg without any express or implied warranty.
154cd6a3aeSmrg
164cd6a3aeSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
174cd6a3aeSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
188c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
194cd6a3aeSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
204cd6a3aeSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
214cd6a3aeSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
228c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
238c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
248c9fbc29Smrg
258c9fbc29Smrg ********************************************************/
268c9fbc29Smrg
278c9fbc29Smrg#ifdef HAVE_DIX_CONFIG_H
288c9fbc29Smrg#include <dix-config.h>
298c9fbc29Smrg#elif defined(HAVE_CONFIG_H)
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg
338c9fbc29Smrg#include <stdio.h>
348c9fbc29Smrg#include <ctype.h>
358c9fbc29Smrg#include <stdlib.h>
368c9fbc29Smrg
378c9fbc29Smrg#include <X11/Xos.h>
388c9fbc29Smrg#include <X11/Xfuncs.h>
398c9fbc29Smrg
408c9fbc29Smrg#ifndef XKB_IN_SERVER
418c9fbc29Smrg
428c9fbc29Smrg#include <X11/Xlib.h>
438c9fbc29Smrg#include <X11/keysym.h>
448c9fbc29Smrg#include <X11/XKBlib.h>
458c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
468c9fbc29Smrg#include "XKMformat.h"
478c9fbc29Smrg#include "XKBfileInt.h"
488c9fbc29Smrg
498c9fbc29Smrg#else
508c9fbc29Smrg
518c9fbc29Smrg#include <X11/X.h>
528c9fbc29Smrg#include <X11/keysym.h>
538c9fbc29Smrg#include <X11/Xproto.h>
548c9fbc29Smrg#include "misc.h"
558c9fbc29Smrg#include "inputstr.h"
568c9fbc29Smrg#include "dix.h"
578c9fbc29Smrg#include <X11/extensions/XKBstr.h>
588c9fbc29Smrg#define XKBSRV_NEED_FILE_FUNCS	1
598c9fbc29Smrg#include <X11/extensions/XKBsrv.h>
608c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
618c9fbc29Smrg#include "xkb.h"
628c9fbc29Smrg
638c9fbc29Smrg#endif
648c9fbc29Smrg
658c9fbc29Smrgunsigned
668c9fbc29Smrg_XkbKSCheckCase(KeySym ks)
678c9fbc29Smrg{
688c9fbc29Smrgunsigned	set,rtrn;
698c9fbc29Smrg
708c9fbc29Smrg    set= (ks & (~0xff)) >> 8;
718c9fbc29Smrg    rtrn= 0;
728c9fbc29Smrg    switch (set) {
738c9fbc29Smrg	case 0:		/* latin 1 */
748c9fbc29Smrg	    if (((ks>=XK_A)&&(ks<=XK_Z))||
758c9fbc29Smrg		((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
768c9fbc29Smrg		rtrn|= _XkbKSUpper;
778c9fbc29Smrg	    }
788c9fbc29Smrg	    if (((ks>=XK_a)&&(ks<=XK_z))||
798c9fbc29Smrg		((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
808c9fbc29Smrg		rtrn|= _XkbKSLower;
818c9fbc29Smrg	    }
828c9fbc29Smrg	    break;
838c9fbc29Smrg	case 1:		/* latin 2 */
848c9fbc29Smrg	    if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
858c9fbc29Smrg		((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
868c9fbc29Smrg		rtrn|= _XkbKSUpper;
878c9fbc29Smrg	    }
888c9fbc29Smrg	    if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
898c9fbc29Smrg		((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
908c9fbc29Smrg		rtrn|= _XkbKSLower;
918c9fbc29Smrg	    }
928c9fbc29Smrg	    break;
938c9fbc29Smrg	case 2:		/* latin 3 */
948c9fbc29Smrg	    if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
958c9fbc29Smrg		((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
968c9fbc29Smrg		rtrn|= _XkbKSUpper;
978c9fbc29Smrg	    }
988c9fbc29Smrg	    if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
998c9fbc29Smrg		((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
1008c9fbc29Smrg		rtrn|= _XkbKSLower;
1018c9fbc29Smrg	    }
1028c9fbc29Smrg	    break;
1038c9fbc29Smrg	case 3:		/* latin 4 */
1048c9fbc29Smrg	    if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
1058c9fbc29Smrg	        (ks==XK_ENG)||
1068c9fbc29Smrg		((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
1078c9fbc29Smrg		rtrn|= _XkbKSUpper;
1088c9fbc29Smrg	    }
1098c9fbc29Smrg	    if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
1108c9fbc29Smrg	        (ks==XK_eng)||
1118c9fbc29Smrg		((ks>=XK_amacron)&&(ks<=XK_umacron))) {
1128c9fbc29Smrg		rtrn|= _XkbKSLower;
1138c9fbc29Smrg	    }
1148c9fbc29Smrg	    break;
1158c9fbc29Smrg	case 18:		/* latin 8 */
1168c9fbc29Smrg	    if ((ks==XK_Babovedot)||
1178c9fbc29Smrg                ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
1188c9fbc29Smrg		((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
1198c9fbc29Smrg	        (ks==XK_Mabovedot)||
1208c9fbc29Smrg	        (ks==XK_Pabovedot)||
1218c9fbc29Smrg	        (ks==XK_Sabovedot)||
1228c9fbc29Smrg	        (ks==XK_Wdiaeresis)||
1238c9fbc29Smrg		((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
1248c9fbc29Smrg		rtrn|= _XkbKSUpper;
1258c9fbc29Smrg	    }
1268c9fbc29Smrg	    if ((ks==XK_babovedot)||
1278c9fbc29Smrg	        (ks==XK_dabovedot)||
1288c9fbc29Smrg	        (ks==XK_fabovedot)||
1298c9fbc29Smrg	        (ks==XK_mabovedot)||
1308c9fbc29Smrg                ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
1318c9fbc29Smrg	        (ks==XK_ygrave)||
1328c9fbc29Smrg		((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
1338c9fbc29Smrg		rtrn|= _XkbKSLower;
1348c9fbc29Smrg	    }
1358c9fbc29Smrg	    break;
1368c9fbc29Smrg	case 19:		/* latin 9 */
1378c9fbc29Smrg	    if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
1388c9fbc29Smrg		rtrn|= _XkbKSUpper;
1398c9fbc29Smrg	    }
1408c9fbc29Smrg	    if (ks==XK_oe) {
1418c9fbc29Smrg		rtrn|= _XkbKSLower;
1428c9fbc29Smrg	    }
1438c9fbc29Smrg	    break;
1448c9fbc29Smrg    }
1458c9fbc29Smrg    return rtrn;
1468c9fbc29Smrg}
1478c9fbc29Smrg
1488c9fbc29Smrg/***===================================================================***/
1498c9fbc29Smrg
1508c9fbc29SmrgBool
1518c9fbc29SmrgXkbLookupGroupAndLevel(	XkbDescPtr 	xkb,
1528c9fbc29Smrg			int 		key,
1538c9fbc29Smrg			int *		mods_inout,
1548c9fbc29Smrg			int *		grp_inout,
1558c9fbc29Smrg			int *		lvl_rtrn)
1568c9fbc29Smrg{
1578c9fbc29Smrgint		nG,eG;
1588c9fbc29Smrg
1598c9fbc29Smrg    if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout))
1608c9fbc29Smrg	return False;
1618c9fbc29Smrg
1628c9fbc29Smrg    nG= XkbKeyNumGroups(xkb,key);
1638c9fbc29Smrg    eG= *grp_inout;
1648c9fbc29Smrg
1658c9fbc29Smrg    if ( nG==0 ) {
1668c9fbc29Smrg	*grp_inout= 0;
1678c9fbc29Smrg	if (lvl_rtrn!=NULL)
1688c9fbc29Smrg	    *lvl_rtrn= 0;
1698c9fbc29Smrg	return False;
1708c9fbc29Smrg    }
1718c9fbc29Smrg    else if ( nG==1 ) {
1728c9fbc29Smrg	eG= 0;
1738c9fbc29Smrg    }
1748c9fbc29Smrg    else if ( eG>=nG ) {
1758c9fbc29Smrg	unsigned gI= XkbKeyGroupInfo(xkb,key);
1768c9fbc29Smrg	switch (XkbOutOfRangeGroupAction(gI)) {
1778c9fbc29Smrg	    default:
1788c9fbc29Smrg		eG %= nG;
1798c9fbc29Smrg		break;
1808c9fbc29Smrg	    case XkbClampIntoRange:
1818c9fbc29Smrg		eG = nG-1;
1828c9fbc29Smrg		break;
1838c9fbc29Smrg	    case XkbRedirectIntoRange:
1848c9fbc29Smrg		eG = XkbOutOfRangeGroupNumber(gI);
1858c9fbc29Smrg		if (eG>=nG)
1868c9fbc29Smrg		    eG= 0;
1878c9fbc29Smrg		break;
1888c9fbc29Smrg	}
1898c9fbc29Smrg    }
1908c9fbc29Smrg    *grp_inout= eG;
1918c9fbc29Smrg    if (mods_inout!=NULL) {
1928c9fbc29Smrg	XkbKeyTypePtr	type;
1938c9fbc29Smrg	int		preserve;
1948c9fbc29Smrg
1958c9fbc29Smrg	type = XkbKeyKeyType(xkb,key,eG);
1968c9fbc29Smrg	if (lvl_rtrn!=NULL)
1978c9fbc29Smrg	    *lvl_rtrn= 0;
1988c9fbc29Smrg	preserve= 0;
1998c9fbc29Smrg	if (type->map) { /* find the shift level */
2008c9fbc29Smrg	    register int i;
2018c9fbc29Smrg	    register XkbKTMapEntryPtr entry;
2028c9fbc29Smrg	    for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
2038c9fbc29Smrg		if ((entry->active)&&
2048c9fbc29Smrg			(((*mods_inout)&type->mods.mask)==entry->mods.mask)){
2058c9fbc29Smrg		    if (lvl_rtrn!=NULL)
2068c9fbc29Smrg			*lvl_rtrn= entry->level;
2078c9fbc29Smrg		    if (type->preserve)
2088c9fbc29Smrg			preserve= type->preserve[i].mask;
2098c9fbc29Smrg		    break;
2108c9fbc29Smrg		}
2118c9fbc29Smrg	    }
2128c9fbc29Smrg	}
2138c9fbc29Smrg	(*mods_inout)&= ~(type->mods.mask&(~preserve));
2148c9fbc29Smrg    }
2158c9fbc29Smrg    return True;
2168c9fbc29Smrg}
2178c9fbc29Smrg
2188c9fbc29Smrg/***===================================================================***/
2198c9fbc29Smrg
2208c9fbc29Smrgstatic Bool
2214cd6a3aeSmrgXkbWriteSectionFromName(FILE *file, const char *sectionName, const char *name)
2228c9fbc29Smrg{
2238c9fbc29Smrg    fprintf(file,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
2248c9fbc29Smrg    return True;
2258c9fbc29Smrg}
2268c9fbc29Smrg
2278c9fbc29Smrg#define	NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
2288c9fbc29Smrg#define	COMPLETE(n)  ((n)&&(!NEED_DESC(n)))
2298c9fbc29Smrg
2308c9fbc29Smrg/* ARGSUSED */
2318c9fbc29Smrgstatic void
2328c9fbc29Smrg_AddIncl(	FILE *		file,
2338c9fbc29Smrg		XkbFileInfo *	result,
2348c9fbc29Smrg		Bool 		topLevel,
2358c9fbc29Smrg		Bool 		showImplicit,
2368c9fbc29Smrg		int 		index,
2378c9fbc29Smrg		void *		priv)
2388c9fbc29Smrg{
2398c9fbc29Smrg    if ((priv)&&(strcmp((char *)priv,"%")!=0))
2408c9fbc29Smrg	fprintf(file,"    include \"%s\"\n",(char *)priv);
2418c9fbc29Smrg    return;
2428c9fbc29Smrg}
2438c9fbc29Smrg
2448c9fbc29SmrgBool
2458c9fbc29SmrgXkbWriteXKBKeymapForNames(	FILE *			file,
2468c9fbc29Smrg				XkbComponentNamesPtr	names,
2478c9fbc29Smrg				Display *		dpy,
2488c9fbc29Smrg				XkbDescPtr		xkb,
2498c9fbc29Smrg				unsigned		want,
2508c9fbc29Smrg				unsigned		need)
2518c9fbc29Smrg{
2528c9fbc29Smrgchar *		name,*tmp;
2538c9fbc29Smrgunsigned	complete;
2548c9fbc29SmrgXkbNamesPtr	old_names;
2558c9fbc29Smrgint		multi_section;
2568c9fbc29Smrgunsigned	wantNames,wantConfig,wantDflts;
2578c9fbc29SmrgXkbFileInfo	finfo;
2588c9fbc29Smrg
2598c9fbc29Smrg    bzero(&finfo,sizeof(XkbFileInfo));
2608c9fbc29Smrg
2618c9fbc29Smrg    complete= 0;
2628c9fbc29Smrg    if ((name=names->keymap)==NULL)	name= "default";
2638c9fbc29Smrg    if (COMPLETE(names->keycodes))	complete|= XkmKeyNamesMask;
2648c9fbc29Smrg    if (COMPLETE(names->types))		complete|= XkmTypesMask;
2658c9fbc29Smrg    if (COMPLETE(names->compat))	complete|= XkmCompatMapMask;
2668c9fbc29Smrg    if (COMPLETE(names->symbols))	complete|= XkmSymbolsMask;
2678c9fbc29Smrg    if (COMPLETE(names->geometry))	complete|= XkmGeometryMask;
2688c9fbc29Smrg    want|= (complete|need);
2698c9fbc29Smrg    if (want&XkmSymbolsMask)
2708c9fbc29Smrg	want|= XkmKeyNamesMask|XkmTypesMask;
2718c9fbc29Smrg
2728c9fbc29Smrg    if (want==0)
2738c9fbc29Smrg	return False;
2748c9fbc29Smrg
2758c9fbc29Smrg    if (xkb!=NULL) {
2768c9fbc29Smrg	 old_names= xkb->names;
2778c9fbc29Smrg	 finfo.type= 0;
2788c9fbc29Smrg	 finfo.defined= 0;
2798c9fbc29Smrg	 finfo.xkb= xkb;
2808c9fbc29Smrg	 if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL))
2818c9fbc29Smrg	    return False;
2828c9fbc29Smrg    }
2838c9fbc29Smrg    else old_names= NULL;
2848c9fbc29Smrg
2858c9fbc29Smrg    wantConfig= want&(~complete);
2868c9fbc29Smrg    if (xkb!=NULL) {
2878c9fbc29Smrg	if (wantConfig&XkmTypesMask) {
2888c9fbc29Smrg	    if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes))
2898c9fbc29Smrg		wantConfig&= ~XkmTypesMask;
2908c9fbc29Smrg	}
2918c9fbc29Smrg	if (wantConfig&XkmCompatMapMask) {
2928c9fbc29Smrg	    if ((!xkb->compat) || (xkb->compat->num_si<1))
2938c9fbc29Smrg		wantConfig&= ~XkmCompatMapMask;
2948c9fbc29Smrg	}
2958c9fbc29Smrg	if (wantConfig&XkmSymbolsMask) {
2968c9fbc29Smrg	    if ((!xkb->map) || (!xkb->map->key_sym_map))
2978c9fbc29Smrg		wantConfig&= ~XkmSymbolsMask;
2988c9fbc29Smrg	}
2998c9fbc29Smrg	if (wantConfig&XkmIndicatorsMask) {
3008c9fbc29Smrg	    if (!xkb->indicators)
3018c9fbc29Smrg		wantConfig&= ~XkmIndicatorsMask;
3028c9fbc29Smrg	}
3038c9fbc29Smrg	if (wantConfig&XkmKeyNamesMask) {
3048c9fbc29Smrg	    if ((!xkb->names)||(!xkb->names->keys))
3058c9fbc29Smrg		wantConfig&= ~XkmKeyNamesMask;
3068c9fbc29Smrg	}
3078c9fbc29Smrg	if ((wantConfig&XkmGeometryMask)&&(!xkb->geom))
3088c9fbc29Smrg	    wantConfig&= ~XkmGeometryMask;
3098c9fbc29Smrg    }
3108c9fbc29Smrg    else {
3118c9fbc29Smrg	wantConfig= 0;
3128c9fbc29Smrg    }
3138c9fbc29Smrg    complete|= wantConfig;
3148c9fbc29Smrg
3158c9fbc29Smrg    wantDflts= 0;
3168c9fbc29Smrg    wantNames= want&(~complete);
3178c9fbc29Smrg    if ((xkb!=NULL) && (old_names!=NULL)) {
3188c9fbc29Smrg	if (wantNames&XkmTypesMask) {
3198c9fbc29Smrg	    if (old_names->types!=None) {
3208c9fbc29Smrg		tmp= XkbAtomGetString(dpy,old_names->types);
3218c9fbc29Smrg		names->types= tmp;
3228c9fbc29Smrg	    }
3238c9fbc29Smrg	    else {
3248c9fbc29Smrg		wantDflts|= XkmTypesMask;
3258c9fbc29Smrg	    }
3264cd6a3aeSmrg	    complete|= XkmTypesMask;
3278c9fbc29Smrg	}
3288c9fbc29Smrg	if (wantNames&XkmCompatMapMask) {
3298c9fbc29Smrg	    if (old_names->compat!=None) {
3308c9fbc29Smrg		tmp= XkbAtomGetString(dpy,old_names->compat);
3318c9fbc29Smrg		names->compat= tmp;
3328c9fbc29Smrg	    }
3338c9fbc29Smrg	    else wantDflts|= XkmCompatMapMask;
3344cd6a3aeSmrg	    complete|= XkmCompatMapMask;
3358c9fbc29Smrg	}
3368c9fbc29Smrg	if (wantNames&XkmSymbolsMask) {
3378c9fbc29Smrg	    if (old_names->symbols==None)
3388c9fbc29Smrg		return False;
3398c9fbc29Smrg	    tmp= XkbAtomGetString(dpy,old_names->symbols);
3408c9fbc29Smrg	    names->symbols= tmp;
3414cd6a3aeSmrg	    complete|= XkmSymbolsMask;
3428c9fbc29Smrg	}
3438c9fbc29Smrg	if (wantNames&XkmKeyNamesMask) {
3448c9fbc29Smrg	   if (old_names->keycodes!=None) {
3458c9fbc29Smrg		tmp= XkbAtomGetString(dpy,old_names->keycodes);
3468c9fbc29Smrg		names->keycodes= tmp;
3478c9fbc29Smrg	    }
3488c9fbc29Smrg	    else wantDflts|= XkmKeyNamesMask;
3498c9fbc29Smrg	    complete|= XkmKeyNamesMask;
3508c9fbc29Smrg	}
3518c9fbc29Smrg	if (wantNames&XkmGeometryMask) {
3528c9fbc29Smrg	    if (old_names->geometry==None)
3538c9fbc29Smrg		return False;
3548c9fbc29Smrg	    tmp= XkbAtomGetString(dpy,old_names->geometry);
3558c9fbc29Smrg	    names->geometry= tmp;
3564cd6a3aeSmrg	    complete|= XkmGeometryMask;
3578c9fbc29Smrg	    wantNames&= ~XkmGeometryMask;
3588c9fbc29Smrg	}
3598c9fbc29Smrg    }
3608c9fbc29Smrg    if (complete&XkmCompatMapMask)
3618c9fbc29Smrg	complete|= XkmIndicatorsMask|XkmVirtualModsMask;
3628c9fbc29Smrg    else if (complete&(XkmSymbolsMask|XkmTypesMask))
3638c9fbc29Smrg	complete|= XkmVirtualModsMask;
3648c9fbc29Smrg    if (need & (~complete))
3658c9fbc29Smrg	return False;
3668c9fbc29Smrg    if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete)))
3678c9fbc29Smrg	return False;
3688c9fbc29Smrg
3698c9fbc29Smrg    multi_section= 1;
3708c9fbc29Smrg    if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
3718c9fbc29Smrg	((complete&(~XkmKeymapLegal))==0)) {
3728c9fbc29Smrg	fprintf(file,"xkb_keymap \"%s\" {\n",name);
3738c9fbc29Smrg    }
3748c9fbc29Smrg    else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
3758c9fbc29Smrg	((complete&(~XkmSemanticsLegal))==0)) {
3768c9fbc29Smrg	fprintf(file,"xkb_semantics \"%s\" {\n",name);
3778c9fbc29Smrg    }
3788c9fbc29Smrg    else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
3798c9fbc29Smrg	((complete&(~XkmLayoutLegal))==0)) {
3808c9fbc29Smrg	fprintf(file,"xkb_layout \"%s\" {\n",name);
3818c9fbc29Smrg    }
3828c9fbc29Smrg    else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
3838c9fbc29Smrg	multi_section= 0;
3848c9fbc29Smrg    }
3858c9fbc29Smrg    else {
3868c9fbc29Smrg	return False;
3878c9fbc29Smrg    }
3888c9fbc29Smrg
3898c9fbc29Smrg    wantNames= complete&(~(wantConfig|wantDflts));
3908c9fbc29Smrg    name= names->keycodes;
3918c9fbc29Smrg    if (wantConfig&XkmKeyNamesMask)
3928c9fbc29Smrg	XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name);
3938c9fbc29Smrg    else if (wantDflts&XkmKeyNamesMask)
3948c9fbc29Smrg	fprintf(stderr,"Default symbols not implemented yet!\n");
3958c9fbc29Smrg    else if (wantNames&XkmKeyNamesMask)
3968c9fbc29Smrg	XkbWriteSectionFromName(file,"keycodes",name);
3978c9fbc29Smrg
3988c9fbc29Smrg    name= names->types;
3998c9fbc29Smrg    if (wantConfig&XkmTypesMask)
4008c9fbc29Smrg	XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name);
4018c9fbc29Smrg    else if (wantDflts&XkmTypesMask)
4028c9fbc29Smrg	fprintf(stderr,"Default types not implemented yet!\n");
4038c9fbc29Smrg    else if (wantNames&XkmTypesMask)
4048c9fbc29Smrg	XkbWriteSectionFromName(file,"types",name);
4058c9fbc29Smrg
4068c9fbc29Smrg    name= names->compat;
4078c9fbc29Smrg    if (wantConfig&XkmCompatMapMask)
4088c9fbc29Smrg	XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name);
4098c9fbc29Smrg    else if (wantDflts&XkmCompatMapMask)
4108c9fbc29Smrg	fprintf(stderr,"Default interps not implemented yet!\n");
4118c9fbc29Smrg    else if (wantNames&XkmCompatMapMask)
4128c9fbc29Smrg	XkbWriteSectionFromName(file,"compatibility",name);
4138c9fbc29Smrg
4148c9fbc29Smrg    name= names->symbols;
4158c9fbc29Smrg    if (wantConfig&XkmSymbolsMask)
4168c9fbc29Smrg	XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name);
4178c9fbc29Smrg    else if (wantNames&XkmSymbolsMask)
4188c9fbc29Smrg	XkbWriteSectionFromName(file,"symbols",name);
4198c9fbc29Smrg
4208c9fbc29Smrg    name= names->geometry;
4218c9fbc29Smrg    if (wantConfig&XkmGeometryMask)
4228c9fbc29Smrg	XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name);
4238c9fbc29Smrg    else if (wantNames&XkmGeometryMask)
4248c9fbc29Smrg	XkbWriteSectionFromName(file,"geometry",name);
4258c9fbc29Smrg
4268c9fbc29Smrg    if (multi_section)
4278c9fbc29Smrg	fprintf(file,"};\n");
4288c9fbc29Smrg    return True;
4298c9fbc29Smrg}
4308c9fbc29Smrg
4318c9fbc29Smrg/***====================================================================***/
4328c9fbc29Smrg
4338c9fbc29Smrg/*ARGSUSED*/
4348c9fbc29SmrgStatus
4358c9fbc29SmrgXkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo)
4368c9fbc29Smrg{
4378c9fbc29Smrg    return BadImplementation;
4388c9fbc29Smrg}
4398c9fbc29Smrg
4408c9fbc29Smrg/***====================================================================***/
4418c9fbc29Smrg
4428c9fbc29Smrgint
4438c9fbc29SmrgXkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases)
4448c9fbc29Smrg{
4458c9fbc29Smrgregister int	i;
4468c9fbc29Smrg
4478c9fbc29Smrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys))
4488c9fbc29Smrg	return 0;
4498c9fbc29Smrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
4508c9fbc29Smrg	if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0)
4518c9fbc29Smrg	    return i;
4528c9fbc29Smrg    }
4538c9fbc29Smrg    if (!use_aliases)
4548c9fbc29Smrg	return 0;
4558c9fbc29Smrg    if (xkb->geom && xkb->geom->key_aliases) {
4568c9fbc29Smrg	XkbKeyAliasPtr	a;
4578c9fbc29Smrg	a= xkb->geom->key_aliases;
4588c9fbc29Smrg	for (i=0;i<xkb->geom->num_key_aliases;i++,a++) {
4598c9fbc29Smrg	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
4608c9fbc29Smrg		return XkbFindKeycodeByName(xkb,a->real,False);
4618c9fbc29Smrg	}
4628c9fbc29Smrg    }
4638c9fbc29Smrg    if (xkb->names && xkb->names->key_aliases) {
4648c9fbc29Smrg	XkbKeyAliasPtr	a;
4658c9fbc29Smrg	a= xkb->names->key_aliases;
4668c9fbc29Smrg	for (i=0;i<xkb->names->num_key_aliases;i++,a++) {
4678c9fbc29Smrg	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
4688c9fbc29Smrg		return XkbFindKeycodeByName(xkb,a->real,False);
4698c9fbc29Smrg	}
4708c9fbc29Smrg    }
4718c9fbc29Smrg    return 0;
4728c9fbc29Smrg}
4738c9fbc29Smrg
4748c9fbc29Smrg
4758c9fbc29Smrgunsigned
4768c9fbc29SmrgXkbConvertGetByNameComponents(Bool toXkm,unsigned orig)
4778c9fbc29Smrg{
4788c9fbc29Smrgunsigned	rtrn;
4798c9fbc29Smrg
4808c9fbc29Smrg    rtrn= 0;
4818c9fbc29Smrg    if (toXkm) {
4828c9fbc29Smrg	if (orig&XkbGBN_TypesMask)		rtrn|= XkmTypesMask;
4838c9fbc29Smrg	if (orig&XkbGBN_CompatMapMask)		rtrn|= XkmCompatMapMask;
4848c9fbc29Smrg	if (orig&XkbGBN_SymbolsMask)		rtrn|= XkmSymbolsMask;
4858c9fbc29Smrg	if (orig&XkbGBN_IndicatorMapMask)	rtrn|= XkmIndicatorsMask;
4868c9fbc29Smrg	if (orig&XkbGBN_KeyNamesMask)		rtrn|= XkmKeyNamesMask;
4878c9fbc29Smrg	if (orig&XkbGBN_GeometryMask)		rtrn|= XkmGeometryMask;
4888c9fbc29Smrg    }
4898c9fbc29Smrg    else {
4908c9fbc29Smrg	if (orig&XkmTypesMask)			rtrn|= XkbGBN_TypesMask;
4918c9fbc29Smrg	if (orig&XkmCompatMapMask)		rtrn|= XkbGBN_CompatMapMask;
4928c9fbc29Smrg	if (orig&XkmSymbolsMask)		rtrn|= XkbGBN_SymbolsMask;
4938c9fbc29Smrg	if (orig&XkmIndicatorsMask)		rtrn|= XkbGBN_IndicatorMapMask;
4948c9fbc29Smrg	if (orig&XkmKeyNamesMask)		rtrn|= XkbGBN_KeyNamesMask;
4958c9fbc29Smrg	if (orig&XkmGeometryMask)		rtrn|= XkbGBN_GeometryMask;
4968c9fbc29Smrg	if (orig!=0)				rtrn|= XkbGBN_OtherNamesMask;
4978c9fbc29Smrg    }
4988c9fbc29Smrg    return rtrn;
4998c9fbc29Smrg}
5008c9fbc29Smrg
5018c9fbc29Smrgunsigned
5028c9fbc29SmrgXkbConvertXkbComponents(Bool toXkm,unsigned orig)
5038c9fbc29Smrg{
5048c9fbc29Smrgunsigned	rtrn;
5058c9fbc29Smrg
5068c9fbc29Smrg    rtrn= 0;
5078c9fbc29Smrg    if (toXkm) {
5088c9fbc29Smrg	if (orig&XkbClientMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
5098c9fbc29Smrg	if (orig&XkbServerMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
5108c9fbc29Smrg	if (orig&XkbCompatMapMask)	rtrn|= XkmCompatMapMask;
5118c9fbc29Smrg	if (orig&XkbIndicatorMapMask)	rtrn|= XkmIndicatorsMask;
5128c9fbc29Smrg	if (orig&XkbNamesMask)		rtrn|= XkmKeyNamesMask;
5138c9fbc29Smrg	if (orig&XkbGeometryMask)	rtrn|= XkmGeometryMask;
5148c9fbc29Smrg    }
5158c9fbc29Smrg    else {
5168c9fbc29Smrg	if (orig!=0)			rtrn|= XkbNamesMask;
5178c9fbc29Smrg	if (orig&XkmTypesMask)		rtrn|= XkbClientMapMask;
5188c9fbc29Smrg	if (orig&XkmCompatMapMask)
5198c9fbc29Smrg		rtrn|= XkbCompatMapMask|XkbIndicatorMapMask;
5208c9fbc29Smrg	if (orig&XkmSymbolsMask)	rtrn|=XkbClientMapMask|XkbServerMapMask;
5218c9fbc29Smrg	if (orig&XkmIndicatorsMask)	rtrn|= XkbIndicatorMapMask;
5224cd6a3aeSmrg	if (orig&XkmKeyNamesMask)
5238c9fbc29Smrg		rtrn|= XkbNamesMask|XkbIndicatorMapMask;
5248c9fbc29Smrg	if (orig&XkmGeometryMask)	rtrn|= XkbGeometryMask;
5258c9fbc29Smrg    }
5268c9fbc29Smrg    return rtrn;
5278c9fbc29Smrg}
5288c9fbc29Smrg
5298c9fbc29SmrgBool
5308c9fbc29SmrgXkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing)
5318c9fbc29Smrg{
5328c9fbc29Smrgunsigned	present;
5338c9fbc29SmrgXkbDescPtr	xkb;
5348c9fbc29Smrg
5358c9fbc29Smrg    if ((!finfo)||(!finfo->xkb))
5368c9fbc29Smrg	return False;
5378c9fbc29Smrg    if (opts_missing)
5388c9fbc29Smrg	*opts_missing= 0;
5398c9fbc29Smrg    xkb= finfo->xkb;
5408c9fbc29Smrg    present= 0;
5418c9fbc29Smrg    if ((xkb->names)&&(xkb->names->keys))	present|= XkmKeyNamesMask;
5428c9fbc29Smrg    if ((xkb->map)&&(xkb->map->types))		present|= XkmTypesMask;
5438c9fbc29Smrg    if (xkb->compat)				present|= XkmCompatMapMask;
5448c9fbc29Smrg    if ((xkb->map)&&(xkb->map->num_syms>1))	present|= XkmSymbolsMask;
5458c9fbc29Smrg    if (xkb->indicators)			present|= XkmIndicatorsMask;
5468c9fbc29Smrg    if (xkb->geom)				present|= XkmGeometryMask;
5478c9fbc29Smrg    if (!present)
5488c9fbc29Smrg	return False;
5498c9fbc29Smrg    else switch (present) {
5504cd6a3aeSmrg	case XkmKeyNamesMask:
5518c9fbc29Smrg	    finfo->type= 	XkmKeyNamesIndex;
5528c9fbc29Smrg	    finfo->defined= 	present;
5538c9fbc29Smrg	    return True;
5548c9fbc29Smrg	case XkmTypesMask:
5558c9fbc29Smrg	    finfo->type=	XkmTypesIndex;
5568c9fbc29Smrg	    finfo->defined= 	present;
5578c9fbc29Smrg	    return True;
5584cd6a3aeSmrg	case XkmCompatMapMask:
5598c9fbc29Smrg	    finfo->type=	XkmCompatMapIndex;
5608c9fbc29Smrg	    finfo->defined=	present;
5618c9fbc29Smrg	    return True;
5624cd6a3aeSmrg	case XkmSymbolsMask:
5638c9fbc29Smrg	    if (format!=XkbXKMFile) {
5648c9fbc29Smrg		finfo->type= 	XkmSymbolsIndex;
5658c9fbc29Smrg		finfo->defined=	present;
5668c9fbc29Smrg		return True;
5678c9fbc29Smrg	    }
5688c9fbc29Smrg	    break;
5694cd6a3aeSmrg	case XkmGeometryMask:
5708c9fbc29Smrg	    finfo->type=	XkmGeometryIndex;
5718c9fbc29Smrg	    finfo->defined=	present;
5728c9fbc29Smrg	    return True;
5738c9fbc29Smrg    }
5748c9fbc29Smrg    if ((present&(~XkmSemanticsLegal))==0) {
5758c9fbc29Smrg	if ((XkmSemanticsRequired&present)==XkmSemanticsRequired) {
5768c9fbc29Smrg	    if (opts_missing)
5778c9fbc29Smrg		*opts_missing= XkmSemanticsOptional&(~present);
5788c9fbc29Smrg	    finfo->type= 	XkmSemanticsFile;
5798c9fbc29Smrg	    finfo->defined=	present;
5808c9fbc29Smrg	    return True;
5818c9fbc29Smrg	}
5828c9fbc29Smrg    }
5838c9fbc29Smrg    else if ((present&(~XkmLayoutLegal))==0) {
5848c9fbc29Smrg	if ((XkmLayoutRequired&present)==XkmLayoutRequired) {
5858c9fbc29Smrg	    if (opts_missing)
5868c9fbc29Smrg		*opts_missing= XkmLayoutOptional&(~present);
5878c9fbc29Smrg	    finfo->type=	XkmLayoutFile;
5888c9fbc29Smrg	    finfo->defined=	present;
5898c9fbc29Smrg	    return True;
5908c9fbc29Smrg	}
5918c9fbc29Smrg    }
5928c9fbc29Smrg    else if ((present&(~XkmKeymapLegal))==0) {
5938c9fbc29Smrg	if ((XkmKeymapRequired&present)==XkmKeymapRequired) {
5948c9fbc29Smrg	    if (opts_missing)
5958c9fbc29Smrg		*opts_missing= XkmKeymapOptional&(~present);
5968c9fbc29Smrg	    finfo->type=	XkmKeymapFile;
5978c9fbc29Smrg	    finfo->defined=	present;
5988c9fbc29Smrg	    return True;
5998c9fbc29Smrg	}
6008c9fbc29Smrg    }
6018c9fbc29Smrg    return False;
6028c9fbc29Smrg}
6038c9fbc29Smrg
6048c9fbc29Smrg/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */
6058c9fbc29Smrg/* wildcards */
6068c9fbc29Smrg
6078c9fbc29Smrgstatic unsigned char componentSpecLegal[] = {
6088c9fbc29Smrg	0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
6098c9fbc29Smrg	0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
6108c9fbc29Smrg	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6118c9fbc29Smrg	0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
6128c9fbc29Smrg};
6138c9fbc29Smrg
6148c9fbc29Smrgvoid
6158c9fbc29SmrgXkbEnsureSafeMapName(char *name)
6168c9fbc29Smrg{
6178c9fbc29Smrg   if (name==NULL)
6188c9fbc29Smrg        return;
6198c9fbc29Smrg    while (*name!='\0') {
6208c9fbc29Smrg	if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0)
6218c9fbc29Smrg	    *name= '_';
6228c9fbc29Smrg        name++;
6238c9fbc29Smrg    }
6248c9fbc29Smrg    return;
6258c9fbc29Smrg}
6268c9fbc29Smrg
6278c9fbc29Smrg/***====================================================================***/
6288c9fbc29Smrg
6298c9fbc29Smrg#define	UNMATCHABLE(c)	(((c)=='(')||((c)==')')||((c)=='/'))
6308c9fbc29Smrg
6318c9fbc29SmrgBool
6328c9fbc29SmrgXkbNameMatchesPattern(char *name,char *ptrn)
6338c9fbc29Smrg{
6348c9fbc29Smrg    while (ptrn[0]!='\0') {
6358c9fbc29Smrg	if (name[0]=='\0') {
6368c9fbc29Smrg	    if (ptrn[0]=='*') {
6378c9fbc29Smrg		ptrn++;
6388c9fbc29Smrg		continue;
6398c9fbc29Smrg	    }
6408c9fbc29Smrg	    return False;
6418c9fbc29Smrg	}
6428c9fbc29Smrg	if (ptrn[0]=='?') {
6438c9fbc29Smrg	    if (UNMATCHABLE(name[0]))
6448c9fbc29Smrg		return False;
6458c9fbc29Smrg	}
6468c9fbc29Smrg	else if (ptrn[0]=='*') {
6478c9fbc29Smrg	    if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn))
6488c9fbc29Smrg		return True;
6498c9fbc29Smrg	    return XkbNameMatchesPattern(name,ptrn+1);
6508c9fbc29Smrg	}
6518c9fbc29Smrg	else if (ptrn[0]!=name[0])
6528c9fbc29Smrg	    return False;
6538c9fbc29Smrg	name++;
6548c9fbc29Smrg	ptrn++;
6558c9fbc29Smrg    }
6568c9fbc29Smrg    /* if we get here, the pattern is exhausted (-:just like me:-) */
6578c9fbc29Smrg    return (name[0]=='\0');
6588c9fbc29Smrg}
6598c9fbc29Smrg
6608c9fbc29Smrg#ifdef NEED_STRCASECMP
6618c9fbc29Smrg_X_HIDDEN int
6628c9fbc29Smrg_XkbStrCaseCmp(char *str1,char *str2)
6638c9fbc29Smrg{
6648c9fbc29Smrg    const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2;
6654cd6a3aeSmrg
6668c9fbc29Smrg    while (tolower(*us1) == tolower(*us2)) {
6678c9fbc29Smrg        if (*us1++ == '\0')
6688c9fbc29Smrg            return (0);
6698c9fbc29Smrg        us2++;
6708c9fbc29Smrg    }
6718c9fbc29Smrg
6728c9fbc29Smrg    return (tolower(*us1) - tolower(*us2));
6738c9fbc29Smrg}
6748c9fbc29Smrg#endif
675