782 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			782 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
| /************************************************************
 | |
| Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this
 | |
| software and its documentation for any purpose and without
 | |
| fee is hereby granted, provided that the above copyright
 | |
| notice appear in all copies and that both that copyright
 | |
| notice and this permission notice appear in supporting
 | |
| documentation, and that the name of Silicon Graphics not be 
 | |
| used in advertising or publicity pertaining to distribution 
 | |
| of the software without specific prior written permission.
 | |
| Silicon Graphics makes no representation about the suitability 
 | |
| of this software for any purpose. It is provided "as is"
 | |
| without any express or implied warranty.
 | |
| 
 | |
| SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
 | |
| SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
 | |
| AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | |
| GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
 | |
| DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
 | |
| DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
 | |
| OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 | |
| THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | |
| 
 | |
| ********************************************************/
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_XKB_CONFIG_H
 | |
| #include <xkb-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| #include <unistd.h>
 | |
| #include <math.h>
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #include <X11/keysym.h>
 | |
| #include <X11/Xatom.h>
 | |
| #include "misc.h"
 | |
| #include "inputstr.h"
 | |
| #include "opaque.h"
 | |
| #include "property.h"
 | |
| #define	XKBSRV_NEED_FILE_FUNCS
 | |
| #include <xkbsrv.h>
 | |
| #include "xkbgeom.h"
 | |
| #include <X11/extensions/XKMformat.h>
 | |
| #include "xkbfile.h"
 | |
| #include "xkb.h"
 | |
| 
 | |
| #define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
 | |
| 
 | |
| #if defined(__alpha) || defined(__alpha__)
 | |
| #define	LED_COMPOSE	2
 | |
| #define LED_CAPS	3
 | |
| #define	LED_SCROLL	4
 | |
| #define	LED_NUM		5
 | |
| #define	PHYS_LEDS	0x1f
 | |
| #else
 | |
| #ifdef sun
 | |
| #define LED_NUM		1
 | |
| #define	LED_SCROLL	2
 | |
| #define	LED_COMPOSE	3
 | |
| #define LED_CAPS	4
 | |
| #define	PHYS_LEDS	0x0f
 | |
| #else
 | |
| #define	LED_CAPS	1
 | |
| #define	LED_NUM		2
 | |
| #define	LED_SCROLL	3
 | |
| #define	PHYS_LEDS	0x07
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #define	MAX_TOC	16
 | |
| typedef struct	_SrvXkmInfo {
 | |
| 	DeviceIntPtr	dev;
 | |
| 	FILE *		file;
 | |
| 	XkbDescPtr	xkb;
 | |
| } SrvXkmInfo;
 | |
| 
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| #ifndef XKB_DFLT_RULES_PROP
 | |
| #define	XKB_DFLT_RULES_PROP	True
 | |
| #endif
 | |
| 
 | |
| char	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
 | |
| char	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
 | |
| static int	 	XkbWantAccessX=		0;	
 | |
| 
 | |
| static char *		XkbRulesDflt=		NULL;
 | |
| static char *		XkbModelDflt=		NULL;
 | |
| static char *		XkbLayoutDflt=		NULL;
 | |
| static char *		XkbVariantDflt=		NULL;
 | |
| static char *		XkbOptionsDflt=		NULL;
 | |
| 
 | |
| static char *           XkbRulesUsed=   NULL;
 | |
| static char *		XkbModelUsed=	NULL;
 | |
| static char *		XkbLayoutUsed=	NULL;
 | |
| static char *		XkbVariantUsed=	NULL;
 | |
| static char *		XkbOptionsUsed=	NULL;
 | |
| 
 | |
| static XkbDescPtr	xkb_cached_map = NULL;
 | |
| 
 | |
| static Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| /**
 | |
|  * Get the current default XKB rules.
 | |
|  * Caller must free the data in rmlvo.
 | |
|  */
 | |
| void
 | |
| XkbGetRulesDflts(XkbRMLVOSet *rmlvo)
 | |
