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