diff options
Diffstat (limited to 'xkb')
36 files changed, 29431 insertions, 0 deletions
diff --git a/xkb/README.compiled b/xkb/README.compiled new file mode 100644 index 000000000..71caa2f63 --- /dev/null +++ b/xkb/README.compiled @@ -0,0 +1,13 @@ + +The X server uses this directory to store the compiled version of the +current keymap and/or any scratch keymaps used by clients. The X server +or some other tool might destroy or replace the files in this directory, +so it is not a safe place to store compiled keymaps for long periods of +time. The default keymap for any server is usually stored in: + X<num>-default.xkm +where <num> is the display number of the server in question, which makes +it possible for several servers *on the same host* to share the same +directory. + +Unless the X server is modified, sharing this directory between servers on +different hosts could cause problems. diff --git a/xkb/XKBAlloc.c b/xkb/XKBAlloc.c new file mode 100644 index 000000000..82e98f4bc --- /dev/null +++ b/xkb/XKBAlloc.c @@ -0,0 +1,587 @@ +/* $Xorg: XKBAlloc.c,v 1.4 2000/08/17 19:44:59 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include "XKBlibint.h" +#include <X11/extensions/XKBgeom.h> +#include <X11/extensions/XKBproto.h> +#include "XKBlibint.h" + +#else + +#include <stdio.h> +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif /* XKB_IN_SERVER */ + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI) +#else +XkbAllocCompatMap(xkb,which,nSI) + XkbDescPtr xkb; + unsigned which; + unsigned nSI; +#endif +{ +XkbCompatMapPtr compat; +XkbSymInterpretRec *prev_interpret; + + if (!xkb) + return BadMatch; + if (xkb->compat) { + if (xkb->compat->size_si>=nSI) + return Success; + compat= xkb->compat; + compat->size_si= nSI; + if (compat->sym_interpret==NULL) + compat->num_si= 0; + prev_interpret = compat->sym_interpret; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + nSI,XkbSymInterpretRec); + if (compat->sym_interpret==NULL) { + _XkbFree(prev_interpret); + compat->size_si= compat->num_si= 0; + return BadAlloc; + } + if (compat->num_si!=0) { + _XkbClearElems(compat->sym_interpret,compat->num_si, + compat->size_si-1,XkbSymInterpretRec); + } + return Success; + } + compat= _XkbTypedCalloc(1,XkbCompatMapRec); + if (compat==NULL) + return BadAlloc; + if (nSI>0) { + compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec); + if (!compat->sym_interpret) { + _XkbFree(compat); + return BadAlloc; + } + } + compat->size_si= nSI; + compat->num_si= 0; + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + xkb->compat= compat; + return Success; +} + + +void +#if NeedFunctionPrototypes +XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeCompatMap(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ +register XkbCompatMapPtr compat; + + if ((xkb==NULL)||(xkb->compat==NULL)) + return; + compat= xkb->compat; + if (freeMap) + which= XkbAllCompatMask; + if (which&XkbGroupCompatMask) + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + if (which&XkbSymInterpMask) { + if ((compat->sym_interpret)&&(compat->size_si>0)) + _XkbFree(compat->sym_interpret); + compat->size_si= compat->num_si= 0; + compat->sym_interpret= NULL; + } + if (freeMap) { + _XkbFree(compat); + xkb->compat= NULL; + } + return; +} + +/***===================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases) +#else +XkbAllocNames(xkb,which,nTotalRG,nTotalAliases) + XkbDescPtr xkb; + unsigned which; + int nTotalRG; + int nTotalAliases; +#endif +{ +XkbNamesPtr names; + + if (xkb==NULL) + return BadMatch; + if (xkb->names==NULL) { + xkb->names = _XkbTypedCalloc(1,XkbNamesRec); + if (xkb->names==NULL) + return BadAlloc; + } + names= xkb->names; + if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){ + register int i; + XkbKeyTypePtr type; + + type= xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + if (type->level_names==NULL) { + type->level_names= _XkbTypedCalloc(type->num_levels,Atom); + if (type->level_names==NULL) + return BadAlloc; + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadValue; + names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec); + if (names->keys==NULL) + return BadAlloc; + } + if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) { + if (names->key_aliases==NULL) { + names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec); + } + else if (nTotalAliases>names->num_key_aliases) { + XkbKeyAliasRec *prev_aliases = names->key_aliases; + + names->key_aliases= _XkbTypedRealloc(names->key_aliases, + nTotalAliases,XkbKeyAliasRec); + if (names->key_aliases!=NULL) { + _XkbClearElems(names->key_aliases,names->num_key_aliases, + nTotalAliases-1,XkbKeyAliasRec); + } else { + _XkbFree(prev_aliases); + } + } + if (names->key_aliases==NULL) { + names->num_key_aliases= 0; + return BadAlloc; + } + names->num_key_aliases= nTotalAliases; + } + if ((which&XkbRGNamesMask)&&(nTotalRG>0)) { + if (names->radio_groups==NULL) { + names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom); + } + else if (nTotalRG>names->num_rg) { + Atom *prev_radio_groups = names->radio_groups; + + names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG, + Atom); + if (names->radio_groups!=NULL) { + _XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1, + Atom); + } else { + _XkbFree(prev_radio_groups); + } + } + if (names->radio_groups==NULL) + return BadAlloc; + names->num_rg= nTotalRG; + } + return Success; +} + +void +#if NeedFunctionPrototypes +XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeNames(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ +XkbNamesPtr names; + + if ((xkb==NULL)||(xkb->names==NULL)) + return; + names= xkb->names; + if (freeMap) + which= XkbAllNamesMask; + if (which&XkbKTLevelNamesMask) { + XkbClientMapPtr map= xkb->map; + if ((map!=NULL)&&(map->types!=NULL)) { + register int i; + register XkbKeyTypePtr type; + type= map->types; + for (i=0;i<map->num_types;i++,type++) { + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) { + _XkbFree(names->keys); + names->keys= NULL; + names->num_keys= 0; + } + if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){ + _XkbFree(names->key_aliases); + names->key_aliases=NULL; + names->num_key_aliases=0; + } + if ((which&XkbRGNamesMask)&&(names->radio_groups)) { + _XkbFree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + if (freeMap) { + _XkbFree(names); + xkb->names= NULL; + } + return; +} + +/***===================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbAllocControls(XkbDescPtr xkb,unsigned which) +#else +XkbAllocControls(xkb,which) + XkbDescPtr xkb; + unsigned which; +#endif +{ + if (xkb==NULL) + return BadMatch; + + if (xkb->ctrls==NULL) { + xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec); + if (!xkb->ctrls) + return BadAlloc; + } + return Success; +} + +/*ARGSUSED*/ +void +#if NeedFunctionPrototypes +XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap) +#else +XkbFreeControls(xkb,which,freeMap) + XkbDescPtr xkb; + unsigned which; + Bool freeMap; +#endif +{ + if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) { + _XkbFree(xkb->ctrls); + xkb->ctrls= NULL; + } + return; +} + +/***===================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocIndicatorMaps(XkbDescPtr xkb) +#else +XkbAllocIndicatorMaps(xkb) + XkbDescPtr xkb; +#endif +{ + if (xkb==NULL) + return BadMatch; + if (xkb->indicators==NULL) { + xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec); + if (!xkb->indicators) + return BadAlloc; + } + return Success; +} + +void +#if NeedFunctionPrototypes +XkbFreeIndicatorMaps(XkbDescPtr xkb) +#else +XkbFreeIndicatorMaps(xkb) + XkbDescPtr xkb; +#endif +{ + if ((xkb!=NULL)&&(xkb->indicators!=NULL)) { + _XkbFree(xkb->indicators); + xkb->indicators= NULL; + } + return; +} + +/***====================================================================***/ + +XkbDescRec * +#if NeedFunctionPrototypes +XkbAllocKeyboard(void) +#else +XkbAllocKeyboard() +#endif +{ +XkbDescRec *xkb; + + xkb = _XkbTypedCalloc(1,XkbDescRec); + if (xkb) + xkb->device_spec= XkbUseCoreKbd; + return xkb; +} + +void +#if NeedFunctionPrototypes +XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll) +#else +XkbFreeKeyboard(xkb,which,freeAll) + XkbDescPtr xkb; + unsigned which; + Bool freeAll; +#endif +{ + if (xkb==NULL) + return; + if (freeAll) + which= XkbAllComponentsMask; + if (which&XkbClientMapMask) + XkbFreeClientMap(xkb,XkbAllClientInfoMask,True); + if (which&XkbServerMapMask) + XkbFreeServerMap(xkb,XkbAllServerInfoMask,True); + if (which&XkbCompatMapMask) + XkbFreeCompatMap(xkb,XkbAllCompatMask,True); + if (which&XkbIndicatorMapMask) + XkbFreeIndicatorMaps(xkb); + if (which&XkbNamesMask) + XkbFreeNames(xkb,XkbAllNamesMask,True); + if ((which&XkbGeometryMask) && (xkb->geom!=NULL)) + XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True); + if (which&XkbControlsMask) + XkbFreeControls(xkb,XkbAllControlsMask,True); + if (freeAll) + _XkbFree(xkb); + return; +} + +/***====================================================================***/ + +XkbDeviceLedInfoPtr +#if NeedFunctionPrototypes +XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi,unsigned ledClass,unsigned ledId) +#else +XkbAddDeviceLedInfo(devi,ledClass,ledId) + XkbDeviceInfoPtr devi; + unsigned ledClass; + unsigned ledId; +#endif +{ +XkbDeviceLedInfoPtr devli; +register int i; + + if ((!devi)||(!XkbSingleXIClass(ledClass))||(!XkbSingleXIId(ledId))) + return NULL; + for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) { + if ((devli->led_class==ledClass)&&(devli->led_id==ledId)) + return devli; + } + if (devi->num_leds>=devi->sz_leds) { + XkbDeviceLedInfoRec *prev_leds = devi->leds; + + if (devi->sz_leds>0) devi->sz_leds*= 2; + else devi->sz_leds= 1; + devi->leds= _XkbTypedRealloc(devi->leds,devi->sz_leds, + XkbDeviceLedInfoRec); + if (!devi->leds) { + _XkbFree(prev_leds); + devi->sz_leds= devi->num_leds= 0; + return NULL; + } + i= devi->num_leds; + for (devli=&devi->leds[i];i<devi->sz_leds;i++,devli++) { + bzero(devli,sizeof(XkbDeviceLedInfoRec)); + devli->led_class= XkbXINone; + devli->led_id= XkbXINone; + } + } + devli= &devi->leds[devi->num_leds++]; + bzero(devli,sizeof(XkbDeviceLedInfoRec)); + devli->led_class= ledClass; + devli->led_id= ledId; + return devli; +} + +Status +#if NeedFunctionPrototypes +XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi,unsigned newTotal) +#else +XkbResizeDeviceButtonActions(devi,newTotal) + XkbDeviceInfoPtr devi; + unsigned newTotal; +#endif +{ + XkbAction *prev_btn_acts; + + if ((!devi)||(newTotal>255)) + return BadValue; + if ((devi->btn_acts!=NULL)&&(newTotal==devi->num_btns)) + return Success; + if (newTotal==0) { + if (devi->btn_acts!=NULL) { + _XkbFree(devi->btn_acts); + devi->btn_acts= NULL; + } + devi->num_btns= 0; + return Success; + } + prev_btn_acts = devi->btn_acts; + devi->btn_acts= _XkbTypedRealloc(devi->btn_acts,newTotal,XkbAction); + if (devi->btn_acts==NULL) { + _XkbFree(prev_btn_acts); + devi->num_btns= 0; + return BadAlloc; + } + if (newTotal>devi->num_btns) { + XkbAction *act; + act= &devi->btn_acts[devi->num_btns]; + bzero((char *)act,(newTotal-devi->num_btns)*sizeof(XkbAction)); + } + devi->num_btns= newTotal; + return Success; +} + +/*ARGSUSED*/ +XkbDeviceInfoPtr +#if NeedFunctionPrototypes +XkbAllocDeviceInfo(unsigned deviceSpec,unsigned nButtons,unsigned szLeds) +#else +XkbAllocDeviceInfo(deviceSpec,nButtons,szLeds) + unsigned deviceSpec; + unsigned nButtons; + unsigned szLeds; +#endif +{ +XkbDeviceInfoPtr devi; + + devi= _XkbTypedCalloc(1,XkbDeviceInfoRec); + if (devi!=NULL) { + devi->device_spec= deviceSpec; + devi->has_own_state= False; + devi->num_btns= 0; + devi->btn_acts= NULL; + if (nButtons>0) { + devi->num_btns= nButtons; + devi->btn_acts= _XkbTypedCalloc(nButtons,XkbAction); + if (!devi->btn_acts) { + _XkbFree(devi); + return NULL; + } + } + devi->dflt_kbd_fb= XkbXINone; + devi->dflt_led_fb= XkbXINone; + devi->num_leds= 0; + devi->sz_leds= 0; + devi->leds= NULL; + if (szLeds>0) { + devi->sz_leds= szLeds; + devi->leds= _XkbTypedCalloc(szLeds,XkbDeviceLedInfoRec); + if (!devi->leds) { + if (devi->btn_acts) + _XkbFree(devi->btn_acts); + _XkbFree(devi); + return NULL; + } + } + } + return devi; +} + + +void +#if NeedFunctionPrototypes +XkbFreeDeviceInfo(XkbDeviceInfoPtr devi,unsigned which,Bool freeDevI) +#else +XkbFreeDeviceInfo(devi,which,freeDevI) + XkbDeviceInfoPtr devi; + unsigned which; + Bool freeDevI; +#endif +{ + if (devi) { + if (freeDevI) { + which= XkbXI_AllDeviceFeaturesMask; + if (devi->name) { + _XkbFree(devi->name); + devi->name= NULL; + } + } + if ((which&XkbXI_ButtonActionsMask)&&(devi->btn_acts)) { + _XkbFree(devi->btn_acts); + devi->num_btns= 0; + devi->btn_acts= NULL; + } + if ((which&XkbXI_IndicatorsMask)&&(devi->leds)) { + register int i; + if ((which&XkbXI_IndicatorsMask)==XkbXI_IndicatorsMask) { + _XkbFree(devi->leds); + devi->sz_leds= devi->num_leds= 0; + devi->leds= NULL; + } + else { + XkbDeviceLedInfoPtr devli; + for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) { + if (which&XkbXI_IndicatorMapsMask) + bzero((char *)&devli->maps[0],sizeof(devli->maps)); + else bzero((char *)&devli->names[0],sizeof(devli->names)); + } + } + } + if (freeDevI) + _XkbFree(devi); + } + return; +} diff --git a/xkb/XKBGAlloc.c b/xkb/XKBGAlloc.c new file mode 100644 index 000000000..c89e1197c --- /dev/null +++ b/xkb/XKBGAlloc.c @@ -0,0 +1,1377 @@ +/* $Xorg: XKBGAlloc.c,v 1.3 2000/08/17 19:45:01 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifndef XKB_IN_SERVER + +#include <stdio.h> +#include "Xlibint.h" +#include "XKBlibint.h" +#include <X11/extensions/XKBgeom.h> +#include <X11/extensions/XKBproto.h> + +#else + +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif /* XKB_IN_SERVER */ + +#ifdef X_NOT_POSIX +#define Size_t unsigned int +#else +#define Size_t size_t +#endif + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +#else +_XkbFreeGeomLeafElems(freeAll,first,count,num_inout,sz_inout,elems,elem_sz) + Bool freeAll; + int first; + int count; + unsigned short * num_inout; + unsigned short * sz_inout; + char ** elems; + unsigned int elem_sz; +#endif +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + if (*elems!=NULL) { + _XkbFree(*elems); + *elems= NULL; + } + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( +#if NeedFunctionPrototypes + char * /* priv */ +#endif +); + +static void +#if NeedFunctionPrototypes +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +#else +_XkbFreeGeomNonLeafElems(freeAll,first,count,num_inout,sz_inout,elems,elem_sz, + freeFunc) + Bool freeAll; + int first; + int count; + unsigned short * num_inout; + unsigned short * sz_inout; + char ** elems; + unsigned int elem_sz; + ContentsClearFunc freeFunc; +#endif +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i<count;i++) { + (*freeFunc)(ptr); + ptr+= elem_sz; + } + } + if (freeAll) { + (*num_inout)= (*sz_inout)= 0; + if (*elems) { + _XkbFree(*elems); + *elems= NULL; + } + } + else if (first+count>=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearProperty(char *prop_in) +#else +_XkbClearProperty(prop_in) + char * prop_in; +#endif +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + if (prop->name) { + _XkbFree(prop->name); + prop->name= NULL; + } + if (prop->value) { + _XkbFree(prop->value); + prop->value= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +#else +XkbFreeGeomProperties(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +#else +XkbFreeGeomKeyAliases(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearColor(char *color_in) +#else +_XkbClearColor(color_in) + char * color_in; +#endif +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + if (color->spec) + _XkbFree(color->spec); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomColors(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +#else +XkbFreeGeomPoints(outline,first,count,freeAll) + XkbOutlinePtr outline; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOutline(char *outline_in) +#else +_XkbClearOutline(outline_in) + char * outline_in; +#endif +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbFreeGeomPoints(outline,0,outline->num_points,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +#else +XkbFreeGeomOutlines(shape,first,count,freeAll) + XkbShapePtr shape; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearShape(char *shape_in) +#else +_XkbClearShape(shape_in) + char * shape_in; +#endif +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbFreeGeomOutlines(shape,0,shape->num_outlines,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomShapes(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlayKeys(row,first,count,freeAll) + XkbOverlayRowPtr row; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOverlayRow(char *row_in) +#else +_XkbClearOverlayRow(row_in) + char * row_in; +#endif +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomOverlayKeys(row,0,row->num_keys,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlayRows(overlay,first,count,freeAll) + XkbOverlayPtr overlay; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearOverlay(char *overlay_in) +#else +_XkbClearOverlay(overlay_in) + char * overlay_in; +#endif +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +#else +XkbFreeGeomOverlays(section,first,count,freeAll) + XkbSectionPtr section; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +#else +XkbFreeGeomKeys(row,first,count,freeAll) + XkbRowPtr row; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearRow(char *row_in) +#else +_XkbClearRow(row_in) + char * row_in; +#endif +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomKeys(row,0,row->num_keys,True); + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +#else +XkbFreeGeomRows(section,first,count,freeAll) + XkbSectionPtr section; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearSection(char *section_in) +#else +_XkbClearSection(section_in) + char * section_in; +#endif +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbFreeGeomRows(section,0,section->num_rows,True); + if (section->doodads!=NULL) { + XkbFreeGeomDoodads(section->doodads,section->num_doodads,True); + section->doodads= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +#else +XkbFreeGeomSections(geom,first,count,freeAll) + XkbGeometryPtr geom; + int first; + int count; + Bool freeAll; +#endif +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_XkbClearDoodad(char *doodad_in) +#else +_XkbClearDoodad(doodad_in) + char * doodad_in; +#endif +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + if (doodad->text.text!=NULL) { + _XkbFree(doodad->text.text); + doodad->text.text= NULL; + } + if (doodad->text.font!=NULL) { + _XkbFree(doodad->text.font); + doodad->text.font= NULL; + } + } + break; + case XkbLogoDoodad: + { + if (doodad->logo.logo_name!=NULL) { + _XkbFree(doodad->logo.logo_name); + doodad->logo.logo_name= NULL; + } + } + break; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +#else +XkbFreeGeomDoodads(doodads,nDoodads,freeAll) + XkbDoodadPtr doodads; + int nDoodads; + Bool freeAll; +#endif +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) { + _XkbClearDoodad((char *)doodad); + } + if (freeAll) + _XkbFree(doodads); + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap) +#else +XkbFreeGeometry(geom,which,freeMap) + XkbGeometryPtr geom; + unsigned which; + Bool freeMap; +#endif +{ + if (geom==NULL) + return; + if (freeMap) + which= XkbGeomAllMask; + if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL)) + XkbFreeGeomProperties(geom,0,geom->num_properties,True); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbFreeGeomColors(geom,0,geom->num_colors,True); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbFreeGeomShapes(geom,0,geom->num_shapes,True); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbFreeGeomSections(geom,0,geom->num_sections,True); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True); + if (freeMap) { + if (geom->label_font!=NULL) { + _XkbFree(geom->label_font); + geom->label_font= NULL; + } + _XkbFree(geom); + } + return; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +_XkbGeomAlloc( XPointer * old, + unsigned short * num, + unsigned short * total, + int num_new, + Size_t sz_elem) +#else +_XkbGeomAlloc(old,num,total,num_new,sz_elem) + XPointer * old; + unsigned short * num; + unsigned short * total; + int num_new; + Size_t sz_elem; +#endif +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem); + else (*old)= (XPointer)_XkbCalloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +Status +#if NeedFunctionPrototypes +XkbAllocGeomProps(XkbGeometryPtr geom,int nProps) +#else +XkbAllocGeomProps(geom,nProps) + XkbGeometryPtr geom; + int nProps; +#endif +{ + return _XkbAllocProps(geom,nProps); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomColors(XkbGeometryPtr geom,int nColors) +#else +XkbAllocGeomColors(geom,nColors) + XkbGeometryPtr geom; + int nColors; +#endif +{ + return _XkbAllocColors(geom,nColors); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases) +#else +XkbAllocGeomKeyAliases(geom,nKeyAliases) + XkbGeometryPtr geom; + int nKeyAliases; +#endif +{ + return _XkbAllocKeyAliases(geom,nKeyAliases); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes) +#else +XkbAllocGeomShapes(geom,nShapes) + XkbGeometryPtr geom; + int nShapes; +#endif +{ + return _XkbAllocShapes(geom,nShapes); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomSections(XkbGeometryPtr geom,int nSections) +#else +XkbAllocGeomSections(geom,nSections) + XkbGeometryPtr geom; + int nSections; +#endif +{ + return _XkbAllocSections(geom,nSections); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays) +#else +XkbAllocGeomOverlays(section,nOverlays) + XkbSectionPtr section; + int nOverlays; +#endif +{ + return _XkbAllocOverlays(section,nOverlays); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows) +#else +XkbAllocGeomOverlayRows(overlay,nRows) + XkbOverlayPtr overlay; + int nRows; +#endif +{ + return _XkbAllocOverlayRows(overlay,nRows); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys) +#else +XkbAllocGeomOverlayKeys(row,nKeys) + XkbOverlayRowPtr row; + int nKeys; +#endif +{ + return _XkbAllocOverlayKeys(row,nKeys); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads) +#else +XkbAllocGeomDoodads(geom,nDoodads) + XkbGeometryPtr geom; + int nDoodads; +#endif +{ + return _XkbAllocDoodads(geom,nDoodads); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads) +#else +XkbAllocGeomSectionDoodads(section,nDoodads) + XkbSectionPtr section; + int nDoodads; +#endif +{ + return _XkbAllocDoodads(section,nDoodads); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomOutlines(XkbShapePtr shape,int nOL) +#else +XkbAllocGeomOutlines(shape,nOL) + XkbShapePtr shape; + int nOL; +#endif +{ + return _XkbAllocOutlines(shape,nOL); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomRows(XkbSectionPtr section,int nRows) +#else +XkbAllocGeomRows(section,nRows) + XkbSectionPtr section; + int nRows; +#endif +{ + return _XkbAllocRows(section,nRows); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts) +#else +XkbAllocGeomPoints(ol,nPts) + XkbOutlinePtr ol; + int nPts; +#endif +{ + return _XkbAllocPoints(ol,nPts); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeomKeys(XkbRowPtr row,int nKeys) +#else +XkbAllocGeomKeys(row,nKeys) + XkbRowPtr row; + int nKeys; +#endif +{ + return _XkbAllocKeys(row,nKeys); +} + +Status +#if NeedFunctionPrototypes +XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes) +#else +XkbAllocGeometry(xkb,sizes) + XkbDescPtr xkb; + XkbGeometrySizesPtr sizes; +#endif +{ +XkbGeometryPtr geom; +Status rtrn; + + if (xkb->geom==NULL) { + xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return rtrn; +} + +/***====================================================================***/ + +XkbPropertyPtr +#if NeedFunctionPrototypes +XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value) +#else +XkbAddGeomProperty(geom,name,value) + XkbGeometryPtr geom; + char * name; + char * value; +#endif +{ +register int i; +register XkbPropertyPtr prop; + + if ((!geom)||(!name)||(!value)) + return NULL; + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + if ((prop->name)&&(strcmp(name,prop->name)==0)) { + if (prop->value) + _XkbFree(prop->value); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (prop->value) + strcpy(prop->value,value); + return prop; + } + } + if ((geom->num_properties>=geom->sz_properties)&& + (_XkbAllocProps(geom,1)!=Success)) { + return NULL; + } + prop= &geom->properties[geom->num_properties]; + prop->name= (char *)_XkbAlloc(strlen(name)+1); + if (!name) + return NULL; + strcpy(prop->name,name); + prop->value= (char *)_XkbAlloc(strlen(value)+1); + if (!value) { + _XkbFree(prop->name); + prop->name= NULL; + return NULL; + } + strcpy(prop->value,value); + geom->num_properties++; + return prop; +} + +XkbKeyAliasPtr +#if NeedFunctionPrototypes +XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr) +#else +XkbAddGeomKeyAlias(geom,aliasStr,realStr) + XkbGeometryPtr geom; + char * aliasStr; + char * realStr; +#endif +{ +register int i; +register XkbKeyAliasPtr alias; + + if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0])) + return NULL; + for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) { + if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) { + bzero(alias->real,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + return alias; + } + } + if ((geom->num_key_aliases>=geom->sz_key_aliases)&& + (_XkbAllocKeyAliases(geom,1)!=Success)) { + return NULL; + } + alias= &geom->key_aliases[geom->num_key_aliases]; + bzero(alias,sizeof(XkbKeyAliasRec)); + strncpy(alias->alias,aliasStr,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + geom->num_key_aliases++; + return alias; +} + +XkbColorPtr +#if NeedFunctionPrototypes +XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel) +#else +XkbAddGeomColor(geom,spec,pixel) + XkbGeometryPtr geom; + char * spec; + unsigned int pixel; +#endif +{ +register int i; +register XkbColorPtr color; + + if ((!geom)||(!spec)) + return NULL; + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + if ((color->spec)&&(strcmp(color->spec,spec)==0)) { + color->pixel= pixel; + return color; + } + } + if ((geom->num_colors>=geom->sz_colors)&& + (_XkbAllocColors(geom,1)!=Success)) { + return NULL; + } + color= &geom->colors[geom->num_colors]; + color->pixel= pixel; + color->spec= (char *)_XkbAlloc(strlen(spec)+1); + if (!color->spec) + return NULL; + strcpy(color->spec,spec); + geom->num_colors++; + return color; +} + +XkbOutlinePtr +#if NeedFunctionPrototypes +XkbAddGeomOutline(XkbShapePtr shape,int sz_points) +#else +XkbAddGeomOutline(shape,sz_points) + XkbShapePtr shape; + int sz_points; +#endif +{ +XkbOutlinePtr outline; + + if ((!shape)||(sz_points<0)) + return NULL; + if ((shape->num_outlines>=shape->sz_outlines)&& + (_XkbAllocOutlines(shape,1)!=Success)) { + return NULL; + } + outline= &shape->outlines[shape->num_outlines]; + bzero(outline,sizeof(XkbOutlineRec)); + if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success)) + return NULL; + shape->num_outlines++; + return outline; +} + +XkbShapePtr +#if NeedFunctionPrototypes +XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines) +#else +XkbAddGeomShape(geom,name,sz_outlines) + XkbGeometryPtr geom; + Atom name; + int sz_outlines; +#endif +{ +XkbShapePtr shape; +register int i; + + if ((!geom)||(!name)||(sz_outlines<0)) + return NULL; + if (geom->num_shapes>0) { + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + if (name==shape->name) + return shape; + } + } + if ((geom->num_shapes>=geom->sz_shapes)&& + (_XkbAllocShapes(geom,1)!=Success)) + return NULL; + shape= &geom->shapes[geom->num_shapes]; + bzero(shape,sizeof(XkbShapeRec)); + if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success)) + return NULL; + shape->name= name; + shape->primary= shape->approx= NULL; + geom->num_shapes++; + return shape; +} + +XkbKeyPtr +#if NeedFunctionPrototypes +XkbAddGeomKey(XkbRowPtr row) +#else +XkbAddGeomKey(row) + XkbRowPtr row; +#endif +{ +XkbKeyPtr key; + if (!row) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys++]; + bzero(key,sizeof(XkbKeyRec)); + return key; +} + +XkbRowPtr +#if NeedFunctionPrototypes +XkbAddGeomRow(XkbSectionPtr section,int sz_keys) +#else +XkbAddGeomRow(section,sz_keys) + XkbSectionPtr section; + int sz_keys; +#endif +{ +XkbRowPtr row; + + if ((!section)||(sz_keys<0)) + return NULL; + if ((section->num_rows>=section->sz_rows)&& + (_XkbAllocRows(section,1)!=Success)) + return NULL; + row= §ion->rows[section->num_rows]; + bzero(row,sizeof(XkbRowRec)); + if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success)) + return NULL; + section->num_rows++; + return row; +} + +XkbSectionPtr +#if NeedFunctionPrototypes +XkbAddGeomSection( XkbGeometryPtr geom, + Atom name, + int sz_rows, + int sz_doodads, + int sz_over) +#else +XkbAddGeomSection(geom,name,sz_rows,sz_doodads,sz_over) + XkbGeometryPtr geom; + Atom name; + int sz_rows; + int sz_doodads; + int sz_over; +#endif +{ +register int i; +XkbSectionPtr section; + + if ((!geom)||(name==None)||(sz_rows<0)) + return NULL; + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + if (section->name!=name) + continue; + if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))|| + ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))|| + ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success))) + return NULL; + return section; + } + if ((geom->num_sections>=geom->sz_sections)&& + (_XkbAllocSections(geom,1)!=Success)) + return NULL; + section= &geom->sections[geom->num_sections]; + if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success)) + return NULL; + if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) { + if (section->rows) { + _XkbFree(section->rows); + section->rows= NULL; + section->sz_rows= section->num_rows= 0; + } + return NULL; + } + section->name= name; + geom->num_sections++; + return section; +} + +XkbDoodadPtr +#if NeedFunctionPrototypes +XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name) +#else +XkbAddGeomDoodad(geom,section,name) + XkbGeometryPtr geom; + XkbSectionPtr section; + Atom name; +#endif +{ +XkbDoodadPtr old,doodad; +register int i,nDoodads; + + if ((!geom)||(name==None)) + return NULL; + if ((section!=NULL)&&(section->num_doodads>0)) { + old= section->doodads; + nDoodads= section->num_doodads; + } + else { + old= geom->doodads; + nDoodads= geom->num_doodads; + } + for (i=0,doodad=old;i<nDoodads;i++,doodad++) { + if (doodad->any.name==name) + return doodad; + } + if (section) { + if ((section->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(section,1)!=Success)) { + return NULL; + } + doodad= §ion->doodads[section->num_doodads++]; + } + else { + if ((geom->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(geom,1)!=Success)) + return NULL; + doodad= &geom->doodads[geom->num_doodads++]; + } + bzero(doodad,sizeof(XkbDoodadRec)); + doodad->any.name= name; + return doodad; +} + +XkbOverlayKeyPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlayKey( XkbOverlayPtr overlay, + XkbOverlayRowPtr row, + char * over, + char * under) +#else +XkbAddGeomOverlayKey(overlay,row,over,under) + XkbOverlayPtr overlay; + XkbOverlayRowPtr row; + char * over; + char * under; +#endif +{ +register int i; +XkbOverlayKeyPtr key; +XkbSectionPtr section; +XkbRowPtr row_under; +Bool found; + + if ((!overlay)||(!row)||(!over)||(!under)) + return NULL; + section= overlay->section_under; + if (row->row_under>=section->num_rows) + return NULL; + row_under= §ion->rows[row->row_under]; + for (i=0,found=False;i<row_under->num_keys;i++) { + if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) { + found= True; + break; + } + } + if (!found) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys]; + strncpy(key->under.name,under,XkbKeyNameLength); + strncpy(key->over.name,over,XkbKeyNameLength); + row->num_keys++; + return key; +} + +XkbOverlayRowPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys) +#else +XkbAddGeomOverlayRow(overlay,row_under,sz_keys) + XkbOverlayPtr overlay; + int row_under; + int sz_keys; +#endif +{ +register int i; +XkbOverlayRowPtr row; + + if ((!overlay)||(sz_keys<0)) + return NULL; + if (row_under>=overlay->section_under->num_rows) + return NULL; + for (i=0;i<overlay->num_rows;i++) { + if (overlay->rows[i].row_under==row_under) { + row= &overlay->rows[i]; + if ((row->sz_keys<sz_keys)&& + (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) { + return NULL; + } + return &overlay->rows[i]; + } + } + if ((overlay->num_rows>=overlay->sz_rows)&& + (_XkbAllocOverlayRows(overlay,1)!=Success)) + return NULL; + row= &overlay->rows[overlay->num_rows]; + bzero(row,sizeof(XkbOverlayRowRec)); + if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) + return NULL; + row->row_under= row_under; + overlay->num_rows++; + return row; +} + +XkbOverlayPtr +#if NeedFunctionPrototypes +XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows) +#else +XkbAddGeomOverlay(section,name,sz_rows) + XkbSectionPtr section; + Atom name; + int sz_rows; +#endif +{ +register int i; +XkbOverlayPtr overlay; + + if ((!section)||(name==None)||(sz_rows==0)) + return NULL; + + for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) { + if (overlay->name==name) { + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + return overlay; + } + } + if ((section->num_overlays>=section->sz_overlays)&& + (_XkbAllocOverlays(section,1)!=Success)) + return NULL; + overlay= §ion->overlays[section->num_overlays]; + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + overlay->name= name; + overlay->section_under= section; + section->num_overlays++; + return overlay; +} diff --git a/xkb/XKBMAlloc.c b/xkb/XKBMAlloc.c new file mode 100644 index 000000000..ba2a70761 --- /dev/null +++ b/xkb/XKBMAlloc.c @@ -0,0 +1,1077 @@ +/* $Xorg: XKBMAlloc.c,v 1.4 2000/08/17 19:45:02 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include <X11/extensions/XKBproto.h> +#include <X11/keysym.h> +#include "XKBlibint.h" + +#else + +#include <stdio.h> +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include <X11/keysym.h> +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif /* XKB_IN_SERVER */ + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes) +#else +XkbAllocClientMap(xkb,which,nTotalTypes) + XkbDescPtr xkb; + unsigned which; + unsigned nTotalTypes; +#endif +{ +register int i; +XkbClientMapPtr map; + + if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes))) + return BadValue; + if ((which&XkbKeySymsMask)&& + ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code))) { +#ifdef DEBUG +fprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n", + xkb->min_key_code,xkb->max_key_code); +#endif + return BadValue; + } + + if (xkb->map==NULL) { + map= _XkbTypedCalloc(1,XkbClientMapRec); + if (map==NULL) + return BadAlloc; + xkb->map= map; + } + else map= xkb->map; + + if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) { + if (map->types==NULL) { + map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) + return BadAlloc; + map->num_types= 0; + map->size_types= nTotalTypes; + } + else if (map->size_types<nTotalTypes) { + XkbKeyTypeRec *prev_types = map->types; + + map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec); + if (map->types==NULL) { + _XkbFree(prev_types); + map->num_types= map->size_types= 0; + return BadAlloc; + } + map->size_types= nTotalTypes; + bzero(&map->types[map->num_types], + ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec))); + } + } + if (which&XkbKeySymsMask) { + int nKeys= XkbNumKeys(xkb); + if (map->syms==NULL) { + map->size_syms= (nKeys*15)/10; + map->syms= _XkbTypedCalloc(map->size_syms,KeySym); + if (!map->syms) { + map->size_syms= 0; + return BadAlloc; + } + map->num_syms= 1; + map->syms[0]= NoSymbol; + } + if (map->key_sym_map==NULL) { + i= xkb->max_key_code+1; + map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec); + if (map->key_sym_map==NULL) + return BadAlloc; + } + } + if (which&XkbModifierMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->modmap==NULL) { + i= xkb->max_key_code+1; + map->modmap= _XkbTypedCalloc(i,unsigned char); + if (map->modmap==NULL) + return BadAlloc; + } + } + return Success; +} + +Status +#if NeedFunctionPrototypes +XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions) +#else +XkbAllocServerMap(xkb,which,nNewActions) + XkbDescPtr xkb; + unsigned which; + unsigned nNewActions; +#endif +{ +register int i; +XkbServerMapPtr map; + + if (xkb==NULL) + return BadMatch; + if (xkb->server==NULL) { + map= _XkbTypedCalloc(1,XkbServerMapRec); + if (map==NULL) + return BadAlloc; + for (i=0;i<XkbNumVirtualMods;i++) { + map->vmods[i]= XkbNoModifierMask; + } + xkb->server= map; + } + else map= xkb->server; + if (which&XkbExplicitComponentsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->explicit==NULL) { + i= xkb->max_key_code+1; + map->explicit= _XkbTypedCalloc(i,unsigned char); + if (map->explicit==NULL) + return BadAlloc; + } + } + if (which&XkbKeyActionsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (nNewActions<1) + nNewActions= 1; + if (map->acts==NULL) { + map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction); + if (map->acts==NULL) + return BadAlloc; + map->num_acts= 1; + map->size_acts= nNewActions+1; + } + else if ((map->size_acts-map->num_acts)<nNewActions) { + unsigned need; + XkbAction *prev_acts = map->acts; + need= map->num_acts+nNewActions; + map->acts= _XkbTypedRealloc(map->acts,need,XkbAction); + if (map->acts==NULL) { + _XkbFree(prev_acts); + map->num_acts= map->size_acts= 0; + return BadAlloc; + } + map->size_acts= need; + bzero(&map->acts[map->num_acts], + ((map->size_acts-map->num_acts)*sizeof(XkbAction))); + } + if (map->key_acts==NULL) { + i= xkb->max_key_code+1; + map->key_acts= _XkbTypedCalloc(i,unsigned short); + if (map->key_acts==NULL) + return BadAlloc; + } + } + if (which&XkbKeyBehaviorsMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->behaviors==NULL) { + i= xkb->max_key_code+1; + map->behaviors= _XkbTypedCalloc(i,XkbBehavior); + if (map->behaviors==NULL) + return BadAlloc; + } + } + if (which&XkbVirtualModMapMask) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_code<xkb->min_key_code)) + return BadMatch; + if (map->vmodmap==NULL) { + i= xkb->max_key_code+1; + map->vmodmap= _XkbTypedCalloc(i,unsigned short); + if (map->vmodmap==NULL) + return BadAlloc; + } + } + return Success; +} + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into) +#else +XkbCopyKeyType(from,into) + XkbKeyTypePtr from; + XkbKeyTypePtr into; +#endif +{ + if ((!from)||(!into)) + return BadMatch; + if (into->map) { + _XkbFree(into->map); + into->map= NULL; + } + if (into->preserve) { + _XkbFree(into->preserve); + into->preserve= NULL; + } + if (into->level_names) { + _XkbFree(into->level_names); + into->level_names= NULL; + } + *into= *from; + if ((from->map)&&(into->map_count>0)) { + into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec); + if (!into->map) + return BadAlloc; + memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec)); + } + if ((from->preserve)&&(into->map_count>0)) { + into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec); + if (!into->preserve) + return BadAlloc; + memcpy(into->preserve,from->preserve, + into->map_count*sizeof(XkbModsRec)); + } + if ((from->level_names)&&(into->num_levels>0)) { + into->level_names= _XkbTypedCalloc(into->num_levels,Atom); + if (!into->level_names) + return BadAlloc; + memcpy(into->level_names,from->level_names, + into->num_levels*sizeof(Atom)); + } + return Success; +} + +Status +#if NeedFunctionPrototypes +XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types) +#else +XkbCopyKeyTypes(from,into,num_types) + XkbKeyTypePtr from; + XkbKeyTypePtr into; + int num_types; +#endif +{ +register int i,rtrn; + + if ((!from)||(!into)||(num_types<0)) + return BadMatch; + for (i=0;i<num_types;i++) { + if ((rtrn= XkbCopyKeyType(from++,into++))!=Success) + return rtrn; + } + return Success; +} + +XkbKeyTypePtr +#if NeedFunctionPrototypes +XkbAddKeyType( XkbDescPtr xkb, + Atom name, + int map_count, + Bool want_preserve, + int num_lvls) +#else +XkbAddKeyType(xkb,name,map_count,want_preserve,num_lvls) + XkbDescPtr xkb; + Atom name; + int map_count; + Bool want_preserve; + int num_lvls; +#endif +{ +register int i; +unsigned tmp; +XkbKeyTypePtr type; +XkbClientMapPtr map; + + if ((!xkb)||(num_lvls<1)) + return NULL; + map= xkb->map; + if ((map)&&(map->types)) { + for (i=0;i<map->num_types;i++) { + if (map->types[i].name==name) { + Status status; + status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls); + return (status==Success?&map->types[i]:NULL); + } + } + } + if ((!map)||(!map->types)||(!map->num_types<XkbNumRequiredTypes)) { + tmp= XkbNumRequiredTypes+1; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,tmp)!=Success) + return NULL; + tmp= 0; + if (map->num_types<=XkbKeypadIndex) + tmp|= XkbKeypadMask; + if (map->num_types<=XkbAlphabeticIndex) + tmp|= XkbAlphabeticMask; + if (map->num_types<=XkbTwoLevelIndex) + tmp|= XkbTwoLevelMask; + if (map->num_types<=XkbOneLevelIndex) + tmp|= XkbOneLevelMask; + if (XkbInitCanonicalKeyTypes(xkb,tmp,XkbNoModifier)==Success) { + for (i=0;i<map->num_types;i++) { + Status status; + if (map->types[i].name!=name) + continue; + status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls); + return (status==Success?&map->types[i]:NULL); + } + } + } + if ((map->num_types<=map->size_types)&& + (XkbAllocClientMap(xkb,XkbKeyTypesMask,map->num_types+1)!=Success)) { + return NULL; + } + type= &map->types[map->num_types]; + map->num_types++; + bzero((char *)type,sizeof(XkbKeyTypeRec)); + type->num_levels= num_lvls; + type->map_count= map_count; + type->name= name; + if (map_count>0) { + type->map= _XkbTypedCalloc(map_count,XkbKTMapEntryRec); + if (!type->map) { + map->num_types--; + return NULL; + } + if (want_preserve) { + type->preserve= _XkbTypedCalloc(map_count,XkbModsRec); + if (!type->preserve) { + _XkbFree(type->map); + map->num_types--; + return NULL; + } + } + } + return type; +} + +Status +#if NeedFunctionPrototypes +XkbResizeKeyType( XkbDescPtr xkb, + int type_ndx, + int map_count, + Bool want_preserve, + int new_num_lvls) +#else +XkbResizeKeyType(xkb,type_ndx,map_count,want_preserve,new_num_lvls) + XkbDescPtr xkb; + int type_ndx; + int map_count; + Bool want_preserve; + int new_num_lvls; +#endif +{ +XkbKeyTypePtr type; +KeyCode matchingKeys[XkbMaxKeyCount],nMatchingKeys; + + if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)|| + (new_num_lvls<1)) + return BadValue; + switch (type_ndx) { + case XkbOneLevelIndex: + if (new_num_lvls!=1) + return BadMatch; + break; + case XkbTwoLevelIndex: + case XkbAlphabeticIndex: + case XkbKeypadIndex: + if (new_num_lvls!=2) + return BadMatch; + break; + } + type= &xkb->map->types[type_ndx]; + if (map_count==0) { + if (type->map!=NULL) + _XkbFree(type->map); + type->map= NULL; + if (type->preserve!=NULL) + _XkbFree(type->preserve); + type->preserve= NULL; + type->map_count= 0; + } + else { + XkbKTMapEntryRec *prev_map = type->map; + + if ((map_count>type->map_count)||(type->map==NULL)) + type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec); + if (!type->map) { + if (prev_map) + _XkbFree(prev_map); + return BadAlloc; + } + if (want_preserve) { + XkbModsRec *prev_preserve = type->preserve; + + if ((map_count>type->map_count)||(type->preserve==NULL)) { + type->preserve= _XkbTypedRealloc(type->preserve,map_count, + XkbModsRec); + } + if (!type->preserve) { + if (prev_preserve) + _XkbFree(prev_preserve); + return BadAlloc; + } + } + else if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= map_count; + } + + if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) { + Atom * prev_level_names = type->level_names; + + type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom); + if (!type->level_names) { + if (prev_level_names) + _XkbFree(prev_level_names); + return BadAlloc; + } + } + /* + * Here's the theory: + * If the width of the type changed, we might have to resize the symbol + * maps for any keys that use the type for one or more groups. This is + * expensive, so we'll try to cull out any keys that are obviously okay: + * In any case: + * - keys that have a group width <= the old width are okay (because + * they could not possibly have been associated with the old type) + * If the key type increased in size: + * - keys that already have a group width >= to the new width are okay + * + keys that have a group width >= the old width but < the new width + * might have to be enlarged. + * If the key type decreased in size: + * - keys that have a group width > the old width don't have to be + * resized (because they must have some other wider type associated + * with some group). + * + keys that have a group width == the old width might have to be + * shrunk. + * The possibilities marked with '+' require us to examine the key types + * associated with each group for the key. + */ + bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode)); + nMatchingKeys= 0; + if (new_num_lvls>type->num_levels) { + int nTotal; + KeySym * newSyms; + int width,match,nResize; + register int i,g,nSyms; + + nResize= 0; + for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (width<type->num_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + if ((!match)||(width>=new_num_lvls)) + nTotal+= XkbKeyNumSyms(xkb,i); + else { + nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + nResize++; + } + } + if (nResize>0) { + int nextMatch; + xkb->map->size_syms= (nTotal*12)/10; + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return BadAlloc; + nextMatch= 0; + nSyms= 1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (matchingKeys[nextMatch]==i) { + KeySym *pOld; + nextMatch++; + width= XkbKeyGroupsWidth(xkb,i); + pOld= XkbKeySymsPtr(xkb,i); + for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) { + memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g], + width*sizeof(KeySym)); + } + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls; + } + else { + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i), + XkbKeyNumSyms(xkb,i)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset= nSyms; + nSyms+= XkbKeyNumSyms(xkb,i); + } + } + type->num_levels= new_num_lvls; + _XkbFree(xkb->map->syms); + xkb->map->syms= newSyms; + xkb->map->num_syms= nSyms; + return Success; + } + } + else if (new_num_lvls<type->num_levels) { + int width,match; + register int g,i; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + width= XkbKeyGroupsWidth(xkb,i); + if (width<type->num_levels) + continue; + for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { + if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { + matchingKeys[nMatchingKeys++]= i; + match= 1; + } + } + } + } + if (nMatchingKeys>0) { + int key,firstClear; + register int i,g; + if (new_num_lvls>type->num_levels) + firstClear= type->num_levels; + else firstClear= new_num_lvls; + for (i=0;i<nMatchingKeys;i++) { + KeySym * pSyms; + int width,nClear; + + key= matchingKeys[i]; + width= XkbKeyGroupsWidth(xkb,key); + nClear= width-firstClear; + pSyms= XkbKeySymsPtr(xkb,key); + for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) { + if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) { + if (nClear>0) + bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym)); + } + } + } + } + type->num_levels= new_num_lvls; + return Success; +} + +KeySym * +#if NeedFunctionPrototypes +XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed) +#else +XkbResizeKeySyms(xkb,key,needed) + XkbDescPtr xkb; + int key; + int needed; +#endif +{ +register int i,nSyms,nKeySyms; +unsigned nOldSyms; +KeySym *newSyms; + + if (needed==0) { + xkb->map->key_sym_map[key].offset= 0; + return xkb->map->syms; + } + nOldSyms= XkbKeyNumSyms(xkb,key); + if (nOldSyms>=(unsigned)needed) { + return XkbKeySymsPtr(xkb,key); + } + if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) { + if (nOldSyms>0) { + memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key), + nOldSyms*sizeof(KeySym)); + } + if ((needed-nOldSyms)>0) { + bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)], + (needed-nOldSyms)*sizeof(KeySym)); + } + xkb->map->key_sym_map[key].offset = xkb->map->num_syms; + xkb->map->num_syms+= needed; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; + } + xkb->map->size_syms+= (needed>32?needed:32); + newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym); + if (newSyms==NULL) + return NULL; + newSyms[0]= NoSymbol; + nSyms = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nCopy; + + nCopy= nKeySyms= XkbKeyNumSyms(xkb,i); + if ((nKeySyms==0)&&(i!=key)) + continue; + if (i==key) + nKeySyms= needed; + if (nCopy!=0) + memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym)); + if (nKeySyms>nCopy) + bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym)); + xkb->map->key_sym_map[i].offset = nSyms; + nSyms+= nKeySyms; + } + _XkbFree(xkb->map->syms); + xkb->map->syms = newSyms; + xkb->map->num_syms = nSyms; + return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; +} + +static unsigned +#if NeedFunctionPrototypes +_ExtendRange( unsigned int old_flags, + unsigned int flag, + KeyCode newKC, + KeyCode * old_min, + unsigned char * old_num) +#else +_ExtendRange(old_flags,flag,newKC,old_min,old_num) + unsigned int old_flags; + unsigned int flag; + KeyCode newKC; + KeyCode * old_min; + unsigned char * old_num; +#endif +{ + if ((old_flags&flag)==0) { + old_flags|= flag; + *old_min= newKC; + *old_num= 1; + } + else { + int last= (*old_min)+(*old_num)-1; + if (newKC<*old_min) { + *old_min= newKC; + *old_num= (last-newKC)+1; + } + else if (newKC>last) { + *old_num= (newKC-(*old_min))+1; + } + } + return old_flags; +} + +Status +#if NeedFunctionPrototypes +XkbChangeKeycodeRange( XkbDescPtr xkb, + int minKC, + int maxKC, + XkbChangesPtr changes) +#else +XkbChangeKeycodeRange(xkb,minKC,maxKC,changes) + XkbDescPtr xkb; + int minKC; + int maxKC; + XkbChangesPtr changes; +#endif +{ +int tmp; + + if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode)) + return BadValue; + if (minKC>maxKC) + return BadMatch; + if (minKC<xkb->min_key_code) { + if (changes) + changes->map.min_key_code= minKC; + tmp= xkb->min_key_code-minKC; + if (xkb->map) { + if (xkb->map->key_sym_map) { + bzero((char *)&xkb->map->key_sym_map[minKC], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,minKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + bzero((char *)&xkb->map->modmap[minKC],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + bzero((char *)&xkb->server->behaviors[minKC], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,minKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + bzero((char *)&xkb->server->key_acts[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,minKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + bzero((char *)&xkb->server->vmodmap[minKC], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,minKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,minKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->min_key_code= minKC; + } + if (maxKC>xkb->max_key_code) { + if (changes) + changes->map.max_key_code= maxKC; + tmp= maxKC-xkb->max_key_code; + if (xkb->map) { + if (xkb->map->key_sym_map) { + XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map; + + xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map, + (maxKC+1),XkbSymMapRec); + if (!xkb->map->key_sym_map) { + _XkbFree(prev_key_sym_map); + return BadAlloc; + } + bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code], + tmp*sizeof(XkbSymMapRec)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeySymsMask,maxKC, + &changes->map.first_key_sym, + &changes->map.num_key_syms); + } + } + if (xkb->map->modmap) { + unsigned char *prev_modmap = xkb->map->modmap; + + xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap, + (maxKC+1),unsigned char); + if (!xkb->map->modmap) { + _XkbFree(prev_modmap); + return BadAlloc; + } + bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbModifierMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_modmap_keys); + } + } + } + if (xkb->server) { + if (xkb->server->behaviors) { + XkbBehavior *prev_behaviors = xkb->server->behaviors; + + xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors, + (maxKC+1),XkbBehavior); + if (!xkb->server->behaviors) { + _XkbFree(prev_behaviors); + return BadAlloc; + } + bzero((char *)&xkb->server->behaviors[xkb->max_key_code], + tmp*sizeof(XkbBehavior)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyBehaviorsMask,maxKC, + &changes->map.first_key_behavior, + &changes->map.num_key_behaviors); + } + } + if (xkb->server->key_acts) { + unsigned short *prev_key_acts = xkb->server->key_acts; + + xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts, + (maxKC+1),unsigned short); + if (!xkb->server->key_acts) { + _XkbFree(prev_key_acts); + return BadAlloc; + } + bzero((char *)&xkb->server->key_acts[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbKeyActionsMask,maxKC, + &changes->map.first_key_act, + &changes->map.num_key_acts); + } + } + if (xkb->server->vmodmap) { + unsigned short *prev_vmodmap = xkb->server->vmodmap; + + xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap, + (maxKC+1),unsigned short); + if (!xkb->server->vmodmap) { + _XkbFree(prev_vmodmap); + return BadAlloc; + } + bzero((char *)&xkb->server->vmodmap[xkb->max_key_code], + tmp*sizeof(unsigned short)); + if (changes) { + changes->map.changed= _ExtendRange(changes->map.changed, + XkbVirtualModMapMask,maxKC, + &changes->map.first_modmap_key, + &changes->map.num_vmodmap_keys); + } + } + } + if ((xkb->names)&&(xkb->names->keys)) { + XkbKeyNameRec *prev_keys = xkb->names->keys; + + xkb->names->keys= _XkbTypedRealloc(xkb->names->keys, + (maxKC+1),XkbKeyNameRec); + if (!xkb->names->keys) { + _XkbFree(prev_keys); + return BadAlloc; + } + bzero((char *)&xkb->names->keys[xkb->max_key_code], + tmp*sizeof(XkbKeyNameRec)); + if (changes) { + changes->names.changed= _ExtendRange(changes->names.changed, + XkbKeyNamesMask,maxKC, + &changes->names.first_key, + &changes->names.num_keys); + } + } + xkb->max_key_code= maxKC; + } + return Success; +} + +XkbAction * +#if NeedFunctionPrototypes +XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed) +#else +XkbResizeKeyActions(xkb,key,needed) + XkbDescPtr xkb; + int key; + int needed; +#endif +{ +register int i,nActs; +XkbAction *newActs; + + if (needed==0) { + xkb->server->key_acts[key]= 0; + return NULL; + } + if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed)) + return XkbKeyActionsPtr(xkb,key); + if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) { + xkb->server->key_acts[key]= xkb->server->num_acts; + xkb->server->num_acts+= needed; + return &xkb->server->acts[xkb->server->key_acts[key]]; + } + xkb->server->size_acts= xkb->server->num_acts+needed+8; + newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction); + if (newActs==NULL) + return NULL; + newActs[0].type = XkbSA_NoAction; + nActs = 1; + for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { + int nKeyActs,nCopy; + + if ((xkb->server->key_acts[i]==0)&&(i!=key)) + continue; + + nCopy= nKeyActs= XkbKeyNumActions(xkb,i); + if (i==key) { + nKeyActs= needed; + if (needed<nCopy) + nCopy= needed; + } + + if (nCopy>0) + memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i), + nCopy*sizeof(XkbAction)); + if (nCopy<nKeyActs) + bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction)); + xkb->server->key_acts[i]= nActs; + nActs+= nKeyActs; + } + _XkbFree(xkb->server->acts); + xkb->server->acts = newActs; + xkb->server->num_acts= nActs; + return &xkb->server->acts[xkb->server->key_acts[key]]; +} + +void +#if NeedFunctionPrototypes +XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +#else +XkbFreeClientMap(xkb,what,freeMap) + XkbDescPtr xkb; + unsigned what; + Bool freeMap; +#endif +{ +XkbClientMapPtr map; + + if ((xkb==NULL)||(xkb->map==NULL)) + return; + if (freeMap) + what= XkbAllClientInfoMask; + map= xkb->map; + if (what&XkbKeyTypesMask) { + if (map->types!=NULL) { + if (map->num_types>0) { + register int i; + XkbKeyTypePtr type; + for (i=0,type=map->types;i<map->num_types;i++,type++) { + if (type->map!=NULL) { + _XkbFree(type->map); + type->map= NULL; + } + if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= 0; + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + _XkbFree(map->types); + map->num_types= map->size_types= 0; + map->types= NULL; + } + } + if (what&XkbKeySymsMask) { + if (map->key_sym_map!=NULL) { + _XkbFree(map->key_sym_map); + map->key_sym_map= NULL; + } + if (map->syms!=NULL) { + _XkbFree(map->syms); + map->size_syms= map->num_syms= 0; + map->syms= NULL; + } + } + if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) { + _XkbFree(map->modmap); + map->modmap= NULL; + } + if (freeMap) { + _XkbFree(xkb->map); + xkb->map= NULL; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap) +#else +XkbFreeServerMap(xkb,what,freeMap) + XkbDescPtr xkb; + unsigned what; + Bool freeMap; +#endif +{ +XkbServerMapPtr map; + + if ((xkb==NULL)||(xkb->server==NULL)) + return; + if (freeMap) + what= XkbAllServerInfoMask; + map= xkb->server; + if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) { + _XkbFree(map->explicit); + map->explicit= NULL; + } + if (what&XkbKeyActionsMask) { + if (map->key_acts!=NULL) { + _XkbFree(map->key_acts); + map->key_acts= NULL; + } + if (map->acts!=NULL) { + _XkbFree(map->acts); + map->num_acts= map->size_acts= 0; + map->acts= NULL; + } + } + if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) { + _XkbFree(map->behaviors); + map->behaviors= NULL; + } + if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) { + _XkbFree(map->vmodmap); + map->vmodmap= NULL; + } + + if (freeMap) { + _XkbFree(xkb->server); + xkb->server= NULL; + } + return; +} diff --git a/xkb/XKBMisc.c b/xkb/XKBMisc.c new file mode 100644 index 000000000..45c00692a --- /dev/null +++ b/xkb/XKBMisc.c @@ -0,0 +1,1071 @@ +/* $Xorg: XKBMisc.c,v 1.4 2000/08/17 19:45:02 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#ifndef XKB_IN_SERVER + +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xlibint.h" +#include <X11/extensions/XKBproto.h> +#include <X11/keysym.h> +#include "XKBlibint.h" + +#else + +#include <stdio.h> +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include <X11/keysym.h> +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif /* XKB_IN_SERVER */ + +/***====================================================================***/ + +#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec)) +static XkbKTMapEntryRec map2Level[]= { + { True, ShiftMask, 1, ShiftMask, 0 } +}; + +static XkbKTMapEntryRec mapAlpha[]= { + { True, ShiftMask, 1, ShiftMask, 0 }, + { True, LockMask, 0, LockMask, 0 } +}; + +static XkbModsRec preAlpha[]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; + +#define NL_VMOD_MASK 0 +static XkbKTMapEntryRec mapKeypad[]= { + { True, ShiftMask, 1, ShiftMask, 0 }, + { False, 0, 1, 0, NL_VMOD_MASK } +}; + +static XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = { + { { 0, 0, 0 }, + 1, /* num_levels */ + 0, /* map_count */ + NULL, NULL, + None, NULL + }, + { { ShiftMask, ShiftMask, 0 }, + 2, /* num_levels */ + mapSize(map2Level), /* map_count */ + map2Level, NULL, + None, NULL + }, + { { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, /* num_levels */ + mapSize(mapAlpha), /* map_count */ + mapAlpha, preAlpha, + None, NULL + }, + { { ShiftMask, ShiftMask, NL_VMOD_MASK }, + 2, /* num_levels */ + mapSize(mapKeypad), /* map_count */ + mapKeypad, NULL, + None, NULL + } +}; + +Status +#if NeedFunctionPrototypes +XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod) +#else +XkbInitCanonicalKeyTypes(xkb,which,keypadVMod) + XkbDescPtr xkb; + unsigned which; + int keypadVMod; +#endif +{ +XkbClientMapPtr map; +XkbKeyTypePtr from,to; +Status rtrn; + + if (!xkb) + return BadMatch; + rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes); + if (rtrn!=Success) + return rtrn; + map= xkb->map; + if ((which&XkbAllRequiredTypes)==0) + return Success; + rtrn= Success; + from= canonicalTypes; + to= map->types; + if (which&XkbOneLevelMask) + rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]); + if ((which&XkbTwoLevelMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]); + if ((which&XkbAlphabeticMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]); + if ((which&XkbKeypadMask)&&(rtrn==Success)) { + XkbKeyTypePtr type; + rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]); + type= &to[XkbKeypadIndex]; + if ((keypadVMod>=0)&&(keypadVMod<XkbNumVirtualMods)&&(rtrn==Success)) { + type->mods.vmods= (1<<keypadVMod); + type->map[0].active= True; + type->map[0].mods.mask= ShiftMask; + type->map[0].mods.real_mods= ShiftMask; + type->map[0].mods.vmods= 0; + type->map[0].level= 1; + type->map[1].active= False; + type->map[1].mods.mask= 0; + type->map[1].mods.real_mods= 0; + type->map[1].mods.vmods= (1<<keypadVMod); + type->map[1].level= 1; + } + } + return Success; +} + +/***====================================================================***/ + +#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) +#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) + +int +#if NeedFunctionPrototypes +XkbKeyTypesForCoreSymbols( XkbDescPtr xkb, + int map_width, + KeySym * core_syms, + unsigned int protected, + int * types_inout, + KeySym * xkb_syms_rtrn) +#else +XkbKeyTypesForCoreSymbols(xkb,map_width,core_syms,protected,types_inout, + xkb_syms_rtrn) + XkbDescPtr xkb; + int map_width; + KeySym * core_syms; + unsigned int protected; + int * types_inout; + KeySym * xkb_syms_rtrn; +#endif +{ +register int i; +unsigned int empty; +int nSyms[XkbNumKbdGroups]; +int nGroups,tmp,groupsWidth; + + /* Section 12.2 of the protocol describes this process in more detail */ + /* Step 1: find the # of symbols in the core mapping per group */ + groupsWidth= 2; + for (i=0;i<XkbNumKbdGroups;i++) { + if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { + nSyms[i]= xkb->map->types[types_inout[i]].num_levels; + if (nSyms[i]>groupsWidth) + groupsWidth= nSyms[i]; + } + else { + types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ + nSyms[i]= 2; + } + } + if (nSyms[XkbGroup1Index]<2) + nSyms[XkbGroup1Index]= 2; + if (nSyms[XkbGroup2Index]<2) + nSyms[XkbGroup2Index]= 2; + /* Step 2: Copy the symbols from the core ordering to XKB ordering */ + /* symbols in the core are in the order: */ + /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); + for (i=2;i<nSyms[XkbGroup1Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); + } + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); + tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ + for (i=2;i<nSyms[XkbGroup2Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); + } + tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; + if ((tmp>=map_width)&& + ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { + nSyms[XkbGroup3Index]= 0; + nSyms[XkbGroup4Index]= 0; + nGroups= 2; + } + else { + nGroups= 3; + for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); + } + if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { + nGroups= 4; + for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); + } + } + else { + nSyms[XkbGroup4Index]= 0; + } + } + /* steps 3&4: alphanumeric expansion, assign canonical types */ + empty= 0; + for (i=0;i<nGroups;i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if (upper!=lower) { + xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; + xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; + if ((protected&(1<<i))==0) + types_inout[i]= XkbAlphabeticIndex; + } + else if ((protected&(1<<i))==0) { + types_inout[i]= XkbOneLevelIndex; + /* nSyms[i]= 1;*/ + } + } + if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { + if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1])) + types_inout[i]= XkbKeypadIndex; + else { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if ((syms[0]==lower)&&(syms[1]==upper)) + types_inout[i]= XkbAlphabeticIndex; + } + } + if (syms[0]==NoSymbol) { + register int n; + Bool found; + for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) { + found= (syms[n]!=NoSymbol); + } + if (!found) + empty|= (1<<i); + } + } + /* step 5: squoosh out empty groups */ + if (empty) { + for (i=nGroups-1;i>=0;i--) { + if (((empty&(1<<i))==0)||(protected&(1<<i))) + break; + nGroups--; + } + } + if (nGroups<1) + return 0; + + /* step 6: replicate group 1 into group two, if necessary */ + if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { + if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { + nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; + types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; + memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, + 2*sizeof(KeySym)); + } + else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { + memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], + (char *)xkb_syms_rtrn, + nSyms[XkbGroup1Index]*sizeof(KeySym)); + } + } + + /* step 7: check for all groups identical or all width 1 */ + if (nGroups>1) { + Bool sameType,allOneLevel; + allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); + for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) { + sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); + if (allOneLevel) + allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); + } + if ((sameType)&& + (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ + register int s; + Bool identical; + for (i=1,identical=True;identical&&(i<nGroups);i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + for (s=0;identical&&(s<nSyms[i]);s++) { + if (syms[s]!=xkb_syms_rtrn[s]) + identical= False; + } + } + if (identical) + nGroups= 1; + } + if (allOneLevel && (nGroups>1)) { + KeySym *syms; + syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; + nSyms[XkbGroup1Index]= 1; + for (i=1;i<nGroups;i++) { + xkb_syms_rtrn[i]= syms[0]; + syms+= nSyms[i]; + nSyms[i]= 1; + } + } + } + return nGroups; +} + +static XkbSymInterpretPtr +#if NeedFunctionPrototypes +_XkbFindMatchingInterp( XkbDescPtr xkb, + KeySym sym, + unsigned int real_mods, + unsigned int level) +#else +_XkbFindMatchingInterp(xkb,sym,real_mods,level) + XkbDescPtr xkb; + KeySym sym; + unsigned int real_mods; + unsigned int level; +#endif +{ +register unsigned i; +XkbSymInterpretPtr interp,rtrn; +CARD8 mods; + + rtrn= NULL; + interp= xkb->compat->sym_interpret; + for (i=0;i<xkb->compat->num_si;i++,interp++) { + if ((interp->sym==NoSymbol)||(sym==interp->sym)) { + int match; + if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) + mods= real_mods; + else mods= 0; + switch (interp->match&XkbSI_OpMask) { + case XkbSI_NoneOf: + match= ((interp->mods&mods)==0); + break; + case XkbSI_AnyOfOrNone: + match= ((mods==0)||((interp->mods&mods)!=0)); + break; + case XkbSI_AnyOf: + match= ((interp->mods&mods)!=0); + break; + case XkbSI_AllOf: + match= ((interp->mods&mods)==interp->mods); + break; + case XkbSI_Exactly: + match= (interp->mods==mods); + break; + default: + match= 0; + break; + } + if (match) { + if (interp->sym!=NoSymbol) { + return interp; + } + else if (rtrn==NULL) { + rtrn= interp; + } + } + } + } + return rtrn; +} + +static void +#if NeedFunctionPrototypes +_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) +#else +_XkbAddKeyChange(pFirst,pNum,newKey) + KeyCode * pFirst; + unsigned char * pNum; + KeyCode newKey; +#endif +{ +KeyCode last; + + last= (*pFirst)+(*pNum); + if (newKey<*pFirst) { + *pFirst= newKey; + *pNum= (last-newKey)+1; + } + else if (newKey>last) { + *pNum= (last-*pFirst)+1; + } + return; +} + +static void +#if NeedFunctionPrototypes +_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +#else +_XkbSetActionKeyMods(xkb,act,mods) + XkbDescPtr xkb; + XkbAction * act; + unsigned mods; +#endif +{ +unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask|= tmp; + } + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask|= tmp; + } + break; + } + return; +} + +#define IBUF_SIZE 8 + +Bool +#if NeedFunctionPrototypes +XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) +#else +XkbApplyCompatMapToKey(xkb,key,changes) + XkbDescPtr xkb; + KeyCode key; + XkbChangesPtr changes; +#endif +{ +KeySym * syms; +unsigned char explicit,mods; +XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; +int n,nSyms,found; +unsigned changed,tmp; + + if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| + (!xkb->compat)||(!xkb->compat->sym_interpret)|| + (key<xkb->min_key_code)||(key>xkb->max_key_code)) { + return False; + } + if (((!xkb->server)||(!xkb->server->key_acts))&& + (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { + return False; + } + changed= 0; /* keeps track of what has changed in _this_ call */ + explicit= xkb->server->explicit[key]; + if (explicit&XkbExplicitInterpretMask) /* nothing to do */ + return True; + mods= (xkb->map->modmap?xkb->map->modmap[key]:0); + nSyms= XkbKeyNumSyms(xkb,key); + syms= XkbKeySymsPtr(xkb,key); + if (nSyms>IBUF_SIZE) { + interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); + if (interps==NULL) { + interps= ibuf; + nSyms= IBUF_SIZE; + } + } + else { + interps= ibuf; + } + found= 0; + for (n=0;n<nSyms;n++) { + unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); + interps[n]= NULL; + if (syms[n]!=NoSymbol) { + interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); + if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) + found++; + else interps[n]= NULL; + } + } + /* 1/28/96 (ef) -- XXX! WORKING HERE */ + if (!found) { + if (xkb->server->key_acts[key]!=0) { + xkb->server->key_acts[key]= 0; + changed|= XkbKeyActionsMask; + } + } + else { + XkbAction *pActs; + unsigned int new_vmodmask; + changed|= XkbKeyActionsMask; + pActs= XkbResizeKeyActions(xkb,key,nSyms); + if (!pActs) + return False; + new_vmodmask= 0; + for (n=0;n<nSyms;n++) { + if (interps[n]) { + unsigned effMods; + + pActs[n]= *((XkbAction *)&interps[n]->act); + if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { + effMods= mods; + if (interps[n]->virtual_mod!=XkbNoModifier) + new_vmodmask|= (1<<interps[n]->virtual_mod); + } + else effMods= 0; + _XkbSetActionKeyMods(xkb,&pActs[n],effMods); + } + else pActs[n].type= XkbSA_NoAction; + } + if (((explicit&XkbExplicitVModMapMask)==0)&& + (xkb->server->vmodmap[key]!=new_vmodmask)) { + changed|= XkbVirtualModMapMask; + xkb->server->vmodmap[key]= new_vmodmask; + } + if (interps[0]) { + if ((interps[0]->flags&XkbSI_LockingKey)&& + ((explicit&XkbExplicitBehaviorMask)==0)) { + xkb->server->behaviors[key].type= XkbKB_Lock; + changed|= XkbKeyBehaviorsMask; + } + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; + if (interps[0]->flags&XkbSI_AutoRepeat) + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + } + } + if ((!found)||(interps[0]==NULL)) { + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; +#if RETURN_SHOULD_REPEAT + if (*XkbKeySymsPtr(xkb,key) != XK_Return) +#endif + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + if (((explicit&XkbExplicitBehaviorMask)==0)&& + (xkb->server->behaviors[key].type==XkbKB_Lock)) { + xkb->server->behaviors[key].type= XkbKB_Default; + changed|= XkbKeyBehaviorsMask; + } + } + if (changes) { + XkbMapChangesPtr mc; + mc= &changes->map; + tmp= (changed&mc->changed); + if (tmp&XkbKeyActionsMask) + _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); + else if (changed&XkbKeyActionsMask) { + mc->changed|= XkbKeyActionsMask; + mc->first_key_act= key; + mc->num_key_acts= 1; + } + if (tmp&XkbKeyBehaviorsMask) { + _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, + key); + } + else if (changed&XkbKeyBehaviorsMask) { + mc->changed|= XkbKeyBehaviorsMask; + mc->first_key_behavior= key; + mc->num_key_behaviors= 1; + } + if (tmp&XkbVirtualModMapMask) + _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); + else if (changed&XkbVirtualModMapMask) { + mc->changed|= XkbVirtualModMapMask; + mc->first_vmodmap_key= key; + mc->num_vmodmap_keys= 1; + } + mc->changed|= changed; + } + if (interps!=ibuf) + _XkbFree(interps); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbUpdateMapFromCore( XkbDescPtr xkb, + KeyCode first_key, + int num_keys, + int map_width, + KeySym * core_keysyms, + XkbChangesPtr changes) +#else +XkbUpdateMapFromCore(xkb,first_key,num_keys,map_width,core_keysyms,changes) + XkbDescPtr xkb; + KeyCode first_key; + int num_keys; + int map_width; + KeySym * core_keysyms; + XkbChangesPtr changes; +#endif +{ +register int key,last_key; +KeySym * syms; + + syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width]; + if (changes) { + if (changes->map.changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms,first_key); + if (num_keys>1) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms, + first_key+num_keys-1); + } + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym= first_key; + changes->map.num_key_syms= num_keys; + } + } + last_key= first_key+num_keys-1; + for (key=first_key;key<=last_key;key++,syms+= map_width) { + XkbMapChangesPtr mc; + unsigned explicit; + KeySym tsyms[XkbMaxSymsPerKey]; + int types[XkbNumKbdGroups]; + int nG; + + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms); + if (changes) + mc= &changes->map; + else mc= NULL; + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if ((xkb->server->vmods!=NULL)&&(xkb->map->modmap!=NULL)&&(changes)&& + (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bit&xkb->server->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes && (changes->map.changed&XkbVirtualModsMask)) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + return True; +} + +Status +#if NeedFunctionPrototypes +XkbChangeTypesOfKey( XkbDescPtr xkb, + int key, + int nGroups, + unsigned groups, + int * newTypesIn, + XkbMapChangesPtr changes) +#else +XkbChangeTypesOfKey(xkb,key,nGroups,groups,newTypesIn,changes) + XkbDescPtr xkb; + int key; + int nGroups; + unsigned groups; + int * newTypesIn; + XkbMapChangesPtr changes; +#endif +{ +XkbKeyTypePtr pOldType,pNewType; +register int i; +int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; + + if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || + (!xkb->map->types)||(!newTypes)||((groups&XkbAllGroupsMask)==0)|| + (nGroups>XkbNumKbdGroups)) { + return BadMatch; + } + if (nGroups==0) { + for (i=0;i<XkbNumKbdGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,0); + xkb->map->key_sym_map[key].group_info= i; + XkbResizeKeySyms(xkb,key,0); + return Success; + } + + nOldGroups= XkbKeyNumGroups(xkb,key); + oldWidth= XkbKeyGroupsWidth(xkb,key); + for (width=i=0;i<nGroups;i++) { + if (groups&(1<<i)) + newTypes[i]= newTypesIn[i]; + else if (i<nOldGroups) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); + else if (nOldGroups>0) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + else newTypes[i]= XkbTwoLevelIndex; + if (newTypes[i]>xkb->map->num_types) + return BadMatch; + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>width) + width= pNewType->num_levels; + } + if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) + xkb->ctrls->num_groups= nGroups; + if ((width!=oldWidth)||(nGroups!=nOldGroups)) { + KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; + int nCopy; + + if (nOldGroups==0) { + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms!=NULL) { + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + } + return Success; + } + return BadAlloc; + } + pSyms= XkbKeySymsPtr(xkb,key); + memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms==NULL) + return BadAlloc; + bzero(pSyms,width*nGroups*sizeof(KeySym)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); + } + if (XkbKeyHasActions(xkb,key)) { + XkbAction oldActs[XkbMaxSymsPerKey],*pActs; + pActs= XkbKeyActionsPtr(xkb,key); + memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); + pActs= XkbResizeKeyActions(xkb,key,width*nGroups); + if (pActs==NULL) + return BadAlloc; + bzero(pActs,width*nGroups*sizeof(XkbAction)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pActs[i*width],&oldActs[i*oldWidth], + nCopy*sizeof(XkbAction)); + } + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + } + width= 0; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + if (xkb->map->types[newTypes[i]].num_levels>width) + width= xkb->map->types[newTypes[i]].num_levels; + } + xkb->map->key_sym_map[key].width= width; + if (changes!=NULL) { + if (changes->changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, + key); + } + else { + changes->changed|= XkbKeySymsMask; + changes->first_key_sym= key; + changes->num_key_syms= 1; + } + } + return Success; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) +#else +XkbVirtualModsToReal(xkb,virtual_mask,mask_rtrn) + XkbDescPtr xkb; + unsigned virtual_mask; + unsigned * mask_rtrn; +#endif +{ +register int i,bit; +register unsigned mask; + + if (xkb==NULL) + return False; + if (virtual_mask==0) { + *mask_rtrn= 0; + return True; + } + if (xkb->server==NULL) + return False; + for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (virtual_mask&bit) + mask|= xkb->server->vmods[i]; + } + *mask_rtrn= mask; + return True; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) +#else +XkbUpdateActionVirtualMods(xkb,act,changed) + XkbDescPtr xkb; + XkbAction * act; + unsigned changed; +#endif +{ +unsigned int tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask= act->mods.real_mods; + act->mods.mask|= tmp; + return True; + } + break; + case XkbSA_ISOLock: + if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask= act->iso.real_mods; + act->iso.mask|= tmp; + return True; + } + break; + } + return False; +} + +void +#if NeedFunctionPrototypes +XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, + XkbKeyTypePtr type, + unsigned int changed, + XkbChangesPtr changes) +#else +XkbUpdateKeyTypeVirtualMods(xkb,type,changed,changes) + XkbDescPtr xkb; + XkbKeyTypePtr type; + unsigned int changed; + XkbChangesPtr changes; +#endif +{ +register unsigned int i; +unsigned int mask; + + XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); + type->mods.mask= type->mods.real_mods|mask; + if ((type->map_count>0)&&(type->mods.vmods!=0)) { + XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;i<type->map_count;i++,entry++) { + if (entry->mods.vmods!=0) { + XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); + entry->mods.mask=entry->mods.real_mods|mask; + /* entry is active if vmods are bound*/ + entry->active= (mask!=0); + } + else entry->active= 1; + } + } + if (changes) { + int type_ndx; + type_ndx= type-xkb->map->types; + if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) + return; + if (changes->map.changed&XkbKeyTypesMask) { + int last; + last= changes->map.first_type+changes->map.num_types-1; + if (type_ndx<changes->map.first_type) { + changes->map.first_type= type_ndx; + changes->map.num_types= (last-type_ndx)+1; + } + else if (type_ndx>last) { + changes->map.num_types= (type_ndx-changes->map.first_type)+1; + } + } + else { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= type_ndx; + changes->map.num_types= 1; + } + } + return; +} + +Bool +#if NeedFunctionPrototypes +XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) +#else +XkbApplyVirtualModChanges(xkb,changed,changes) + XkbDescPtr xkb; + unsigned changed; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned checkState; + + if ((!xkb) || (!xkb->map) || (changed==0)) + return False; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].mods.vmods & changed) + XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); + } + if (changed&xkb->ctrls->internal.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); + newMask|= xkb->ctrls->internal.real_mods; + if (xkb->ctrls->internal.mask!=newMask) { + xkb->ctrls->internal.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbInternalModsMask; + checkState= True; + } + } + } + if (changed&xkb->ctrls->ignore_lock.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); + newMask|= xkb->ctrls->ignore_lock.real_mods; + if (xkb->ctrls->ignore_lock.mask!=newMask) { + xkb->ctrls->ignore_lock.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; + checkState= True; + } + } + } + if (xkb->indicators!=NULL) { + XkbIndicatorMapPtr map; + map= &xkb->indicators->maps[0]; + for (i=0;i<XkbNumIndicators;i++,map++) { + if (map->mods.vmods&changed) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); + newMask|= map->mods.real_mods; + if (newMask!=map->mods.mask) { + map->mods.mask= newMask; + if (changes) { + changes->indicators.map_changes|= (1<<i); + checkState= True; + } + } + } + } + } + if (xkb->compat!=NULL) { + XkbCompatMapPtr compat; + compat= xkb->compat; + for (i=0;i<XkbNumKbdGroups;i++) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); + newMask|= compat->groups[i].real_mods; + if (compat->groups[i].mask!=newMask) { + compat->groups[i].mask= newMask; + if (changes) { + changes->compat.changed_groups|= (1<<i); + checkState= True; + } + } + } + } + if (xkb->map && xkb->server) { + int highChange,lowChange; + lowChange= -1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyHasActions(xkb,i)) { + register XkbAction *pAct; + register int n; + + pAct= XkbKeyActionsPtr(xkb,i); + for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { + if ((pAct->type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,pAct,changed)) { + if (lowChange<0) + lowChange= i; + highChange= i; + } + } + } + } + if (changes && (lowChange>0)) { /* something changed */ + if (changes->map.changed&XkbKeyActionsMask) { + int last; + if (changes->map.first_key_act<lowChange) + lowChange= changes->map.first_key_act; + last= changes->map.first_key_act+changes->map.num_key_acts-1; + if (last>highChange) + highChange= last; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= lowChange; + changes->map.num_key_acts= (highChange-lowChange)+1; + } + } + return checkState; +} diff --git a/xkb/ddxBeep.c b/xkb/ddxBeep.c new file mode 100644 index 000000000..3f3ae57a0 --- /dev/null +++ b/xkb/ddxBeep.c @@ -0,0 +1,359 @@ +/* $Xorg: ddxBeep.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +#if (defined(__osf__) && defined(__alpha)) +#include <sys/sysinfo.h> +#include <alpha/hal_sysinfo.h> +#include <alpha/prom.h> +#endif + +/*#define FALLING_TONE 1*/ +/*#define RISING_TONE 1*/ +#define FALLING_TONE 10 +#define RISING_TONE 10 +#define SHORT_TONE 50 +#define SHORT_DELAY 60 +#define LONG_TONE 75 +#define VERY_LONG_TONE 100 +#define LONG_DELAY 85 +#define CLICK_DURATION 1 + +#define DEEP_PITCH 250 +#define LOW_PITCH 500 +#define MID_PITCH 1000 +#define HIGH_PITCH 2000 +#define CLICK_PITCH 1500 + +static unsigned long atomGeneration= -1; +static Atom featureOn; +static Atom featureOff; +static Atom featureChange; +static Atom ledOn; +static Atom ledOff; +static Atom ledChange; +static Atom slowWarn; +static Atom slowPress; +static Atom slowReject; +static Atom slowAccept; +static Atom slowRelease; +static Atom stickyLatch; +static Atom stickyLock; +static Atom stickyUnlock; +static Atom bounceReject; +static char doesPitch = 1; + +#define FEATURE_ON "AX_FeatureOn" +#define FEATURE_OFF "AX_FeatureOff" +#define FEATURE_CHANGE "AX_FeatureChange" +#define LED_ON "AX_IndicatorOn" +#define LED_OFF "AX_IndicatorOff" +#define LED_CHANGE "AX_IndicatorChange" +#define SLOW_WARN "AX_SlowKeysWarning" +#define SLOW_PRESS "AX_SlowKeyPress" +#define SLOW_REJECT "AX_SlowKeyReject" +#define SLOW_ACCEPT "AX_SlowKeyAccept" +#define SLOW_RELEASE "AX_SlowKeyRelease" +#define STICKY_LATCH "AX_StickyLatch" +#define STICKY_LOCK "AX_StickyLock" +#define STICKY_UNLOCK "AX_StickyUnlock" +#define BOUNCE_REJECT "AX_BounceKeyReject" + +#define MAKE_ATOM(a) MakeAtom(a,sizeof(a)-1,True) + +static void +#if NeedFunctionPrototypes +_XkbDDXBeepInitAtoms(void) +#else +_XkbDDXBeepInitAtoms() +#endif +{ + featureOn= MAKE_ATOM(FEATURE_ON); + featureOff= MAKE_ATOM(FEATURE_OFF); + featureChange= MAKE_ATOM(FEATURE_CHANGE); + ledOn= MAKE_ATOM(LED_ON); + ledOff= MAKE_ATOM(LED_OFF); + ledChange= MAKE_ATOM(LED_CHANGE); + slowWarn= MAKE_ATOM(SLOW_WARN); + slowPress= MAKE_ATOM(SLOW_PRESS); + slowReject= MAKE_ATOM(SLOW_REJECT); + slowAccept= MAKE_ATOM(SLOW_ACCEPT); + slowRelease= MAKE_ATOM(SLOW_RELEASE); + stickyLatch= MAKE_ATOM(STICKY_LATCH); + stickyLock= MAKE_ATOM(STICKY_LOCK); + stickyUnlock= MAKE_ATOM(STICKY_UNLOCK); + bounceReject= MAKE_ATOM(BOUNCE_REJECT); +#if (defined(__osf__) && defined(__alpha)) + /* [[[ WDW - Some bells do not allow for pitch changes. + * Maybe this could become part of the keymap? ]]] + */ + { + char keyboard[8]; + + /* Find the class of keyboard being used. + */ + keyboard[0] = '\0'; + if (-1 == getsysinfo(GSI_KEYBOARD, + keyboard, sizeof(keyboard), + 0, NULL)) + keyboard[0] = '\0'; + + if ((strcmp(keyboard,"LK201") == 0) || + (strcmp(keyboard,"LK401") == 0) || + (strcmp(keyboard,"LK421") == 0) || + (strcmp(keyboard,"LK443") == 0)) + doesPitch = 0; + } +#endif + return; +} + +static CARD32 +#if NeedFunctionPrototypes +_XkbDDXBeepExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +_XkbDDXBeepExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr dev= (DeviceIntPtr)arg; +KbdFeedbackPtr feed; +KeybdCtrl * ctrl; +XkbSrvInfoPtr xkbInfo; +CARD32 next; +int pitch,duration; +int oldPitch,oldDuration; +Atom name; + + if ((dev==NULL)||(dev->key==NULL)||(dev->key->xkbInfo==NULL)|| + (dev->kbdfeed==NULL)) + return 0; + if (atomGeneration!=serverGeneration) { + _XkbDDXBeepInitAtoms(); + atomGeneration= serverGeneration; + } + + feed= dev->kbdfeed; + ctrl= &feed->ctrl; + xkbInfo= dev->key->xkbInfo; + next= 0; + pitch= oldPitch= ctrl->bell_pitch; + duration= oldDuration= ctrl->bell_duration; +#ifdef DEBUG + if (xkbDebugFlags>1) + ErrorF("beep: %d (count= %d)\n",xkbInfo->beepType,xkbInfo->beepCount); +#endif + name= None; + switch (xkbInfo->beepType) { + default: + ErrorF("Unknown beep type %d\n",xkbInfo->beepType); + case _BEEP_NONE: + duration= 0; + break; + + /* When an LED is turned on, we want a high-pitched beep. + * When the LED it turned off, we want a low-pitched beep. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_LED_ON: + if (name==None) name= ledOn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + break; + case _BEEP_LED_OFF: + if (name==None) name= ledOff; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + + /* When a Feature is turned on, we want an up-siren. + * When a Feature is turned off, we want a down-siren. + * If we cannot do pitch, we want a single beep for on and two + * beeps for off. + */ + case _BEEP_FEATURE_ON: + if (name==None) name= featureOn; + if (xkbInfo->beepCount<1) { + pitch= LOW_PITCH; + duration= VERY_LONG_TONE; + if (doesPitch) + next= SHORT_DELAY; + } + else { + pitch= MID_PITCH; + duration= SHORT_TONE; + } + break; + + case _BEEP_FEATURE_OFF: + if (name==None) name= featureOff; + if (xkbInfo->beepCount<1) { + pitch= MID_PITCH; + if (doesPitch) + duration= VERY_LONG_TONE; + else duration= SHORT_TONE; + next= SHORT_DELAY; + } + else { + pitch= LOW_PITCH; + duration= SHORT_TONE; + } + break; + + /* Two high beeps indicate an LED or Feature changed + * state, but that another LED or Feature is also on. + * [[[WDW - This is not in AccessDOS ]]] + */ + case _BEEP_LED_CHANGE: + if (name==None) name= ledChange; + case _BEEP_FEATURE_CHANGE: + if (name==None) name= featureChange; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + } + break; + + /* Three high-pitched beeps are the warning that SlowKeys + * is going to be turned on or off. + */ + case _BEEP_SLOW_WARN: + if (name==None) name= slowWarn; + duration= SHORT_TONE; + pitch= HIGH_PITCH; + if (xkbInfo->beepCount<2) + next= SHORT_DELAY; + break; + + /* Click on SlowKeys press and accept. + * Deep pitch when a SlowKey or BounceKey is rejected. + * [[[WDW - Rejects are not in AccessDOS ]]] + * If we cannot do pitch, we want single beeps. + */ + case _BEEP_SLOW_PRESS: + if (name==None) name= slowPress; + case _BEEP_SLOW_ACCEPT: + if (name==None) name= slowAccept; + case _BEEP_SLOW_RELEASE: + if (name==None) name= slowRelease; + duration= CLICK_DURATION; + pitch= CLICK_PITCH; + break; + case _BEEP_BOUNCE_REJECT: + if (name==None) name= bounceReject; + case _BEEP_SLOW_REJECT: + if (name==None) name= slowReject; + duration= SHORT_TONE; + pitch= DEEP_PITCH; + break; + + /* Low followed by high pitch when a StickyKey is latched. + * High pitch when a StickyKey is locked. + * Low pitch when unlocked. + * If we cannot do pitch, two beeps for latch, nothing for + * lock, and two for unlock. + */ + case _BEEP_STICKY_LATCH: + if (name==None) name= stickyLatch; + duration= SHORT_TONE; + if (xkbInfo->beepCount<1) { + next= SHORT_DELAY; + pitch= LOW_PITCH; + } + else pitch= HIGH_PITCH; + break; + case _BEEP_STICKY_LOCK: + if (name==None) name= stickyLock; + if (doesPitch) { + duration= SHORT_TONE; + pitch= HIGH_PITCH; + } + break; + case _BEEP_STICKY_UNLOCK: + if (name==None) name= stickyUnlock; + duration= SHORT_TONE; + pitch= LOW_PITCH; + if (!doesPitch && xkbInfo->beepCount<1) + next = SHORT_DELAY; + break; + } + if (duration>0) { + ctrl->bell_duration= duration; + ctrl->bell_pitch= pitch; + if (xkbInfo->beepCount==0) { + XkbHandleBell(0,0,dev,ctrl->bell,(pointer)ctrl,KbdFeedbackClass,name,None, + NULL); + } + else if (xkbInfo->desc->ctrls->enabled_ctrls&XkbAudibleBellMask) { + (*dev->kbdfeed->BellProc)(ctrl->bell,dev,(pointer)ctrl,KbdFeedbackClass); + } + ctrl->bell_duration= oldDuration; + ctrl->bell_pitch= oldPitch; + xkbInfo->beepCount++; + } + return next; +} + +int +#if NeedFunctionPrototypes +XkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which) +#else +XkbDDXAccessXBeep(dev,what,which) + DeviceIntPtr dev; + unsigned what; + unsigned which; +#endif +{ +XkbSrvInfoRec *xkbInfo= dev->key->xkbInfo; +CARD32 next; + + xkbInfo->beepType= what; + xkbInfo->beepCount= 0; + next= _XkbDDXBeepExpire(NULL,0,(pointer)dev); + if (next>0) { + xkbInfo->beepTimer= TimerSet(xkbInfo->beepTimer, + 0, next, + _XkbDDXBeepExpire, (pointer)dev); + } + return 1; +} diff --git a/xkb/ddxConfig.c b/xkb/ddxConfig.c new file mode 100644 index 000000000..f3635902f --- /dev/null +++ b/xkb/ddxConfig.c @@ -0,0 +1,217 @@ +/* $Xorg: ddxConfig.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "os.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include <X11/extensions/XKBconfig.h> + +Bool +#if NeedFunctionPrototypes +XkbDDXApplyConfig(XPointer cfg_in,XkbSrvInfoPtr info) +#else +XkbDDXApplyConfig(cfg_in,info) + XPointer cfg_in; + XkbSrvInfoPtr info; +#endif +{ +XkbConfigRtrnPtr rtrn; +XkbDescPtr xkb; +Bool ok; +XkbEventCauseRec cause; + + xkb= info->desc; + rtrn= (XkbConfigRtrnPtr)cfg_in; + if (rtrn==NULL) + return True; + ok= XkbCFApplyRtrnValues(rtrn,XkbCFDflts,xkb); + if (rtrn->initial_mods.replace) { + info->state.locked_mods= rtrn->initial_mods.mods; + } + else { + info->state.locked_mods|= rtrn->initial_mods.mods; + if (rtrn->initial_mods.mods_clear) + info->state.locked_mods&= ~rtrn->initial_mods.mods_clear; + } + XkbComputeDerivedState(info); + XkbSetCauseUnknown(&cause); + XkbUpdateIndicators(info->device,XkbAllIndicatorsMask,False,NULL,&cause); + if (info->device && info->device->kbdfeed) { + DeviceIntPtr dev; + KeybdCtrl newCtrl; + dev= info->device; + newCtrl= dev->kbdfeed->ctrl; + if (rtrn->click_volume>=0) + newCtrl.click= rtrn->click_volume; + if (rtrn->bell_volume>=0) + newCtrl.bell= rtrn->bell_volume; + if (rtrn->bell_pitch>0) + newCtrl.bell_pitch= rtrn->bell_pitch; + if (rtrn->bell_duration>0) + newCtrl.bell_duration= rtrn->bell_duration; + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&newCtrl); + } + XkbCFFreeRtrn(rtrn,XkbCFDflts,xkb); + return ok; +} + +XPointer +#if NeedFunctionPrototypes +XkbDDXPreloadConfig( char ** rulesRtrn, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names, + DeviceIntPtr dev) +#else +XkbDDXPreloadConfig(rulesRtrn,defs,names,dev) + char ** rulesRtrn; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; + DeviceIntPtr dev; +#endif +{ +char buf[PATH_MAX]; +char * dName; +FILE * file; +XkbConfigRtrnPtr rtrn; +extern char * display; + +#if defined(MetroLink) + if (dev && dev->name) + dName= dev->name; + else dName= ""; + /* It doesn't appear that XkbBaseDirectory could ever get set to NULL */ + sprintf(buf,"%s/X%s-config%s%s",XkbBaseDirectory,display, + (dName[0]?".":""),dName); +#else + if (dev && dev->name) + dName= dev->name; + else dName= ""; + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)+strlen(display) + +strlen(dName)+10+(dName[0]?1:0) > PATH_MAX) + { +#ifdef DEBUG + ErrorF("path exceeds max length\n"); +#endif + return NULL; + } + sprintf(buf,"%s/X%s-config%s%s",XkbBaseDirectory,display, + (dName[0]?".":""),dName); + } + else { + if (strlen(display)+strlen(dName)+10+(dName[0]?1:0) > PATH_MAX) + { +#ifdef DEBUG + ErrorF("path exceeds max length\n"); +#endif + return NULL; + } + sprintf(buf,"X%s-config%s%s",display,(dName[0]?".":""),dName); + } +#endif +#ifdef DEBUG + ErrorF("Looking for keyboard configuration in %s...",buf); +#endif + file= fopen(buf,"r"); + if (file==NULL) { +#ifdef DEBUG + ErrorF("file not found\n"); +#endif + return NULL; + } + rtrn= _XkbTypedCalloc(1,XkbConfigRtrnRec); + if (rtrn!=NULL) { + if (!XkbCFParse(file,XkbCFDflts,NULL,rtrn)) { +#ifdef DEBUG + ErrorF("error\n"); +#endif + ErrorF("Error parsing config file: "); + XkbCFReportError(stderr,buf,rtrn->error,rtrn->line); + _XkbFree(rtrn); + fclose(file); + return NULL; + } +#ifdef DEBUG + ErrorF("found it\n"); +#endif + if (rtrn->rules_file) { + *rulesRtrn= rtrn->rules_file; + rtrn->rules_file= NULL; + } + if (rtrn->model) { + defs->model= rtrn->model; + rtrn->model= NULL; + } + if (rtrn->layout) { + defs->layout= rtrn->layout; + rtrn->layout= NULL; + } + if (rtrn->variant) { + defs->variant= rtrn->variant; + rtrn->variant= NULL; + } + if (rtrn->options) { + defs->options= rtrn->options; + rtrn->options= NULL; + } + XkbSetRulesUsed(defs); + + if (rtrn->keycodes!=NULL) { + names->keycodes= rtrn->keycodes; + rtrn->keycodes= NULL; + } + if (rtrn->geometry!=NULL) { + names->geometry= rtrn->geometry; + rtrn->geometry= NULL; + } + if (rtrn->symbols!=NULL) { + if (rtrn->phys_symbols==NULL) + rtrn->phys_symbols= _XkbDupString(names->symbols); + names->symbols= rtrn->symbols; + rtrn->symbols= NULL; + } + if (rtrn->types!=NULL) { + names->types= rtrn->types; + rtrn->types= NULL; + } + if (rtrn->compat!=NULL) { + names->compat= rtrn->compat; + rtrn->compat= NULL; + } + } + fclose(file); + return (XPointer)rtrn; +} diff --git a/xkb/ddxCtrls.c b/xkb/ddxCtrls.c new file mode 100644 index 000000000..da599fbf2 --- /dev/null +++ b/xkb/ddxCtrls.c @@ -0,0 +1,133 @@ +/* $Xorg: ddxCtrls.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXKeybdCtrlProc(DeviceIntPtr dev,KeybdCtrl *ctrl) +#else +XkbDDXKeybdCtrlProc(dev,ctrl) + DeviceIntPtr dev; + KeybdCtrl * ctrl; +#endif +{ +int realRepeat; + + realRepeat= ctrl->autoRepeat; + if ((dev->kbdfeed)&&(XkbDDXUsesSoftRepeat(dev))) + ctrl->autoRepeat= 0; +#ifdef DEBUG +if (xkbDebugFlags&0x4) { + ErrorF("XkbDDXKeybdCtrlProc: setting repeat to %d (real repeat is %d)\n", + ctrl->autoRepeat,realRepeat); +} +#endif + if (dev->key && dev->key->xkbInfo && dev->key->xkbInfo->kbdProc) + (*dev->key->xkbInfo->kbdProc)(dev,ctrl); + ctrl->autoRepeat= realRepeat; + return; +} + + +int +#if NeedFunctionPrototypes +XkbDDXUsesSoftRepeat(DeviceIntPtr pXDev) +#else +XkbDDXUsesSoftRepeat(pXDev) + DeviceIntPtr pXDev; +#endif +{ +#ifndef XKB_ALWAYS_USES_SOFT_REPEAT + if (pXDev && pXDev->kbdfeed ) { + if (pXDev->kbdfeed->ctrl.autoRepeat) { + if (pXDev->key && pXDev->key->xkbInfo) { + XkbDescPtr xkb; + xkb= pXDev->key->xkbInfo->desc; + if ((xkb->ctrls->repeat_delay == 660) && + (xkb->ctrls->repeat_interval == 40) && + ((xkb->ctrls->enabled_ctrls&(XkbSlowKeysMask| + XkbBounceKeysMask| + XkbMouseKeysMask))==0)) { + return 0; + } + return ((xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0); + } + } + } + return 0; +#else + return 1; +#endif +} + +void +#if NeedFunctionPrototypes +XkbDDXChangeControls(DeviceIntPtr dev,XkbControlsPtr old,XkbControlsPtr new) +#else +XkbDDXChangeControls(dev,old,new) + DeviceIntPtr dev; + XkbControlsPtr old; + XkbControlsPtr new; +#endif +{ +unsigned changed; + + changed= new->enabled_ctrls^old->enabled_ctrls; +#ifdef NOTDEF + if (changed&XkbRepeatKeysMask) { + if (dev->kbdfeed) { + int realRepeat; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + dev->kbdfeed->ctrl.autoRepeat= realRepeat= 1; + else dev->kbdfeed->ctrl.autoRepeat= realRepeat= 0; + + if (XkbDDXUsesSoftRepeat(dev)) + dev->kbdfeed->ctrl.autoRepeat= FALSE; + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + dev->kbdfeed->ctrl.autoRepeat= realRepeat; + } + } +#endif + if (changed&XkbPerKeyRepeatMask) { + if (dev->kbdfeed->CtrlProc) + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + } + return; +} + diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c new file mode 100644 index 000000000..7d641358f --- /dev/null +++ b/xkb/ddxDevBtn.c @@ -0,0 +1,104 @@ +/* $Xorg: ddxDevBtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" +#include "XIproto.h" + +extern int DeviceButtonPress,DeviceButtonRelease,DeviceValuator; + +void +#if NeedFunctionPrototypes +XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) +#else +XkbDDXFakeDeviceButton(dev,press,button) + DeviceIntPtr dev; + Bool press; + int button; +#endif +{ +int * devVal; +INT32 * evVal; +xEvent events[2]; +deviceKeyButtonPointer *btn; +deviceValuator * val; +int x,y; +int nAxes, i, count; + + if ((dev==(DeviceIntPtr)LookupPointerDevice())||(!dev->public.on)) + return; + + nAxes = (dev->valuator?dev->valuator->numAxes:0); + if (nAxes > 6) + nAxes = 6; + + GetSpritePosition(&x,&y); + btn= (deviceKeyButtonPointer *) &events[0]; + val= (deviceValuator *) &events[1]; + if (press) btn->type= DeviceButtonPress; + else btn->type= DeviceButtonRelease; + btn->detail= button; + btn->time= GetTimeInMillis(); + btn->root_x= x; + btn->root_y= y; + btn->deviceid= dev->id; + count= 1; + if (nAxes>0) { + btn->deviceid|= 0x80; + val->type = DeviceValuator; + val->deviceid = dev->id; + val->first_valuator = 0; + + evVal= &val->valuator0; + devVal= dev->valuator->axisVal; + for (i=nAxes;i>0;i--) { + *evVal++ = *devVal++; + if (evVal > &val->valuator5) { + int tmp = val->first_valuator+6; + val->num_valuators = 6; + val++; + evVal= &val->valuator0; + val->first_valuator= tmp; + } + } + if ((nAxes % 6) != 0) { + val->num_valuators = (nAxes % 6); + } + count= 1+((nAxes+5)/6); + } + + (*dev->public.processInputProc)((xEventPtr)btn, dev, count); + return; +} diff --git a/xkb/ddxFakeBtn.c b/xkb/ddxFakeBtn.c new file mode 100644 index 000000000..9394c4772 --- /dev/null +++ b/xkb/ddxFakeBtn.c @@ -0,0 +1,62 @@ +/* $Xorg: ddxFakeBtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXFakePointerButton(int event,int button) +#else +XkbDDXFakePointerButton(event,button) + int event; + int button; +#endif +{ +xEvent ev; +int x,y; +DevicePtr ptr; + + if ((ptr = LookupPointerDevice())==NULL) + return; + GetSpritePosition(&x,&y); + ev.u.u.type = event; + ev.u.u.detail = button; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + (*ptr->processInputProc)( &ev, (DeviceIntPtr)ptr, 1 ); + return; +} diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c new file mode 100644 index 000000000..04a8c80e9 --- /dev/null +++ b/xkb/ddxFakeMtn.c @@ -0,0 +1,76 @@ +/* $Xorg: ddxFakeMtn.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +extern WindowPtr GetSpriteWindow( +#if NeedFunctionPrototypes + void +#endif +); + +void +#if NeedFunctionPrototypes +XkbDDXFakePointerMotion(unsigned flags,int x,int y) +#else +XkbDDXFakePointerMotion(flags,x,y) + unsigned flags; + int x; + int y; +#endif +{ +ScreenPtr pScreen; +int oldX,oldY; + + pScreen= GetSpriteWindow()->drawable.pScreen; + GetSpritePosition(&oldX,&oldY); + if (flags&XkbSA_MoveAbsoluteX) + oldX= x; + else oldX+= x; + if (flags&XkbSA_MoveAbsoluteY) + oldY= y; + else oldY+= y; + + if (oldX<0) oldX= 0; + else if (oldX>=pScreen->width) oldX= pScreen->width-1; + if (oldY<0) oldY= 0; + else if (oldY>=pScreen->height) oldY= pScreen->height-1; + + if (pScreen->SetCursorPosition) + (*pScreen->SetCursorPosition)(pScreen, oldX, oldY, TRUE); + return; +} + diff --git a/xkb/ddxInit.c b/xkb/ddxInit.c new file mode 100644 index 000000000..12dbfe838 --- /dev/null +++ b/xkb/ddxInit.c @@ -0,0 +1,48 @@ +/* $Xorg: ddxInit.c,v 1.3 2000/08/17 19:53:45 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXInitDevice(DeviceIntPtr dev) +#else +XkbDDXInitDevice(dev) + DeviceIntPtr dev; +#endif +{ + return 1; +} diff --git a/xkb/ddxKeyClick.c b/xkb/ddxKeyClick.c new file mode 100644 index 000000000..af1185f72 --- /dev/null +++ b/xkb/ddxKeyClick.c @@ -0,0 +1,54 @@ +/* $Xorg: ddxKeyClick.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXKeyClick(DeviceIntPtr pXDev,int keycode,int synthetic) +#else +XkbDDXKeyClick(pXDev,keycode,synthetic) + DeviceIntPtr pXDev; + int keycode; + int synthetic; +#endif +{ +#ifdef DEBUG + if (xkbDebugFlags) + ErrorF("Click.\n"); +#endif + return; +} diff --git a/xkb/ddxKillSrv.c b/xkb/ddxKillSrv.c new file mode 100644 index 000000000..50fc9b24c --- /dev/null +++ b/xkb/ddxKillSrv.c @@ -0,0 +1,51 @@ +/* $Xorg: ddxKillSrv.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXTerminateServer(DeviceIntPtr dev,KeyCode key,XkbAction *act) +#else +XkbDDXTerminateServer(dev,key,act) + DeviceIntPtr dev; + KeyCode key; + XkbAction *act; +#endif +{ + GiveUp(1); + return 0; +} diff --git a/xkb/ddxLEDs.c b/xkb/ddxLEDs.c new file mode 100644 index 000000000..f6ea86965 --- /dev/null +++ b/xkb/ddxLEDs.c @@ -0,0 +1,82 @@ +/* $Xorg: ddxLEDs.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +void +#if NeedFunctionPrototypes +XkbDDXUpdateIndicators(DeviceIntPtr dev,CARD32 new) +#else +XkbDDXUpdateIndicators(dev,new) + DeviceIntPtr dev; + CARD32 new; +#endif +{ + dev->kbdfeed->ctrl.leds= new; + (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); + return; +} + +void +#if NeedFunctionPrototypes +XkbDDXUpdateDeviceIndicators( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + CARD32 new) +#else +XkbDDXUpdateDeviceIndicators(dev,sli,new) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + CARD32 new; +#endif +{ + if (sli->fb.kf==dev->kbdfeed) + XkbDDXUpdateIndicators(dev,new); + else if (sli->class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + kf= sli->fb.kf; + if (kf && kf->CtrlProc) { + (*kf->CtrlProc)(dev,&kf->ctrl); + } + } + else if (sli->class==LedFeedbackClass) { + LedFeedbackPtr lf; + lf= sli->fb.lf; + if (lf && lf->CtrlProc) { + (*lf->CtrlProc)(dev,&lf->ctrl); + } + } + return; +} diff --git a/xkb/ddxList.c b/xkb/ddxList.c new file mode 100644 index 000000000..9f1ad4406 --- /dev/null +++ b/xkb/ddxList.c @@ -0,0 +1,309 @@ +/* $Xorg: ddxList.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 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. + +********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKM.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XI.h" + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +/***====================================================================***/ + +static char *componentDirs[_XkbListNumComponents] = { + "keymap", "keycodes", "types", "compat", "symbols", "geometry" +}; + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +_AddListComponent( XkbSrvListInfoPtr list, + int what, + unsigned flags, + char * str, + ClientPtr client) +#else +_AddListComponent(list,what,flags,str,client) + XkbSrvListInfoPtr list; + int what; + unsigned flags; + char * str; + ClientPtr client; +#endif +{ +int slen,wlen; +unsigned char * wire8; +unsigned short *wire16; +char * tmp; + + if (list->nTotal>=list->maxRtrn) { + list->nTotal++; + return Success; + } + tmp= strchr(str,')'); + if ((tmp==NULL)&&((tmp=strchr(str,'('))==NULL)) { + slen= strlen(str); + while ((slen>0) && isspace(str[slen-1])) { + slen--; + } + } + else { + slen= (tmp-str+1); + } + wlen= (((slen+1)/2)*2)+4; /* four bytes for flags and length, pad to */ + /* 2-byte boundary */ + if ((list->szPool-list->nPool)<wlen) { + if (wlen>1024) list->szPool+= XkbPaddedSize(wlen*2); + else list->szPool+= 1024; + list->pool= _XkbTypedRealloc(list->pool,list->szPool,char); + if (!list->pool) + return BadAlloc; + } + wire16= (unsigned short *)&list->pool[list->nPool]; + wire8= (unsigned char *)&wire16[2]; + wire16[0]= flags; + wire16[1]= slen; + memcpy(wire8,str,slen); + if (client->swapped) { + register int n; + swaps(&wire16[0],n); + swaps(&wire16[1],n); + } + list->nPool+= wlen; + list->nFound[what]++; + list->nTotal++; + return Success; +} + +/***====================================================================***/ +static Status +#if NeedFunctionPrototypes +XkbDDXListComponent( DeviceIntPtr dev, + int what, + XkbSrvListInfoPtr list, + ClientPtr client) +#else +XkbDDXListComponent(dev,what,list,client) + DeviceIntPtr dev; + int what; + XkbSrvListInfoPtr list; + ClientPtr client; +#endif +{ +char *file,*map,*tmp,buf[PATH_MAX]; +FILE *in; +Status status; +int rval; +Bool haveDir; +#ifdef WIN32 +char tmpname[32]; +#endif + + if ((list->pattern[what]==NULL)||(list->pattern[what][0]=='\0')) + return Success; + file= list->pattern[what]; + map= strrchr(file,'('); + if (map!=NULL) { + char *tmp; + map++; + tmp= strrchr(map,')'); + if ((tmp==NULL)||(tmp[1]!='\0')) { + /* illegal pattern. No error, but no match */ + return Success; + } + } + + in= NULL; + haveDir= True; +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)+strlen(componentDirs[what])+6 > PATH_MAX) + return BadImplementation; + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + sprintf(buf,"%s/%s.dir",XkbBaseDirectory,componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + if (strlen(XkbBaseDirectory)*2+strlen(componentDirs[what]) + +(xkbDebugFlags>9?2:1)+strlen(file)+31 > PATH_MAX) + return BadImplementation; +#ifndef WIN32 + sprintf(buf,"%s/xkbcomp -R%s/%s -w %d -l -vlfhpR '%s'", + XkbBaseDirectory,XkbBaseDirectory,componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file); +#else + sprintf(buf,"%s/xkbcomp -R%s/%s -w %d -l -vlfhpR '%s' %s", + XkbBaseDirectory,XkbBaseDirectory,componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file, tmpname); +#endif + } + } + else { + if (strlen(XkbBaseDirectory)+strlen(componentDirs[what])+6 > PATH_MAX) + return BadImplementation; + if ((list->pattern[what][0]=='*')&&(list->pattern[what][1]=='\0')) { + sprintf(buf,"%s.dir",componentDirs[what]); + in= fopen(buf,"r"); + } + if (!in) { + haveDir= False; + if (strlen(componentDirs[what]) + +(xkbDebugFlags>9?2:1)+strlen(file)+29 > PATH_MAX) + return BadImplementation; +#ifndef WIN32 + sprintf(buf,"xkbcomp -R%s -w %d -l -vlfhpR '%s'", + componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file); +#else + sprintf(buf,"xkbcomp -R%s -w %d -l -vlfhpR '%s' %s", + componentDirs[what], + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + file, tmpname); +#endif + } + } + status= Success; + if (!haveDir) +#ifndef WIN32 + in= popen(buf,"r"); +#else + { + if (system(buf) < 0) + ErrorF("Could not invoke keymap compiler\n"); + else + in= fopen(tmpname, "r"); + } +#endif + if (!in) + return BadImplementation; + list->nFound[what]= 0; + while ((status==Success)&&((tmp=fgets(buf,PATH_MAX,in))!=NULL)) { + unsigned flags; + register unsigned int i; + if (*tmp=='#') /* comment, skip it */ + continue; + if (!strncmp(tmp, "Warning:", 8) || !strncmp(tmp, " ", 8)) + /* skip warnings too */ + continue; + flags= 0; + /* each line in the listing is supposed to start with two */ + /* groups of eight characters, which specify the general */ + /* flags and the flags that are specific to the component */ + /* if they're missing, fail with BadImplementation */ + for (i=0;(i<8)&&(status==Success);i++) { /* read the general flags */ + if (isalpha(*tmp)) flags|= (1L<<i); + else if (*tmp!='-') status= BadImplementation; + tmp++; + } + if (status != Success) break; + if (!isspace(*tmp)) { + status= BadImplementation; + break; + } + else tmp++; + for (i=0;(i<8)&&(status==Success);i++) { /* read the component flags */ + if (isalpha(*tmp)) flags|= (1L<<(i+8)); + else if (*tmp!='-') status= BadImplementation; + tmp++; + } + if (status != Success) break; + if (isspace(*tmp)) { + while (isspace(*tmp)) { + tmp++; + } + } + else { + status= BadImplementation; + break; + } + status= _AddListComponent(list,what,flags,tmp,client); + } +#ifndef WIN32 + if (haveDir) + fclose(in); + else if ((rval=pclose(in))!=0) { + if (xkbDebugFlags) + ErrorF("xkbcomp returned exit code %d\n",rval); + } +#else + fclose(in); +#endif + return status; +} + +/***====================================================================***/ + +/* ARGSUSED */ +Status +#if NeedFunctionPrototypes +XkbDDXList(DeviceIntPtr dev,XkbSrvListInfoPtr list,ClientPtr client) +#else +XkbDDXList(dev,list,client) + DeviceIntPtr dev; + XkbSrvListInfoPtr list; + ClientPtr client; +#endif +{ +Status status; + + status= XkbDDXListComponent(dev,_XkbListKeymaps,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListKeycodes,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListTypes,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListCompat,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListSymbols,list,client); + if (status==Success) + status= XkbDDXListComponent(dev,_XkbListGeometry,list,client); + return status; +} diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c new file mode 100644 index 000000000..31b88a83f --- /dev/null +++ b/xkb/ddxLoad.c @@ -0,0 +1,495 @@ +/* $Xorg: ddxLoad.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKM.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XI.h" + +#if defined(CSRG_BASED) || defined(linux) || defined(__sgi) || defined(AIXV3) || defined(__osf__) +#include <paths.h> +#endif + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + + /* + * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is + * relative to the top-level XKB configuration directory. + * Making the server write to a subdirectory of that directory + * requires some work in the general case (install procedure + * has to create links to /var or somesuch on many machines), + * so we just compile into /usr/tmp for now. + */ +#ifndef XKM_OUTPUT_DIR +#define XKM_OUTPUT_DIR "compiled/" +#endif + +#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" +#define ERROR_PREFIX "\"> \"" +#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" +#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" + +static void +OutputDirectory (outdir) + char* outdir; +{ +#ifndef WIN32 + if (getuid() == 0 || geteuid() == 0) { + /* if server running as root it'll be able to write */ + (void) strcpy (outdir, XKM_OUTPUT_DIR); + } else +#endif + { +#ifdef _PATH_VARTMP + (void) strcpy (outdir, _PATH_VARTMP); + if (outdir[strlen(outdir) - 1] != '/') /* Hi IBM, Digital */ + (void) strcat (outdir, "/"); +#else + (void) strcpy (outdir, "/tmp/"); +#endif + } +} + +Bool +#if NeedFunctionPrototypes +XkbDDXCompileNamedKeymap( XkbDescPtr xkb, + XkbComponentNamesPtr names, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen) + XkbDescPtr xkb; + XkbComponentNamesPtr names; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +char cmd[PATH_MAX],file[PATH_MAX],xkm_output_dir[PATH_MAX],*map,*outFile; + + if (names->keymap==NULL) + return False; + strncpy(file,names->keymap,PATH_MAX); file[PATH_MAX-1]= '\0'; + if ((map= strrchr(file,'('))!=NULL) { + char *tmp; + if ((tmp= strrchr(map,')'))!=NULL) { + *map++= '\0'; + *tmp= '\0'; + } + else { + map= NULL; + } + } + if ((outFile= strrchr(file,'/'))!=NULL) + outFile= _XkbDupString(&outFile[1]); + else outFile= _XkbDupString(file); + XkbEnsureSafeMapName(outFile); + OutputDirectory(xkm_output_dir); + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)*2+(xkbDebugFlags>9?2:1) + +(map?strlen(map)+3:0)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(file)+strlen(xkm_output_dir) + +strlen(outFile)+53 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } + sprintf(cmd,"%s/xkbcomp -w %d -R%s -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s %s%s.xkm", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory,(map?"-m ":""),(map?map:""), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file, + xkm_output_dir,outFile); + } + else { + if ((xkbDebugFlags>9?2:1)+(map?strlen(map)+3:0)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(file)+strlen(xkm_output_dir) + +strlen(outFile)+49 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } + sprintf(cmd,"xkbcomp -w %d -xkm %s%s -em1 %s -emp %s -eml %s keymap/%s %s%s.xkm", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + (map?"-m ":""),(map?map:""), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1,file, + xkm_output_dir,outFile); + } +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("XkbDDXCompileNamedKeymap compiling keymap using:\n"); + ErrorF(" \"cmd\"\n"); + } +#endif + if (system(cmd)==0) { + if (nameRtrn) { + strncpy(nameRtrn,outFile,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + if (outFile!=NULL) + Xfree(outFile); + return True; + } +#ifdef DEBUG + ErrorF("Error compiling keymap (%s)\n",names->keymap); +#endif + if (outFile!=NULL) + Xfree(outFile); + return False; +} + +Bool +#if NeedFunctionPrototypes +XkbDDXCompileKeymapByNames( XkbDescPtr xkb, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXCompileKeymapByNames(xkb,names,want,need,nameRtrn,nameRtrnLen) + XkbDescPtr xkb; + XkbComponentNamesPtr names; + unsigned want; + unsigned need; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +FILE * out; +char buf[PATH_MAX],keymap[PATH_MAX],xkm_output_dir[PATH_MAX]; +#ifdef WIN32 +char tmpname[32]; +#endif + if ((names->keymap==NULL)||(names->keymap[0]=='\0')) { + extern char *display; + sprintf(keymap,"server-%s",display); + } + else { + strcpy(keymap,names->keymap); + } + + XkbEnsureSafeMapName(keymap); + OutputDirectory(xkm_output_dir); +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + if (XkbBaseDirectory!=NULL) { + if (strlen(XkbBaseDirectory)*2+(xkbDebugFlags>9?2:1) + +strlen(PRE_ERROR_MSG)+strlen(ERROR_PREFIX) + +strlen(POST_ERROR_MSG1)+strlen(xkm_output_dir) + +strlen(keymap)+48 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } +#ifndef WIN32 + sprintf(buf, + "%s/xkbcomp -w %d -R%s -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); +#else + sprintf(buf, + "%s/xkbcomp -w %d -R%s -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\" < %s", + XkbBaseDirectory, + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + XkbBaseDirectory, + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap,tmpname); +#endif + } + else { + if ((xkbDebugFlags>9?2:1)+strlen(PRE_ERROR_MSG) + +strlen(ERROR_PREFIX)+strlen(POST_ERROR_MSG1) + +strlen(xkm_output_dir)+strlen(keymap)+44 > PATH_MAX) + { +#ifdef DEBUG + ErrorF("compiler command for keymap (%s) exceeds max length\n", + names->keymap); +#endif + return False; + } +#ifndef WIN32 + sprintf(buf, + "xkbcomp -w %d -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\"", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap); +#else + sprintf(buf, + "xkbcomp -w %d -xkm - -em1 %s -emp %s -eml %s \"%s%s.xkm\" < %s", + ((xkbDebugFlags<2)?1:((xkbDebugFlags>10)?10:xkbDebugFlags)), + PRE_ERROR_MSG,ERROR_PREFIX,POST_ERROR_MSG1, + xkm_output_dir,keymap,tmpname); +#endif + } +#ifndef WIN32 + out= popen(buf,"w"); +#else + out= fopen(tmpname, "w"); +#endif + if (out!=NULL) { +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n"); + XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need); + } +#endif + XkbWriteXKBKeymapForNames(out,names,NULL,xkb,want,need); +#ifndef WIN32 + if (pclose(out)==0) +#else + if (fclose(out)==0) +#endif + { +#ifdef WIN32 + if (system(buf) < 0) + ErrorF("Could not invoke keymap compiler\n"); + else { +#endif + if (nameRtrn) { + strncpy(nameRtrn,keymap,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + return True; +#ifdef WIN32 + } +#endif + } +#ifdef DEBUG + else + ErrorF("Error compiling keymap (%s)\n",keymap); +#endif + } +#ifdef DEBUG + else { +#ifndef WIN32 + ErrorF("Could not invoke keymap compiler\n"); +#else + ErrorF("Could not open file %s\n", tmpname); +#endif + } +#endif + if (nameRtrn) + nameRtrn[0]= '\0'; + return False; +} + +FILE * +#if NeedFunctionPrototypes +XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) +#else +XkbDDXOpenConfigFile(mapName,fileNameRtrn,fileNameRtrnLen) + char * mapName; + char * fileNameRtrn; + int fileNameRtrnLen; +#endif +{ +char buf[PATH_MAX],xkm_output_dir[PATH_MAX]; +FILE * file; + + buf[0]= '\0'; + if (mapName!=NULL) { + OutputDirectory(xkm_output_dir); + if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/')) { + if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir) + +strlen(mapName)+6 <= PATH_MAX) + { + sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory, + xkm_output_dir,mapName); + } + } + else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX) + sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName); + if (buf[0] != '\0') + file= fopen(buf,"r"); + else file= NULL; + } + else file= NULL; + if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { + strncpy(fileNameRtrn,buf,fileNameRtrnLen); + buf[fileNameRtrnLen-1]= '\0'; + } + return file; +} + +unsigned +#if NeedFunctionPrototypes +XkbDDXLoadKeymapByNames( DeviceIntPtr keybd, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + XkbFileInfo * finfoRtrn, + char * nameRtrn, + int nameRtrnLen) +#else +XkbDDXLoadKeymapByNames(keybd,names,want,need,finfoRtrn,nameRtrn,nameRtrnLen) + DeviceIntPtr keybd; + XkbComponentNamesPtr names; + unsigned want; + unsigned need; + XkbFileInfo * finfoRtrn; + char * nameRtrn; + int nameRtrnLen; +#endif +{ +XkbDescPtr xkb; +FILE * file; +char fileName[PATH_MAX]; +unsigned missing; + + bzero(finfoRtrn,sizeof(XkbFileInfo)); + if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) + xkb= NULL; + else xkb= keybd->key->xkbInfo->desc; + if ((names->keycodes==NULL)&&(names->types==NULL)&& + (names->compat==NULL)&&(names->symbols==NULL)&& + (names->geometry==NULL)) { + if (names->keymap==NULL) { + bzero(finfoRtrn,sizeof(XkbFileInfo)); + if (xkb && XkbDetermineFileType(finfoRtrn,XkbXKMFile,NULL) && + ((finfoRtrn->defined&need)==need) ) { + finfoRtrn->xkb= xkb; + nameRtrn[0]= '\0'; + return finfoRtrn->defined; + } + return 0; + } + else if (!XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen)) { +#ifdef NOISY + ErrorF("Couldn't compile keymap file\n"); +#endif + return 0; + } + } + else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, + nameRtrn,nameRtrnLen)){ +#ifdef NOISY + ErrorF("Couldn't compile keymap file\n"); +#endif + return 0; + } + file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); + if (file==NULL) { + ErrorF("Couldn't open compiled keymap file %s\n",fileName); + return 0; + } + missing= XkmReadFile(file,need,want,finfoRtrn); + if (finfoRtrn->xkb==NULL) { + ErrorF("Error loading keymap %s\n",fileName); + fclose(file); + (void) unlink (fileName); + return 0; + } +#ifdef DEBUG + else if (xkbDebugFlags) { + ErrorF("Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined); + } +#endif + fclose(file); + (void) unlink (fileName); + return (need|want)&(~missing); +} + +Bool +#if NeedFunctionPrototypes +XkbDDXNamesFromRules( DeviceIntPtr keybd, + char * rules_name, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbDDXNamesFromRules(keybd,rules_name,defs,names) + DeviceIntPtr keybd; + char * rules_name; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +char buf[PATH_MAX]; +FILE * file; +Bool complete; +XkbRF_RulesPtr rules; + + if (!rules_name) + return False; + if (XkbBaseDirectory==NULL) { + if (strlen(rules_name)+7 > PATH_MAX) + return False; + sprintf(buf,"rules/%s",rules_name); + } + else { + if (strlen(XkbBaseDirectory)+strlen(rules_name)+8 > PATH_MAX) + return False; + sprintf(buf,"%s/rules/%s",XkbBaseDirectory,rules_name); + } + if ((file= fopen(buf,"r"))==NULL) + return False; + if ((rules= XkbRF_Create(0,0))==NULL) { + fclose(file); + return False; + } + if (!XkbRF_LoadRules(file,rules)) { + fclose(file); + XkbRF_Free(rules,True); + return False; + } + bzero((char *)names,sizeof(XkbComponentNamesRec)); + complete= XkbRF_GetComponents(rules,defs,names); + fclose(file); + XkbRF_Free(rules,True); + return complete; +} diff --git a/xkb/ddxVT.c b/xkb/ddxVT.c new file mode 100644 index 000000000..e1978d88b --- /dev/null +++ b/xkb/ddxVT.c @@ -0,0 +1,50 @@ +/* $Xorg: ddxVT.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "XKBsrv.h" +#include "XI.h" + +int +#if NeedFunctionPrototypes +XkbDDXSwitchScreen(DeviceIntPtr dev,KeyCode key,XkbAction *act) +#else +XkbDDXSwitchScreen(dev,key,act) + DeviceIntPtr dev; + KeyCode key; + XkbAction *act; +#endif +{ + return 1; +} diff --git a/xkb/maprules.c b/xkb/maprules.c new file mode 100644 index 000000000..559dc9c7f --- /dev/null +++ b/xkb/maprules.c @@ -0,0 +1,1382 @@ +/* $Xorg: maprules.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1996 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif + + +#define X_INCLUDE_STRING_H +#define XOS_USE_NO_LOCKING +#include <X11/Xos_r.h> + +#ifndef XKB_IN_SERVER + +#include <X11/Xproto.h> +#include <X11/Xlib.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBgeom.h> +#include "XKMformat.h" +#include "XKBfileInt.h" +#include "XKBrules.h" + +#else + +#define NEED_EVENTS +#include <X11/Xproto.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" + +#endif + +#ifdef DEBUG +#define PR_DEBUG(s) fprintf(stderr,s) +#define PR_DEBUG1(s,a) fprintf(stderr,s,a) +#else +#define PR_DEBUG(s) +#define PR_DEBUG1(s,a) +#endif + +/***====================================================================***/ + +#define DFLT_LINE_SIZE 128 + +typedef struct { + int line_num; + int sz_line; + int num_line; + char buf[DFLT_LINE_SIZE]; + char * line; +} InputLine; + +static void +#if NeedFunctionPrototypes +InitInputLine(InputLine *line) +#else +InitInputLine(line) + InputLine * line; +#endif +{ + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static void +#if NeedFunctionPrototypes +FreeInputLine(InputLine *line) +#else +FreeInputLine(line) + InputLine *line; +#endif +{ + if (line->line!=line->buf) + _XkbFree(line->line); + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static int +#if NeedFunctionPrototypes +InputLineAddChar(InputLine *line,int ch) +#else +InputLineAddChar(line,ch) + InputLine * line; + int ch; +#endif +{ + if (line->num_line>=line->sz_line) { + if (line->line==line->buf) { + line->line= (char *)_XkbAlloc(line->sz_line*2); + memcpy(line->line,line->buf,line->sz_line); + } + else { + line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2); + } + line->sz_line*= 2; + } + line->line[line->num_line++]= ch; + return ch; +} + +#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ + (int)((l)->line[(l)->num_line++]= (c)):\ + InputLineAddChar(l,c)) + +static Bool +#if NeedFunctionPrototypes +GetInputLine(FILE *file,InputLine *line,Bool checkbang) +#else +GetInputLine(file,line,checkbang) + FILE * file; + InputLine * line; + Bool checkbang; +#endif +{ +int ch; +Bool endOfFile,spacePending,slashPending,inComment; + + endOfFile= False; + while ((!endOfFile)&&(line->num_line==0)) { + spacePending= slashPending= inComment= False; + while (((ch=getc(file))!='\n')&&(ch!=EOF)) { + if (ch=='\\') { + if ((ch=getc(file))==EOF) + break; + if (ch=='\n') { + inComment= False; + ch= ' '; + line->line_num++; + } + } + if (inComment) + continue; + if (ch=='/') { + if (slashPending) { + inComment= True; + slashPending= False; + } + else { + slashPending= True; + } + continue; + } + else if (slashPending) { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + ADD_CHAR(line,'/'); + slashPending= False; + } + if (isspace(ch)) { + while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { + ch= getc(file); + } + if (ch==EOF) + break; + if ((ch!='\n')&&(line->num_line>0)) + spacePending= True; + ungetc(ch,file); + } + else { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= False; + } + if (checkbang && ch=='!') { + if (line->num_line!=0) { + PR_DEBUG("The '!' legal only at start of line\n"); + PR_DEBUG("Line containing '!' ignored\n"); + line->num_line= 0; + inComment= 0; + break; + } + + } + ADD_CHAR(line,ch); + } + } + if (ch==EOF) + endOfFile= True; +/* else line->num_line++;*/ + } + if ((line->num_line==0)&&(endOfFile)) + return False; + ADD_CHAR(line,'\0'); + return True; +} + +/***====================================================================***/ + +#define MODEL 0 +#define LAYOUT 1 +#define VARIANT 2 +#define OPTION 3 +#define KEYCODES 4 +#define SYMBOLS 5 +#define TYPES 6 +#define COMPAT 7 +#define GEOMETRY 8 +#define KEYMAP 9 +#define MAX_WORDS 10 + +#define PART_MASK 0x000F +#define COMPONENT_MASK 0x03F0 + +static char * cname[MAX_WORDS] = { + "model", "layout", "variant", "option", + "keycodes", "symbols", "types", "compat", "geometry", "keymap" +}; + +typedef struct _RemapSpec { + int num_remap; + int remap[MAX_WORDS]; +} RemapSpec; + +typedef struct _FileSpec { + char * name[MAX_WORDS]; + struct _FileSpec * pending; +} FileSpec; + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +SetUpRemap(InputLine *line,RemapSpec *remap) +#else +SetUpRemap(line,remap) + InputLine * line; + RemapSpec * remap; +#endif +{ +char * tok,*str; +unsigned present; +register int i; +#ifdef DEBUG +Bool found; +#endif +_Xstrtokparams strtok_buf; + + present= 0; + str= &line->line[1]; + bzero((char *)remap,sizeof(RemapSpec)); + while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { +#ifdef DEBUG + found= False; +#endif + str= NULL; + if (strcmp(tok,"=")==0) + continue; + for (i=0;i<MAX_WORDS;i++) { + if (strcmp(cname[i],tok)==0) { +#ifdef DEBUG + found= True; +#endif + if (present&(1<<i)) { + PR_DEBUG1("Component \"%s\" listed twice\n",tok); + PR_DEBUG("Second definition ignored\n"); + break; + } + present|= (1<<i); + remap->remap[remap->num_remap++]= i; + break; + } + } +#ifdef DEBUG + if (!found) { + fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); + } +#endif + } + if ((present&PART_MASK)==0) { +#ifdef DEBUG + unsigned mask= PART_MASK; + fprintf(stderr,"Mapping needs at one of "); + for (i=0;(i<MAX_WORDS)&mask;i++) { + if ((1L<<i)&mask) { + mask&= ~(1L<<i); + if (mask) fprintf(stderr,"\"%s,\" ",cname[i]); + else fprintf(stderr,"or \"%s\"\n",cname[i]); + } + } + fprintf(stderr,"Illegal mapping ignored\n"); +#endif + remap->num_remap= 0; + return; + } + if ((present&COMPONENT_MASK)==0) { + PR_DEBUG("Mapping needs at least one component\n"); + PR_DEBUG("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if (((present&PART_MASK)&(1<<OPTION))&& + ((present&PART_MASK)!=(1<<OPTION))) { + PR_DEBUG("Options cannot appear with other parts\n"); + PR_DEBUG("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if (((present&COMPONENT_MASK)&(1<<KEYMAP))&& + ((present&COMPONENT_MASK)!=(1<<KEYMAP))) { + PR_DEBUG("Keymap cannot appear with other components\n"); + PR_DEBUG("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + return; +} + +static Bool +#if NeedFunctionPrototypes +MatchOneOf(char *wanted,char *vals_defined) +#else +MatchOneOf(wanted,vals_defined) + char * wanted; + char * vals_defined; +#endif +{ +char *str,*next; +int want_len= strlen(wanted); + + for (str=vals_defined,next=NULL;str!=NULL;str=next) { + int len; + next= strchr(str,','); + if (next) { + len= next-str; + next++; + } + else { + len= strlen(str); + } + if ((len==want_len)&&(strncmp(wanted,str,len)==0)) + return True; + } + return False; +} + +/***====================================================================***/ + +static Bool +#if NeedFunctionPrototypes +CheckLine( InputLine * line, + RemapSpec * remap, + XkbRF_RulePtr rule) +#else +CheckLine(line,remap,rule) + InputLine * line; + RemapSpec * remap; + XkbRF_RulePtr rule; +#endif +{ +char * str,*tok; +register int nread; +FileSpec tmp; +_Xstrtokparams strtok_buf; + + if (line->line[0]=='!') { + SetUpRemap(line,remap); + return False; + } + if (remap->num_remap==0) { + PR_DEBUG("Must have a mapping before first line of data\n"); + PR_DEBUG("Illegal line of data ignored\n"); + return False; + } + bzero((char *)&tmp,sizeof(FileSpec)); + str= line->line; + for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { + str= NULL; + if (strcmp(tok,"=")==0) { + nread--; + continue; + } + if (nread>remap->num_remap) { + PR_DEBUG("Too many words on a line\n"); + PR_DEBUG1("Extra word \"%s\" ignored\n",tok); + continue; + } + tmp.name[remap->remap[nread]]= tok; + } + if (nread<remap->num_remap) { + PR_DEBUG("Too few words on a line\n"); + PR_DEBUG("line ignored\n"); + return False; + } + if ((tmp.name[MODEL]!=NULL)&&(strcmp(tmp.name[MODEL],"*")==0)) + tmp.name[MODEL]= NULL; + if ((tmp.name[LAYOUT]!=NULL)&&(strcmp(tmp.name[LAYOUT],"*")==0)) + tmp.name[LAYOUT]= NULL; + if ((tmp.name[VARIANT]!=NULL)&&(strcmp(tmp.name[VARIANT],"*")==0)) + tmp.name[VARIANT]= NULL; + + rule->flags= 0; + if (tmp.name[OPTION]) + rule->flags|= XkbRF_Delayed|XkbRF_Append; + rule->model= _XkbDupString(tmp.name[MODEL]); + rule->layout= _XkbDupString(tmp.name[LAYOUT]); + rule->variant= _XkbDupString(tmp.name[VARIANT]); + rule->option= _XkbDupString(tmp.name[OPTION]); + + rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); + rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); + rule->types= _XkbDupString(tmp.name[TYPES]); + rule->compat= _XkbDupString(tmp.name[COMPAT]); + rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); + rule->keymap= _XkbDupString(tmp.name[KEYMAP]); + return True; +} + +static char * +#if NeedFunctionPrototypes +_Concat(char *str1,char *str2) +#else +_Concat(str1,str2) + char * str1; + char * str2; +#endif +{ +int len; + + if ((!str1)||(!str2)) + return str1; + len= strlen(str1)+strlen(str2)+1; + str1= _XkbTypedRealloc(str1,len,char); + if (str1) + strcat(str1,str2); + return str1; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_ApplyRule( XkbRF_RulePtr rule, + XkbComponentNamesPtr names) +#else +XkbRF_ApplyRule(rule,names) + XkbRF_RulePtr rule; + XkbComponentNamesPtr names; +#endif +{ + rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ + if ((rule->flags&XkbRF_Append)==0) { + if ((names->keycodes==NULL)&&(rule->keycodes!=NULL)) + names->keycodes= _XkbDupString(rule->keycodes); + + if ((names->symbols==NULL)&&(rule->symbols!=NULL)) + names->symbols= _XkbDupString(rule->symbols); + + if ((names->types==NULL)&&(rule->types!=NULL)) + names->types= _XkbDupString(rule->types); + + if ((names->compat==NULL)&&(rule->compat!=NULL)) + names->compat= _XkbDupString(rule->compat); + + if ((names->geometry==NULL)&&(rule->geometry!=NULL)) + names->geometry= _XkbDupString(rule->geometry); + + if ((names->keymap==NULL)&&(rule->keymap!=NULL)) + names->keymap= _XkbDupString(rule->keymap); + } + else { + if (rule->keycodes) + names->keycodes= _Concat(names->keycodes,rule->keycodes); + if (rule->symbols) + names->symbols= _Concat(names->symbols,rule->symbols); + if (rule->types) + names->types= _Concat(names->types,rule->types); + if (rule->compat) + names->compat= _Concat(names->compat,rule->compat); + if (rule->geometry) + names->geometry= _Concat(names->geometry,rule->geometry); + if (rule->keymap) + names->keymap= _Concat(names->keymap,rule->keymap); + } + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +#define CHECK_MATCH(r,d) ((((r)[0]=='?')&&((r)[1]=='\0'))||(strcmp(r,d)==0)) + +Bool +#if NeedFunctionPrototypes +XkbRF_CheckApplyRule( XkbRF_RulePtr rule, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyRule(rule,defs,names) + XkbRF_RulePtr rule; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ + if (rule->model!=NULL) { + if ((!defs->model)||(!CHECK_MATCH(rule->model,defs->model))) + return False; + } + if (rule->layout!=NULL) { + if ((!defs->layout)||(!CHECK_MATCH(rule->layout,defs->layout))) + return False; + } + if (rule->variant!=NULL) { + if ((!defs->variant)||(!CHECK_MATCH(rule->variant,defs->variant))) + return False; + } + if (rule->option!=NULL) { + if ((!defs->options)||(!MatchOneOf(rule->option,defs->options))) + return False; + } + + if ((!rule->option)&& + ((!rule->model)||(!rule->layout)||(!rule->variant))) { + /* partial map -- partial maps are applied in the order they */ + /* appear, but all partial maps come before any options. */ + rule->flags|= XkbRF_PendingMatch; + return False; + } + /* exact match, apply it now */ + return XkbRF_ApplyRule(rule,names); +} + +void +#if NeedFunctionPrototypes +XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) +#else +XkbRF_ClearPartialMatches(rules) + XkbRF_RulesPtr rules; +#endif +{ +register int i; +XkbRF_RulePtr rule; + + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + rule->flags&= ~XkbRF_PendingMatch; + } +} + +Bool +#if NeedFunctionPrototypes +XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) +#else +XkbRF_ApplyPartialMatches(rules,names) + XkbRF_RulesPtr rules; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; +Bool complete; + + complete= False; + for (rule=rules->rules,i=0;(i<rules->num_rules)&&(!complete);i++,rule++) { + if ((rule->flags&XkbRF_PendingMatch)==0) + continue; + complete= XkbRF_ApplyRule(rule,names); + } + return complete; +} + +void +#if NeedFunctionPrototypes +XkbRF_CheckApplyDelayedRules( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyDelayedRules(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; + + for (rule=rules->rules,i=0;(i<rules->num_rules);i++,rule++) { + if ((rule->flags&XkbRF_Delayed)==0) + continue; + XkbRF_CheckApplyRule(rule,defs,names); + } + return; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_CheckApplyRules(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +int i; +XkbRF_RulePtr rule; +Bool complete; + + complete= False; + for (rule=rules->rules,i=0;(i<rules->num_rules)&&(!complete);i++,rule++) { + if ((rule->flags&XkbRF_Delayed)!=0) + continue; + complete= XkbRF_CheckApplyRule(rule,defs,names); + } + return complete; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbRF_SubstituteVars(char *name,XkbRF_VarDefsPtr defs) +#else +XkbRF_SubstituteVars(name,defs) + char * name; + XkbRF_VarDefsPtr defs; +#endif +{ +char *str,*outstr,*orig; +int len; + + orig= name; + str= index(name,'%'); + if (str==NULL) + return name; + len= strlen(name); + while (str!=NULL) { + char pfx= str[1]; + int extra_len= 0; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + extra_len= 1; + str++; + } + else if (pfx=='(') { + extra_len= 2; + str++; + } + + if ((str[1]=='l')&&defs->layout) + len+= strlen(defs->layout)+extra_len; + else if ((str[1]=='m')&&defs->model) + len+= strlen(defs->model)+extra_len; + else if ((str[1]=='v')&&defs->variant) + len+= strlen(defs->variant)+extra_len; + if ((pfx=='(')&&(str[2]==')')) { + str++; + } + str= index(&str[1],'%'); + } + name= (char *)_XkbAlloc(len+1); + str= orig; + outstr= name; + while (*str!='\0') { + if (str[0]=='%') { + char pfx,sfx; + str++; + pfx= str[0]; + sfx= '\0'; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + str++; + } + else if (pfx=='(') { + sfx= ')'; + str++; + } + else pfx= '\0'; + + if ((str[0]=='l')&&(defs->layout)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->layout); + outstr+= strlen(defs->layout); + if (sfx) *outstr++= sfx; + } + else if ((str[0]=='m')&&(defs->model)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->model); + outstr+= strlen(defs->model); + if (sfx) *outstr++= sfx; + } + else if ((str[0]=='v')&&(defs->variant)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,defs->variant); + outstr+= strlen(defs->variant); + if (sfx) *outstr++= sfx; + } + str++; + if ((pfx=='(')&&(str[0]==')')) + str++; + } + else { + *outstr++= *str++; + } + } + *outstr++= '\0'; + if (orig!=name) + _XkbFree(orig); + return name; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbRF_GetComponents( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +#else +XkbRF_GetComponents(rules,defs,names) + XkbRF_RulesPtr rules; + XkbRF_VarDefsPtr defs; + XkbComponentNamesPtr names; +#endif +{ +Bool complete; + + bzero((char *)names,sizeof(XkbComponentNamesRec)); + XkbRF_ClearPartialMatches(rules); + complete= XkbRF_CheckApplyRules(rules,defs,names); + if (!complete) + complete= XkbRF_ApplyPartialMatches(rules,names); + XkbRF_CheckApplyDelayedRules(rules,defs,names); + if (names->keycodes) + names->keycodes= XkbRF_SubstituteVars(names->keycodes,defs); + if (names->symbols) + names->symbols= XkbRF_SubstituteVars(names->symbols,defs); + if (names->types) + names->types= XkbRF_SubstituteVars(names->types,defs); + if (names->compat) + names->compat= XkbRF_SubstituteVars(names->compat,defs); + if (names->geometry) + names->geometry= XkbRF_SubstituteVars(names->geometry,defs); + if (names->keymap) + names->keymap= XkbRF_SubstituteVars(names->keymap,defs); + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +XkbRF_RulePtr +#if NeedFunctionPrototypes +XkbRF_AddRule(XkbRF_RulesPtr rules) +#else +XkbRF_AddRule(rules) + XkbRF_RulesPtr rules; +#endif +{ + if (rules->sz_rules<1) { + rules->sz_rules= 16; + rules->num_rules= 0; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + } + else if (rules->num_rules>=rules->sz_rules) { + rules->sz_rules*= 2; + rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules, + XkbRF_RuleRec); + } + if (!rules->rules) { + rules->sz_rules= rules->num_rules= 0; +#ifdef DEBUG + fprintf(stderr,"Allocation failure in XkbRF_AddRule\n"); +#endif + return NULL; + } + bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec)); + return &rules->rules[rules->num_rules++]; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) +#else +XkbRF_LoadRules(file,rules) + FILE * file; + XkbRF_RulesPtr rules; +#endif +{ +InputLine line; +RemapSpec remap; +XkbRF_RuleRec trule,*rule; + + if (!(rules && file)) + return False; + bzero((char *)&remap,sizeof(RemapSpec)); + InitInputLine(&line); + while (GetInputLine(file,&line,True)) { + if (CheckLine(&line,&remap,&trule)) { + if ((rule= XkbRF_AddRule(rules))!=NULL) { + *rule= trule; + bzero((char *)&trule,sizeof(XkbRF_RuleRec)); + } + } + line.num_line= 0; + } + FreeInputLine(&line); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) +#else +XkbRF_LoadRulesByName(base,locale,rules) + char * base; + char * locale; + XkbRF_RulesPtr rules; +#endif +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+2 > PATH_MAX) + return False; + sprintf(buf,"%s-%s", base, locale); + } + else { + if (strlen(base)+1 > PATH_MAX) + return False; + strcpy(buf,base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + strcpy(buf,base); + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadRules(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +#define HEAD_NONE 0 +#define HEAD_MODEL 1 +#define HEAD_LAYOUT 2 +#define HEAD_VARIANT 3 +#define HEAD_OPTION 4 +#define HEAD_EXTRA 5 + +XkbRF_VarDescPtr +#if NeedFunctionPrototypes +XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) +#else +XkbRF_AddVarDesc(vars) + XkbRF_DescribeVarsPtr vars; +#endif +{ + if (vars->sz_desc<1) { + vars->sz_desc= 16; + vars->num_desc= 0; + vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec); + } + else if (vars->num_desc>=vars->sz_desc) { + vars->sz_desc*= 2; + vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec); + } + if (!vars->desc) { + vars->sz_desc= vars->num_desc= 0; + PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n"); + return NULL; + } + vars->desc[vars->num_desc].name= NULL; + vars->desc[vars->num_desc].desc= NULL; + return &vars->desc[vars->num_desc++]; +} + +XkbRF_VarDescPtr +#if NeedFunctionPrototypes +XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) +#else +XkbRF_AddVarDescCopy(vars,from) + XkbRF_DescribeVarsPtr vars; + XkbRF_VarDescPtr from; +#endif +{ +XkbRF_VarDescPtr nd; + + if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { + nd->name= _XkbDupString(from->name); + nd->desc= _XkbDupString(from->desc); + } + return nd; +} + +XkbRF_DescribeVarsPtr +#if NeedFunctionPrototypes +XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) +#else +XkbRF_AddVarToDescribe(rules,name) + XkbRF_RulesPtr rules; + char * name; +#endif +{ + if (rules->sz_extra<1) { + rules->num_extra= 0; + rules->sz_extra= 1; + rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *); + rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec); + } + else if (rules->num_extra>=rules->sz_extra) { + rules->sz_extra*= 2; + rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra, + char *); + rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra, + XkbRF_DescribeVarsRec); + } + if ((!rules->extra_names)||(!rules->extra)) { + PR_DEBUG("allocation error in extra parts\n"); + rules->sz_extra= rules->num_extra= 0; + rules->extra_names= NULL; + rules->extra= NULL; + return NULL; + } + rules->extra_names[rules->num_extra]= _XkbDupString(name); + bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec)); + return &rules->extra[rules->num_extra++]; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) +#else +XkbRF_LoadDescriptions(file,rules) + FILE * file; + XkbRF_RulesPtr rules; +#endif +{ +InputLine line; +XkbRF_VarDescRec tmp; +char *tok; +int len,headingtype,extra_ndx; + + bzero((char *)&tmp, sizeof(XkbRF_VarDescRec)); + headingtype = HEAD_NONE; + InitInputLine(&line); + for ( ; GetInputLine(file,&line,False); line.num_line= 0) { + if (line.line[0]=='!') { + tok = strtok(&(line.line[1]), " \t"); + if (!_XkbStrCaseCmp(tok,"model")) + headingtype = HEAD_MODEL; + else if (!_XkbStrCaseCmp(tok,"layout")) + headingtype = HEAD_LAYOUT; + else if (!_XkbStrCaseCmp(tok,"variant")) + headingtype = HEAD_VARIANT; + else if (!_XkbStrCaseCmp(tok,"option")) + headingtype = HEAD_OPTION; + else { + int i; + headingtype = HEAD_EXTRA; + extra_ndx= -1; + for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) { + if (!_XkbStrCaseCmp(tok,rules->extra_names[i])) + extra_ndx= i; + } + if (extra_ndx<0) { + XkbRF_DescribeVarsPtr var; + PR_DEBUG1("Extra heading \"%s\" encountered\n",tok); + var= XkbRF_AddVarToDescribe(rules,tok); + if (var) + extra_ndx= var-rules->extra; + else headingtype= HEAD_NONE; + } + } + continue; + } + + if (headingtype == HEAD_NONE) { + PR_DEBUG("Must have a heading before first line of data\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + + len = strlen(line.line); + if ((tmp.name= strtok(line.line, " \t")) == NULL) { + PR_DEBUG("Huh? No token on line\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + if (strlen(tmp.name) == len) { + PR_DEBUG("No description found\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + + tok = line.line + strlen(tmp.name) + 1; + while ((*tok!='\n')&&isspace(*tok)) + tok++; + if (*tok == '\0') { + PR_DEBUG("No description found\n"); + PR_DEBUG("Illegal line of data ignored\n"); + continue; + } + tmp.desc= tok; + switch (headingtype) { + case HEAD_MODEL: + XkbRF_AddVarDescCopy(&rules->models,&tmp); + break; + case HEAD_LAYOUT: + XkbRF_AddVarDescCopy(&rules->layouts,&tmp); + break; + case HEAD_VARIANT: + XkbRF_AddVarDescCopy(&rules->variants,&tmp); + break; + case HEAD_OPTION: + XkbRF_AddVarDescCopy(&rules->options,&tmp); + break; + case HEAD_EXTRA: + XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp); + break; + } + } + FreeInputLine(&line); + if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) && + (rules->variants.num_desc==0) && (rules->options.num_desc==0) && + (rules->num_extra==0)) { + return False; + } + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) +#else +XkbRF_LoadDescriptionsByName(base,locale,rules) + char * base; + char * locale; + XkbRF_RulesPtr rules; +#endif +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return False; + if (locale) { + if (strlen(base)+strlen(locale)+6 > PATH_MAX) + return False; + sprintf(buf,"%s-%s.lst", base, locale); + } + else { + if (strlen(base)+5 > PATH_MAX) + return False; + sprintf(buf,"%s.lst", base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + sprintf(buf,"%s.lst", base); + + file= fopen(buf, "r"); + } + if (!file) + return False; + ok= XkbRF_LoadDescriptions(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +XkbRF_RulesPtr +#if NeedFunctionPrototypes +XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) +#else +XkbRF_Load(base,locale,wantDesc,wantRules) + char *base; + char *locale; + Bool wantDesc; + Bool wantRules; +#endif +{ +XkbRF_RulesPtr rules; + + if ((!base)||((!wantDesc)&&(!wantRules))) + return NULL; + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) { + XkbRF_Free(rules,True); + return NULL; + } + return rules; +} + +XkbRF_RulesPtr +XkbRF_Create(int szRules,int szExtra) +{ +XkbRF_RulesPtr rules; + + if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) + return NULL; + if (szRules>0) { + rules->sz_rules= szRules; + rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); + if (!rules->rules) { + _XkbFree(rules); + return NULL; + } + } + if (szExtra>0) { + rules->sz_extra= szExtra; + rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec); + if (!rules->extra) { + if (rules->rules) + _XkbFree(rules->rules); + _XkbFree(rules); + return NULL; + } + } + return rules; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) +#else +XkbRF_ClearVarDescriptions(var) + XkbRF_DescribeVarsPtr var; +#endif +{ +register int i; + + for (i=0;i<var->num_desc;i++) { + if (var->desc[i].name) + _XkbFree(var->desc[i].name); + if (var->desc[i].desc) + _XkbFree(var->desc[i].desc); + var->desc[i].name= var->desc[i].desc= NULL; + } + if (var->desc) + _XkbFree(var->desc); + var->desc= NULL; + return; +} + +void +#if NeedFunctionPrototypes +XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) +#else +XkbRF_Free(rules,freeRules) + XkbRF_RulesPtr rules; + Bool freeRules; +#endif +{ +int i; +XkbRF_RulePtr rule; + + if (!rules) + return; + XkbRF_ClearVarDescriptions(&rules->models); + XkbRF_ClearVarDescriptions(&rules->layouts); + XkbRF_ClearVarDescriptions(&rules->variants); + XkbRF_ClearVarDescriptions(&rules->options); + if (rules->extra) { + for (i = 0; i < rules->num_extra; i++) { + XkbRF_ClearVarDescriptions(&rules->extra[i]); + } + _XkbFree(rules->extra); + rules->num_extra= rules->sz_extra= 0; + rules->extra= NULL; + } + if (rules->rules) { + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + if (rule->model) _XkbFree(rule->model); + if (rule->layout) _XkbFree(rule->layout); + if (rule->variant) _XkbFree(rule->variant); + if (rule->option) _XkbFree(rule->option); + if (rule->keycodes) _XkbFree(rule->keycodes); + if (rule->symbols) _XkbFree(rule->symbols); + if (rule->types) _XkbFree(rule->types); + if (rule->compat) _XkbFree(rule->compat); + if (rule->geometry) _XkbFree(rule->geometry); + if (rule->keymap) _XkbFree(rule->keymap); + bzero((char *)rule,sizeof(XkbRF_RuleRec)); + } + _XkbFree(rules->rules); + rules->num_rules= rules->sz_rules= 0; + rules->rules= NULL; + } + if (freeRules) + _XkbFree(rules); + return; +} + +#ifndef XKB_IN_SERVER + +Bool +#if NeedFunctionPrototypes +XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn) +#else +XkbRF_GetNamesProp(dpy,rf_rtrn,vd_rtrn) + Display * dpy; + char ** rf_rtrn; + XkbRF_VarDefsPtr vd_rtrn; +#endif +{ +Atom rules_atom,actual_type; +int fmt; +unsigned long nitems,bytes_after; +char *data,*out; +Status rtrn; + + rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,True); + if (rules_atom==None) /* property cannot exist */ + return False; + rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy),rules_atom, + 0L,_XKB_RF_NAMES_PROP_MAXLEN,False, + XA_STRING,&actual_type, + &fmt,&nitems,&bytes_after, + (unsigned char **)&data); + if (rtrn!=Success) + return False; + if (rf_rtrn) + *rf_rtrn= NULL; + (void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec)); + if ((bytes_after>0)||(actual_type!=XA_STRING)||(fmt!=8)) { + if (data) XFree(data); + return (fmt==0?True:False); + } + + out= data; + if (out && (*out) && rf_rtrn) + *rf_rtrn= _XkbDupString(out); + out+=strlen(out)+1; + + if ((out-data)<nitems) { + if (*out) + vd_rtrn->model= _XkbDupString(out); + out+=strlen(out)+1; + } + + if ((out-data)<nitems) { + if (*out) + vd_rtrn->layout= _XkbDupString(out); + out+=strlen(out)+1; + } + + if ((out-data)<nitems) { + if (*out) + vd_rtrn->variant= _XkbDupString(out); + out+=strlen(out)+1; + } + + + if ((out-data)<nitems) { + if (*out) + vd_rtrn->options= _XkbDupString(out); + out+=strlen(out)+1; + } + XFree(data); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs) +#else +XkbRF_SetNamesProp(dpy,rules_file,var_defs) + Display * dpy; + char * rules_file; + XkbRF_VarDefsPtr var_defs; +#endif +{ +int len,out; +Atom name; +char * pval; + + len= (rules_file?strlen(rules_file):0); + len+= (var_defs->model?strlen(var_defs->model):0); + len+= (var_defs->layout?strlen(var_defs->layout):0); + len+= (var_defs->variant?strlen(var_defs->variant):0); + len+= (var_defs->options?strlen(var_defs->options):0); + if (len<1) + return True; + + len+= 5; /* trailing NULs */ + + name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,False); + if (name==None) { /* should never happen */ + _XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom); + return False; + } + pval= (char *)_XkbAlloc(len); + if (!pval) { + _XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len); + return False; + } + out= 0; + if (rules_file) { + strcpy(&pval[out],rules_file); + out+= strlen(rules_file); + } + pval[out++]= '\0'; + if (var_defs->model) { + strcpy(&pval[out],var_defs->model); + out+= strlen(var_defs->model); + } + pval[out++]= '\0'; + if (var_defs->layout) { + strcpy(&pval[out],var_defs->layout); + out+= strlen(var_defs->layout); + } + pval[out++]= '\0'; + if (var_defs->variant) { + strcpy(&pval[out],var_defs->variant); + out+= strlen(var_defs->variant); + } + pval[out++]= '\0'; + if (var_defs->options) { + strcpy(&pval[out],var_defs->options); + out+= strlen(var_defs->options); + } + pval[out++]= '\0'; + if (out!=len) { + _XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out); + _XkbFree(pval); + return False; + } + + XChangeProperty(dpy,DefaultRootWindow(dpy),name,XA_STRING,8,PropModeReplace, + (unsigned char *)pval,len); + _XkbFree(pval); + return True; +} + +#endif diff --git a/xkb/xkb.c b/xkb/xkb.c new file mode 100644 index 000000000..6f75e8146 --- /dev/null +++ b/xkb/xkb.c @@ -0,0 +1,6929 @@ +/* $Xorg: xkb.c,v 1.3 2000/08/17 19:53:46 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "extnsionst.h" + +#include "XI.h" + + int XkbEventBase; + int XkbErrorBase; + int XkbReqCode; + int XkbKeyboardErrorCode; +Atom xkbONE_LEVEL; +Atom xkbTWO_LEVEL; +Atom xkbKEYPAD; +CARD32 xkbDebugFlags = 0; +CARD32 xkbDebugCtrls = 0; + +#ifndef XKB_SRV_UNSUPPORTED_XI_FEATURES +#define XKB_SRV_UNSUPPORTED_XI_FEATURES XkbXI_KeyboardsMask +#endif + +unsigned XkbXIUnsupported= XKB_SRV_UNSUPPORTED_XI_FEATURES; + +RESTYPE RT_XKBCLIENT; + +/***====================================================================***/ + +#define CHK_DEVICE(d,sp,lf) {\ + int why;\ + d = (DeviceIntPtr)lf((sp),&why);\ + if (!dev) {\ + client->errorValue = _XkbErrCode2(why,(sp));\ + return XkbKeyboardErrorCode;\ + }\ +} + +#define CHK_KBD_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupKeyboard) +#define CHK_LED_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupLedDevice) +#define CHK_BELL_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupBellDevice) +#define CHK_ANY_DEVICE(d,sp) CHK_DEVICE(d,sp,_XkbLookupAnyDevice) + +#define CHK_ATOM_ONLY2(a,ev,er) {\ + if (((a)==None)||(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_ONLY(a) \ + CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) + +#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + (er)= BadAtom;\ + return ret;\ + }\ +} +#define CHK_ATOM_OR_NONE2(a,ev,er) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_OR_NONE(a) \ + CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) + +#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + (er)= BadValue;\ + return ret;\ + }\ +} +#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + return er;\ + }\ +} +#define CHK_MASK_LEGAL(err,mask,legal) \ + CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) + +#define CHK_MASK_MATCH(err,affect,value) {\ + if ((value)&(~(affect))) { \ + client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ + return BadMatch;\ + }\ +} +#define CHK_MASK_OVERLAP(err,m1,m2) {\ + if ((m1)&(m2)) { \ + client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ + return BadMatch;\ + }\ +} +#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ + (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ + return er;\ + }\ + else if ( (first)<(x)->min_key_code ) {\ + (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ + return er;\ + }\ +} +#define CHK_KEY_RANGE(err,first,num,x) \ + CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) + +#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ + (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ + return er;\ + }\ + else if ( (first)<(r)->minKeyCode ) {\ + (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ + return er;\ + }\ +} +#define CHK_REQ_KEY_RANGE(err,first,num,r) \ + CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbUseExtension(ClientPtr client) +#else +ProcXkbUseExtension(client) + ClientPtr client; +#endif +{ + REQUEST(xkbUseExtensionReq); + xkbUseExtensionReply rep; + register int n; + int supported; + + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + if (stuff->wantedMajor != XkbMajorVersion) { + /* pre-release version 0.65 is compatible with 1.00 */ + supported= ((XkbMajorVersion==1)&& + (stuff->wantedMajor==0)&&(stuff->wantedMinor==65)); + } + else supported = 1; + +#ifdef XKB_SWAPPING_BUSTED + if (client->swapped) + supported= 0; +#endif + + if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) { + client->xkbClientFlags= _XkbClientInitialized; + client->vMajor= stuff->wantedMajor; + client->vMinor= stuff->wantedMinor; + } + else if (xkbDebugFlags&0x1) { + ErrorF("Rejecting client %d (0x%x) (wants %d.%02d, have %d.%02d)\n", + client->index, client->clientAsMask, + stuff->wantedMajor,stuff->wantedMinor, + XkbMajorVersion,XkbMinorVersion); + } + rep.type = X_Reply; + rep.supported = supported; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.serverMajor = XkbMajorVersion; + rep.serverMinor = XkbMinorVersion; + if ( client->swapped ) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.serverMajor, n); + swaps(&rep.serverMinor, n); + } + WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbSelectEvents(ClientPtr client) +#else +ProcXkbSelectEvents(client) + ClientPtr client; +#endif +{ + unsigned legal; + DeviceIntPtr dev; + XkbInterestPtr masks; + REQUEST(xkbSelectEventsReq); + + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + + if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) { + client->mapNotifyMask&= ~stuff->affectMap; + client->mapNotifyMask|= (stuff->affectMap&stuff->map); + } + if (stuff->affectWhich&(~XkbMapNotifyMask)==0) + return client->noClientException; + + masks = XkbFindClientResource((DevicePtr)dev,client); + if (!masks){ + XID id = FakeClientID(client->index); + AddResource(id,RT_XKBCLIENT,dev); + masks= XkbAddClientResource((DevicePtr)dev,client,id); + } + if (masks) { + union { + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from,to; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if ((bit&maskLeft)==0) + continue; + maskLeft&= ~bit; + switch (ndx) { + case XkbNewKeyboardNotify: + to.c16= &client->newKeyboardNotifyMask; + legal= XkbAllNewKeyboardEventsMask; + size= 2; + break; + case XkbStateNotify: + to.c16= &masks->stateNotifyMask; + legal= XkbAllStateEventsMask; + size= 2; + break; + case XkbControlsNotify: + to.c32= &masks->ctrlsNotifyMask; + legal= XkbAllControlEventsMask; + size= 4; + break; + case XkbIndicatorStateNotify: + to.c32= &masks->iStateNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbIndicatorMapNotify: + to.c32= &masks->iMapNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbNamesNotify: + to.c16= &masks->namesNotifyMask; + legal= XkbAllNameEventsMask; + size= 2; + break; + case XkbCompatMapNotify: + to.c8= &masks->compatNotifyMask; + legal= XkbAllCompatMapEventsMask; + size= 1; + break; + case XkbBellNotify: + to.c8= &masks->bellNotifyMask; + legal= XkbAllBellEventsMask; + size= 1; + break; + case XkbActionMessage: + to.c8= &masks->actionMessageMask; + legal= XkbAllActionMessagesMask; + size= 1; + break; + case XkbAccessXNotify: + to.c16= &masks->accessXNotifyMask; + legal= XkbAllAccessXEventsMask; + size= 2; + break; + case XkbExtensionDeviceNotify: + to.c16= &masks->extDevNotifyMask; + legal= XkbAllExtensionDeviceEventsMask; + size= 2; + break; + default: + client->errorValue = _XkbErrCode2(33,bit); + return BadValue; + } + + if (stuff->clear&bit) { + if (size==2) to.c16[0]= 0; + else if (size==4) to.c32[0]= 0; + else to.c8[0]= 0; + } + else if (stuff->selectAll&bit) { + if (size==2) to.c16[0]= ~0; + else if (size==4) to.c32[0]= ~0; + else to.c8[0]= ~0; + } + else { + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]); + CHK_MASK_LEGAL(ndx,from.c16[0],legal); + to.c16[0]&= ~from.c16[0]; + to.c16[0]|= (from.c16[0]&from.c16[1]); + } + else if (size==4) { + CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]); + CHK_MASK_LEGAL(ndx,from.c32[0],legal); + to.c32[0]&= ~from.c32[0]; + to.c32[0]|= (from.c32[0]&from.c32[1]); + } + else { + CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]); + CHK_MASK_LEGAL(ndx,from.c8[0],legal); + to.c8[0]&= ~from.c8[0]; + to.c8[0]|= (from.c8[0]&from.c8[1]); + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + } + if (dataLeft>2) { + ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + return client->noClientException; + } + return BadAlloc; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbBell(ClientPtr client) +#else +ProcXkbBell(client) + ClientPtr client; +#endif +{ + REQUEST(xkbBellReq); + DeviceIntPtr dev; + WindowPtr pWin; + int base; + int newPercent,oldPitch,oldDuration; + pointer ctrl; + + REQUEST_SIZE_MATCH(xkbBellReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_BELL_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + if ((stuff->forceSound)&&(stuff->eventOnly)) { + client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly); + return BadMatch; + } + if (stuff->percent < -100 || stuff->percent > 100) { + client->errorValue = _XkbErrCode2(0x2,stuff->percent); + return BadValue; + } + if (stuff->duration<-1) { + client->errorValue = _XkbErrCode2(0x3,stuff->duration); + return BadValue; + } + if (stuff->pitch<-1) { + client->errorValue = _XkbErrCode2(0x4,stuff->pitch); + return BadValue; + } + + if (stuff->bellClass == XkbDfltXIClass) { + if (dev->kbdfeed!=NULL) + stuff->bellClass= KbdFeedbackClass; + else stuff->bellClass= BellFeedbackClass; + } + if (stuff->bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + if (stuff->bellID==XkbDfltXIId) + k= dev->kbdfeed; + else { + for (k=dev->kbdfeed; k; k=k->next) { + if (k->ctrl.id == stuff->bellID) + break; + } + } + if (!k) { + client->errorValue= _XkbErrCode2(0x5,stuff->bellID); + return BadValue; + } + base = k->ctrl.bell; + ctrl = (pointer) &(k->ctrl); + oldPitch= k->ctrl.bell_pitch; + oldDuration= k->ctrl.bell_duration; + if (stuff->pitch!=0) { + if (stuff->pitch==-1) + k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch; + else k->ctrl.bell_pitch= stuff->pitch; + } + if (stuff->duration!=0) { + if (stuff->duration==-1) + k->ctrl.bell_duration= defaultKeyboardControl.bell_duration; + else k->ctrl.bell_duration= stuff->duration; + } + } + else if (stuff->bellClass == BellFeedbackClass) { + BellFeedbackPtr b; + if (stuff->bellID==XkbDfltXIId) + b= dev->bell; + else { + for (b=dev->bell; b; b=b->next) { + if (b->ctrl.id == stuff->bellID) + break; + } + } + if (!b) { + client->errorValue = _XkbErrCode2(0x6,stuff->bellID); + return BadValue; + } + base = b->ctrl.percent; + ctrl = (pointer) &(b->ctrl); + oldPitch= b->ctrl.pitch; + oldDuration= b->ctrl.duration; + if (stuff->pitch!=0) { + if (stuff->pitch==-1) + b->ctrl.pitch= defaultKeyboardControl.bell_pitch; + else b->ctrl.pitch= stuff->pitch; + } + if (stuff->duration!=0) { + if (stuff->duration==-1) + b->ctrl.duration= defaultKeyboardControl.bell_duration; + else b->ctrl.duration= stuff->duration; + } + } + else { + client->errorValue = _XkbErrCode2(0x7,stuff->bellClass);; + return BadValue; + } + if (stuff->window!=None) { + pWin= (WindowPtr)LookupIDByType(stuff->window,RT_WINDOW); + if (pWin==NULL) { + client->errorValue= stuff->window; + return BadValue; + } + } + else pWin= NULL; + + newPercent= (base*stuff->percent)/100; + if (stuff->percent < 0) + newPercent= base+newPercent; + else newPercent= base-newPercent+stuff->percent; + XkbHandleBell(stuff->forceSound, stuff->eventOnly, + dev, newPercent, ctrl, stuff->bellClass, + stuff->name, pWin, client); + if ((stuff->pitch!=0)||(stuff->duration!=0)) { + if (stuff->bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + k= (KbdFeedbackPtr)ctrl; + if (stuff->pitch!=0) + k->ctrl.bell_pitch= oldPitch; + if (stuff->duration!=0) + k->ctrl.bell_duration= oldDuration; + } + else { + BellFeedbackPtr b; + b= (BellFeedbackPtr)ctrl; + if (stuff->pitch!=0) + b->ctrl.pitch= oldPitch; + if (stuff->duration!=0) + b->ctrl.duration= oldDuration; + } + } + return Success; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetState(ClientPtr client) +#else +ProcXkbGetState(client) + ClientPtr client; +#endif +{ + REQUEST(xkbGetStateReq); + DeviceIntPtr dev; + xkbGetStateReply rep; + XkbStateRec *xkb; + + REQUEST_SIZE_MATCH(xkbGetStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb= &dev->key->xkbInfo->state; + bzero(&rep,sizeof(xkbGetStateReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.mods = dev->key->state&0xff; + rep.baseMods = xkb->base_mods; + rep.lockedMods = xkb->locked_mods; + rep.latchedMods = xkb->latched_mods; + rep.group = xkb->group; + rep.baseGroup = xkb->base_group; + rep.latchedGroup = xkb->latched_group; + rep.lockedGroup = xkb->locked_group; + rep.compatState = xkb->compat_state; + rep.ptrBtnState = xkb->ptr_buttons; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swaps(&rep.ptrBtnState,n); + } + WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbLatchLockState(ClientPtr client) +#else +ProcXkbLatchLockState(client) + ClientPtr client; +#endif +{ + int status; + DeviceIntPtr dev; + XkbStateRec oldState,*newState; + CARD16 changed; + + REQUEST(xkbLatchLockStateReq); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_MATCH(0x01,stuff->affectModLocks,stuff->modLocks); + CHK_MASK_MATCH(0x01,stuff->affectModLatches,stuff->modLatches); + + status = Success; + oldState= dev->key->xkbInfo->state; + newState= &dev->key->xkbInfo->state; + if ( stuff->affectModLocks ) { + newState->locked_mods&= ~stuff->affectModLocks; + newState->locked_mods|= (stuff->affectModLocks&stuff->modLocks); + } + if (( status == Success ) && stuff->lockGroup ) + newState->locked_group = stuff->groupLock; + if (( status == Success ) && stuff->affectModLatches ) + status=XkbLatchModifiers(dev,stuff->affectModLatches,stuff->modLatches); + if (( status == Success ) && stuff->latchGroup ) + status=XkbLatchGroup(dev,stuff->groupLatch); + + if ( status != Success ) + return status; + + XkbComputeDerivedState(dev->key->xkbInfo); + dev->key->state= XkbStateFieldFromRec(newState); + + changed = XkbStateChangedFlags(&oldState,newState); + if (changed) { + xkbStateNotify sn; + sn.keycode= 0; + sn.eventType= 0; + sn.requestMajor = XkbReqCode; + sn.requestMinor = X_kbLatchLockState; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,changed,False); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseXkbReq(&cause,X_kbLatchLockState,client); + XkbUpdateIndicators(dev,changed,True,NULL,&cause); + } + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetControls(ClientPtr client) +#else +ProcXkbGetControls(client) + ClientPtr client; +#endif +{ + xkbGetControlsReply rep; + XkbControlsPtr xkb; + DeviceIntPtr dev; + register int n; + + REQUEST(xkbGetControlsReq); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc->ctrls; + rep.type = X_Reply; + rep.length = (SIZEOF(xkbGetControlsReply)- + SIZEOF(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.deviceID = ((DeviceIntPtr)dev)->id; + rep.numGroups = xkb->num_groups; + rep.groupsWrap = xkb->groups_wrap; + rep.internalMods = xkb->internal.mask; + rep.ignoreLockMods = xkb->ignore_lock.mask; + rep.internalRealMods = xkb->internal.real_mods; + rep.ignoreLockRealMods = xkb->ignore_lock.real_mods; + rep.internalVMods = xkb->internal.vmods; + rep.ignoreLockVMods = xkb->ignore_lock.vmods; + rep.enabledCtrls = xkb->enabled_ctrls; + rep.repeatDelay = xkb->repeat_delay; + rep.repeatInterval = xkb->repeat_interval; + rep.slowKeysDelay = xkb->slow_keys_delay; + rep.debounceDelay = xkb->debounce_delay; + rep.mkDelay = xkb->mk_delay; + rep.mkInterval = xkb->mk_interval; + rep.mkTimeToMax = xkb->mk_time_to_max; + rep.mkMaxSpeed = xkb->mk_max_speed; + rep.mkCurve = xkb->mk_curve; + rep.mkDfltBtn = xkb->mk_dflt_btn; + rep.axTimeout = xkb->ax_timeout; + rep.axtCtrlsMask = xkb->axt_ctrls_mask; + rep.axtCtrlsValues = xkb->axt_ctrls_values; + rep.axtOptsMask = xkb->axt_opts_mask; + rep.axtOptsValues = xkb->axt_opts_values; + rep.axOptions = xkb->ax_options; + memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length,n); + swaps(&rep.internalVMods, n); + swaps(&rep.ignoreLockVMods, n); + swapl(&rep.enabledCtrls, n); + swaps(&rep.repeatDelay, n); + swaps(&rep.repeatInterval, n); + swaps(&rep.slowKeysDelay, n); + swaps(&rep.debounceDelay, n); + swaps(&rep.mkDelay, n); + swaps(&rep.mkInterval, n); + swaps(&rep.mkTimeToMax, n); + swaps(&rep.mkMaxSpeed, n); + swaps(&rep.mkCurve, n); + swaps(&rep.axTimeout, n); + swapl(&rep.axtCtrlsMask, n); + swapl(&rep.axtCtrlsValues, n); + swaps(&rep.axtOptsMask, n); + swaps(&rep.axtOptsValues, n); + swaps(&rep.axOptions, n); + } + WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep); + return(client->noClientException); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetControls(ClientPtr client) +#else +ProcXkbSetControls(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrl; + XkbControlsRec new,old; + xkbControlsNotify cn; + XkbEventCauseRec cause; + XkbSrvLedInfoPtr sli; + + REQUEST(xkbSetControlsReq); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->changeCtrls,XkbAllControlsMask); + + xkbi = dev->key->xkbInfo; + ctrl = xkbi->desc->ctrls; + new = *ctrl; + XkbSetCauseXkbReq(&cause,X_kbSetControls,client); + if (stuff->changeCtrls&XkbInternalModsMask) { + CHK_MASK_MATCH(0x02,stuff->affectInternalMods,stuff->internalMods); + CHK_MASK_MATCH(0x03,stuff->affectInternalVMods,stuff->internalVMods); + new.internal.real_mods&=~stuff->affectInternalMods; + new.internal.real_mods|=(stuff->affectInternalMods&stuff->internalMods); + new.internal.vmods&=~stuff->affectInternalVMods; + new.internal.vmods|= (stuff->affectInternalVMods&stuff->internalVMods); + new.internal.mask= new.internal.real_mods| + XkbMaskForVMask(xkbi->desc,new.internal.vmods); + } + if (stuff->changeCtrls&XkbIgnoreLockModsMask) { + CHK_MASK_MATCH(0x4,stuff->affectIgnoreLockMods,stuff->ignoreLockMods); + CHK_MASK_MATCH(0x5,stuff->affectIgnoreLockVMods,stuff->ignoreLockVMods); + new.ignore_lock.real_mods&=~stuff->affectIgnoreLockMods; + new.ignore_lock.real_mods|= + (stuff->affectIgnoreLockMods&stuff->ignoreLockMods); + new.ignore_lock.vmods&= ~stuff->affectIgnoreLockVMods; + new.ignore_lock.vmods|= + (stuff->affectIgnoreLockVMods&stuff->ignoreLockVMods); + new.ignore_lock.mask= new.ignore_lock.real_mods| + XkbMaskForVMask(xkbi->desc,new.ignore_lock.vmods); + } + CHK_MASK_MATCH(0x06,stuff->affectEnabledCtrls,stuff->enabledCtrls); + if (stuff->affectEnabledCtrls) { + CHK_MASK_LEGAL(0x07,stuff->affectEnabledCtrls,XkbAllBooleanCtrlsMask); + new.enabled_ctrls&= ~stuff->affectEnabledCtrls; + new.enabled_ctrls|= (stuff->affectEnabledCtrls&stuff->enabledCtrls); + } + if (stuff->changeCtrls&XkbRepeatKeysMask) { + if ((stuff->repeatDelay<1)||(stuff->repeatInterval<1)) { + client->errorValue = _XkbErrCode3(0x08,stuff->repeatDelay, + stuff->repeatInterval); + return BadValue; + } + new.repeat_delay = stuff->repeatDelay; + new.repeat_interval = stuff->repeatInterval; + } + if (stuff->changeCtrls&XkbSlowKeysMask) { + if (stuff->slowKeysDelay<1) { + client->errorValue = _XkbErrCode2(0x09,stuff->slowKeysDelay); + return BadValue; + } + new.slow_keys_delay = stuff->slowKeysDelay; + } + if (stuff->changeCtrls&XkbBounceKeysMask) { + if (stuff->debounceDelay<1) { + client->errorValue = _XkbErrCode2(0x0A,stuff->debounceDelay); + return BadValue; + } + new.debounce_delay = stuff->debounceDelay; + } + if (stuff->changeCtrls&XkbMouseKeysMask) { + if (stuff->mkDfltBtn>XkbMaxMouseKeysBtn) { + client->errorValue = _XkbErrCode2(0x0B,stuff->mkDfltBtn); + return BadValue; + } + new.mk_dflt_btn = stuff->mkDfltBtn; + } + if (stuff->changeCtrls&XkbMouseKeysAccelMask) { + if ((stuff->mkDelay<1) || (stuff->mkInterval<1) || + (stuff->mkTimeToMax<1) || (stuff->mkMaxSpeed<1)|| + (stuff->mkCurve<-1000)) { + client->errorValue = _XkbErrCode2(0x0C,0); + return BadValue; + } + new.mk_delay = stuff->mkDelay; + new.mk_interval = stuff->mkInterval; + new.mk_time_to_max = stuff->mkTimeToMax; + new.mk_max_speed = stuff->mkMaxSpeed; + new.mk_curve = stuff->mkCurve; + AccessXComputeCurveFactor(xkbi,&new); + } + if (stuff->changeCtrls&XkbGroupsWrapMask) { + unsigned act,num; + act= XkbOutOfRangeGroupAction(stuff->groupsWrap); + switch (act) { + case XkbRedirectIntoRange: + num= XkbOutOfRangeGroupNumber(stuff->groupsWrap); + if (num>=new.num_groups) { + client->errorValue= _XkbErrCode3(0x0D,new.num_groups,num); + return BadValue; + } + case XkbWrapIntoRange: + case XkbClampIntoRange: + break; + default: + client->errorValue= _XkbErrCode2(0x0E,act); + return BadValue; + } + new.groups_wrap= stuff->groupsWrap; + } + CHK_MASK_LEGAL(0x0F,stuff->axOptions,XkbAX_AllOptionsMask); + if (stuff->changeCtrls&XkbAccessXKeysMask) + new.ax_options = stuff->axOptions&XkbAX_AllOptionsMask; + else { + if (stuff->changeCtrls&XkbStickyKeysMask) { + new.ax_options&= ~XkbAX_SKOptionsMask; + new.ax_options|= stuff->axOptions&XkbAX_SKOptionsMask; + } + if (stuff->changeCtrls&XkbAccessXFeedbackMask) { + new.ax_options&= ~XkbAX_FBOptionsMask; + new.ax_options|= stuff->axOptions&XkbAX_FBOptionsMask; + } + } + + if (stuff->changeCtrls&XkbAccessXTimeoutMask) { + if (stuff->axTimeout<1) { + client->errorValue = _XkbErrCode2(0x10,stuff->axTimeout); + return BadValue; + } + CHK_MASK_MATCH(0x11,stuff->axtCtrlsMask,stuff->axtCtrlsValues); + CHK_MASK_LEGAL(0x12,stuff->axtCtrlsMask,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x13,stuff->axtOptsMask,stuff->axtOptsValues); + CHK_MASK_LEGAL(0x14,stuff->axtOptsMask,XkbAX_AllOptionsMask); + new.ax_timeout = stuff->axTimeout; + new.axt_ctrls_mask = stuff->axtCtrlsMask; + new.axt_ctrls_values = (stuff->axtCtrlsValues&stuff->axtCtrlsMask); + new.axt_opts_mask = stuff->axtOptsMask; + new.axt_opts_values= (stuff->axtOptsValues&stuff->axtOptsMask); + } + if (stuff->changeCtrls&XkbPerKeyRepeatMask) { + memcpy(new.per_key_repeat,stuff->perKeyRepeat,XkbPerKeyBitArraySize); + } + old= *ctrl; + *ctrl= new; + XkbDDXChangeControls(dev,&old,ctrl); + if (XkbComputeControlsNotify(dev,&old,ctrl,&cn,False)) { + cn.keycode= 0; + cn.eventType = 0; + cn.requestMajor = XkbReqCode; + cn.requestMinor = X_kbSetControls; + XkbSendControlsNotify(dev,&cn); + } + if ((sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0))!=NULL) + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrl->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(dev,xkbi,True,&cause); + } +#endif + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +XkbSetRepeatRate(DeviceIntPtr dev,int timeout,int interval,int major,int minor) +#else +XkbSetRepeatRate(dev,timeout,interval,major,minor) + DeviceIntPtr dev; + int timeout; + int interval; + int major; + int minor; +#endif +{ +int changed= 0; +XkbControlsRec old,*xkb; + + if ((!dev)||(!dev->key)||(!dev->key->xkbInfo)) + return 0; + xkb= dev->key->xkbInfo->desc->ctrls; + old= *xkb; + if ((timeout!=0) && (xkb->repeat_delay!=timeout)) { + xkb->repeat_delay= timeout; + changed++; + } + if ((interval!=0) && (xkb->repeat_interval!=interval)) { + xkb->repeat_interval= interval; + changed++; + } + if (changed) { + xkbControlsNotify cn; + XkbDDXChangeControls(dev,&old,xkb); + if (XkbComputeControlsNotify(dev,&old,xkb,&cn,False)) { + cn.keycode= 0; + cn.eventType = 0; + cn.requestMajor = major; + cn.requestMinor = minor; + XkbSendControlsNotify(dev,&cn); + } + } + return 1; +} + +int +#if NeedFunctionPrototypes +XkbGetRepeatRate(DeviceIntPtr dev,int *timeout,int *interval) +#else +XkbGetRepeatRate(dev,timeout,interval) + DeviceIntPtr dev; + int * timeout; + int * interval; +#endif +{ +XkbControlsPtr xkb; + + if ((!dev)||(!dev->key)||(!dev->key->xkbInfo)) + return 0; + xkb= dev->key->xkbInfo->desc->ctrls; + if (timeout) *timeout= xkb->repeat_delay; + if (interval) *interval= xkb->repeat_interval; + return 1; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyTypes(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + XkbKeyTypeRec *type; + unsigned i,len; + + len= 0; + if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->types)) { + rep->present&= ~XkbKeyTypesMask; + rep->firstType= rep->nTypes= 0; + return 0; + } + type= &xkb->map->types[rep->firstType]; + for (i=0;i<rep->nTypes;i++,type++){ + len+= SIZEOF(xkbKeyTypeWireDesc); + if (type->map_count>0) { + len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc)); + if (type->preserve) + len+= (type->map_count*SIZEOF(xkbModsWireDesc)); + } + } + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyTypes( XkbDescPtr xkb, + xkbGetMapReply * rep, + char * buf, + ClientPtr client) +#else +XkbWriteKeyTypes(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ + XkbKeyTypePtr type; + unsigned i; + xkbKeyTypeWireDesc *wire; + + type= &xkb->map->types[rep->firstType]; + for (i=0;i<rep->nTypes;i++,type++) { + register unsigned n; + wire= (xkbKeyTypeWireDesc *)buf; + wire->mask = type->mods.mask; + wire->realMods = type->mods.real_mods; + wire->virtualMods = type->mods.vmods; + wire->numLevels = type->num_levels; + wire->nMapEntries = type->map_count; + wire->preserve = (type->preserve!=NULL); + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + + buf= (char *)&wire[1]; + if (wire->nMapEntries>0) { + xkbKTMapEntryWireDesc * wire; + XkbKTMapEntryPtr entry; + wire= (xkbKTMapEntryWireDesc *)buf; + entry= type->map; + for (n=0;n<type->map_count;n++,wire++,entry++) { + wire->active= entry->active; + wire->mask= entry->mods.mask; + wire->level= entry->level; + wire->realMods= entry->mods.real_mods; + wire->virtualMods= entry->mods.vmods; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + } + buf= (char *)wire; + if (type->preserve!=NULL) { + xkbModsWireDesc * pwire; + XkbModsPtr preserve; + pwire= (xkbModsWireDesc *)buf; + preserve= type->preserve; + for (n=0;n<type->map_count;n++,pwire++,preserve++) { + pwire->mask= preserve->mask; + pwire->realMods= preserve->real_mods; + pwire->virtualMods= preserve->vmods; + if (client->swapped) { + register int n; + swaps(&pwire->virtualMods,n); + } + } + buf= (char *)pwire; + } + } + } + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeySyms(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + XkbSymMapPtr symMap; + unsigned i,len; + unsigned nSyms,nSymsThisKey; + + if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) { + rep->present&= ~XkbKeySymsMask; + rep->firstKeySym= rep->nKeySyms= 0; + rep->totalSyms= 0; + return 0; + } + len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc); + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) { + if (symMap->offset!=0) { + nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width; + nSyms+= nSymsThisKey; + } + } + len+= nSyms*4; + rep->totalSyms= nSyms; + return len; +} + +static int +#if NeedFunctionPrototypes +XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeVirtualMods(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +register unsigned i,nMods,bit; + + if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)|| + (!xkb)||(!xkb->server)) { + rep->present&= ~XkbVirtualModsMask; + rep->virtualMods= 0; + return 0; + } + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&bit) + nMods++; + } + return XkbPaddedSize(nMods); +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +#else +XkbWriteKeySyms(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ +register KeySym * pSym; +XkbSymMapPtr symMap; +xkbSymMapWireDesc * outMap; +register unsigned i; + + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=0;i<rep->nKeySyms;i++,symMap++) { + outMap = (xkbSymMapWireDesc *)buf; + outMap->ktIndex[0] = symMap->kt_index[0]; + outMap->ktIndex[1] = symMap->kt_index[1]; + outMap->ktIndex[2] = symMap->kt_index[2]; + outMap->ktIndex[3] = symMap->kt_index[3]; + outMap->groupInfo = symMap->group_info; + outMap->width= symMap->width; + outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info); + buf= (char *)&outMap[1]; + if (outMap->nSyms==0) + continue; + + pSym = &xkb->map->syms[symMap->offset]; + memcpy((char *)buf,(char *)pSym,outMap->nSyms*4); + if (client->swapped) { + register int n,nSyms= outMap->nSyms; + swaps(&outMap->nSyms,n); + while (nSyms-->0) { + swapl(buf,n); + buf+= 4; + } + } + else buf+= outMap->nSyms*4; + } + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyActions(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nActs; + register KeyCode firstKey; + + if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) { + rep->present&= ~XkbKeyActionsMask; + rep->firstKeyAct= rep->nKeyActs= 0; + rep->totalActs= 0; + return 0; + } + firstKey= rep->firstKeyAct; + for (nActs=i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+firstKey]!=0) + nActs+= XkbKeyNumActions(xkb,i+firstKey); + } + len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc)); + rep->totalActs= nActs; + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteKeyActions(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply * rep; + char * buf; + ClientPtr client; +#endif +{ + unsigned i; + CARD8 * numDesc; + XkbAnyAction * actDesc; + + numDesc = (CARD8 *)buf; + for (i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]==0) + numDesc[i] = 0; + else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + } + buf+= XkbPaddedSize(rep->nKeyActs); + + actDesc = (XkbAnyAction *)buf; + for (i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) { + unsigned int num; + num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + memcpy((char *)actDesc, + (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)), + num*SIZEOF(xkbActionWireDesc)); + actDesc+= num; + } + } + buf = (char *)actDesc; + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeKeyBehaviors(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nBhvr; + XkbBehavior * bhv; + + if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) { + rep->present&= ~XkbKeyBehaviorsMask; + rep->firstKeyBehavior= rep->nKeyBehaviors= 0; + rep->totalKeyBehaviors= 0; + return 0; + } + bhv= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) { + if (bhv->type!=XkbKB_Default) + nBhvr++; + } + len= nBhvr*SIZEOF(xkbBehaviorWireDesc); + rep->totalKeyBehaviors= nBhvr; + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteKeyBehaviors(xkb,rep,buf,client) + XkbDescRec *xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ + unsigned i; + xkbBehaviorWireDesc *wire; + XkbBehavior *pBhvr; + + wire = (xkbBehaviorWireDesc *)buf; + pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) { + if (pBhvr->type!=XkbKB_Default) { + wire->key= i+rep->firstKeyBehavior; + wire->type= pBhvr->type; + wire->data= pBhvr->data; + wire++; + } + } + buf = (char *)wire; + return buf; +} + +static int +#if NeedFunctionPrototypes +XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeExplicit(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->explicit)) { + rep->present&= ~XkbExplicitComponentsMask; + rep->firstKeyExplicit= rep->nKeyExplicit= 0; + rep->totalKeyExplicit= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nKeyExplicit;i++) { + if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0) + nRtrn++; + } + rep->totalKeyExplicit= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */ + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +#else +XkbWriteExplicit(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +char * start; +unsigned char * pExp; + + start= buf; + pExp= &xkb->server->explicit[rep->firstKeyExplicit]; + for (i=0;i<rep->nKeyExplicit;i++,pExp++) { + if (*pExp!=0) { + *buf++= i+rep->firstKeyExplicit; + *buf++= *pExp; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +#if NeedFunctionPrototypes +XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeModifierMap(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->modmap)) { + rep->present&= ~XkbModifierMapMask; + rep->firstModMapKey= rep->nModMapKeys= 0; + rep->totalModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nModMapKeys;i++) { + if (xkb->map->modmap[i+rep->firstModMapKey]!=0) + nRtrn++; + } + rep->totalModMapKeys= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */ + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteModifierMap(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +char * start; +unsigned char * pMap; + + start= buf; + pMap= &xkb->map->modmap[rep->firstModMapKey]; + for (i=0;i<rep->nModMapKeys;i++,pMap++) { + if (*pMap!=0) { + *buf++= i+rep->firstModMapKey; + *buf++= *pMap; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +#if NeedFunctionPrototypes +XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSizeVirtualModMap(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) { + rep->present&= ~XkbVirtualModMapMask; + rep->firstVModMapKey= rep->nVModMapKeys= 0; + rep->totalVModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nVModMapKeys;i++) { + if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0) + nRtrn++; + } + rep->totalVModMapKeys= nRtrn; + len= nRtrn*SIZEOF(xkbVModMapWireDesc); + return len; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +#else +XkbWriteVirtualModMap(xkb,rep,buf,client) + XkbDescPtr xkb; + xkbGetMapReply *rep; + char *buf; + ClientPtr client; +#endif +{ +unsigned i; +xkbVModMapWireDesc * wire; +unsigned short * pMap; + + wire= (xkbVModMapWireDesc *)buf; + pMap= &xkb->server->vmodmap[rep->firstVModMapKey]; + for (i=0;i<rep->nVModMapKeys;i++,pMap++) { + if (*pMap!=0) { + wire->key= i+rep->firstVModMapKey; + wire->vmods= *pMap; + wire++; + } + } + return (char *)wire; +} + +static Status +#if NeedFunctionPrototypes +XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbComputeGetMapReplySize(xkb,rep) + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +int len; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + len= XkbSizeKeyTypes(xkb,rep); + len+= XkbSizeKeySyms(xkb,rep); + len+= XkbSizeKeyActions(xkb,rep); + len+= XkbSizeKeyBehaviors(xkb,rep); + len+= XkbSizeVirtualMods(xkb,rep); + len+= XkbSizeExplicit(xkb,rep); + len+= XkbSizeModifierMap(xkb,rep); + len+= XkbSizeVirtualModMap(xkb,rep); + rep->length+= (len/4); + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep) +#else +XkbSendMap(client,xkb,rep) + ClientPtr client; + XkbDescPtr xkb; + xkbGetMapReply * rep; +#endif +{ +unsigned i,len; +char *desc,*start; + + len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)); + start= desc= (char *)ALLOCATE_LOCAL(len); + if (!start) + return BadAlloc; + if ( rep->nTypes>0 ) + desc = XkbWriteKeyTypes(xkb,rep,desc,client); + if ( rep->nKeySyms>0 ) + desc = XkbWriteKeySyms(xkb,rep,desc,client); + if ( rep->nKeyActs>0 ) + desc = XkbWriteKeyActions(xkb,rep,desc,client); + if ( rep->totalKeyBehaviors>0 ) + desc = XkbWriteKeyBehaviors(xkb,rep,desc,client); + if ( rep->virtualMods ) { + register int sz,bit; + for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&bit) { + desc[sz++]= xkb->server->vmods[i]; + } + } + desc+= XkbPaddedSize(sz); + } + if ( rep->totalKeyExplicit>0 ) + desc= XkbWriteExplicit(xkb,rep,desc,client); + if ( rep->totalModMapKeys>0 ) + desc= XkbWriteModifierMap(xkb,rep,desc,client); + if ( rep->totalVModMapKeys>0 ) + desc= XkbWriteVirtualModMap(xkb,rep,desc,client); + if ((desc-start)!=(len)) { + ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %d\n", + len, desc-start); + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->present,n); + swaps(&rep->totalSyms,n); + swaps(&rep->totalActs,n); + } + WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep); + WriteToClient(client, len, start); + DEALLOCATE_LOCAL((char *)start); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetMap(ClientPtr client) +#else +ProcXkbGetMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetMapReply rep; + XkbDescRec *xkb; + int n,status; + + REQUEST(xkbGetMapReq); + REQUEST_SIZE_MATCH(xkbGetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial); + CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask); + CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask); + + xkb= dev->key->xkbInfo->desc; + bzero(&rep,sizeof(xkbGetMapReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2; + rep.deviceID = dev->id; + rep.present = stuff->partial|stuff->full; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + if ( stuff->full&XkbKeyTypesMask ) { + rep.firstType = 0; + rep.nTypes = xkb->map->num_types; + } + else if (stuff->partial&XkbKeyTypesMask) { + if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types, + stuff->firstType,stuff->nTypes); + return BadValue; + } + rep.firstType = stuff->firstType; + rep.nTypes = stuff->nTypes; + } + else rep.nTypes = 0; + rep.totalTypes = xkb->map->num_types; + + n= XkbNumKeys(xkb); + if ( stuff->full&XkbKeySymsMask ) { + rep.firstKeySym = xkb->min_key_code; + rep.nKeySyms = n; + } + else if (stuff->partial&XkbKeySymsMask) { + CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb); + rep.firstKeySym = stuff->firstKeySym; + rep.nKeySyms = stuff->nKeySyms; + } + else rep.nKeySyms = 0; + rep.totalSyms= 0; + + if ( stuff->full&XkbKeyActionsMask ) { + rep.firstKeyAct= xkb->min_key_code; + rep.nKeyActs= n; + } + else if (stuff->partial&XkbKeyActionsMask) { + CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb); + rep.firstKeyAct= stuff->firstKeyAct; + rep.nKeyActs= stuff->nKeyActs; + } + else rep.nKeyActs= 0; + rep.totalActs= 0; + + if ( stuff->full&XkbKeyBehaviorsMask ) { + rep.firstKeyBehavior = xkb->min_key_code; + rep.nKeyBehaviors = n; + } + else if (stuff->partial&XkbKeyBehaviorsMask) { + CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb); + rep.firstKeyBehavior= stuff->firstKeyBehavior; + rep.nKeyBehaviors= stuff->nKeyBehaviors; + } + else rep.nKeyBehaviors = 0; + rep.totalKeyBehaviors= 0; + + if (stuff->full&XkbVirtualModsMask) + rep.virtualMods= ~0; + else if (stuff->partial&XkbVirtualModsMask) + rep.virtualMods= stuff->virtualMods; + + if (stuff->full&XkbExplicitComponentsMask) { + rep.firstKeyExplicit= xkb->min_key_code; + rep.nKeyExplicit= n; + } + else if (stuff->partial&XkbExplicitComponentsMask) { + CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb); + rep.firstKeyExplicit= stuff->firstKeyExplicit; + rep.nKeyExplicit= stuff->nKeyExplicit; + } + else rep.nKeyExplicit = 0; + rep.totalKeyExplicit= 0; + + if (stuff->full&XkbModifierMapMask) { + rep.firstModMapKey= xkb->min_key_code; + rep.nModMapKeys= n; + } + else if (stuff->partial&XkbModifierMapMask) { + CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb); + rep.firstModMapKey= stuff->firstModMapKey; + rep.nModMapKeys= stuff->nModMapKeys; + } + else rep.nModMapKeys = 0; + rep.totalModMapKeys= 0; + + if (stuff->full&XkbVirtualModMapMask) { + rep.firstVModMapKey= xkb->min_key_code; + rep.nVModMapKeys= n; + } + else if (stuff->partial&XkbVirtualModMapMask) { + CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb); + rep.firstVModMapKey= stuff->firstVModMapKey; + rep.nVModMapKeys= stuff->nVModMapKeys; + } + else rep.nVModMapKeys = 0; + rep.totalVModMapKeys= 0; + + if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success) + return status; + return XkbSendMap(client,xkb,&rep); +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +CheckKeyTypes( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc **wireRtrn, + int * nMapsRtrn, + CARD8 * mapWidthRtrn) +#else +CheckKeyTypes(client,xkb,req,wireRtrn,nMapsRtrn,mapWidthRtrn) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbKeyTypeWireDesc **wireRtrn; + int * nMapsRtrn; + CARD8 * mapWidthRtrn; +#endif +{ +unsigned nMaps; +register unsigned i,n; +register CARD8 * map; +register xkbKeyTypeWireDesc *wire = *wireRtrn; + + if (req->firstType>((unsigned)xkb->map->num_types)) { + *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types); + return 0; + } + if (req->flags&XkbSetMapResizeTypes) { + nMaps = req->firstType+req->nTypes; + if (nMaps<XkbNumRequiredTypes) { /* canonical types must be there */ + *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4); + return 0; + } + } + else if (req->present&XkbKeyTypesMask) { + nMaps = xkb->map->num_types; + if ((req->firstType+req->nTypes)>nMaps) { + *nMapsRtrn = req->firstType+req->nTypes; + return 0; + } + } + else { + *nMapsRtrn = xkb->map->num_types; + for (i=0;i<xkb->map->num_types;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + return 1; + } + + for (i=0;i<req->firstType;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + for (i=0;i<req->nTypes;i++) { + unsigned width; + if (client->swapped) { + register int s; + swaps(&wire->virtualMods,s); + } + n= i+req->firstType; + width= wire->numLevels; + if (width<1) { + *nMapsRtrn= _XkbErrCode3(0x04,n,width); + return 0; + } + else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + else if ((width!=2)&& + ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)|| + (n==XkbAlphabeticIndex))) { + /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + if (wire->nMapEntries>0) { + xkbKTSetMapEntryWireDesc * mapWire; + xkbModsWireDesc * preWire; + mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1]; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;n<wire->nMapEntries;n++) { + if (client->swapped) { + register int s; + swaps(&mapWire[n].virtualMods,s); + } + if (mapWire[n].realMods&(~wire->realMods)) { + *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods, + wire->realMods); + return 0; + } + if (mapWire[n].virtualMods&(~wire->virtualMods)) { + *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods); + return 0; + } + if (mapWire[n].level>=wire->numLevels) { + *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels, + mapWire[n].level); + return 0; + } + if (wire->preserve) { + if (client->swapped) { + register int s; + swaps(&preWire[n].virtualMods,s); + } + if (preWire[n].realMods&(~mapWire[n].realMods)) { + *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods, + mapWire[n].realMods); + return 0; + } + if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) { + *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods); + return 0; + } + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + mapWidthRtrn[i+req->firstType] = wire->numLevels; + wire= (xkbKeyTypeWireDesc *)map; + } + for (i=req->firstType+req->nTypes;i<nMaps;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + *nMapsRtrn = nMaps; + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + xkbSymMapWireDesc ** wireRtrn, + int * errorRtrn) +#else +CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,wireRtrn,errorRtrn) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + int nTypes; + CARD8 * mapWidths; + CARD16 * symsPerKey; + xkbSymMapWireDesc **wireRtrn; + int * errorRtrn; +#endif +{ +register unsigned i; +XkbSymMapPtr map; +xkbSymMapWireDesc* wire = *wireRtrn; + + if (!(XkbKeySymsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0); + map = &xkb->map->key_sym_map[xkb->min_key_code]; + for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) { + register int g,ng,w; + ng= XkbNumGroups(map->group_info); + for (w=g=0;g<ng;g++) { + if (map->kt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*ng; + } + for (i=0;i<req->nKeySyms;i++) { + KeySym *pSyms; + register unsigned nG; + if (client->swapped) { + swaps(&wire->nSyms,nG); + } + nG = XkbNumGroups(wire->groupInfo); + if (nG>XkbNumKbdGroups) { + *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG); + return 0; + } + if (nG>0) { + register int g,w; + for (g=w=0;g<nG;g++) { + if (wire->ktIndex[g]>=(unsigned)nTypes) { + *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g, + wire->ktIndex[g]); + return 0; + } + if (mapWidths[wire->ktIndex[g]]>w) + w= mapWidths[wire->ktIndex[g]]; + } + if (wire->width!=w) { + *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width); + return 0; + } + w*= nG; + symsPerKey[i+req->firstKeySym] = w; + if (w!=wire->nSyms) { + *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w); + return 0; + } + } + else if (wire->nSyms!=0) { + *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms); + return 0; + } + pSyms = (KeySym *)&wire[1]; + wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + + map = &xkb->map->key_sym_map[i]; + for (;i<=(unsigned)xkb->max_key_code;i++,map++) { + register int g,nG,w; + nG= XkbKeyNumGroups(xkb,i); + for (w=g=0;g<nG;g++) { + if (map->kt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*nG; + } + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + CARD8 ** wireRtrn, + int * nActsRtrn) +#else +CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,wireRtrn,nActsRtrn) + XkbDescRec *xkb; + xkbSetMapReq *req; + int nTypes; + CARD8 *mapWidths; + CARD16 *symsPerKey; + CARD8 **wireRtrn; + int *nActsRtrn; +#endif +{ +int nActs; +CARD8 * wire = *wireRtrn; +register unsigned i; + + if (!(XkbKeyActionsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0); + for (nActs=i=0;i<req->nKeyActs;i++) { + if (wire[0]!=0) { + if (wire[0]==symsPerKey[i+req->firstKeyAct]) + nActs+= wire[0]; + else { + *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]); + return 0; + } + } + wire++; + } + if (req->nKeyActs%4) + wire+= 4-(req->nKeyActs%4); + *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs); + *nActsRtrn = nActs; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyBehaviors( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbBehaviorWireDesc ** wireRtrn, + int * errorRtrn) +#else +CheckKeyBehaviors(xkb,req,wireRtrn,errorRtrn) + XkbDescRec *xkb; + xkbSetMapReq *req; + xkbBehaviorWireDesc **wireRtrn; + int *errorRtrn; +#endif +{ +register xkbBehaviorWireDesc * wire = *wireRtrn; +register XkbServerMapPtr server = xkb->server; +register unsigned i; +unsigned first,last; + + if ((req->present&XkbKeyBehaviorsMask==0)||(req->nKeyBehaviors<1)) { + req->present&= ~XkbKeyBehaviorsMask; + req->nKeyBehaviors= 0; + return 1; + } + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + if (first<req->minKeyCode) { + *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); + return 0; + } + + for (i=0;i<req->totalKeyBehaviors;i++,wire++) { + if ((wire->key<first)||(wire->key>last)) { + *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key); + return 0; + } + if ((wire->type&XkbKB_Permanent)&& + ((server->behaviors[wire->key].type!=wire->type)|| + (server->behaviors[wire->key].data!=wire->data))) { + *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type); + return 0; + } + if ((wire->type==XkbKB_RadioGroup)&& + ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) { + *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data, + XkbMaxRadioGroups); + return 0; + } + if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) { + CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0); + } + } + *wireRtrn = wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckVirtualMods( XkbDescRec * xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +#else +CheckVirtualMods(xkb,req,wireRtrn,errorRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errorRtrn; +#endif +{ +register CARD8 *wire = *wireRtrn; +register unsigned i,nMods,bit; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return 1; + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&bit) + nMods++; + } + *wireRtrn= (wire+XkbPaddedSize(nMods)); + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckKeyExplicit( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +#else +CheckKeyExplicit(xkb,req,wireRtrn,errorRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errorRtrn; +#endif +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) { + req->present&= ~XkbExplicitComponentsMask; + req->nKeyExplicit= 0; + return 1; + } + first= req->firstKeyExplicit; + last= first+req->nKeyExplicit-1; + if (first<req->minKeyCode) { + *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;i<req->totalKeyExplicit;i++,wire+=2) { + if ((wire[0]<first)||(wire[0]>last)) { + *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]); + return 0; + } + if (wire[1]&(~XkbAllExplicitMask)) { + *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn) +#else +CheckModifierMap(xkb,req,wireRtrn,errRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 ** wireRtrn; + int * errRtrn; +#endif +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) { + req->present&= ~XkbModifierMapMask; + req->nModMapKeys= 0; + return 1; + } + first= req->firstModMapKey; + last= first+req->nModMapKeys-1; + if (first<req->minKeyCode) { + *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;i<req->totalModMapKeys;i++,wire+=2) { + if ((wire[0]<first)||(wire[0]>last)) { + *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +#if NeedFunctionPrototypes +CheckVirtualModMap( XkbDescPtr xkb, + xkbSetMapReq *req, + xkbVModMapWireDesc **wireRtrn, + int *errRtrn) +#else +CheckVirtualModMap(xkb,req,wireRtrn,errRtrn) + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbVModMapWireDesc ** wireRtrn; + int * errRtrn; +#endif +{ +register xkbVModMapWireDesc * wire = *wireRtrn; +register unsigned i; +int first,last; + + if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) { + req->present&= ~XkbVirtualModMapMask; + req->nVModMapKeys= 0; + return 1; + } + first= req->firstVModMapKey; + last= first+req->nVModMapKeys-1; + if (first<req->minKeyCode) { + *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); + return 0; + } + for (i=0;i<req->totalVModMapKeys;i++,wire++) { + if ((wire->key<first)||(wire->key>last)) { + *errRtrn = _XkbErrCode4(0x73,first,last,wire->key); + return 0; + } + } + *wireRtrn= wire; + return 1; +} + +static char * +#if NeedFunctionPrototypes +SetKeyTypes( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc * wire, + XkbChangesPtr changes) +#else +SetKeyTypes(xkb,req,wire,changes) + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbKeyTypeWireDesc *wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i; +unsigned first,last; +CARD8 *map; + + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) { + i= req->firstType+req->nTypes; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) { + return NULL; + } + } + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types) + xkb->map->num_types= req->firstType+req->nTypes; + + for (i=0;i<req->nTypes;i++) { + XkbKeyTypePtr pOld; + register unsigned n; + + if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries, + wire->preserve,wire->numLevels)!=Success) { + return NULL; + } + pOld = &xkb->map->types[i+req->firstType]; + map = (CARD8 *)&wire[1]; + + pOld->mods.real_mods = wire->realMods; + pOld->mods.vmods= wire->virtualMods; + pOld->num_levels = wire->numLevels; + pOld->map_count= wire->nMapEntries; + + pOld->mods.mask= pOld->mods.real_mods| + XkbMaskForVMask(xkb,pOld->mods.vmods); + + if (wire->nMapEntries) { + xkbKTSetMapEntryWireDesc *mapWire; + xkbModsWireDesc *preWire; + unsigned tmp; + mapWire= (xkbKTSetMapEntryWireDesc *)map; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;n<wire->nMapEntries;n++) { + pOld->map[n].active= 1; + pOld->map[n].mods.mask= mapWire[n].realMods; + pOld->map[n].mods.real_mods= mapWire[n].realMods; + pOld->map[n].mods.vmods= mapWire[n].virtualMods; + pOld->map[n].level= mapWire[n].level; + if (mapWire[n].virtualMods!=0) { + tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods); + pOld->map[n].active= (tmp!=0); + pOld->map[n].mods.mask|= tmp; + } + if (wire->preserve) { + pOld->preserve[n].real_mods= preWire[n].realMods; + pOld->preserve[n].vmods= preWire[n].virtualMods; + tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods); + pOld->preserve[n].mask= preWire[n].realMods|tmp; + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + wire = (xkbKeyTypeWireDesc *)map; + } + first= req->firstType; + last= first+req->nTypes-1; /* last changed type */ + if (changes->map.changed&XkbKeyTypesMask) { + int oldLast; + oldLast= changes->map.first_type+changes->map.num_types-1; + if (changes->map.first_type<first) + first= changes->map.first_type; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type = first; + changes->map.num_types = (last-first)+1; + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbSymMapWireDesc * wire, + XkbChangesPtr changes, + DeviceIntPtr dev) +#else +SetKeySyms(client,xkb,req,wire,changes,dev) + ClientPtr client; + XkbDescPtr xkb; + xkbSetMapReq * req; + xkbSymMapWireDesc * wire; + XkbChangesPtr changes; + DeviceIntPtr dev; +#endif +{ +register unsigned i,s; +XkbSymMapPtr oldMap; +KeySym * newSyms; +KeySym * pSyms; +unsigned first,last; + + oldMap = &xkb->map->key_sym_map[req->firstKeySym]; + for (i=0;i<req->nKeySyms;i++,oldMap++) { + pSyms = (KeySym *)&wire[1]; + if (wire->nSyms>0) { + newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); + for (s=0;s<wire->nSyms;s++) { + newSyms[s]= pSyms[s]; + } + if (client->swapped) { + int n; + for (s=0;s<wire->nSyms;s++) { + swapl(&newSyms[s],n); + } + } + } + oldMap->kt_index[0] = wire->ktIndex[0]; + oldMap->kt_index[1] = wire->ktIndex[1]; + oldMap->kt_index[2] = wire->ktIndex[2]; + oldMap->kt_index[3] = wire->ktIndex[3]; + oldMap->group_info = wire->groupInfo; + oldMap->width = wire->width; + wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + first= req->firstKeySym; + last= first+req->nKeySyms-1; + if (changes->map.changed&XkbKeySymsMask) { + int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1); + if (changes->map.first_key_sym<first) + first= changes->map.first_key_sym; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = (last-first+1); + + s= 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyNumGroups(xkb,i)>s) + s= XkbKeyNumGroups(xkb,i); + } + if (s!=xkb->ctrls->num_groups) { + xkbControlsNotify cn; + XkbControlsRec old; + cn.keycode= 0; + cn.eventType= 0; + cn.requestMajor= XkbReqCode; + cn.requestMinor= X_kbSetMap; + old= *xkb->ctrls; + xkb->ctrls->num_groups= s; + if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False)) + XkbSendControlsNotify(dev,&cn); + } + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +#else +SetKeyActions(xkb,req,wire,changes) + XkbDescPtr xkb; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +CARD8 * nActs = wire; +XkbAction * newActs; + + wire+= XkbPaddedSize(req->nKeyActs); + for (i=0;i<req->nKeyActs;i++) { + if (nActs[i]==0) + xkb->server->key_acts[i+req->firstKeyAct]= 0; + else { + newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]); + memcpy((char *)newActs,(char *)wire, + nActs[i]*SIZEOF(xkbActionWireDesc)); + wire+= nActs[i]*SIZEOF(xkbActionWireDesc); + } + } + first= req->firstKeyAct; + last= (first+req->nKeyActs-1); + if (changes->map.changed&XkbKeyActionsMask) { + int oldLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + if (changes->map.first_key_act<first) + first= changes->map.first_key_act; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= first; + changes->map.num_key_acts= (last-first+1); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetKeyBehaviors( XkbSrvInfoPtr xkbi, + xkbSetMapReq *req, + xkbBehaviorWireDesc *wire, + XkbChangesPtr changes) +#else +SetKeyBehaviors(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + xkbBehaviorWireDesc*wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i; +int maxRG = -1; +XkbDescPtr xkb = xkbi->desc; +XkbServerMapPtr server = xkb->server; +unsigned first,last; + + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior)); + for (i=0;i<req->totalKeyBehaviors;i++) { + if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) { + server->behaviors[wire->key].type= wire->type; + server->behaviors[wire->key].data= wire->data; + if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG)) + maxRG= wire->data; + } + wire++; + } + + if (maxRG>(int)xkbi->nRadioGroups) { + int sz = (maxRG+1)*sizeof(XkbRadioGroupRec); + if (xkbi->radioGroups) + xkbi->radioGroups=(XkbRadioGroupPtr)Xrealloc(xkbi->radioGroups,sz); + else xkbi->radioGroups= (XkbRadioGroupPtr)Xcalloc(sz); + if (xkbi->radioGroups) { + if (xkbi->nRadioGroups) + bzero(&xkbi->radioGroups[xkbi->nRadioGroups], + (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec)); + xkbi->nRadioGroups= maxRG+1; + } + else xkbi->nRadioGroups= 0; + /* should compute members here */ + } + if (changes->map.changed&XkbKeyBehaviorsMask) { + unsigned oldLast; + oldLast= changes->map.first_key_behavior+ + changes->map.num_key_behaviors-1; + if (changes->map.first_key_behavior<req->firstKeyBehavior) + first= changes->map.first_key_behavior; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyBehaviorsMask; + changes->map.first_key_behavior = first; + changes->map.num_key_behaviors = (last-first+1); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +#else +SetVirtualMods(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register int i,bit,nMods; +XkbServerMapPtr srv = xkbi->desc->server; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return (char *)wire; + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&bit) { + if (srv->vmods[i]!=wire[nMods]) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + srv->vmods[i]= wire[nMods]; + } + nMods++; + } + } + return (char *)(wire+XkbPaddedSize(nMods)); +} + +static char * +#if NeedFunctionPrototypes +SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +#else +SetKeyExplicit(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbServerMapPtr xkb = xkbi->desc->server; +CARD8 * start; + + start= wire; + first= req->firstKeyExplicit; + last= req->firstKeyExplicit+req->nKeyExplicit-1; + bzero(&xkb->explicit[first],req->nKeyExplicit); + for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) { + xkb->explicit[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbExplicitComponentsMask) { + int oldLast; + oldLast= changes->map.first_key_explicit+ + changes->map.num_key_explicit-1; + if (changes->map.first_key_explicit<first) + first= changes->map.first_key_explicit; + if (oldLast>last) + last= oldLast; + } + changes->map.first_key_explicit= first; + changes->map.num_key_explicit= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetModifierMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +#else +SetModifierMap(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + CARD8 * wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbClientMapPtr xkb = xkbi->desc->map; +CARD8 * start; + + start= wire; + first= req->firstModMapKey; + last= req->firstModMapKey+req->nModMapKeys-1; + bzero(&xkb->modmap[first],req->nModMapKeys); + for (i=0;i<req->totalModMapKeys;i++,wire+= 2) { + xkb->modmap[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbModifierMapMask) { + int oldLast; + oldLast= changes->map.first_modmap_key+ + changes->map.num_modmap_keys-1; + if (changes->map.first_modmap_key<first) + first= changes->map.first_modmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_modmap_key= first; + changes->map.num_modmap_keys= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +#if NeedFunctionPrototypes +SetVirtualModMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + xkbVModMapWireDesc * wire, + XkbChangesPtr changes) +#else +SetVirtualModMap(xkbi,req,wire,changes) + XkbSrvInfoPtr xkbi; + xkbSetMapReq * req; + xkbVModMapWireDesc *wire; + XkbChangesPtr changes; +#endif +{ +register unsigned i,first,last; +XkbServerMapPtr srv = xkbi->desc->server; + + first= req->firstVModMapKey; + last= req->firstVModMapKey+req->nVModMapKeys-1; + bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short)); + for (i=0;i<req->totalVModMapKeys;i++,wire++) { + srv->vmodmap[wire->key]= wire->vmods; + } + if (first>0) { + if (changes->map.changed&XkbVirtualModMapMask) { + int oldLast; + oldLast= changes->map.first_vmodmap_key+ + changes->map.num_vmodmap_keys-1; + if (changes->map.first_vmodmap_key<first) + first= changes->map.first_vmodmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_vmodmap_key= first; + changes->map.num_vmodmap_keys= (last-first)+1; + } + return (char *)wire; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetMap(ClientPtr client) +#else +ProcXkbSetMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbChangesRec change; + XkbEventCauseRec cause; + int nTypes,nActions,error; + char * tmp; + CARD8 mapWidths[XkbMaxLegalKeyCode+1]; + CARD16 symsPerKey[XkbMaxLegalKeyCode+1]; + Bool sentNKN; + + REQUEST(xkbSetMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask); + + XkbSetCauseXkbReq(&cause,X_kbSetMap,client); + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + if ((xkb->min_key_code!=stuff->minKeyCode)|| + (xkb->max_key_code!=stuff->maxKeyCode)) { + if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ + stuff->minKeyCode= xkb->min_key_code; + stuff->maxKeyCode= xkb->max_key_code; + } + else { + if ((stuff->minKeyCode<XkbMinLegalKeyCode)|| + (stuff->maxKeyCode>XkbMaxLegalKeyCode)) { + client->errorValue= _XkbErrCode3(2,stuff->minKeyCode, + stuff->maxKeyCode); + return BadValue; + } + if (stuff->minKeyCode>stuff->maxKeyCode) { + client->errorValue= _XkbErrCode3(3,stuff->minKeyCode, + stuff->maxKeyCode); + return BadMatch; + } + } + } + + tmp = (char *)&stuff[1]; + if ((stuff->present&XkbKeyTypesMask)&& + (!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp, + &nTypes,mapWidths))) { + client->errorValue = nTypes; + return BadValue; + } + if ((stuff->present&XkbKeySymsMask)&& + (!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey, + (xkbSymMapWireDesc **)&tmp,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((stuff->present&XkbKeyActionsMask)&& + (!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey, + (CARD8 **)&tmp,&nActions))) { + client->errorValue = nActions; + return BadValue; + } + + if ((stuff->present&XkbKeyBehaviorsMask)&& + (!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((stuff->present&XkbVirtualModsMask)&& + (!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbExplicitComponentsMask)&& + (!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbModifierMapMask)&& + (!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if ((stuff->present&XkbVirtualModMapMask)&& + (!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) { + client->errorValue= error; + return BadValue; + } + if (((tmp-((char *)stuff))/4)!=stuff->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after check)\n"); + client->errorValue = tmp-((char *)&stuff[1]); + return BadLength; + } + bzero(&change,sizeof(change)); + sentNKN= False; + if ((xkb->min_key_code!=stuff->minKeyCode)|| + (xkb->max_key_code!=stuff->maxKeyCode)) { + Status status; + xkbNewKeyboardNotify nkn; + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode, + &change); + if (status!=Success) + return status; + nkn.minKeyCode= xkb->min_key_code; + nkn.maxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetMap; + nkn.changed= XkbNKN_KeycodesMask; + XkbSendNewKeyboardNotify(dev,&nkn); + sentNKN= True; + } + tmp = (char *)&stuff[1]; + if (stuff->present&XkbKeyTypesMask) { + tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeySymsMask) { + tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeyActionsMask) { + tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbKeyBehaviorsMask) { + tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change); + if (!tmp) goto allocFailure; + } + if (stuff->present&XkbVirtualModsMask) + tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbExplicitComponentsMask) + tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbModifierMapMask) + tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change); + if (stuff->present&XkbVirtualModMapMask) + tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change); + if (((tmp-((char *)stuff))/4)!=stuff->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after set)\n"); + client->errorValue = tmp-((char *)&stuff[1]); + return BadLength; + } + if (stuff->flags&XkbSetMapRecomputeActions) { + KeyCode first,last,firstMM,lastMM; + if (change.map.num_key_syms>0) { + first= change.map.first_key_sym; + last= first+change.map.num_key_syms-1; + } + else first= last= 0; + if (change.map.num_modmap_keys>0) { + firstMM= change.map.first_modmap_key; + lastMM= first+change.map.num_modmap_keys-1; + } + else firstMM= lastMM= 0; + if ((last>0) && (lastMM>0)) { + if (firstMM<first) + first= firstMM; + if (lastMM>last) + last= lastMM; + } + else if (lastMM>0) { + first= firstMM; + last= lastMM; + } + if (last>0) { + unsigned check= 0; + XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + } + } + if (!sentNKN) + XkbSendNotification(dev,&change,&cause); + + XkbUpdateCoreDescription(dev,False); + return client->noClientException; +allocFailure: + return BadAlloc; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +#else +XkbComputeGetCompatMapReplySize(compat,rep) + XkbCompatMapPtr compat; + xkbGetCompatMapReply * rep; +#endif +{ +unsigned size,nGroups; + + nGroups= 0; + if (rep->groups!=0) { + register int i,bit; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&bit) + nGroups++; + } + } + size= nGroups*SIZEOF(xkbModsWireDesc); + size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc)); + rep->length= size/4; + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendCompatMap( ClientPtr client, + XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +#else +XkbSendCompatMap(client,compat,rep) + ClientPtr client; + XkbCompatMapPtr compat; + xkbGetCompatMapReply * rep; +#endif +{ +char * data; +int size; + + size= rep->length*4; + if (size>0) { + data = (char *)ALLOCATE_LOCAL(size); + if (data) { + register unsigned i,bit; + xkbModsWireDesc * grp; + XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + for (i=0;i<rep->nSI;i++,sym++,wire++) { + wire->sym= sym->sym; + wire->mods= sym->mods; + wire->match= sym->match; + wire->virtualMod= sym->virtual_mod; + wire->flags= sym->flags; + memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc); + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + } + if (rep->groups) { + grp = (xkbModsWireDesc *)wire; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&bit) { + grp->mask= compat->groups[i].mask; + grp->realMods= compat->groups[i].real_mods; + grp->virtualMods= compat->groups[i].vmods; + if (client->swapped) { + register int n; + swaps(&grp->virtualMods,n); + } + grp++; + } + } + wire= (xkbSymInterpretWireDesc*)grp; + } + } + else return BadAlloc; + } + else data= NULL; + + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->firstSI,n); + swaps(&rep->nSI,n); + swaps(&rep->nTotalSI,n); + } + + WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep); + if (data) { + WriteToClient(client, size, data); + DEALLOCATE_LOCAL((char *)data); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetCompatMap(ClientPtr client) +#else +ProcXkbGetCompatMap(client) + ClientPtr client; +#endif +{ + xkbGetCompatMapReply rep; + DeviceIntPtr dev; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + + REQUEST(xkbGetCompatMapReq); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc; + compat= xkb->compat; + + rep.type = X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.firstSI = stuff->firstSI; + rep.nSI = stuff->nSI; + if (stuff->getAllSI) { + rep.firstSI = 0; + rep.nSI = compat->num_si; + } + else if ((((unsigned)stuff->nSI)>0)&& + ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) { + client->errorValue = _XkbErrCode2(0x05,compat->num_si); + return BadValue; + } + rep.nTotalSI = compat->num_si; + rep.groups= stuff->groups; + XkbComputeGetCompatMapReplySize(compat,&rep); + return XkbSendCompatMap(client,compat,&rep); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetCompatMap(ClientPtr client) +#else +ProcXkbSetCompatMap(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + char * data; + int nGroups; + register unsigned i,bit; + + REQUEST(xkbSetCompatMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + data = (char *)&stuff[1]; + xkbi = dev->key->xkbInfo; + xkb= xkbi->desc; + compat= xkb->compat; + if ((stuff->nSI>0)||(stuff->truncateSI)) { + xkbSymInterpretWireDesc *wire; + if (stuff->firstSI>compat->num_si) { + client->errorValue = _XkbErrCode2(0x02,compat->num_si); + return BadValue; + } + wire= (xkbSymInterpretWireDesc *)data; + wire+= stuff->nSI; + data = (char *)wire; + } + nGroups= 0; + if (stuff->groups!=0) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if ( stuff->groups&bit ) + nGroups++; + } + } + data+= nGroups*SIZEOF(xkbModsWireDesc); + if (((data-((char *)stuff))/4)!=stuff->length) { + return BadLength; + } + data = (char *)&stuff[1]; + if (stuff->nSI>0) { + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + XkbSymInterpretPtr sym; + if ((unsigned)(stuff->firstSI+stuff->nSI)>compat->num_si) { + compat->num_si= stuff->firstSI+stuff->nSI; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + compat->num_si, + XkbSymInterpretRec); + if (!compat->sym_interpret) { + compat->num_si= 0; + return BadAlloc; + } + } + else if (stuff->truncateSI) { + compat->num_si = stuff->firstSI+stuff->nSI; + } + sym = &compat->sym_interpret[stuff->firstSI]; + for (i=0;i<stuff->nSI;i++,wire++,sym++) { + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + sym->sym= wire->sym; + sym->mods= wire->mods; + sym->match= wire->match; + sym->flags= wire->flags; + sym->virtual_mod= wire->virtualMod; + memcpy((char *)&sym->act,(char *)&wire->act, + SIZEOF(xkbActionWireDesc)); + } + data = (char *)wire; + } + else if (stuff->truncateSI) { + compat->num_si = stuff->firstSI; + } + + if (stuff->groups!=0) { + register unsigned i,bit; + xkbModsWireDesc *wire = (xkbModsWireDesc *)data; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (stuff->groups&bit) { + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + compat->groups[i].mask= wire->realMods; + compat->groups[i].real_mods= wire->realMods; + compat->groups[i].vmods= wire->virtualMods; + if (wire->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkb,wire->virtualMods); + compat->groups[i].mask|= tmp; + } + data+= SIZEOF(xkbModsWireDesc); + wire= (xkbModsWireDesc *)data; + } + } + } + i= XkbPaddedSize((data-((char *)stuff))); + if ((i/4)!=stuff->length) { + ErrorF("Internal length error on read in ProcXkbSetCompatMap\n"); + return BadLength; + } + + if (dev->xkb_interest) { + xkbCompatMapNotify ev; + ev.deviceID = dev->id; + ev.changedGroups = stuff->groups; + ev.firstSI = stuff->firstSI; + ev.nSI = stuff->nSI; + ev.nTotalSI = compat->num_si; + XkbSendCompatMapNotify(dev,&ev); + } + + if (stuff->recomputeActions) { + XkbChangesRec change; + unsigned check; + XkbEventCauseRec cause; + + XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client); + bzero(&change,sizeof(XkbChangesRec)); + XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, + &cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + XkbUpdateCoreDescription(dev,False); + XkbSendNotification(dev,&change,&cause); + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetIndicatorState(ClientPtr client) +#else +ProcXkbGetIndicatorState(client) + ClientPtr client; +#endif +{ + xkbGetIndicatorStateReply rep; + XkbSrvLedInfoPtr sli; + DeviceIntPtr dev; + register int i; + + REQUEST(xkbGetIndicatorStateReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorStateMask); + if (!sli) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.state = sli->effectiveState; + + if (client->swapped) { + swaps(&rep.sequenceNumber,i); + swapl(&rep.state,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +Status +#if NeedFunctionPrototypes +XkbComputeGetIndicatorMapReplySize( + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply *rep) +#else +XkbComputeGetIndicatorMapReplySize(indicators,rep) + XkbIndicatorPtr indicators; + xkbGetIndicatorMapReply *rep; +#endif +{ +register int i,bit; +int nIndicators; + + rep->realIndicators = indicators->phys_indicators; + for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&bit) + nIndicators++; + } + rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4; + return Success; +} + +int +#if NeedFunctionPrototypes +XkbSendIndicatorMap( ClientPtr client, + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply * rep) +#else +XkbSendIndicatorMap(client,indicators,rep) + ClientPtr client; + XkbIndicatorPtr indicators; + xkbGetIndicatorMapReply * rep; +#endif +{ +int length; +CARD8 * map; +register int i; +register unsigned bit; + + length = rep->length*4; + if (length>0) { + CARD8 *to; + to= map= (CARD8 *)ALLOCATE_LOCAL(length); + if (map) { + xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&bit) { + wire->flags= indicators->maps[i].flags; + wire->whichGroups= indicators->maps[i].which_groups; + wire->groups= indicators->maps[i].groups; + wire->whichMods= indicators->maps[i].which_mods; + wire->mods= indicators->maps[i].mods.mask; + wire->realMods= indicators->maps[i].mods.real_mods; + wire->virtualMods= indicators->maps[i].mods.vmods; + wire->ctrls= indicators->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + swapl(&wire->ctrls,n); + } + wire++; + } + } + to = (CARD8 *)wire; + if ((to-map)!=length) { + client->errorValue = _XkbErrCode2(0xff,length); + return BadLength; + } + } + else return BadAlloc; + } + else map = NULL; + if (client->swapped) { + swaps(&rep->sequenceNumber,i); + swapl(&rep->length,i); + swapl(&rep->which,i); + swapl(&rep->realIndicators,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep); + if (map) { + WriteToClient(client, length, (char *)map); + DEALLOCATE_LOCAL((char *)map); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetIndicatorMap(ClientPtr client) +#else +ProcXkbGetIndicatorMap(client) + ClientPtr client; +#endif +{ +xkbGetIndicatorMapReply rep; +DeviceIntPtr dev; +XkbDescPtr xkb; +XkbIndicatorPtr leds; + + REQUEST(xkbGetIndicatorMapReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb= dev->key->xkbInfo->desc; + leds= xkb->indicators; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + XkbComputeGetIndicatorMapReplySize(leds,&rep); + return XkbSendIndicatorMap(client,leds,&rep); +} + +int +#if NeedFunctionPrototypes +ProcXkbSetIndicatorMap(ClientPtr client) +#else +ProcXkbSetIndicatorMap(client) + ClientPtr client; +#endif +{ + register int i,bit; + int nIndicators,why; + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + xkbIndicatorMapWireDesc *from; + XkbSrvLedInfoPtr sli; + XkbEventCauseRec cause; + + REQUEST(xkbSetIndicatorMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + dev = _XkbLookupKeyboard(stuff->deviceSpec,&why); + if (!dev) { + client->errorValue = _XkbErrCode2(why,stuff->deviceSpec); + return XkbKeyboardErrorCode; + } + xkbi= dev->key->xkbInfo; + + if (stuff->which==0) + return client->noClientException; + + for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) + nIndicators++; + } + if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ + (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { + return BadLength; + } + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorMapsMask); + if (!sli) + return BadAlloc; + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) { + if (client->swapped) { + register int n; + swaps(&from->virtualMods,n); + swapl(&from->ctrls,n); + } + CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods); + from++; + } + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) { + sli->maps[i].flags = from->flags; + sli->maps[i].which_groups = from->whichGroups; + sli->maps[i].groups = from->groups; + sli->maps[i].which_mods = from->whichMods; + sli->maps[i].mods.mask = from->mods; + sli->maps[i].mods.real_mods = from->mods; + sli->maps[i].mods.vmods= from->virtualMods; + sli->maps[i].ctrls = from->ctrls; + if (from->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkbi->desc,from->virtualMods); + sli->maps[i].mods.mask= from->mods|tmp; + } + from++; + } + } + + XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); + XkbApplyLedMapChanges(dev,sli,stuff->which,NULL,NULL,&cause); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetNamedIndicator(ClientPtr client) +#else +ProcXkbGetNamedIndicator(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetNamedIndicatorReply rep; + register int i; + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map; + Bool supported; + + REQUEST(xkbGetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_ONLY(stuff->indicator); + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0); + if (!sli) + return BadAlloc; + + supported= True; + if (XkbXIUnsupported&XkbXI_IndicatorsMask) { + if ((dev!=(DeviceIntPtr)LookupKeyboardDevice())|| + ((sli->flags&XkbSLI_IsDefault)==0)) { + supported= False; + } + } + + if (supported) { + i= 0; + map= NULL; + if ((sli->names)&&(sli->maps)) { + for (i=0;i<XkbNumIndicators;i++) { + if (stuff->indicator==sli->names[i]) { + map= &sli->maps[i]; + break; + } + } + } + } + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.deviceID = dev->id; + rep.indicator= stuff->indicator; + if ((map!=NULL)&&(supported)) { + rep.found= True; + rep.on= ((sli->effectiveState&(1<<i))!=0); + rep.realIndicator= ((sli->physIndicators&(1<<i))!=0); + rep.ndx= i; + rep.flags= map->flags; + rep.whichGroups= map->which_groups; + rep.groups= map->groups; + rep.whichMods= map->which_mods; + rep.mods= map->mods.mask; + rep.realMods= map->mods.real_mods; + rep.virtualMods= map->mods.vmods; + rep.ctrls= map->ctrls; + rep.supported= True; + } + else { + rep.found= False; + rep.on= False; + rep.realIndicator= False; + rep.ndx= XkbNoIndicator; + rep.flags= 0; + rep.whichGroups= 0; + rep.groups= 0; + rep.whichMods= 0; + rep.mods= 0; + rep.realMods= 0; + rep.virtualMods= 0; + rep.ctrls= 0; + rep.supported= supported; + } + if ( client->swapped ) { + register int n; + swapl(&rep.length,n); + swaps(&rep.sequenceNumber,n); + swapl(&rep.indicator,n); + swaps(&rep.virtualMods,n); + swapl(&rep.ctrls,n); + } + + WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep); + if (!supported) { + xkbExtensionDeviceNotify edev; + + bzero(&edev,sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_UnsupportedFeatureMask; + edev.ledClass= stuff->ledClass; + edev.ledID= stuff->ledID; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.unsupported= XkbXIUnsupported&XkbXI_IndicatorsMask; + edev.supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetNamedIndicator(ClientPtr client) +#else +ProcXkbSetNamedIndicator(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev,kbd; + XkbIndicatorMapPtr map; + XkbSrvLedInfoPtr sli; + register int led; + unsigned extDevReason; + unsigned statec,namec,mapc; + XkbEventCauseRec cause; + xkbExtensionDeviceNotify ed; + XkbChangesRec changes; + + REQUEST(xkbSetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_ONLY(stuff->indicator); + CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); + + extDevReason= 0; + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID, + XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + if (XkbXIUnsupported&XkbXI_IndicatorsMask) { + if ((dev!=(DeviceIntPtr)LookupKeyboardDevice())|| + ((sli->flags&XkbSLI_IsDefault)==0)) { + bzero(&ed,sizeof(xkbExtensionDeviceNotify)); + ed.reason= XkbXI_UnsupportedFeatureMask; + ed.ledClass= stuff->ledClass; + ed.ledID= stuff->ledID; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.ledState= sli->effectiveState; + ed.firstBtn= 0; + ed.nBtns= 0; + ed.unsupported= XkbXIUnsupported&XkbXI_IndicatorsMask; + ed.supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + XkbSendExtensionDeviceNotify(dev,client,&ed); + return client->noClientException; + } + } + + statec= mapc= namec= 0; + map= NULL; + if (sli->names && sli->maps) { + for (led=0;(led<XkbNumIndicators)&&(map==NULL);led++) { + if (sli->names[led]==stuff->indicator) { + map= &sli->maps[led]; + break; + } + } + } + if (map==NULL) { + if (!stuff->createMap) + return client->noClientException; + for (led=0,map=NULL;(led<XkbNumIndicators)&&(map==NULL);led++) { + if ((sli->names[led]==None)&&(!XkbIM_InUse(&sli->maps[led]))) { + map= &sli->maps[led]; + sli->names[led]= stuff->indicator; + break; + } + } + if (map==NULL) + return client->noClientException; + namec|= (1<<led); + sli->namesPresent|= ((stuff->indicator!=None)?(1<<led):0); + extDevReason|= XkbXI_IndicatorNamesMask; + } + + if (stuff->setMap) { + map->flags = stuff->flags; + map->which_groups = stuff->whichGroups; + map->groups = stuff->groups; + map->which_mods = stuff->whichMods; + map->mods.mask = stuff->realMods; + map->mods.real_mods = stuff->realMods; + map->mods.vmods= stuff->virtualMods; + map->ctrls = stuff->ctrls; + mapc|= (1<<led); + } + if ((stuff->setState)&&((map->flags&XkbIM_NoExplicit)==0)) { + if (stuff->on) sli->explicitState|= (1<<led); + else sli->explicitState&= ~(1<<led); + statec|= ((sli->effectiveState^sli->explicitState)&(1<<led)); + } + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd= dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd= (DeviceIntPtr)LookupKeyboardDevice(); + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + return client->noClientException; +} + +/***====================================================================***/ + +static CARD32 +#if NeedFunctionPrototypes +_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count) +#else +_XkbCountAtoms(atoms,maxAtoms,count) + Atom *atoms; + int maxAtoms; + int *count; +#endif +{ +register unsigned int i,bit,nAtoms; +register CARD32 atomsPresent; + + for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) { + if (atoms[i]!=None) { + atomsPresent|= bit; + nAtoms++; + } + } + if (count) + *count= nAtoms; + return atomsPresent; +} + +static char * +#if NeedFunctionPrototypes +_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap) +#else +_XkbWriteAtoms(wire,atoms,maxAtoms,swap) + char *wire; + Atom *atoms; + int maxAtoms; + int swap; +#endif +{ +register unsigned int i; +Atom *atm; + + atm = (Atom *)wire; + for (i=0;i<maxAtoms;i++) { + if (atoms[i]!=None) { + *atm= atoms[i]; + if (swap) { + register int n; + swapl(atm,n); + } + atm++; + } + } + return (char *)atm; +} + +static Status +#if NeedFunctionPrototypes +XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep) +#else +XkbComputeGetNamesReplySize(xkb,rep) + XkbDescPtr xkb; + xkbGetNamesReply * rep; +#endif +{ +register unsigned which,length; +register int i; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + which= rep->which; + length= 0; + if (xkb->names!=NULL) { + if (which&XkbKeycodesNameMask) length++; + if (which&XkbGeometryNameMask) length++; + if (which&XkbSymbolsNameMask) length++; + if (which&XkbPhysSymbolsNameMask) length++; + if (which&XkbTypesNameMask) length++; + if (which&XkbCompatNameMask) length++; + } + else which&= ~XkbComponentNamesMask; + + if (xkb->map!=NULL) { + if (which&XkbKeyTypeNamesMask) + length+= xkb->map->num_types; + rep->nTypes= xkb->map->num_types; + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr pType = xkb->map->types; + int nKTLevels = 0; + + length+= XkbPaddedSize(xkb->map->num_types)/4; + for (i=0;i<xkb->map->num_types;i++,pType++) { + if (pType->level_names!=NULL) + nKTLevels+= pType->num_levels; + } + rep->nKTLevels= nKTLevels; + length+= nKTLevels; + } + } + else { + rep->nTypes= 0; + rep->nKTLevels= 0; + which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask); + } + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + rep->indicators= 0; + rep->virtualMods= 0; + rep->groupNames= 0; + if (xkb->names!=NULL) { + if (which&XkbIndicatorNamesMask) { + int nLeds; + rep->indicators= + _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds); + length+= nLeds; + if (nLeds==0) + which&= ~XkbIndicatorNamesMask; + } + + if (which&XkbVirtualModNamesMask) { + int nVMods; + rep->virtualMods= + _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods); + length+= nVMods; + if (nVMods==0) + which&= ~XkbVirtualModNamesMask; + } + + if (which&XkbGroupNamesMask) { + int nGroups; + rep->groupNames= + _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups); + length+= nGroups; + if (nGroups==0) + which&= ~XkbGroupNamesMask; + } + + if ((which&XkbKeyNamesMask)&&(xkb->names->keys)) + length+= rep->nKeys; + else which&= ~XkbKeyNamesMask; + + if ((which&XkbKeyAliasesMask)&& + (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) { + rep->nKeyAliases= xkb->names->num_key_aliases; + length+= rep->nKeyAliases*2; + } + else { + which&= ~XkbKeyAliasesMask; + rep->nKeyAliases= 0; + } + + if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0)) + length+= xkb->names->num_rg; + else which&= ~XkbRGNamesMask; + } + else { + which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask); + which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask); + which&= ~XkbRGNamesMask; + } + + rep->length= length; + rep->which= which; + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep) +#else +XkbSendNames(client,xkb,rep) + ClientPtr client; + XkbDescPtr xkb; + xkbGetNamesReply * rep; +#endif +{ +register unsigned i,length,which; +char * start; +char * desc; + + length= rep->length*4; + which= rep->which; + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->which,n); + swaps(&rep->virtualMods,n); + swapl(&rep->indicators,n); + } + + start = desc = (char *)ALLOCATE_LOCAL(length); + if ( !start ) + return BadAlloc; + if (which&XkbKeycodesNameMask) { + *((CARD32 *)desc)= xkb->names->keycodes; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbGeometryNameMask) { + *((CARD32 *)desc)= xkb->names->geometry; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbSymbolsNameMask) { + *((CARD32 *)desc)= xkb->names->symbols; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbPhysSymbolsNameMask) { + register CARD32 *atm= (CARD32 *)desc; + atm[0]= (CARD32)xkb->names->phys_symbols; + if (client->swapped) { + register int n; + swapl(&atm[0],n); + } + desc+= 4; + } + if (which&XkbTypesNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->types; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbCompatNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->compat; + if (client->swapped) { + register int n; + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbKeyTypeNamesMask) { + register CARD32 *atm= (CARD32 *)desc; + register XkbKeyTypePtr type= xkb->map->types; + + for (i=0;i<xkb->map->num_types;i++,atm++,type++) { + *atm= (CARD32)type->name; + if (client->swapped) { + register int n; + swapl(atm,n); + } + } + desc= (char *)atm; + } + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr type = xkb->map->types; + register CARD32 *atm; + for (i=0;i<rep->nTypes;i++,type++) { + *desc++ = type->num_levels; + } + desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; + + atm= (CARD32 *)desc; + type = xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + register unsigned l; + if (type->level_names) { + for (l=0;l<type->num_levels;l++,atm++) { + *atm= type->level_names[l]; + if (client->swapped) { + register unsigned n; + swapl(atm,n); + } + } + desc+= type->num_levels*4; + } + } + } + if (which&XkbIndicatorNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators, + client->swapped); + } + if (which&XkbVirtualModNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods, + client->swapped); + } + if (which&XkbGroupNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups, + client->swapped); + } + if (which&XkbKeyNamesMask) { + for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) { + *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey]; + } + } + if (which&XkbKeyAliasesMask) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { + *((XkbKeyAliasPtr)desc)= *pAl; + } + } + if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { + register CARD32 *atm= (CARD32 *)desc; + for (i=0;i<rep->nRadioGroups;i++,atm++) { + *atm= (CARD32)xkb->names->radio_groups[i]; + if (client->swapped) { + register unsigned n; + swapl(atm,n); + } + } + desc+= rep->nRadioGroups*4; + } + if ((desc-start)!=(length)) { + ErrorF("BOGUS LENGTH in write names, expected %d, got %d\n", + length, desc-start); + } + WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); + WriteToClient(client, length, start); + DEALLOCATE_LOCAL((char *)start); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetNames(ClientPtr client) +#else +ProcXkbGetNames(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbDescPtr xkb; + xkbGetNamesReply rep; + + REQUEST(xkbGetNamesReq); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + rep.nTypes = xkb->map->num_types; + rep.firstKey = xkb->min_key_code; + rep.nKeys = XkbNumKeys(xkb); + if (xkb->names!=NULL) { + rep.nKeyAliases= xkb->names->num_key_aliases; + rep.nRadioGroups = xkb->names->num_rg; + } + else { + rep.nKeyAliases= rep.nRadioGroups= 0; + } + XkbComputeGetNamesReplySize(xkb,&rep); + return XkbSendNames(client,xkb,&rep); +} + +/***====================================================================***/ + +static CARD32 * +#if NeedFunctionPrototypes +_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError) +#else +_XkbCheckAtoms(wire,nAtoms,swapped,pError) + CARD32 *wire; + int nAtoms; + int swapped; + Atom *pError; +#endif +{ +register int i; + + for (i=0;i<nAtoms;i++,wire++) { + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) { + *pError= ((Atom)*wire); + return NULL; + } + } + return wire; +} + +static CARD32 * +#if NeedFunctionPrototypes +_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped, + Atom *pError) +#else +_XkbCheckMaskedAtoms(wire,nAtoms,present,swapped,pError) + CARD32 *wire; + int nAtoms; + CARD32 present; + int swapped; + Atom *pError; +#endif +{ +register unsigned i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) { + *pError= (Atom)*wire; + return NULL; + } + wire++; + } + return wire; +} + +static Atom * +#if NeedFunctionPrototypes +_XkbCopyMaskedAtoms( Atom *wire, + Atom *dest, + int nAtoms, + CARD32 present) +#else +_XkbCopyMaskedAtoms(wire,dest,nAtoms,present) + Atom *wire; + Atom *dest; + int nAtoms; + CARD32 present; +#endif +{ +register int i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + dest[i]= *wire++; + } + return wire; +} + +static Bool +#if NeedFunctionPrototypes +_XkbCheckTypeName(Atom name,int typeNdx) +#else +_XkbCheckTypeName(name,typeNdx) + Atom name; + int typeNdx; +#endif +{ +char * str; + + str= NameForAtom(name); + if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)|| + (strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0)) + return False; + return True; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetNames(ClientPtr client) +#else +ProcXkbSetNames(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbDescRec *xkb; + XkbNamesRec *names; + xkbNamesNotify nn; + CARD32 *tmp; + Atom bad; + + REQUEST(xkbSetNamesReq); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + names = xkb->names; + tmp = (CARD32 *)&stuff[1]; + + if (stuff->which&XkbKeycodesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGeometryNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbPhysSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbTypesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbCompatNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyTypeNamesMask) { + register int i; + CARD32 *old; + if ( stuff->nTypes<1 ) { + client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); + return BadValue; + } + if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x03,stuff->firstType, + stuff->nTypes, + xkb->map->num_types); + return BadValue; + } + if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { + client->errorValue = _XkbErrCode2(0x04,stuff->firstType); + return BadAccess; + } + old= tmp; + tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + for (i=0;i<stuff->nTypes;i++,old++) { + if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) + client->errorValue= _XkbErrCode2(0x05,i); + } + } + if (stuff->which&XkbKTLevelNamesMask) { + register unsigned i; + XkbKeyTypePtr type; + CARD8 * width; + if ( stuff->nKTLevels<1 ) { + client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); + return BadValue; + } + if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= + xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, + stuff->nKTLevels,xkb->map->num_types); + return BadValue; + } + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type = &xkb->map->types[stuff->firstKTLevel]; + for (i=0;i<stuff->nKTLevels;i++,type++) { + if (width[i]==0) + continue; + else if (width[i]!=type->num_levels) { + client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, + type->num_levels,width[i]); + return BadMatch; + } + tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + } + if (stuff->which&XkbIndicatorNamesMask) { + if (stuff->indicators==0) { + client->errorValue= 0x08; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, + client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbVirtualModNamesMask) { + if (stuff->virtualMods==0) { + client->errorValue= 0x09; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, + (CARD32)stuff->virtualMods, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGroupNamesMask) { + if (stuff->groupNames==0) { + client->errorValue= 0x0a; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, + (CARD32)stuff->groupNames, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyNamesMask) { + if (stuff->firstKey<(unsigned)xkb->min_key_code) { + client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, + stuff->firstKey); + return BadValue; + } + if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| + (stuff->nKeys<1)) { + client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, + stuff->firstKey,stuff->nKeys); + return BadValue; + } + tmp+= stuff->nKeys; + } + if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { + tmp+= stuff->nKeyAliases*2; + } + if (stuff->which&XkbRGNamesMask) { + if ( stuff->nRadioGroups<1 ) { + client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); + return BadValue; + } + tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if ((tmp-((CARD32 *)stuff))!=stuff->length) { + client->errorValue = stuff->length; + return BadLength; + } + if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, + stuff->nKeyAliases)!=Success) { + return BadAlloc; + } + + /* everything is okay -- update names */ + bzero(&nn,sizeof(xkbNamesNotify)); + nn.changed= stuff->which; + tmp = (CARD32 *)&stuff[1]; + if (stuff->which&XkbKeycodesNameMask) + names->keycodes= *tmp++; + if (stuff->which&XkbGeometryNameMask) + names->geometry= *tmp++; + if (stuff->which&XkbSymbolsNameMask) + names->symbols= *tmp++; + if (stuff->which&XkbPhysSymbolsNameMask) + names->phys_symbols= *tmp++; + if (stuff->which&XkbTypesNameMask) + names->types= *tmp++; + if (stuff->which&XkbCompatNameMask) + names->compat= *tmp++; + if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { + register unsigned i; + register XkbKeyTypePtr type; + + type= &xkb->map->types[stuff->firstType]; + for (i=0;i<stuff->nTypes;i++,type++) { + type->name= *tmp++; + } + nn.firstType= stuff->firstType; + nn.nTypes= stuff->nTypes; + } + if (stuff->which&XkbKTLevelNamesMask) { + register XkbKeyTypePtr type; + register unsigned i; + CARD8 *width; + + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type= &xkb->map->types[stuff->firstKTLevel]; + for (i=0;i<stuff->nKTLevels;i++,type++) { + if (width[i]>0) { + if (type->level_names) { + register unsigned n; + for (n=0;n<width[i];n++) { + type->level_names[n]= tmp[n]; + } + } + tmp+= width[i]; + } + } + nn.firstLevelName= 0; + nn.nLevelNames= stuff->nTypes; + } + if (stuff->which&XkbIndicatorNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, + stuff->indicators); + nn.changedIndicators= stuff->indicators; + } + if (stuff->which&XkbVirtualModNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, + stuff->virtualMods); + nn.changedVirtualMods= stuff->virtualMods; + } + if (stuff->which&XkbGroupNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, + stuff->groupNames); + nn.changedVirtualMods= stuff->groupNames; + } + if (stuff->which&XkbKeyNamesMask) { + memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, + stuff->nKeys*XkbKeyNameLength); + tmp+= stuff->nKeys; + nn.firstKey= stuff->firstKey; + nn.nKeys= stuff->nKeys; + } + if (stuff->which&XkbKeyAliasesMask) { + if (stuff->nKeyAliases>0) { + register int na= stuff->nKeyAliases; + if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) + return BadAlloc; + memcpy((char *)names->key_aliases,(char *)tmp, + stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); + tmp+= stuff->nKeyAliases*2; + } + else if (names->key_aliases!=NULL) { + _XkbFree(names->key_aliases); + names->key_aliases= NULL; + names->num_key_aliases= 0; + } + nn.nAliases= names->num_key_aliases; + } + if (stuff->which&XkbRGNamesMask) { + if (stuff->nRadioGroups>0) { + register unsigned i,nrg; + nrg= stuff->nRadioGroups; + if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) + return BadAlloc; + + for (i=0;i<stuff->nRadioGroups;i++) { + names->radio_groups[i]= tmp[i]; + } + tmp+= stuff->nRadioGroups; + } + else if (names->radio_groups) { + Xfree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + nn.nRadioGroups= names->num_rg; + } + if (nn.changed) { + Bool needExtEvent; + needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; + XkbSendNamesNotify(dev,&nn); + if (needExtEvent) { + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify edev; + register int i; + register unsigned bit; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorsMask); + sli->namesPresent= 0; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (names->indicators[i]!=None) + sli->namesPresent|= bit; + } + bzero(&edev,sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_IndicatorNamesMask; + edev.ledClass= KbdFeedbackClass; + edev.ledID= dev->kbdfeed->ctrl.id; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.supported= XkbXI_AllFeaturesMask; + edev.unsupported= 0; + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + } + return client->noClientException; +} + +/***====================================================================***/ + +#include "XKBgeom.h" + +#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) + +static char * +#if NeedFunctionPrototypes +XkbWriteCountedString(char *wire,char *str,Bool swap) +#else +XkbWriteCountedString(wire,str,swap) + char * wire; + char * str; + Bool swap; +#endif +{ +CARD16 len,*pLen; + + len= (str?strlen(str):0); + pLen= (CARD16 *)wire; + *pLen= len; + if (swap) { + register int n; + swaps(pLen,n); + } + memcpy(&wire[2],str,len); + wire+= ((2+len+3)/4)*4; + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomProperties(XkbGeometryPtr geom) +#else +XkbSizeGeomProperties(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +XkbPropertyPtr prop; + + for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + size+= XkbSizeCountedString(prop->name); + size+= XkbSizeCountedString(prop->value); + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomProperties(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +register XkbPropertyPtr prop; + + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + wire= XkbWriteCountedString(wire,prop->name,swap); + wire= XkbWriteCountedString(wire,prop->value,swap); + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomKeyAliases(XkbGeometryPtr geom) +#else +XkbSizeGeomKeyAliases(geom) + XkbGeometryPtr geom; +#endif +{ + return geom->num_key_aliases*(2*XkbKeyNameLength); +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomKeyAliases(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int sz; + + sz= geom->num_key_aliases*(XkbKeyNameLength*2); + if (sz>0) { + memcpy(wire,(char *)geom->key_aliases,sz); + wire+= sz; + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomColors(XkbGeometryPtr geom) +#else +XkbSizeGeomColors(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +register XkbColorPtr color; + + for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) { + size+= XkbSizeCountedString(color->spec); + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomColors(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +register XkbColorPtr color; + + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + wire= XkbWriteCountedString(wire,color->spec,swap); + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomShapes(XkbGeometryPtr geom) +#else +XkbSizeGeomShapes(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +register XkbShapePtr shape; + + for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) { + register int n; + register XkbOutlinePtr ol; + size+= SIZEOF(xkbShapeWireDesc); + for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) { + size+= SIZEOF(xkbOutlineWireDesc); + size+= ol->num_points*SIZEOF(xkbPointWireDesc); + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomShapes(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +int i; +XkbShapePtr shape; +xkbShapeWireDesc * shapeWire; + + for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) { + register int o; + XkbOutlinePtr ol; + xkbOutlineWireDesc * olWire; + shapeWire= (xkbShapeWireDesc *)wire; + shapeWire->name= shape->name; + shapeWire->nOutlines= shape->num_outlines; + if (shape->primary!=NULL) + shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary); + else shapeWire->primaryNdx= XkbNoShape; + if (shape->approx!=NULL) + shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx); + else shapeWire->approxNdx= XkbNoShape; + if (swap) { + register int n; + swapl(&shapeWire->name,n); + } + wire= (char *)&shapeWire[1]; + for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + olWire= (xkbOutlineWireDesc *)wire; + olWire->nPoints= ol->num_points; + olWire->cornerRadius= ol->corner_radius; + wire= (char *)&olWire[1]; + ptWire= (xkbPointWireDesc *)wire; + for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) { + ptWire[p].x= pt->x; + ptWire[p].y= pt->y; + if (swap) { + register int n; + swaps(&ptWire[p].x,n); + swaps(&ptWire[p].y,n); + } + } + wire= (char *)&ptWire[ol->num_points]; + } + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad) +#else +XkbSizeGeomDoodads(num_doodads,doodad) + int num_doodads; + XkbDoodadPtr doodad; +#endif +{ +register int i,size; + + for (i=size=0;i<num_doodads;i++,doodad++) { + size+= SIZEOF(xkbAnyDoodadWireDesc); + if (doodad->any.type==XkbTextDoodad) { + size+= XkbSizeCountedString(doodad->text.text); + size+= XkbSizeCountedString(doodad->text.font); + } + else if (doodad->any.type==XkbLogoDoodad) { + size+= XkbSizeCountedString(doodad->logo.logo_name); + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap) +#else +XkbWriteGeomDoodads(wire,num_doodads,doodad,swap) + char * wire; + int num_doodads; + XkbDoodadPtr doodad; + Bool swap; +#endif +{ +register int i; +xkbDoodadWireDesc * doodadWire; + + for (i=0;i<num_doodads;i++,doodad++) { + doodadWire= (xkbDoodadWireDesc *)wire; + wire= (char *)&doodadWire[1]; + bzero(doodadWire,SIZEOF(xkbDoodadWireDesc)); + doodadWire->any.name= doodad->any.name; + doodadWire->any.type= doodad->any.type; + doodadWire->any.priority= doodad->any.priority; + doodadWire->any.top= doodad->any.top; + doodadWire->any.left= doodad->any.left; + if (swap) { + register int n; + swapl(&doodadWire->any.name,n); + swaps(&doodadWire->any.top,n); + swaps(&doodadWire->any.left,n); + } + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodadWire->shape.angle= doodad->shape.angle; + doodadWire->shape.colorNdx= doodad->shape.color_ndx; + doodadWire->shape.shapeNdx= doodad->shape.shape_ndx; + if (swap) { + register int n; + swaps(&doodadWire->shape.angle,n); + } + break; + case XkbTextDoodad: + doodadWire->text.angle= doodad->text.angle; + doodadWire->text.width= doodad->text.width; + doodadWire->text.height= doodad->text.height; + doodadWire->text.colorNdx= doodad->text.color_ndx; + if (swap) { + register int n; + swaps(&doodadWire->text.angle,n); + swaps(&doodadWire->text.width,n); + swaps(&doodadWire->text.height,n); + } + wire= XkbWriteCountedString(wire,doodad->text.text,swap); + wire= XkbWriteCountedString(wire,doodad->text.font,swap); + break; + case XkbIndicatorDoodad: + doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx; + doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx; + doodadWire->indicator.offColorNdx= + doodad->indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodadWire->logo.angle= doodad->logo.angle; + doodadWire->logo.colorNdx= doodad->logo.color_ndx; + doodadWire->logo.shapeNdx= doodad->logo.shape_ndx; + wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); + break; + default: + ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n"); + ErrorF("Ignored\n"); + break; + } + } + return wire; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap) +#else +XkbWriteGeomOverlay(wire,ol,swap) + char * wire; + XkbOverlayPtr ol; + Bool swap; +#endif +{ +register int r; +XkbOverlayRowPtr row; +xkbOverlayWireDesc * olWire; + + olWire= (xkbOverlayWireDesc *)wire; + olWire->name= ol->name; + olWire->nRows= ol->num_rows; + if (swap) { + register int n; + swapl(&olWire->name,n); + } + wire= (char *)&olWire[1]; + for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + unsigned int k; + XkbOverlayKeyPtr key; + xkbOverlayRowWireDesc * rowWire; + rowWire= (xkbOverlayRowWireDesc *)wire; + rowWire->rowUnder= row->row_under; + rowWire->nKeys= row->num_keys; + wire= (char *)&rowWire[1]; + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + xkbOverlayKeyWireDesc * keyWire; + keyWire= (xkbOverlayKeyWireDesc *)wire; + memcpy(keyWire->over,key->over.name,XkbKeyNameLength); + memcpy(keyWire->under,key->under.name,XkbKeyNameLength); + wire= (char *)&keyWire[1]; + } + } + return wire; +} + +static int +#if NeedFunctionPrototypes +XkbSizeGeomSections(XkbGeometryPtr geom) +#else +XkbSizeGeomSections(geom) + XkbGeometryPtr geom; +#endif +{ +register int i,size; +XkbSectionPtr section; + + for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) { + size+= SIZEOF(xkbSectionWireDesc); + if (section->rows) { + int r; + XkbRowPtr row; + for (r=0,row=section->rows;r<section->num_rows;row++,r++) { + size+= SIZEOF(xkbRowWireDesc); + size+= row->num_keys*SIZEOF(xkbKeyWireDesc); + } + } + if (section->doodads) + size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads); + if (section->overlays) { + int o; + XkbOverlayPtr ol; + for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) { + int r; + XkbOverlayRowPtr row; + size+= SIZEOF(xkbOverlayWireDesc); + for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + size+= SIZEOF(xkbOverlayRowWireDesc); + size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc); + } + } + } + } + return size; +} + +static char * +#if NeedFunctionPrototypes +XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap) +#else +XkbWriteGeomSections(wire,geom,swap) + char * wire; + XkbGeometryPtr geom; + Bool swap; +#endif +{ +register int i; +XkbSectionPtr section; +xkbSectionWireDesc * sectionWire; + + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + sectionWire= (xkbSectionWireDesc *)wire; + sectionWire->name= section->name; + sectionWire->top= section->top; + sectionWire->left= section->left; + sectionWire->width= section->width; + sectionWire->height= section->height; + sectionWire->angle= section->angle; + sectionWire->priority= section->priority; + sectionWire->nRows= section->num_rows; + sectionWire->nDoodads= section->num_doodads; + sectionWire->nOverlays= section->num_overlays; + sectionWire->pad= 0; + if (swap) { + register int n; + swapl(§ionWire->name,n); + swaps(§ionWire->top,n); + swaps(§ionWire->left,n); + swaps(§ionWire->width,n); + swaps(§ionWire->height,n); + swaps(§ionWire->angle,n); + } + wire= (char *)§ionWire[1]; + if (section->rows) { + int r; + XkbRowPtr row; + xkbRowWireDesc * rowWire; + for (r=0,row=section->rows;r<section->num_rows;r++,row++) { + rowWire= (xkbRowWireDesc *)wire; + rowWire->top= row->top; + rowWire->left= row->left; + rowWire->nKeys= row->num_keys; + rowWire->vertical= row->vertical; + rowWire->pad= 0; + if (swap) { + register int n; + swaps(&rowWire->top,n); + swaps(&rowWire->left,n); + } + wire= (char *)&rowWire[1]; + if (row->keys) { + int k; + XkbKeyPtr key; + xkbKeyWireDesc * keyWire; + keyWire= (xkbKeyWireDesc *)wire; + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength); + keyWire[k].gap= key->gap; + keyWire[k].shapeNdx= key->shape_ndx; + keyWire[k].colorNdx= key->color_ndx; + if (swap) { + register int n; + swaps(&keyWire[k].gap,n); + } + } + wire= (char *)&keyWire[row->num_keys]; + } + } + } + if (section->doodads) { + wire= XkbWriteGeomDoodads(wire, + section->num_doodads,section->doodads, + swap); + } + if (section->overlays) { + register int o; + for (o=0;o<section->num_overlays;o++) { + wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap); + } + } + } + return wire; +} + +static Status +#if NeedFunctionPrototypes +XkbComputeGetGeometryReplySize( XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Atom name) +#else +XkbComputeGetGeometryReplySize(geom,rep,name) + XkbGeometryPtr geom; + xkbGetGeometryReply * rep; + Atom name; +#endif +{ +int len; + + if (geom!=NULL) { + len= XkbSizeCountedString(geom->label_font); + len+= XkbSizeGeomProperties(geom); + len+= XkbSizeGeomColors(geom); + len+= XkbSizeGeomShapes(geom); + len+= XkbSizeGeomSections(geom); + len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads); + len+= XkbSizeGeomKeyAliases(geom); + rep->length= len/4; + rep->found= True; + rep->name= geom->name; + rep->widthMM= geom->width_mm; + rep->heightMM= geom->height_mm; + rep->nProperties= geom->num_properties; + rep->nColors= geom->num_colors; + rep->nShapes= geom->num_shapes; + rep->nSections= geom->num_sections; + rep->nDoodads= geom->num_doodads; + rep->nKeyAliases= geom->num_key_aliases; + rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color); + rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color); + } + else { + rep->length= 0; + rep->found= False; + rep->name= name; + rep->widthMM= rep->heightMM= 0; + rep->nProperties= rep->nColors= rep->nShapes= 0; + rep->nSections= rep->nDoodads= 0; + rep->nKeyAliases= 0; + rep->labelColorNdx= rep->baseColorNdx= 0; + } + return Success; +} + +static int +#if NeedFunctionPrototypes +XkbSendGeometry( ClientPtr client, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Bool freeGeom) +#else +XkbSendGeometry(client,geom,rep,freeGeom) + ClientPtr client; + XkbGeometryPtr geom; + xkbGetGeometryReply *rep; + Bool freeGeom; +#endif +{ + char *desc,*start; + int len; + + if (geom!=NULL) { + len= rep->length*4; + start= desc= (char *)ALLOCATE_LOCAL(len); + if (!start) + return BadAlloc; + desc= XkbWriteCountedString(desc,geom->label_font,client->swapped); + if ( rep->nProperties>0 ) + desc = XkbWriteGeomProperties(desc,geom,client->swapped); + if ( rep->nColors>0 ) + desc = XkbWriteGeomColors(desc,geom,client->swapped); + if ( rep->nShapes>0 ) + desc = XkbWriteGeomShapes(desc,geom,client->swapped); + if ( rep->nSections>0 ) + desc = XkbWriteGeomSections(desc,geom,client->swapped); + if ( rep->nDoodads>0 ) + desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads, + client->swapped); + if ( rep->nKeyAliases>0 ) + desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); + if ((desc-start)!=(len)) { + ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %d\n", + len, desc-start); + } + } + else { + len= 0; + start= NULL; + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->name,n); + swaps(&rep->widthMM,n); + swaps(&rep->heightMM,n); + swaps(&rep->nProperties,n); + swaps(&rep->nColors,n); + swaps(&rep->nShapes,n); + swaps(&rep->nSections,n); + swaps(&rep->nDoodads,n); + swaps(&rep->nKeyAliases,n); + } + WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep); + if (len>0) + WriteToClient(client, len, start); + if (start!=NULL) + DEALLOCATE_LOCAL((char *)start); + if (freeGeom) + XkbFreeGeometry(geom,XkbGeomAllMask,True); + return client->noClientException; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetGeometry(ClientPtr client) +#else +ProcXkbGetGeometry(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbGetGeometryReply rep; + XkbGeometryPtr geom; + Bool shouldFree; + Status status; + + REQUEST(xkbGetGeometryReq); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree); + rep.type= X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber= client->sequence; + rep.length= 0; + status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name); + if (status!=Success) + return status; + else return XkbSendGeometry(client,geom,&rep,shouldFree); +} + +/***====================================================================***/ + +static char * +#if NeedFunctionPrototypes +_GetCountedString(char **wire_inout,Bool swap) +#else +_GetCountedString(wire_inout,swap) + char ** wire_inout; + Bool swap; +#endif +{ +char * wire,*str; +CARD16 len,*plen; + + wire= *wire_inout; + plen= (CARD16 *)wire; + if (swap) { + register int n; + swaps(plen,n); + } + len= *plen; + str= (char *)_XkbAlloc(len+1); + if (str) { + memcpy(str,&wire[2],len); + str[len]= '\0'; + } + wire+= XkbPaddedSize(len+2); + *wire_inout= wire; + return str; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetDoodad( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +#else +_CheckSetDoodad(wire_inout,geom,section,client) + char ** wire_inout; + XkbGeometryPtr geom; + XkbSectionPtr section; + ClientPtr client; +#endif +{ +char * wire; +xkbDoodadWireDesc * dWire; +XkbDoodadPtr doodad; + + dWire= (xkbDoodadWireDesc *)(*wire_inout); + wire= (char *)&dWire[1]; + if (client->swapped) { + register int n; + swapl(&dWire->any.name,n); + swaps(&dWire->any.top,n); + swaps(&dWire->any.left,n); + swaps(&dWire->any.angle,n); + } + CHK_ATOM_ONLY(dWire->any.name); + doodad= XkbAddGeomDoodad(geom,section,dWire->any.name); + if (!doodad) + return BadAlloc; + doodad->any.type= dWire->any.type; + doodad->any.priority= dWire->any.priority; + doodad->any.top= dWire->any.top; + doodad->any.left= dWire->any.left; + doodad->any.angle= dWire->any.angle; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (dWire->shape.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x40,geom->num_colors, + dWire->shape.colorNdx); + return BadMatch; + } + if (dWire->shape.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x41,geom->num_shapes, + dWire->shape.shapeNdx); + return BadMatch; + } + doodad->shape.color_ndx= dWire->shape.colorNdx; + doodad->shape.shape_ndx= dWire->shape.shapeNdx; + break; + case XkbTextDoodad: + if (dWire->text.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x42,geom->num_colors, + dWire->text.colorNdx); + return BadMatch; + } + if (client->swapped) { + register int n; + swaps(&dWire->text.width,n); + swaps(&dWire->text.height,n); + } + doodad->text.width= dWire->text.width; + doodad->text.height= dWire->text.height; + doodad->text.color_ndx= dWire->text.colorNdx; + doodad->text.text= _GetCountedString(&wire,client->swapped); + doodad->text.font= _GetCountedString(&wire,client->swapped); + break; + case XkbIndicatorDoodad: + if (dWire->indicator.onColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x43,geom->num_colors, + dWire->indicator.onColorNdx); + return BadMatch; + } + if (dWire->indicator.offColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x44,geom->num_colors, + dWire->indicator.offColorNdx); + return BadMatch; + } + if (dWire->indicator.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x45,geom->num_shapes, + dWire->indicator.shapeNdx); + return BadMatch; + } + doodad->indicator.shape_ndx= dWire->indicator.shapeNdx; + doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx; + doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx; + break; + case XkbLogoDoodad: + if (dWire->logo.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x46,geom->num_colors, + dWire->logo.colorNdx); + return BadMatch; + } + if (dWire->logo.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x47,geom->num_shapes, + dWire->logo.shapeNdx); + return BadMatch; + } + doodad->logo.color_ndx= dWire->logo.colorNdx; + doodad->logo.shape_ndx= dWire->logo.shapeNdx; + doodad->logo.logo_name= _GetCountedString(&wire,client->swapped); + break; + default: + client->errorValue= _XkbErrCode2(0x4F,dWire->any.type); + return BadValue; + } + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetOverlay( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +#else +_CheckSetOverlay(wire_inout,geom,section,client) + char ** wire_inout; + XkbGeometryPtr geom; + XkbSectionPtr section; + ClientPtr client; +#endif +{ +register int r; +char * wire; +XkbOverlayPtr ol; +xkbOverlayWireDesc * olWire; +xkbOverlayRowWireDesc * rWire; + + wire= *wire_inout; + olWire= (xkbOverlayWireDesc *)wire; + if (client->swapped) { + register int n; + swapl(&olWire->name,n); + } + CHK_ATOM_ONLY(olWire->name); + ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); + rWire= (xkbOverlayRowWireDesc *)&olWire[1]; + for (r=0;r<olWire->nRows;r++) { + register int k; + xkbOverlayKeyWireDesc * kWire; + XkbOverlayRowPtr row; + + if (rWire->rowUnder>section->num_rows) { + client->errorValue= _XkbErrCode4(0x20,r,section->num_rows, + rWire->rowUnder); + return BadMatch; + } + row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys); + kWire= (xkbOverlayKeyWireDesc *)&rWire[1]; + for (k=0;k<rWire->nKeys;k++,kWire++) { + if (XkbAddGeomOverlayKey(ol,row, + (char *)kWire->over,(char *)kWire->under)==NULL) { + client->errorValue= _XkbErrCode3(0x21,r,k); + return BadMatch; + } + } + rWire= (xkbOverlayRowWireDesc *)kWire; + } + olWire= (xkbOverlayWireDesc *)rWire; + wire= (char *)olWire; + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetSections( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +#else +_CheckSetSections(geom,req,wire_inout,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + char ** wire_inout; + ClientPtr client; +#endif +{ +Status status; +register int s; +char * wire; +xkbSectionWireDesc * sWire; +XkbSectionPtr section; + + wire= *wire_inout; + if (req->nSections<1) + return Success; + sWire= (xkbSectionWireDesc *)wire; + for (s=0;s<req->nSections;s++) { + register int r; + xkbRowWireDesc * rWire; + if (client->swapped) { + register int n; + swapl(&sWire->name,n); + swaps(&sWire->top,n); + swaps(&sWire->left,n); + swaps(&sWire->width,n); + swaps(&sWire->height,n); + swaps(&sWire->angle,n); + } + CHK_ATOM_ONLY(sWire->name); + section= XkbAddGeomSection(geom,sWire->name,sWire->nRows, + sWire->nDoodads,sWire->nOverlays); + if (!section) + return BadAlloc; + section->priority= sWire->priority; + section->top= sWire->top; + section->left= sWire->left; + section->width= sWire->width; + section->height= sWire->height; + section->angle= sWire->angle; + rWire= (xkbRowWireDesc *)&sWire[1]; + for (r=0;r<sWire->nRows;r++) { + register int k; + XkbRowPtr row; + xkbKeyWireDesc * kWire; + if (client->swapped) { + register int n; + swaps(&rWire->top,n); + swaps(&rWire->left,n); + } + row= XkbAddGeomRow(section,rWire->nKeys); + if (!row) + return BadAlloc; + row->top= rWire->top; + row->left= rWire->left; + row->vertical= rWire->vertical; + kWire= (xkbKeyWireDesc *)&rWire[1]; + for (k=0;k<rWire->nKeys;k++) { + XkbKeyPtr key; + key= XkbAddGeomKey(row); + if (!key) + return BadAlloc; + memcpy(key->name.name,kWire[k].name,XkbKeyNameLength); + key->gap= kWire[k].gap; + key->shape_ndx= kWire[k].shapeNdx; + key->color_ndx= kWire[k].colorNdx; + if (key->shape_ndx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x10,key->shape_ndx, + geom->num_shapes); + return BadMatch; + } + if (key->color_ndx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x11,key->color_ndx, + geom->num_colors); + return BadMatch; + } + } + rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys]; + } + wire= (char *)rWire; + if (sWire->nDoodads>0) { + register int d; + for (d=0;d<sWire->nDoodads;d++) { + status=_CheckSetDoodad(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + if (sWire->nOverlays>0) { + register int o; + for (o=0;o<sWire->nOverlays;o++) { + status= _CheckSetOverlay(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + sWire= (xkbSectionWireDesc *)wire; + } + wire= (char *)sWire; + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetShapes( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +#else +_CheckSetShapes(geom,req,wire_inout,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + char ** wire_inout; + ClientPtr client; +#endif +{ +register int i; +char * wire; + + wire= *wire_inout; + if (req->nShapes<1) { + client->errorValue= _XkbErrCode2(0x06,req->nShapes); + return BadValue; + } + else { + xkbShapeWireDesc * shapeWire; + XkbShapePtr shape; + register int o; + shapeWire= (xkbShapeWireDesc *)wire; + for (i=0;i<req->nShapes;i++) { + xkbOutlineWireDesc * olWire; + XkbOutlinePtr ol; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); + for (o=0;o<shapeWire->nOutlines;o++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + + ol= XkbAddGeomOutline(shape,olWire->nPoints); + if (!ol) + return BadAlloc; + ol->corner_radius= olWire->cornerRadius; + ptWire= (xkbPointWireDesc *)&olWire[1]; + for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) { + pt->x= ptWire[p].x; + pt->y= ptWire[p].y; + if (client->swapped) { + register int n; + swaps(&pt->x,n); + swaps(&pt->y,n); + } + } + ol->num_points= olWire->nPoints; + olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]); + } + if (shapeWire->primaryNdx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire->primaryNdx]; + if (shapeWire->approxNdx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire->approxNdx]; + shapeWire= (xkbShapeWireDesc *)olWire; + } + wire= (char *)shapeWire; + } + if (geom->num_shapes!=req->nShapes) { + client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes); + return BadMatch; + } + + *wire_inout= wire; + return Success; +} + +static Status +#if NeedFunctionPrototypes +_CheckSetGeom( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + ClientPtr client) +#else +_CheckSetGeom(geom,req,client) + XkbGeometryPtr geom; + xkbSetGeometryReq * req; + ClientPtr client; +#endif +{ +register int i; +Status status; +char * wire; + + wire= (char *)&req[1]; + geom->label_font= _GetCountedString(&wire,client->swapped); + + for (i=0;i<req->nProperties;i++) { + char *name,*val; + name= _GetCountedString(&wire,client->swapped); + val= _GetCountedString(&wire,client->swapped); + if ((!name)||(!val)||(XkbAddGeomProperty(geom,name,val)==NULL)) + return BadAlloc; + } + + if (req->nColors<2) { + client->errorValue= _XkbErrCode3(0x01,2,req->nColors); + return BadValue; + } + if (req->baseColorNdx>req->nColors) { + client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx); + return BadMatch; + } + if (req->labelColorNdx>req->nColors) { + client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx); + return BadMatch; + } + if (req->labelColorNdx==req->baseColorNdx) { + client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx, + req->labelColorNdx); + return BadMatch; + } + + for (i=0;i<req->nColors;i++) { + char *name; + name= _GetCountedString(&wire,client->swapped); + if ((!name)||(!XkbAddGeomColor(geom,name,geom->num_colors))) + return BadAlloc; + } + if (req->nColors!=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors); + return BadMatch; + } + geom->label_color= &geom->colors[req->labelColorNdx]; + geom->base_color= &geom->colors[req->baseColorNdx]; + + if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success) + return status; + + if ((status=_CheckSetSections(geom,req,&wire,client))!=Success) + return status; + + for (i=0;i<req->nDoodads;i++) { + status=_CheckSetDoodad(&wire,geom,NULL,client); + if (status!=Success) + return status; + } + + for (i=0;i<req->nKeyAliases;i++) { + if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL) + return BadAlloc; + wire+= 2*XkbKeyNameLength; + } + return Success; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetGeometry(ClientPtr client) +#else +ProcXkbSetGeometry(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbGeometryPtr geom,old; + XkbGeometrySizesRec sizes; + Status status; + XkbDescPtr xkb; + Bool new_name; + xkbNewKeyboardNotify nkn; + + REQUEST(xkbSetGeometryReq); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_ATOM_OR_NONE(stuff->name); + + xkb= dev->key->xkbInfo->desc; + old= xkb->geom; + xkb->geom= NULL; + + sizes.which= XkbGeomAllMask; + sizes.num_properties= stuff->nProperties; + sizes.num_colors= stuff->nColors; + sizes.num_shapes= stuff->nShapes; + sizes.num_sections= stuff->nSections; + sizes.num_doodads= stuff->nDoodads; + sizes.num_key_aliases= stuff->nKeyAliases; + if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { + xkb->geom= old; + return status; + } + geom= xkb->geom; + geom->name= stuff->name; + geom->width_mm= stuff->widthMM; + geom->height_mm= stuff->heightMM; + if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= old; + return status; + } + new_name= (xkb->names->geometry!=geom->name); + xkb->names->geometry= geom->name; + if (old) + XkbFreeGeometry(old,XkbGeomAllMask,True); + if (new_name) { + xkbNamesNotify nn; + bzero(&nn,sizeof(xkbNamesNotify)); + nn.changed= XkbGeometryNameMask; + XkbSendNamesNotify(dev,&nn); + } + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; + nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetGeometry; + nkn.changed= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + return Success; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbPerClientFlags(ClientPtr client) +#else +ProcXkbPerClientFlags(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbPerClientFlagsReply rep; + XkbInterestPtr interest; + + REQUEST(xkbPerClientFlagsReq); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask); + CHK_MASK_MATCH(0x02,stuff->change,stuff->value); + + interest = XkbFindClientResource((DevicePtr)dev,client); + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->change) { + client->xkbClientFlags&= ~stuff->change; + client->xkbClientFlags|= stuff->value; + } + if (stuff->change&XkbPCF_AutoResetControlsMask) { + Bool want; + want= stuff->value&XkbPCF_AutoResetControlsMask; + if (interest && !want) { + interest->autoCtrls= interest->autoCtrlValues= 0; + } + else if (want && (!interest)) { + XID id = FakeClientID(client->index); + AddResource(id,RT_XKBCLIENT,dev); + interest= XkbAddClientResource((DevicePtr)dev,client,id); + if (!interest) + return BadAlloc; + } + if (interest && want ) { + register unsigned affect; + affect= stuff->ctrlsToChange; + + CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls); + CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues); + + interest->autoCtrls&= ~affect; + interest->autoCtrlValues&= ~affect; + interest->autoCtrls|= stuff->autoCtrls&affect; + interest->autoCtrlValues|= stuff->autoCtrlValues&affect; + } + } + rep.supported = XkbPCF_AllFlagsMask; + rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask; + if (interest) { + rep.autoCtrls= interest->autoCtrls; + rep.autoCtrlValues= interest->autoCtrlValues; + } + else { + rep.autoCtrls= rep.autoCtrlValues= 0; + } + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.supported,n); + swapl(&rep.value,n); + swapl(&rep.autoCtrls,n); + swapl(&rep.autoCtrlValues,n); + } + WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ +/* and wildcards */ +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +/* same as above but accepts percent, plus and bar too */ +static unsigned char componentExprLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +static char * +#if NeedFunctionPrototypes +GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn) +#else +GetComponentSpec(pWire,allowExpr,errRtrn) + unsigned char ** pWire; + Bool allowExpr; + int * errRtrn; +#endif +{ +int len; +register int i; +unsigned char *wire,*str,*tmp,*legal; + + if (allowExpr) legal= &componentExprLegal[0]; + else legal= &componentSpecLegal[0]; + + wire= *pWire; + len= (*(unsigned char *)wire++); + if (len>0) { + str= (unsigned char *)Xcalloc(len+1); + if (str) { + tmp= str; + for (i=0;i<len;i++) { + if (legal[(*wire)/8]&(1<<((*wire)%8))) + *tmp++= *wire++; + else wire++; + } + if (tmp!=str) + *tmp++= '\0'; + else { + Xfree(str); + str= NULL; + } + } + else { + *errRtrn= BadAlloc; + } + } + else { + str= NULL; + } + *pWire= wire; + return (char *)str; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbListComponents(ClientPtr client) +#else +ProcXkbListComponents(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + xkbListComponentsReply rep; + unsigned len; + int status; + unsigned char * str; + XkbSrvListInfoRec list; + + REQUEST(xkbListComponentsReq); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + status= Success; + str= (unsigned char *)&stuff[1]; + bzero(&list,sizeof(XkbSrvListInfoRec)); + list.maxRtrn= stuff->maxNames; + list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status); + list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + if ((status=XkbDDXList(dev,&list,client))!=Success) { + if (list.pool) { + _XkbFree(list.pool); + list.pool= NULL; + } + return status; + } + bzero(&rep,sizeof(xkbListComponentsReply)); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = XkbPaddedSize(list.nPool)/4; + rep.nKeymaps = list.nFound[_XkbListKeymaps]; + rep.nKeycodes = list.nFound[_XkbListKeycodes]; + rep.nTypes = list.nFound[_XkbListTypes]; + rep.nCompatMaps = list.nFound[_XkbListCompat]; + rep.nSymbols = list.nFound[_XkbListSymbols]; + rep.nGeometries = list.nFound[_XkbListGeometry]; + rep.extra= 0; + if (list.nTotal>list.maxRtrn) + rep.extra = (list.nTotal-list.maxRtrn); + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.nKeymaps,n); + swaps(&rep.nKeycodes,n); + swaps(&rep.nTypes,n); + swaps(&rep.nCompatMaps,n); + swaps(&rep.nSymbols,n); + swaps(&rep.nGeometries,n); + swaps(&rep.extra,n); + } + WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep); + if (list.nPool && list.pool) { + WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool); + _XkbFree(list.pool); + list.pool= NULL; + } + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbGetKbdByName(ClientPtr client) +#else +ProcXkbGetKbdByName(client) + ClientPtr client; +#endif +{ + DeviceIntPtr dev; + XkbFileInfo finfo; + xkbGetKbdByNameReply rep; + xkbGetMapReply mrep; + xkbGetCompatMapReply crep; + xkbGetIndicatorMapReply irep; + xkbGetNamesReply nrep; + xkbGetGeometryReply grep; + XkbComponentNamesRec names; + XkbDescPtr xkb; + unsigned char * str; + char mapFile[PATH_MAX]; + unsigned len; + unsigned fwant,fneed,reported; + int status; + Bool geom_changed; + + REQUEST(xkbGetKbdByNameReq); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev,stuff->deviceSpec); + + xkb = dev->key->xkbInfo->desc; + status= Success; + str= (unsigned char *)&stuff[1]; + names.keymap= GetComponentSpec(&str,True,&status); + names.keycodes= GetComponentSpec(&str,True,&status); + names.types= GetComponentSpec(&str,True,&status); + names.compat= GetComponentSpec(&str,True,&status); + names.symbols= GetComponentSpec(&str,True,&status); + names.geometry= GetComponentSpec(&str,True,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + + CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask); + CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask); + + if (stuff->load) + fwant= XkbGBN_AllComponentsMask; + else fwant= stuff->want|stuff->need; + if (!names.keymap) { + if ((!names.compat)&& + (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) { + names.compat= _XkbDupString("%"); + } + if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) { + names.types= _XkbDupString("%"); + } + if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) { + names.symbols= _XkbDupString("%"); + } + geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0)); + if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) { + names.geometry= _XkbDupString("%"); + geom_changed= False; + } + } + else { + geom_changed= True; + } + + bzero(mapFile,PATH_MAX); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + rep.loaded= False; + fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask; + fneed= XkbConvertGetByNameComponents(True,stuff->need); + rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed); + if (stuff->load) { + fneed|= XkmKeymapRequired; + fwant|= XkmKeymapLegal; + } + if ((fwant|fneed)&XkmSymbolsMask) { + fneed|= XkmKeyNamesIndex|XkmTypesIndex; + fwant|= XkmIndicatorsIndex; + } + rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&finfo, + mapFile,PATH_MAX); + rep.newKeyboard= False; + rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0; + + stuff->want|= stuff->need; + if (finfo.xkb==NULL) + rep.reported= 0; + else { + if (stuff->load) + rep.loaded= True; + if (stuff->load || + ((rep.reported&XkbGBN_SymbolsMask) && (finfo.xkb->compat))) { + XkbChangesRec changes; + bzero(&changes,sizeof(changes)); + XkbUpdateDescActions(finfo.xkb, + finfo.xkb->min_key_code,XkbNumKeys(finfo.xkb), + &changes); + } + + if (finfo.xkb->map==NULL) + rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask); + else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) { + mrep.type= X_Reply; + mrep.deviceID = dev->id; + mrep.sequenceNumber= client->sequence; + mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2); + mrep.minKeyCode = finfo.xkb->min_key_code; + mrep.maxKeyCode = finfo.xkb->max_key_code; + mrep.present = 0; + mrep.totalSyms = mrep.totalActs = + mrep.totalKeyBehaviors= mrep.totalKeyExplicit= + mrep.totalModMapKeys= 0; + if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) { + mrep.present|= XkbKeyTypesMask; + mrep.firstType = 0; + mrep.nTypes = mrep.totalTypes= finfo.xkb->map->num_types; + } + else { + mrep.firstType = mrep.nTypes= 0; + mrep.totalTypes= 0; + } + if (rep.reported&XkbGBN_ClientSymbolsMask) { + mrep.present|= (XkbKeySymsMask|XkbModifierMapMask); + mrep.firstKeySym = mrep.firstModMapKey= finfo.xkb->min_key_code; + mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(finfo.xkb); + } + else { + mrep.firstKeySym= mrep.firstModMapKey= 0; + mrep.nKeySyms= mrep.nModMapKeys= 0; + } + if (rep.reported&XkbGBN_ServerSymbolsMask) { + mrep.present|= XkbAllServerInfoMask; + mrep.virtualMods= ~0; + mrep.firstKeyAct = mrep.firstKeyBehavior = + mrep.firstKeyExplicit = finfo.xkb->min_key_code; + mrep.nKeyActs = mrep.nKeyBehaviors = + mrep.nKeyExplicit = XkbNumKeys(finfo.xkb); + } + else { + mrep.virtualMods= 0; + mrep.firstKeyAct= mrep.firstKeyBehavior= + mrep.firstKeyExplicit = 0; + mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0; + } + XkbComputeGetMapReplySize(finfo.xkb,&mrep); + rep.length+= SIZEOF(xGenericReply)/4+mrep.length; + } + if (finfo.xkb->compat==NULL) + rep.reported&= ~XkbGBN_CompatMapMask; + else if (rep.reported&XkbGBN_CompatMapMask) { + crep.type= X_Reply; + crep.deviceID= dev->id; + crep.sequenceNumber= client->sequence; + crep.length= 0; + crep.groups= XkbAllGroupsMask; + crep.firstSI= 0; + crep.nSI= crep.nTotalSI= finfo.xkb->compat->num_si; + XkbComputeGetCompatMapReplySize(finfo.xkb->compat,&crep); + rep.length+= SIZEOF(xGenericReply)/4+crep.length; + } + if (finfo.xkb->indicators==NULL) + rep.reported&= ~XkbGBN_IndicatorMapMask; + else if (rep.reported&XkbGBN_IndicatorMapMask) { + irep.type= X_Reply; + irep.deviceID= dev->id; + irep.sequenceNumber= client->sequence; + irep.length= 0; + irep.which= XkbAllIndicatorsMask; + XkbComputeGetIndicatorMapReplySize(finfo.xkb->indicators,&irep); + rep.length+= SIZEOF(xGenericReply)/4+irep.length; + } + if (finfo.xkb->names==NULL) + rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask); + else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) { + nrep.type= X_Reply; + nrep.deviceID= dev->id; + nrep.sequenceNumber= client->sequence; + nrep.length= 0; + nrep.minKeyCode= finfo.xkb->min_key_code; + nrep.maxKeyCode= finfo.xkb->max_key_code; + if (rep.reported&XkbGBN_OtherNamesMask) { + nrep.which= XkbAllNamesMask; + if (finfo.xkb->map!=NULL) + nrep.nTypes= finfo.xkb->map->num_types; + else nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= XkbAllGroupsMask; + nrep.virtualMods= XkbAllVirtualModsMask; + nrep.indicators= XkbAllIndicatorsMask; + nrep.nRadioGroups= finfo.xkb->names->num_rg; + } + else { + nrep.which= 0; + nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= 0; + nrep.virtualMods= 0; + nrep.indicators= 0; + nrep.nRadioGroups= 0; + } + if (rep.reported&XkbGBN_KeyNamesMask) { + nrep.which|= XkbKeyNamesMask; + nrep.firstKey= finfo.xkb->min_key_code; + nrep.nKeys= XkbNumKeys(finfo.xkb); + nrep.nKeyAliases= finfo.xkb->names->num_key_aliases; + if (nrep.nKeyAliases) + nrep.which|= XkbKeyAliasesMask; + } + else { + nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask); + nrep.firstKey= nrep.nKeys= 0; + nrep.nKeyAliases= 0; + } + XkbComputeGetNamesReplySize(finfo.xkb,&nrep); + rep.length+= SIZEOF(xGenericReply)/4+nrep.length; + } + if (finfo.xkb->geom==NULL) + rep.reported&= ~XkbGBN_GeometryMask; + else if (rep.reported&XkbGBN_GeometryMask) { + grep.type= X_Reply; + grep.deviceID= dev->id; + grep.sequenceNumber= client->sequence; + grep.length= 0; + grep.found= True; + grep.pad= 0; + grep.widthMM= grep.heightMM= 0; + grep.nProperties= grep.nColors= grep.nShapes= 0; + grep.nSections= grep.nDoodads= 0; + grep.baseColorNdx= grep.labelColorNdx= 0; + XkbComputeGetGeometryReplySize(finfo.xkb->geom,&grep,None); + rep.length+= SIZEOF(xGenericReply)/4+grep.length; + } + } + + reported= rep.reported; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.found,n); + swaps(&rep.reported,n); + } + WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep); + if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) + XkbSendMap(client,finfo.xkb,&mrep); + if (reported&XkbGBN_CompatMapMask) + XkbSendCompatMap(client,finfo.xkb->compat,&crep); + if (reported&XkbGBN_IndicatorMapMask) + XkbSendIndicatorMap(client,finfo.xkb->indicators,&irep); + if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask)) + XkbSendNames(client,finfo.xkb,&nrep); + if (reported&XkbGBN_GeometryMask) + XkbSendGeometry(client,finfo.xkb->geom,&grep,False); + if (rep.loaded) { + XkbDescPtr old_xkb; + xkbNewKeyboardNotify nkn; + int i,nG,nTG; + old_xkb= xkb; + xkb= finfo.xkb; + dev->key->xkbInfo->desc= xkb; + finfo.xkb= old_xkb; /* so it'll get freed automatically */ + + if (dev->kbdfeed && dev->kbdfeed->xkb_sli) { + XkbFreeSrvLedInfo(dev->kbdfeed->xkb_sli); + dev->kbdfeed->xkb_sli= NULL; + } + *xkb->ctrls= *old_xkb->ctrls; + for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + nG= XkbKeyNumGroups(xkb,i); + if (nG>=XkbNumKbdGroups) { + nTG= XkbNumKbdGroups; + break; + } + if (nG>nTG) { + nTG= nG; + } + } + xkb->ctrls->num_groups= nTG; + + memcpy(dev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + XkbUpdateCoreDescription(dev,True); + + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= finfo.xkb->min_key_code; + nkn.maxKeyCode= finfo.xkb->max_key_code; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbGetKbdByName; + nkn.changed= XkbNKN_KeycodesMask; + if (geom_changed) + nkn.changed|= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + } + if ((finfo.xkb!=NULL)&&(finfo.xkb!=xkb)) { + XkbFreeKeyboard(finfo.xkb,XkbAllComponentsMask,True); + finfo.xkb= NULL; + } + if (names.keymap) { Xfree(names.keymap); names.keymap= NULL; } + if (names.keycodes) { Xfree(names.keycodes); names.keycodes= NULL; } + if (names.types) { Xfree(names.types); names.types= NULL; } + if (names.compat) { Xfree(names.compat); names.compat= NULL; } + if (names.symbols) { Xfree(names.symbols); names.symbols= NULL; } + if (names.geometry) { Xfree(names.geometry); names.geometry= NULL; } + return client->noClientException; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ComputeDeviceLedInfoSize( DeviceIntPtr dev, + unsigned int what, + XkbSrvLedInfoPtr sli) +#else +ComputeDeviceLedInfoSize(dev,what,sli) + DeviceIntPtr dev; + unsigned int what; + XkbSrvLedInfoPtr sli; +#endif +{ +int nNames,nMaps; +register unsigned n,bit; + + if (sli==NULL) + return 0; + nNames= nMaps= 0; + if ((what&XkbXI_IndicatorNamesMask)==0) + sli->namesPresent= 0; + if ((what&XkbXI_IndicatorMapsMask)==0) + sli->mapsPresent= 0; + + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (sli->names && sli->names[n]!=None) { + sli->namesPresent|= bit; + nNames++; + } + if (sli->maps && XkbIM_InUse(&sli->maps[n])) { + sli->mapsPresent|= bit; + nMaps++; + } + } + return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc)); +} + +static int +#if NeedFunctionPrototypes +CheckDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + xkbGetDeviceInfoReply * rep, + ClientPtr client) +#else +CheckDeviceLedFBs(dev,class,id,rep,client) + DeviceIntPtr dev; + int class; + int id; + xkbGetDeviceInfoReply * rep; + ClientPtr client; +#endif +{ +int nFBs= 0; +int length= 0; +Bool classOk; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else { + client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; + } + } + classOk= False; + if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + classOk= True; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!kf->xkb_sli) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + classOk= True; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!lf->xkb_sli) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if (nFBs>0) { + if (rep->supported&XkbXI_IndicatorsMask) { + rep->nDeviceLedFBs= nFBs; + rep->length+= (length/4); + } + return Success; + } + if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id); + else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; +} + +static int +#if NeedFunctionPrototypes +SendDeviceLedInfo( XkbSrvLedInfoPtr sli, + ClientPtr client) +#else +SendDeviceLedInfo(sli,client) + XkbSrvLedInfoPtr sli; + ClientPtr client; +#endif +{ +xkbDeviceLedsWireDesc wire; +int length; + + length= 0; + wire.ledClass= sli->class; + wire.ledID= sli->id; + wire.namesPresent= sli->namesPresent; + wire.mapsPresent= sli->mapsPresent; + wire.physIndicators= sli->physIndicators; + wire.state= sli->effectiveState; + if (client->swapped) { + register int n; + swaps(&wire.ledClass,n); + swaps(&wire.ledID,n); + swapl(&wire.namesPresent,n); + swapl(&wire.mapsPresent,n); + swapl(&wire.physIndicators,n); + swapl(&wire.state,n); + } + WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire); + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (sli->namesPresent|sli->mapsPresent) { + register unsigned i,bit; + if (sli->namesPresent) { + CARD32 awire; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (sli->namesPresent&bit) { + awire= (CARD32)sli->names[i]; + if (client->swapped) { + register int n; + swapl(&awire,n); + } + WriteToClient(client,4,(char *)&awire); + length+= 4; + } + } + } + if (sli->mapsPresent) { + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + xkbIndicatorMapWireDesc iwire; + if (sli->mapsPresent&bit) { + iwire.flags= sli->maps[i].flags; + iwire.whichGroups= sli->maps[i].which_groups; + iwire.groups= sli->maps[i].groups; + iwire.whichMods= sli->maps[i].which_mods; + iwire.mods= sli->maps[i].mods.mask; + iwire.realMods= sli->maps[i].mods.real_mods; + iwire.virtualMods= sli->maps[i].mods.vmods; + iwire.ctrls= sli->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&iwire.virtualMods,n); + swapl(&iwire.ctrls,n); + } + WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc), + (char *)&iwire); + length+= SIZEOF(xkbIndicatorMapWireDesc); + } + } + } + } + return length; +} + +static int +#if NeedFunctionPrototypes +SendDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + unsigned wantLength, + ClientPtr client) +#else +SendDeviceLedFBs(dev,class,id,wantLength,client) + DeviceIntPtr dev; + int class; + int id; + unsigned wantLength; + ClientPtr client; +#endif +{ +int length= 0; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + } + if ((dev->kbdfeed)&& + ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) { + length+= SendDeviceLedInfo(kf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if ((dev->leds)&& + ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) { + length+= SendDeviceLedInfo(lf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if (length==wantLength) + return Success; + else return BadLength; +} + +int +#if NeedFunctionPrototypes +ProcXkbGetDeviceInfo(ClientPtr client) +#else +ProcXkbGetDeviceInfo(client) + ClientPtr client; +#endif +{ +DeviceIntPtr dev; +xkbGetDeviceInfoReply rep; +int status,nDeviceLedFBs; +unsigned length,nameLen; +CARD16 ledClass,ledID; +unsigned wanted,supported; +char * str; + + REQUEST(xkbGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + wanted= stuff->wanted; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask); + + if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns))) + wanted&= ~XkbXI_ButtonActionsMask; + if ((!dev->kbdfeed)&&(!dev->leds)) + wanted&= ~XkbXI_IndicatorsMask; + wanted&= ~XkbXIUnsupported; + + nameLen= XkbSizeCountedString(dev->name); + bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply)); + rep.type = X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber = client->sequence; + rep.length = nameLen/4; + rep.present = wanted; + rep.supported = XkbXI_AllDeviceFeaturesMask&(~XkbXIUnsupported); + rep.unsupported = XkbXIUnsupported; + rep.firstBtnWanted = rep.nBtnsWanted = 0; + rep.firstBtnRtrn = rep.nBtnsRtrn = 0; + if (dev->button) + rep.totalBtns= dev->button->numButtons; + else rep.totalBtns= 0; + rep.devType= dev->type; + rep.hasOwnState= (dev->key && dev->key->xkbInfo); + rep.nDeviceLedFBs = 0; + if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id; + else rep.dfltKbdFB= XkbXINone; + if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id; + else rep.dfltLedFB= XkbXINone; + + ledClass= stuff->ledClass; + ledID= stuff->ledID; + + rep.firstBtnWanted= rep.nBtnsWanted= 0; + rep.firstBtnRtrn= rep.nBtnsRtrn= 0; + if (wanted&XkbXI_ButtonActionsMask) { + if (stuff->allBtns) { + stuff->firstBtn= 0; + stuff->nBtns= dev->button->numButtons; + } + + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons, + stuff->firstBtn, + stuff->nBtns); + return BadValue; + } + else { + rep.firstBtnWanted= stuff->firstBtn; + rep.nBtnsWanted= stuff->nBtns; + if (dev->button->xkb_acts!=NULL) { + XkbAction *act; + register int i; + + rep.firstBtnRtrn= stuff->firstBtn; + rep.nBtnsRtrn= stuff->nBtns; + act= &dev->button->xkb_acts[rep.firstBtnWanted]; + for (i=0;i<rep.nBtnsRtrn;i++,act++) { + if (act->type!=XkbSA_NoAction) + break; + } + rep.firstBtnRtrn+= i; + rep.nBtnsRtrn-= i; + act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; + for (i=0;i<rep.nBtnsRtrn;i++,act--) { + if (act->type!=XkbSA_NoAction) + break; + } + rep.nBtnsRtrn-= i; + } + rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4; + } + } + + if (wanted&XkbXI_IndicatorsMask) { + status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client); + if (status!=Success) + return status; + } + length= rep.length*4; + supported= rep.supported; + nDeviceLedFBs = rep.nDeviceLedFBs; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.present,n); + swaps(&rep.supported,n); + swaps(&rep.unsupported,n); + swaps(&rep.nDeviceLedFBs,n); + swapl(&rep.type,n); + } + WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep); + + str= (char*) ALLOCATE_LOCAL(nameLen); + if (!str) + return BadAlloc; + XkbWriteCountedString(str,dev->name,client->swapped); + WriteToClient(client,nameLen,str); + DEALLOCATE_LOCAL(str); + length-= nameLen; + + if (rep.nBtnsRtrn>0) { + int sz; + xkbActionWireDesc * awire; + sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc); + awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn]; + WriteToClient(client,sz,(char *)awire); + length-= sz; + } + if (nDeviceLedFBs>0) { + status= SendDeviceLedFBs(dev,ledClass,ledID,length,client); + if (status!=Success) + return status; + } + else if (length!=0) { +#ifdef DEBUG + ErrorF("Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF(" Wrote %d fewer bytes than expected\n",length); +#endif + return BadLength; + } + if (stuff->wanted&(~supported)) { + xkbExtensionDeviceNotify ed; + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.ledClass= ledClass; + ed.ledID= ledID; + ed.ledsDefined= 0; + ed.ledState= 0; + ed.firstBtn= ed.nBtns= 0; + ed.reason= XkbXI_UnsupportedFeatureMask; + ed.supported= supported; + ed.unsupported= stuff->wanted&(~supported); + XkbSendExtensionDeviceNotify(dev,client,&ed); + } + return client->noClientException; +} + +static char * +#if NeedFunctionPrototypes +CheckSetDeviceIndicators( char * wire, + DeviceIntPtr dev, + int num, + int * status_rtrn, + ClientPtr client) +#else +CheckSetDeviceIndicators(wire,dev,num,status_rtrn,client) + char * wire; + DeviceIntPtr dev; + int num; + int * status_rtrn; + ClientPtr client; +#endif +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbSrvLedInfoPtr sli; + + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;i<num;i++) { + if (client->swapped) { + register int n; + swaps(&ledWire->ledClass,n); + swaps(&ledWire->ledID,n); + swapl(&ledWire->namesPresent,n); + swapl(&ledWire->mapsPresent,n); + swapl(&ledWire->physIndicators,n); + } + + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorsMask); + if (sli!=NULL) { + register int n; + register unsigned bit; + int nMaps,nNames; + CARD32 *atomWire; + xkbIndicatorMapWireDesc *mapWire; + + nMaps= nNames= 0; + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&bit) + nNames++; + if (ledWire->mapsPresent&bit) + nMaps++; + } + atomWire= (CARD32 *)&ledWire[1]; + if (nNames>0) { + for (n=0;n<nNames;n++) { + if (client->swapped) { + register int t; + swapl(atomWire,t); + } + CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue, + *status_rtrn,NULL); + atomWire++; + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (nMaps>0) { + for (n=0;n<nMaps;n++) { + if (client->swapped) { + register int t; + swaps(&mapWire->virtualMods,t); + swapl(&mapWire->ctrls,t); + } + CHK_MASK_LEGAL3(0x21,mapWire->whichGroups, + XkbIM_UseAnyGroup, + client->errorValue, + *status_rtrn,NULL); + CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods, + client->errorValue, + *status_rtrn,NULL); + mapWire++; + } + } + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + else { + /* SHOULD NEVER HAPPEN */ + return (char *)ledWire; + } + } + return (char *)ledWire; +} + +static char * +#if NeedFunctionPrototypes +SetDeviceIndicators( char * wire, + DeviceIntPtr dev, + unsigned changed, + int num, + int * status_rtrn, + ClientPtr client, + xkbExtensionDeviceNotify *ev) +#else +SetDeviceIndicators(wire,dev,changed,num,status_rtrn,client,ev) + char * wire; + DeviceIntPtr dev; + unsigned changed; + int num; + ClientPtr client; + int * status_rtrn; + xkbExtensionDeviceNotify *ev; +#endif +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbEventCauseRec cause; +unsigned namec,mapc,statec; +xkbExtensionDeviceNotify ed; +XkbChangesRec changes; +DeviceIntPtr kbd; + + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;i<num;i++) { + register int n; + register unsigned bit; + CARD32 * atomWire; + xkbIndicatorMapWireDesc * mapWire; + XkbSrvLedInfoPtr sli; + + namec= mapc= statec= 0; + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorMapsMask); + if (!sli) { + /* SHOULD NEVER HAPPEN!! */ + return (char *)ledWire; + } + + atomWire= (CARD32 *)&ledWire[1]; + if (changed&XkbXI_IndicatorNamesMask) { + namec= sli->namesPresent|ledWire->namesPresent; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + } + if (ledWire->namesPresent) { + sli->namesPresent= ledWire->namesPresent; + bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom)); + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&bit) { + sli->names[n]= (Atom)*atomWire; + if (sli->names[n]==None) + ledWire->namesPresent&= ~bit; + atomWire++; + } + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (changed&XkbXI_IndicatorMapsMask) { + mapc= sli->mapsPresent|ledWire->mapsPresent; + sli->mapsPresent= ledWire->mapsPresent; + bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec)); + } + if (ledWire->mapsPresent) { + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->mapsPresent&bit) { + sli->maps[n].flags= mapWire->flags; + sli->maps[n].which_groups= mapWire->whichGroups; + sli->maps[n].groups= mapWire->groups; + sli->maps[n].which_mods= mapWire->whichMods; + sli->maps[n].mods.mask= mapWire->mods; + sli->maps[n].mods.real_mods=mapWire->realMods; + sli->maps[n].mods.vmods= mapWire->virtualMods; + sli->maps[n].ctrls= mapWire->ctrls; + mapWire++; + } + } + } + if (changed&XkbXI_IndicatorStateMask) { + statec= sli->effectiveState^ledWire->state; + sli->explicitState&= ~statec; + sli->explicitState|= (ledWire->state&statec); + } + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd= dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + return (char *)ledWire; +} + +int +#if NeedFunctionPrototypes +ProcXkbSetDeviceInfo(ClientPtr client) +#else +ProcXkbSetDeviceInfo(client) + ClientPtr client; +#endif +{ +DeviceIntPtr dev; +unsigned change; +char * wire; +xkbExtensionDeviceNotify ed; + + REQUEST(xkbSetDeviceInfoReq); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + change= stuff->change; + + CHK_ANY_DEVICE(dev,stuff->deviceSpec); + CHK_MASK_LEGAL(0x01,change,(XkbXI_AllFeaturesMask&(~XkbXI_KeyboardsMask))); + + wire= (char *)&stuff[1]; + if (change&XkbXI_ButtonActionsMask) { + if (!dev->button) { + client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass); + return XkbKeyboardErrorCode; + } + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns, + dev->button->numButtons); + return BadMatch; + } + wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc)); + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs, + &status,client); + if (status!=Success) + return status; + } + if (((wire-((char *)stuff))/4)!=stuff->length) + return BadLength; + + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + wire= (char *)&stuff[1]; + if (change&XkbXI_ButtonActionsMask) { + int nBtns,sz,i; + XkbAction * acts; + DeviceIntPtr kbd; + + nBtns= dev->button->numButtons; + acts= dev->button->xkb_acts; + if (acts==NULL) { + acts= _XkbTypedCalloc(nBtns,XkbAction); + if (!acts) + return BadAlloc; + dev->button->xkb_acts= acts; + } + sz= stuff->nBtns*SIZEOF(xkbActionWireDesc); + memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz); + wire+= sz; + ed.reason|= XkbXI_ButtonActionsMask; + ed.firstBtn= stuff->firstBtn; + ed.nBtns= stuff->nBtns; + + if (dev->key) kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + acts= &dev->button->xkb_acts[stuff->firstBtn]; + for (i=0;i<stuff->nBtns;i++,acts++) { + if (acts->type!=XkbSA_NoAction) + XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0); + } + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= SetDeviceIndicators(wire,dev,change,stuff->nDeviceLedFBs, + &status,client,&ed); + if (status!=Success) + return status; + } + if ((stuff->change)&&(ed.reason)) + XkbSendExtensionDeviceNotify(dev,client,&ed); + return client->noClientException; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +ProcXkbSetDebuggingFlags(ClientPtr client) +#else +ProcXkbSetDebuggingFlags(client) + ClientPtr client; +#endif +{ +CARD32 newFlags,newCtrls,extraLength; +xkbSetDebuggingFlagsReply rep; + + REQUEST(xkbSetDebuggingFlagsReq); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + + newFlags= xkbDebugFlags&(~stuff->affectFlags); + newFlags|= (stuff->flags&stuff->affectFlags); + newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); + newCtrls|= (stuff->ctrls&stuff->affectCtrls); + if (xkbDebugFlags || newFlags || stuff->msgLength) { + ErrorF("XkbDebug: Setting debug flags to 0x%x\n",newFlags); + if (newCtrls!=xkbDebugCtrls) + ErrorF("XkbDebug: Setting debug controls to 0x%x\n",newCtrls); + } + extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; + if (stuff->msgLength>0) { + char *msg; + if (extraLength<XkbPaddedSize(stuff->msgLength)) { + ErrorF("XkbDebug: msgLength= %d, length= %d (should be %d)\n", + stuff->msgLength,extraLength, + XkbPaddedSize(stuff->msgLength)); + return BadLength; + } + msg= (char *)&stuff[1]; + if (msg[stuff->msgLength-1]!='\0') { + ErrorF("XkbDebug: message not null-terminated\n"); + return BadValue; + } + ErrorF("XkbDebug: %s\n",msg); + } + xkbDebugFlags = newFlags; + xkbDebugCtrls = newCtrls; + + XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks); + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.currentFlags = newFlags; + rep.currentCtrls = newCtrls; + rep.supportedFlags = ~0; + rep.supportedCtrls = ~0; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.currentFlags, n); + swapl(&rep.currentCtrls, n); + swapl(&rep.supportedFlags, n); + swapl(&rep.supportedCtrls, n); + } + WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep); + return client->noClientException; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ProcXkbDispatch (ClientPtr client) +#else +ProcXkbDispatch (client) + ClientPtr client; +#endif +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return ProcXkbUseExtension(client); + case X_kbSelectEvents: + return ProcXkbSelectEvents(client); + case X_kbBell: + return ProcXkbBell(client); + case X_kbGetState: + return ProcXkbGetState(client); + case X_kbLatchLockState: + return ProcXkbLatchLockState(client); + case X_kbGetControls: + return ProcXkbGetControls(client); + case X_kbSetControls: + return ProcXkbSetControls(client); + case X_kbGetMap: + return ProcXkbGetMap(client); + case X_kbSetMap: + return ProcXkbSetMap(client); + case X_kbGetCompatMap: + return ProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return ProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return ProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return ProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return ProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return ProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return ProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return ProcXkbGetNames(client); + case X_kbSetNames: + return ProcXkbSetNames(client); + case X_kbGetGeometry: + return ProcXkbGetGeometry(client); + case X_kbSetGeometry: + return ProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return ProcXkbPerClientFlags(client); + case X_kbListComponents: + return ProcXkbListComponents(client); + case X_kbGetKbdByName: + return ProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return ProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return ProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return ProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} + +static int +#if NeedFunctionPrototypes +XkbClientGone(pointer data,XID id) +#else +XkbClientGone(data,id) + pointer data; + XID id; +#endif +{ + DevicePtr pXDev = (DevicePtr)data; + + if (!XkbRemoveResourceClient(pXDev,id)) { + ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + } + return 1; +} + +/*ARGSUSED*/ +static void +#if NeedFunctionPrototypes +XkbResetProc(ExtensionEntry *extEntry) +#else +XkbResetProc(extEntry) + ExtensionEntry *extEntry; +#endif +{ +} + +void +#if NeedFunctionPrototypes +XkbExtensionInit(void) +#else +XkbExtensionInit() +#endif +{ + ExtensionEntry *extEntry; + + if (extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, + ProcXkbDispatch, SProcXkbDispatch, + XkbResetProc, StandardMinorOpcode)) { + XkbReqCode = (unsigned char)extEntry->base; + XkbEventBase = (unsigned char)extEntry->eventBase; + XkbErrorBase = (unsigned char)extEntry->errorBase; + XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; + RT_XKBCLIENT = CreateNewResourceType(XkbClientGone); + } + return; +} + + diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c new file mode 100644 index 000000000..7596d068b --- /dev/null +++ b/xkb/xkbAccessX.c @@ -0,0 +1,856 @@ +/* $Xorg: xkbAccessX.c,v 1.4 2001/02/05 18:50:20 coskrey Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "inputstr.h" +#include "XKBsrv.h" +#ifndef WIN32 +#include <sys/time.h> +#endif + +int XkbDfltRepeatDelay= 660; +int XkbDfltRepeatInterval= 40; +pointer XkbLastRepeatEvent= NULL; + +#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) +#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) + +unsigned short XkbDfltAccessXTimeout= 120; +unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; +unsigned int XkbDfltAccessXTimeoutValues= 0; +unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; +unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; +unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; +unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); + +void +#if NeedFunctionPrototypes +AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) +#else +AccessXComputeCurveFactor(xkbi,ctrls) + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrls; +#endif +{ + xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); + xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ + pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); + return; +} + +void +#if NeedFunctionPrototypes +AccessXInit(DeviceIntPtr keybd) +#else +AccessXInit(keybd) + DeviceIntPtr keybd; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; + + xkbi->shiftKeyCount= 0; + xkbi->mouseKeysCounter= 0; + xkbi->inactiveKey= 0; + xkbi->slowKey= 0; + xkbi->repeatKey= 0; + xkbi->krgTimerActive= _OFF_TIMER; + xkbi->beepType= _BEEP_NONE; + xkbi->beepCount= 0; + xkbi->mouseKeyTimer= NULL; + xkbi->slowKeysTimer= NULL; + xkbi->bounceKeysTimer= NULL; + xkbi->repeatKeyTimer= NULL; + xkbi->krgTimer= NULL; + xkbi->beepTimer= NULL; + ctrls->repeat_delay = XkbDfltRepeatDelay; + ctrls->repeat_interval = XkbDfltRepeatInterval; + ctrls->debounce_delay = 300; + ctrls->slow_keys_delay = 300; + ctrls->mk_delay = 160; + ctrls->mk_interval = 40; + ctrls->mk_time_to_max = 30; + ctrls->mk_max_speed = 30; + ctrls->mk_curve = 500; + ctrls->mk_dflt_btn = 1; + ctrls->ax_timeout = XkbDfltAccessXTimeout; + ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; + ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; + ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; + ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; + if (XkbDfltAccessXTimeout) + ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; + else + ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; + ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; + ctrls->ax_options = XkbDfltAccessXOptions; + AccessXComputeCurveFactor(xkbi,ctrls); + return; +} + +/************************************************************************/ +/* */ +/* AccessXKeyboardEvent */ +/* */ +/* Generate a synthetic keyboard event. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKeyboardEvent(DeviceIntPtr keybd, + BYTE type, + BYTE keyCode, + Bool isRepeat) +#else +AccessXKeyboardEvent(keybd,type,keyCode,isRepeat) + DeviceIntPtr keybd; + BYTE type; + BYTE keyCode; + Bool isRepeat; +#endif +{ +xEvent xE; +#ifdef XINPUT +extern int DeviceKeyPress; +#endif + + xE.u.u.type = type; + xE.u.u.detail = keyCode; + xE.u.keyButtonPointer.time = GetTimeInMillis(); +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + ErrorF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up")); + } +#endif + + if (_XkbIsPressEvent(type)) + XkbDDXKeyClick(keybd,keyCode,TRUE); + else if (isRepeat) + XkbLastRepeatEvent= (pointer)&xE; + XkbProcessKeyboardEvent(&xE,keybd,1L); + XkbLastRepeatEvent= NULL; + return; + +} /* AccessXKeyboardEvent */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOn */ +/* */ +/* Turn the keyboard response group on. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) +#else +AccessXKRGTurnOn(dev,KRGControl,pCN) + DeviceIntPtr dev; + CARD16 KRGControl; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old= *ctrls; + ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); + return; + +} /* AccessXKRGTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOff */ +/* */ +/* Turn the keyboard response group off. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXKRGTurnOff(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbAX_KRGMask; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); + } + return; + +} /* AccessXKRGTurnOff */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOn */ +/* */ +/* Turn StickyKeys on. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXStickyKeysTurnOn(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls |= XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); + } + return; + +} /* AccessXStickyKeysTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOff */ +/* */ +/* Turn StickyKeys off. */ +/* */ +/************************************************************************/ +static void +#if NeedFunctionPrototypes +AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +#else +AccessXStickyKeysTurnOff(dev,pCN) + DeviceIntPtr dev; + xkbControlsNotify *pCN; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,False)) + XkbSendControlsNotify(dev,pCN); + + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); + } +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + XkbClearAllLatchesAndLocks(dev,xkbi,False,&cause); +#endif + return; +} /* AccessXStickyKeysTurnOff */ + +static CARD32 +#if NeedFunctionPrototypes +AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXKRGExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +xkbControlsNotify cn; + + if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { + XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); + xkbi->krgTimerActive= _KRG_TIMER; + return 4000; + } + xkbi->krgTimerActive= _OFF_TIMER; + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) + AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); + else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXRepeatKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +KeyCode key; + + if (xkbi->repeatKey==0) + return 0; + key= xkbi->repeatKey; + AccessXKeyboardEvent((DeviceIntPtr)arg,KeyRelease,key,True); + AccessXKeyboardEvent((DeviceIntPtr)arg,KeyPress,key,True); + return xkbi->desc->ctrls->repeat_interval; +} + +void +#if NeedFunctionPrototypes +AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) +#else +AccessXCancelRepeatKey(xkbi,key) + XkbSrvInfoPtr xkbi; + KeyCode key; +#endif +{ + if (xkbi->repeatKey==key) + xkbi->repeatKey= 0; + return; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXSlowKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr keybd; +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + keybd= (DeviceIntPtr)arg; + xkbi= keybd->key->xkbInfo; + xkb= xkbi->desc; + ctrls= xkb->ctrls; + if (xkbi->slowKey!=0) { + xkbAccessXNotify ev; + KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); + ev.detail= XkbAXN_SKAccept; + ev.keycode= xkbi->slowKey; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); + AccessXKeyboardEvent(keybd,KeyPress,xkbi->slowKey,False); + /* check for magic sequences */ + if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && + ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) + xkbi->shiftKeyCount++; + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (keybd->kbdfeed->ctrl.autoRepeat && + ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && + (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { +#ifndef AIXV3 + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) +#endif + { + xkbi->repeatKey = xkbi->slowKey; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXBounceKeyExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; + + xkbi->inactiveKey= 0; + return 0; +} + +static CARD32 +#if NeedFunctionPrototypes +AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +AccessXTimeoutExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)arg; +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +XkbControlsRec old; +xkbControlsNotify cn; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + if (xkbi->lastPtrEventTime) { + unsigned timeToWait = (ctrls->ax_timeout*1000); + unsigned timeElapsed = (now-xkbi->lastPtrEventTime); + + if (timeToWait > timeElapsed) + return (timeToWait - timeElapsed); + } + old= *ctrls; + xkbi->shiftKeyCount= 0; + ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; + ctrls->enabled_ctrls|= + (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); + if (ctrls->axt_opts_mask) { + ctrls->ax_options&= ~ctrls->axt_opts_mask; + ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); + } + if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,False)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(dev,&cn); + } + XkbSetCauseUnknown(&cause); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); + if (ctrls->ax_options!=old.ax_options) { + unsigned set,cleared,bell; + set= ctrls->ax_options&(~old.ax_options); + cleared= (~ctrls->ax_options)&old.ax_options; + if (set && cleared) bell= _BEEP_FEATURE_CHANGE; + else if (set) bell= _BEEP_FEATURE_ON; + else bell= _BEEP_FEATURE_OFF; + XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); + } + xkbi->krgTimerActive= _OFF_TIMER; + return 0; +} + + +/************************************************************************/ +/* */ +/* AccessXFilterPressEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +#if NeedFunctionPrototypes +AccessXFilterPressEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +#else +AccessXFilterPressEvent(xE,keybd,count) + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +Bool ignoreKeyEvent = FALSE; +KeyCode key = xE->u.u.detail; +KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); + + if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { + /* check for magic sequences */ + if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { + xkbi->krgTimerActive = _KRG_WARN_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, + AccessXKRGExpire, (pointer)keybd); + } + else { + xkbi->krgTimerActive = _KRG_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, + AccessXKRGExpire, (pointer)keybd); + } + if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { + CARD32 now= GetTimeInMillis(); + if ((now-xkbi->lastShiftEventTime)>15000) + xkbi->shiftKeyCount= 1; + else xkbi->shiftKeyCount++; + xkbi->lastShiftEventTime= now; + } + } + else { + if (xkbi->krgTimerActive) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + } + } + + /* Don't transmit the KeyPress if SlowKeys is turned on; + * The wakeup handler will synthesize one for us if the user + * has held the key long enough. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + /* If key was already pressed, ignore subsequent press events + * from the server's autorepeat + */ + if(xkbi->slowKey == key) + return TRUE; + + ev.detail= XkbAXN_SKPress; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); + xkbi->slowKey= key; + xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, + 0, ctrls->slow_keys_delay, + AccessXSlowKeyExpire, (pointer)keybd); + ignoreKeyEvent = TRUE; + } + + /* Don't transmit the KeyPress if BounceKeys is turned on + * and the user pressed the same key within a given time period + * from the last release. + */ + else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && + (key == xkbi->inactiveKey)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); + ignoreKeyEvent = TRUE; + } + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (XkbDDXUsesSoftRepeat(keybd)) { + if ((keybd->kbdfeed->ctrl.autoRepeat) && + ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== + XkbRepeatKeysMask)) { +#ifndef AIXV3 + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) +#endif + { +#ifdef DEBUG + if (xkbDebugFlags&0x10) + ErrorF("Starting software autorepeat...\n"); +#endif + xkbi->repeatKey = key; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + + /* Check for two keys being pressed at the same time. This section + * essentially says the following: + * + * If StickyKeys is on, and a modifier is currently being held down, + * and one of the following is true: the current key is not a modifier + * or the currentKey is a modifier, but not the only modifier being + * held down, turn StickyKeys off if the TwoKeys off ctrl is set. + */ + if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && + (xkbi->state.base_mods!=0) && + (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + AccessXStickyKeysTurnOff(keybd,&cn); + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; +} /* AccessXFilterPressEvent */ + +/************************************************************************/ +/* */ +/* AccessXFilterReleaseEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +#if NeedFunctionPrototypes +AccessXFilterReleaseEvent( register xEvent * xE, + register DeviceIntPtr keybd, + int count) +#else +AccessXFilterReleaseEvent(xE,keybd,count) + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +#endif +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +KeyCode key = xE->u.u.detail; +Bool ignoreKeyEvent = FALSE; + + /* Don't transmit the KeyRelease if BounceKeys is on and + * this is the release of a key that was ignored due to + * BounceKeys. + */ + if (ctrls->enabled_ctrls & XkbBounceKeysMask) { + if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) + ignoreKeyEvent = TRUE; + xkbi->inactiveKey= key; + xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, + ctrls->debounce_delay, + AccessXBounceKeyExpire, (pointer)keybd); + } + + /* Don't transmit the KeyRelease if SlowKeys is turned on and + * the user didn't hold the key long enough. We know we passed + * the key if the down bit was set by CoreProcessKeyboadEvent. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + unsigned beep_type; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + if (BitIsOn(keybd->key->down,key) | (xkbi->mouseKey == key)) { + ev.detail= XkbAXN_SKRelease; + beep_type= _BEEP_SLOW_RELEASE; + } + else { + ev.detail= XkbAXN_SKReject; + beep_type= _BEEP_SLOW_REJECT; + ignoreKeyEvent = TRUE; + } + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { + XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); + } + if (xkbi->slowKey==key) + xkbi->slowKey= 0; + } + + /* Stop Repeating if the user releases the key that is currently + * repeating. + */ + if (xkbi->repeatKey==key) { + xkbi->repeatKey= 0; + } + + if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { + xkbi->lastPtrEventTime= 0; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, + ctrls->ax_timeout*1000, + AccessXTimeoutExpire, (pointer)keybd); + xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; + } + else if (xkbi->krgTimerActive!=_OFF_TIMER) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + + /* Keep track of how many times the Shift key has been pressed. + * If it has been pressed and released 5 times in a row, toggle + * the state of StickyKeys. + */ + if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { + KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); + if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { + xkbi->shiftKeyCount= 0; + } + else if (xkbi->shiftKeyCount>=5) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (ctrls->enabled_ctrls & XkbStickyKeysMask) + AccessXStickyKeysTurnOff(keybd,&cn); + else + AccessXStickyKeysTurnOn(keybd,&cn); + xkbi->shiftKeyCount= 0; + } + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(xE,keybd,count); + return ignoreKeyEvent; + +} /* AccessXFilterReleaseEvent */ + +/************************************************************************/ +/* */ +/* ProcessPointerEvent */ +/* */ +/* This routine merely sets the shiftKeyCount and clears the keyboard */ +/* response group timer (if necessary) on a mouse event. This is so */ +/* multiple shifts with just the mouse and shift-drags with the mouse */ +/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ +/* */ +/************************************************************************/ +void +#if NeedFunctionPrototypes +ProcessPointerEvent( register xEvent * xE, + register DeviceIntPtr mouse, + int count) +#else +ProcessPointerEvent(xE,mouse,count) + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice(); +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +unsigned changed = 0; + + xkbi->shiftKeyCount = 0; + xkbi->lastPtrEventTime= xE->u.keyButtonPointer.time; + + if (xE->u.u.type==ButtonPress) { + changed |= XkbPointerButtonMask; + } + else if (xE->u.u.type==ButtonRelease) { + xkbi->lockedPtrButtons&= ~(1<<(xE->u.u.detail&0x7)); + changed |= XkbPointerButtonMask; + } + CoreProcessPointerEvent(xE,mouse,count); + + xkbi->state.ptr_buttons = mouse->button->state; + + /* clear any latched modifiers */ + if ( xkbi->state.latched_mods && (xE->u.u.type==ButtonRelease) ) { + unsigned changed_leds; + XkbStateRec oldState; + XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + oldState= xkbi->state; + XkbLatchModifiers(dev,0xFF,0x00); + + XkbComputeDerivedState(xkbi); + changed |= XkbStateChangedFlags(&oldState,&xkbi->state); + if (changed&sli->usedComponents) { + changed_leds= XkbIndicatorsToUpdate(dev,changed,False); + if (changed_leds) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,(xE->u.u.detail&0x7),xE->u.u.type); + XkbUpdateIndicators(dev,changed_leds,True,NULL,&cause); + } + } + dev->key->state= XkbStateFieldFromRec(&xkbi->state); + } + + if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { + xkbStateNotify sn; + sn.keycode= xE->u.u.detail; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + +} /* ProcessPointerEvent */ + + + + diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c new file mode 100644 index 000000000..fd8910841 --- /dev/null +++ b/xkb/xkbActions.c @@ -0,0 +1,1462 @@ +/* $Xorg: xkbActions.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include <ctype.h> + +#ifdef XINPUT +extern void ProcessOtherEvent( +#if NeedFunctionPrototypes + xEvent * /* xE */, + DeviceIntPtr /* dev */, + int /* count */ +#endif +); +#endif + +/***====================================================================***/ + +static XkbAction +#if NeedFunctionPrototypes +_FixUpAction(XkbDescPtr xkb,XkbAction *act) +#else +_FixUpAction(xkb,act) + XkbDescPtr xkb; + XkbAction * act; +#endif +{ +static XkbAction fake; + + if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { + fake.type = XkbSA_NoAction; + return fake; + } + if (XkbDisableLockActions) { + switch (act->type) { + case XkbSA_LockMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_LatchMods: + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->mods.mask; + return fake; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_ISODfltIsGroup) { + fake.group.type = XkbSA_SetGroup; + fake.group.flags = act->iso.flags&XkbSA_GroupAbsolute; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->iso)); + } + else { + fake.mods.type = XkbSA_SetMods; + fake.mods.flags = 0; + fake.mods.mask = act->iso.mask; + } + return fake; + case XkbSA_LockGroup: + case XkbSA_LatchGroup: + /* We want everything from the latch/lock action except the + * type should be changed to set. + */ + fake = *act; + fake.group.type = XkbSA_SetGroup; + return fake; + } + } + else + if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { + if (act->any.type==XkbSA_SetMods) { + fake.mods.type = XkbSA_LatchMods; + fake.mods.mask = act->mods.mask; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.mods.flags= XkbSA_ClearLocks; + return fake; + } + if (act->any.type==XkbSA_SetGroup) { + fake.group.type = XkbSA_LatchGroup; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.group.flags= XkbSA_ClearLocks; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); + return fake; + } + } + return *act; +} + +static XkbAction +#if NeedFunctionPrototypes +XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) +#else +XkbGetKeyAction(xkbi,xkbState,key) + XkbSrvInfoPtr xkbi; + XkbStatePtr xkbState; + CARD8 key; +#endif +{ +int effectiveGroup; +int col; +XkbDescPtr xkb; +XkbKeyTypePtr type; +XkbAction * pActs; +static XkbAction fake; + + xkb= xkbi->desc; + if (!XkbKeyHasActions(xkb,key)) { + fake.type = XkbSA_NoAction; + return fake; + } + pActs= XkbKeyActionsPtr(xkb,key); + col= 0; + effectiveGroup= xkbState->group; + if (effectiveGroup!=XkbGroup1Index) { + if (XkbKeyNumGroups(xkb,key)>(unsigned)1) { + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) { + unsigned gi= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(gi)) { + default: + case XkbWrapIntoRange: + effectiveGroup %= XkbKeyNumGroups(xkb,key); + break; + case XkbClampIntoRange: + effectiveGroup = XkbKeyNumGroups(xkb,key)-1; + break; + case XkbRedirectIntoRange: + effectiveGroup= XkbOutOfRangeGroupInfo(gi); + if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) + effectiveGroup= 0; + break; + } + } + } + else effectiveGroup= XkbGroup1Index; + col+= (effectiveGroup*XkbKeyGroupsWidth(xkb,key)); + } + type= XkbKeyKeyType(xkb,key,effectiveGroup); + if (type->map!=NULL) { + register unsigned i,mods; + register XkbKTMapEntryPtr entry; + mods= xkbState->mods&type->mods.mask; + for (entry= type->map,i=0;i<type->map_count;i++,entry++) { + if ((entry->active)&&(entry->mods.mask==mods)) { + col+= entry->level; + break; + } + } + } + if (pActs[col].any.type==XkbSA_NoAction) + return pActs[col]; + fake= _FixUpAction(xkb,&pActs[col]); + return fake; +} + +XkbAction +#if NeedFunctionPrototypes +XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) +#else +XkbGetButtonAction(kbd,dev,button) + DeviceIntPtr kbd; + DeviceIntPtr dev; + int button; +#endif +{ +XkbAction fake; + if ((dev->button)&&(dev->button->xkb_acts)) { + if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { + fake= _FixUpAction(kbd->key->xkbInfo->desc, + &dev->button->xkb_acts[button-1]); + return fake; + } + } + fake.any.type= XkbSA_NoAction; + return fake; +} + +/***====================================================================***/ + +#define SYNTHETIC_KEYCODE 1 +#define BTN_ACT_FLAG 0x100 + +typedef struct _XkbFilter { + CARD16 keycode; + CARD8 what; + CARD8 active; + CARD8 filterOthers; + CARD32 priv; + XkbAction upAction; + int (*filter)( +#if NeedFunctionPrototypes + XkbSrvInfoPtr /* xkbi */, + struct _XkbFilter * /* filter */, + unsigned /* keycode */, + XkbAction * /* action */ +#endif + ); + struct _XkbFilter *next; +} XkbFilterRec,*XkbFilterPtr; + +static int +#if NeedFunctionPrototypes +_XkbFilterSetState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction *pAction) +#else +_XkbFilterSetState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); + filter->priv = 0; + filter->filter = _XkbFilterSetState; + if (pAction->type==XkbSA_SetMods) { + filter->upAction = *pAction; + xkbi->setMods= pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if (filter->keycode==keycode) { + if (filter->upAction.type==XkbSA_SetMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if (filter->upAction.mods.flags&XkbSA_ClearLocks) { + xkbi->state.locked_mods&= ~filter->upAction.mods.mask; + } + } + else { + if (filter->upAction.group.flags&XkbSA_ClearLocks) { + xkbi->state.locked_group = 0; + } + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + } + filter->active = 0; + } + else { + filter->upAction.mods.flags&= ~XkbSA_ClearLocks; + filter->filterOthers = 0; + } + return 1; +} + +#define LATCH_KEY_DOWN 1 +#define LATCH_PENDING 2 +#define NO_LATCH 3 + +static int +#if NeedFunctionPrototypes +_XkbFilterLatchState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterLatchState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = LATCH_KEY_DOWN; + filter->filter = _XkbFilterLatchState; + if (pAction->type==XkbSA_LatchMods) { + filter->upAction = *pAction; + xkbi->setMods = pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if ( pAction && (filter->priv==LATCH_PENDING) ) { + if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) { + filter->active = 0; + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + } + else if ((pAction->type==filter->upAction.type)&& + (pAction->mods.flags==filter->upAction.mods.flags)&& + (pAction->mods.mask==filter->upAction.mods.mask)) { + if (filter->upAction.mods.flags&XkbSA_LatchToLock) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_LockMods; + else pAction->group.type= XkbSA_LockGroup; + if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& + (ctrls->enabled_ctrls&XkbStickyKeysMask)) { + XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + } + else { + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_SetMods; + else pAction->group.type= XkbSA_SetGroup; + } + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + filter->active = 0; + } + } + else if (filter->keycode==keycode) { /* release */ + XkbControlsPtr ctrls= xkbi->desc->ctrls; + int needBeep; + int beepType= _BEEP_NONE; + + needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& + XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& + (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { + xkbi->state.locked_mods&= ~xkbi->clearMods; + filter->priv= NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + else { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& + (xkbi->state.locked_group)) { + xkbi->state.locked_group = 0; + filter->priv = NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + if (filter->priv==NO_LATCH) { + filter->active= 0; + } + else { + filter->priv= LATCH_PENDING; + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->state.latched_mods |= filter->upAction.mods.mask; + needBeep = xkbi->state.latched_mods ? needBeep : 0; + xkbi->state.latched_mods |= filter->upAction.mods.mask; + } + else { + xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); + } + if (needBeep && (beepType==_BEEP_NONE)) + beepType= _BEEP_STICKY_LATCH; + } + if (needBeep && (beepType!=_BEEP_NONE)) + XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); + } + else if (filter->priv==LATCH_KEY_DOWN) { + filter->priv= NO_LATCH; + filter->filterOthers = 0; + } + return 1; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterLockState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterLockState(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (pAction&&(pAction->type==XkbSA_LockGroup)) { + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&pAction->group); + else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); + return 1; + } + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterLockState; + filter->upAction = *pAction; + xkbi->state.locked_mods^= pAction->mods.mask; + xkbi->setMods = pAction->mods.mask; + } + else if (filter->keycode==keycode) { + filter->active = 0; + xkbi->clearMods = filter->upAction.mods.mask; + } + return 1; +} + +#define ISO_KEY_DOWN 0 +#define NO_ISO_LOCK 1 + +static int +#if NeedFunctionPrototypes +_XkbFilterISOLock( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterISOLock(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + + if (filter->keycode==0) { /* initial press */ + CARD8 flags= pAction->iso.flags; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = ISO_KEY_DOWN; + filter->upAction = *pAction; + filter->filter = _XkbFilterISOLock; + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = XkbSAGroup(&pAction->iso); + xkbi->setMods = 0; + } + else { + xkbi->setMods = pAction->iso.mask; + xkbi->groupChange = 0; + } + if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { + filter->priv= NO_ISO_LOCK; + xkbi->state.locked_mods^= xkbi->state.base_mods; + } + if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { +/* 6/22/93 (ef) -- lock groups if group key is down first */ + } + if (!(flags&XkbSA_ISONoAffectPtr)) { +/* 6/22/93 (ef) -- lock mouse buttons if they're down */ + } + } + else if (filter->keycode==keycode) { + CARD8 flags= filter->upAction.iso.flags; + + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); + xkbi->clearMods = 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); + } + else { + xkbi->clearMods= filter->upAction.iso.mask; + xkbi->groupChange= 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_mods^= filter->upAction.iso.mask; + } + filter->active = 0; + } + else if (pAction) { + CARD8 flags= filter->upAction.iso.flags; + + switch (pAction->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: + if (!(flags&XkbSA_ISONoAffectMods)) { + pAction->type= XkbSA_LockMods; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetGroup: case XkbSA_LatchGroup: + if (!(flags&XkbSA_ISONoAffectGroup)) { + pAction->type= XkbSA_LockGroup; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_PtrBtn: + if (!(flags&XkbSA_ISONoAffectPtr)) { + pAction->type= XkbSA_LockPtrBtn; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetControls: + if (!(flags&XkbSA_ISONoAffectCtrls)) { + pAction->type= XkbSA_LockControls; + filter->priv= NO_ISO_LOCK; + } + break; + } + } + return 1; +} + + +static CARD32 +#if NeedFunctionPrototypes +_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) +#else +_XkbPtrAccelExpire(timer,now,arg) + OsTimerPtr timer; + CARD32 now; + pointer arg; +#endif +{ +XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +int dx,dy; + + if (xkbi->mouseKey==0) + return 0; + + if (xkbi->mouseKeysAccel) { + if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) { + double step; + xkbi->mouseKeysCounter++; + step= xkbi->mouseKeysCurveFactor* + pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); + if (xkbi->mouseKeysDX<0) + dx= floor( ((double)xkbi->mouseKeysDX)*step ); + else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); + if (xkbi->mouseKeysDY<0) + dy= floor( ((double)xkbi->mouseKeysDY)*step ); + else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); + } + else { + dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; + dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; + } + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) + dx= xkbi->mouseKeysDX; + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) + dy= xkbi->mouseKeysDY; + } + else { + dx= xkbi->mouseKeysDX; + dy= xkbi->mouseKeysDY; + } + XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy); + return xkbi->desc->ctrls->mk_interval; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterPointerMove(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +int x,y; +Bool accel; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerMove; + filter->upAction= *pAction; + xkbi->mouseKeysCounter= 0; + xkbi->mouseKey= keycode; + accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); + x= XkbPtrActionX(&pAction->ptr); + y= XkbPtrActionY(&pAction->ptr); + XkbDDXFakePointerMotion(pAction->ptr.flags,x,y); + AccessXCancelRepeatKey(xkbi,keycode); + xkbi->mouseKeysAccel= accel&& + (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); + if (xkbi->mouseKeysAccel) { + xkbi->mouseKeysFlags= pAction->ptr.flags; + xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); + xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, + xkbi->desc->ctrls->mk_delay, + _XkbPtrAccelExpire,(pointer)xkbi); + } + } + else if (filter->keycode==keycode) { + filter->active = 0; + if (xkbi->mouseKey==keycode) { + xkbi->mouseKey= 0; + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, + NULL, NULL); + } + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterPointerBtn(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ + if (filter->keycode==0) { /* initial press */ + int button= pAction->btn.button; + + if (button==XkbSA_UseDfltButton) + button = xkbi->desc->ctrls->mk_dflt_btn; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerBtn; + filter->upAction= *pAction; + filter->upAction.btn.button= button; + switch (pAction->type) { + case XkbSA_LockPtrBtn: + if (((xkbi->lockedPtrButtons&(1<<button))==0)&& + ((pAction->btn.flags&XkbSA_LockNoLock)==0)) { + xkbi->lockedPtrButtons|= (1<<button); + AccessXCancelRepeatKey(xkbi,keycode); + XkbDDXFakePointerButton(ButtonPress,button); + filter->upAction.type= XkbSA_NoAction; + } + break; + case XkbSA_PtrBtn: + { + register int i,nClicks; + AccessXCancelRepeatKey(xkbi,keycode); + if (pAction->btn.count>0) { + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbDDXFakePointerButton(ButtonPress,button); + XkbDDXFakePointerButton(ButtonRelease,button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbDDXFakePointerButton(ButtonPress,button); + } + break; + case XkbSA_SetPtrDflt: + { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + XkbControlsRec old; + xkbControlsNotify cn; + + old= *ctrls; + AccessXCancelRepeatKey(xkbi,keycode); + switch (pAction->dflt.affect) { + case XkbSA_AffectDfltBtn: + if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) + ctrls->mk_dflt_btn= + XkbSAPtrDfltValue(&pAction->dflt); + else { + ctrls->mk_dflt_btn+= + XkbSAPtrDfltValue(&pAction->dflt); + if (ctrls->mk_dflt_btn>5) + ctrls->mk_dflt_btn= 5; + else if (ctrls->mk_dflt_btn<1) + ctrls->mk_dflt_btn= 1; + } + break; + default: + ErrorF( + "Attempt to change unknown pointer default (%d) ignored\n", + pAction->dflt.affect); + break; + } + if (XkbComputeControlsNotify(xkbi->device, + &old,xkbi->desc->ctrls, + &cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(xkbi->device,&cn); + } + } + break; + } + } + else if (filter->keycode==keycode) { + int button= filter->upAction.btn.button; + + switch (filter->upAction.type) { + case XkbSA_LockPtrBtn: + if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| + ((xkbi->lockedPtrButtons&(1<<button))==0)) { + break; + } + xkbi->lockedPtrButtons&= ~(1<<button); + case XkbSA_PtrBtn: + XkbDDXFakePointerButton(ButtonRelease,button); + break; + } + filter->active = 0; + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterControls( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterControls(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +XkbControlsRec old; +XkbControlsPtr ctrls; +DeviceIntPtr kbd; +unsigned int change; +XkbEventCauseRec cause; + + kbd= xkbi->device; + ctrls= xkbi->desc->ctrls; + old= *ctrls; + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + change= XkbActionCtrls(&pAction->ctrls); + filter->priv = change; + filter->filter = _XkbFilterControls; + filter->upAction = *pAction; + + if (pAction->type==XkbSA_LockControls) { + filter->priv= (ctrls->enabled_ctrls&change); + change&= ~ctrls->enabled_ctrls; + } + + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls|= change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyPress); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); + } + } + else if (filter->keycode==keycode) { + change= filter->priv; + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls&= ~change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) { + cn.keycode = keycode; + cn.eventType = KeyRelease; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyRelease); + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); + } + filter->keycode= 0; + filter->active= 0; + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterActionMessage(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +XkbMessageAction * pMsg; +DeviceIntPtr kbd; + + kbd= xkbi->device; + if (filter->keycode==0) { /* initial press */ + pMsg= &pAction->msg; + if ((pMsg->flags&XkbSA_MessageOnRelease)|| + ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterActionMessage; + filter->upAction = *pAction; + } + if (pMsg->flags&XkbSA_MessageOnPress) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 1; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message, + (char *)pMsg->message,XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); + } + else if (filter->keycode==keycode) { + pMsg= &filter->upAction.msg; + if (pMsg->flags&XkbSA_MessageOnRelease) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 0; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message,(char *)pMsg->message, + XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + filter->keycode= 0; + filter->active= 0; + return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + } + return 0; +} + +static int +#if NeedFunctionPrototypes +_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterRedirectKey(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +unsigned realMods; +xEvent ev; +int x,y,kc; +XkbStateRec old; +unsigned mods,mask,oldCoreState,oldCorePrevState; + + if ((filter->keycode!=0)&&(filter->keycode!=keycode)) + return 0; + + GetSpritePosition(&x,&y); + ev.u.keyButtonPointer.time = GetTimeInMillis(); + ev.u.keyButtonPointer.rootX = x; + ev.u.keyButtonPointer.rootY = y; + + mask= XkbSARedirectVModsMask(&pAction->redirect); + mods= XkbSARedirectVMods(&pAction->redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= pAction->redirect.mods_mask; + mods|= pAction->redirect.mods; + + if (filter->keycode==0) { /* initial press */ + if ((pAction->redirect.new_key<xkbi->desc->min_key_code)|| + (pAction->redirect.new_key>xkbi->desc->max_key_code)) { + return 1; + } + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterRedirectKey; + filter->upAction = *pAction; + + ev.u.u.type = KeyPress; + ev.u.u.detail = pAction->redirect.new_key; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + CoreProcessKeyboardEvent(&ev,xkbi->device,1); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + + return 0; + } + else if (filter->keycode==keycode) { + + ev.u.u.type = KeyRelease; + ev.u.u.detail = filter->upAction.redirect.new_key; + + if ( mask || mods ) { + old= xkbi->state; + oldCoreState= xkbi->device->key->state; + oldCorePrevState= xkbi->device->key->prev_state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + xkbi->device->key->state= xkbi->device->key->prev_state= + xkbi->state.mods; + } + + realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; + xkbi->device->key->modifierMap[ev.u.u.detail] = 0; + CoreProcessKeyboardEvent(&ev,xkbi->device,1); + xkbi->device->key->modifierMap[ev.u.u.detail] = realMods; + + if ( mask || mods ) { + xkbi->device->key->state= oldCoreState; + xkbi->device->key->prev_state= oldCorePrevState; + xkbi->state= old; + } + + filter->keycode= 0; + filter->active= 0; + return 0; + } + return 0; +} + +#ifdef XINPUT + +static int +#if NeedFunctionPrototypes +_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +#else +_XkbFilterDeviceBtn(xkbi,filter,keycode,pAction) + XkbSrvInfoPtr xkbi; + XkbFilterPtr filter; + unsigned keycode; + XkbAction * pAction; +#endif +{ +DeviceIntPtr dev; +int button; + + if (filter->keycode==0) { /* initial press */ + dev= _XkbLookupButtonDevice(pAction->devbtn.device,NULL); + if ((!dev)||(!dev->public.on)||(&dev->public==LookupPointerDevice())) + return 1; + + button= pAction->devbtn.button; + if ((button<1)||(button>dev->button->numButtons)) + return 1; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterDeviceBtn; + filter->upAction= *pAction; + switch (pAction->type) { + case XkbSA_LockDeviceBtn: + if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| + (dev->button->down[button/8]&(1L<<(button%8)))) + return 0; + XkbDDXFakeDeviceButton(dev,True,button); + filter->upAction.type= XkbSA_NoAction; + break; + case XkbSA_DeviceBtn: + if (pAction->devbtn.count>0) { + int nClicks,i; + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbDDXFakeDeviceButton(dev,True,button); + XkbDDXFakeDeviceButton(dev,False,button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbDDXFakeDeviceButton(dev,True,button); + break; + } + } + else if (filter->keycode==keycode) { + int button; + + filter->active= 0; + dev= _XkbLookupButtonDevice(filter->upAction.devbtn.device,NULL); + if ((!dev)||(!dev->public.on)||(&dev->public==LookupPointerDevice())) + return 1; + + button= filter->upAction.btn.button; + switch (filter->upAction.type) { + case XkbSA_LockDeviceBtn: + if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| + ((dev->button->down[button/8]&(1L<<(button%8)))==0)) + return 0; + XkbDDXFakeDeviceButton(dev,False,button); + break; + case XkbSA_DeviceBtn: + XkbDDXFakeDeviceButton(dev,False,button); + break; + } + filter->active = 0; + } + return 0; +} +#endif + +static int szFilters = 0; +static XkbFilterPtr filters = NULL; + +static XkbFilterPtr +_XkbNextFreeFilter( +#if NeedFunctionPrototypes + void +#endif +) +{ +register int i; + + if (szFilters==0) { + szFilters = 4; + filters = _XkbTypedCalloc(szFilters,XkbFilterRec); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + } + for (i=0;i<szFilters;i++) { + if (!filters[i].active) { + filters[i].keycode = 0; + return &filters[i]; + } + } + szFilters*=2; + filters= _XkbTypedRealloc(filters,szFilters,XkbFilterRec); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + bzero(&filters[szFilters/2],(szFilters/2)*sizeof(XkbFilterRec)); + return &filters[szFilters/2]; +} + +static int +#if NeedFunctionPrototypes +_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction) +#else +_XkbApplyFilters(xkbi,kc,pAction) + XkbSrvInfoPtr xkbi; + unsigned kc; + XkbAction * pAction; +#endif +{ +register int i,send; + + send= 1; + for (i=0;i<szFilters;i++) { + if ((filters[i].active)&&(filters[i].filter)) + send= ((*filters[i].filter)(xkbi,&filters[i],kc,pAction)&&send); + } + return send; +} + +void +#if NeedFunctionPrototypes +XkbHandleActions(DeviceIntPtr dev,DeviceIntPtr kbd,xEvent *xE,int count) +#else +XkbHandleActions(dev,kbd,xE,count) + DeviceIntPtr dev; + DeviceIntPtr kbd; + xEvent * xE; + int count; +#endif +{ +int key,bit,i; +CARD8 realMods; +XkbSrvInfoPtr xkbi; +KeyClassPtr keyc; +int changed,sendEvent; +Bool genStateNotify; +XkbStateRec oldState; +XkbAction act; +XkbFilterPtr filter; +Bool keyEvent; +Bool pressEvent; +#ifdef XINPUT +Bool xiEvent; +#endif + + keyc= kbd->key; + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; + if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { + oldState= xkbi->state; + xkbi->flags|= _XkbStateNotifyInProgress; + genStateNotify= True; + } + else genStateNotify= False; + + xkbi->clearMods = xkbi->setMods = 0; + xkbi->groupChange = 0; + + sendEvent = 1; +#ifdef XINPUT + keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease)); + pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)|| + (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress); + xiEvent= (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)|| + (xE->u.u.type==DeviceButtonPress)|| + (xE->u.u.type==DeviceButtonRelease); +#else + keyEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease); + pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==ButtonPress); +#endif + + if (pressEvent) { + if (keyEvent) + act = XkbGetKeyAction(xkbi,&xkbi->state,key); + else { + act = XkbGetButtonAction(kbd,dev,key); + key|= BTN_ACT_FLAG; + } + sendEvent = _XkbApplyFilters(xkbi,key,&act); + if (sendEvent) { + switch (act.type) { + case XkbSA_SetMods: + case XkbSA_SetGroup: + filter = _XkbNextFreeFilter(); + sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); + break; + case XkbSA_LatchMods: + case XkbSA_LatchGroup: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); + break; + case XkbSA_LockMods: + case XkbSA_LockGroup: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + break; + case XkbSA_ISOLock: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); + break; + case XkbSA_MovePtr: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + case XkbSA_SetPtrDflt: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); + break; + case XkbSA_Terminate: + sendEvent= XkbDDXTerminateServer(dev,key,&act); + break; + case XkbSA_SwitchScreen: + sendEvent= XkbDDXSwitchScreen(dev,key,&act); + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterControls(xkbi,filter,key,&act); + break; + case XkbSA_ActionMessage: + filter = _XkbNextFreeFilter(); + sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); + break; + case XkbSA_RedirectKey: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); + break; +#ifdef XINPUT + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + filter = _XkbNextFreeFilter(); + sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); + break; +#endif + } + } + } + else { + if (!keyEvent) + key|= BTN_ACT_FLAG; + sendEvent = _XkbApplyFilters(xkbi,key,NULL); + } + + if (xkbi->groupChange!=0) + xkbi->state.base_group+= xkbi->groupChange; + if (xkbi->setMods) { + for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { + if (xkbi->setMods&bit) { + keyc->modifierKeyCount[i]++; + xkbi->state.base_mods|= bit; + xkbi->setMods&= ~bit; + } + } + } + if (xkbi->clearMods) { + for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { + if (xkbi->clearMods&bit) { + keyc->modifierKeyCount[i]--; + if (keyc->modifierKeyCount[i]<=0) { + xkbi->state.base_mods&= ~bit; + keyc->modifierKeyCount[i] = 0; + } + xkbi->clearMods&= ~bit; + } + } + } + + if (sendEvent) { +#if XINPUT + if (xiEvent) + ProcessOtherEvent(xE,dev,count); + else +#endif + if (keyEvent) { + realMods = keyc->modifierMap[key]; + keyc->modifierMap[key] = 0; + CoreProcessKeyboardEvent(xE,dev,count); + keyc->modifierMap[key] = realMods; + } + else CoreProcessPointerEvent(xE,dev,count); + } + xkbi->prev_state= oldState; + XkbComputeDerivedState(xkbi); + keyc->prev_state= keyc->state; + keyc->state= XkbStateFieldFromRec(&xkbi->state); + changed = XkbStateChangedFlags(&oldState,&xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + sn.keycode= key; + sn.eventType= xE->u.u.type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + xkbi->flags&= ~_XkbStateNotifyInProgress; + } + changed= XkbIndicatorsToUpdate(dev,changed,False); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,key,xE->u.u.type); + XkbUpdateIndicators(dev,changed,True,NULL,&cause); + } + return; +} + +int +#if NeedFunctionPrototypes +XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) +#else +XkbLatchModifiers(pXDev,mask,latches) + DeviceIntPtr pXDev; + CARD8 mask; + CARD8 latches; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; +unsigned clear; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + clear= (mask&(~latches)); + xkbi->state.latched_mods&= ~clear; + /* Clear any pending latch to locks. + */ + act.type = XkbSA_NoAction; + _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); + act.type = XkbSA_LatchMods; + act.mods.flags = 0; + act.mods.mask = mask&latches; + filter = _XkbNextFreeFilter(); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +int +#if NeedFunctionPrototypes +XkbLatchGroup(DeviceIntPtr pXDev,int group) +#else +XkbLatchGroup(pXDev,group) + DeviceIntPtr pXDev; + int group; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + act.type = XkbSA_LatchGroup; + act.group.flags = 0; + XkbSASetGroup(&act.group,group); + filter = _XkbNextFreeFilter(); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbClearAllLatchesAndLocks( DeviceIntPtr dev, + XkbSrvInfoPtr xkbi, + Bool genEv, + XkbEventCausePtr cause) +#else +XkbClearAllLatchesAndLocks(dev,xkbi,genEv,cause) + DeviceIntPtr dev; + XkbSrvInfoPtr xkbi; + Bool genEv; + XkbEventCausePtr cause; +#endif +{ +XkbStateRec os; +xkbStateNotify sn; + + sn.changed= 0; + os= xkbi->state; + if (os.latched_mods) { /* clear all latches */ + XkbLatchModifiers(dev,~0,0); + sn.changed|= XkbModifierLatchMask; + } + if (os.latched_group) { + XkbLatchGroup(dev,0); + sn.changed|= XkbGroupLatchMask; + } + if (os.locked_mods) { + xkbi->state.locked_mods= 0; + sn.changed|= XkbModifierLockMask; + } + if (os.locked_group) { + xkbi->state.locked_group= 0; + sn.changed|= XkbGroupLockMask; + } + if ( genEv && sn.changed) { + CARD32 changed; + + XkbComputeDerivedState(xkbi); + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + sn.changed= XkbStateChangedFlags(&os,&xkbi->state); + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,sn.changed,False); + if (changed) { + XkbUpdateIndicators(dev,changed,True,NULL,cause); + } + } + return; +} + diff --git a/xkb/xkbDflts.h b/xkb/xkbDflts.h new file mode 100644 index 000000000..a79202065 --- /dev/null +++ b/xkb/xkbDflts.h @@ -0,0 +1,519 @@ +/* $Xorg: xkbDflts.h,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/* This file generated automatically by xkbcomp */ +/* DO NOT EDIT */ +#ifndef DEFAULT_H +#define DEFAULT_H 1 + +#ifndef XKB_IN_SERVER +#define GET_ATOM(d,s) XInternAtom(d,s,0) +#define DPYTYPE Display * +#else +#define GET_ATOM(d,s) MakeAtom(s,strlen(s),1) +#define DPYTYPE char * +#endif +#define NUM_KEYS 1 + +#define vmod_NumLock 0 +#define vmod_Alt 1 +#define vmod_LevelThree 2 +#define vmod_AltGr 3 +#define vmod_ScrollLock 4 + +#define vmod_NumLockMask (1<<0) +#define vmod_AltMask (1<<1) +#define vmod_LevelThreeMask (1<<2) +#define vmod_AltGrMask (1<<3) +#define vmod_ScrollLockMask (1<<4) + +/* types name is "default" */ +static Atom lnames_ONE_LEVEL[1]; + +static XkbKTMapEntryRec map_TWO_LEVEL[1]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } } +}; +static Atom lnames_TWO_LEVEL[2]; + +static XkbKTMapEntryRec map_ALPHABETIC[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 1, 0, { LockMask, LockMask, 0 } } +}; +static XkbModsRec preserve_ALPHABETIC[2]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; +static Atom lnames_ALPHABETIC[2]; + +static XkbKTMapEntryRec map_KEYPAD[2]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 1, { 0, 0, vmod_NumLockMask } } +}; +static Atom lnames_KEYPAD[2]; + +static XkbKTMapEntryRec map_PC_BREAK[1]= { + { 1, 1, { ControlMask, ControlMask, 0 } } +}; +static Atom lnames_PC_BREAK[2]; + +static XkbKTMapEntryRec map_PC_SYSRQ[1]= { + { 0, 1, { 0, 0, vmod_AltMask } } +}; +static Atom lnames_PC_SYSRQ[2]; + +static XkbKTMapEntryRec map_CTRL_ALT[1]= { + { 0, 1, { ControlMask, ControlMask, vmod_AltMask } } +}; +static Atom lnames_CTRL_ALT[2]; + +static XkbKTMapEntryRec map_THREE_LEVEL[3]= { + { 1, 1, { ShiftMask, ShiftMask, 0 } }, + { 0, 2, { 0, 0, vmod_LevelThreeMask } }, + { 0, 2, { ShiftMask, ShiftMask, vmod_LevelThreeMask } } +}; +static Atom lnames_THREE_LEVEL[3]; + +static XkbKTMapEntryRec map_SHIFT_ALT[1]= { + { 0, 1, { ShiftMask, ShiftMask, vmod_AltMask } } +}; +static Atom lnames_SHIFT_ALT[2]; + +static XkbKeyTypeRec dflt_types[]= { + { + { 0, 0, 0 }, + 1, + 0, NULL, NULL, + None, lnames_ONE_LEVEL + }, + { + { ShiftMask, ShiftMask, 0 }, + 2, + 1, map_TWO_LEVEL, NULL, + None, lnames_TWO_LEVEL + }, + { + { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, + 2, map_ALPHABETIC, preserve_ALPHABETIC, + None, lnames_ALPHABETIC + }, + { + { ShiftMask, ShiftMask, vmod_NumLockMask }, + 2, + 2, map_KEYPAD, NULL, + None, lnames_KEYPAD + }, + { + { ControlMask, ControlMask, 0 }, + 2, + 1, map_PC_BREAK, NULL, + None, lnames_PC_BREAK + }, + { + { 0, 0, vmod_AltMask }, + 2, + 1, map_PC_SYSRQ, NULL, + None, lnames_PC_SYSRQ + }, + { + { ControlMask, ControlMask, vmod_AltMask }, + 2, + 1, map_CTRL_ALT, NULL, + None, lnames_CTRL_ALT + }, + { + { ShiftMask, ShiftMask, vmod_LevelThreeMask }, + 3, + 3, map_THREE_LEVEL, NULL, + None, lnames_THREE_LEVEL + }, + { + { ShiftMask, ShiftMask, vmod_AltMask }, + 2, + 1, map_SHIFT_ALT, NULL, + None, lnames_SHIFT_ALT + } +}; +#define num_dflt_types (sizeof(dflt_types)/sizeof(XkbKeyTypeRec)) + + +static void +#if NeedFunctionPrototypes +initTypeNames(DPYTYPE dpy) +#else +initTypeNames(dpy) +DPYTYPE dpy; +#endif +{ + dflt_types[0].name= GET_ATOM(dpy,"ONE_LEVEL"); + lnames_ONE_LEVEL[0]= GET_ATOM(dpy,"Any"); + dflt_types[1].name= GET_ATOM(dpy,"TWO_LEVEL"); + lnames_TWO_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_TWO_LEVEL[1]= GET_ATOM(dpy,"Shift"); + dflt_types[2].name= GET_ATOM(dpy,"ALPHABETIC"); + lnames_ALPHABETIC[0]= GET_ATOM(dpy,"Base"); + lnames_ALPHABETIC[1]= GET_ATOM(dpy,"Caps"); + dflt_types[3].name= GET_ATOM(dpy,"KEYPAD"); + lnames_KEYPAD[0]= GET_ATOM(dpy,"Base"); + lnames_KEYPAD[1]= GET_ATOM(dpy,"Number"); + dflt_types[4].name= GET_ATOM(dpy,"PC_BREAK"); + lnames_PC_BREAK[0]= GET_ATOM(dpy,"Base"); + lnames_PC_BREAK[1]= GET_ATOM(dpy,"Control"); + dflt_types[5].name= GET_ATOM(dpy,"PC_SYSRQ"); + lnames_PC_SYSRQ[0]= GET_ATOM(dpy,"Base"); + lnames_PC_SYSRQ[1]= GET_ATOM(dpy,"Alt"); + dflt_types[6].name= GET_ATOM(dpy,"CTRL+ALT"); + lnames_CTRL_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_CTRL_ALT[1]= GET_ATOM(dpy,"Ctrl+Alt"); + dflt_types[7].name= GET_ATOM(dpy,"THREE_LEVEL"); + lnames_THREE_LEVEL[0]= GET_ATOM(dpy,"Base"); + lnames_THREE_LEVEL[1]= GET_ATOM(dpy,"Shift"); + lnames_THREE_LEVEL[2]= GET_ATOM(dpy,"Level3"); + dflt_types[8].name= GET_ATOM(dpy,"SHIFT+ALT"); + lnames_SHIFT_ALT[0]= GET_ATOM(dpy,"Base"); + lnames_SHIFT_ALT[1]= GET_ATOM(dpy,"Shift+Alt"); +} +/* compat name is "default" */ +static XkbSymInterpretRec dfltSI[69]= { + { XK_ISO_Level2_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_Exactly, ShiftMask, + 255, + { XkbSA_LatchMods, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Eisu_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Eisu_toggle, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Kana_Shift, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Kana_Lock, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_NoAction, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Shift_Lock, 0x0000, + XkbSI_AnyOf, ShiftMask|LockMask, + 255, + { XkbSA_LockMods, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Num_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 0, + { XkbSA_LockMods, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_Alt_L, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Alt_R, 0x0000, + XkbSI_AnyOf, 0xff, + 1, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Scroll_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 4, + { XkbSA_LockMods, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Lock, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_ISOLock, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Level3_Shift, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_SetMods, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } }, + { XK_ISO_Level3_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOf, 0xff, + 2, + { XkbSA_LatchMods, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } }, + { XK_Mode_switch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_SetGroup, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_End, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_Down, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_Next, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00 } }, + { XK_KP_4, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Left, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_6, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Right, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_7, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Home, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_8, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Up, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_9, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_Prior, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_MovePtr, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00 } }, + { XK_KP_5, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Begin, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F1, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Divide, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F2, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Multiply, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_F3, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Subtract, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x04, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Separator, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Add, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_0, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Insert, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Decimal, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_KP_Delete, 0x0001, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Button3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DblClick3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_PtrBtn, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag_Dflt, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag1, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag2, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_Drag3, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockPtrBtn, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_EnableKeys, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 } }, + { XK_Pointer_Accelerate, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 } }, + { XK_Pointer_DfltBtnNext, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { XK_Pointer_DfltBtnPrev, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_SetPtrDflt, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00 } }, + { XK_AccessX_Enable, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockControls, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } }, + { XK_Terminate_Server, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_Terminate, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Group_Latch, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LatchGroup, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Next_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Prev_Group, 0x0000, + XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff, + 3, + { XkbSA_LockGroup, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_First_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { XK_ISO_Last_Group, 0x0000, + XkbSI_AnyOfOrNone, 0xff, + 255, + { XkbSA_LockGroup, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { NoSymbol, 0x0000, + XkbSI_Exactly, LockMask, + 255, + { XkbSA_LockMods, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { NoSymbol, 0x0000, + XkbSI_AnyOf, 0xff, + 255, + { XkbSA_SetMods, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +}; +#define num_dfltSI (sizeof(dfltSI)/sizeof(XkbSymInterpretRec)) + +static XkbCompatMapRec compatMap= { + dfltSI, + { /* group compatibility */ + { 0, 0, 0 }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask }, + { 0, 0, vmod_AltGrMask } + }, + num_dfltSI, num_dfltSI +}; + +static XkbIndicatorRec indicators= { + 0x0, + { + { 0x80, 0, 0x00, XkbIM_UseEffective, LockMask, LockMask, 0, 0 }, + { 0x80, 0, 0x00, XkbIM_UseEffective, 0, 0, vmod_NumLockMask, 0 }, + { 0x80, 0, 0x00, XkbIM_UseLocked, ShiftMask, ShiftMask, 0, 0 }, + { 0x80, 0, 0x00, 0, 0, 0, 0, XkbMouseKeysMask }, + { 0x80, 0, 0x00, XkbIM_UseLocked, 0, 0, vmod_ScrollLockMask, 0 }, + { 0x80, XkbIM_UseEffective, 0xfe, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 }, + { 0x00, 0, 0x00, 0, 0, 0, 0, 0 } + } +}; +static void +#if NeedFunctionPrototypes +initIndicatorNames(DPYTYPE dpy,XkbDescPtr xkb) +#else +initIndicatorNames(dpy,xkb) + DPYTYPE dpy; + XkbDescPtr xkb; +#endif +{ + xkb->names->indicators[ 0]= GET_ATOM(dpy,"Caps Lock"); + xkb->names->indicators[ 1]= GET_ATOM(dpy,"Num Lock"); + xkb->names->indicators[ 2]= GET_ATOM(dpy,"Shift Lock"); + xkb->names->indicators[ 3]= GET_ATOM(dpy,"Mouse Keys"); + xkb->names->indicators[ 4]= GET_ATOM(dpy,"Scroll Lock"); + xkb->names->indicators[ 5]= GET_ATOM(dpy,"Group 2"); +} +#endif /* DEFAULT_H */ diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c new file mode 100644 index 000000000..5a0f1d54b --- /dev/null +++ b/xkb/xkbEvents.c @@ -0,0 +1,1154 @@ +/* $Xorg: xkbEvents.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "XI.h" +#include "inputstr.h" +#include "windowstr.h" +#include "XKBsrv.h" + +extern int (*InitialVector[3])(); + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN) +#else +XkbSendNewKeyboardNotify(kbd,pNKN) + DeviceIntPtr kbd; + xkbNewKeyboardNotify * pNKN; +#endif +{ +register int i; +Time time; +CARD16 changed; +XkbChangesRec changes; + + pNKN->type = XkbEventCode + XkbEventBase; + pNKN->xkbType = XkbNewKeyboardNotify; + pNKN->time = time = GetTimeInMillis(); + changed = pNKN->changed; + + for (i=1; i<currentMaxClients; i++) { + if ((!clients[i]) || clients[i]->clientGone || + (clients[i]->requestVector==InitialVector)) { + continue; + } + + if (clients[i]->xkbClientFlags&_XkbClientInitialized) { + if (clients[i]->newKeyboardNotifyMask&changed) { + pNKN->sequenceNumber = clients[i]->sequence; + pNKN->time = time; + pNKN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pNKN->sequenceNumber,n); + swapl(&pNKN->time,n); + swaps(&pNKN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN); + if (changed&XkbNKN_KeycodesMask) { + clients[i]->minKC= pNKN->minKeyCode; + clients[i]->maxKC= pNKN->maxKeyCode; + } + } + } + else if (changed&XkbNKN_KeycodesMask) { + xEvent event; + event.u.u.type= MappingNotify; + event.u.mappingNotify.request= MappingKeyboard; + event.u.mappingNotify.firstKeyCode= clients[i]->minKC; + event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1; + event.u.u.sequenceNumber= clients[i]->sequence; + if (clients[i]->swapped) { + int n; + swaps(&event.u.u.sequenceNumber,n); + } + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + event.u.mappingNotify.request= MappingModifier; + WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); + } + } + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN) +#else +XkbSendStateNotify(kbd,pSN) + DeviceIntPtr kbd; + xkbStateNotify *pSN; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbStatePtr state; +XkbInterestPtr interest; +Time time; +register CARD16 changed,bState; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + state= &xkbi->state; + + pSN->type = XkbEventCode + XkbEventBase; + pSN->xkbType = XkbStateNotify; + pSN->deviceID = kbd->id; + pSN->time = time = GetTimeInMillis(); + pSN->mods = state->mods; + pSN->baseMods = state->base_mods; + pSN->latchedMods = state->latched_mods; + pSN->lockedMods = state->locked_mods; + pSN->group = state->group; + pSN->baseGroup = state->base_group; + pSN->latchedGroup = state->latched_group; + pSN->lockedGroup = state->locked_group; + pSN->compatState = state->compat_state; + pSN->grabMods = state->grab_mods; + pSN->compatGrabMods = state->compat_grab_mods; + pSN->lookupMods = state->lookup_mods; + pSN->compatLookupMods = state->compat_lookup_mods; + pSN->ptrBtnState = state->ptr_buttons; + changed = pSN->changed; + bState= pSN->ptrBtnState; + + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->stateNotifyMask&changed)) { + pSN->sequenceNumber = interest->client->sequence; + pSN->time = time; + pSN->changed = changed; + pSN->ptrBtnState = bState; + if ( interest->client->swapped ) { + register int n; + swaps(&pSN->sequenceNumber,n); + swapl(&pSN->time,n); + swaps(&pSN->changed,n); + swaps(&pSN->ptrBtnState,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pSN); + } + interest= interest->next; + } + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN) +#else +XkbSendMapNotify(kbd,pMN) + DeviceIntPtr kbd; + xkbMapNotify *pMN; +#endif +{ +int i; +XkbSrvInfoPtr xkbi; +unsigned time,initialized; +CARD16 changed; + + xkbi = kbd->key->xkbInfo; + initialized= 0; + + changed = pMN->changed; + pMN->minKeyCode= xkbi->desc->min_key_code; + pMN->maxKeyCode= xkbi->desc->max_key_code; + for (i=1; i<currentMaxClients; i++) { + if (clients[i] && ! clients[i]->clientGone && + (clients[i]->requestVector != InitialVector) && + (clients[i]->xkbClientFlags&_XkbClientInitialized) && + (clients[i]->mapNotifyMask&changed)) + { + if (!initialized) { + pMN->type = XkbEventCode + XkbEventBase; + pMN->xkbType = XkbMapNotify; + pMN->deviceID = kbd->id; + time = GetTimeInMillis(); + initialized= 1; + } + pMN->time= time; + pMN->sequenceNumber = clients[i]->sequence; + pMN->changed = changed; + if ( clients[i]->swapped ) { + register int n; + swaps(&pMN->sequenceNumber,n); + swapl(&pMN->time,n); + swaps(&pMN->changed,n); + } + WriteToClient(clients[i],sizeof(xEvent),(char *)pMN); + } + } + return; +} + +int +#if NeedFunctionPrototypes +XkbComputeControlsNotify( DeviceIntPtr kbd, + XkbControlsPtr old, + XkbControlsPtr new, + xkbControlsNotify * pCN, + Bool forceCtrlProc) +#else +XkbComputeControlsNotify(kbd,old,new,pCN,forceCtrlProc) + DeviceIntPtr kbd; + XkbControlsPtr old; + XkbControlsPtr new; + xkbControlsNotify *pCN; + Bool forceCtrlProc; +#endif +{ +int i; +CARD32 changedControls; + + changedControls= 0; + if (old->enabled_ctrls!=new->enabled_ctrls) + changedControls|= XkbControlsEnabledMask; + if ((old->repeat_delay!=new->repeat_delay)|| + (old->repeat_interval!=new->repeat_interval)) + changedControls|= XkbRepeatKeysMask; + for (i = 0; i < XkbPerKeyBitArraySize; i++) + if (old->per_key_repeat[i] != new->per_key_repeat[i]) + changedControls|= XkbPerKeyRepeatMask; + if (old->slow_keys_delay!=new->slow_keys_delay) + changedControls|= XkbSlowKeysMask; + if (old->debounce_delay!=new->debounce_delay) + changedControls|= XkbBounceKeysMask; + if ((old->mk_delay!=new->mk_delay)|| + (old->mk_interval!=new->mk_interval)|| + (old->mk_dflt_btn!=new->mk_dflt_btn)) + changedControls|= XkbMouseKeysMask; + if ((old->mk_time_to_max!=new->mk_time_to_max)|| + (old->mk_curve!=new->mk_curve)|| + (old->mk_max_speed!=new->mk_max_speed)) + changedControls|= XkbMouseKeysAccelMask; + if (old->ax_options!=new->ax_options) + changedControls|= XkbAccessXKeysMask; + if ((old->ax_timeout!=new->ax_timeout)|| + (old->axt_ctrls_mask!=new->axt_ctrls_mask)|| + (old->axt_ctrls_values!=new->axt_ctrls_values)|| + (old->axt_opts_mask!=new->axt_opts_mask)|| + (old->axt_opts_values!= new->axt_opts_values)) { + changedControls|= XkbAccessXTimeoutMask; + } + if ((old->internal.mask!=new->internal.mask)|| + (old->internal.real_mods!=new->internal.real_mods)|| + (old->internal.vmods!=new->internal.vmods)) + changedControls|= XkbInternalModsMask; + if ((old->ignore_lock.mask!=new->ignore_lock.mask)|| + (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)|| + (old->ignore_lock.vmods!=new->ignore_lock.vmods)) + changedControls|= XkbIgnoreLockModsMask; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + kbd->kbdfeed->ctrl.autoRepeat=TRUE; + else kbd->kbdfeed->ctrl.autoRepeat=FALSE; + + if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc && + (changedControls || forceCtrlProc)) + (*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl); + + if ((!changedControls)&&(old->num_groups==new->num_groups)) + return 0; + + if (!kbd->xkb_interest) + return 0; + + pCN->changedControls = changedControls; + pCN->enabledControls = new->enabled_ctrls; + pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls); + pCN->numGroups = new->num_groups; + + return 1; +} + +void +#if NeedFunctionPrototypes +XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN) +#else +XkbSendControlsNotify(kbd,pCN) + DeviceIntPtr kbd; + xkbControlsNotify *pCN; +#endif +{ +int initialized; +CARD32 changedControls,enabledControls,enabledChanges; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time; + + interest = kbd->xkb_interest; + if (!interest) + return; + xkbi = kbd->key->xkbInfo; + + initialized = 0; + enabledControls = xkbi->desc->ctrls->enabled_ctrls; + changedControls = pCN->changedControls; + pCN->numGroups= xkbi->desc->ctrls->num_groups; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->ctrlsNotifyMask&changedControls)) { + if (!initialized) { + pCN->type = XkbEventCode + XkbEventBase; + pCN->xkbType = XkbControlsNotify; + pCN->deviceID = kbd->id; + pCN->time = time = GetTimeInMillis(); + enabledChanges = pCN->enabledControlChanges; + initialized= 1; + } + pCN->changedControls = changedControls; + pCN->enabledControls = enabledControls; + pCN->enabledControlChanges = enabledChanges; + pCN->sequenceNumber = interest->client->sequence; + pCN->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pCN->sequenceNumber,n); + swapl(&pCN->changedControls,n); + swapl(&pCN->enabledControls,n); + swapl(&pCN->enabledControlChanges,n); + swapl(&pCN->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pCN); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv) +#else +XkbSendIndicatorNotify(kbd,xkbType,pEv) + DeviceIntPtr kbd; + int xkbType; + xkbIndicatorNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD32 state,changed; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + state = pEv->state; + changed = pEv->changed; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (((xkbType==XkbIndicatorStateNotify)&& + (interest->iStateNotifyMask&changed))|| + ((xkbType==XkbIndicatorMapNotify)&& + (interest->iMapNotifyMask&changed)))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = xkbType; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->state = state; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->changed,n); + swapl(&pEv->state,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + + +void +#if NeedFunctionPrototypes +XkbHandleBell( BOOL force, + BOOL eventOnly, + DeviceIntPtr kbd, + CARD8 percent, + pointer pCtrl, + CARD8 class, + Atom name, + WindowPtr pWin, + ClientPtr pClient) +#else +XkbHandleBell(force,eventOnly,kbd,percent,pCtrl,class,name,pWin,pClient) + BOOL force; + BOOL eventOnly; + DeviceIntPtr kbd; + CARD8 percent; + pointer *pCtrl; + CARD8 class; + Atom name; + WindowPtr pWin; + ClientPtr pClient; +#endif +{ +xkbBellNotify bn; +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +CARD8 id; +CARD16 pitch,duration; +Time time; +XID winID; + + xkbi = kbd->key->xkbInfo; + + if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&& + (!eventOnly)) { + (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class); + } + interest = kbd->xkb_interest; + if ((!interest)||(force)) + return; + + if ((class==0)||(class==KbdFeedbackClass)) { + KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl; + id= pKeyCtrl->id; + pitch= pKeyCtrl->bell_pitch; + duration= pKeyCtrl->bell_duration; + } + else if (class==BellFeedbackClass) { + BellCtrl *pBellCtrl= (BellCtrl *)pCtrl; + id= pBellCtrl->id; + pitch= pBellCtrl->pitch; + duration= pBellCtrl->duration; + } + else return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->bellNotifyMask)) { + if (!initialized) { + time = GetTimeInMillis(); + bn.type = XkbEventCode + XkbEventBase; + bn.xkbType = XkbBellNotify; + bn.deviceID = kbd->id; + bn.bellClass = class; + bn.bellID = id; + bn.percent= percent; + bn.eventOnly = (eventOnly!=0); + winID= (pWin?pWin->drawable.id:None); + initialized= 1; + } + bn.sequenceNumber = interest->client->sequence; + bn.time = time; + bn.pitch = pitch; + bn.duration = duration; + bn.name = name; + bn.window= winID; + if ( interest->client->swapped ) { + register int n; + swaps(&bn.sequenceNumber,n); + swapl(&bn.time,n); + swaps(&bn.pitch,n); + swaps(&bn.duration,n); + swapl(&bn.name,n); + swapl(&bn.window,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)&bn); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv) +#else +XkbSendAccessXNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbAccessXNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 sk_delay,db_delay; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + sk_delay= pEv->slowKeysDelay; + db_delay= pEv->debounceDelay; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->accessXNotifyMask&(1<<pEv->detail))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbAccessXNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->slowKeysDelay = sk_delay; + pEv->debounceDelay = db_delay; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->slowKeysDelay,n); + swaps(&pEv->debounceDelay,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv) +#else +XkbSendNamesNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbNamesNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 changed,changedVirtualMods; +CARD32 changedIndicators; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + changed= pEv->changed; + changedIndicators= pEv->changedIndicators; + changedVirtualMods= pEv->changedVirtualMods; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->namesNotifyMask&pEv->changed)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbNamesNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->changedIndicators = changedIndicators; + pEv->changedVirtualMods= changedVirtualMods; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->changed,n); + swapl(&pEv->changedIndicators,n); + swaps(&pEv->changedVirtualMods,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv) +#else +XkbSendCompatMapNotify(kbd,pEv) + DeviceIntPtr kbd; + xkbCompatMapNotify *pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD16 firstSI,nSI,nTotalSI; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->compatNotifyMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbCompatMapNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + firstSI= pEv->firstSI; + nSI= pEv->nSI; + nTotalSI= pEv->nTotalSI; + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->firstSI = firstSI; + pEv->nSI = nSI; + pEv->nTotalSI = nTotalSI; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->firstSI,n); + swaps(&pEv->nSI,n); + swaps(&pEv->nTotalSI,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv) +#else +XkbSendActionMessage(kbd,pEv) + DeviceIntPtr kbd; + xkbActionMessage * pEv; +#endif +{ +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time; + + xkbi = kbd->key->xkbInfo; + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + pEv->mods= xkbi->state.mods; + pEv->group= xkbi->state.group; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->actionMessageMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbActionMessage; + pEv->deviceID = kbd->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendExtensionDeviceNotify( DeviceIntPtr dev, + ClientPtr client, + xkbExtensionDeviceNotify * pEv) +#else +XkbSendExtensionDeviceNotify(dev,client,pEv) + DeviceIntPtr dev; + ClientPtr client; + xkbExtensionDeviceNotify * pEv; +#endif +{ +int initialized; +XkbInterestPtr interest; +Time time; +CARD32 defined,state; +CARD16 reason,supported; + + interest = dev->xkb_interest; + if (!interest) + return; + + initialized = 0; + reason= pEv->reason; + defined= pEv->ledsDefined; + state= pEv->ledState; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->extDevNotifyMask&reason)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbExtensionDeviceNotify; + pEv->deviceID = dev->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + supported= pEv->supported; + initialized= 1; + } + else { + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->ledsDefined= defined; + pEv->ledState= state; + pEv->reason= reason; + pEv->supported= supported; + } + if (client!=interest->client) { + /* only report UnsupportedFeature to the client that */ + /* issued the failing request */ + pEv->reason&= ~XkbXI_UnsupportedFeatureMask; + if ((interest->extDevNotifyMask&reason)==0) + continue; + } + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->ledsDefined,n); + swapl(&pEv->ledState,n); + swaps(&pEv->reason,n); + swaps(&pEv->supported,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbSendNotification( DeviceIntPtr kbd, + XkbChangesPtr pChanges, + XkbEventCausePtr cause) +#else +XkbSendNotification(kbd,pChanges,cause) + DeviceIntPtr kbd; + XkbChangesPtr pChanges; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; + + sli= NULL; + if (pChanges->state_changes) { + xkbStateNotify sn; + sn.changed= pChanges->state_changes; + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + XkbSendStateNotify(kbd,&sn); + } + if (pChanges->map.changed) { + xkbMapNotify mn; + mn.changed= pChanges->map.changed; + mn.firstType= pChanges->map.first_type; + mn.nTypes= pChanges->map.num_types; + mn.firstKeySym= pChanges->map.first_key_sym; + mn.nKeySyms= pChanges->map.num_key_syms; + mn.firstKeyAct= pChanges->map.first_key_act; + mn.nKeyActs= pChanges->map.num_key_acts; + mn.firstKeyBehavior= pChanges->map.first_key_behavior; + mn.nKeyBehaviors= pChanges->map.num_key_behaviors; + mn.virtualMods= pChanges->map.vmods; + mn.firstKeyExplicit= pChanges->map.first_key_explicit; + mn.nKeyExplicit= pChanges->map.num_key_explicit; + mn.firstModMapKey= pChanges->map.first_modmap_key; + mn.nModMapKeys= pChanges->map.num_modmap_keys; + mn.firstVModMapKey= pChanges->map.first_vmodmap_key; + mn.nVModMapKeys= pChanges->map.num_vmodmap_keys; + XkbSendMapNotify(kbd,&mn); + } + if ((pChanges->ctrls.changed_ctrls)|| + (pChanges->ctrls.enabled_ctrls_changes)) { + xkbControlsNotify cn; + cn.changedControls= pChanges->ctrls.changed_ctrls; + cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes; + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(kbd,&cn); + } + if (pChanges->indicators.map_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.map_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in); + } + if (pChanges->indicators.state_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.state_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in); + } + if (pChanges->names.changed) { + xkbNamesNotify nn; + nn.changed= pChanges->names.changed; + nn.firstType= pChanges->names.first_type; + nn.nTypes= pChanges->names.num_types; + nn.firstLevelName= pChanges->names.first_lvl; + nn.nLevelNames= pChanges->names.num_lvls; + nn.nRadioGroups= pChanges->names.num_rg; + nn.changedVirtualMods= pChanges->names.changed_vmods; + nn.changedIndicators= pChanges->names.changed_indicators; + XkbSendNamesNotify(kbd,&nn); + } + if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) { + xkbCompatMapNotify cmn; + cmn.changedGroups= pChanges->compat.changed_groups; + cmn.firstSI= pChanges->compat.first_si; + cmn.nSI= pChanges->compat.num_si; + cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si; + XkbSendCompatMapNotify(kbd,&cmn); + } + return; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE) +#else +XkbFilterEvents(pClient,nEvents,xE) + ClientPtr pClient; + int nEvents; + xEvent *xE; +#endif +{ +int i; +DeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice(); +XkbSrvInfoPtr xkbi; + + xkbi= pXDev->key->xkbInfo; + if ( pClient->xkbClientFlags & _XkbClientInitialized ) { +#ifdef DEBUG + if ((xkbDebugFlags&0x10)&& + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) { + ErrorF("XKbFilterWriteEvents:\n"); + ErrorF(" Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state); + ErrorF(" XkbLastRepeatEvent!=xE (0x%x!=0x%x) %s\n", + XkbLastRepeatEvent,xE, + ((XkbLastRepeatEvent!=(pointer)xE)?"True":"False")); + ErrorF(" (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n", + pClient->xkbClientFlags, + (_XkbWantsDetectableAutoRepeat(pClient)?"True":"False")); + ErrorF(" !IsRelease(%d) %s\n",xE[0].u.u.type, + (!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False"); + } +#endif /* DEBUG */ + if ( (XkbLastRepeatEvent==(pointer)xE) && + (_XkbWantsDetectableAutoRepeat(pClient)) && + (_XkbIsReleaseEvent(xE[0].u.u.type)) ) { + return False; + } + if ((pXDev->grab != NullGrab) && + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) { + register unsigned state,flags; + + flags= pClient->xkbClientFlags; + state= xkbi->state.compat_grab_mods; + if (flags & XkbPCF_GrabsUseXKBStateMask) { + int group; + if (flags&XkbPCF_LookupStateWhenGrabbed) { + group= xkbi->state.group; + state= xkbi->state.lookup_mods; + } + else { + state= xkbi->state.grab_mods; + group= xkbi->state.base_group+xkbi->state.latched_group; + if ((group<0)||(group>=xkbi->desc->ctrls->num_groups)) { + group= XkbAdjustGroup(group,xkbi->desc->ctrls); + } + } + state = XkbBuildCoreState(state, group); + } + else if (flags&XkbPCF_LookupStateWhenGrabbed) + state= xkbi->state.compat_lookup_mods; + xE[0].u.keyButtonPointer.state= state; + } + } + else { + register CARD8 type; + + for (i=0;i<nEvents;i++) { + type= xE[i].u.u.type; +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) { + XkbStatePtr s= &xkbi->state; + ErrorF("XKbFilterWriteEvents (non-XKB):\n"); + ErrorF("event= 0x%04x\n",xE[0].u.keyButtonPointer.state); + ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods, + s->grab_mods); + ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n", + s->compat_lookup_mods, + s->compat_grab_mods); + } +#endif + if ( (type>=KeyPress)&&(type<=MotionNotify) ) { + CARD16 old,new; + + old= xE[i].u.keyButtonPointer.state&(~0x1f00); + new= xE[i].u.keyButtonPointer.state&0x1F00; + + if (old==XkbStateFieldFromRec(&xkbi->state)) + new|= xkbi->state.compat_lookup_mods; + else new|= xkbi->state.compat_grab_mods; + xE[i].u.keyButtonPointer.state= new; + } + else if ((type==EnterNotify)||(type==LeaveNotify)) { + xE->u.enterLeave.state&= 0x1F00; + xE->u.enterLeave.state|= xkbi->state.compat_grab_mods; + } + } + } + return True; +} + +/***====================================================================***/ + +XkbInterestPtr +#if NeedFunctionPrototypes +XkbFindClientResource(DevicePtr inDev,ClientPtr client) +#else +XkbFindClientResource(inDev,client) + DevicePtr inDev; + ClientPtr client; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + while (interest){ + if (interest->client==client) { + return interest; + } + interest = interest->next; + } + } + return NULL; +} + +XkbInterestPtr +#if NeedFunctionPrototypes +XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id) +#else +XkbAddClientResource(inDev,client,id) + DevicePtr inDev; + ClientPtr client; + XID id; +#endif +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + interest = dev->xkb_interest; + while (interest) { + if (interest->client==client) + return ((interest->resource==id)?interest:NULL); + interest = interest->next; + } + interest = _XkbTypedAlloc(XkbInterestRec); + bzero(interest,sizeof(XkbInterestRec)); + if (interest) { + interest->dev = dev; + interest->client = client; + interest->resource = id; + interest->stateNotifyMask= 0; + interest->ctrlsNotifyMask= 0; + interest->namesNotifyMask= 0; + interest->compatNotifyMask= 0; + interest->bellNotifyMask= FALSE; + interest->accessXNotifyMask= 0; + interest->iStateNotifyMask= 0; + interest->iMapNotifyMask= 0; + interest->altSymsNotifyMask= 0; + interest->next = dev->xkb_interest; + dev->xkb_interest= interest; + return interest; + } + return NULL; +} + +int +#if NeedFunctionPrototypes +XkbRemoveClient(DevicePtr inDev,ClientPtr client) +#else +XkbRemoveClient(inDev,client) +DevicePtr inDev; +ClientPtr client; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +unsigned long autoCtrls,autoValues; +Bool found; + + found= False; + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->client==client)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + xfree(interest); + found= True; + } + while ((!found)&&(interest->next)) { + if (interest->next->client==client) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + xfree(victim); + found= True; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} + +int +#if NeedFunctionPrototypes +XkbRemoveResourceClient(DevicePtr inDev,XID id) +#else +XkbRemoveResourceClient(inDev,id) + DevicePtr inDev; + XID id; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +Bool found; +unsigned long autoCtrls,autoValues; +ClientPtr client; + + found= False; + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->resource==id)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + client= interest->client; + xfree(interest); + found= True; + } + while ((!found)&&(interest->next)) { + if (interest->next->resource==id) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + client= victim->client; + xfree(victim); + found= True; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} + + + diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c new file mode 100644 index 000000000..3ca52ebc5 --- /dev/null +++ b/xkb/xkbInit.c @@ -0,0 +1,994 @@ +/* + * @(#)$RCSfile$ $Revision$ (DEC) $Date$ + */ +/* $Xorg: xkbInit.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include "misc.h" +#include "inputstr.h" +#include "property.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XKBgeom.h" +#include <X11/extensions/XKMformat.h> +#include <X11/extensions/XKBfile.h> + + +#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) + +#ifdef sgi +#define LED_CAPS 5 +#define LED_NUM 6 +#define LED_SCROLL 7 +#define PHYS_LEDS 0x7f +#define LED_COMPOSE 8 +#else +#if defined(ultrix) || defined(__osf__) || 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 +#endif + +#define MAX_TOC 16 +typedef struct _SrvXkmInfo { + DeviceIntPtr dev; + FILE * file; + XkbFileInfo xkbinfo; +} SrvXkmInfo; + + +/***====================================================================***/ + +#ifndef XKB_BASE_DIRECTORY +#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb" +#endif +#ifndef XKB_DFLT_RULES_FILE +#define XKB_DFLT_RULES_FILE "rules" +#endif +#ifndef XKB_DFLT_KB_LAYOUT +#define XKB_DFLT_KB_LAYOUT "us" +#endif +#ifndef XKB_DFLT_KB_MODEL +#define XKB_DFLT_KB_MODEL "dflt" +#endif +#ifndef XKB_DFLT_KB_VARIANT +#define XKB_DFLT_KB_VARIANT NULL +#endif +#ifndef XKB_DFLT_KB_OPTIONS +#define XKB_DFLT_KB_OPTIONS NULL +#endif +#ifndef XKB_DFLT_DISABLED +#define XKB_DFLT_DISABLED True +#endif +#ifndef XKB_DFLT_RULES_PROP +#define XKB_DFLT_RULES_PROP True +#endif + +char * XkbBaseDirectory= XKB_BASE_DIRECTORY; +char * XkbInitialMap= NULL; +int XkbWantAccessX= 0; +static XkbFileInfo * _XkbInitFileInfo= NULL; +char * XkbDB= NULL; +int XkbAutoLoad= 1; + +static Bool rulesDefined= False; +static char * XkbRulesFile= NULL; +static char * XkbModelDflt= NULL; +static char * XkbLayoutDflt= NULL; +static char * XkbVariantDflt= NULL; +static char * XkbOptionsDflt= NULL; + +char * XkbModelUsed= NULL; +char * XkbLayoutUsed= NULL; +char * XkbVariantUsed= NULL; +char * XkbOptionsUsed= NULL; + +int _XkbClientMajor= XkbMajorVersion; +int _XkbClientMinor= XkbMinorVersion; + +Bool noXkbExtension= XKB_DFLT_DISABLED; +Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbGetRulesDflts(XkbRF_VarDefsPtr defs) +#else +XkbGetRulesDflts(defs) + XkbRF_VarDefsPtr defs; +#endif +{ + if (XkbModelDflt) defs->model= XkbModelDflt; + else defs->model= XKB_DFLT_KB_MODEL; + if (XkbLayoutDflt) defs->layout= XkbLayoutDflt; + else defs->layout= XKB_DFLT_KB_LAYOUT; + if (XkbVariantDflt) defs->variant= XkbVariantDflt; + else defs->variant= XKB_DFLT_KB_VARIANT; + if (XkbOptionsDflt) defs->options= XkbOptionsDflt; + else defs->options= XKB_DFLT_KB_OPTIONS; + return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE); +} + +Bool +#if NeedFunctionPrototypes +XkbWriteRulesProp(ClientPtr client, pointer closure) +#else +XkbWriteRulesProp(client, closure) + ClientPtr client; + pointer closure; +#endif +{ +int len,out; +extern WindowPtr * WindowTable; +Atom name; +char * pval; + + if (rulesDefined && (!XkbRulesFile)) + return False; + len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE)); + 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("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); + return True; + } + pval= (char*) ALLOCATE_LOCAL(len); + if (!pval) { + ErrorF("Allocation error: %s proprerty not created\n", + _XKB_RF_NAMES_PROP_ATOM); + return True; + } + out= 0; + if (XkbRulesFile) { + strcpy(&pval[out],XkbRulesFile); + out+= strlen(XkbRulesFile); + } + 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("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", + out,len); + } + ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace, + len,pval,True); + DEALLOCATE_LOCAL(pval); + return True; +} + +void +#if NeedFunctionPrototypes +XkbSetRulesUsed(XkbRF_VarDefsPtr defs) +#else +XkbSetRulesUsed(defs) + XkbRF_VarDefsPtr defs; +#endif +{ + if (XkbModelUsed) + _XkbFree(XkbModelUsed); + XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL); + if (XkbLayoutUsed) + _XkbFree(XkbLayoutUsed); + XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL); + if (XkbVariantUsed) + _XkbFree(XkbVariantUsed); + XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL); + if (XkbOptionsUsed) + _XkbFree(XkbOptionsUsed); + XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL); + if (XkbWantRulesProp) + QueueWorkProc(XkbWriteRulesProp,NULL,NULL); + return; +} + +void +#if NeedFunctionPrototypes +XkbSetRulesDflts(char *rulesFile,char *model,char *layout, + char *variant,char *options) +#else +XkbSetRulesDflts(rulesFile,model,layout,variant,options) + char * rulesFile; + char * model; + char * layout; + char * variant; + char * options; +#endif +{ + if (XkbRulesFile) + _XkbFree(XkbRulesFile); + XkbRulesFile= _XkbDupString(rulesFile); + rulesDefined= True; + if (model) { + if (XkbModelDflt) + _XkbFree(XkbModelDflt); + XkbModelDflt= _XkbDupString(model); + } + if (layout) { + if (XkbLayoutDflt) + _XkbFree(XkbLayoutDflt); + XkbLayoutDflt= _XkbDupString(layout); + } + if (variant) { + if (XkbVariantDflt) + _XkbFree(XkbVariantDflt); + XkbVariantDflt= _XkbDupString(variant); + } + if (options) { + if (XkbOptionsDflt) + _XkbFree(XkbOptionsDflt); + XkbOptionsDflt= _XkbDupString(options); + } + return; +} + +/***====================================================================***/ + +#if defined(luna) +#define XKB_DDX_PERMANENT_LOCK 1 +#endif + +#include "xkbDflts.h" + +static Bool +#if NeedFunctionPrototypes +XkbInitKeyTypes(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitKeyTypes(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ + if (file->xkbinfo.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 +#if NeedFunctionPrototypes +XkbInitRadioGroups(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitRadioGroups(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ + xkbi->nRadioGroups = 0; + xkbi->radioGroups = NULL; + return; +} + + +static Status +#if NeedFunctionPrototypes +XkbInitCompatStructs(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitCompatStructs(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ +register int i; +XkbCompatMapPtr compat; + + if (file->xkbinfo.defined&XkmCompatMapMask) + return Success; + 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 +#if NeedFunctionPrototypes +XkbInitSemantics(XkbDescPtr xkb,SrvXkmInfo *file) +#else +XkbInitSemantics(xkb,file) + XkbDescPtr xkb; + SrvXkmInfo * file; +#endif +{ + XkbInitKeyTypes(xkb,file); + XkbInitCompatStructs(xkb,file); + return; +} + +/***====================================================================***/ + +static Status +#if NeedFunctionPrototypes +XkbInitNames(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitNames(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +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 ((file->xkbinfo.defined&XkmVirtualModsMask)==0) { + 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 (((file->xkbinfo.defined&XkmIndicatorsMask)==0)|| + ((file->xkbinfo.defined&XkmGeometryMask)==0)) { + 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 + } +#ifdef DEBUG_RADIO_GROUPS + if (names->num_rg<1) { + names->radio_groups= (Atom *)Xcalloc(RG_COUNT*sizeof(Atom)); + if (names->radio_groups) { + names->num_rg = RG_COUNT; + names->radio_groups[RG_BOGUS_FUNCTION_GROUP]= CREATE_ATOM("BOGUS"); + } + } +#endif + if (xkb->geom!=NULL) + names->geometry= xkb->geom->name; + else names->geometry= unknown; + return Success; +} + +static Status +#if NeedFunctionPrototypes +XkbInitIndicatorMap(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitIndicatorMap(xkbi,file) + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +XkbDescPtr xkb; +XkbIndicatorPtr map; +XkbSrvLedInfoPtr sli; + + xkb= xkbi->desc; + if (XkbAllocIndicatorMaps(xkb)!=Success) + return BadAlloc; + if ((file->xkbinfo.defined&XkmIndicatorsMask)==0) { + 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; + } + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + if (sli) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); + return Success; +} + +static Status +#if NeedFunctionPrototypes +XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi,SrvXkmInfo *file) +#else +XkbInitControls(pXDev,xkbi,file) + DeviceIntPtr pXDev; + XkbSrvInfoPtr xkbi; + SrvXkmInfo * file; +#endif +{ +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 ((file->xkbinfo.defined&XkmSymbolsMask)==0) + 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; +} + +void +#if NeedFunctionPrototypes +XkbInitDevice(DeviceIntPtr pXDev) +#else +XkbInitDevice(pXDev) + DeviceIntPtr pXDev; +#endif +{ +int i; +XkbSrvInfoPtr xkbi; +XkbChangesRec changes; +SrvXkmInfo file; +unsigned check; +XkbEventCauseRec cause; + + file.dev= pXDev; + file.file=NULL; + bzero(&file.xkbinfo,sizeof(XkbFileInfo)); + bzero(&changes,sizeof(XkbChangesRec)); + if (XkbAutoLoad && (XkbInitialMap!=NULL)) { + if ((file.file=XkbDDXOpenConfigFile(XkbInitialMap,NULL,0))!=NULL) { + XkmReadFile(file.file,0,XkmKeymapLegal,&file.xkbinfo); + if (file.xkbinfo.xkb==NULL) { + ErrorF("Error loading keymap file %s (%s in %s)\n", + XkbInitialMap, _XkbErrMessages[_XkbErrCode], + (_XkbErrLocation?_XkbErrLocation:"unknown")); + ErrorF(" reverting to defaults\n"); + fclose(file.file); + file.file= NULL; + bzero(&file.xkbinfo,sizeof(XkbFileInfo)); + } + else { + if (_XkbInitFileInfo!=NULL) { + XkbDescPtr tmp; + if ((tmp=_XkbInitFileInfo->xkb)!=NULL) { + XkbFreeKeyboard(tmp,XkbAllComponentsMask,True); + _XkbInitFileInfo->xkb= NULL; + } + } + _XkbInitFileInfo= &file.xkbinfo; + } + } + else { + ErrorF("Error opening keymap file %s, reverting to defaults\n", + XkbInitialMap); + } + } + pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec); + if ( xkbi ) { + XkbDescPtr xkb; + if ((_XkbInitFileInfo!=NULL)&&(_XkbInitFileInfo->xkb!=NULL)) { + file.xkbinfo= *_XkbInitFileInfo; + xkbi->desc= _XkbInitFileInfo->xkb; + _XkbInitFileInfo= NULL; + } + else { + xkbi->desc= XkbAllocKeyboard(); + if (!xkbi->desc) + FatalError("Couldn't allocate keyboard description\n"); + xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode; + xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + } + xkb= xkbi->desc; + if (xkb->min_key_code == 0) + xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode; + if (xkb->max_key_code == 0) + xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode; + if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)|| + (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) { + /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */ + /* the other here, but for now just complain */ + /* can't just update the core range without */ + /* reallocating the KeySymsRec (pain) */ + ErrorF("Internal Error!! XKB and core keymap have different range\n"); + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) + FatalError("Couldn't allocate client map in XkbInitDevice\n"); + i= XkbNumKeys(xkb)/3+1; + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success) + FatalError("Couldn't allocate server map in XkbInitDevice\n"); + + xkbi->dfltPtrDelta=1; + xkbi->device = pXDev; + + file.xkbinfo.xkb= xkb; + XkbInitSemantics(xkb,&file); + XkbInitNames(xkbi,&file); + XkbInitRadioGroups(xkbi,&file); + + /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */ + bzero(&xkbi->state,sizeof(XkbStateRec)); + + XkbInitControls(pXDev,xkbi,&file); + + if (file.xkbinfo.defined&XkmSymbolsMask) + memcpy(pXDev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + else + memcpy(xkb->map->modmap,pXDev->key->modifierMap,xkb->max_key_code+1); + + XkbInitIndicatorMap(xkbi,&file); + + XkbDDXInitDevice(pXDev); + + if (!(file.xkbinfo.defined&XkmSymbolsMask)) { + XkbUpdateKeyTypesFromCore(pXDev,xkb->min_key_code,XkbNumKeys(xkb), + &changes); + } + else { + XkbUpdateCoreDescription(pXDev,True); + } + XkbSetCauseUnknown(&cause); + XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes, + &check,&cause); + /* For sanity. The first time the connection + * is opened, the client side min and max are set + * using QueryMinMaxKeyCodes() which grabs them + * from pXDev. + */ + pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code; + pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code; + } + if (file.file!=NULL) + fclose(file.file); + return; +} + + +Bool +#if NeedFunctionPrototypes +XkbInitKeyboardDeviceStruct( DeviceIntPtr dev, + XkbComponentNamesPtr names, + KeySymsPtr pSymsIn, + CARD8 pModsIn[], + void (*bellProc)(), + void (*ctrlProc)()) +#else +XkbInitKeyboardDeviceStruct( dev,names,pSymsIn,pModsIn,bellProc,ctrlProc ) + DeviceIntPtr dev; + XkbComponentNamesPtr names; + KeySymsPtr pSymsIn; + CARD8 pModsIn[]; + void (*bellProc)(); + void (*ctrlProc)(); +#endif +{ +XkbFileInfo finfo; +KeySymsRec tmpSyms,*pSyms; +CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods; +char name[PATH_MAX],*rules; +Bool ok; +XPointer config; +XkbComponentNamesRec cfgNames; +XkbRF_VarDefsRec defs; + + if ((dev->key!=NULL)||(dev->kbdfeed!=NULL)) + return False; + pSyms= pSymsIn; + pMods= pModsIn; + bzero(&defs,sizeof(XkbRF_VarDefsRec)); + bzero(&cfgNames,sizeof(XkbComponentNamesRec)); + rules= XkbGetRulesDflts(&defs); + config= XkbDDXPreloadConfig(&rules,&defs,&cfgNames,dev); + + if (defs.model && defs.layout && rules) { + XkbComponentNamesRec rNames; + bzero(&rNames,sizeof(XkbComponentNamesRec)); + if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) { + if (rNames.keymap) names->keymap= rNames.keymap; + if (rNames.keycodes) names->keycodes= rNames.keycodes; + if (rNames.types) names->types= rNames.types; + if (rNames.compat) names->compat= rNames.compat; + if (rNames.symbols) names->symbols= rNames.symbols; + if (rNames.geometry) names->geometry= rNames.geometry; + XkbSetRulesUsed(&defs); + } + } + if (cfgNames.keymap) names->keymap= cfgNames.keymap; + if (cfgNames.keycodes) names->keycodes= cfgNames.keycodes; + if (cfgNames.types) names->types= cfgNames.types; + if (cfgNames.compat) names->compat= cfgNames.compat; + if (cfgNames.symbols) names->symbols= cfgNames.symbols; + if (cfgNames.geometry) names->geometry= cfgNames.geometry; + + if ((XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0, + &finfo,name,PATH_MAX))&& + (finfo.xkb!=NULL)) { + XkbDescPtr xkb; + int minKC,maxKC; + + xkb= finfo.xkb; + minKC= xkb->min_key_code; + maxKC= xkb->max_key_code; + if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&& + ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) { + if (xkb->map!=NULL) { + KeySym *inSym,*outSym; + int width= pSymsIn->mapWidth; + + tmpSyms.minKeyCode= minKC; + tmpSyms.maxKeyCode= maxKC; + + if (minKC<pSymsIn->minKeyCode) + minKC= pSymsIn->minKeyCode; + if (maxKC>pSymsIn->maxKeyCode) + maxKC= pSymsIn->maxKeyCode; + + tmpSyms.mapWidth= width; + tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym); + inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width]; + outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width]; + memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym)); + pSyms= &tmpSyms; + } + if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) { + bzero(tmpMods,XkbMaxKeyCount); + memcpy(tmpMods,xkb->map->modmap,maxKC+1); + pMods= tmpMods; + } + } + _XkbInitFileInfo= &finfo; + } + else { + ErrorF("Couldn't load XKB keymap, falling back to pre-XKB keymap\n"); + } + ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc); + if ((config!=NULL)&&(dev && dev->key && dev->key->xkbInfo)) + XkbDDXApplyConfig(config,dev->key->xkbInfo); + _XkbInitFileInfo= NULL; + if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) { + _XkbFree(pSyms->map); + pSyms->map= NULL; + } + return ok; +} + +/***====================================================================***/ + + /* + * InitKeyClassDeviceStruct initializes the key class before it + * initializes the keyboard feedback class for a device. + * UpdateActions can't set up the correct autorepeat for keyboard + * initialization because the keyboard feedback isn't created yet. + * Instead, UpdateActions notes the "correct" autorepeat in the + * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat + * to apply the computed autorepeat once the feedback class exists. + * + * DIX will apply the changed autorepeat, so there's no need to + * do so here. This function returns True if both RepeatKeys and + * the core protocol autorepeat ctrls are set (i.e. should use + * software autorepeat), false otherwise. + * + * This function also computes the autorepeat accelerators for the + * default indicator feedback. + */ +int +#if NeedFunctionPrototypes +XkbFinishDeviceInit(DeviceIntPtr pXDev) +#else +XkbFinishDeviceInit(pXDev) + DeviceIntPtr pXDev; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +int softRepeat; +XkbSrvLedInfoPtr sli; + + xkbi = NULL; + if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + if (pXDev->kbdfeed) { + xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; + pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; + } + if (pXDev->kbdfeed->ctrl.autoRepeat) + xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask; + softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0; + if (pXDev->kbdfeed) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats, + xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize); + softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat; + } + } + else softRepeat= 0; + sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); + if (sli && xkbi) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); +#ifdef DEBUG + else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); +#endif + return softRepeat; +} + + /* + * 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 +#if NeedFunctionPrototypes +XkbFreeInfo(XkbSrvInfoPtr xkbi) +#else +XkbFreeInfo(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ + 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 +#if NeedFunctionPrototypes +XkbProcessArguments(int argc,char *argv[],int i) +#else +XkbProcessArguments(argc,argv,i) + int argc; + char * argv[]; + int i; +#endif +{ + if (strcmp(argv[i],"-kb")==0) { + noXkbExtension= True; + return 1; + } + else if (strcmp(argv[i],"+kb")==0) { + noXkbExtension= False; + return 1; + } + else if (strncmp(argv[i], "-xkbmap", 7) == 0) { + if(++i < argc) { + XkbInitialMap= argv[i]; + return 2; + } + else { + return -1; + } + } + else if (strncmp(argv[i], "-xkbdb", 7) == 0) { + if(++i < argc) { + XkbDB= argv[i]; + return 2; + } + else { + return -1; + } + } + else if (strncmp(argv[i], "-noloadxkb", 7) == 0) { + XkbAutoLoad= 0; + 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], "-ar1") == 0) { /* -ar1 int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatDelay = (long)atoi(argv[i]); + return 2; + } + if (strcmp (argv[i], "-ar2") == 0) { /* -ar2 int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatInterval = (long)atoi(argv[i]); + return 2; + } + return 0; +} + +void +#if NeedFunctionPrototypes +XkbUseMsg(void) +#else +XkbUseMsg() +#endif +{ + ErrorF("The X Keyboard Extension adds the following arguments:\n"); + ErrorF("-kb disable the X Keyboard Extension\n"); + ErrorF("+kb enable the X Keyboard Extension\n"); + ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); + ErrorF(" enable/disable accessx key sequences\n"); + ErrorF("-ar1 set XKB autorepeat delay\n"); + ErrorF("-ar2 set XKB autorepeat interval\n"); + ErrorF("-noloadxkb don't load XKB keymap description\n"); + ErrorF("-xkbcomp default keymap compiler\n"); + ErrorF("-xkbdb file that contains default XKB keymaps\n"); + ErrorF("-xkbmap XKB keyboard description to load on startup\n"); +} diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c new file mode 100644 index 000000000..d3be89af7 --- /dev/null +++ b/xkb/xkbLEDs.c @@ -0,0 +1,1212 @@ +/* $Xorg: xkbLEDs.c,v 1.3 2000/08/17 19:53:47 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 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. + +********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" + +#include "XI.h" +#include "XKBsrv.h" + +extern InputInfo inputInfo; + +/***====================================================================***/ + + /* + * unsigned + * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) + * + * Given a keyboard and a set of state components that have changed, + * this function returns the indicators on the default keyboard + * feedback that might be affected. It also reports whether or not + * any extension devices might be affected in check_devs_rtrn. + */ + +unsigned +#if NeedFunctionPrototypes +XkbIndicatorsToUpdate( DeviceIntPtr dev, + unsigned long state_changes, + Bool enable_changes) +#else +XkbIndicatorsToUpdate(dev,state_changes,enable_changes) + DeviceIntPtr dev; + unsigned long state_changes; + Bool enable_changes; +#endif +{ +register unsigned update= 0; +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + + if (state_changes&(XkbModifierStateMask|XkbGroupStateMask)) + update|= sli->usesEffective; + if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask)) + update|= sli->usesBase; + if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask)) + update|= sli->usesLatched; + if (state_changes&(XkbModifierLockMask|XkbGroupLockMask)) + update|= sli->usesLocked; + if (state_changes&XkbCompatStateMask) + update|= sli->usesCompat; + if (enable_changes) + update|= sli->usesControls; + return update; +} + +/***====================================================================***/ + + /* + * Bool + * XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) + * + * Some indicators "drive" the keyboard when their state is explicitly + * changed, as described in section 9.2.1 of the XKB protocol spec. + * This function updates the state and controls for the keyboard + * specified by 'xkbi' to reflect any changes that are required + * when the indicator described by 'map' is turned on or off. The + * extent of the changes is reported in change, which must be defined. + */ +Bool +#if NeedFunctionPrototypes +XkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi, + XkbIndicatorMapPtr map, + Bool on, + XkbChangesPtr change) +#else +XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) + XkbSrvInfoPtr xkbi; + XkbIndicatorMapPtr map; + Bool on; + XkbChangesPtr change; +#endif +{ +Bool ctrlChange,stateChange; +XkbStatePtr state; + + if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0)) + return False; + ctrlChange= stateChange= False; + if (map->ctrls) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + unsigned old; + + old= ctrls->enabled_ctrls; + if (on) ctrls->enabled_ctrls|= map->ctrls; + else ctrls->enabled_ctrls&= ~map->ctrls; + if (old!=ctrls->enabled_ctrls) { + change->ctrls.changed_ctrls= XkbControlsEnabledMask; + change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls; + ctrlChange= True; + } + } + state= &xkbi->state; + if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) { + register int i; + register unsigned bit,match; + + if (on) match= (map->groups)&XkbAllGroupsMask; + else match= (~map->groups)&XkbAllGroupsMask; + if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (bit&match) + break; + } + if (map->which_groups&XkbIM_UseLatched) + XkbLatchGroup(xkbi->device,0); /* unlatch group */ + state->locked_group= i; + stateChange= True; + } + else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (bit&match) + break; + } + state->locked_group= 0; + XkbLatchGroup(xkbi->device,i); + stateChange= True; + } + } + if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) { + if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) { + register unsigned long old; + old= state->locked_mods; + if (on) state->locked_mods|= map->mods.mask; + else state->locked_mods&= ~map->mods.mask; + if (state->locked_mods!=old) + stateChange= True; + } + if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) { + register unsigned long newmods; + newmods= state->latched_mods; + if (on) newmods|= map->mods.mask; + else newmods&= ~map->mods.mask; + if (newmods!=state->locked_mods) { + newmods&= map->mods.mask; + XkbLatchModifiers(xkbi->device,map->mods.mask,newmods); + stateChange= True; + } + } + } + return (stateChange || ctrlChange); +} + +/***====================================================================***/ + + /* + * void + * XkbSetIndicators(dev,affect,values,cause) + * + * Attempts to change the indicators specified in 'affect' to the + * states specified in 'values' for the default keyboard feedback + * on the keyboard specified by 'dev.' Attempts to change indicator + * state might be ignored or have no affect, depending on the XKB + * indicator map for any affected indicators, as described in section + * 9.2 of the XKB protocol specification. + * + * If 'changes' is non-NULL, this function notes any changes to the + * keyboard state, controls, or indicator state that result from this + * attempted change. If 'changes' is NULL, this function generates + * XKB events to report any such changes to interested clients. + * + * If 'cause' is non-NULL, it specifies the reason for the change, + * as reported in some XKB events. If it is NULL, this function + * assumes that the change is the result of a core protocol + * ChangeKeyboardMapping request. + */ + +void +#if NeedFunctionPrototypes +XkbSetIndicators( DeviceIntPtr dev, + CARD32 affect, + CARD32 values, + XkbEventCausePtr cause) +#else +XkbSetIndicators(dev,affect,values,cause) + DeviceIntPtr dev; + CARD32 affect; + CARD32 values; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; +XkbChangesRec changes; +xkbExtensionDeviceNotify ed; +unsigned side_affected; + + bzero((char *)&changes,sizeof(XkbChangesRec)); + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + sli->explicitState&= ~affect; + sli->explicitState|= (affect&values); + XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause); + + side_affected= 0; + if (changes.state_changes!=0) + side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False); + if (changes.ctrls.enabled_ctrls_changes) + side_affected|= sli->usesControls; + + if (side_affected) { + XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause); + affect|= side_affected; + } + XkbSendNotification(dev,&changes,cause); + if (ed.reason) + XkbSendExtensionDeviceNotify(dev,cause->client,&ed); + if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) + XkbUpdateAllDeviceIndicators(NULL,cause); + return; +} + +/***====================================================================***/ + + /* + * Bool + * ComputeAutoState(map,state,ctrls) + * + * This function reports the effect of applying the specified + * indicator map given the specified state and controls, as + * described in section 9.2 of the XKB protocol specification. + */ + +static Bool +#if NeedFunctionPrototypes +ComputeAutoState( XkbIndicatorMapPtr map, + XkbStatePtr state, + XkbControlsPtr ctrls) +#else +ComputeAutoState(map,state,ctrls) + XkbIndicatorMapPtr map; + XkbStatePtr state; + XkbControlsPtr ctrls; +#endif +{ +Bool on; +CARD8 mods,group; + + on= False; + mods= group= 0; + if (map->which_mods&XkbIM_UseAnyMods) { + if (map->which_mods&XkbIM_UseBase) + mods|= state->base_mods; + if (map->which_mods&XkbIM_UseLatched) + mods|= state->latched_mods; + if (map->which_mods&XkbIM_UseLocked) + mods|= state->locked_mods; + if (map->which_mods&XkbIM_UseEffective) + mods|= state->mods; + if (map->which_mods&XkbIM_UseCompat) + mods|= state->compat_state; + on = ((map->mods.mask&mods)!=0); + on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0)); + } + if (map->which_groups&XkbIM_UseAnyGroup) { + if (map->which_groups&XkbIM_UseBase) + group|= (1L << state->base_group); + if (map->which_groups&XkbIM_UseLatched) + group|= (1L << state->latched_group); + if (map->which_groups&XkbIM_UseLocked) + group|= (1L << state->locked_group); + if (map->which_groups&XkbIM_UseEffective) + group|= (1L << state->group); + on = on||(((map->groups&group)!=0)||(map->groups==0)); + } + if (map->ctrls) + on = on||(ctrls->enabled_ctrls&map->ctrls); + return on; +} + +/***====================================================================***/ + + /* + * void + * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) + * + * Applies the indicator maps for any indicators specified in + * 'update' from the default keyboard feedback on the device + * specified by 'dev.' + * + * If 'changes' is NULL, this function generates and XKB events + * required to report the necessary changes, otherwise it simply + * notes the indicators with changed state. + * + * If 'check_edevs' is True, this function also checks the indicator + * maps for any open extension devices that have them, and updates + * the state of any extension device indicators as necessary. + */ + +void +#if NeedFunctionPrototypes +XkbUpdateIndicators( DeviceIntPtr dev, + register CARD32 update, + Bool check_edevs, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbUpdateIndicators(dev,update,check_edevs,changes,cause) + DeviceIntPtr dev; + register CARD32 update; + Bool check_edevs; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause); + if (check_edevs) + XkbUpdateAllDeviceIndicators(changes,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause) +#else +XkbUpdateAllDeviceIndicators(changes,cause) + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr edev; +XkbSrvLedInfoPtr sli; + + for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { + if (edev->kbdfeed) { + KbdFeedbackPtr kf; + for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) + continue; + sli= kf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + if (edev->leds) { + LedFeedbackPtr lf; + for (lf=edev->leds;lf!=NULL;lf=lf->next) { + if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) + continue; + sli= lf->xkb_sli; + XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, + changes,cause); + + } + } + } + return; +} + +/***====================================================================***/ + + /* + * void + * XkbCheckIndicatorMaps(dev,sli,which) + * + * Updates the 'indicator accelerators' for the indicators specified + * by 'which' in the feedback specified by 'sli.' The indicator + * accelerators are internal to the server and are used to simplify + * and speed up the process of figuring out which indicators might + * be affected by a particular change in keyboard state or controls. + */ + +void +#if NeedFunctionPrototypes +XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which) +#else +XkbCheckIndicatorMaps(dev,sli,which) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned which; +#endif +{ +register unsigned i,bit; +XkbIndicatorMapPtr map; +XkbDescPtr xkb; + + if ((sli->flags&XkbSLI_HasOwnState)==0) + dev= (DeviceIntPtr)LookupKeyboardDevice(); + + sli->usesBase&= ~which; + sli->usesLatched&= ~which; + sli->usesLocked&= ~which; + sli->usesEffective&= ~which; + sli->usesCompat&= ~which; + sli->usesControls&= ~which; + sli->mapsPresent&= ~which; + + xkb= dev->key->xkbInfo->desc; + for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) { + if (which&bit) { + CARD8 what; + + if (!XkbIM_InUse(map)) + continue; + sli->mapsPresent|= bit; + + what= (map->which_mods|map->which_groups); + if (what&XkbIM_UseBase) + sli->usesBase|= bit; + if (what&XkbIM_UseLatched) + sli->usesLatched|= bit; + if (what&XkbIM_UseLocked) + sli->usesLocked|= bit; + if (what&XkbIM_UseEffective) + sli->usesEffective|= bit; + if (what&XkbIM_UseCompat) + sli->usesCompat|= bit; + if (map->ctrls) + sli->usesControls|= bit; + + map->mods.mask= map->mods.real_mods; + if (map->mods.vmods!=0) { + map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); + } + } + } + sli->usedComponents= 0; + if (sli->usesBase) + sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask; + if (sli->usesLatched) + sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask; + if (sli->usesLocked) + sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask; + if (sli->usesEffective) + sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask; + if (sli->usesCompat) + sli->usedComponents|= XkbCompatStateMask; + return; +} + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) + * + * Allocates an XkbSrvLedInfoPtr for the feedback specified by either + * 'kf' or 'lf' on the keyboard specified by 'dev.' + * + * If 'needed_parts' is non-zero, this function makes sure that any + * of the parts speicified therein are allocated. + */ +XkbSrvLedInfoPtr +#if NeedFunctionPrototypes +XkbAllocSrvLedInfo( DeviceIntPtr dev, + KbdFeedbackPtr kf, + LedFeedbackPtr lf, + unsigned needed_parts) +#else +XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) + DeviceIntPtr dev; + KbdFeedbackPtr kf; + LedFeedbackPtr lf; + unsigned needed_parts; +#endif +{ +XkbSrvLedInfoPtr sli; +Bool checkAccel; +Bool checkNames; + + sli= NULL; + checkAccel= checkNames= False; + if ((kf!=NULL)&&(kf->xkb_sli==NULL)) { + kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= KbdFeedbackClass; + sli->id= kf->ctrl.id; + sli->fb.kf= kf; + + sli->autoState= 0; + sli->explicitState= kf->ctrl.leds; + sli->effectiveState= kf->ctrl.leds; + + if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->flags|= XkbSLI_IsDefault; + sli->physIndicators= xkb->indicators->phys_indicators; + sli->names= xkb->names->indicators; + sli->maps= xkb->indicators->maps; + checkNames= checkAccel= True; + } + else { + sli->physIndicators= XkbAllIndicatorsMask; + sli->names= NULL; + sli->maps= NULL; + } + } + else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) { + XkbDescPtr xkb; + xkb= dev->key->xkbInfo->desc; + sli->physIndicators= xkb->indicators->phys_indicators; + if (xkb->names->indicators!=sli->names) { + checkNames= True; + sli->names= xkb->names->indicators; + } + if (xkb->indicators->maps!=sli->maps) { + checkAccel= True; + sli->maps= xkb->indicators->maps; + } + } + else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) { + lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); + if (sli==NULL) + return NULL; /* ALLOCATION ERROR */ + if (dev->key && dev->key->xkbInfo) + sli->flags= XkbSLI_HasOwnState; + else sli->flags= 0; + sli->class= LedFeedbackClass; + sli->id= lf->ctrl.id; + sli->fb.lf= lf; + + sli->physIndicators= lf->ctrl.led_mask; + sli->autoState= 0; + sli->explicitState= lf->ctrl.led_values; + sli->effectiveState= lf->ctrl.led_values; + sli->maps= NULL; + sli->names= NULL; + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + if (checkNames) { + register unsigned i,bit; + sli->namesPresent= 0; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (sli->names[i]!=None) + sli->namesPresent|= bit; + } + } + if (checkAccel) + XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask); + return sli; +} + +void +#if NeedFunctionPrototypes +XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) +#else +XkbFreeSrvLedInfo(sli) + XkbSrvLedInfoPtr sli; +#endif +{ + if ((sli->flags&XkbSLI_IsDefault)==0) { + if (sli->maps) _XkbFree(sli->maps); + if (sli->names) _XkbFree(sli->names); + } + sli->maps= NULL; + sli->names= NULL; + _XkbFree(sli); + return; +} + + +/***====================================================================***/ + + /* + * XkbSrvLedInfoPtr + * XkbFindSrvLedInfo(dev,class,id,needed_parts) + * + * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' + * on the device specified by 'dev.' If the class and id specify + * a valid device feedback, this function returns the existing + * feedback or allocates a new one. + * + */ + +XkbSrvLedInfoPtr +#if NeedFunctionPrototypes +XkbFindSrvLedInfo( DeviceIntPtr dev, + unsigned class, + unsigned id, + unsigned needed_parts) +#else +XkbFindSrvLedInfo(dev,class,id,needed_parts) + DeviceIntPtr dev; + unsigned class; + unsigned id; + unsigned needed_parts; +#endif +{ +XkbSrvLedInfoPtr sli; + + /* optimization to check for most common case */ + if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) { + XkbSrvLedInfoPtr sli; + sli= dev->kbdfeed->xkb_sli; + if (dev->kbdfeed->xkb_sli==NULL) { + sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts); + dev->kbdfeed->xkb_sli= sli; + } + return dev->kbdfeed->xkb_sli; + } + + sli= NULL; + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else return NULL; + } + if (class==KbdFeedbackClass) { + KbdFeedbackPtr kf; + for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) { + if (kf->xkb_sli==NULL) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts); + sli= kf->xkb_sli; + break; + } + } + } + else if (class==LedFeedbackClass) { + LedFeedbackPtr lf; + for (lf=dev->leds;lf!=NULL;lf=lf->next) { + if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) { + if (lf->xkb_sli==NULL) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts); + sli= lf->xkb_sli; + break; + } + } + } + if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) + sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) + sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + return sli; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbFlushLedEvents( DeviceIntPtr dev, + DeviceIntPtr kbd, + XkbSrvLedInfoPtr sli, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause) + DeviceIntPtr dev; + DeviceIntPtr kbd; + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ + if (changes) { + if (changes->indicators.state_changes) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendNotification(kbd,changes,cause); + bzero((char *)changes,sizeof(XkbChangesRec)); + } + if (ed && (ed->reason)) { + if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask)) + XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); + XkbSendExtensionDeviceNotify(dev,cause->client,ed); + } + bzero((char *)ed,sizeof(XkbExtensionDeviceNotify)); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbApplyLedNameChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_names, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedNameChanges(dev,sli,changed_names,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_names; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_names==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->names.changed|= XkbIndicatorNamesMask; + changes->names.changed_indicators|= changed_names; + } + + ed->reason|= (XkbXI_IndicatorNamesMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorNamesMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} +/***====================================================================***/ + + /* + * void + * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) + * + * Handles all of the secondary effects of the changes to the + * feedback specified by 'sli' on the device specified by 'dev.' + * + * If 'changed_maps' specifies any indicators, this function generates + * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify + * events to report the changes, and recalculates the effective + * state of each indicator with a changed map. If any indicators + * change state, the server generates XkbExtensionDeviceNotify and + * XkbIndicatorStateNotify events as appropriate. + * + * If 'changes' is non-NULL, this function updates it to reflect + * any changes to the keyboard state or controls or to the 'core' + * indicator names, maps, or state. If 'changes' is NULL, this + * function generates XKB events as needed to report the changes. + * If 'dev' is not a keyboard device, any changes are reported + * for the core keyboard. + * + * The 'cause' specifies the reason for the event (key event or + * request) for the change, as reported in some XKB events. + */ + +void +#if NeedFunctionPrototypes +XkbApplyLedMapChanges( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_maps, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedMapChanges(dev,sli,changed_maps,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_maps; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; + + if (changed_maps==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.map_changes|= changed_maps; + } + + XkbCheckIndicatorMaps(dev,sli,changed_maps); + + ed->reason|= (XkbXI_IndicatorMapsMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorMapsMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbApplyLedStateChanges(DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned changed_leds, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbApplyLedStateChanges(dev,sli,changed_leds,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned changed_leds; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr kbd; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +XkbIndicatorMapPtr map; +unsigned oldState; +Bool kb_changed; + + if (changed_leds==0) + return; + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + xkbi= kbd->key->xkbInfo; + + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + + kb_changed= False; + affected= changed_leds; + oldState= sli->effectiveState; + for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { + if ((affected&bit)==0) + continue; + affected&= ~bit; + map= &sli->maps[i]; + if (map->flags&XkbIM_NoExplicit) { + sli->explicitState&= ~bit; + continue; + } + if (map->flags&XkbIM_LEDDrivesKB) { + Bool on= ((sli->explicitState&bit)!=0); + if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes)) + kb_changed= True; + } + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) + changes->indicators.state_changes|= affected; + if (affected) { + ed->reason|= (XkbXI_IndicatorStateMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + } + + if (kb_changed) { + XkbComputeDerivedState(kbd->key->xkbInfo); + XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause); + } + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + if (kb_changed) + XkbUpdateAllDeviceIndicators(NULL,cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbUpdateLedAutoState( DeviceIntPtr dev, + XkbSrvLedInfoPtr sli, + unsigned maps_to_check, + xkbExtensionDeviceNotify * ed, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbUpdateLedAutoState(dev,sli,maps_to_check,ed,changes,cause) + DeviceIntPtr dev; + XkbSrvLedInfoPtr sli; + unsigned maps_to_check; + xkbExtensionDeviceNotify * ed; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr kbd; +XkbStatePtr state; +XkbControlsPtr ctrls; +XkbChangesRec my_changes; +xkbExtensionDeviceNotify my_ed; +register unsigned i,bit,affected; +register XkbIndicatorMapPtr map; +unsigned oldState; + + if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0)) + return; + + if (dev->key && dev->key->xkbInfo) + kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + + state= &kbd->key->xkbInfo->state; + ctrls= kbd->key->xkbInfo->desc->ctrls; + affected= maps_to_check; + oldState= sli->effectiveState; + sli->autoState&= ~affected; + for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { + if ((affected&bit)==0) + continue; + affected&= ~bit; + map= &sli->maps[i]; + if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls)) + sli->autoState|= bit; + } + sli->effectiveState= (sli->autoState|sli->explicitState); + affected= sli->effectiveState^oldState; + if (affected==0) + return; + + if (ed==NULL) { + ed= &my_ed; + bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); + } + else if ((ed->reason&XkbXI_IndicatorsMask)&& + ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + } + + if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { + if (changes==NULL) { + changes= &my_changes; + bzero((char *)changes,sizeof(XkbChangesRec)); + } + changes->indicators.state_changes|= affected; + } + + ed->reason|= (XkbXI_IndicatorStateMask&(~XkbXIUnsupported)); + ed->ledClass= sli->class; + ed->ledID= sli->id; + ed->ledsDefined= sli->namesPresent|sli->mapsPresent; + ed->ledState= sli->effectiveState; + ed->unsupported|= XkbXIUnsupported&XkbXI_IndicatorStateMask; + ed->supported= XkbXI_AllFeaturesMask&(~XkbXIUnsupported); + + if (changes!=&my_changes) changes= NULL; + if (ed!=&my_ed) ed= NULL; + if (changes || ed) + XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); + return; +} + +/***====================================================================***/ + +static void +#if NeedFunctionPrototypes +_UpdateButtonVMods( XkbDescPtr xkb, + unsigned num_btns, + XkbAction * acts, + unsigned changed, + xkbExtensionDeviceNotify * ed_inout) +#else +_UpdateButtonVMods(xkb,num_btns,acts,changed,ed_inout) + XkbDescPtr xkb; + unsigned num_btns; + XkbAction * acts; + unsigned changed; + xkbExtensionDeviceNotify * ed_inout; +#endif +{ +register int i; + + for (i=0;i<num_btns;i++,acts++) { + if ((acts->any.type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,acts,changed)) { + if ((ed_inout->reason&XkbXI_ButtonActionsMask)==0) { + ed_inout->reason|= XkbXI_ButtonActionsMask; + ed_inout->firstBtn= i; + ed_inout->nBtns= 1; + } + else { + ed_inout->nBtns= (i-ed_inout->firstBtn)+1; + } + } + } + return; +} + +static void +#if NeedFunctionPrototypes +_UpdateMapVMods( XkbDescPtr xkb, + register XkbIndicatorMapPtr map, + unsigned changed_vmods, + unsigned * changed_maps_rtrn) +#else +_UpdateMapVMods(xkb,map,changed_vmods,changed_maps_rtrn) + XkbDescPtr xkb; + register XkbIndicatorMapPtr map; + unsigned changed_vmods; + unsigned * changed_maps_rtrn; +#endif +{ +register int i; + + *changed_maps_rtrn= 0; + for (i=0;i<XkbNumIndicators;i++,map++) { + if (map->mods.vmods&changed_vmods) { + map->mods.mask= map->mods.real_mods; + map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); + *changed_maps_rtrn|= (1L<<i); + } + } + return; +} + +static void +#if NeedFunctionPrototypes +_UpdateDeviceVMods( DeviceIntPtr dev, + XkbDescPtr xkb, + unsigned changed, + XkbEventCausePtr cause) +#else +_UpdateDeviceVMods(dev,xkb,changed,cause) + DeviceIntPtr dev; + XkbDescPtr xkb; + unsigned changed; + XkbEventCausePtr cause; +#endif +{ +xkbExtensionDeviceNotify ed; +XkbSrvLedInfoPtr sli; +unsigned changed_maps; + + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + if ((dev->button)&&(dev->button->xkb_acts)) { + _UpdateButtonVMods(xkb,dev->button->numButtons, + dev->button->xkb_acts,changed,&ed); + } + if (dev->kbdfeed) { + KbdFeedbackPtr kf; + for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { + if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) + continue; + sli= kf->xkb_sli; + _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps); + if (changed_maps) { + if (ed.reason&XkbXI_IndicatorsMask) { + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + ed.reason= 0; + ed.firstBtn= ed.nBtns; + } + ed.ledClass= sli->class; + ed.ledID= sli->id; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.reason|= XkbXI_IndicatorMapsMask; + XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause); + } + } + } + if (dev->leds) { + LedFeedbackPtr lf; + for (lf=dev->leds;lf!=NULL;lf=lf->next) { + if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) + continue; + sli= lf->xkb_sli; + _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps); + if (changed_maps) { + if (ed.reason&XkbXI_IndicatorsMask) { + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + ed.reason= 0; + ed.firstBtn= ed.nBtns; + } + ed.ledClass= sli->class; + ed.ledID= sli->id; + ed.ledsDefined= sli->namesPresent|sli->mapsPresent; + ed.reason|= XkbXI_IndicatorMapsMask; + XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause); + } + } + } + if (ed.reason!=0) + XkbSendExtensionDeviceNotify(dev,NULL,&ed); + return; +} + +void +#if NeedFunctionPrototypes +XkbApplyVModChangesToAllDevices( DeviceIntPtr dev, + XkbDescPtr xkb, + unsigned changed, + XkbEventCausePtr cause) +#else +XkbApplyVModChangesToAllDevices(dev,xkb,changed,cause) + DeviceIntPtr dev; + XkbDescPtr xkb; + unsigned changed; + XkbEventCausePtr cause; +#endif +{ +DeviceIntPtr edev; + if (dev!=(DeviceIntPtr)LookupKeyboardDevice()) + return; + for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { + if (edev->key) + continue; + _UpdateDeviceVMods(edev,xkb,changed,cause); + } + for (edev=inputInfo.off_devices;edev!=NULL;edev=edev->next) { + if (edev->key) + continue; + _UpdateDeviceVMods(edev,xkb,changed,cause); + } + return; +} diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c new file mode 100644 index 000000000..907cc3ab5 --- /dev/null +++ b/xkb/xkbPrKeyEv.c @@ -0,0 +1,193 @@ +/* $Xorg: xkbPrKeyEv.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include <ctype.h> + + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +#else +XkbProcessKeyboardEvent(xE,keybd,count) + xEvent * xE; + DeviceIntPtr keybd; + int count; +#endif +{ +KeyClassPtr keyc = keybd->key; +XkbSrvInfoPtr xkbi; +int key; +XkbBehavior behavior; + + xkbi= keyc->xkbInfo; + key= xE->u.u.detail; +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + ErrorF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + } +#endif + + if ( (xkbi->repeatKey==key) && (xE->u.u.type==KeyRelease) && + ((xkbi->desc->ctrls->enabled_ctrls&XkbRepeatKeysMask)==0) ) { + AccessXCancelRepeatKey(xkbi,key); + } + + behavior= xkbi->desc->server->behaviors[key]; + /* The "permanent" flag indicates a hard-wired behavior that occurs */ + /* below XKB, such as a key that physically locks. XKB does not */ + /* do anything to implement the behavior, but it *does* report that */ + /* key is hardwired */ + if ((behavior.type&XkbKB_Permanent)==0) { + switch (behavior.type) { + case XkbKB_Default: + if (( xE->u.u.type == KeyPress ) && + (keyc->down[key>>3] & (1<<(key&7)))) { + XkbLastRepeatEvent= (pointer)xE; + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + else if ((xE->u.u.type==KeyRelease) && + (!(keyc->down[key>>3]&(1<<(key&7))))) { + XkbLastRepeatEvent= (pointer)&xE; + xE->u.u.type = KeyPress; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + XkbLastRepeatEvent= NULL; + return; + } + break; + case XkbKB_Lock: + if ( xE->u.u.type == KeyRelease ) + return; + else { + int bit= 1<<(key&7); + if ( keyc->down[key>>3]&bit ) + xE->u.u.type= KeyRelease; + } + break; + case XkbKB_RadioGroup: + if ( xE->u.u.type == KeyRelease ) + return; + else { + unsigned ndx= (behavior.data&(~XkbKB_RGAllowNone)); + if ( ndx<xkbi->nRadioGroups ) { + XkbRadioGroupPtr rg; + + rg = &xkbi->radioGroups[ndx]; + if ( rg->currentDown == xE->u.u.detail ) { + if (behavior.data&XkbKB_RGAllowNone) { + xE->u.u.type = KeyRelease; + XkbHandleActions(keybd,keybd,xE,count); + rg->currentDown= 0; + } + return; + } + if ( rg->currentDown!=0 ) { + int key = xE->u.u.detail; + xE->u.u.type= KeyRelease; + xE->u.u.detail= rg->currentDown; + XkbHandleActions(keybd,keybd,xE,count); + xE->u.u.type= KeyPress; + xE->u.u.detail= key; + } + rg->currentDown= key; + } + else ErrorF("InternalError! Illegal radio group %d\n",ndx); + } + break; + case XkbKB_Overlay1: case XkbKB_Overlay2: + { + unsigned which; + if (behavior.type==XkbKB_Overlay1) which= XkbOverlay1Mask; + else which= XkbOverlay2Mask; + if ( (xkbi->desc->ctrls->enabled_ctrls&which)==0 ) + break; + if ((behavior.data>=xkbi->desc->min_key_code)&& + (behavior.data<=xkbi->desc->max_key_code)) { + xE->u.u.detail= behavior.data; + /* 9/11/94 (ef) -- XXX! need to match release with */ + /* press even if the state of the */ + /* corresponding overlay control */ + /* changes while the key is down */ + } + } + break; + default: + ErrorF("unknown key behavior 0x%04x\n",behavior.type); + break; + } + } + XkbHandleActions(keybd,keybd,xE,count); + return; +} + +void +#if NeedFunctionPrototypes +ProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) +#else +ProcessKeyboardEvent(xE,keybd,count) + xEvent * xE; + DeviceIntPtr keybd; + int count; +#endif +{ +KeyClassPtr keyc = keybd->key; +XkbSrvInfoPtr xkbi; + + xkbi= keyc->xkbInfo; + +#ifdef DEBUG + if (xkbDebugFlags&0x8) { + int key= xE->u.u.detail; + ErrorF("PKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + } +#endif + if ((xkbi->desc->ctrls->enabled_ctrls&XkbAllFilteredEventsMask)==0) + XkbProcessKeyboardEvent(xE,keybd,count); + else if (xE->u.u.type==KeyPress) + AccessXFilterPressEvent(xE,keybd,count); + else if (xE->u.u.type==KeyRelease) + AccessXFilterReleaseEvent(xE,keybd,count); + return; +} + diff --git a/xkb/xkbPrOtherEv.c b/xkb/xkbPrOtherEv.c new file mode 100644 index 000000000..fd24283f5 --- /dev/null +++ b/xkb/xkbPrOtherEv.c @@ -0,0 +1,88 @@ +/* $Xorg: xkbPrOtherEv.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +Copyright (c) 1995 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. + +********************************************************/ + +#include <stdio.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" + +#include "XI.h" +#include "XIproto.h" + +extern void ProcessOtherEvent( +#if NeedFunctionPrototypes + xEvent * /* xE */, + DeviceIntPtr /* dev */, + int /* count */ +#endif +); + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbProcessOtherEvent(xEvent *xE,DeviceIntPtr dev,int count) +#else +XkbProcessOtherEvent(xE,dev,count) + xEvent * xE; + DeviceIntPtr dev; + int count; +#endif +{ +Bool xkbCares,isBtn; + + xkbCares= True; + isBtn= False; + switch ( xE->u.u.type ) { + case KeyPress: xE->u.u.type= DeviceKeyPress; break; + case KeyRelease: xE->u.u.type= DeviceKeyRelease; break; + case ButtonPress: xE->u.u.type= DeviceButtonPress; + isBtn= True; + break; + case ButtonRelease: xE->u.u.type= DeviceButtonRelease; + isBtn= True; + break; + default: xkbCares= False; break; + } + if (xkbCares) { + if ((!isBtn)||((dev->button)&&(dev->button->xkb_acts))) { + DeviceIntPtr kbd; + if (dev->key) kbd= dev; + else kbd= (DeviceIntPtr)LookupKeyboardDevice(); + XkbHandleActions(dev,kbd,xE,count); + return; + } + } + ProcessOtherEvent(xE,dev,count); + return; +} + diff --git a/xkb/xkbSwap.c b/xkb/xkbSwap.c new file mode 100644 index 000000000..c9df88f7f --- /dev/null +++ b/xkb/xkbSwap.c @@ -0,0 +1,759 @@ +/* $Xorg: xkbSwap.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include "stdio.h" +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "XKBsrv.h" +#include "XKBstr.h" +#include "extnsionst.h" + +#if NeedFunctionPrototypes +#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr) +#else +#define PROC_EXTERN(pfunc) extern int pfunc() +#endif + +PROC_EXTERN(ProcXkbUseExtension); +PROC_EXTERN(ProcXkbSelectEvents); +PROC_EXTERN(ProcXkbBell); +PROC_EXTERN(ProcXkbGetState); +PROC_EXTERN(ProcXkbLatchLockState); +PROC_EXTERN(ProcXkbGetControls); +PROC_EXTERN(ProcXkbSetControls); +PROC_EXTERN(ProcXkbGetMap); +PROC_EXTERN(ProcXkbSetMap); +PROC_EXTERN(ProcXkbGetCompatMap); +PROC_EXTERN(ProcXkbSetCompatMap); +PROC_EXTERN(ProcXkbGetIndicatorState); +PROC_EXTERN(ProcXkbGetIndicatorMap); +PROC_EXTERN(ProcXkbSetIndicatorMap); +PROC_EXTERN(ProcXkbGetNamedIndicator); +PROC_EXTERN(ProcXkbSetNamedIndicator); +PROC_EXTERN(ProcXkbGetNames); +PROC_EXTERN(ProcXkbSetNames); +PROC_EXTERN(ProcXkbGetGeometry); +PROC_EXTERN(ProcXkbSetGeometry); +PROC_EXTERN(ProcXkbPerClientFlags); +PROC_EXTERN(ProcXkbListComponents); +PROC_EXTERN(ProcXkbGetKbdByName); +PROC_EXTERN(ProcXkbGetDeviceInfo); +PROC_EXTERN(ProcXkbSetDeviceInfo); +PROC_EXTERN(ProcXkbSetDebuggingFlags); + + /* + * REQUEST SWAPPING + */ +static int +#if NeedFunctionPrototypes +SProcXkbUseExtension(ClientPtr client) +#else +SProcXkbUseExtension(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbUseExtensionReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + swaps(&stuff->wantedMajor,n); + swaps(&stuff->wantedMinor,n); + return ProcXkbUseExtension(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSelectEvents(ClientPtr client) +#else +SProcXkbSelectEvents(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSelectEventsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectWhich,n); + swaps(&stuff->clear,n); + swaps(&stuff->selectAll,n); + swaps(&stuff->affectMap,n); + swaps(&stuff->map,n); + if (stuff->affectWhich&(~XkbMapNotifyMask)!=0) { + union { + BOOL *b; + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if (((bit&maskLeft)==0)||(ndx==XkbMapNotify)) + continue; + maskLeft&= ~bit; + if ((stuff->selectAll&bit)||(stuff->clear&bit)) + continue; + switch (ndx) { + case XkbNewKeyboardNotify: + case XkbStateNotify: + case XkbNamesNotify: + case XkbAccessXNotify: + case XkbExtensionDeviceNotify: + size= 2; + break; + case XkbControlsNotify: + case XkbIndicatorStateNotify: + case XkbIndicatorMapNotify: + size= 4; + break; + case XkbBellNotify: + case XkbActionMessage: + case XkbCompatMapNotify: + size= 1; + break; + default: + client->errorValue = _XkbErrCode2(0x1,bit); + return BadValue; + } + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + swaps(&from.c16[0],n); + swaps(&from.c16[1],n); + } + else if (size==4) { + swapl(from.c32[0],n); + swapl(from.c32[1],n); + } + else { + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + if (dataLeft>2) { + ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + } + return ProcXkbSelectEvents(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbBell(ClientPtr client) +#else +SProcXkbBell(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbBellReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbBellReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->bellClass,n); + swaps(&stuff->bellID,n); + swapl(&stuff->name,n); + swapl(&stuff->window,n); + swaps(&stuff->pitch,n); + swaps(&stuff->duration,n); + return ProcXkbBell(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetState(ClientPtr client) +#else +SProcXkbGetState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbLatchLockState(ClientPtr client) +#else +SProcXkbLatchLockState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbLatchLockStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->groupLatch,n); + return ProcXkbLatchLockState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetControls(ClientPtr client) +#else +SProcXkbGetControls(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetControls(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetControls(ClientPtr client) +#else +SProcXkbSetControls(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetControlsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->affectInternalVMods,n); + swaps(&stuff->internalVMods,n); + swaps(&stuff->affectIgnoreLockVMods,n); + swaps(&stuff->ignoreLockVMods,n); + swaps(&stuff->axOptions,n); + swapl(&stuff->affectEnabledCtrls,n); + swapl(&stuff->enabledCtrls,n); + swapl(&stuff->changeCtrls,n); + swaps(&stuff->repeatDelay,n); + swaps(&stuff->repeatInterval,n); + swaps(&stuff->slowKeysDelay,n); + swaps(&stuff->debounceDelay,n); + swaps(&stuff->mkDelay,n); + swaps(&stuff->mkInterval,n); + swaps(&stuff->mkTimeToMax,n); + swaps(&stuff->mkMaxSpeed,n); + swaps(&stuff->mkCurve,n); + swaps(&stuff->axTimeout,n); + swapl(&stuff->axtCtrlsMask,n); + swapl(&stuff->axtCtrlsValues,n); + swaps(&stuff->axtOptsMask,n); + swaps(&stuff->axtOptsValues,n); + return ProcXkbSetControls(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetMap(ClientPtr client) +#else +SProcXkbGetMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->full,n); + swaps(&stuff->partial,n); + swaps(&stuff->virtualMods,n); + return ProcXkbGetMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetMap(ClientPtr client) +#else +SProcXkbSetMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->present,n); + swaps(&stuff->flags,n); + swaps(&stuff->totalSyms,n); + swaps(&stuff->totalActs,n); + swaps(&stuff->virtualMods,n); + return ProcXkbSetMap(client); +} + + +static int +#if NeedFunctionPrototypes +SProcXkbGetCompatMap(ClientPtr client) +#else +SProcXkbGetCompatMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbGetCompatMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetCompatMap(ClientPtr client) +#else +SProcXkbSetCompatMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetCompatMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->firstSI,n); + swaps(&stuff->nSI,n); + return ProcXkbSetCompatMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetIndicatorState(ClientPtr client) +#else +SProcXkbGetIndicatorState(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetIndicatorStateReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + swaps(&stuff->deviceSpec,n); + return ProcXkbGetIndicatorState(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetIndicatorMap(ClientPtr client) +#else +SProcXkbGetIndicatorMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetIndicatorMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetIndicatorMap(ClientPtr client) +#else +SProcXkbSetIndicatorMap(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetIndicatorMapReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbSetIndicatorMap(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetNamedIndicator(ClientPtr client) +#else +SProcXkbGetNamedIndicator(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + return ProcXkbGetNamedIndicator(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetNamedIndicator(ClientPtr client) +#else +SProcXkbSetNamedIndicator(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetNamedIndicatorReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + swapl(&stuff->indicator,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->ctrls,n); + return ProcXkbSetNamedIndicator(client); +} + + +static int +#if NeedFunctionPrototypes +SProcXkbGetNames(ClientPtr client) +#else +SProcXkbGetNames(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetNamesReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->which,n); + return ProcXkbGetNames(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetNames(ClientPtr client) +#else +SProcXkbSetNames(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetNamesReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->virtualMods,n); + swapl(&stuff->which,n); + swapl(&stuff->indicators,n); + swaps(&stuff->totalKTLevelNames,n); + return ProcXkbSetNames(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetGeometry(ClientPtr client) +#else +SProcXkbGetGeometry(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + return ProcXkbGetGeometry(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetGeometry(ClientPtr client) +#else +SProcXkbSetGeometry(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetGeometryReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->name,n); + swaps(&stuff->widthMM,n); + swaps(&stuff->heightMM,n); + swaps(&stuff->nProperties,n); + swaps(&stuff->nColors,n); + swaps(&stuff->nDoodads,n); + swaps(&stuff->nKeyAliases,n); + return ProcXkbSetGeometry(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbPerClientFlags(ClientPtr client) +#else +SProcXkbPerClientFlags(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbPerClientFlagsReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + swaps(&stuff->deviceSpec,n); + swapl(&stuff->change,n); + swapl(&stuff->value,n); + swapl(&stuff->ctrlsToChange,n); + swapl(&stuff->autoCtrls,n); + swapl(&stuff->autoCtrlValues,n); + return ProcXkbPerClientFlags(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbListComponents(ClientPtr client) +#else +SProcXkbListComponents(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbListComponentsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->maxNames,n); + return ProcXkbListComponents(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetKbdByName(ClientPtr client) +#else +SProcXkbGetKbdByName(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetKbdByNameReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->want,n); + swaps(&stuff->need,n); + return ProcXkbGetKbdByName(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbGetDeviceInfo(ClientPtr client) +#else +SProcXkbGetDeviceInfo(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbGetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->wanted,n); + swaps(&stuff->ledClass,n); + swaps(&stuff->ledID,n); + return ProcXkbGetDeviceInfo(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetDeviceInfo(ClientPtr client) +#else +SProcXkbSetDeviceInfo(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetDeviceInfoReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + swaps(&stuff->deviceSpec,n); + swaps(&stuff->change,n); + swaps(&stuff->nDeviceLedFBs,n); + return ProcXkbSetDeviceInfo(client); +} + +static int +#if NeedFunctionPrototypes +SProcXkbSetDebuggingFlags(ClientPtr client) +#else +SProcXkbSetDebuggingFlags(client) + ClientPtr client; +#endif +{ +register int n; + + REQUEST(xkbSetDebuggingFlagsReq); + + swaps(&stuff->length,n); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + swapl(&stuff->affectFlags,n); + swapl(&stuff->flags,n); + swapl(&stuff->affectCtrls,n); + swapl(&stuff->ctrls,n); + swaps(&stuff->msgLength,n); + return ProcXkbSetDebuggingFlags(client); +} + +int +#if NeedFunctionPrototypes +SProcXkbDispatch (ClientPtr client) +#else +SProcXkbDispatch (client) + ClientPtr client; +#endif +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return SProcXkbUseExtension(client); + case X_kbSelectEvents: + return SProcXkbSelectEvents(client); + case X_kbBell: + return SProcXkbBell(client); + case X_kbGetState: + return SProcXkbGetState(client); + case X_kbLatchLockState: + return SProcXkbLatchLockState(client); + case X_kbGetControls: + return SProcXkbGetControls(client); + case X_kbSetControls: + return SProcXkbSetControls(client); + case X_kbGetMap: + return SProcXkbGetMap(client); + case X_kbSetMap: + return SProcXkbSetMap(client); + case X_kbGetCompatMap: + return SProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return SProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return SProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return SProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return SProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return SProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return SProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return SProcXkbGetNames(client); + case X_kbSetNames: + return SProcXkbSetNames(client); + case X_kbGetGeometry: + return SProcXkbGetGeometry(client); + case X_kbSetGeometry: + return SProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return SProcXkbPerClientFlags(client); + case X_kbListComponents: + return SProcXkbListComponents(client); + case X_kbGetKbdByName: + return SProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return SProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return SProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return SProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c new file mode 100644 index 000000000..05a817ba3 --- /dev/null +++ b/xkb/xkbUtils.c @@ -0,0 +1,1141 @@ +/* $Xorg: xkbUtils.c,v 1.3 2000/08/17 19:53:48 cpqbld Exp $ */ +/************************************************************ +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. + +********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#define NEED_EVENTS 1 +#include <X11/X.h> +#include <X11/Xproto.h> +#define XK_CYRILLIC +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" + +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "extensions/XKBgeom.h" + +#ifdef MODE_SWITCH +extern Bool noKME; /* defined in os/utils.c */ +#endif + + int XkbDisableLockActions = 0; + +/***====================================================================***/ + +#ifndef RETURN_SHOULD_REPEAT +#if (defined(__osf__) && defined(__alpha)) +#define RETURN_SHOULD_REPEAT 1 +#else +#define RETURN_SHOULD_REPEAT 0 +#endif +#endif + +/***====================================================================***/ + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupAnyDevice(int id,int *why_rtrn) +#else +_XkbLookupAnyDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + dev= (DeviceIntPtr)LookupKeyboardDevice(); + if ((id==XkbUseCoreKbd)||(dev->id==id)) + return dev; + + dev= (DeviceIntPtr)LookupPointerDevice(); + if ((id==XkbUseCorePtr)||(dev->id==id)) + return dev; + + if (id&(~0xff)) + dev = NULL; + + dev= (DeviceIntPtr)LookupDevice(id); + if (dev!=NULL) + return dev; + if ((!dev)&&(why_rtrn)) + *why_rtrn= XkbErr_BadDevice; + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupKeyboard(int id,int *why_rtrn) +#else +_XkbLookupKeyboard(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->key)||(!dev->key->xkbInfo)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupBellDevice(int id,int *why_rtrn) +#else +_XkbLookupBellDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->kbdfeed)&&(!dev->bell)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupLedDevice(int id,int *why_rtrn) +#else +_XkbLookupLedDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if ((!dev->kbdfeed)&&(!dev->leds)) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +DeviceIntPtr +#if NeedFunctionPrototypes +_XkbLookupButtonDevice(int id,int *why_rtrn) +#else +_XkbLookupButtonDevice(id,why_rtrn) + int id; + int *why_rtrn; +#endif +{ +DeviceIntPtr dev = NULL; + + if ((dev= _XkbLookupAnyDevice(id,why_rtrn))==NULL) + return NULL; + else if (!dev->button) { + if (why_rtrn) + *why_rtrn= XkbErr_BadClass; + return NULL; + } + return dev; +} + +void +#if NeedFunctionPrototypes +XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +#else +XkbSetActionKeyMods(xkb,act,mods) + XkbDescPtr xkb; + XkbAction * act; + unsigned mods; +#endif +{ +register unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) + act->mods.mask|= XkbMaskForVMask(xkb,tmp); + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) + act->iso.mask|= XkbMaskForVMask(xkb,tmp); + break; + } + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask) +#else +XkbMaskForVMask(xkb,vmask) + XkbDescPtr xkb; + unsigned vmask; +#endif +{ +register int i,bit; +register unsigned mask; + + for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (vmask&bit) + mask|= xkb->server->vmods[i]; + } + return mask; +} + + +Bool +#if NeedFunctionPrototypes +XkbApplyVModChanges( XkbSrvInfoPtr xkbi, + unsigned changed, + XkbChangesPtr changes, + unsigned * needChecksRtrn, + XkbEventCausePtr cause) +#else +XkbApplyVModChanges(xkbi,changed,changes,needChecksRtrn,cause) + XkbSrvInfoPtr xkbi; + unsigned changed; + XkbChangesPtr changes; + unsigned * needChecksRtrn; + XkbEventCausePtr cause; +#endif +{ +XkbDescPtr xkb; +Bool check; + + xkb= xkbi->desc; +#ifdef DEBUG +{ +register unsigned i,bit; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if ((changed&bit)==0) + continue; + if (xkbDebugFlags) + ErrorF("Should be applying: change vmod %d to 0x%x\n",i, + xkb->server->vmods[i]); + } +} +#endif + check= XkbApplyVirtualModChanges(xkb,changed,changes); + XkbApplyVModChangesToAllDevices(xkbi->device,xkb,changed,cause); + + if (needChecksRtrn!=NULL) { + if (check) + *needChecksRtrn= XkbStateNotifyMask|XkbIndicatorStateNotifyMask; + else *needChecksRtrn= 0; + } + else if (check) { + /* 7/12/95 (ef) -- XXX check compatibility and/or indicator state */ + } + return 1; +} + +/***====================================================================***/ + +#if NeedFunctionPrototypes +void +XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +#else +void +XkbUpdateKeyTypesFromCore(pXDev,first,num,changes) + DeviceIntPtr pXDev; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; +#endif +{ +XkbDescPtr xkb; +unsigned key,nG,explicit; +KeySymsPtr pCore; +int types[XkbNumKbdGroups]; +KeySym tsyms[XkbMaxSymsPerKey],*syms; +XkbMapChangesPtr mc; + + xkb= pXDev->key->xkbInfo->desc; +#ifdef NOTYET + if (first<xkb->min_key_code) { + if (first>=XkbMinLegalKeyCode) { + xkb->min_key_code= first; + /* 1/12/95 (ef) -- XXX! should zero out the new maps */ + changes->map.changed|= XkbKeycodesMask; +generate a NewKeyboard notify here? + } + } +#endif + if (first+num-1>xkb->max_key_code) { + /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */ + num= xkb->max_key_code-first+1; + } + + mc= (changes?(&changes->map):NULL); + + pCore= &pXDev->key->curKeySyms; + syms= &pCore->map[(first-xkb->min_key_code)*pCore->mapWidth]; + for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) { + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types, + tsyms); + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + } + if (changes->map.changed&XkbKeySymsMask) { + CARD8 oldLast,newLast; + oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1; + newLast = first+num-1; + + if (first<changes->map.first_key_sym) + changes->map.first_key_sym = first; + if (oldLast>newLast) + newLast= oldLast; + changes->map.num_key_syms = newLast-changes->map.first_key_sym+1; + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = num; + } + return; +} + +void +#if NeedFunctionPrototypes +XkbUpdateDescActions( XkbDescPtr xkb, + KeyCode first, + CARD8 num, + XkbChangesPtr changes) +#else +XkbUpdateDescActions(xkb,first,num,changes) + XkbDescPtr xkb; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; +#endif +{ +register unsigned key; + + for (key=first;key<(first+num);key++) { + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if (changes->map.changed&XkbVirtualModMapMask|XkbModifierMapMask) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bit&xkb->server->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes->map.changed&XkbVirtualModsMask) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + + if (changes->map.changed&XkbKeyActionsMask) { + CARD8 oldLast,newLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + newLast = first+num-1; + + if (first<changes->map.first_key_act) + changes->map.first_key_act = first; + if (newLast>oldLast) + newLast= oldLast; + changes->map.num_key_acts= newLast-changes->map.first_key_act+1; + } + else { + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act = first; + changes->map.num_key_acts = num; + } + return; +} + +#if NeedFunctionPrototypes +void +XkbUpdateActions( DeviceIntPtr pXDev, + KeyCode first, + CARD8 num, + XkbChangesPtr changes, + unsigned * needChecksRtrn, + XkbEventCausePtr cause) +#else +void +XkbUpdateActions(pXDev,first,num,changes,needChecksRtrn,cause) + DeviceIntPtr pXDev; + KeyCode first; + CARD8 num; + XkbChangesPtr changes; + unsigned * needChecksRtrn; + XkbEventCausePtr cause; +#endif +{ +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +CARD8 * repeat; + + if (needChecksRtrn) + *needChecksRtrn= 0; + xkbi= pXDev->key->xkbInfo; + xkb= xkbi->desc; + repeat= xkb->ctrls->per_key_repeat; + + if (pXDev->kbdfeed) + memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,32); + + XkbUpdateDescActions(xkb,first,num,changes); + + if ((pXDev->kbdfeed)&& + (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) { + memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, 32); + (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); + } + return; +} + +void +#if NeedFunctionPrototypes +XkbUpdateCoreDescription(DeviceIntPtr keybd,Bool resize) +#else +XkbUpdateCoreDescription(keybd,resize) + DeviceIntPtr keybd; + Bool resize; +#endif +{ +register int key,tmp; +int maxSymsPerKey,maxKeysPerMod; +int first,last,firstCommon,lastCommon; +XkbDescPtr xkb; +KeyClassPtr keyc; +CARD8 keysPerMod[XkbNumModifiers]; + + if (!keybd || !keybd->key || !keybd->key->xkbInfo) + return; + xkb= keybd->key->xkbInfo->desc; + keyc= keybd->key; + maxSymsPerKey= maxKeysPerMod= 0; + bzero(keysPerMod,sizeof(keysPerMod)); + memcpy(keyc->modifierMap,xkb->map->modmap,xkb->max_key_code+1); + if ((xkb->min_key_code==keyc->curKeySyms.minKeyCode)&& + (xkb->max_key_code==keyc->curKeySyms.maxKeyCode)) { + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else if (resize) { + keyc->curKeySyms.minKeyCode= xkb->min_key_code; + keyc->curKeySyms.maxKeyCode= xkb->max_key_code; + tmp= keyc->curKeySyms.mapWidth*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (!keyc->curKeySyms.map) + FatalError("Couldn't allocate keysyms\n"); + first= firstCommon= xkb->min_key_code; + last= lastCommon= xkb->max_key_code; + } + else { + if (xkb->min_key_code<keyc->curKeySyms.minKeyCode) { + first= xkb->min_key_code; + firstCommon= keyc->curKeySyms.minKeyCode; + } + else { + firstCommon= xkb->min_key_code; + first= keyc->curKeySyms.minKeyCode; + } + if (xkb->max_key_code>keyc->curKeySyms.maxKeyCode) { + lastCommon= keyc->curKeySyms.maxKeyCode; + last= xkb->max_key_code; + } + else { + lastCommon= xkb->max_key_code; + last= keyc->curKeySyms.maxKeyCode; + } + } + + /* determine sizes */ + for (key=first;key<=last;key++) { + if (XkbKeycodeInRange(xkb,key)) { + int nGroups; + int w; + nGroups= XkbKeyNumGroups(xkb,key); + tmp= 0; + if (nGroups>0) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<2) + tmp+= 2; + else tmp+= w; + } + if (nGroups>1) { + if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2) + tmp+= 2; + else tmp+= w; + } + if (nGroups>2) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index); + if (nGroups>3) + tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index); + if (tmp>maxSymsPerKey) + maxSymsPerKey= tmp; + } + if (_XkbCoreKeycodeInRange(keyc,key)) { + if (keyc->modifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + keysPerMod[i]++; + if (keysPerMod[i]>maxKeysPerMod) + maxKeysPerMod= keysPerMod[i]; + } + } + } + } + } + + if (maxKeysPerMod>0) { + tmp= maxKeysPerMod*XkbNumModifiers; + if (keyc->modifierKeyMap==NULL) + keyc->modifierKeyMap= (KeyCode *)Xcalloc(tmp); + else if (keyc->maxKeysPerModifier<maxKeysPerMod) + keyc->modifierKeyMap= (KeyCode *)Xrealloc(keyc->modifierKeyMap,tmp); + if (keyc->modifierKeyMap==NULL) + FatalError("Couldn't allocate modifierKeyMap in UpdateCore\n"); + bzero(keyc->modifierKeyMap,tmp); + } + else if ((keyc->maxKeysPerModifier>0)&&(keyc->modifierKeyMap!=NULL)) { + Xfree(keyc->modifierKeyMap); + keyc->modifierKeyMap= NULL; + } + keyc->maxKeysPerModifier= maxKeysPerMod; + + if (maxSymsPerKey>0) { + tmp= maxSymsPerKey*_XkbCoreNumKeys(keyc); + keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym); + if (keyc->curKeySyms.map==NULL) + FatalError("Couldn't allocate symbols map in UpdateCore\n"); + } + else if ((keyc->curKeySyms.mapWidth>0)&&(keyc->curKeySyms.map!=NULL)) { + _XkbFree(keyc->curKeySyms.map); + keyc->curKeySyms.map= NULL; + } + keyc->curKeySyms.mapWidth= maxSymsPerKey; + + bzero(keysPerMod,sizeof(keysPerMod)); + for (key=firstCommon;key<=lastCommon;key++) { + if (keyc->curKeySyms.map!=NULL) { + KeySym *pCore,*pXKB; + unsigned nGroups,groupWidth,n,nOut; + + nGroups= XkbKeyNumGroups(xkb,key); + n= (key-keyc->curKeySyms.minKeyCode)*maxSymsPerKey; + pCore= &keyc->curKeySyms.map[n]; + bzero(pCore,maxSymsPerKey*sizeof(KeySym)); + pXKB= XkbKeySymsPtr(xkb,key); + nOut= 2; + if (nGroups>0) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index); + if (groupWidth>0) pCore[0]= pXKB[0]; + if (groupWidth>1) pCore[1]= pXKB[1]; + for (n=2;n<groupWidth;n++) { + pCore[2+n]= pXKB[n]; + } + if (groupWidth>2) + nOut= groupWidth; + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + nOut+= 2; + if (nGroups>1) { + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); + if (groupWidth>0) pCore[2]= pXKB[0]; + if (groupWidth>1) pCore[3]= pXKB[1]; + for (n=2;n<groupWidth;n++) { + pCore[nOut+(n-2)]= pXKB[n]; + } + if (groupWidth>2) + nOut+= (groupWidth-2); + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + for (n=XkbGroup3Index;n<nGroups;n++) { + register int s; + groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); + for (s=0;s<groupWidth;s++) { + pCore[nOut++]= pXKB[s]; + } + pXKB+= XkbKeyGroupsWidth(xkb,key); + } + } + if (keyc->modifierMap[key]!=0) { + register unsigned bit,i,mask; + mask= keyc->modifierMap[key]; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + tmp= i*maxKeysPerMod+keysPerMod[i]; + keyc->modifierKeyMap[tmp]= key; + keysPerMod[i]++; + } + } + } + } +#ifdef MODE_SWITCH + /* Fix up any of the KME stuff if we changed the core description. + */ + if (!noKME) + HandleKeyBinding(keyc, &keyc->curKeySyms); +#endif + return; +} + +void +#if NeedFunctionPrototypes +XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) +#else +XkbSetRepeatKeys(pXDev,key,onoff) + DeviceIntPtr pXDev; + int key; + int onoff; +#endif +{ + if (pXDev && pXDev->key && pXDev->key->xkbInfo) { + xkbControlsNotify cn; + XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls; + XkbControlsRec old; + old = *ctrls; + + if (key== -1) { /* global autorepeat setting changed */ + if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask; + else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask; + } + else if (pXDev->kbdfeed) { + ctrls->per_key_repeat[key/8] = + pXDev->kbdfeed->ctrl.autoRepeats[key/8]; + } + + if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,True)) + XkbSendControlsNotify(pXDev,&cn); + } + return; +} + +#if NeedFunctionPrototypes +void +XkbApplyMappingChange( DeviceIntPtr kbd, + CARD8 request, + KeyCode firstKey, + CARD8 num, + ClientPtr client) +#else +void +XkbApplyMappingChange(kbd,request,firstKey,num,client) + DeviceIntPtr kbd; + CARD8 request; + KeyCode firstKey; + CARD8 num; + ClientPtr client; +#endif +{ +XkbEventCauseRec cause; +XkbChangesRec changes; +unsigned check; + + if (kbd->key->xkbInfo==NULL) + XkbInitDevice(kbd); + bzero(&changes,sizeof(XkbChangesRec)); + check= 0; + if (request==MappingKeyboard) { + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardMapping,client); + XkbUpdateKeyTypesFromCore(kbd,firstKey,num,&changes); + XkbUpdateActions(kbd,firstKey,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + else if (request==MappingModifier) { + XkbDescPtr xkb= kbd->key->xkbInfo->desc; + + XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); + + num = xkb->max_key_code-xkb->min_key_code+1; + memcpy(xkb->map->modmap,kbd->key->modifierMap,xkb->max_key_code+1); + + changes.map.changed|= XkbModifierMapMask; + changes.map.first_modmap_key= xkb->min_key_code; + changes.map.num_modmap_keys= num; + XkbUpdateActions(kbd,xkb->min_key_code,num,&changes,&check,&cause); + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + } + /* 3/26/94 (ef) -- XXX! Doesn't deal with input extension requests */ + XkbSendNotification(kbd,&changes,&cause); + return; +} + +void +#if NeedFunctionPrototypes +XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key) +#else +XkbDisableComputedAutoRepeats(dev,key) + DeviceIntPtr dev; + unsigned key; +#endif +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +xkbMapNotify mn; + + xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask; + bzero(&mn,sizeof(mn)); + mn.changed= XkbExplicitComponentsMask; + mn.firstKeyExplicit= key; + mn.nKeyExplicit= 1; + XkbSendMapNotify(dev,&mn); + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new) +#else +XkbStateChangedFlags(old,new) + XkbStatePtr old; + XkbStatePtr new; +#endif +{ +int changed; + + changed=(old->group!=new->group?XkbGroupStateMask:0); + changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0); + changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0); + changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0); + changed|=(old->mods!=new->mods?XkbModifierStateMask:0); + changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0); + changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0); + changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0); + changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0); + changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0); + if (old->compat_grab_mods!=new->compat_grab_mods) + changed|= XkbCompatGrabModsMask; + changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0); + if (old->compat_lookup_mods!=new->compat_lookup_mods) + changed|= XkbCompatLookupModsMask; + changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0); + return changed; +} + +void +#if NeedFunctionPrototypes +XkbComputeCompatState(XkbSrvInfoPtr xkbi) +#else +XkbComputeCompatState(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ +CARD16 grp_mask; +XkbStatePtr state= &xkbi->state; +XkbCompatMapPtr map; + + map= xkbi->desc->compat; + grp_mask= map->groups[state->group].mask; + state->compat_state = state->mods|grp_mask; + state->compat_lookup_mods= state->lookup_mods|grp_mask; + + if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask) + grp_mask= map->groups[state->base_group].mask; + state->compat_grab_mods= state->grab_mods|grp_mask; + return; +} + +unsigned +#if NeedFunctionPrototypes +XkbAdjustGroup(int group,XkbControlsPtr ctrls) +#else +XkbAdjustGroup(group,ctrls) + int group; + XkbControlsPtr ctrls; +#endif +{ +unsigned act; + + act= XkbOutOfRangeGroupAction(ctrls->groups_wrap); + if (group<0) { + while ( group < 0 ) { + if (act==XkbClampIntoRange) { + group= XkbGroup1Index; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group+= ctrls->num_groups; + } + } + } + else if (group>=ctrls->num_groups) { + if (act==XkbClampIntoRange) { + group= ctrls->num_groups-1; + } + else if (act==XkbRedirectIntoRange) { + int newGroup; + newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); + if (newGroup>=ctrls->num_groups) + group= XkbGroup1Index; + else group= newGroup; + } + else { + group%= ctrls->num_groups; + } + } + return group; +} + +void +#if NeedFunctionPrototypes +XkbComputeDerivedState(XkbSrvInfoPtr xkbi) +#else +XkbComputeDerivedState(xkbi) + XkbSrvInfoPtr xkbi; +#endif +{ +XkbStatePtr state= &xkbi->state; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +unsigned grp; + + state->mods= (state->base_mods|state->latched_mods); + state->mods|= state->locked_mods; + state->lookup_mods= state->mods&(~ctrls->internal.mask); + state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask); + state->grab_mods|= + (state->base_mods|state->latched_mods&ctrls->ignore_lock.mask); + + + grp= state->locked_group; + if (grp>=ctrls->num_groups) + state->locked_group= XkbAdjustGroup(grp,ctrls); + + grp= state->locked_group+state->base_group+state->latched_group; + if (grp>=ctrls->num_groups) + state->group= XkbAdjustGroup(grp,ctrls); + else state->group= grp; + XkbComputeCompatState(xkbi); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi, + unsigned which, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbCheckSecondaryEffects(xkbi,which,changes,cause) + XkbSrvInfoPtr xkbi; + unsigned which; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ + if (which&XkbStateNotifyMask) { + XkbStateRec old; + old= xkbi->state; + changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state); + XkbComputeDerivedState(xkbi); + } + if (which&XkbIndicatorStateNotifyMask) + XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,True,changes, + cause); + return; +} + +/***====================================================================***/ + +void +#if NeedFunctionPrototypes +XkbSetPhysicalLockingKey(DeviceIntPtr dev,unsigned key) +#else +XkbSetPhysicalLockingKey(dev,key) + DeviceIntPtr dev; + unsigned key; +#endif +{ +XkbDescPtr xkb; + + xkb= dev->key->xkbInfo->desc; + if ((key>=xkb->min_key_code) && (key<=xkb->max_key_code)) { + xkb->server->behaviors[key].type= XkbKB_Lock|XkbKB_Permanent; + } + else ErrorF("Internal Error! Bad XKB info in SetPhysicalLockingKey\n"); + return; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbEnableDisableControls( XkbSrvInfoPtr xkbi, + unsigned long change, + unsigned long newValues, + XkbChangesPtr changes, + XkbEventCausePtr cause) +#else +XkbEnableDisableControls(xkbi,change,newValues,changes,cause) + XkbSrvInfoPtr xkbi; + unsigned long change; + unsigned long newValues; + XkbChangesPtr changes; + XkbEventCausePtr cause; +#endif +{ +XkbControlsPtr ctrls; +unsigned old; +XkbSrvLedInfoPtr sli; + + ctrls= xkbi->desc->ctrls; + old= ctrls->enabled_ctrls; + ctrls->enabled_ctrls&= ~change; + ctrls->enabled_ctrls|= (change&newValues); + if (old==ctrls->enabled_ctrls) + return False; + if (cause!=NULL) { + xkbControlsNotify cn; + cn.numGroups= ctrls->num_groups; + cn.changedControls|= XkbControlsEnabledMask; + cn.enabledControls= ctrls->enabled_ctrls; + cn.enabledControlChanges= (ctrls->enabled_ctrls^old); + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(xkbi->device,&cn); + } + else { + /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/ + /* is non-zero, the controls in question changed already in "this" */ + /* request and this change merely undoes the previous one. By the */ + /* same token, we have to figure out whether or not ControlsEnabled */ + /* should be set or not in the changes structure */ + changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old); + if (changes->ctrls.enabled_ctrls_changes) + changes->ctrls.changed_ctrls|= XkbControlsEnabledMask; + else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask; + } + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(xkbi->device,sli->usesControls,True,changes,cause); + return True; +} + +/***====================================================================***/ + +#define MAX_TOC 16 + +XkbGeometryPtr +#if NeedFunctionPrototypes +XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree) +#else +XkbLookupNamedGeometry(dev,name,shouldFree) + DeviceIntPtr dev; + Atom name; + Bool * shouldFree; +#endif +{ +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbDescPtr xkb= xkbi->desc; + + *shouldFree= 0; + if (name==None) { + if (xkb->geom!=NULL) + return xkb->geom; + name= xkb->names->geometry; + } + if ((xkb->geom!=NULL)&&(xkb->geom->name==name)) + return xkb->geom; + else if ((name==xkb->names->geometry)&&(xkb->geom==NULL)) { + FILE *file= XkbDDXOpenConfigFile(XkbInitialMap,NULL,0); + if (file!=NULL) { + XkbFileInfo xkbFInfo; + xkmFileInfo finfo; + xkmSectionInfo toc[MAX_TOC],*entry; + bzero(&xkbFInfo,sizeof(xkbFInfo)); + xkbFInfo.xkb= xkb; + if (XkmReadTOC(file,&finfo,MAX_TOC,toc)) { + entry= XkmFindTOCEntry(&finfo,toc,XkmGeometryIndex); + if (entry!=NULL) + XkmReadFileSection(file,entry,&xkbFInfo,NULL); + } + fclose(file); + if (xkb->geom) { + *shouldFree= 0; + return xkb->geom; + } + } + } + *shouldFree= 1; + return NULL; +} + +void +#if NeedFunctionPrototypes +XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper) +#else +XkbConvertCase(sym, lower, upper) + register KeySym sym; + KeySym *lower; + KeySym *upper; +#endif +{ + *lower = sym; + *upper = sym; + switch(sym >> 8) { + case 0: /* Latin 1 */ + if ((sym >= XK_A) && (sym <= XK_Z)) + *lower += (XK_a - XK_A); + else if ((sym >= XK_a) && (sym <= XK_z)) + *upper -= (XK_a - XK_A); + else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + *lower += (XK_agrave - XK_Agrave); + else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) + *upper -= (XK_agrave - XK_Agrave); + else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) + *lower += (XK_oslash - XK_Ooblique); + else if ((sym >= XK_oslash) && (sym <= XK_thorn)) + *upper -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + } +} + + diff --git a/xkb/xkbconfig.c b/xkb/xkbconfig.c new file mode 100644 index 000000000..d2e67945e --- /dev/null +++ b/xkb/xkbconfig.c @@ -0,0 +1,1394 @@ +/* $Xorg: xkbconfig.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1995 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif + +#include <X11/Xfuncs.h> + +#include <X11/Xfuncs.h> + +#ifndef XKB_IN_SERVER + +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <X11/XKBlib.h> +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include <X11/keysym.h> +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#endif + +#include <X11/extensions/XKBconfig.h> + +/***====================================================================***/ + +#define XKBCF_MAX_STR_LEN 100 +static char _XkbCF_rtrn[XKBCF_MAX_STR_LEN+1]; + +static int +#if NeedFunctionPrototypes +ScanIdent(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) +#else +ScanIdent(file,ch,val_rtrn) + FILE * file; + int ch; + XkbCFScanResultPtr val_rtrn; +#endif +{ +register int i; +char * str; + + val_rtrn->str= str= _XkbCF_rtrn; + for (i=0;(isalpha(ch)||isdigit(ch)||(ch=='_'));ch=getc(file)) { + if (i<XKBCF_MAX_STR_LEN) + str[i++]= ch; + } + if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) + ungetc(ch,file); + str[i]= '\0'; + return XkbCF_Ident; +} + +static int +#if NeedFunctionPrototypes +ScanString(FILE *file,int quote,XkbCFScanResultPtr val_rtrn) +#else +ScanString(file,quote,val_rtrn) + FILE * file; + int quote; + XkbCFScanResultPtr val_rtrn; +#endif +{ +int ch,nInBuf; + + nInBuf = 0; + while ( ((ch=getc(file))!=EOF) && (ch!='\n') && (ch!=quote) ) { + if ( ch == '\\' ) { + if ((ch = getc(file))!=EOF) { + if ( ch=='n' ) ch = '\n'; + else if ( ch == 't' ) ch = '\t'; + else if ( ch == 'v' ) ch = '\v'; + else if ( ch == 'b' ) ch = '\b'; + else if ( ch == 'r' ) ch = '\r'; + else if ( ch == 'f' ) ch = '\f'; + else if ( ch == 'e' ) ch = '\033'; + else if ( ch == '0' ) { + int tmp,stop; + ch = stop = 0; + if (((tmp=getc(file))!=EOF) && (isdigit(tmp)) && + (tmp!='8') && (tmp!='9')) { + ch= (ch*8)+(tmp-'0'); + } + else { + stop= 1; + ungetc(tmp,file); + } + if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && + (tmp!='8') && (tmp!='9')) { + ch= (ch*8)+(tmp-'0'); + } + else { + stop= 1; + ungetc(tmp,file); + } + if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && + (tmp!='8') && (tmp!='9')) { + ch= (ch*8)+(tmp-'0'); + } + else { + stop= 1; + ungetc(tmp,file); + } + } + } + else return XkbCF_EOF; + } + + if ( nInBuf < XKBCF_MAX_STR_LEN-1 ) + _XkbCF_rtrn[nInBuf++] = ch; + } + if ( ch == quote ) { + _XkbCF_rtrn[nInBuf++] = '\0'; + val_rtrn->str= _XkbCF_rtrn; + return XkbCF_String; + } + return XkbCF_UnterminatedString; +} + +static int +#if NeedFunctionPrototypes +ScanInteger(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) +#else +ScanInteger(file,ch,val_rtrn) + FILE * file; + int ch; + XkbCFScanResultPtr val_rtrn; +#endif +{ +int i; + + if (isdigit(ch)) + ungetc(ch,file); + if (fscanf(file,"%i",&i)==1) { + val_rtrn->ival= i; + return XkbCF_Integer; + } + return XkbCF_Unknown; +} + +int +#if NeedFunctionPrototypes +XkbCFScan(FILE *file,XkbCFScanResultPtr val_rtrn,XkbConfigRtrnPtr rtrn) +#else +XkbCFScan(file,val_rtrn,rtrn) + FILE * file; + XkbCFScanResultPtr val_rtrn; + XkbConfigRtrnPtr rtrn; +#endif +{ +int ch; + + do { + ch= getc(file); + } while ((ch=='\t')||(ch==' ')); + if (isalpha(ch)) + return ScanIdent(file,ch,val_rtrn); + else if (isdigit(ch)) + return ScanInteger(file,ch,val_rtrn); + else if (ch=='"') + return ScanString(file,ch,val_rtrn); + else if (ch=='\n') { + rtrn->line++; + return XkbCF_EOL; + } + else if (ch==';') + return XkbCF_Semi; + else if (ch=='=') + return XkbCF_Equals; + else if (ch=='+') { + ch= getc(file); + if (ch=='=') + return XkbCF_PlusEquals; + if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) + ungetc(ch,file); + return XkbCF_Plus; + } + else if (ch=='-') { + ch= getc(file); + if (ch=='=') + return XkbCF_MinusEquals; + if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) + ungetc(ch,file); + return XkbCF_Minus; + } + else if (ch==EOF) + return XkbCF_EOF; + else if ((ch=='#')||((ch=='/')&&(getc(file)=='/'))) { + while ((ch!='\n')&&(ch!=EOF)) + ch= getc(file); + rtrn->line++; + return XkbCF_EOL; + } + return XkbCF_Unknown; +} + +/***====================================================================***/ + +#define _XkbCF_Illegal 0 +#define _XkbCF_Keymap 1 +#define _XkbCF_Keycodes 2 +#define _XkbCF_Geometry 3 +#define _XkbCF_PhysSymbols 4 +#define _XkbCF_Symbols 5 +#define _XkbCF_Types 6 +#define _XkbCF_CompatMap 7 + +#define _XkbCF_RulesFile 8 +#define _XkbCF_Model 9 +#define _XkbCF_Layout 10 +#define _XkbCF_Variant 11 +#define _XkbCF_Options 12 + +#define _XkbCF_InitialMods 13 +#define _XkbCF_InitialCtrls 14 + +#define _XkbCF_ClickVolume 15 +#define _XkbCF_BellVolume 16 +#define _XkbCF_BellPitch 17 +#define _XkbCF_BellDuration 18 +#define _XkbCF_RepeatDelay 19 +#define _XkbCF_RepeatInterval 20 +#define _XkbCF_SlowKeysDelay 21 +#define _XkbCF_DebounceDelay 22 +#define _XkbCF_MouseKeysDelay 23 +#define _XkbCF_MouseKeysInterval 24 +#define _XkbCF_MouseKeysTimeToMax 25 +#define _XkbCF_MouseKeysMaxSpeed 26 +#define _XkbCF_MouseKeysCurve 27 +#define _XkbCF_AccessXTimeout 28 +#define _XkbCF_AccessXTimeoutCtrlsOn 29 +#define _XkbCF_AccessXTimeoutCtrlsOff 30 +#define _XkbCF_AccessXTimeoutOptsOn 31 +#define _XkbCF_AccessXTimeoutOptsOff 32 + +#define _XkbCF_IgnoreLockMods 33 +#define _XkbCF_IgnoreGroupLock 34 +#define _XkbCF_InternalMods 35 + +#define _XkbCF_GroupsWrap 36 + +static Bool +#if NeedFunctionPrototypes +AddCtrlByName(XkbConfigRtrnPtr rtrn,char *name,unsigned long *ctrls_rtrn) +#else +AddCtrlByName(rtrn,name,ctrls_rtrn) + XkbConfigRtrnPtr rtrn; + char * name; + unsigned long * ctrls_rtrn; +#endif +{ + if ((_XkbStrCaseCmp(name,"repeat")==0)|| + (_XkbStrCaseCmp(name,"repeatkeys")==0)) + *ctrls_rtrn= XkbRepeatKeysMask; + else if (_XkbStrCaseCmp(name,"slowkeys")==0) + *ctrls_rtrn= XkbSlowKeysMask; + else if (_XkbStrCaseCmp(name,"bouncekeys")==0) + *ctrls_rtrn= XkbBounceKeysMask; + else if (_XkbStrCaseCmp(name,"stickykeys")==0) + *ctrls_rtrn= XkbStickyKeysMask; + else if (_XkbStrCaseCmp(name,"mousekeys")==0) + *ctrls_rtrn= XkbMouseKeysMask; + else if (_XkbStrCaseCmp(name,"mousekeysaccel")==0) + *ctrls_rtrn= XkbMouseKeysAccelMask; + else if (_XkbStrCaseCmp(name,"accessxkeys")==0) + *ctrls_rtrn= XkbAccessXKeysMask; + else if (_XkbStrCaseCmp(name,"accessxtimeout")==0) + *ctrls_rtrn= XkbAccessXTimeoutMask; + else if (_XkbStrCaseCmp(name,"accessxfeedback")==0) + *ctrls_rtrn= XkbAccessXFeedbackMask; + else if (_XkbStrCaseCmp(name,"audiblebell")==0) + *ctrls_rtrn= XkbAudibleBellMask; + else if (_XkbStrCaseCmp(name,"overlay1")==0) + *ctrls_rtrn= XkbOverlay1Mask; + else if (_XkbStrCaseCmp(name,"overlay2")==0) + *ctrls_rtrn= XkbOverlay2Mask; + else if (_XkbStrCaseCmp(name,"ignoregrouplock")==0) + *ctrls_rtrn= XkbIgnoreGroupLockMask; + else { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +AddAXTimeoutOptByName( XkbConfigRtrnPtr rtrn, + char * name, + unsigned short * opts_rtrn) +#else +AddAXTimeoutOptByName(rtrn,name,opts_rtrn) + XkbConfigRtrnPtr rtrn; + char * name; + unsigned short * opts_rtrn; +#endif +{ + if (_XkbStrCaseCmp(name,"slowkeyspress")==0) + *opts_rtrn= XkbAX_SKPressFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysaccept")==0) + *opts_rtrn= XkbAX_SKAcceptFBMask; + else if (_XkbStrCaseCmp(name,"feature")==0) + *opts_rtrn= XkbAX_FeatureFBMask; + else if (_XkbStrCaseCmp(name,"slowwarn")==0) + *opts_rtrn= XkbAX_SlowWarnFBMask; + else if (_XkbStrCaseCmp(name,"indicator")==0) + *opts_rtrn= XkbAX_IndicatorFBMask; + else if (_XkbStrCaseCmp(name,"stickykeys")==0) + *opts_rtrn= XkbAX_StickyKeysFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysrelease")==0) + *opts_rtrn= XkbAX_SKReleaseFBMask; + else if (_XkbStrCaseCmp(name,"slowkeysreject")==0) + *opts_rtrn= XkbAX_SKRejectFBMask; + else if (_XkbStrCaseCmp(name,"bouncekeysreject")==0) + *opts_rtrn= XkbAX_BKRejectFBMask; + else if (_XkbStrCaseCmp(name,"dumbbell")==0) + *opts_rtrn= XkbAX_DumbBellFBMask; + else { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + return True; +} + +XkbConfigUnboundModPtr +#if NeedFunctionPrototypes +XkbCFAddModByName( XkbConfigRtrnPtr rtrn, + int what, + char * name, + Bool merge, + XkbConfigUnboundModPtr last) +#else +XkbCFAddModByName(rtrn,what,name,merge,last) + XkbConfigRtrnPtr rtrn; + int what; + char * name; + Bool merge; + XkbConfigUnboundModPtr last; +#endif +{ + if (rtrn->num_unbound_mods>=rtrn->sz_unbound_mods) { + rtrn->sz_unbound_mods+= 5; + rtrn->unbound_mods= _XkbTypedRealloc(rtrn->unbound_mods, + rtrn->sz_unbound_mods, + XkbConfigUnboundModRec); + if (rtrn->unbound_mods==NULL) { + rtrn->error= XkbCF_BadAlloc; + return False; + } + } + if (last==NULL) { + last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; + last->what= what; + last->mods= 0; + last->vmods= 0; + last->merge= merge; + last->name= NULL; + } + if (_XkbStrCaseCmp(name,"shift")==0) + last->mods|= ShiftMask; + else if (_XkbStrCaseCmp(name,"lock")==0) + last->mods|= LockMask; + else if ((_XkbStrCaseCmp(name,"control")==0)|| + (_XkbStrCaseCmp(name,"ctrl")==0)) + last->mods|= ControlMask; + else if (_XkbStrCaseCmp(name,"mod1")==0) + last->mods|= Mod1Mask; + else if (_XkbStrCaseCmp(name,"mod2")==0) + last->mods|= Mod2Mask; + else if (_XkbStrCaseCmp(name,"mod3")==0) + last->mods|= Mod3Mask; + else if (_XkbStrCaseCmp(name,"mod4")==0) + last->mods|= Mod4Mask; + else if (_XkbStrCaseCmp(name,"mod5")==0) + last->mods|= Mod5Mask; + else { + if (last->name!=NULL) { + last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; + last->what= what; + last->mods= 0; + last->vmods= 0; + last->merge= merge; + last->name= NULL; + } + last->name= _XkbDupString(name); + } + return last; +} + +int +#if NeedFunctionPrototypes +XkbCFBindMods(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +XkbCFBindMods(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +register int n,v; +Atom name; +XkbConfigUnboundModPtr mod; +int missing; + + if (rtrn->num_unbound_mods<1) + return 0; + if ((xkb==NULL) || (xkb->names==NULL)) + return -1; + + missing= 0; + for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) { + if (mod->name!=NULL) { + name= XkbInternAtom(xkb->dpy,mod->name,True); + if (name==None) + continue; + for (v=0;v<XkbNumVirtualMods;v++) { + if (xkb->names->vmods[v]==name) { + mod->vmods= (1<<v); + _XkbFree(mod->name); + mod->name= NULL; + break; + } + } + if (mod->name!=NULL) + missing++; + } + } + return missing; +} + +Bool +#if NeedFunctionPrototypes +XkbCFApplyMods(XkbConfigRtrnPtr rtrn,int what,XkbConfigModInfoPtr info) +#else +XkbCFApplyMods(rtrn,what,info) + XkbConfigRtrnPtr rtrn; + int what; + XkbConfigModInfoPtr info; +#endif +{ +register int n; +XkbConfigUnboundModPtr mod; + + if (rtrn->num_unbound_mods<1) + return True; + + for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) { + if (mod->what!=what) + continue; + if (mod->merge==XkbCF_MergeRemove) { + info->mods_clear|= mod->mods; + info->vmods_clear|= mod->vmods; + } + else { + if (mod->merge==XkbCF_MergeSet) + info->replace= True; + info->mods|= mod->mods; + info->vmods|= mod->vmods; + } + if (mod->name==NULL) { + mod->what= _XkbCF_Illegal; + } + else { + mod->mods= 0; + mod->vmods= 0; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +DefaultParser( FILE * file, + XkbConfigFieldsPtr fields, + XkbConfigFieldPtr field, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn) +#else +DefaultParser(file,fields,field,xkb,rtrn) + FILE * file; + XkbConfigFieldsPtr fields; + XkbConfigFieldPtr field; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; +#endif +{ +int tok; +XkbCFScanResultRec val; +char ** str; +int merge; +unsigned long * ctrls; +unsigned short * opts; +int * pival; +int onoff; +XkbConfigUnboundModPtr last; +unsigned what; + + tok= XkbCFScan(file,&val,rtrn); + str= NULL; + onoff= 0; + pival= NULL; + switch (field->field_id) { + case _XkbCF_RulesFile: if (!str) str= &rtrn->rules_file; + case _XkbCF_Model: if (!str) str= &rtrn->model; + case _XkbCF_Layout: if (!str) str= &rtrn->layout; + case _XkbCF_Variant: if (!str) str= &rtrn->variant; + case _XkbCF_Options: if (!str) str= &rtrn->options; + case _XkbCF_Keymap: if (!str) str= &rtrn->keymap; + case _XkbCF_Keycodes: if (!str) str= &rtrn->keycodes; + case _XkbCF_Geometry: if (!str) str= &rtrn->geometry; + case _XkbCF_PhysSymbols:if (!str) str= &rtrn->phys_symbols; + case _XkbCF_Symbols: if (!str) str= &rtrn->symbols; + case _XkbCF_Types: if (!str) str= &rtrn->types; + case _XkbCF_CompatMap: if (!str) str= &rtrn->compat; + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_String)&&(tok!=XkbCF_Ident)) { + rtrn->error= XkbCF_ExpectedString; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + if (*str!=NULL) + _XkbFree(*str); + *str= _XkbDupString(val.str); + break; + case _XkbCF_InitialMods: + case _XkbCF_IgnoreLockMods: + case _XkbCF_InternalMods: + what= XkbCF_InitialMods; + if (field->field_id==_XkbCF_InitialMods) + rtrn->defined|= (what=XkbCF_InitialMods); + else if (field->field_id==_XkbCF_InternalMods) + rtrn->defined|= (what=XkbCF_InternalMods); + else if (field->field_id==_XkbCF_IgnoreLockMods) + rtrn->defined|= (what=XkbCF_IgnoreLockMods); + if (tok==XkbCF_Equals) merge= XkbCF_MergeSet; + else if (tok==XkbCF_MinusEquals) merge= XkbCF_MergeRemove; + else if (tok==XkbCF_PlusEquals) merge= XkbCF_MergeAdd; + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedModifier; + return False; + } + last= NULL; + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedModifier; + return False; + } + last=XkbCFAddModByName(rtrn,what,val.str,merge,last); + if (last==NULL) + return False; + if (merge==XkbCF_MergeSet) + merge= XkbCF_MergeAdd; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_InitialCtrls: + rtrn->defined|= XkbCF_InitialCtrls; + opts= NULL; + ctrls= NULL; + if (tok==XkbCF_PlusEquals) + ctrls= &rtrn->initial_ctrls; + else if (tok==XkbCF_MinusEquals) + ctrls= &rtrn->initial_ctrls_clear; + else if (tok==XkbCF_Equals) { + ctrls= &rtrn->initial_ctrls; + rtrn->replace_initial_ctrls= True; + *ctrls= 0; + } + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + if (!AddCtrlByName(rtrn,val.str,ctrls)) { + return False; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_AccessXTimeoutCtrlsOn: + case _XkbCF_AccessXTimeoutCtrlsOff: + case _XkbCF_AccessXTimeoutOptsOff: + case _XkbCF_AccessXTimeoutOptsOn: + if (field->field_id==_XkbCF_AccessXTimeoutOptsOff) + field->field_id= _XkbCF_AccessXTimeoutCtrlsOff; + else if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOn) + field->field_id= _XkbCF_AccessXTimeoutCtrlsOn; + + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) + rtrn->defined|= XkbCF_AccessXTimeoutCtrlsOff; + else if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOn) + rtrn->defined|= XkbCF_AccessXTimeoutCtrlsOn; + + opts= NULL; + if (tok==XkbCF_MinusEquals) { + ctrls= &rtrn->axt_ctrls_ignore; + opts= &rtrn->axt_opts_ignore; + } + else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) { + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { + ctrls= &rtrn->axt_ctrls_off; + opts= &rtrn->axt_opts_off; + if (tok==XkbCF_Equals) + rtrn->replace_axt_ctrls_off= True; + } + else { + ctrls= &rtrn->axt_ctrls_on; + opts= &rtrn->axt_opts_on; + if (tok==XkbCF_Equals) + rtrn->replace_axt_ctrls_on= True; + } + *ctrls= 0; + } + else { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { + rtrn->error= XkbCF_ExpectedControl; + return False; + } + if (!AddCtrlByName(rtrn,val.str,ctrls)) { + if (!AddAXTimeoutOptByName(rtrn,val.str,opts)) + return False; + if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { + rtrn->defined|= XkbCF_AccessXTimeoutOptsOff; + if (rtrn->replace_axt_ctrls_off) + rtrn->replace_axt_opts_off= True; + } + else { + rtrn->defined|= XkbCF_AccessXTimeoutOptsOn; + if (rtrn->replace_axt_ctrls_on) + rtrn->replace_axt_opts_on= True; + } + } + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { + if (tok!=XkbCF_Plus) { + rtrn->error= XkbCF_ExpectedOperator; + return False; + } + tok= XkbCFScan(file,&val,rtrn); + } + } + break; + case _XkbCF_ClickVolume: + if (!pival) { + pival= &rtrn->click_volume; + onoff= 100; + } + case _XkbCF_BellVolume: + if (!pival) { + pival= &rtrn->bell_volume; + onoff= 100; + } + case _XkbCF_BellPitch: + if (!pival) + pival= &rtrn->bell_pitch; + case _XkbCF_BellDuration: + if (!pival) + pival= &rtrn->bell_duration; + case _XkbCF_RepeatDelay: + if (!pival) + pival= &rtrn->repeat_delay; + case _XkbCF_RepeatInterval: + if (!pival) + pival= &rtrn->repeat_interval; + case _XkbCF_SlowKeysDelay: + if (!pival) + pival= &rtrn->slow_keys_delay; + case _XkbCF_DebounceDelay: + if (!pival) + pival= &rtrn->debounce_delay; + case _XkbCF_MouseKeysDelay: + if (!pival) + pival= &rtrn->mk_delay; + case _XkbCF_MouseKeysInterval: + if (!pival) + pival= &rtrn->mk_interval; + case _XkbCF_MouseKeysTimeToMax: + if (!pival) + pival= &rtrn->mk_time_to_max; + case _XkbCF_MouseKeysMaxSpeed: + if (!pival) + pival= &rtrn->mk_max_speed; + case _XkbCF_MouseKeysCurve: + if (!pival) + pival= &rtrn->mk_curve; + case _XkbCF_AccessXTimeout: + if (!pival) + pival= &rtrn->ax_timeout; + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if (tok!=XkbCF_Integer) { + Bool ok= False; + if ((onoff)&&(tok==XkbCF_Ident)&&(val.str!=NULL)) { + if (_XkbStrCaseCmp(val.str,"on")) { + val.ival= onoff; + ok= True; + } + else if (_XkbStrCaseCmp(val.str,"off")) { + val.ival= 0; + ok= True; + } + } + if (!ok) { + rtrn->error= XkbCF_ExpectedInteger; + goto BAILOUT; + } + } + *pival= val.ival; + rtrn->defined|= XkbCF_AccessXTimeout; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + break; + case _XkbCF_GroupsWrap: + if (tok!=XkbCF_Equals) { + rtrn->error= XkbCF_MissingEquals; + goto BAILOUT; + } + tok= XkbCFScan(file,&val,rtrn); + if (tok==XkbCF_Ident) { + if (_XkbStrCaseCmp(val.str,"wrap")==0) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbWrapIntoRange,0); + } + else if (_XkbStrCaseCmp(val.str,"clamp")==0) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbClampIntoRange,0); + } + else { + rtrn->error= XkbCF_ExpectedOORGroupBehavior; + return False; + } + } + else if ((tok==XkbCF_Integer)&&(XkbIsLegalGroup(val.ival-1))) { + rtrn->groups_wrap= XkbSetGroupInfo(0,XkbRedirectIntoRange, + val.ival-1); + } + else { + rtrn->error= XkbCF_ExpectedOORGroupBehavior; + return False; + } + rtrn->defined|= XkbCF_GroupsWrap; + tok= XkbCFScan(file,&val,rtrn); + if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { + rtrn->error= XkbCF_ExpectedEOS; + return False; + } + break; + default: + rtrn->error= XkbCF_ExpectedInteger; + goto BAILOUT; + + } + return True; +BAILOUT: + return False; +} + +static Bool +#if NeedFunctionPrototypes +DefaultCleanUp(XkbConfigRtrnPtr rtrn) +#else +DefaultCleanUp(rtrn) + XkbConfigRtrnPtr rtrn; +#endif +{ + if (rtrn->keymap) _XkbFree(rtrn->keymap); + if (rtrn->keycodes) _XkbFree(rtrn->keycodes); + if (rtrn->geometry) _XkbFree(rtrn->geometry); + if (rtrn->phys_symbols) _XkbFree(rtrn->phys_symbols); + if (rtrn->symbols) _XkbFree(rtrn->symbols); + if (rtrn->types) _XkbFree(rtrn->types); + if (rtrn->compat) _XkbFree(rtrn->compat); + rtrn->keycodes= rtrn->geometry= NULL; + rtrn->symbols= rtrn->phys_symbols= NULL; + rtrn->types= rtrn->compat= NULL; + if ((rtrn->unbound_mods!=NULL)&&(rtrn->num_unbound_mods>0)) { + register int i; + for (i=0;i<rtrn->num_unbound_mods;i++) { + if (rtrn->unbound_mods[i].name!=NULL) { + _XkbFree(rtrn->unbound_mods[i].name); + rtrn->unbound_mods[i].name= NULL; + } + } + _XkbFree(rtrn->unbound_mods); + rtrn->sz_unbound_mods= 0; + rtrn->num_unbound_mods= 0; + rtrn->unbound_mods= NULL; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +DefaultApplyNames(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +DefaultApplyNames(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +char *str; + + if (XkbAllocNames(xkb,XkbComponentNamesMask,0,0)!=Success) + return False; + if ((str=rtrn->keycodes)!=NULL) { + xkb->names->keycodes= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->keycodes= NULL; + } + if ((str=rtrn->geometry)!=NULL) { + xkb->names->geometry= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->geometry= NULL; + } + if ((str=rtrn->symbols)!=NULL) { + xkb->names->symbols= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->symbols= NULL; + } + if ((str=rtrn->phys_symbols)!=NULL) { + xkb->names->phys_symbols= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->phys_symbols= NULL; + } + if ((str=rtrn->types)!=NULL) { + xkb->names->types= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->types= NULL; + } + if ((str=rtrn->compat)!=NULL) { + xkb->names->compat= XkbInternAtom(xkb->dpy,str,False); + _XkbFree(str); + rtrn->compat= NULL; + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +DefaultApplyControls(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) +#else +DefaultApplyControls(rtrn,xkb) + XkbConfigRtrnPtr rtrn; + XkbDescPtr xkb; +#endif +{ +unsigned on,off; +XkbControlsPtr ctrls; +unsigned int mask; + + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) + return False; + ctrls= xkb->ctrls; + if (rtrn->replace_initial_ctrls) + ctrls->enabled_ctrls= rtrn->initial_ctrls; + else ctrls->enabled_ctrls|= rtrn->initial_ctrls; + ctrls->enabled_ctrls&= ~rtrn->initial_ctrls_clear; + if (rtrn->internal_mods.replace) { + ctrls->internal.real_mods= rtrn->internal_mods.mods; + ctrls->internal.vmods= rtrn->internal_mods.vmods; + } + else { + ctrls->internal.real_mods&= ~rtrn->internal_mods.mods_clear; + ctrls->internal.vmods&= ~rtrn->internal_mods.vmods_clear; + ctrls->internal.real_mods|= rtrn->internal_mods.mods; + ctrls->internal.vmods|= rtrn->internal_mods.vmods; + } + mask= 0; + (void)XkbVirtualModsToReal(xkb,ctrls->internal.vmods,&mask); + ctrls->internal.mask= (ctrls->internal.real_mods|mask); + + if (rtrn->ignore_lock_mods.replace) { + ctrls->ignore_lock.real_mods= rtrn->ignore_lock_mods.mods; + ctrls->ignore_lock.vmods= rtrn->ignore_lock_mods.vmods; + } + else { + ctrls->ignore_lock.real_mods&= ~rtrn->ignore_lock_mods.mods_clear; + ctrls->ignore_lock.vmods&= ~rtrn->ignore_lock_mods.vmods_clear; + ctrls->ignore_lock.real_mods|= rtrn->ignore_lock_mods.mods; + ctrls->ignore_lock.vmods|= rtrn->ignore_lock_mods.vmods; + } + mask= 0; + (void)XkbVirtualModsToReal(xkb,ctrls->ignore_lock.vmods,&mask); + ctrls->ignore_lock.mask= (ctrls->ignore_lock.real_mods|mask); + + if (rtrn->repeat_delay>0) + ctrls->repeat_delay= rtrn->repeat_delay; + if (rtrn->repeat_interval>0) + ctrls->repeat_interval= rtrn->repeat_interval; + if (rtrn->slow_keys_delay>0) + ctrls->slow_keys_delay= rtrn->slow_keys_delay; + if (rtrn->debounce_delay>0) + ctrls->debounce_delay= rtrn->debounce_delay; + if (rtrn->mk_delay>0) + ctrls->mk_delay= rtrn->mk_delay; + if (rtrn->mk_interval>0) + ctrls->mk_interval= rtrn->mk_interval; + if (rtrn->mk_time_to_max>0) + ctrls->mk_time_to_max= rtrn->mk_time_to_max; + if (rtrn->mk_max_speed>0) + ctrls->mk_max_speed= rtrn->mk_max_speed; + if (rtrn->mk_curve>0) + ctrls->mk_curve= rtrn->mk_curve; + if (rtrn->defined&XkbCF_AccessXTimeout) + ctrls->ax_timeout= rtrn->ax_timeout; + + /* any value set to both off and on is reset to ignore */ + if ((off=(rtrn->axt_ctrls_on&rtrn->axt_ctrls_off))!=0) + rtrn->axt_ctrls_ignore|= off; + + /* ignore takes priority over on and off */ + rtrn->axt_ctrls_on&= ~rtrn->axt_ctrls_ignore; + rtrn->axt_ctrls_off&= ~rtrn->axt_ctrls_ignore; + + if (!rtrn->replace_axt_ctrls_off) { + off= (ctrls->axt_ctrls_mask&(~ctrls->axt_ctrls_values)); + off&= ~rtrn->axt_ctrls_on; + off|= rtrn->axt_ctrls_off; + } + else off= rtrn->axt_ctrls_off; + if (!rtrn->replace_axt_ctrls_on) { + on= (ctrls->axt_ctrls_mask&ctrls->axt_ctrls_values); + on&= ~rtrn->axt_ctrls_off; + on|= rtrn->axt_ctrls_on; + } + else on= rtrn->axt_ctrls_on; + ctrls->axt_ctrls_mask= (on|off)&~rtrn->axt_ctrls_ignore; + ctrls->axt_ctrls_values= on&~rtrn->axt_ctrls_ignore; + + /* any value set to both off and on is reset to ignore */ + if ((off=(rtrn->axt_opts_on&rtrn->axt_opts_off))!=0) + rtrn->axt_opts_ignore|= off; + + /* ignore takes priority over on and off */ + rtrn->axt_opts_on&= ~rtrn->axt_opts_ignore; + rtrn->axt_opts_off&= ~rtrn->axt_opts_ignore; + + if (rtrn->replace_axt_opts_off) { + off= (ctrls->axt_opts_mask&(~ctrls->axt_opts_values)); + off&= ~rtrn->axt_opts_on; + off|= rtrn->axt_opts_off; + } + else off= rtrn->axt_opts_off; + if (!rtrn->replace_axt_opts_on) { + on= (ctrls->axt_opts_mask&ctrls->axt_opts_values); + on&= ~rtrn->axt_opts_off; + on|= rtrn->axt_opts_on; + } + else on= rtrn->axt_opts_on; + ctrls->axt_opts_mask= (unsigned short)((on|off)&~rtrn->axt_ctrls_ignore); + ctrls->axt_opts_values= (unsigned short)(on&~rtrn->axt_ctrls_ignore); + + if (rtrn->defined&XkbCF_GroupsWrap) { + int n; + n= XkbNumGroups(ctrls->groups_wrap); + rtrn->groups_wrap= XkbSetNumGroups(rtrn->groups_wrap,n); + ctrls->groups_wrap= rtrn->groups_wrap; + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +DefaultFinish( XkbConfigFieldsPtr fields, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn, + int what) +#else +DefaultFinish(fields,xkb,rtrn,what) + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; + int what; +#endif +{ + if ((what==XkbCF_Destroy)||(what==XkbCF_CleanUp)) + return DefaultCleanUp(rtrn); + if (what==XkbCF_Check) { + if ((rtrn->symbols==NULL)&&(rtrn->phys_symbols!=NULL)) + rtrn->symbols= _XkbDupString(rtrn->phys_symbols); + } + if ((what==XkbCF_Apply)||(what==XkbCF_Check)) { + if (xkb && xkb->names && (rtrn->num_unbound_mods>0)) + XkbCFBindMods(rtrn,xkb); + XkbCFApplyMods(rtrn,XkbCF_InitialMods,&rtrn->initial_mods); + XkbCFApplyMods(rtrn,XkbCF_InternalMods,&rtrn->internal_mods); + XkbCFApplyMods(rtrn,XkbCF_IgnoreLockMods,&rtrn->ignore_lock_mods); + } + if (what==XkbCF_Apply) { + if (xkb!=NULL) { + DefaultApplyNames(rtrn,xkb); + DefaultApplyControls(rtrn,xkb); + XkbCFBindMods(rtrn,xkb); + } + } + return True; +} + +static XkbConfigFieldRec _XkbCFDfltFields[] = { + { "rules", _XkbCF_RulesFile }, + { "model", _XkbCF_Model }, + { "layout", _XkbCF_Layout }, + { "variant", _XkbCF_Variant }, + { "options", _XkbCF_Options }, + { "keymap", _XkbCF_Keymap }, + { "keycodes", _XkbCF_Keycodes }, + { "geometry", _XkbCF_Geometry }, + { "realsymbols",_XkbCF_PhysSymbols }, + { "actualsymbols",_XkbCF_PhysSymbols }, + { "symbols", _XkbCF_Symbols }, + { "symbolstouse",_XkbCF_Symbols }, + { "types", _XkbCF_Types }, + { "compat", _XkbCF_CompatMap }, + { "modifiers", _XkbCF_InitialMods }, + { "controls", _XkbCF_InitialCtrls }, + { "click", _XkbCF_ClickVolume }, + { "clickvolume",_XkbCF_ClickVolume }, + { "bell", _XkbCF_BellVolume }, + { "bellvolume", _XkbCF_BellVolume }, + { "bellpitch", _XkbCF_BellPitch }, + { "bellduration",_XkbCF_BellDuration }, + { "repeatdelay",_XkbCF_RepeatDelay }, + { "repeatinterval",_XkbCF_RepeatInterval }, + { "slowkeysdelay",_XkbCF_SlowKeysDelay }, + { "debouncedelay",_XkbCF_DebounceDelay }, + { "mousekeysdelay",_XkbCF_MouseKeysDelay }, + { "mousekeysinterval",_XkbCF_MouseKeysInterval }, + { "mousekeystimetomax",_XkbCF_MouseKeysTimeToMax }, + { "mousekeysmaxspeed",_XkbCF_MouseKeysMaxSpeed }, + { "mousekeyscurve",_XkbCF_MouseKeysCurve }, + { "accessxtimeout",_XkbCF_AccessXTimeout }, + { "axtimeout",_XkbCF_AccessXTimeout }, + { "accessxtimeoutctrlson",_XkbCF_AccessXTimeoutCtrlsOn }, + { "axtctrlson", _XkbCF_AccessXTimeoutCtrlsOn }, + { "accessxtimeoutctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, + { "axtctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, + { "ignorelockmods",_XkbCF_IgnoreLockMods }, + { "ignorelockmodifiers",_XkbCF_IgnoreLockMods }, + { "ignoregrouplock",_XkbCF_IgnoreGroupLock }, + { "internalmods",_XkbCF_InternalMods }, + { "internalmodifiers",_XkbCF_InternalMods }, + { "outofrangegroups",_XkbCF_GroupsWrap }, + { "groups", _XkbCF_GroupsWrap } +}; +#define _XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec)) + +static XkbConfigFieldsRec _XkbCFDflts = { + 0, /* cfg_id */ + _XkbCFNumDfltFields, /* num_fields */ + _XkbCFDfltFields, /* fields */ + DefaultParser, /* parser */ + DefaultFinish, /* finish */ + NULL, /* priv */ + NULL /* next */ +}; + +XkbConfigFieldsPtr XkbCFDflts= &_XkbCFDflts; + +/***====================================================================***/ + +XkbConfigFieldsPtr +#if NeedFunctionPrototypes +XkbCFDup(XkbConfigFieldsPtr fields) +#else +XkbCFDup(fields) + XkbConfigFieldsPtr fields; +#endif +{ +XkbConfigFieldsPtr pNew; + + pNew= _XkbTypedAlloc(XkbConfigFieldsRec); + if (pNew!=NULL) { + memcpy(pNew,fields,sizeof(XkbConfigFieldsRec)); + if ((pNew->fields!=NULL)&&(pNew->num_fields>0)) { + pNew->fields= _XkbTypedCalloc(pNew->num_fields,XkbConfigFieldRec); + if (pNew->fields) { + memcpy(fields->fields,pNew->fields, + (pNew->num_fields*sizeof(XkbConfigFieldRec))); + } + else { + _XkbFree(pNew); + return NULL; + } + } + else { + pNew->num_fields= 0; + pNew->fields= NULL; + } + pNew->next= NULL; + } + return pNew; +} + +XkbConfigFieldsPtr +#if NeedFunctionPrototypes +XkbCFFree(XkbConfigFieldsPtr fields,Bool all) +#else +XkbCFFree(fields,all) + XkbConfigFieldsPtr fields; + Bool all; +#endif +{ +XkbConfigFieldsPtr next; + + next= NULL; + while (fields!=NULL) { + next= fields->next; + if (fields!=XkbCFDflts) { + if (fields->fields) { + _XkbFree(fields->fields); + fields->fields= NULL; + fields->num_fields= 0; + } + _XkbFree(fields); + } + fields= (all?next:NULL); + } + return next; +} + +Bool +#if NeedFunctionPrototypes +XkbCFApplyRtrnValues( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb) +#else +XkbCFApplyRtrnValues(rtrn,fields,xkb) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; +#endif +{ +Bool ok; + + if ((fields==NULL)||(rtrn==NULL)||(xkb==NULL)) + return False; + for (ok=True;fields!=NULL;fields=fields->next) { + if (fields->finish!=NULL) + ok= (*fields->finish)(fields,xkb,rtrn,XkbCF_Apply)&&ok; + } + return ok; +} + +XkbConfigRtrnPrivPtr +#if NeedFunctionPrototypes +XkbCFAddPrivate( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XPointer ptr) +#else +XkbCFAddPrivate(rtrn,fields,ptr) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XPointer ptr; +#endif +{ +XkbConfigRtrnPrivPtr priv; + + if ((rtrn==NULL)||(fields==NULL)) + return NULL; + priv= _XkbTypedAlloc(XkbConfigRtrnPrivRec); + if (priv!=NULL) { + priv->cfg_id= fields->cfg_id; + priv->priv= ptr; + priv->next= rtrn->priv; + rtrn->priv= priv; + } + return priv; +} + +void +#if NeedFunctionPrototypes +XkbCFFreeRtrn( XkbConfigRtrnPtr rtrn, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb) +#else +XkbCFFreeRtrn(rtrn,fields,xkb) + XkbConfigRtrnPtr rtrn; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; +#endif +{ +XkbConfigRtrnPrivPtr tmp,next; + + if ((fields==NULL)||(rtrn==NULL)) + return; + while (fields!=NULL) { + if (fields->finish!=NULL) + (*fields->finish)(fields,xkb,rtrn,XkbCF_Destroy); + fields= fields->next; + } + for (tmp=rtrn->priv;tmp!=NULL;tmp=next) { + next= tmp->next; + bzero((char *)tmp,sizeof(XkbConfigRtrnPrivRec)); + _XkbFree(tmp); + } + bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); + return; +} + +Bool +#if NeedFunctionPrototypes +XkbCFParse( FILE * file, + XkbConfigFieldsPtr fields, + XkbDescPtr xkb, + XkbConfigRtrnPtr rtrn) +#else +XkbCFParse(file,fields,xkb,rtrn) + FILE * file; + XkbConfigFieldsPtr fields; + XkbDescPtr xkb; + XkbConfigRtrnPtr rtrn; +#endif +{ +int tok; +XkbCFScanResultRec val; +XkbConfigFieldsPtr tmp; + + if ((file==NULL)||(fields==NULL)||(rtrn==NULL)) + return False; + for (tok=0,tmp=fields;tmp!=NULL;tmp=tmp->next,tok++) { + fields->cfg_id= tok; + } + bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); + rtrn->line= 1; + rtrn->click_volume= -1; + rtrn->bell_volume= -1; + while ((tok=XkbCFScan(file,&val,rtrn))!=XkbCF_EOF) { + if (tok==XkbCF_Ident) { + Bool done; + for (tmp=fields,done=False;(tmp!=NULL)&&(!done);tmp=tmp->next) { + register int i; + XkbConfigFieldPtr f; + + for (i=0,f=tmp->fields;(i<tmp->num_fields)&&(!done);i++,f++) { + if (_XkbStrCaseCmp(val.str,f->field)!=0) + continue; + if ((*tmp->parser)(file,tmp,f,xkb,rtrn)) + done= True; + else goto BAILOUT; + } + } + } + else if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)) { + rtrn->error= XkbCF_MissingIdent; + goto BAILOUT; + } + } + for (tmp=fields;tmp!=NULL;tmp=tmp->next) { + if ((tmp->finish)&&(!(*tmp->finish)(tmp,xkb,rtrn,XkbCF_Check))) + goto BAILOUT; + } + return True; +BAILOUT: + for (tmp=fields;tmp!=NULL;tmp=tmp->next) { + if (tmp->finish) + (*tmp->finish)(tmp,xkb,rtrn,XkbCF_CleanUp); + } + return False; +} + +void +#if NeedFunctionPrototypes +XkbCFReportError(FILE *file,char *name,int error,int line) +#else +XkbCFReportError(file,name,error,line) + FILE * file; + char * name; + int error; + int line; +#endif +{ +char * msg; + + switch(error) { + case XkbCF_BadAlloc: + msg= "allocation failed\n"; break; + case XkbCF_UnterminatedString: + msg= "unterminated string on line %d"; break; + case XkbCF_MissingIdent: + msg= "expected identifier on line %d"; break; + case XkbCF_MissingEquals: + msg= "expected '=' on line %d"; break; + case XkbCF_ExpectedEOS: + msg= "expected ';' or newline on line %d"; break; + case XkbCF_ExpectedBoolean: + msg= "expected a boolean value on line %d"; break; + case XkbCF_ExpectedInteger: + msg= "expected a numeric value on line %d"; break; + case XkbCF_ExpectedString: + msg= "expected a string on line %d"; break; + case XkbCF_ExpectedModifier: + msg= "expected a modifier name on line %d"; break; + case XkbCF_ExpectedControl: + msg= "expected a control name on line %d"; break; + case XkbCF_ExpectedAXOption: + msg= "expected an AccessX option on line %d"; break; + case XkbCF_ExpectedOperator: + msg= "expected '+' or '-' on line %d"; break; + case XkbCF_ExpectedOORGroupBehavior: + msg= "expected wrap, clamp or group number on line %d"; break; + default: + msg= "unknown error on line %d"; break; + } + fprintf(file,msg,line); + if (name) fprintf(file," of %s\n",name); + else fprintf(file,"\n"); + return; +} diff --git a/xkb/xkberrs.c b/xkb/xkberrs.c new file mode 100644 index 000000000..41df420b8 --- /dev/null +++ b/xkb/xkberrs.c @@ -0,0 +1,70 @@ +/* $Xorg: xkberrs.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif +#include <X11/Xlib.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBfile.h> + +char * _XkbErrMessages[] = { + "success", /* _XkbSuccess */ + "key names not defined", /* _XkbErrMissingNames */ + "key types not defined", /* _XkbErrMissingTypes */ + "required key types not present", /* _XkbErrMissingReqTypes */ + "symbols not defined", /* _XkbErrMissingSymbols */ + "virtual modifier bindings not defined",/* _XkbErrMissingVMods */ + "indicators not defined", /* _XkbErrMissingIndicators */ + "compatibility map not defined", /* _XkbErrMissingCompatMap */ + "symbol interpretations not defined", /* _XkbErrMissingSymInterps */ + "geometry not defined", /* _XkbErrMissingGeometry */ + "illegal doodad type", /* _XkbErrIllegalDoodad */ + "illegal TOC type", /* _XkbErrIllegalTOCType */ + "illegal contents", /* _XkbErrIllegalContents */ + "empty file", /* _XkbErrEmptyFile */ + "file not found", /* _XkbErrFileNotFound */ + "cannot open", /* _XkbErrFileCannotOpen */ + "bad value", /* _XkbErrBadValue */ + "bad match", /* _XkbErrBadMatch */ + "illegal name for type", /* _XkbErrBadTypeName */ + "illegal width for type", /* _XkbErrBadTypeWidth */ + "bad file type", /* _XkbErrBadFileType */ + "bad file version", /* _XkbErrBadFileVersion */ + "error in Xkm file", /* _XkbErrBadFileFormat */ + "allocation failed", /* _XkbErrBadAlloc */ + "bad length", /* _XkbErrBadLength */ + "X request failed", /* _XkbErrXReqFailure */ + "not implemented" /* _XkbErrBadImplementation */ +}; + +unsigned _XkbErrCode; +char * _XkbErrLocation= NULL; +unsigned _XkbErrData; + diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c new file mode 100644 index 000000000..d07a704c3 --- /dev/null +++ b/xkb/xkbfmisc.c @@ -0,0 +1,716 @@ +/* $Xorg: xkbmisc.c,v 1.4 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1995 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif + +#define XK_CYRILLIC + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> + +#ifndef XKB_IN_SERVER + +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBgeom.h> +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include <X11/keysym.h> +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" +#include <X11/extensions/XKBgeom.h> + +#endif + +unsigned +#if NeedFunctionPrototypes +_XkbKSCheckCase(KeySym ks) +#else +_XkbKSCheckCase(ks) + KeySym ks; +#endif +{ +unsigned set,rtrn; +unsigned char ch; + + set= (ks & (~0xff)); + ch= (char)(ks&0xff); + rtrn= 0; + switch (set) { + case 0: /* latin 1 */ + if (((ch>=XK_A)&&(ch<=XK_Z))|| + ((ch>=XK_Agrave)&&(ch<=XK_THORN)&&(ch!=XK_multiply))) { + rtrn|= _XkbKSUpper; + } + if (((ch>=XK_a)&&(ch<=XK_z))|| + ((ch>=XK_agrave)&&(ch<=XK_ydiaeresis))) { + rtrn|= _XkbKSLower; + } + break; + } + return rtrn; +} + +/***===================================================================***/ + +int +#if NeedFunctionPrototypes +_XkbStrCaseCmp(char *str1,char *str2) +#else +_XkbStrCaseCmp(str1,str2) + char * str1; + char * str2; +#endif +{ + char buf1[512],buf2[512]; + char c, *s; + register int n; + + for (n=0, s = buf1; (c = *str1++); n++) { + if (isupper(c)) + c = tolower(c); + if (n>510) + break; + *s++ = c; + } + *s = '\0'; + for (n=0, s = buf2; (c = *str2++); n++) { + if (isupper(c)) + c = tolower(c); + if (n>510) + break; + *s++ = c; + } + *s = '\0'; + return (strcmp(buf1, buf2)); +} + +/***===================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbLookupGroupAndLevel( XkbDescPtr xkb, + int key, + int * mods_inout, + int * grp_inout, + int * lvl_rtrn) +#else +XkbLookupGroupAndLevel(xkb,key,mods_inout,grp_inout,lvl_rtrn) + XkbDescPtr xkb; + int key; + int * mods_inout; + int * grp_inout; + int * lvl_rtrn; +#endif +{ +int nG,eG; + + if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout)) + return False; + + nG= XkbKeyNumGroups(xkb,key); + eG= *grp_inout; + + if ( nG==0 ) { + *grp_inout= 0; + if (lvl_rtrn!=NULL) + *lvl_rtrn= 0; + return False; + } + else if ( nG==1 ) { + eG= 0; + } + else if ( eG>=nG ) { + unsigned gI= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(gI)) { + default: + eG %= nG; + break; + case XkbClampIntoRange: + eG = nG-1; + break; + case XkbRedirectIntoRange: + eG = XkbOutOfRangeGroupNumber(gI); + if (eG>=nG) + eG= 0; + break; + } + } + *grp_inout= eG; + if (mods_inout!=NULL) { + XkbKeyTypePtr type; + int preserve; + + type = XkbKeyKeyType(xkb,key,eG); + if (lvl_rtrn!=NULL) + *lvl_rtrn= 0; + preserve= 0; + if (type->map) { /* find the shift level */ + register int i; + register XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;i<type->map_count;i++,entry++) { + if ((entry->active)&& + (((*mods_inout)&type->mods.mask)==entry->mods.mask)){ + if (lvl_rtrn!=NULL) + *lvl_rtrn= entry->level; + if (type->preserve) + preserve= type->preserve[i].mask; + break; + } + } + } + (*mods_inout)&= ~(type->mods.mask&(~preserve)); + } + return True; +} + +/***===================================================================***/ + +static Bool +#if NeedFunctionPrototypes +XkbWriteSectionFromName(FILE *file,char *sectionName,char *name) +#else +XkbWriteSectionFromName(file,sectionName,name) + FILE * file; + char * sectionName; + char * name; +#endif +{ + fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name); + return True; +} + +#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) +#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) + +/* ARGSUSED */ +static void +#if NeedFunctionPrototypes +_AddIncl( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + int index, + void * priv) +#else +_AddIncl(file,result,topLevel,showImplicit,index,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + int index; + void * priv; +#endif +{ + if ((priv)&&(strcmp(priv,"%")!=0)) + fprintf(file," include \"%s\"\n",(char *)priv); + return; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeymapForNames( FILE * file, + XkbComponentNamesPtr names, + Display * dpy, + XkbDescPtr xkb, + unsigned want, + unsigned need) +#else +XkbWriteXKBKeymapForNames(file,names,dpy,xkb,want,need) + FILE * file; + XkbComponentNamesPtr names; + Display * dpy; + XkbDescPtr xkb; + unsigned want; + unsigned need; +#endif +{ +char * name,*tmp; +unsigned complete; +XkbNamesPtr old_names; +int multi_section; +unsigned wantNames,wantConfig,wantDflts; +XkbFileInfo finfo; + + bzero(&finfo,sizeof(XkbFileInfo)); + + complete= 0; + if ((name=names->keymap)==NULL) name= "default"; + if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; + if (COMPLETE(names->types)) complete|= XkmTypesMask; + if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; + if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; + if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; + want|= (complete|need); + if (want&XkmSymbolsMask) + want|= XkmKeyNamesMask|XkmTypesMask; + + if (want==0) + return False; + + if (xkb!=NULL) { + old_names= xkb->names; + finfo.type= 0; + finfo.defined= 0; + finfo.xkb= xkb; + if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL)) + return False; + } + else old_names= NULL; + + wantConfig= want&(~complete); + if (xkb!=NULL) { + if (wantConfig&XkmTypesMask) { + if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes)) + wantConfig&= ~XkmTypesMask; + } + if (wantConfig&XkmCompatMapMask) { + if ((!xkb->compat) || (xkb->compat->num_si<1)) + wantConfig&= ~XkmCompatMapMask; + } + if (wantConfig&XkmSymbolsMask) { + if ((!xkb->map) || (!xkb->map->key_sym_map)) + wantConfig&= ~XkmSymbolsMask; + } + if (wantConfig&XkmIndicatorsMask) { + if (!xkb->indicators) + wantConfig&= ~XkmIndicatorsMask; + } + if (wantConfig&XkmKeyNamesMask) { + if ((!xkb->names)||(!xkb->names->keys)) + wantConfig&= ~XkmKeyNamesMask; + } + if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) + wantConfig&= ~XkmGeometryMask; + } + else { + wantConfig= 0; + } + complete|= wantConfig; + + wantDflts= 0; + wantNames= want&(~complete); + if ((xkb!=NULL) && (old_names!=NULL)) { + if (wantNames&XkmTypesMask) { + if (old_names->types!=None) { + tmp= XkbAtomGetString(dpy,old_names->types); + names->types= _XkbDupString(tmp); + } + else { + wantDflts|= XkmTypesMask; + } + complete|= XkmTypesMask; + } + if (wantNames&XkmCompatMapMask) { + if (old_names->compat!=None) { + tmp= XkbAtomGetString(dpy,old_names->compat); + names->compat= _XkbDupString(tmp); + } + else wantDflts|= XkmCompatMapMask; + complete|= XkmCompatMapMask; + } + if (wantNames&XkmSymbolsMask) { + if (old_names->symbols==None) + return False; + tmp= XkbAtomGetString(dpy,old_names->symbols); + names->symbols= _XkbDupString(tmp); + complete|= XkmSymbolsMask; + } + if (wantNames&XkmKeyNamesMask) { + if (old_names->keycodes!=None) { + tmp= XkbAtomGetString(dpy,old_names->keycodes); + names->keycodes= _XkbDupString(tmp); + } + else wantDflts|= XkmKeyNamesMask; + complete|= XkmKeyNamesMask; + } + if (wantNames&XkmGeometryMask) { + if (old_names->geometry==None) + return False; + tmp= XkbAtomGetString(dpy,old_names->geometry); + names->geometry= _XkbDupString(tmp); + complete|= XkmGeometryMask; + wantNames&= ~XkmGeometryMask; + } + } + if (complete&XkmCompatMapMask) + complete|= XkmIndicatorsMask|XkmVirtualModsMask; + else if (complete&(XkmSymbolsMask|XkmTypesMask)) + complete|= XkmVirtualModsMask; + if (need & (~complete)) + return False; + if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) + return False; + + multi_section= 1; + if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& + ((complete&(~XkmKeymapLegal))==0)) { + fprintf(file,"xkb_keymap \"%s\" {\n",name); + } + else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& + ((complete&(~XkmSemanticsLegal))==0)) { + fprintf(file,"xkb_semantics \"%s\" {\n",name); + } + else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& + ((complete&(~XkmLayoutLegal))==0)) { + fprintf(file,"xkb_layout \"%s\" {\n",name); + } + else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { + multi_section= 0; + } + else { + return False; + } + + wantNames= complete&(~(wantConfig|wantDflts)); + name= names->keycodes; + if (wantConfig&XkmKeyNamesMask) + XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmKeyNamesMask) + fprintf(stderr,"Default symbols not implemented yet!\n"); + else if (wantNames&XkmKeyNamesMask) + XkbWriteSectionFromName(file,"keycodes",name); + + name= names->types; + if (wantConfig&XkmTypesMask) + XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmTypesMask) + fprintf(stderr,"Default types not implemented yet!\n"); + else if (wantNames&XkmTypesMask) + XkbWriteSectionFromName(file,"types",name); + + name= names->compat; + if (wantConfig&XkmCompatMapMask) + XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name); + else if (wantDflts&XkmCompatMapMask) + fprintf(stderr,"Default interps not implemented yet!\n"); + else if (wantNames&XkmCompatMapMask) + XkbWriteSectionFromName(file,"compatibility",name); + + name= names->symbols; + if (wantConfig&XkmSymbolsMask) + XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name); + else if (wantNames&XkmSymbolsMask) + XkbWriteSectionFromName(file,"symbols",name); + + name= names->geometry; + if (wantConfig&XkmGeometryMask) + XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name); + else if (wantNames&XkmGeometryMask) + XkbWriteSectionFromName(file,"geometry",name); + + if (multi_section) + fprintf(file,"};\n"); + return True; +} + +/***====================================================================***/ + +/*ARGSUSED*/ +Status +#if NeedFunctionPrototypes +XkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo) +#else +XkbMergeFile(xkb,finfo) + XkbDescPtr xkb; + XkbFileInfo *finfo; +#endif +{ + return BadImplementation; +} + +/***====================================================================***/ + +int +#if NeedFunctionPrototypes +XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) +#else +XkbFindKeycodeByName(xkb,name,use_aliases) + XkbDescPtr xkb; + char * name; + Bool use_aliases; +#endif +{ +register int i; + + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) + return 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) + return i; + } + if (!use_aliases) + return 0; + if (xkb->geom && xkb->geom->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->geom->key_aliases; + for (i=0;i<xkb->geom->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + if (xkb->names && xkb->names->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->names->key_aliases; + for (i=0;i<xkb->names->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,False); + } + } + return 0; +} + + +unsigned +#if NeedFunctionPrototypes +XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) +#else +XkbConvertGetByNameComponents(toXkm,orig) + Bool toXkm; + unsigned orig; +#endif +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; + if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; + if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; + if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; + if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; + if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; + if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; + if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; + } + return rtrn; +} + +unsigned +#if NeedFunctionPrototypes +XkbConvertXkbComponents(Bool toXkm,unsigned orig) +#else +XkbConvertXkbComponents(toXkm,orig) + Bool toXkm; + unsigned orig; +#endif +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbClientMapMask) rtrn|= XkmTypesMask|XkmSymbolsMask; + if (orig&XkbServerMapMask) rtrn|= XkmTypesMask|XkmSymbolsMask; + if (orig&XkbCompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbIndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig!=0) rtrn|= XkbNamesMask; + if (orig&XkmTypesMask) rtrn|= XkbClientMapMask; + if (orig&XkmCompatMapMask) + rtrn|= XkbCompatMapMask|XkbIndicatorMapMask; + if (orig&XkmSymbolsMask) rtrn|=XkbClientMapMask|XkbServerMapMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbIndicatorMapMask; + if (orig&XkmKeyNamesMask) + rtrn|= XkbNamesMask|XkbIndicatorMapMask; + if (orig&XkmGeometryMask) rtrn|= XkbGeometryMask; + } + return rtrn; +} + +Bool +#if NeedFunctionPrototypes +XkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing) +#else +XkbDetermineFileType(finfo,format,opts_missing) + XkbFileInfoPtr finfo; + int format; + int * opts_missing; +#endif +{ +unsigned present; +XkbDescPtr xkb; + + if ((!finfo)||(!finfo->xkb)) + return False; + if (opts_missing) + *opts_missing= 0; + xkb= finfo->xkb; + present= 0; + if ((xkb->names)&&(xkb->names->keys)) present|= XkmKeyNamesMask; + if ((xkb->map)&&(xkb->map->types)) present|= XkmTypesMask; + if (xkb->compat) present|= XkmCompatMapMask; + if ((xkb->map)&&(xkb->map->num_syms>1)) present|= XkmSymbolsMask; + if (xkb->indicators) present|= XkmIndicatorsMask; + if (xkb->geom) present|= XkmGeometryMask; + if (!present) + return False; + else switch (present) { + case XkmKeyNamesMask: + finfo->type= XkmKeyNamesIndex; + finfo->defined= present; + return True; + case XkmTypesMask: + finfo->type= XkmTypesIndex; + finfo->defined= present; + return True; + case XkmCompatMapMask: + finfo->type= XkmCompatMapIndex; + finfo->defined= present; + return True; + case XkmSymbolsMask: + if (format!=XkbXKMFile) { + finfo->type= XkmSymbolsIndex; + finfo->defined= present; + return True; + } + break; + case XkmGeometryMask: + finfo->type= XkmGeometryIndex; + finfo->defined= present; + return True; + } + if ((present&(~XkmSemanticsLegal))==0) { + if ((XkmSemanticsRequired&present)==XkmSemanticsRequired) { + if (opts_missing) + *opts_missing= XkmSemanticsOptional&(~present); + finfo->type= XkmSemanticsFile; + finfo->defined= present; + return True; + } + } + else if ((present&(~XkmLayoutLegal))==0) { + if ((XkmLayoutRequired&present)==XkmLayoutRequired) { + if (opts_missing) + *opts_missing= XkmLayoutOptional&(~present); + finfo->type= XkmLayoutFile; + finfo->defined= present; + return True; + } + } + else if ((present&(~XkmKeymapLegal))==0) { + if ((XkmKeymapRequired&present)==XkmKeymapRequired) { + if (opts_missing) + *opts_missing= XkmKeymapOptional&(~present); + finfo->type= XkmKeymapFile; + finfo->defined= present; + return True; + } + } + return False; +} + +/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */ +/* wildcards */ + +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +void +#if NeedFunctionPrototypes +XkbEnsureSafeMapName(char *name) +#else +XkbEnsureSafeMapName(name) + char *name; +#endif +{ + if (name==NULL) + return; + while (*name!='\0') { + if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0) + *name= '_'; + name++; + } + return; +} + +/***====================================================================***/ + +#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) + +Bool +#if NeedFunctionPrototypes +XkbNameMatchesPattern(char *name,char *ptrn) +#else +XkbNameMatchesPattern(name,ptrn) + char * name; + char * ptrn; +#endif +{ + while (ptrn[0]!='\0') { + if (name[0]=='\0') { + if (ptrn[0]=='*') { + ptrn++; + continue; + } + return False; + } + if (ptrn[0]=='?') { + if (UNMATCHABLE(name[0])) + return False; + } + else if (ptrn[0]=='*') { + if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) + return True; + return XkbNameMatchesPattern(name,ptrn+1); + } + else if (ptrn[0]!=name[0]) + return False; + name++; + ptrn++; + } + /* if we get here, the pattern is exhausted (-:just like me:-) */ + return (name[0]=='\0'); +} diff --git a/xkb/xkbout.c b/xkb/xkbout.c new file mode 100644 index 000000000..845325358 --- /dev/null +++ b/xkb/xkbout.c @@ -0,0 +1,1216 @@ +/* $Xorg: xkbout.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif +#include <X11/Xfuncs.h> + +#ifndef XKB_IN_SERVER + +#include <X11/Xlib.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBgeom.h> + +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include <X11/keysym.h> +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" + +#include <X11/extensions/XKBgeom.h> +#include "extensions/XKBfile.h" + +#endif + +#define VMOD_HIDE_VALUE 0 +#define VMOD_SHOW_VALUE 1 +#define VMOD_COMMENT_VALUE 2 + +static Bool +#if NeedFunctionPrototypes +WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue) +#else +WriteXKBVModDecl(file,dpy,xkb,showValue) + FILE * file; + Display * dpy; + XkbDescPtr xkb; + int showValue; +#endif +{ +register int i,nMods; +Atom * vmodNames; + + if (xkb==NULL) + return False; + if (xkb->names!=NULL) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + for (i=nMods=0;i<XkbNumVirtualMods;i++) { + if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) { + if (nMods==0) fprintf(file," virtual_modifiers "); + else fprintf(file,","); + fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile)); + if ((showValue!=VMOD_HIDE_VALUE)&& + (xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) { + if (showValue==VMOD_COMMENT_VALUE) { + fprintf(file,"/* = %s */", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + else { + fprintf(file,"= %s", + XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); + } + } + nMods++; + } + } + if (nMods>0) + fprintf(file,";\n\n"); + return True; +} + +/***====================================================================***/ + +static Bool +#if NeedFunctionPrototypes +WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action) +#else +WriteXKBAction(file,result,action) + FILE * file; + XkbFileInfo * result; + XkbAnyAction * action; +#endif +{ +XkbDescPtr xkb; +Display * dpy; + + xkb= result->xkb; + dpy= xkb->dpy; + fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile)); + return True; +} + +/***====================================================================***/ + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeycodes( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeycodes(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Atom kcName; +register unsigned i; +XkbDescPtr xkb; +Display * dpy; +char * alternate; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0); + return False; + } + kcName= xkb->names->keycodes; + if (kcName!=None) + fprintf(file,"xkb_keycodes \"%s\" {\n", + XkbAtomText(dpy,kcName,XkbXKBFile)); + else fprintf(file,"xkb_keycodes {\n"); + fprintf(file," minimum = %d;\n",xkb->min_key_code); + fprintf(file," maximum = %d;\n",xkb->max_key_code); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (xkb->names->keys[i].name[0]!='\0') { + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + alternate= "alternate "; + else alternate= ""; + fprintf(file," %s%6s = %d;\n",alternate, + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile), + i); + } + } + if (xkb->indicators!=NULL) { + for (i=0;i<XkbNumIndicators;i++) { + char *type; + if (xkb->indicators->phys_indicators&(1<<i)) + type= " "; + else type= " virtual "; + if (xkb->names->indicators[i]!=None) { + fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1, + XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile)); + } + } + } + if (xkb->names->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeyTypes( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeyTypes(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,n; +XkbKeyTypePtr type; +XkbKTMapEntryPtr entry; +XkbDescPtr xkb; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->map)||(!xkb->map->types)) { + _XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0); + return False; + } + if (xkb->map->num_types<XkbNumRequiredTypes) { + _XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0); + return 0; + } + if ((xkb->names==NULL)||(xkb->names->types==None)) + fprintf(file,"xkb_types {\n\n"); + else fprintf(file,"xkb_types \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->types,XkbXKBFile)); + WriteXKBVModDecl(file,dpy,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + type= xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + fprintf(file," type \"%s\" {\n", + XkbAtomText(dpy,type->name,XkbXKBFile)); + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods, + XkbXKBFile)); + entry= type->map; + for (n=0;n<type->map_count;n++,entry++) { + char *str; + str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods, + XkbXKBFile); + fprintf(file," map[%s]= Level%d;\n",str,entry->level+1); + if ((type->preserve)&&((type->preserve[n].real_mods)|| + (type->preserve[n].vmods))) { + fprintf(file," preserve[%s]= ",str); + fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb, + type->preserve[n].real_mods, + type->preserve[n].vmods, + XkbXKBFile)); + } + } + if (type->level_names!=NULL) { + Atom *name= type->level_names; + for (n=0;n<type->num_levels;n++,name++) { + if ((*name)==None) + continue; + fprintf(file," level_name[Level%d]= \"%s\";\n",n+1, + XkbAtomText(dpy,*name,XkbXKBFile)); + } + } + fprintf(file," };\n"); + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBIndicatorMap( FILE * file, + XkbFileInfo * result, + Atom name, + XkbIndicatorMapPtr led, + XkbFileAddOnFunc addOn, + void * priv) +#else +WriteXKBIndicatorMap(file,result,name,led,addOn,priv) + FILE * file; + XkbFileInfo * result; + Atom name; + XkbIndicatorMapPtr led; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file," indicator \"%s\" {\n",XkbAtomGetString(xkb->dpy,name)); + if (led->flags&XkbIM_NoExplicit) + fprintf(file," !allowExplicit;\n"); + if (led->flags&XkbIM_LEDDrivesKB) + fprintf(file," indicatorDrivesKeyboard;\n"); + if (led->which_groups!=0) { + if (led->which_groups!=XkbIM_UseEffective) { + fprintf(file," whichGroupState= %s;\n", + XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile)); + } + fprintf(file," groups= 0x%02x;\n",led->groups); + } + if (led->which_mods!=0) { + if (led->which_mods!=XkbIM_UseEffective) { + fprintf(file," whichModState= %s;\n", + XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile)); + } + fprintf(file," modifiers= %s;\n", + XkbVModMaskText(xkb->dpy,xkb, + led->mods.real_mods,led->mods.vmods, + XkbXKBFile)); + } + if (led->ctrls!=0) { + fprintf(file," controls= %s;\n", + XkbControlsMaskText(led->ctrls,XkbXKBFile)); + } + if (addOn) + (*addOn)(file,result,False,True,XkmIndicatorsIndex,priv); + fprintf(file," };\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBCompatMap( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBCompatMap(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i; +XkbSymInterpretPtr interp; +XkbDescPtr xkb; + + xkb= result->xkb; + dpy= xkb->dpy; + if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) { + _XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->compat==None)) + fprintf(file,"xkb_compatibility {\n\n"); + else fprintf(file,"xkb_compatibility \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->compat,XkbXKBFile)); + WriteXKBVModDecl(file,dpy,xkb, + (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); + + fprintf(file," interpret.useModMapMods= AnyLevel;\n"); + fprintf(file," interpret.repeat= False;\n"); + fprintf(file," interpret.locking= False;\n"); + interp= xkb->compat->sym_interpret; + for (i=0;i<xkb->compat->num_si;i++,interp++) { + fprintf(file," interpret %s+%s(%s) {\n", + ((interp->sym==NoSymbol)?"Any": + XkbKeysymText(interp->sym,XkbXKBFile)), + XkbSIMatchText(interp->match,XkbXKBFile), + XkbModMaskText(interp->mods,XkbXKBFile)); + if (interp->virtual_mod!=XkbNoModifier) { + fprintf(file," virtualModifier= %s;\n", + XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile)); + } + if (interp->match&XkbSI_LevelOneOnly) + fprintf(file," useModMapMods=level1;\n"); + if (interp->flags&XkbSI_LockingKey) + fprintf(file," locking= True;\n"); + if (interp->flags&XkbSI_AutoRepeat) + fprintf(file," repeat= True;\n"); + fprintf(file," action= "); + WriteXKBAction(file,result,&interp->act); + fprintf(file,";\n"); + fprintf(file," };\n"); + } + for (i=0;i<XkbNumKbdGroups;i++) { + XkbModsPtr gc; + + gc= &xkb->compat->groups[i]; + if ((gc->real_mods==0)&&(gc->vmods==0)) + continue; + fprintf(file," group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb, + gc->real_mods,gc->vmods, + XkbXKBFile)); + } + if (xkb->indicators) { + for (i=0;i<XkbNumIndicators;i++) { + XkbIndicatorMapPtr map= &xkb->indicators->maps[i]; + if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)|| + (map->which_mods!=0)|| + (map->mods.real_mods!=0)||(map->mods.vmods!=0)|| + (map->ctrls!=0)) { + WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map, + addOn,priv); + } + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBSymbols( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBSymbols(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,tmp; +XkbDescPtr xkb; +XkbClientMapPtr map; +XkbServerMapPtr srv; +Bool showActions; + + xkb= result->xkb; + map= xkb->map; + srv= xkb->server; + dpy= xkb->dpy; + if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) { + _XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0); + return False; + } + if ((!xkb->names)||(!xkb->names->keys)) { + _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0); + return False; + } + if ((xkb->names==NULL)||(xkb->names->symbols==None)) + fprintf(file,"xkb_symbols {\n\n"); + else fprintf(file,"xkb_symbols \"%s\" {\n\n", + XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile)); + for (tmp=i=0;i<XkbNumKbdGroups;i++) { + if (xkb->names->groups[i]!=None) { + fprintf(file," name[group%d]=\"%s\";\n",i+1, + XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile)); + tmp++; + } + } + if (tmp>0) + fprintf(file,"\n"); + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + Bool simple; + if ((int)XkbKeyNumSyms(xkb,i)<1) + continue; + if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) + continue; + simple= True; + fprintf(file," key %6s {", + XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile)); + if (srv->explicit) { + if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)|| + (showImplicit)) { + int typeNdx,g; + Bool multi; + char * comment=" "; + + if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0) + comment= "//"; + multi= False; + typeNdx= XkbKeyKeyTypeIndex(xkb,i,0); + for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) { + if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx) + multi= True; + } + if (multi) { + for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { + typeNdx= XkbKeyKeyTypeIndex(xkb,i,g); + if (srv->explicit[i]&(1<<g)) { + fprintf(file,"\n%s type[group%d]= \"%s\",", + comment,g+1, + XkbAtomText(dpy,map->types[typeNdx].name, + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// type[group%d]= \"%s\",",g+1, + XkbAtomText(dpy,map->types[typeNdx].name, + XkbXKBFile)); + } + } + } + else { + fprintf(file,"\n%s type= \"%s\",",comment, + XkbAtomText(dpy,map->types[typeNdx].name, + XkbXKBFile)); + } + simple= False; + } + if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&& + (xkb->ctrls!=NULL)) { + if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8))) + fprintf(file,"\n repeat= Yes,"); + else fprintf(file,"\n repeat= No,"); + simple= False; + } + if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&& + (xkb->server->vmodmap[i]!=0)) { + if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) { + fprintf(file,"\n virtualMods= %s,", + XkbVModMaskText(dpy,xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + else if (showImplicit) { + fprintf(file,"\n// virtualMods= %s,", + XkbVModMaskText(dpy,xkb,0, + xkb->server->vmodmap[i], + XkbXKBFile)); + } + } + } + switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) { + case XkbClampIntoRange: + fprintf(file,"\n groupsClamp,"); + break; + case XkbRedirectIntoRange: + fprintf(file,"\n groupsRedirect= Group%d,", + XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1); + break; + } + if (srv->behaviors!=NULL) { + unsigned type; + type= srv->behaviors[i].type&XkbKB_OpMask; + + if (type!=XkbKB_Default) { + simple= False; + fprintf(file,"\n %s,", + XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile)); + } + } + if ((srv->explicit==NULL) || showImplicit || + ((srv->explicit[i]&XkbExplicitInterpretMask)!=0)) + showActions= XkbKeyHasActions(xkb,i); + else showActions= False; + + if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions) + simple= False; + if (simple) { + KeySym *syms; + unsigned s; + + syms= XkbKeySymsPtr(xkb,i); + fprintf(file," [ "); + for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) { + if (s!=0) + fprintf(file,", "); + fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile)); + } + fprintf(file," ] };\n"); + } + else { + unsigned g,s; + KeySym *syms; + XkbAction *acts; + syms= XkbKeySymsPtr(xkb,i); + acts= XkbKeyActionsPtr(xkb,i); + for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { + if (g!=0) + fprintf(file,","); + fprintf(file,"\n symbols[Group%d]= [ ",g+1); + for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { + if (s!=0) + fprintf(file,", "); + fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile)); + } + fprintf(file," ]"); + syms+= XkbKeyGroupsWidth(xkb,i); + if (showActions) { + fprintf(file,",\n actions[Group%d]= [ ",g+1); + for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { + if (s!=0) + fprintf(file,", "); + WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]); + } + fprintf(file," ]"); + acts+= XkbKeyGroupsWidth(xkb,i); + } + } + fprintf(file,"\n };\n"); + } + } + if (map && map->modmap) { + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (map->modmap[i]!=0) { + register int n,bit; + for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) { + if (map->modmap[i]&bit) { + char buf[5]; + memcpy(buf,xkb->names->keys[i].name,4); + buf[4]= '\0'; + fprintf(file," modifier_map %s { <%s> };\n", + XkbModIndexText(n,XkbXKBFile),buf); + } + } + } + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBOutline( FILE * file, + XkbShapePtr shape, + XkbOutlinePtr outline, + int lastRadius, + int first, + int indent) +#else +WriteXKBOutline(file,shape,outline,lastRadius,first,indent) + FILE * file; + XkbShapePtr shape; + XkbOutlinePtr outline; + int lastRadius; + int first; + int indent; +#endif +{ +register int i; +XkbPointPtr pt; +char * iStr; + + fprintf(file,"%s",iStr= XkbIndentText(first)); + if (first!=indent) + iStr= XkbIndentText(indent); + if (outline->corner_radius!=lastRadius) { + fprintf(file,"corner= %s,", + XkbGeomFPText(outline->corner_radius,XkbMessage)); + if (shape!=NULL) { + fprintf(file,"\n%s",iStr); + } + } + if (shape) { + if (outline==shape->approx) + fprintf(file,"approx= "); + else if (outline==shape->primary) + fprintf(file,"primary= "); + } + fprintf(file,"{"); + for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) { + if (i==0) fprintf(file," "); + else if ((i%4)==0) fprintf(file,",\n%s ",iStr); + else fprintf(file,", "); + fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile), + XkbGeomFPText(pt->y,XkbXKBFile)); + } + fprintf(file," }"); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBDoodad( FILE * file, + Display * dpy, + unsigned indent, + XkbGeometryPtr geom, + XkbDoodadPtr doodad) +#else +WriteXKBDoodad(file,dpy,indent,geom,doodad) + FILE * file; + Display * dpy; + unsigned indent; + XkbGeometryPtr geom; + XkbDoodadPtr doodad; +#endif +{ +register char * i_str; +XkbShapePtr shape; +XkbColorPtr color; + + i_str= XkbIndentText(indent); + fprintf(file,"%s%s \"%s\" {\n",i_str, + XkbDoodadTypeText(doodad->any.type,XkbMessage), + XkbAtomText(dpy,doodad->any.name,XkbMessage)); + fprintf(file,"%s top= %s;\n",i_str, + XkbGeomFPText(doodad->any.top,XkbXKBFile)); + fprintf(file,"%s left= %s;\n",i_str, + XkbGeomFPText(doodad->any.left,XkbXKBFile)); + fprintf(file,"%s priority= %d;\n",i_str,doodad->any.priority); + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->shape.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbShapeDoodadColor(geom,&doodad->shape)->spec); + } + shape= XkbShapeDoodadShape(geom,&doodad->shape); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + case XkbTextDoodad: + if (doodad->text.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->text.angle,XkbXKBFile)); + } + if (doodad->text.width!=0) { + fprintf(file,"%s width= %s;\n",i_str, + XkbGeomFPText(doodad->text.width,XkbXKBFile)); + + } + if (doodad->text.height!=0) { + fprintf(file,"%s height= %s;\n",i_str, + XkbGeomFPText(doodad->text.height,XkbXKBFile)); + + } + if (doodad->text.color_ndx!=0) { + color= XkbTextDoodadColor(geom,&doodad->text); + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"%s XFont= \"%s\";\n",i_str, + XkbStringText(doodad->text.font,XkbXKBFile)); + fprintf(file,"%s text= \"%s\";\n",i_str, + XkbStringText(doodad->text.text,XkbXKBFile)); + break; + case XkbIndicatorDoodad: + shape= XkbIndicatorDoodadShape(geom,&doodad->indicator); + color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator); + fprintf(file,"%s onColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator); + fprintf(file,"%s offColor= \"%s\";\n",i_str, + XkbStringText(color->spec,XkbXKBFile)); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + case XkbLogoDoodad: + fprintf(file,"%s logoName= \"%s\";\n",i_str, + XkbStringText(doodad->logo.logo_name,XkbXKBFile)); + if (doodad->shape.angle!=0) { + fprintf(file,"%s angle= %s;\n",i_str, + XkbGeomFPText(doodad->logo.angle,XkbXKBFile)); + } + if (doodad->shape.color_ndx!=0) { + fprintf(file,"%s color= \"%s\";\n",i_str, + XkbLogoDoodadColor(geom,&doodad->logo)->spec); + } + shape= XkbLogoDoodadShape(geom,&doodad->logo); + fprintf(file,"%s shape= \"%s\";\n",i_str, + XkbAtomText(dpy,shape->name,XkbXKBFile)); + break; + } + fprintf(file,"%s};\n",i_str); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +WriteXKBOverlay( FILE * file, + Display * dpy, + unsigned indent, + XkbGeometryPtr geom, + XkbOverlayPtr ol) +#else +WriteXKBOverlay(file,dpy,indent,geom,ol) + FILE * file; + Display * dpy; + unsigned indent; + XkbGeometryPtr geom; + XkbOverlayPtr ol; +#endif +{ +register char * i_str; +int r,k,nOut; +XkbOverlayRowPtr row; +XkbOverlayKeyPtr key; + + i_str= XkbIndentText(indent); + if (ol->name!=None) { + fprintf(file,"%soverlay \"%s\" {\n",i_str, + XkbAtomText(dpy,ol->name,XkbMessage)); + } + else fprintf(file,"%soverlay {\n",i_str); + for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + char *over,*under; + over= XkbKeyNameText(key->over.name,XkbXKBFile); + under= XkbKeyNameText(key->under.name,XkbXKBFile); + if (nOut==0) + fprintf(file,"%s %6s=%6s",i_str,under,over); + else if ((nOut%4)==0) + fprintf(file,",\n%s %6s=%6s",i_str,under,over); + else fprintf(file,", %6s=%6s",under,over); + nOut++; + } + } + fprintf(file,"\n%s};\n",i_str); + return True; +} + +static Bool +#if NeedFunctionPrototypes +WriteXKBSection( FILE * file, + Display * dpy, + XkbSectionPtr s, + XkbGeometryPtr geom) +#else +WriteXKBSection(file,dpy,s,geom) + FILE * file; + Display * dpy; + XkbSectionPtr s; + XkbGeometryPtr geom; +#endif +{ +register int i; +XkbRowPtr row; +int dfltKeyColor; + + fprintf(file," section \"%s\" {\n", + XkbAtomText(dpy,s->name,XkbXKBFile)); + if (s->rows&&(s->rows->num_keys>0)) { + dfltKeyColor= s->rows->keys[0].color_ndx; + fprintf(file," key.color= \"%s\";\n", + XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile)); + } + fprintf(file," priority= %d;\n",s->priority); + fprintf(file," top= %s;\n",XkbGeomFPText(s->top,XkbXKBFile)); + fprintf(file," left= %s;\n",XkbGeomFPText(s->left,XkbXKBFile)); + fprintf(file," width= %s;\n",XkbGeomFPText(s->width,XkbXKBFile)); + fprintf(file," height= %s;\n", + XkbGeomFPText(s->height,XkbXKBFile)); + if (s->angle!=0) { + fprintf(file," angle= %s;\n", + XkbGeomFPText(s->angle,XkbXKBFile)); + } + for (i=0,row=s->rows;i<s->num_rows;i++,row++) { + fprintf(file," row {\n"); + fprintf(file," top= %s;\n", + XkbGeomFPText(row->top,XkbXKBFile)); + fprintf(file," left= %s;\n", + XkbGeomFPText(row->left,XkbXKBFile)); + if (row->vertical) + fprintf(file," vertical;\n"); + if (row->num_keys>0) { + register int k; + register XkbKeyPtr key; + int forceNL=0; + int nThisLine= 0; + fprintf(file," keys {\n"); + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + XkbShapePtr shape; + if (key->color_ndx!=dfltKeyColor) + forceNL= 1; + if (k==0) { + fprintf(file," "); + nThisLine= 0; + } + else if (((nThisLine%2)==1)||(forceNL)) { + fprintf(file,",\n "); + forceNL= nThisLine= 0; + } + else { + fprintf(file,", "); + nThisLine++; + } + shape= XkbKeyShape(geom,key); + fprintf(file,"{ %6s, \"%s\", %3s", + XkbKeyNameText(key->name.name,XkbXKBFile), + XkbAtomText(dpy,shape->name,XkbXKBFile), + XkbGeomFPText(key->gap,XkbXKBFile)); + if (key->color_ndx!=dfltKeyColor) { + fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec); + forceNL= 1; + } + fprintf(file," }"); + } + fprintf(file,"\n };\n"); + } + fprintf(file," };\n"); + } + if (s->doodads!=NULL) { + XkbDoodadPtr doodad; + for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) { + WriteXKBDoodad(file,dpy,8,geom,doodad); + } + } + if (s->overlays!=NULL) { + XkbOverlayPtr ol; + for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) { + WriteXKBOverlay(file,dpy,8,geom,ol); + } + } + fprintf(file," }; // End of \"%s\" section\n\n", + XkbAtomText(dpy,s->name,XkbXKBFile)); + return True; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBGeometry( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBGeometry(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Display * dpy; +register unsigned i,n; +XkbDescPtr xkb; +XkbGeometryPtr geom; + + xkb= result->xkb; + if ((!xkb)||(!xkb->geom)) { + _XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0); + return False; + } + dpy= xkb->dpy; + geom= xkb->geom; + if (geom->name==None) + fprintf(file,"xkb_geometry {\n\n"); + else fprintf(file,"xkb_geometry \"%s\" {\n\n", + XkbAtomText(dpy,geom->name,XkbXKBFile)); + fprintf(file," width= %s;\n", + XkbGeomFPText(geom->width_mm,XkbXKBFile)); + fprintf(file," height= %s;\n\n", + XkbGeomFPText(geom->height_mm,XkbXKBFile)); + + if (geom->key_aliases!=NULL) { + XkbKeyAliasPtr pAl; + pAl= geom->key_aliases; + for (i=0;i<geom->num_key_aliases;i++,pAl++) { + fprintf(file," alias %6s = %6s;\n", + XkbKeyNameText(pAl->alias,XkbXKBFile), + XkbKeyNameText(pAl->real,XkbXKBFile)); + } + fprintf(file,"\n"); + } + + if (geom->base_color!=NULL) + fprintf(file," baseColor= \"%s\";\n", + XkbStringText(geom->base_color->spec,XkbXKBFile)); + if (geom->label_color!=NULL) + fprintf(file," labelColor= \"%s\";\n", + XkbStringText(geom->label_color->spec,XkbXKBFile)); + if (geom->label_font!=NULL) + fprintf(file," xfont= \"%s\";\n", + XkbStringText(geom->label_font,XkbXKBFile)); + if ((geom->num_colors>0)&&(showImplicit)) { + XkbColorPtr color; + for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) { + fprintf(file,"// color[%d]= \"%s\"\n",i, + XkbStringText(color->spec,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_properties>0) { + XkbPropertyPtr prop; + for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) { + fprintf(file," %s= \"%s\";\n",prop->name, + XkbStringText(prop->value,XkbXKBFile)); + } + fprintf(file,"\n"); + } + if (geom->num_shapes>0) { + XkbShapePtr shape; + XkbOutlinePtr outline; + int lastR; + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + lastR=0; + fprintf(file," shape \"%s\" {", + XkbAtomText(dpy,shape->name,XkbXKBFile)); + outline= shape->outlines; + if (shape->num_outlines>1) { + for (n=0;n<shape->num_outlines;n++,outline++) { + if (n==0) fprintf(file,"\n"); + else fprintf(file,",\n"); + WriteXKBOutline(file,shape,outline,lastR,8,8); + lastR= outline->corner_radius; + } + fprintf(file,"\n };\n"); + } + else { + WriteXKBOutline(file,NULL,outline,lastR,1,8); + fprintf(file," };\n"); + } + } + } + if (geom->num_sections>0) { + XkbSectionPtr section; + for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){ + WriteXKBSection(file,dpy,section,geom); + } + } + if (geom->num_doodads>0) { + XkbDoodadPtr doodad; + for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) { + WriteXKBDoodad(file,dpy,4,geom,doodad); + } + } + if (addOn) + (*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv); + fprintf(file,"};\n\n"); + return True; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBSemantics( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBSemantics(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; + + fprintf(file,"xkb_semantics {\n"); + ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv); + ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBLayout( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBLayout(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file,"xkb_layout {\n"); + ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); + if (xkb->geom) + ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +/*ARGSUSED*/ +Bool +#if NeedFunctionPrototypes +XkbWriteXKBKeymap( FILE * file, + XkbFileInfo * result, + Bool topLevel, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBKeymap(file,result,topLevel,showImplicit,addOn,priv) + FILE * file; + XkbFileInfo * result; + Bool topLevel; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +XkbDescPtr xkb; + + xkb= result->xkb; + fprintf(file,"xkb_keymap {\n"); + ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv); + ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); + if (xkb->geom) + ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); + fprintf(file,"};\n"); + return ok; +} + +Bool +#if NeedFunctionPrototypes +XkbWriteXKBFile( FILE * out, + XkbFileInfo * result, + Bool showImplicit, + XkbFileAddOnFunc addOn, + void * priv) +#else +XkbWriteXKBFile(out,result,showImplicit,addOn,priv) + FILE * out; + XkbFileInfo * result; + Bool showImplicit; + XkbFileAddOnFunc addOn; + void * priv; +#endif +{ +Bool ok; +Bool (*func)( +#if NeedFunctionPrototypes + FILE * /* file */, + XkbFileInfo * /* result */, + Bool /* topLevel */, + Bool /* showImplicit */, + XkbFileAddOnFunc /* addOn */, + void * /* priv */ +#endif +); + + switch (result->type) { + case XkmSemanticsFile: + func= XkbWriteXKBSemantics; + break; + case XkmLayoutFile: + func= XkbWriteXKBLayout; + break; + case XkmKeymapFile: + func= XkbWriteXKBKeymap; + break; + case XkmTypesIndex: + func= XkbWriteXKBKeyTypes; + break; + case XkmCompatMapIndex: + func= XkbWriteXKBCompatMap; + break; + case XkmSymbolsIndex: + func= XkbWriteXKBSymbols; + break; + case XkmKeyNamesIndex: + func= XkbWriteXKBKeycodes; + break; + case XkmGeometryFile: + case XkmGeometryIndex: + func= XkbWriteXKBGeometry; + break; + case XkmVirtualModsIndex: + case XkmIndicatorsIndex: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(result->type,XkbMessage),0); + return False; + } + if (out==NULL) { + _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0); + ok= False; + } + else { + ok= (*func)(out,result,True,showImplicit,addOn,priv); + } + if (!ok) { + return False; + } + return True; +} + diff --git a/xkb/xkbtext.c b/xkb/xkbtext.c new file mode 100644 index 000000000..18c07a18a --- /dev/null +++ b/xkb/xkbtext.c @@ -0,0 +1,1700 @@ +/* $Xorg: xkbtext.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 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. + + ********************************************************/ + +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif + +#include <X11/Xos.h> + +#ifndef XKB_IN_SERVER + +#include <X11/Xlib.h> +#include <X11/XKBlib.h> +#include <X11/extensions/XKBgeom.h> + +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include "XKBsrv.h" +#include "XKBgeom.h" + +#endif + +/***====================================================================***/ + +#define BUFFER_SIZE 512 + +static char textBuffer[BUFFER_SIZE]; +static int tbNext= 0; + +static char * +#if NeedFunctionPrototypes +tbGetBuffer(unsigned size) +#else +tbGetBuffer(size) + unsigned size; +#endif +{ +char *rtrn; + + if (size>=BUFFER_SIZE) + return NULL; + if ((BUFFER_SIZE-tbNext)<=size) + tbNext= 0; + rtrn= &textBuffer[tbNext]; + tbNext+= size; + return rtrn; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbAtomText(Display *dpy,Atom atm,unsigned format) +#else +XkbAtomText(dpy,atm,format) + Display * dpy; + Atom atm; + unsigned format; +#endif +{ +char *rtrn,*tmp; + + tmp= XkbAtomGetString(dpy,atm); + if (tmp!=NULL) { + int len; + len= strlen(tmp)+1; + if (len>BUFFER_SIZE) + len= BUFFER_SIZE-2; + rtrn= tbGetBuffer(len); + strncpy(rtrn,tmp,len); + rtrn[len]= '\0'; + } + else { + rtrn= tbGetBuffer(1); + rtrn[0]= '\0'; + } + if (format==XkbCFile) { + for (tmp=rtrn;*tmp!='\0';tmp++) { + if ((tmp==rtrn)&&(!isalpha(*tmp))) + *tmp= '_'; + else if (!isalnum(*tmp)) + *tmp= '_'; + } + } + return XkbStringText(rtrn,format); +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbVModIndexText(Display *dpy,XkbDescPtr xkb,unsigned ndx,unsigned format) +#else +XkbVModIndexText(dpy,xkb,ndx,format) + Display * dpy; + XkbDescPtr xkb; + unsigned ndx; + unsigned format; +#endif +{ +register int len; +register Atom *vmodNames; +char *rtrn,*tmp; +char numBuf[20]; + + if (xkb && xkb->names) + vmodNames= xkb->names->vmods; + else vmodNames= NULL; + + tmp= NULL; + if (ndx>=XkbNumVirtualMods) + tmp= "illegal"; + else if (vmodNames&&(vmodNames[ndx]!=None)) + tmp= XkbAtomGetString(dpy,vmodNames[ndx]); + if (tmp==NULL) + sprintf(tmp=numBuf,"%d",ndx); + + len= strlen(tmp)+1; + if (format==XkbCFile) + len+= 4; + if (len>=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len); + if (format==XkbCFile) { + strcpy(rtrn,"vmod_"); + strncpy(&rtrn[5],tmp,len-4); + } + else strncpy(rtrn,tmp,len); + return rtrn; +} + +char * +#if NeedFunctionPrototypes +XkbVModMaskText( Display * dpy, + XkbDescPtr xkb, + unsigned modMask, + unsigned mask, + unsigned format) +#else +XkbVModMaskText(dpy,xkb,modMask,mask,format) + Display * dpy; + XkbDescPtr xkb; + unsigned modMask; + unsigned mask; + unsigned format; +#endif +{ +register int i,bit; +int len; +char *mm,*rtrn; +char *str,buf[BUFFER_SIZE]; + + if ((modMask==0)&&(mask==0)) { + rtrn= tbGetBuffer(5); + if (format==XkbCFile) + sprintf(rtrn,"0"); + else sprintf(rtrn,"none"); + return rtrn; + } + if (modMask!=0) + mm= XkbModMaskText(modMask,format); + else mm= NULL; + + str= buf; + buf[0]= '\0'; + if (mask) { + char *tmp; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (mask&bit) { + tmp= XkbVModIndexText(dpy,xkb,i,format); + len= strlen(tmp)+1+(str==buf?0:1); + if (format==XkbCFile) + len+= 4; + if ((str-(buf+len))<=BUFFER_SIZE) { + if (str!=buf) { + if (format==XkbCFile) *str++= '|'; + else *str++= '+'; + len--; + } + } + if (format==XkbCFile) + sprintf(str,"%sMask",tmp); + else strcpy(str,tmp); + str= &str[len-1]; + } + } + str= buf; + } + else str= NULL; + if (mm) + len= strlen(mm); + else len= 0; + if (str) + len+= strlen(str)+(mm==NULL?0:1); + if (len>=BUFFER_SIZE) + len= BUFFER_SIZE-1; + rtrn= tbGetBuffer(len+1); + rtrn[0]= '\0'; + + if (mm!=NULL) { + i= strlen(mm); + if (i>len) + i= len; + strcpy(rtrn,mm); + } + else { + i=0; + } + if (str!=NULL) { + if (mm!=NULL) { + if (format==XkbCFile) strcat(rtrn,"|"); + else strcat(rtrn,"+"); + } + strncat(rtrn,str,len-i); + } + rtrn[len]= '\0'; + return rtrn; +} + +static char *modNames[XkbNumModifiers] = { + "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" +}; + +char * +#if NeedFunctionPrototypes +XkbModIndexText(unsigned ndx,unsigned format) +#else +XkbModIndexText(ndx,format) + unsigned ndx; + unsigned format; +#endif +{ +char * rtrn; +char buf[100]; + + if (format==XkbCFile) { + if (ndx<XkbNumModifiers) + sprintf(buf,"%sMapIndex",modNames[ndx]); + else if (ndx==XkbNoModifier) + sprintf(buf,"XkbNoModifier"); + else sprintf(buf,"0x%02x",ndx); + } + else { + if (ndx<XkbNumModifiers) + strcpy(buf,modNames[ndx]); + else if (ndx==XkbNoModifier) + strcpy(buf,"none"); + else sprintf(buf,"ILLEGAL_%02x",ndx); + } + rtrn= tbGetBuffer(strlen(buf)+1); + strcpy(rtrn,buf); + return rtrn; +} + +char * +#if NeedFunctionPrototypes +XkbModMaskText(unsigned mask,unsigned format) +#else +XkbModMaskText(mask,format) + unsigned mask; + unsigned format; +#endif +{ +register int i,bit; +char buf[64],*rtrn; + + if ((mask&0xff)==0xff) { + if (format==XkbCFile) strcpy(buf,"0xff"); + else strcpy(buf,"all"); + } + else if ((mask&0xff)==0) { + if (format==XkbCFile) strcpy(buf,"0"); + else strcpy(buf,"none"); + } + else { + char *str= buf; + buf[0]= '\0'; + for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { + if (mask&bit) { + if (str!=buf) { + if (format==XkbCFile) *str++= '|'; + else *str++= '+'; + } + strcpy(str,modNames[i]); + str= &str[strlen(str)]; + if (format==XkbCFile) { + strcpy(str,"Mask"); + str+= 4; + } + } + } + } + rtrn= tbGetBuffer(strlen(buf)+1); + strcpy(rtrn,buf); + return rtrn; +} + +/***====================================================================***/ + +/*ARGSUSED*/ +char * +#if NeedFunctionPrototypes +XkbConfigText(unsigned config,unsigned format) +#else +XkbConfigText(config,format) + unsigned config; + unsigned format; +#endif +{ +static char *buf; + + buf= tbGetBuffer(32); + switch (config) { + case XkmSemanticsFile: + strcpy(buf,"Semantics"); + break; + case XkmLayoutFile: + strcpy(buf,"Layout"); + break; + case XkmKeymapFile: + strcpy(buf,"Keymap"); + break; + case XkmGeometryFile: + case XkmGeometryIndex: + strcpy(buf,"Geometry"); + break; + case XkmTypesIndex: + strcpy(buf,"Types"); + break; + case XkmCompatMapIndex: + strcpy(buf,"CompatMap"); + break; + case XkmSymbolsIndex: + strcpy(buf,"Symbols"); + break; + case XkmIndicatorsIndex: + strcpy(buf,"Indicators"); + break; + case XkmKeyNamesIndex: + strcpy(buf,"KeyNames"); + break; + case XkmVirtualModsIndex: + strcpy(buf,"VirtualMods"); + break; + default: + sprintf(buf,"unknown(%d)",config); + break; + } + return buf; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbKeysymText(KeySym sym,unsigned format) +#else +XkbKeysymText(sym,format) + KeySym sym; + unsigned format; +#endif +{ +static char buf[32],*rtrn; + +#ifndef XKB_IN_SERVER + if (sym==NoSymbol) + strcpy(rtrn=buf,"NoSymbol"); + else if ((rtrn=XKeysymToString(sym))==NULL) + sprintf(rtrn=buf,"0x%x",sym); + else if (format==XkbCFile) { + sprintf(buf,"XK_%s",rtrn); + rtrn= buf; + } + return rtrn; +#else /* def XKB_IN_SERVER */ + if (sym==NoSymbol) + strcpy(rtrn=buf,"NoSymbol"); + else sprintf(rtrn=buf,"0x%x",sym); + return rtrn; +#endif /* XKB_IN_SERVER */ +} + +char * +#if NeedFunctionPrototypes +XkbKeyNameText(char *name,unsigned format) +#else +XkbKeyNameText(name,format) + char * name; + unsigned format; +#endif +{ +char *buf; + + if (format==XkbCFile) { + buf= tbGetBuffer(5); + memcpy(buf,name,4); + buf[4]= '\0'; + } + else { + int len; + buf= tbGetBuffer(7); + buf[0]= '<'; + memcpy(&buf[1],name,4); + buf[5]= '\0'; + len= strlen(buf); + buf[len++]= '>'; + buf[len]= '\0'; + } + return buf; +} + +/***====================================================================***/ + +static char *siMatchText[5] = { + "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly" +}; + +char * +#if NeedFunctionPrototypes +XkbSIMatchText(unsigned type,unsigned format) +#else +XkbSIMatchText(type,format) + unsigned type; + unsigned format; +#endif +{ +static char buf[40]; +char *rtrn; + + switch (type&XkbSI_OpMask) { + case XkbSI_NoneOf: rtrn= siMatchText[0]; break; + case XkbSI_AnyOfOrNone: rtrn= siMatchText[1]; break; + case XkbSI_AnyOf: rtrn= siMatchText[2]; break; + case XkbSI_AllOf: rtrn= siMatchText[3]; break; + case XkbSI_Exactly: rtrn= siMatchText[4]; break; + default: sprintf(buf,"0x%x",type&XkbSI_OpMask); + return buf; + } + if (format==XkbCFile) { + if (type&XkbSI_LevelOneOnly) + sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn); + else sprintf(buf,"XkbSI_%s",rtrn); + rtrn= buf; + } + return rtrn; +} + +/***====================================================================***/ + +static char *imWhichNames[]= { + "base", + "latched", + "locked", + "effective", + "compat" +}; + +char * +#if NeedFunctionPrototypes +XkbIMWhichStateMaskText(unsigned use_which,unsigned format) +#else +XkbIMWhichStateMaskText(use_which,format) + unsigned use_which; + unsigned format; +#endif +{ +int len; +unsigned i,bit,tmp; +char * buf; + + if (use_which==0) { + buf= tbGetBuffer(2); + strcpy(buf,"0"); + return buf; + } + tmp= use_which&XkbIM_UseAnyMods; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + len+= strlen(imWhichNames[i])+1; + if (format==XkbCFile) + len+= 9; + } + } + buf= tbGetBuffer(len+1); + tmp= use_which&XkbIM_UseAnyMods; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + if (format==XkbCFile) { + if (len!=0) + buf[len++]= '|'; + sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]); + buf[len+9]= toupper(buf[len+9]); + } + else { + if (len!=0) + buf[len++]= '+'; + sprintf(&buf[len],"%s",imWhichNames[i]); + } + len+= strlen(&buf[len]); + } + } + return buf; +} + +char * +#if NeedFunctionPrototypes +XkbAccessXDetailText(unsigned state,unsigned format) +#else +XkbAccessXDetailText(state,format) + unsigned state; + unsigned format; +#endif +{ +char *buf,*prefix; + + buf= tbGetBuffer(32); + if (format==XkbMessage) prefix= ""; + else prefix= "XkbAXN_"; + switch (state){ + case XkbAXN_SKPress: sprintf(buf,"%sSKPress",prefix); break; + case XkbAXN_SKAccept: sprintf(buf,"%sSKAccept",prefix); break; + case XkbAXN_SKRelease: sprintf(buf,"%sSKRelease",prefix); break; + case XkbAXN_SKReject: sprintf(buf,"%sSKReject",prefix); break; + case XkbAXN_BKAccept: sprintf(buf,"%sBKAccept",prefix); break; + case XkbAXN_BKReject: sprintf(buf,"%sBKReject",prefix); break; + case XkbAXN_AXKWarning: sprintf(buf,"%sAXKWarning",prefix); break; + default: sprintf(buf,"ILLEGAL"); break; + } + return buf; +} + +static char *nknNames[] = { + "keycodes", "geometry", "deviceID" +}; +#define NUM_NKN (sizeof(nknNames)/sizeof(char *)) + +char * +#if NeedFunctionPrototypes +XkbNKNDetailMaskText(unsigned detail,unsigned format) +#else +XkbNKNDetailMaskText(detail,format) + unsigned detail; + unsigned format; +#endif +{ +char *buf,*prefix,*suffix; +register int i; +register unsigned bit; +int len,plen,slen; + + + if ((detail&XkbAllNewKeyboardEventsMask)==0) { + char * tmp; + if (format==XkbCFile) tmp= "0"; + else if (format==XkbMessage) tmp= "none"; + buf= tbGetBuffer(strlen(tmp)+1); + strcpy(buf,tmp); + return buf; + } + else if ((detail&XkbAllNewKeyboardEventsMask)==XkbAllNewKeyboardEventsMask){ + char * tmp; + if (format==XkbCFile) tmp= "XkbAllNewKeyboardEventsMask"; + else tmp= "all"; + buf= tbGetBuffer(strlen(tmp)+1); + strcpy(buf,tmp); + return buf; + } + if (format==XkbMessage) { + prefix= ""; + suffix= ""; + slen= plen= 0; + } + else { + prefix= "XkbNKN_"; + plen= 7; + if (format==XkbCFile) + suffix= "Mask"; + else suffix= ""; + slen= strlen(suffix); + } + for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) { + if (detail&bit) { + if (len!=0) len+= 1; /* room for '+' or '|' */ + len+= plen+slen+strlen(nknNames[i]); + } + } + buf= tbGetBuffer(len+1); + buf[0]= '\0'; + for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) { + if (detail&bit) { + if (len!=0) { + if (format==XkbCFile) buf[len++]= '|'; + else buf[len++]= '+'; + } + if (plen) { + strcpy(&buf[len],prefix); + len+= plen; + } + strcpy(&buf[len],nknNames[i]); + len+= strlen(nknNames[i]); + if (slen) { + strcpy(&buf[len],suffix); + len+= slen; + } + } + } + buf[len++]= '\0'; + return buf; +} + +static char *ctrlNames[] = { + "repeatKeys", + "slowKeys", + "bounceKeys", + "stickyKeys", + "mouseKeys", + "mouseKeysAccel", + "accessXKeys", + "accessXTimeout", + "accessXFeedback", + "audibleBell", + "overlay1", + "overlay2", + "ignoreGroupLock" +}; + +char * +#if NeedFunctionPrototypes +XkbControlsMaskText(unsigned ctrls,unsigned format) +#else +XkbControlsMaskText(ctrls,format) + unsigned ctrls; + unsigned format; +#endif +{ +int len; +unsigned i,bit,tmp; +char * buf; + + if (ctrls==0) { + buf= tbGetBuffer(5); + if (format==XkbCFile) + strcpy(buf,"0"); + else strcpy(buf,"none"); + return buf; + } + tmp= ctrls&XkbAllBooleanCtrlsMask; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + len+= strlen(ctrlNames[i])+1; + if (format==XkbCFile) + len+= 7; + } + } + buf= tbGetBuffer(len+1); + tmp= ctrls&XkbAllBooleanCtrlsMask; + for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { + if (tmp&bit) { + tmp&= ~bit; + if (format==XkbCFile) { + if (len!=0) + buf[len++]= '|'; + sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]); + buf[len+3]= toupper(buf[len+3]); + } + else { + if (len!=0) + buf[len++]= '+'; + sprintf(&buf[len],"%s",ctrlNames[i]); + } + len+= strlen(&buf[len]); + } + } + return buf; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbStringText(char *str,unsigned format) +#else +XkbStringText(str,format) + char * str; + unsigned format; +#endif +{ +char * buf; +register char *in,*out; +int len; +Bool ok; + + if (str==NULL) { + buf= tbGetBuffer(2); + buf[0]='\0'; + return buf; + } + else if (format==XkbXKMFile) + return str; + for (ok= True,len=0,in=str;*in!='\0';in++,len++) { + if (!isprint(*in)) { + ok= False; + switch (*in) { + case '\n': case '\t': case '\v': + case '\b': case '\r': case '\f': + len++; + break; + default: + len+= 4; + break; + } + } + } + if (ok) + return str; + buf= tbGetBuffer(len+1); + for (in=str,out=buf;*in!='\0';in++) { + if (isprint(*in)) + *out++= *in; + else { + *out++= '\\'; + if (*in=='\n') *out++= 'n'; + else if (*in=='\t') *out++= 't'; + else if (*in=='\v') *out++= 'v'; + else if (*in=='\b') *out++= 'b'; + else if (*in=='\r') *out++= 'r'; + else if (*in=='\f') *out++= 'f'; + else if ((*in=='\033')&&(format==XkbXKMFile)) { + *out++= 'e'; + } + else { + *out++= '0'; + sprintf(out,"%o",*in); + while (*out!='\0') + out++; + } + } + } + *out++= '\0'; + return buf; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbGeomFPText(int val,unsigned format) +#else +XkbGeomFPText(val,format) + int val; + unsigned format; +#endif +{ +int whole,frac; +char * buf; + + buf= tbGetBuffer(12); + if (format==XkbCFile) { + sprintf(buf,"%d",val); + } + else { + whole= val/XkbGeomPtsPerMM; + frac= val%XkbGeomPtsPerMM; + if (frac!=0) + sprintf(buf,"%d.%d",whole,frac); + else sprintf(buf,"%d",whole); + } + return buf; +} + +char * +#if NeedFunctionPrototypes +XkbDoodadTypeText(unsigned type,unsigned format) +#else +XkbDoodadTypeText(type,format) + unsigned type; + unsigned format; +#endif +{ +char * buf; + if (format==XkbCFile) { + buf= tbGetBuffer(24); + if (type==XkbOutlineDoodad) strcpy(buf,"XkbOutlineDoodad"); + else if (type==XkbSolidDoodad) strcpy(buf,"XkbSolidDoodad"); + else if (type==XkbTextDoodad) strcpy(buf,"XkbTextDoodad"); + else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad"); + else if (type==XkbLogoDoodad) strcpy(buf,"XkbLogoDoodad"); + else sprintf(buf,"UnknownDoodad%d",type); + } + else { + buf= tbGetBuffer(12); + if (type==XkbOutlineDoodad) strcpy(buf,"outline"); + else if (type==XkbSolidDoodad) strcpy(buf,"solid"); + else if (type==XkbTextDoodad) strcpy(buf,"text"); + else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator"); + else if (type==XkbLogoDoodad) strcpy(buf,"logo"); + else sprintf(buf,"unknown%d",type); + } + return buf; +} + +static char *actionTypeNames[XkbSA_NumActions]= { + "NoAction", + "SetMods", "LatchMods", "LockMods", + "SetGroup", "LatchGroup", "LockGroup", + "MovePtr", + "PtrBtn", "LockPtrBtn", + "SetPtrDflt", + "ISOLock", + "Terminate", "SwitchScreen", + "SetControls", "LockControls", + "ActionMessage", + "RedirectKey", + "DeviceBtn", "LockDeviceBtn" +}; + +char * +#if NeedFunctionPrototypes +XkbActionTypeText(unsigned type,unsigned format) +#else +XkbActionTypeText(type,format) + unsigned type; + unsigned format; +#endif +{ +static char buf[32]; +char *rtrn; + + if (type<=XkbSA_LastAction) { + rtrn= actionTypeNames[type]; + if (format==XkbCFile) { + sprintf(buf,"XkbSA_%s",rtrn); + return buf; + } + return rtrn; + } + sprintf(buf,"0x%x",type); + return buf; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +TryCopyStr(char *to,char *from,int *pLeft) +#else +TryCopyStr(to,from,pLeft) + char * to; + char * from; + int * pLeft; +#endif +{ +register int len; + if (*pLeft>0) { + len= strlen(from); + if (len<((*pLeft)-3)) { + strcat(to,from); + *pLeft-= len; + return True; + } + } + *pLeft= -1; + return False; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyNoActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int*sz) +#else +CopyNoActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyModActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int* sz) +#else +CopyModActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbModAction * act; +unsigned tmp; + + act= &action->mods; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + TryCopyStr(buf, + XkbVModMaskText(dpy,xkb,act->real_mods,tmp,XkbXKBFile), + sz); + } + else TryCopyStr(buf,"none",sz); + if (act->type==XkbSA_LockMods) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyGroupActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyGroupActionArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbGroupAction * act; +char tbuf[32]; + + act= &action->group; + TryCopyStr(buf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + if (act->type==XkbSA_LockGroup) + return True; + if (act->flags&XkbSA_ClearLocks) + TryCopyStr(buf,",clearLocks",sz); + if (act->flags&XkbSA_LatchToLock) + TryCopyStr(buf,",latchToLock",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyMovePtrArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyMovePtrArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrAction * act; +int x,y; +char tbuf[32]; + + act= &action->ptr; + x= XkbPtrActionX(act); + y= XkbPtrActionY(act); + if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0)) + sprintf(tbuf,"x=%d",x); + else sprintf(tbuf,"x=+%d",x); + TryCopyStr(buf,tbuf,sz); + + if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0)) + sprintf(tbuf,",y=%d",y); + else sprintf(tbuf,",y=+%d",y); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_NoAcceleration) + TryCopyStr(buf,",!accel",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyPtrBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyPtrBtnArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrBtnAction * act; +char tbuf[32]; + + act= &action->btn; + TryCopyStr(buf,"button=",sz); + if ((act->button>0)&&(act->button<6)) { + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + } + else TryCopyStr(buf,"default",sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockPtrBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySetPtrDfltArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopySetPtrDfltArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbPtrDfltAction * act; +char tbuf[32]; + + act= &action->dflt; + if (act->affect==XkbSA_AffectDfltBtn) { + TryCopyStr(buf,"affect=button,button=",sz); + if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0)) + sprintf(tbuf,"%d",XkbSAPtrDfltValue(act)); + else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act)); + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyISOLockArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyISOLockArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbISOAction * act; +char tbuf[64]; + + act= &action->iso; + if (act->flags&XkbSA_ISODfltIsGroup) { + TryCopyStr(tbuf,"group=",sz); + if (act->flags&XkbSA_GroupAbsolute) + sprintf(tbuf,"%d",XkbSAGroup(act)+1); + else if (XkbSAGroup(act)<0) + sprintf(tbuf,"%d",XkbSAGroup(act)); + else sprintf(tbuf,"+%d",XkbSAGroup(act)); + TryCopyStr(buf,tbuf,sz); + } + else { + unsigned tmp; + tmp= XkbModActionVMods(act); + TryCopyStr(buf,"modifiers=",sz); + if (act->flags&XkbSA_UseModMapMods) + TryCopyStr(buf,"modMapMods",sz); + else if (act->real_mods || tmp) { + if (act->real_mods) { + TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz); + if (tmp) + TryCopyStr(buf,"+",sz); + } + if (tmp) + TryCopyStr(buf,XkbVModMaskText(dpy,xkb,0,tmp,XkbXKBFile),sz); + } + else TryCopyStr(buf,"none",sz); + } + TryCopyStr(buf,",affect=",sz); + if ((act->affect&XkbSA_ISOAffectMask)==0) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if ((act->affect&XkbSA_ISONoAffectMods)==0) { + TryCopyStr(buf,"mods",sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectGroup)==0) { + sprintf(tbuf,"%sgroups",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectPtr)==0) { + sprintf(tbuf,"%spointer",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if ((act->affect&XkbSA_ISONoAffectCtrls)==0) { + sprintf(tbuf,"%scontrols",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySwitchScreenArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopySwitchScreenArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbSwitchScreenAction * act; +char tbuf[32]; + + act= &action->screen; + if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0)) + sprintf(tbuf,"screen=%d",XkbSAScreen(act)); + else sprintf(tbuf,"screen=+%d",XkbSAScreen(act)); + TryCopyStr(buf,tbuf,sz); + if (act->flags&XkbSA_SwitchApplication) + TryCopyStr(buf,",!same",sz); + else TryCopyStr(buf,",same",sz); + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopySetLockControlsArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action, + char *buf,int *sz) +#else +CopySetLockControlsArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbCtrlsAction * act; +unsigned tmp; +char tbuf[32]; + + act= &action->ctrls; + tmp= XkbActionCtrls(act); + TryCopyStr(buf,"controls=",sz); + if (tmp==0) + TryCopyStr(buf,"none",sz); + else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask) + TryCopyStr(buf,"all",sz); + else { + int nOut= 0; + if (tmp&XkbRepeatKeysMask) { + sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbSlowKeysMask) { + sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbBounceKeysMask) { + sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbStickyKeysMask) { + sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysMask) { + sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbMouseKeysAccelMask) { + sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXKeysMask) { + sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXTimeoutMask) { + sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAccessXFeedbackMask) { + sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbAudibleBellMask) { + sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay1Mask) { + sprintf(tbuf,"%sOverlay1",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbOverlay2Mask) { + sprintf(tbuf,"%sOverlay2",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + if (tmp&XkbIgnoreGroupLockMask) { + sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":"")); + TryCopyStr(buf,tbuf,sz); + nOut++; + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyActionMessageArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyActionMessageArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbMessageAction * act; +unsigned all; +char tbuf[32]; + + act= &action->msg; + all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease; + TryCopyStr(buf,"report=",sz); + if ((act->flags&all)==0) + TryCopyStr(buf,"none",sz); + else if ((act->flags&all)==all) + TryCopyStr(buf,"all",sz); + else if (act->flags&XkbSA_MessageOnPress) + TryCopyStr(buf,"KeyPress",sz); + else TryCopyStr(buf,"KeyRelease",sz); + sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz); + return True; +} + +static Bool +#if NeedFunctionPrototypes +CopyRedirectKeyArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyRedirectKeyArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbRedirectKeyAction * act; +char tbuf[32],*tmp; +unsigned kc; +unsigned vmods,vmods_mask; + + act= &action->redirect; + kc= act->new_key; + vmods= XkbSARedirectVMods(act); + vmods_mask= XkbSARedirectVModsMask(act); + if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) && + (xkb->names->keys[kc].name[0]!='\0')) { + char *kn; + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + sprintf(tbuf,"key=%s",kn); + } + else sprintf(tbuf,"key=%d",kc); + TryCopyStr(buf,tbuf,sz); + if ((act->mods_mask==0)&&(vmods_mask==0)) + return True; + if ((act->mods_mask==XkbAllModifiersMask)&& + (vmods_mask==XkbAllVirtualModsMask)) { + tmp= XkbVModMaskText(dpy,xkb,act->mods,vmods,XkbXKBFile); + TryCopyStr(buf,",mods=",sz); + TryCopyStr(buf,tmp,sz); + } + else { + if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) { + tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&act->mods, + vmods_mask&vmods,XkbXKBFile); + TryCopyStr(buf,",mods= ",sz); + TryCopyStr(buf,tmp,sz); + } + if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) { + tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&(~act->mods), + vmods_mask&(~vmods),XkbXKBFile); + TryCopyStr(buf,",clearMods= ",sz); + TryCopyStr(buf,tmp,sz); + } + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyDeviceBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf, + int *sz) +#else +CopyDeviceBtnArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbDeviceBtnAction * act; +char tbuf[32]; + + act= &action->devbtn; + sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz); + TryCopyStr(buf,",button=",sz); + sprintf(tbuf,"%d",act->button); + TryCopyStr(buf,tbuf,sz); + if (act->count>0) { + sprintf(tbuf,",count=%d",act->count); + TryCopyStr(buf,tbuf,sz); + } + if (action->type==XkbSA_LockDeviceBtn) { + switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { + case XkbSA_LockNoLock: + sprintf(tbuf,",affect=unlock"); break; + case XkbSA_LockNoUnlock: + sprintf(tbuf,",affect=lock"); break; + case XkbSA_LockNoUnlock|XkbSA_LockNoLock: + sprintf(tbuf,",affect=neither"); break; + default: + sprintf(tbuf,",affect=both"); break; + } + TryCopyStr(buf,tbuf,sz); + } + return True; +} + +/*ARGSUSED*/ +static Bool +#if NeedFunctionPrototypes +CopyOtherArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) +#else +CopyOtherArgs(dpy,xkb,action,buf,sz) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + char * buf; + int * sz; +#endif +{ +XkbAnyAction * act; +char tbuf[32]; + + act= &action->any; + sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz); + sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz); + return True; +} + +typedef Bool (*actionCopy)( +#if NeedFunctionPrototypes + Display * /* dpy */, + XkbDescPtr /* xkb */, + XkbAction * /* action */, + char * /* buf */, + int* /* sz */ +#endif +); +static actionCopy copyActionArgs[XkbSA_NumActions] = { + CopyNoActionArgs /* NoAction */, + CopyModActionArgs /* SetMods */, + CopyModActionArgs /* LatchMods */, + CopyModActionArgs /* LockMods */, + CopyGroupActionArgs /* SetGroup */, + CopyGroupActionArgs /* LatchGroup */, + CopyGroupActionArgs /* LockGroup */, + CopyMovePtrArgs /* MovePtr */, + CopyPtrBtnArgs /* PtrBtn */, + CopyPtrBtnArgs /* LockPtrBtn */, + CopySetPtrDfltArgs /* SetPtrDflt */, + CopyISOLockArgs /* ISOLock */, + CopyNoActionArgs /* Terminate */, + CopySwitchScreenArgs /* SwitchScreen */, + CopySetLockControlsArgs /* SetControls */, + CopySetLockControlsArgs /* LockControls */, + CopyActionMessageArgs /* ActionMessage*/, + CopyRedirectKeyArgs /* RedirectKey */, + CopyDeviceBtnArgs /* DeviceBtn */, + CopyDeviceBtnArgs /* LockDeviceBtn*/ +}; + +#define ACTION_SZ 256 + +char * +#if NeedFunctionPrototypes +XkbActionText(Display *dpy,XkbDescPtr xkb,XkbAction *action,unsigned format) +#else +XkbActionText(dpy,xkb,action,format) + Display * dpy; + XkbDescPtr xkb; + XkbAction * action; + unsigned format; +#endif +{ +char buf[ACTION_SZ],*tmp; +int sz; + + if (format==XkbCFile) { + sprintf(buf, + "{ %20s, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x }", + XkbActionTypeText(action->type,XkbCFile), + action->any.data[0],action->any.data[1],action->any.data[2], + action->any.data[3],action->any.data[4],action->any.data[5], + action->any.data[6]); + } + else { + sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile)); + sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */ + if (action->type<(unsigned)XkbSA_NumActions) + (*copyActionArgs[action->type])(dpy,xkb,action,buf,&sz); + else CopyOtherArgs(dpy,xkb,action,buf,&sz); + TryCopyStr(buf,")",&sz); + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +char * +#if NeedFunctionPrototypes +XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format) +#else +XkbBehaviorText(xkb,behavior,format) + XkbDescPtr xkb; + XkbBehavior * behavior; + unsigned format; +#endif +{ +char buf[256],*tmp; + + if (format==XkbCFile) { + if (behavior->type==XkbKB_Default) + sprintf(buf,"{ 0, 0 }"); + else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data); + } + else { + unsigned type,permanent; + type= behavior->type&XkbKB_OpMask; + permanent=((behavior->type&XkbKB_Permanent)!=0); + + if (type==XkbKB_Lock) { + sprintf(buf,"lock= %s,",(permanent?"Permanent":"True")); + } + else if (type==XkbKB_RadioGroup) { + int g; + char *tmp; + g= ((behavior->data)&(~XkbKB_RGAllowNone))+1; + if (XkbKB_RGAllowNone&behavior->data) { + sprintf(buf,"allowNone,"); + tmp= &buf[strlen(buf)]; + } + else tmp= buf; + if (permanent) + sprintf(tmp,"permanentRadioGroup= %d",g); + else sprintf(tmp,"radioGroup= %d",g); + } + else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) { + int ndx,kc; + char *kn; + + ndx= ((type==XkbKB_Overlay1)?1:2); + kc= behavior->data; + if ((xkb)&&(xkb->names)&&(xkb->names->keys)) + kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); + else { + static char tbuf[8]; + sprintf(tbuf,"%d",kc); + kn= tbuf; + } + if (permanent) + sprintf(buf,"permanentOverlay%d= %s",ndx,kn); + else sprintf(buf,"overlay%d= %s",ndx,kn); + } + } + tmp= tbGetBuffer(strlen(buf)+1); + if (tmp!=NULL) + strcpy(tmp,buf); + return tmp; +} + +/***====================================================================***/ + +char * +#if NeedFunctionPrototypes +XkbIndentText(unsigned size) +#else +XkbIndentText(size) + unsigned size; +#endif +{ +static char buf[32]; +register int i; + + if (size>31) + size= 31; + + for (i=0;i<size;i++) { + buf[i]= ' '; + } + buf[size]= '\0'; + return buf; +} + +#ifndef XKB_IN_SERVER + +/***====================================================================***/ + +#define PIXEL_MAX 65535 + +Bool +#if NeedFunctionPrototypes +XkbLookupCanonicalRGBColor(char *def,XColor *color) +#else +XkbLookupCanonicalRGBColor(def,color) + char * def; + XColor * color; +#endif +{ +int tmp; + + if (_XkbStrCaseEqual(def,"black")) { + color->red= color->green= color->blue= 0; + return True; + } + else if (_XkbStrCaseEqual(def,"white")) { + color->red= color->green= color->blue= PIXEL_MAX; + return True; + } + else if ((sscanf(def,"grey%d",&tmp)==1)|| + (sscanf(def,"gray%d",&tmp)==1)|| + (sscanf(def,"Grey%d",&tmp)==1)|| + (sscanf(def,"Gray%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= color->green= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"red")*100))|| + (sscanf(def,"red%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= tmp; + color->green= color->blue= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"green")*100))|| + (sscanf(def,"green%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->green= tmp; + color->red= color->blue= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"blue")*100))|| + (sscanf(def,"blue%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->blue= tmp; + color->red= color->green= 0; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"magenta")*100))|| + (sscanf(def,"magenta%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->green= 0; + color->red= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"cyan")*100))|| + (sscanf(def,"cyan%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->red= 0; + color->green= color->blue= tmp; + return True; + } + } + else if ((tmp=(_XkbStrCaseEqual(def,"yellow")*100))|| + (sscanf(def,"yellow%d",&tmp)==1)) { + if ((tmp>0)&&(tmp<=100)) { + tmp= (PIXEL_MAX*tmp)/100; + color->blue= 0; + color->red= color->green= tmp; + return True; + } + } + return False; +} + +#endif diff --git a/xkb/xkmread.c b/xkb/xkmread.c new file mode 100644 index 000000000..7a4a2b429 --- /dev/null +++ b/xkb/xkmread.c @@ -0,0 +1,1481 @@ +/* $Xorg: xkmread.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */ +/************************************************************ + Copyright (c) 1994 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. + + ********************************************************/ + +#include <stdio.h> + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> + +#ifndef XKB_IN_SERVER + +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif +#include <X11/Xlib.h> +#include <X11/keysym.h> + +#include <X11/XKBlib.h> + +#include <X11/extensions/XKBgeom.h> +#include "XKMformat.h" +#include "XKBfileInt.h" + +#else + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "XKBstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include "XKBsrv.h" +#include "XKBgeom.h" + +Atom +#if NeedFunctionPrototypes +XkbInternAtom(Display *dpy,char *str,Bool only_if_exists) +#else +XkbInternAtom(dpy,str,only_if_exists) + Display * dpy; + char * str; + Bool only_if_exists; +#endif +{ + if (str==NULL) + return None; + return MakeAtom(str,strlen(str),!only_if_exists); +} + +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +char * +#if NeedFunctionPrototypes +_XkbDupString(char *str) +#else +_XkbDupString(str) + char *str; +#endif +{ +char *new; + + if (str==NULL) + return NULL; + new= (char *)_XkbCalloc(strlen(str)+1,sizeof(char)); + if (new) + strcpy(new,str); + return new; +} + +/***====================================================================***/ + +static XPointer +#if NeedFunctionPrototypes +XkmInsureSize(XPointer oldPtr,int oldCount,int *newCountRtrn,int elemSize) +#else +XkmInsureSize(oldPtr,oldCount,newCountRtrn,elemSize) + XPointer oldPtr; + int oldCount; + int * newCountRtrn; + int elemSize; +#endif +{ +int newCount= *newCountRtrn; + + if (oldPtr==NULL) { + if (newCount==0) + return NULL; + oldPtr= (XPointer)_XkbCalloc(newCount,elemSize); + } + else if (oldCount<newCount) { + oldPtr= (XPointer)_XkbRealloc(oldPtr,newCount*elemSize); + if (oldPtr!=NULL) { + char *tmp= (char *)oldPtr; + bzero(&tmp[oldCount*elemSize],(newCount-oldCount)*elemSize); + } + } + else if (newCount<oldCount) { + *newCountRtrn= oldCount; + } + return oldPtr; +} + +#define XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t)))) + +static CARD8 +#if NeedFunctionPrototypes +XkmGetCARD8(FILE *file,int *pNRead) +#else +XkmGetCARD8(file,pNRead) + FILE * file; + int * pNRead; +#endif +{ +int tmp; + tmp= getc(file); + if (pNRead&&(tmp!=EOF)) + (*pNRead)+= 1; + return tmp; +} + +static CARD16 +#if NeedFunctionPrototypes +XkmGetCARD16(FILE *file,int *pNRead) +#else +XkmGetCARD16(file,pNRead) + FILE * file; + int * pNRead; +#endif +{ +CARD16 val; + + if ((fread(&val,2,1,file)==1)&&(pNRead)) + (*pNRead)+= 2; + return val; +} + +static CARD32 +#if NeedFunctionPrototypes +XkmGetCARD32(FILE *file,int *pNRead) +#else +XkmGetCARD32(file,pNRead) + FILE * file; + int * pNRead; +#endif +{ +unsigned long val; + + if ((fread(&val,4,1,file)==1)&&(pNRead)) + (*pNRead)+= 4; + return val; +} + +static int +#if NeedFunctionPrototypes +XkmSkipPadding(FILE *file,unsigned pad) +#else +XkmSkipPadding(file,pad) + FILE * file; + unsigned pad; +#endif +{ +register int i,nRead=0; + + for (i=0;i<pad;i++) { + if (getc(file)!=EOF) + nRead++; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +XkmGetCountedString(FILE *file,char *str,int max_len) +#else +XkmGetCountedString(file,str,max_len) + FILE * file; + char * str; + int max_len; +#endif +{ +int count,nRead=0; + + count= XkmGetCARD16(file,&nRead); + if (count>0) { + int tmp; + if (count>max_len) { + tmp= fread(str,1,max_len,file); + while (tmp<count) { + if ((getc(file))!=EOF) + tmp++; + else break; + } + } + else { + tmp= fread(str,1,count,file); + } + nRead+= tmp; + } + if (count>=max_len) str[max_len-1]= '\0'; + else str[count]= '\0'; + count= XkbPaddedSize(nRead)-nRead; + if (count>0) + nRead+= XkmSkipPadding(file,count); + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmVirtualMods(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmVirtualMods(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned int i,bit; +unsigned int bound,named,tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + bound= XkmGetCARD16(file,&nRead); + named= XkmGetCARD16(file,&nRead); + for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bound&bit) { + xkb->server->vmods[i]= XkmGetCARD8(file,&nRead); + if (changes) + changes->map.vmods|= bit; + tmp++; + } + } + if ((i= XkbPaddedSize(tmp)-tmp)>0) + nRead+= XkmSkipPadding(file,i); + if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + char name[100]; + if (named&bit) { + if (nRead+=XkmGetCountedString(file,name,100)) { + xkb->names->vmods[i]= XkbInternAtom(xkb->dpy,name,False); + if (changes) + changes->names.changed_vmods|= bit; + } + } + } + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmKeycodes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmKeycodes(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned minKC,maxKC,nAl; +int nRead=0; +char name[100]; +XkbKeyNamePtr pN; +XkbDescPtr xkb; + + xkb= result->xkb; + name[0]= '\0'; + nRead+= XkmGetCountedString(file,name,100); + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + if (xkb->min_key_code==0) { + xkb->min_key_code= minKC; + xkb->max_key_code= maxKC; + } + else { + if (minKC<xkb->min_key_code) + xkb->min_key_code= minKC; + if (maxKC>xkb->max_key_code) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC); + return -1; + } + } + nAl= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + +#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask) + if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return -1; + } + if (name[0]!='\0') { + xkb->names->keycodes= XkbInternAtom(xkb->dpy,name,False); + } + + for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) { + if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= XkbKeyNameLength; + } + if (nAl>0) { + XkbKeyAliasPtr pAl; + for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) { + int tmp; + tmp= fread(pAl,1,2*XkbKeyNameLength,file); + if (tmp!=2*XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= 2*XkbKeyNameLength; + } + if (changes) + changes->names.changed|= XkbKeyAliasesMask; + } + if (changes) + changes->names.changed|= XkbKeyNamesMask; + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmKeyTypes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmKeyTypes(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned i,n; +unsigned num_types; +int nRead=0; +int tmp; +XkbKeyTypePtr type; +xkmKeyTypeDesc wire; +XkbKTMapEntryPtr entry; +xkmKTMapEntryDesc wire_entry; +char buf[100]; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((tmp= XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') { + if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return -1; + } + xkb->names->types= XkbInternAtom(xkb->dpy,buf,False); + } + num_types= XkmGetCARD16(file,&nRead); + nRead+= XkmSkipPadding(file,2); + if (num_types<1) + return nRead; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return nRead; + } + xkb->map->num_types= num_types; + if (num_types<XkbNumRequiredTypes) { + _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0); + return -1; + } + type= xkb->map->types; + for (i=0;i<num_types;i++,type++) { + if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKeyTypeDesc); + if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))|| + (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)|| + ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) { + _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i); + return -1; + } + tmp= wire.nMapEntries; + XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec); + if ((wire.nMapEntries>0)&&(type->map==NULL)) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries); + return -1; + } + for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) { + if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKTMapEntryDesc); + entry->active= (wire_entry.virtualMods==0); + entry->level= wire_entry.level; + entry->mods.mask= wire_entry.realMods; + entry->mods.real_mods= wire_entry.realMods; + entry->mods.vmods= wire_entry.virtualMods; + } + nRead+= XkmGetCountedString(file,buf,100); + if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))|| + ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))|| + ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))|| + ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) { + _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0); + return -1; + } + if (buf[0]!='\0') { + type->name= XkbInternAtom(xkb->dpy,buf,False); + } + else type->name= None; + + if (wire.preserve) { + xkmModsDesc p_entry; + XkbModsPtr pre; + XkmInsureTypedSize(type->preserve,type->map_count,&tmp, + XkbModsRec); + if (type->preserve==NULL) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) { + if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= SIZEOF(xkmModsDesc); + pre->mask= p_entry.realMods; + pre->real_mods= p_entry.realMods; + pre->vmods= p_entry.virtualMods; + } + } + if (wire.nLevelNames>0) { + int width= wire.numLevels; + if (wire.nLevelNames>(unsigned)width) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom); + if (type->level_names!=NULL) { + for (n=0;n<wire.nLevelNames;n++) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + if (strlen(buf)==0) + type->level_names[n]= None; + else type->level_names[n]= XkbInternAtom(xkb->dpy,buf,0); + } + } + } + type->mods.mask= wire.realMods; + type->mods.real_mods= wire.realMods; + type->mods.vmods= wire.virtualMods; + type->num_levels= wire.numLevels; + type->map_count= wire.nMapEntries; + } + if (changes) { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= 0; + changes->map.num_types= xkb->map->num_types; + } + return nRead; +} + +/***====================================================================***/ + +static int +#if NeedFunctionPrototypes +ReadXkmCompatMap(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmCompatMap(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register int i; +unsigned num_si,groups; +char name[100]; +XkbSymInterpretPtr interp; +xkmSymInterpretDesc wire; +unsigned tmp; +int nRead=0; +XkbDescPtr xkb; +XkbCompatMapPtr compat; + + xkb= result->xkb; + if ((tmp= XkmGetCountedString(file,name,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0); + return -1; + } + nRead+= tmp; + if (name[0]!='\0') { + if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0); + return -1; + } + xkb->names->compat= XkbInternAtom(xkb->dpy,name,False); + } + num_si= XkmGetCARD16(file,&nRead); + groups= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success) + return -1; + compat= xkb->compat; + compat->num_si= num_si; + interp= compat->sym_interpret; + for (i=0;i<num_si;i++,interp++) { + tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file); + nRead+= tmp*SIZEOF(xkmSymInterpretDesc); + interp->sym= wire.sym; + interp->mods= wire.mods; + interp->match= wire.match; + interp->virtual_mod= wire.virtualMod; + interp->flags= wire.flags; + interp->act.type= wire.actionType; + interp->act.data[0]= wire.actionData[0]; + interp->act.data[1]= wire.actionData[1]; + interp->act.data[2]= wire.actionData[2]; + interp->act.data[3]= wire.actionData[3]; + interp->act.data[4]= wire.actionData[4]; + interp->act.data[5]= wire.actionData[5]; + interp->act.data[6]= wire.actionData[6]; + } + if ((num_si>0)&&(changes)) { + changes->compat.first_si= 0; + changes->compat.num_si= num_si; + } + if (groups) { + register unsigned bit; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + xkmModsDesc md; + if (groups&bit) { + tmp= fread(&md,SIZEOF(xkmModsDesc),1,file); + nRead+= tmp*SIZEOF(xkmModsDesc); + xkb->compat->groups[i].real_mods= md.realMods; + xkb->compat->groups[i].vmods= md.virtualMods; + if (md.virtualMods != 0) { + unsigned mask; + if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask)) + xkb->compat->groups[i].mask= md.realMods|mask; + } + else xkb->compat->groups[i].mask= md.realMods; + } + } + if (changes) + changes->compat.changed_groups|= groups; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmIndicators(FILE *file,XkbFileInfo *result,XkbChangesPtr changes) +#else +ReadXkmIndicators(file,result,changes) + FILE * file; + XkbFileInfo * result; + XkbChangesPtr changes; +#endif +{ +register unsigned nLEDs; +xkmIndicatorMapDesc wire; +char buf[100]; +unsigned tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) { + _XkbLibError(_XkbErrBadAlloc,"indicator rec",0); + return -1; + } + if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"indicator names",0); + return -1; + } + nLEDs= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,3); + xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead); + while (nLEDs-->0) { + Atom name; + XkbIndicatorMapPtr map; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') + name= XkbInternAtom(xkb->dpy,buf,False); + else name= None; + if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmIndicatorMapDesc); + if (xkb->names) { + xkb->names->indicators[wire.indicator-1]= name; + if (changes) + changes->names.changed_indicators|= (1<<(wire.indicator-1)); + } + map= &xkb->indicators->maps[wire.indicator-1]; + map->flags= wire.flags; + map->which_groups= wire.which_groups; + map->groups= wire.groups; + map->which_mods= wire.which_mods; + map->mods.mask= wire.real_mods; + map->mods.real_mods= wire.real_mods; + map->mods.vmods= wire.vmods; + map->ctrls= wire.ctrls; + } + return nRead; +} + +static XkbKeyTypePtr +#if NeedFunctionPrototypes +FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms) +#else +FindTypeForKey(xkb,name,width,syms) + XkbDescPtr xkb; + Atom name; + unsigned width; + KeySym * syms; +#endif +{ + if ((!xkb)||(!xkb->map)) + return NULL; + if (name!=None) { + register unsigned i; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].name==name) { +#ifdef DEBUG + if (xkb->map->types[i].num_levels!=width) + fprintf(stderr,"Group width mismatch between key and type\n"); +#endif + return &xkb->map->types[i]; + } + } + } + if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol))) + return &xkb->map->types[XkbOneLevelIndex]; + if (syms!=NULL) { + if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1])) + return &xkb->map->types[XkbAlphabeticIndex]; + else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) + return &xkb->map->types[XkbKeypadIndex]; + } + return &xkb->map->types[XkbTwoLevelIndex]; +} + +static int +#if NeedFunctionPrototypes +ReadXkmSymbols(FILE *file,XkbFileInfo *result) +#else +ReadXkmSymbols(file,result) + FILE * file; + XkbFileInfo * result; +#endif +{ +register int i,g,s,totalVModMaps; +xkmKeySymMapDesc wireMap; +char buf[100]; +unsigned minKC,maxKC,groupNames,tmp; +int nRead=0; +XkbDescPtr xkb; + + xkb= result->xkb; + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + groupNames= XkmGetCARD8(file,&nRead); + totalVModMaps= XkmGetCARD8(file,&nRead); + if (XkbAllocNames(xkb, + XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask, + 0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"physical names",0); + return -1; + } + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(xkb->dpy,buf,0); + xkb->names->symbols= name; + xkb->names->phys_symbols= name; + } + for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) { + if (groupNames&g) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(xkb->dpy,buf,0); + xkb->names->groups[i]= name; + } + else xkb->names->groups[i]= None; + } + } + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"server map",0); + return -1; + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"client map",0); + return -1; + } + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"controls",0); + return -1; + } + if ((xkb->map==NULL)||(xkb->server==NULL)) + return -1; + if (xkb->min_key_code<8) xkb->min_key_code= minKC; + if (xkb->max_key_code<8) xkb->max_key_code= maxKC; + if ((minKC>=8)&&(minKC<xkb->min_key_code)) + xkb->min_key_code= minKC; + if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) { + _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC); + return -1; + } + for (i=minKC;i<=(int)maxKC;i++) { + Atom typeName[XkbNumKbdGroups]; + XkbKeyTypePtr type[XkbNumKbdGroups]; + if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmKeySymMapDesc); + bzero((char *)typeName,XkbNumKbdGroups*sizeof(Atom)); + bzero((char *)type,XkbNumKbdGroups*sizeof(XkbKeyTypePtr)); + if (wireMap.flags&XkmKeyHasTypes) { + register int g; + for (g=0;g<XkbNumKbdGroups;g++) { + if ((wireMap.flags&(1<<g))&& + ((tmp=XkmGetCountedString(file,buf,100))>0)) { + typeName[g]= XkbInternAtom(xkb->dpy,buf,1); + nRead+= tmp; + } + type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL); + if (type[g]==NULL) { + _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0); + return -1; + } + if (typeName[g]==type[g]->name) + xkb->server->explicit[i]|= (1<<g); + } + } + if (wireMap.flags&XkmRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + else if (wireMap.flags&XkmNonRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + xkb->map->modmap[i]= wireMap.modifier_map; + if (wireMap.num_groups>0) { + KeySym *sym; + int nSyms; + + if (wireMap.num_groups>xkb->ctrls->num_groups) + xkb->ctrls->num_groups= wireMap.num_groups; + nSyms= wireMap.num_groups*wireMap.width; + sym= XkbResizeKeySyms(xkb,i,nSyms); + if (!sym) + return -1; + for (s=0;s<nSyms;s++) { + *sym++= XkmGetCARD32(file,&nRead); + } + if (wireMap.flags&XkmKeyHasActions) { + XkbAction * act; + act= XkbResizeKeyActions(xkb,i,nSyms); + for (s=0;s<nSyms;s++,act++) { + tmp=fread(act,SIZEOF(xkmActionDesc),1,file); + nRead+= tmp*SIZEOF(xkmActionDesc); + } + xkb->server->explicit[i]|= XkbExplicitInterpretMask; + } + } + for (g=0;g<wireMap.num_groups;g++) { + if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) { + KeySym *tmpSyms; + tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g); + type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms); + } + xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]); + } + xkb->map->key_sym_map[i].group_info= wireMap.num_groups; + xkb->map->key_sym_map[i].width= wireMap.width; + if (wireMap.flags&XkmKeyHasBehavior) { + xkmBehaviorDesc b; + tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file); + nRead+= tmp*SIZEOF(xkmBehaviorDesc); + xkb->server->behaviors[i].type= b.type; + xkb->server->behaviors[i].data= b.data; + xkb->server->explicit[i]|= XkbExplicitBehaviorMask; + } + } + if (totalVModMaps>0) { + xkmVModMapDesc v; + for (i=0;i<totalVModMaps;i++) { + tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file); + nRead+= tmp*SIZEOF(xkmVModMapDesc); + if (tmp>0) + xkb->server->vmodmap[v.key]= v.vmods; + } + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomDoodad( + FILE * file, + Display * dpy, + XkbGeometryPtr geom, + XkbSectionPtr section) +#else +ReadXkmGeomDoodad(file,dpy,geom,section) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; + XkbSectionPtr section; +#endif +{ +XkbDoodadPtr doodad; +xkmDoodadDesc doodadWire; +char buf[100]; +unsigned tmp; +int nRead=0; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file); + nRead+= SIZEOF(xkmDoodadDesc)*tmp; + doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(dpy,buf,False)); + if (!doodad) + return nRead; + doodad->any.type= doodadWire.any.type; + doodad->any.priority= doodadWire.any.priority; + doodad->any.top= doodadWire.any.top; + doodad->any.left= doodadWire.any.left; + switch (doodadWire.any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodad->shape.angle= doodadWire.shape.angle; + doodad->shape.color_ndx= doodadWire.shape.color_ndx; + doodad->shape.shape_ndx= doodadWire.shape.shape_ndx; + break; + case XkbTextDoodad: + doodad->text.angle= doodadWire.text.angle; + doodad->text.width= doodadWire.text.width; + doodad->text.height= doodadWire.text.height; + doodad->text.color_ndx= doodadWire.text.color_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.text= _XkbDupString(buf); + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.font= _XkbDupString(buf); + break; + case XkbIndicatorDoodad: + doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx; + doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx; + doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodad->logo.angle= doodadWire.logo.angle; + doodad->logo.color_ndx= doodadWire.logo.color_ndx; + doodad->logo.shape_ndx= doodadWire.logo.shape_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->logo.logo_name= _XkbDupString(buf); + break; + default: + /* report error? */ + return nRead; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomOverlay( FILE * file, + Display * dpy, + XkbGeometryPtr geom, + XkbSectionPtr section) +#else +ReadXkmGeomOverlay(file,dpy,geom,section) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; + XkbSectionPtr section; +#endif +{ +char buf[100]; +unsigned tmp; +int nRead=0; +XkbOverlayPtr ol; +XkbOverlayRowPtr row; +xkmOverlayDesc olWire; +xkmOverlayRowDesc rowWire; +register int r; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayDesc); + ol= XkbAddGeomOverlay(section,XkbInternAtom(dpy,buf,False), + olWire.num_rows); + if (!ol) + return nRead; + for (r=0;r<olWire.num_rows;r++) { + int k; + xkmOverlayKeyDesc keyWire; + tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayRowDesc); + row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0); + return nRead; + } + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayKeyDesc); + memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength); + memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength); + } + row->num_keys= rowWire.num_keys; + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeomSection( FILE * file, + Display * dpy, + XkbGeometryPtr geom) +#else +ReadXkmGeomSection(file,dpy,geom) + FILE * file; + Display * dpy; + XkbGeometryPtr geom; +#endif +{ +register int i; +XkbSectionPtr section; +xkmSectionDesc sectionWire; +unsigned tmp; +int nRead= 0; +char buf[100]; +Atom nameAtom; + + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(dpy,buf,False); + tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file); + nRead+= SIZEOF(xkmSectionDesc)*tmp; + section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows, + sectionWire.num_doodads, + sectionWire.num_overlays); + if (!section) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + section->top= sectionWire.top; + section->left= sectionWire.left; + section->width= sectionWire.width; + section->height= sectionWire.height; + section->angle= sectionWire.angle; + section->priority= sectionWire.priority; + if (sectionWire.num_rows>0) { + register int k; + XkbRowPtr row; + xkmRowDesc rowWire; + XkbKeyPtr key; + xkmKeyDesc keyWire; + + for (i=0;i<sectionWire.num_rows;i++) { + tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file); + nRead+= SIZEOF(xkmRowDesc)*tmp; + row= XkbAddGeomRow(section,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return nRead; + } + row->top= rowWire.top; + row->left= rowWire.left; + row->vertical= rowWire.vertical; + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file); + nRead+= SIZEOF(xkmKeyDesc)*tmp; + key= XkbAddGeomKey(row); + if (!key) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + memcpy(key->name.name,keyWire.name,XkbKeyNameLength); + key->gap= keyWire.gap; + key->shape_ndx= keyWire.shape_ndx; + key->color_ndx= keyWire.color_ndx; + } + } + } + if (sectionWire.num_doodads>0) { + for (i=0;i<sectionWire.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,dpy,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + if (sectionWire.num_overlays>0) { + for (i=0;i<sectionWire.num_overlays;i++) { + tmp= ReadXkmGeomOverlay(file,dpy,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + return nRead; +} + +static int +#if NeedFunctionPrototypes +ReadXkmGeometry(FILE *file,XkbFileInfo *result) +#else +ReadXkmGeometry(file,result) + FILE * file; + XkbFileInfo * result; +#endif +{ +register int i; +char buf[100]; +unsigned tmp; +int nRead= 0; +xkmGeometryDesc wireGeom; +XkbGeometryPtr geom; +XkbGeometrySizesRec sizes; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file); + nRead+= tmp*SIZEOF(xkmGeometryDesc); + sizes.which= XkbGeomAllMask; + sizes.num_properties= wireGeom.num_properties; + sizes.num_colors= wireGeom.num_colors; + sizes.num_shapes= wireGeom.num_shapes; + sizes.num_sections= wireGeom.num_sections; + sizes.num_doodads= wireGeom.num_doodads; + sizes.num_key_aliases= wireGeom.num_key_aliases; + if (XkbAllocGeometry(result->xkb,&sizes)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + geom= result->xkb->geom; + geom->name= XkbInternAtom(result->xkb->dpy,buf,False); + geom->width_mm= wireGeom.width_mm; + geom->height_mm= wireGeom.height_mm; + nRead+= XkmGetCountedString(file,buf,100); + geom->label_font= _XkbDupString(buf); + if (wireGeom.num_properties>0) { + char val[1024]; + for (i=0;i<wireGeom.num_properties;i++) { + nRead+= XkmGetCountedString(file,buf,100); + nRead+= XkmGetCountedString(file,val,1024); + if (XkbAddGeomProperty(geom,buf,val)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + if (wireGeom.num_colors>0) { + for (i=0;i<wireGeom.num_colors;i++) { + nRead+= XkmGetCountedString(file,buf,100); + if (XkbAddGeomColor(geom,buf,i)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + geom->base_color= &geom->colors[wireGeom.base_color_ndx]; + geom->label_color= &geom->colors[wireGeom.label_color_ndx]; + if (wireGeom.num_shapes>0) { + XkbShapePtr shape; + xkmShapeDesc shapeWire; + Atom nameAtom; + for (i=0;i<wireGeom.num_shapes;i++) { + register int n; + XkbOutlinePtr ol; + xkmOutlineDesc olWire; + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(result->xkb->dpy,buf,False); + tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file); + nRead+= tmp*SIZEOF(xkmShapeDesc); + shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines); + if (!shape) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + for (n=0;n<shapeWire.num_outlines;n++) { + register int p; + xkmPointDesc ptWire; + tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file); + nRead+= tmp*SIZEOF(xkmOutlineDesc); + ol= XkbAddGeomOutline(shape,olWire.num_points); + if (!ol) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + ol->num_points= olWire.num_points; + ol->corner_radius= olWire.corner_radius; + for (p=0;p<olWire.num_points;p++) { + tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file); + nRead+= tmp*SIZEOF(xkmPointDesc); + ol->points[p].x= ptWire.x; + ol->points[p].y= ptWire.y; + if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x; + if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x; + if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y; + if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y; + } + } + if (shapeWire.primary_ndx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire.primary_ndx]; + if (shapeWire.approx_ndx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire.approx_ndx]; + } + } + if (wireGeom.num_sections>0) { + for (i=0;i<wireGeom.num_sections;i++) { + tmp= ReadXkmGeomSection(file,result->xkb->dpy,geom); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if (wireGeom.num_doodads>0) { + for (i=0;i<wireGeom.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,result->xkb->dpy,geom,NULL); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) { + int sz= XkbKeyNameLength*2; + int num= wireGeom.num_key_aliases; + if (fread(geom->key_aliases,sz,num,file)!=num) { + _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0); + return -1; + } + nRead+= (num*sz); + geom->num_key_aliases= num; + } + return nRead; +} + +Bool +#if NeedFunctionPrototypes +XkmProbe(FILE *file) +#else +XkmProbe(file) + FILE * file; +#endif +{ +unsigned hdr,tmp; +int nRead=0; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff); + } + return 0; + } + return 1; +} + +Bool +#if NeedFunctionPrototypes +XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc) +#else +XkmReadTOC(file,file_info,max_toc,toc) + FILE * file; + xkmFileInfo * file_info; + int max_toc; + xkmSectionInfo * toc; +#endif +{ +unsigned hdr,tmp; +int nRead=0; +unsigned i,size_toc; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff); + } + else { + _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp); + } + return 0; + } + fread(file_info,SIZEOF(xkmFileInfo),1,file); + size_toc= file_info->num_toc; + if (size_toc>max_toc) { +#ifdef DEBUG + fprintf(stderr,"Warning! Too many TOC entries; last %d ignored\n", + size_toc-max_toc); +#endif + size_toc= max_toc; + } + for (i=0;i<size_toc;i++) { + fread(&toc[i],SIZEOF(xkmSectionInfo),1,file); + } + return 1; +} + +xkmSectionInfo * +#if NeedFunctionPrototypes +XkmFindTOCEntry(xkmFileInfo *finfo,xkmSectionInfo *toc,unsigned type) +#else +XkmFindTOCEntry(finfo,toc,type) + xkmFileInfo * finfo; + xkmSectionInfo * toc; + unsigned type; +#endif +{ +register int i; + + for (i=0;i<finfo->num_toc;i++) { + if (toc[i].type==type) + return &toc[i]; + } + return NULL; +} + +Bool +#if NeedFunctionPrototypes +XkmReadFileSection( FILE * file, + xkmSectionInfo * toc, + XkbFileInfo * result, + unsigned * loaded_rtrn) +#else +XkmReadFileSection(file,toc,result,loaded_rtrn) + FILE * file; + xkmSectionInfo * toc; + XkbFileInfo * result; + unsigned * loaded_rtrn; +#endif +{ +xkmSectionInfo tmpTOC; +int nRead; + + if ((!result)||(!result->xkb)) { + _XkbLibError(_XkbErrBadMatch,"XkmReadFileSection",0); + return 0; + } + fseek(file,toc->offset,SEEK_SET); + fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + nRead= SIZEOF(xkmSectionInfo); + if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)|| + (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSection",0); + return 0; + } + switch (tmpTOC.type) { + case XkmVirtualModsIndex: + nRead+= ReadXkmVirtualMods(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmVirtualModsMask; + break; + case XkmTypesIndex: + nRead+= ReadXkmKeyTypes(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmTypesMask; + break; + case XkmCompatMapIndex: + nRead+= ReadXkmCompatMap(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmCompatMapMask; + break; + case XkmKeyNamesIndex: + nRead+= ReadXkmKeycodes(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmKeyNamesMask; + break; + case XkmSymbolsIndex: + nRead+= ReadXkmSymbols(file,result); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmSymbolsMask; + break; + case XkmIndicatorsIndex: + nRead+= ReadXkmIndicators(file,result,NULL); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmIndicatorsMask; + break; + case XkmGeometryIndex: + nRead+= ReadXkmGeometry(file,result); + if ((loaded_rtrn)&&(nRead>=0)) + *loaded_rtrn|= XkmGeometryMask; + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + nRead= 0; + break; + } + if (nRead!=tmpTOC.size) { + _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), + nRead-tmpTOC.size); + return 0; + } + return (nRead>=0); +} + +char * +#if NeedFunctionPrototypes +XkmReadFileSectionName(FILE *file,xkmSectionInfo *toc) +#else +XkmReadFileSectionName(file,toc) + FILE * file; + xkmSectionInfo * toc; +#endif +{ +xkmSectionInfo tmpTOC; +char name[100]; + + if ((!file)||(!toc)) + return 0; + switch (toc->type) { + case XkmVirtualModsIndex: + case XkmIndicatorsIndex: + break; + case XkmTypesIndex: + case XkmCompatMapIndex: + case XkmKeyNamesIndex: + case XkmSymbolsIndex: + case XkmGeometryIndex: + fseek(file,toc->offset,SEEK_SET); + fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)|| + (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSectionName",0); + return 0; + } + if (XkmGetCountedString(file,name,100)>0) + return _XkbDupString(name); + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + break; + } + return NULL; +} + +/***====================================================================***/ + +#define MAX_TOC 16 +unsigned +#if NeedFunctionPrototypes +XkmReadFile(FILE *file,unsigned need,unsigned want,XkbFileInfo *result) +#else +XkmReadFile(file,need,want,result) + FILE * file; + unsigned need; + unsigned want; + XkbFileInfo * result; +#endif +{ +register unsigned i; +xkmSectionInfo toc[MAX_TOC],tmpTOC; +xkmFileInfo fileInfo; +unsigned tmp,nRead=0; +unsigned which= need|want; + + if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc)) + return which; + if ((fileInfo.present&need)!=need) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFile", + need&(~fileInfo.present)); + return which; + } + result->type= fileInfo.type; + if (result->xkb==NULL) + result->xkb= XkbAllocKeyboard(); + for (i=0;i<fileInfo.num_toc;i++) { +#ifdef SEEK_SET + fseek(file,toc[i].offset,SEEK_SET); +#else + fseek(file,toc[i].offset,0); +#endif + tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + nRead= tmp*SIZEOF(xkmSectionInfo); + if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)|| + (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) { + return which; + } + if ((which&(1<<tmpTOC.type))==0) { + continue; + } + switch (tmpTOC.type) { + case XkmVirtualModsIndex: + tmp= ReadXkmVirtualMods(file,result,NULL); + break; + case XkmTypesIndex: + tmp= ReadXkmKeyTypes(file,result,NULL); + break; + case XkmCompatMapIndex: + tmp= ReadXkmCompatMap(file,result,NULL); + break; + case XkmKeyNamesIndex: + tmp= ReadXkmKeycodes(file,result,NULL); + break; + case XkmIndicatorsIndex: + tmp= ReadXkmIndicators(file,result,NULL); + break; + case XkmSymbolsIndex: + tmp= ReadXkmSymbols(file,result); + break; + case XkmGeometryIndex: + tmp= ReadXkmGeometry(file,result); + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + tmp= 0; + break; + } + if (tmp>0) { + nRead+= tmp; + which&= ~(1<<toc[i].type); + result->defined|= (1<<toc[i].type); + } + if (nRead!=tmpTOC.size) { + _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), + nRead-tmpTOC.size); + } + } + return which; +} |