| {
 | |
|     if (XkbRulesDflt)   rmlvo->rules = XkbRulesDflt;
 | |
|     else                rmlvo->rules = XKB_DFLT_RULES;
 | |
|     if (XkbModelDflt)	rmlvo->model= XkbModelDflt;
 | |
|     else		rmlvo->model= XKB_DFLT_MODEL;
 | |
|     if (XkbLayoutDflt)	rmlvo->layout= XkbLayoutDflt;
 | |
|     else		rmlvo->layout= XKB_DFLT_LAYOUT;
 | |
|     if (XkbVariantDflt)	rmlvo->variant= XkbVariantDflt;
 | |
|     else		rmlvo->variant= XKB_DFLT_VARIANT;
 | |
|     if (XkbOptionsDflt)	rmlvo->options= XkbOptionsDflt;
 | |
|     else		rmlvo->options= XKB_DFLT_OPTIONS;
 | |
| 
 | |
|     rmlvo->rules = strdup(rmlvo->rules);
 | |
|     rmlvo->model = strdup(rmlvo->model);
 | |
|     rmlvo->layout = strdup(rmlvo->layout);
 | |
|     rmlvo->variant = strdup(rmlvo->variant);
 | |
|     rmlvo->options = strdup(rmlvo->options);
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbFreeRMLVOSet(XkbRMLVOSet *rmlvo, Bool freeRMLVO)
 | |
| {
 | |
|     if (!rmlvo)
 | |
|         return;
 | |
| 
 | |
|     xfree(rmlvo->rules);
 | |
|     xfree(rmlvo->model);
 | |
|     xfree(rmlvo->layout);
 | |
|     xfree(rmlvo->variant);
 | |
|     xfree(rmlvo->options);
 | |
| 
 | |
|     if (freeRMLVO)
 | |
|         xfree(rmlvo);
 | |
|     else
 | |
|         memset(rmlvo, 0, sizeof(XkbRMLVOSet));
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| XkbWriteRulesProp(ClientPtr client, pointer closure)
 | |
| {
 | |
| int 			len,out;
 | |
| Atom			name;
 | |
| char *			pval;
 | |
| 
 | |
|     len= (XkbRulesUsed?strlen(XkbRulesUsed):0);
 | |
|     len+= (XkbModelUsed?strlen(XkbModelUsed):0);
 | |
|     len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
 | |
|     len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
 | |
|     len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
 | |
|     if (len<1)
 | |
| 	return True;
 | |
| 
 | |
|     len+= 5; /* trailing NULs */
 | |
| 
 | |
|     name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
 | |
|     if (name==None) {
 | |
| 	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
 | |
| 	return True;
 | |
|     }
 | |
|     pval= (char*) xalloc(len);
 | |
|     if (!pval) {
 | |
| 	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
 | |
| 						_XKB_RF_NAMES_PROP_ATOM);
 | |
| 	return True;
 | |
|     }
 | |
|     out= 0;
 | |
|     if (XkbRulesUsed) {
 | |
| 	strcpy(&pval[out],XkbRulesUsed);
 | |
| 	out+= strlen(XkbRulesUsed);
 | |
|     }
 | |
|     pval[out++]= '\0';
 | |
|     if (XkbModelUsed) {
 | |
| 	strcpy(&pval[out],XkbModelUsed);
 | |
| 	out+= strlen(XkbModelUsed);
 | |
|     } 
 | |
|     pval[out++]= '\0';
 | |
|     if (XkbLayoutUsed) {
 | |
| 	strcpy(&pval[out],XkbLayoutUsed);
 | |
| 	out+= strlen(XkbLayoutUsed);
 | |
|     }
 | |
|     pval[out++]= '\0';
 | |
|     if (XkbVariantUsed) {
 | |
| 	strcpy(&pval[out],XkbVariantUsed);
 | |
| 	out+= strlen(XkbVariantUsed);
 | |
|     }
 | |
|     pval[out++]= '\0';
 | |
|     if (XkbOptionsUsed) {
 | |
| 	strcpy(&pval[out],XkbOptionsUsed);
 | |
| 	out+= strlen(XkbOptionsUsed);
 | |
|     }
 | |
|     pval[out++]= '\0';
 | |
|     if (out!=len) {
 | |
| 	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
 | |
| 								out,len);
 | |
|     }
 | |
|     dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
 | |
| 			    PropModeReplace, len, pval, True);
 | |
|     xfree(pval);
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static void
 | |
| XkbSetRulesUsed(XkbRMLVOSet *rmlvo)
 | |
| {
 | |
|     if (XkbRulesUsed)
 | |
|         xfree(XkbRulesUsed);
 | |
|     XkbRulesUsed= (rmlvo->rules?_XkbDupString(rmlvo->rules):NULL);
 | |
|     if (XkbModelUsed)
 | |
| 	xfree(XkbModelUsed);
 | |
|     XkbModelUsed= (rmlvo->model?_XkbDupString(rmlvo->model):NULL);
 | |
|     if (XkbLayoutUsed)
 | |
| 	xfree(XkbLayoutUsed);
 | |
|     XkbLayoutUsed= (rmlvo->layout?_XkbDupString(rmlvo->layout):NULL);
 | |
|     if (XkbVariantUsed)
 | |
| 	xfree(XkbVariantUsed);
 | |
|     XkbVariantUsed= (rmlvo->variant?_XkbDupString(rmlvo->variant):NULL);
 | |
|     if (XkbOptionsUsed)
 | |
| 	xfree(XkbOptionsUsed);
 | |
|     XkbOptionsUsed= (rmlvo->options?_XkbDupString(rmlvo->options):NULL);
 | |
|     if (XkbWantRulesProp)
 | |
| 	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbSetRulesDflts(XkbRMLVOSet *rmlvo)
 | |
| {
 | |
|     if (rmlvo->rules) {
 | |
|         if (XkbRulesDflt)
 | |
| 	    xfree(XkbRulesDflt);
 | |
|         XkbRulesDflt= _XkbDupString(rmlvo->rules);
 | |
|     }
 | |
|     if (rmlvo->model) {
 | |
| 	if (XkbModelDflt)
 | |
| 	    xfree(XkbModelDflt);
 | |
| 	XkbModelDflt= _XkbDupString(rmlvo->model);
 | |
|     }
 | |
|     if (rmlvo->layout) {
 | |
| 	if (XkbLayoutDflt)
 | |
| 	    xfree(XkbLayoutDflt);
 | |
| 	XkbLayoutDflt= _XkbDupString(rmlvo->layout);
 | |
|     }
 | |
|     if (rmlvo->variant) {
 | |
| 	if (XkbVariantDflt)
 | |
| 	    xfree(XkbVariantDflt);
 | |
| 	XkbVariantDflt= _XkbDupString(rmlvo->variant);
 | |
|     }
 | |
|     if (rmlvo->options) {
 | |
| 	if (XkbOptionsDflt)
 | |
| 	    xfree(XkbOptionsDflt);
 | |
| 	XkbOptionsDflt= _XkbDupString(rmlvo->options);
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbDeleteRulesDflts(void)
 | |
| {
 | |
|     xfree(XkbRulesDflt);
 | |
|     XkbRulesDflt = NULL;
 | |
|     xfree(XkbModelDflt);
 | |
|     XkbModelDflt = NULL;
 | |
|     xfree(XkbLayoutDflt);
 | |
|     XkbLayoutDflt = NULL;
 | |
|     xfree(XkbVariantDflt);
 | |
|     XkbVariantDflt = NULL;
 | |
|     xfree(XkbOptionsDflt);
 | |
|     XkbOptionsDflt = NULL;
 | |
| 
 | |
|     XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True);
 | |
|     xkb_cached_map = NULL;
 | |
| }
 | |
| 
 | |
| #define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
 | |
| 
 | |
| static Bool
 | |
| XkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo)
 | |
| {
 | |
|     if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
 | |
|         DIFFERS(rmlvo->model, XkbModelUsed) ||
 | |
|         DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
 | |
|         DIFFERS(rmlvo->variant, XkbVariantUsed) ||
 | |
|         DIFFERS(rmlvo->options, XkbOptionsUsed))
 | |
|         return FALSE;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| #undef DIFFERS
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| #include "xkbDflts.h"
 | |
| 
 | |
| static Bool
 | |
| XkbInitKeyTypes(XkbDescPtr xkb)
 | |
| {
 | |
|     if (xkb->defined & XkmTypesMask)
 | |
|         return True;
 | |
| 
 | |
|     initTypeNames(NULL);
 | |
|     if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
 | |
| 	return False;
 | |
|     if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
 | |
|     								 Success) {
 | |
| 	return False;
 | |
|     }
 | |
|     xkb->map->size_types= xkb->map->num_types= num_dflt_types;
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static void
 | |
| XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
 | |
| {
 | |
|     xkbi->nRadioGroups = 0;
 | |
|     xkbi->radioGroups = NULL;
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| static Status
 | |
| XkbInitCompatStructs(XkbDescPtr xkb)
 | |
| {
 | |
| register int 	i;
 | |
| XkbCompatMapPtr	compat;
 | |
| 
 | |
|     if (xkb->defined & XkmCompatMapMask)
 | |
|         return True;
 | |
| 
 | |
|     if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
 | |
| 	return BadAlloc;
 | |
|     compat = xkb->compat;
 | |
|     if (compat->sym_interpret) {
 | |
| 	compat->num_si = num_dfltSI;
 | |
| 	memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
 | |
|     }
 | |
|     for (i=0;i<XkbNumKbdGroups;i++) {
 | |
| 	compat->groups[i]= compatMap.groups[i];
 | |
| 	if (compat->groups[i].vmods!=0) {
 | |
| 	    unsigned mask;
 | |
| 	    mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
 | |
| 	    compat->groups[i].mask= compat->groups[i].real_mods|mask;
 | |
| 	}
 | |
| 	else compat->groups[i].mask= compat->groups[i].real_mods;
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| XkbInitSemantics(XkbDescPtr xkb)
 | |
| {
 | |
|     XkbInitKeyTypes(xkb);
 | |
|     XkbInitCompatStructs(xkb);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| static Status
 | |
| XkbInitNames(XkbSrvInfoPtr xkbi)
 | |
| {
 | |
| XkbDescPtr	xkb;
 | |
| XkbNamesPtr	names;
 | |
| Status		rtrn;
 | |
| Atom		unknown;
 | |
| 
 | |
|     xkb= xkbi->desc;
 | |
|     if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
 | |
| 	return rtrn;
 | |
|     unknown= CREATE_ATOM("unknown");
 | |
|     names = xkb->names;
 | |
|     if (names->keycodes==None)		names->keycodes= unknown;
 | |
|     if (names->geometry==None)		names->geometry= unknown;
 | |
|     if (names->phys_symbols==None)	names->phys_symbols= unknown;
 | |
|     if (names->symbols==None)		names->symbols= unknown;
 | |
|     if (names->types==None)		names->types= unknown;
 | |
|     if (names->compat==None)		names->compat= unknown;
 | |
|     if (!(xkb->defined & XkmVirtualModsMask)) {
 | |
|         if (names->vmods[vmod_NumLock]==None)
 | |
|             names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
 | |
|         if (names->vmods[vmod_Alt]==None)
 | |
|             names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
 | |
|         if (names->vmods[vmod_AltGr]==None)
 | |
|             names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
 | |
|     }
 | |
| 
 | |
|     if (!(xkb->defined & XkmIndicatorsMask) ||
 | |
|         !(xkb->defined & XkmGeometryMask)) {
 | |
|         initIndicatorNames(NULL,xkb);
 | |
|         if (names->indicators[LED_CAPS-1]==None)
 | |
|             names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
 | |
|         if (names->indicators[LED_NUM-1]==None)
 | |
|             names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
 | |
|         if (names->indicators[LED_SCROLL-1]==None)
 | |
|             names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
 | |
| #ifdef LED_COMPOSE
 | |
|         if (names->indicators[LED_COMPOSE-1]==None)
 | |
|             names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
 | |
| #endif
 | |
|     }
 | |
| 
 | |
|     if (xkb->geom!=NULL)
 | |
| 	 names->geometry= xkb->geom->name;
 | |
|     else names->geometry= unknown;
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static Status
 | |
| XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
 | |
| {
 | |
| XkbDescPtr		xkb;
 | |
| XkbIndicatorPtr		map;
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| 
 | |
|     xkb= xkbi->desc;
 | |
|     if (XkbAllocIndicatorMaps(xkb)!=Success)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     if (!(xkb->defined & XkmIndicatorsMask)) {
 | |
|         map= xkb->indicators;
 | |
|         map->phys_indicators = PHYS_LEDS;
 | |
|         map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
 | |
|         map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
 | |
|         map->maps[LED_CAPS-1].mods.mask= LockMask;
 | |
|         map->maps[LED_CAPS-1].mods.real_mods= LockMask;
 | |
| 
 | |
|         map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
 | |
|         map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
 | |
|         map->maps[LED_NUM-1].mods.mask= 0;
 | |
|         map->maps[LED_NUM-1].mods.real_mods= 0;
 | |
|         map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
 | |
| 
 | |
|         map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
 | |
|         map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
 | |
|         map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
 | |
|         map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
 | |
|     }
 | |
| 
 | |
|     sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
 | |
|     if (sli)
 | |
| 	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static Status
 | |
| XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
 | |
| {
 | |
| XkbDescPtr	xkb;
 | |
| XkbControlsPtr	ctrls;
 | |
| 
 | |
|     xkb= xkbi->desc;
 | |
|     /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
 | |
|     if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
 | |
| 	FatalError("Couldn't allocate keyboard controls\n");
 | |
|     ctrls= xkb->ctrls;
 | |
|     if (!(xkb->defined & XkmSymbolsMask))
 | |
|         ctrls->num_groups = 1;
 | |
|     ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
 | |
|     ctrls->internal.mask = 0;
 | |
|     ctrls->internal.real_mods = 0;
 | |
|     ctrls->internal.vmods = 0;
 | |
|     ctrls->ignore_lock.mask = 0;
 | |
|     ctrls->ignore_lock.real_mods = 0;
 | |
|     ctrls->ignore_lock.vmods = 0;
 | |
|     ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
 | |
| 				XkbMouseKeysAccelMask|XkbAudibleBellMask|
 | |
| 				XkbIgnoreGroupLockMask;
 | |
|     if (XkbWantAccessX)
 | |
| 	ctrls->enabled_ctrls|= XkbAccessXKeysMask;
 | |
|     AccessXInit(pXDev);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| _X_EXPORT Bool
 | |
| InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo,
 | |
|                          BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
 | |
| {
 | |
|     int	i;
 | |
|     unsigned int check;
 | |
|     XkbSrvInfoPtr xkbi;
 | |
|     XkbDescPtr xkb;
 | |
|     XkbSrvLedInfoPtr sli;
 | |
|     XkbChangesRec changes;
 | |
|     XkbEventCauseRec cause;
 | |
|     XkbRMLVOSet rmlvo_dflts = { NULL };
 | |
| 
 | |
|     if (dev->key || dev->kbdfeed)
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (!rmlvo)
 | |
|     {
 | |
|         rmlvo = &rmlvo_dflts;
 | |
|         XkbGetRulesDflts(rmlvo);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     memset(&changes, 0, sizeof(changes));
 | |
|     XkbSetCauseUnknown(&cause);
 | |
| 
 | |
|     dev->key = xcalloc(1, sizeof(*dev->key));
 | |
|     if (!dev->key) {
 | |
|         ErrorF("XKB: Failed to allocate key class\n");
 | |
|         return False;
 | |
|     }
 | |
|     dev->key->sourceid = dev->id;
 | |
| 
 | |
|     dev->kbdfeed = xcalloc(1, sizeof(*dev->kbdfeed));
 | |
|     if (!dev->kbdfeed) {
 | |
|         ErrorF("XKB: Failed to allocate key feedback class\n");
 | |
|         goto unwind_key;
 | |
|     }
 | |
| 
 | |
|     xkbi = xcalloc(1, sizeof(*xkbi));
 | |
|     if (!xkbi) {
 | |
|         ErrorF("XKB: Failed to allocate XKB info\n");
 | |
|         goto unwind_kbdfeed;
 | |
|     }
 | |
|     dev->key->xkbInfo = xkbi;
 | |
| 
 | |
|     if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
 | |
|         XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True);
 | |
|         xkb_cached_map = NULL;
 | |
|     }
 | |
| 
 | |
|     if (xkb_cached_map)
 | |
|         LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
 | |
|     else {
 | |
|         xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
 | |
|         if (!xkb_cached_map) {
 | |
|             ErrorF("XKB: Failed to compile keymap\n");
 | |
|             goto unwind_info;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     xkb = XkbAllocKeyboard();
 | |
|     if (!xkb) {
 | |
|         ErrorF("XKB: Failed to allocate keyboard description\n");
 | |
|         goto unwind_info;
 | |
|     }
 | |
| 
 | |
|     if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
 | |
|         ErrorF("XKB: Failed to copy keymap\n");
 | |
|         goto unwind_desc;
 | |
|     }
 | |
|     xkb->defined = xkb_cached_map->defined;
 | |
|     xkb->flags = xkb_cached_map->flags;
 | |
|     xkb->device_spec = xkb_cached_map->device_spec;
 | |
|     xkbi->desc = xkb;
 | |
| 
 | |
|     if (xkb->min_key_code == 0)
 | |
|         xkb->min_key_code = 8;
 | |
|     if (xkb->max_key_code == 0)
 | |
|         xkb->max_key_code = 255;
 | |
| 
 | |
|     i = XkbNumKeys(xkb) / 3 + 1;
 | |
|     if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
 | |
|         goto unwind_desc;
 | |
|     if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
 | |
|         goto unwind_desc;
 | |
| 
 | |
|     xkbi->dfltPtrDelta = 1;
 | |
|     xkbi->device = dev;
 | |
| 
 | |
|     XkbInitSemantics(xkb);
 | |
|     XkbInitNames(xkbi);
 | |
|     XkbInitRadioGroups(xkbi);
 | |
| 
 | |
|     XkbInitControls(dev, xkbi);
 | |
| 
 | |
|     XkbInitIndicatorMap(xkbi);
 | |
| 
 | |
|     XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
 | |
|                      &check, &cause);
 | |
| 
 | |
|     InitFocusClassDeviceStruct(dev);
 | |
| 
 | |
|     xkbi->kbdProc = ctrl_func;
 | |
|     dev->kbdfeed->BellProc = bell_func;
 | |
|     dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
 | |
| 
 | |
|     dev->kbdfeed->ctrl = defaultKeyboardControl;
 | |
|     if (dev->kbdfeed->ctrl.autoRepeat)
 | |
|         xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
 | |
| 
 | |
|     memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
 | |
|            XkbPerKeyBitArraySize);
 | |
| 
 | |
|     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
 | |
|     if (sli)
 | |
| 	XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
 | |
|     else
 | |
|         DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
 | |
| 
 | |
|     dev->kbdfeed->CtrlProc(dev,&dev->kbdfeed->ctrl);
 | |
| 
 | |
|     XkbSetRulesDflts(rmlvo);
 | |
|     XkbSetRulesUsed(rmlvo);
 | |
|     XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
 | |
| 
 | |
|     return TRUE;
 | |
| 
 | |
| unwind_desc:
 | |
|     XkbFreeKeyboard(xkb, 0, TRUE);
 | |
| unwind_info:
 | |
|     xfree(xkbi);
 | |
|     dev->key->xkbInfo = NULL;
 | |
| unwind_kbdfeed:
 | |
|     xfree(dev->kbdfeed);
 | |
|     dev->kbdfeed = NULL;
 | |
| unwind_key:
 | |
|     xfree(dev->key);
 | |
|     dev->key = NULL;
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * Be very careful about what does and doesn't get freed by this 
 | |
| 	 * function.  To reduce fragmentation, XkbInitDevice allocates a 
 | |
| 	 * single huge block per device and divides it up into most of the 
 | |
| 	 * fixed-size structures for the device.   Don't free anything that
 | |
| 	 * is part of this larger block.
 | |
| 	 */
 | |
| void
 | |
| XkbFreeInfo(XkbSrvInfoPtr xkbi)
 | |
| {
 | |
|     if (xkbi->radioGroups) {
 | |
| 	xfree(xkbi->radioGroups);
 | |
| 	xkbi->radioGroups= NULL;
 | |
|     }
 | |
|     if (xkbi->mouseKeyTimer) {
 | |
| 	TimerFree(xkbi->mouseKeyTimer);
 | |
| 	xkbi->mouseKeyTimer= NULL;
 | |
|     }
 | |
|     if (xkbi->slowKeysTimer) {
 | |
| 	TimerFree(xkbi->slowKeysTimer);
 | |
| 	xkbi->slowKeysTimer= NULL;
 | |
|     }
 | |
|     if (xkbi->bounceKeysTimer) {
 | |
| 	TimerFree(xkbi->bounceKeysTimer);
 | |
| 	xkbi->bounceKeysTimer= NULL;
 | |
|     }
 | |
|     if (xkbi->repeatKeyTimer) {
 | |
| 	TimerFree(xkbi->repeatKeyTimer);
 | |
| 	xkbi->repeatKeyTimer= NULL;
 | |
|     }
 | |
|     if (xkbi->krgTimer) {
 | |
| 	TimerFree(xkbi->krgTimer);
 | |
| 	xkbi->krgTimer= NULL;
 | |
|     }
 | |
|     xkbi->beepType= _BEEP_NONE;
 | |
|     if (xkbi->beepTimer) {
 | |
| 	TimerFree(xkbi->beepTimer);
 | |
| 	xkbi->beepTimer= NULL;
 | |
|     }
 | |
|     if (xkbi->desc) {
 | |
| 	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
 | |
| 	xkbi->desc= NULL;
 | |
|     }
 | |
|     xfree(xkbi);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| extern int	XkbDfltRepeatDelay;
 | |
| extern int	XkbDfltRepeatInterval;
 | |
| 
 | |
| extern unsigned short	XkbDfltAccessXTimeout;
 | |
| extern unsigned int	XkbDfltAccessXTimeoutMask;
 | |
| extern unsigned int	XkbDfltAccessXFeedback;
 | |
| extern unsigned char	XkbDfltAccessXOptions;
 | |
| 
 | |
| int
 | |
| XkbProcessArguments(int argc,char *argv[],int i)
 | |
| {
 | |
|     if (strncmp(argv[i], "-xkbdir", 7) == 0) {
 | |
| 	if(++i < argc) {
 | |
| #if !defined(WIN32) && !defined(__CYGWIN__)
 | |
| 	    if (getuid() != geteuid()) {
 | |
| 		LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
 | |
| 		return -1;
 | |
| 	    } else
 | |
| #endif
 | |
| 	    {
 | |
| 		if (strlen(argv[i]) < PATH_MAX) {
 | |
| 		    XkbBaseDirectory= argv[i];
 | |
| 		    return 2;
 | |
| 	        } else {
 | |
| 		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
 | |
| 		    return -1;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	else {
 | |
| 	    return -1;
 | |
| 	}
 | |
|     }
 | |
|     else if ((strncmp(argv[i],"-accessx",8)==0)||
 | |
|                  (strncmp(argv[i],"+accessx",8)==0)) {
 | |
| 	int j=1;	    
 | |
| 	if (argv[i][0]=='-')        
 | |
| 	    XkbWantAccessX= 0;
 | |
| 	else {
 | |
| 	    XkbWantAccessX= 1;
 | |
| 	    
 | |
| 	    if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
 | |
| 		XkbDfltAccessXTimeout = atoi(argv[++i]);
 | |
| 		j++;
 | |
| 
 | |
| 		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
 | |
| 		    /*
 | |
| 		     * presumption that the reasonably useful range of
 | |
| 		     * values fits in 0..MAXINT since SunOS 4 doesn't
 | |
| 		     * have strtoul.
 | |
| 		     */
 | |
| 		    XkbDfltAccessXTimeoutMask=(unsigned int)
 | |
| 					      strtol(argv[++i],NULL,16); 
 | |
| 		    j++;
 | |
| 		}
 | |
| 		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
 | |
| 		    if (argv[++i][0] == '1' ) 
 | |
| 			XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
 | |
| 		    else
 | |
| 			XkbDfltAccessXFeedback=0;
 | |
| 		    j++;
 | |
| 		}
 | |
| 		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
 | |
| 		    XkbDfltAccessXOptions=(unsigned char)
 | |
| 					   strtol(argv[++i],NULL,16);
 | |
| 		    j++;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	return j;
 | |
|     }
 | |
|     if ((strcmp(argv[i], "-ardelay") == 0) ||
 | |
|         (strcmp (argv[i], "-ar1") == 0)) {	/* -ardelay int */
 | |
| 	if (++i >= argc) UseMsg ();
 | |
| 	XkbDfltRepeatDelay = (long)atoi(argv[i]);
 | |
| 	return 2;
 | |
|     }
 | |
|     if ((strcmp(argv[i], "-arinterval") == 0) ||
 | |
|         (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
 | |
| 	if (++i >= argc) UseMsg ();
 | |
| 	XkbDfltRepeatInterval = (long)atoi(argv[i]);
 | |
| 	return 2;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbUseMsg(void)
 | |
| {
 | |
|     ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
 | |
|     ErrorF("                       enable/disable accessx key sequences\n");
 | |
|     ErrorF("-ardelay               set XKB autorepeat delay\n");
 | |
|     ErrorF("-arinterval            set XKB autorepeat interval\n");
 | |
| }
 |