aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/xkb/xkbInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/xkb/xkbInit.c')
-rw-r--r--xorg-server/xkb/xkbInit.c902
1 files changed, 902 insertions, 0 deletions
diff --git a/xorg-server/xkb/xkbInit.c b/xorg-server/xkb/xkbInit.c
new file mode 100644
index 000000000..3b47396e5
--- /dev/null
+++ b/xorg-server/xkb/xkbInit.c
@@ -0,0 +1,902 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef HAVE_XKB_CONFIG_H
+#include <xkb-config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <math.h>
+#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 "opaque.h"
+#include "property.h"
+#define XKBSRV_NEED_FILE_FUNCS
+#include <xkbsrv.h>
+#include "xkbgeom.h"
+#include <X11/extensions/XKMformat.h>
+#include "xkbfile.h"
+#include "xkb.h"
+
+#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1)
+
+#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) || 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;
+ XkbDescPtr xkb;
+} SrvXkmInfo;
+
+
+/***====================================================================***/
+
+#ifndef XKB_BASE_DIRECTORY
+#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb"
+#endif
+#ifndef XKB_BIN_DIRECTORY
+#define XKB_BIN_DIRECTORY XKB_BASE_DIRECTORY
+#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 * XkbBinDirectory= XKB_BIN_DIRECTORY;
+static int XkbWantAccessX= 0;
+
+static Bool rulesDefined= False;
+static char * XkbRulesFile= NULL;
+static char * XkbModelDflt= NULL;
+static char * XkbLayoutDflt= NULL;
+static char * XkbVariantDflt= NULL;
+static char * XkbOptionsDflt= NULL;
+
+static char * XkbModelUsed= NULL;
+static char * XkbLayoutUsed= NULL;
+static char * XkbVariantUsed= NULL;
+static char * XkbOptionsUsed= NULL;
+
+static XkbDescPtr xkb_cached_map = NULL;
+
+_X_EXPORT Bool noXkbExtension= XKB_DFLT_DISABLED;
+static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP;
+
+/***====================================================================***/
+
+static char *
+XkbGetRulesDflts(XkbRF_VarDefsPtr defs)
+{
+ 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);
+}
+
+static Bool
+XkbWriteRulesProp(ClientPtr client, pointer closure)
+{
+int len,out;
+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*) xalloc(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);
+ } else {
+ strcpy(&pval[out],XKB_DFLT_RULES_FILE);
+ out+= strlen(XKB_DFLT_RULES_FILE);
+ }
+ 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);
+ }
+ dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
+ PropModeReplace, len, pval, True);
+ xfree(pval);
+ return True;
+}
+
+static void
+XkbSetRulesUsed(XkbRF_VarDefsPtr defs)
+{
+ 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;
+}
+
+_X_EXPORT void
+XkbSetRulesDflts(char *rulesFile,char *model,char *layout,
+ char *variant,char *options)
+{
+ 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;
+}
+
+/***====================================================================***/
+
+#include "xkbDflts.h"
+
+static Bool
+XkbInitKeyTypes(XkbDescPtr xkb)
+{
+ if (xkb->defined & XkmTypesMask)
+ return True;
+
+ initTypeNames(NULL);
+ if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
+ return False;
+ if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
+ Success) {
+ return False;
+ }
+ xkb->map->size_types= xkb->map->num_types= num_dflt_types;
+ return True;
+}
+
+static void
+XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
+{
+ xkbi->nRadioGroups = 0;
+ xkbi->radioGroups = NULL;
+ return;
+}
+
+
+static Status
+XkbInitCompatStructs(XkbDescPtr xkb)
+{
+register int i;
+XkbCompatMapPtr compat;
+
+ if (xkb->defined & XkmCompatMapMask)
+ return True;
+
+ if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
+ return BadAlloc;
+ compat = xkb->compat;
+ if (compat->sym_interpret) {
+ compat->num_si = num_dfltSI;
+ memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
+ }
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ compat->groups[i]= compatMap.groups[i];
+ if (compat->groups[i].vmods!=0) {
+ unsigned mask;
+ mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
+ compat->groups[i].mask= compat->groups[i].real_mods|mask;
+ }
+ else compat->groups[i].mask= compat->groups[i].real_mods;
+ }
+ return Success;
+}
+
+static void
+XkbInitSemantics(XkbDescPtr xkb)
+{
+ XkbInitKeyTypes(xkb);
+ XkbInitCompatStructs(xkb);
+ return;
+}
+
+/***====================================================================***/
+
+static Status
+XkbInitNames(XkbSrvInfoPtr xkbi)
+{
+XkbDescPtr xkb;
+XkbNamesPtr names;
+Status rtrn;
+Atom unknown;
+
+ xkb= xkbi->desc;
+ if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
+ return rtrn;
+ unknown= CREATE_ATOM("unknown");
+ names = xkb->names;
+ if (names->keycodes==None) names->keycodes= unknown;
+ if (names->geometry==None) names->geometry= unknown;
+ if (names->phys_symbols==None) names->phys_symbols= unknown;
+ if (names->symbols==None) names->symbols= unknown;
+ if (names->types==None) names->types= unknown;
+ if (names->compat==None) names->compat= unknown;
+ if (!(xkb->defined & XkmVirtualModsMask)) {
+ if (names->vmods[vmod_NumLock]==None)
+ names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
+ if (names->vmods[vmod_Alt]==None)
+ names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
+ if (names->vmods[vmod_AltGr]==None)
+ names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
+ }
+
+ if (!(xkb->defined & XkmIndicatorsMask) ||
+ !(xkb->defined & XkmGeometryMask)) {
+ initIndicatorNames(NULL,xkb);
+ if (names->indicators[LED_CAPS-1]==None)
+ names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
+ if (names->indicators[LED_NUM-1]==None)
+ names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
+ if (names->indicators[LED_SCROLL-1]==None)
+ names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
+#ifdef LED_COMPOSE
+ if (names->indicators[LED_COMPOSE-1]==None)
+ names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
+#endif
+ }
+
+ if (xkb->geom!=NULL)
+ names->geometry= xkb->geom->name;
+ else names->geometry= unknown;
+
+ return Success;
+}
+
+static Status
+XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
+{
+XkbDescPtr xkb;
+XkbIndicatorPtr map;
+XkbSrvLedInfoPtr sli;
+
+ xkb= xkbi->desc;
+ if (XkbAllocIndicatorMaps(xkb)!=Success)
+ return BadAlloc;
+
+ if (!(xkb->defined & XkmIndicatorsMask)) {
+ map= xkb->indicators;
+ map->phys_indicators = PHYS_LEDS;
+ map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
+ map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
+ map->maps[LED_CAPS-1].mods.mask= LockMask;
+ map->maps[LED_CAPS-1].mods.real_mods= LockMask;
+
+ map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
+ map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
+ map->maps[LED_NUM-1].mods.mask= 0;
+ map->maps[LED_NUM-1].mods.real_mods= 0;
+ map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
+
+ map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
+ map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
+ map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
+ map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
+ }
+
+ sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
+ if (sli)
+ XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
+
+ return Success;
+}
+
+static Status
+XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
+{
+XkbDescPtr xkb;
+XkbControlsPtr ctrls;
+
+ xkb= xkbi->desc;
+ /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
+ if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
+ FatalError("Couldn't allocate keyboard controls\n");
+ ctrls= xkb->ctrls;
+ if (!(xkb->defined & XkmSymbolsMask))
+ ctrls->num_groups = 1;
+ ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
+ ctrls->internal.mask = 0;
+ ctrls->internal.real_mods = 0;
+ ctrls->internal.vmods = 0;
+ ctrls->ignore_lock.mask = 0;
+ ctrls->ignore_lock.real_mods = 0;
+ ctrls->ignore_lock.vmods = 0;
+ ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
+ XkbMouseKeysAccelMask|XkbAudibleBellMask|
+ XkbIgnoreGroupLockMask;
+ if (XkbWantAccessX)
+ ctrls->enabled_ctrls|= XkbAccessXKeysMask;
+ AccessXInit(pXDev);
+ return Success;
+}
+
+void
+XkbInitDevice(DeviceIntPtr pXDev)
+{
+int i;
+XkbSrvInfoPtr xkbi;
+XkbChangesRec changes;
+unsigned check;
+XkbEventCauseRec cause;
+
+ bzero(&changes,sizeof(XkbChangesRec));
+ pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec);
+ if ( xkbi ) {
+ XkbDescPtr xkb;
+
+ if (xkb_cached_map) {
+ xkbi->desc = xkb_cached_map;
+ xkb_cached_map = 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;
+
+ XkbInitSemantics(xkb);
+ XkbInitNames(xkbi);
+ XkbInitRadioGroups(xkbi);
+
+ /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */
+ bzero(&xkbi->state,sizeof(XkbStateRec));
+
+ XkbInitControls(pXDev,xkbi);
+
+ if (xkb->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);
+
+ XkbDDXInitDevice(pXDev);
+
+ if (xkb->defined & XkmSymbolsMask)
+ XkbUpdateCoreDescription(pXDev, True);
+ else
+ XkbUpdateKeyTypesFromCore(pXDev, xkb->min_key_code,
+ XkbNumKeys(xkb), &changes);
+
+ 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;
+ }
+ return;
+}
+
+#if MAP_LENGTH > XkbMaxKeyCount
+#undef XkbMaxKeyCount
+#define XkbMaxKeyCount MAP_LENGTH
+#endif
+
+_X_EXPORT Bool
+XkbInitKeyboardDeviceStruct(
+ DeviceIntPtr dev,
+ XkbComponentNamesPtr names,
+ KeySymsPtr pSymsIn,
+ CARD8 pModsIn[],
+ void (*bellProc)(
+ int /*percent*/,
+ DeviceIntPtr /*device*/,
+ pointer /*ctrl*/,
+ int),
+ void (*ctrlProc)(
+ DeviceIntPtr /*device*/,
+ KeybdCtrl * /*ctrl*/))
+{
+KeySymsRec tmpSyms,*pSyms;
+CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods;
+char name[PATH_MAX],*rules;
+Bool ok=False;
+XkbRF_VarDefsRec defs;
+XkbDescPtr xkb;
+
+ if ((dev->key!=NULL)||(dev->kbdfeed!=NULL))
+ return False;
+ pSyms= pSymsIn;
+ pMods= pModsIn;
+ bzero(&defs,sizeof(XkbRF_VarDefsRec));
+ rules= XkbGetRulesDflts(&defs);
+
+ /*
+ * The strings are duplicated because it is not guaranteed that
+ * they are allocated, or that they are allocated for every server
+ * generation. Eventually they will be freed at the end of this
+ * function.
+ */
+ names->keymap = NULL;
+ if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes);
+ if (names->types) names->types = _XkbDupString(names->types);
+ if (names->compat) names->compat = _XkbDupString(names->compat);
+ if (names->geometry) names->geometry = _XkbDupString(names->geometry);
+ if (names->symbols) names->symbols = _XkbDupString(names->symbols);
+
+ if (defs.model && defs.layout && rules) {
+ XkbComponentNamesRec rNames;
+ bzero(&rNames,sizeof(XkbComponentNamesRec));
+ if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) {
+ if (rNames.keycodes) {
+ if (!names->keycodes)
+ names->keycodes = rNames.keycodes;
+ else
+ _XkbFree(rNames.keycodes);
+ }
+ if (rNames.types) {
+ if (!names->types)
+ names->types = rNames.types;
+ else _XkbFree(rNames.types);
+ }
+ if (rNames.compat) {
+ if (!names->compat)
+ names->compat = rNames.compat;
+ else _XkbFree(rNames.compat);
+ }
+ if (rNames.symbols) {
+ if (!names->symbols)
+ names->symbols = rNames.symbols;
+ else _XkbFree(rNames.symbols);
+ }
+ if (rNames.geometry) {
+ if (!names->geometry)
+ names->geometry = rNames.geometry;
+ else _XkbFree(rNames.geometry);
+ }
+ XkbSetRulesUsed(&defs);
+ }
+ }
+
+ ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0,
+ &xkb,name,PATH_MAX);
+
+ if (ok && (xkb!=NULL)) {
+ KeyCode minKC,maxKC;
+
+ 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;
+ }
+ }
+ /* Store the map here so we can pick it back up in XkbInitDevice.
+ * Sigh. */
+ xkb_cached_map = xkb;
+ }
+ else {
+ LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n");
+ }
+ ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc);
+ xkb_cached_map = NULL;
+ if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) {
+ _XkbFree(pSyms->map);
+ pSyms->map= NULL;
+ }
+
+ if (names->keycodes) _XkbFree(names->keycodes);
+ names->keycodes = NULL;
+ if (names->types) _XkbFree(names->types);
+ names->types = NULL;
+ if (names->compat) _XkbFree(names->compat);
+ names->compat = NULL;
+ if (names->geometry) _XkbFree(names->geometry);
+ names->geometry = NULL;
+ if (names->symbols) _XkbFree(names->symbols);
+ names->symbols = 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
+XkbFinishDeviceInit(DeviceIntPtr pXDev)
+{
+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);
+ else DebugF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
+ 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
+XkbFreeInfo(XkbSrvInfoPtr xkbi)
+{
+ if (xkbi->radioGroups) {
+ _XkbFree(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;
+ }
+ _XkbFree(xkbi);
+ return;
+}
+
+/***====================================================================***/
+
+extern int XkbDfltRepeatDelay;
+extern int XkbDfltRepeatInterval;
+
+extern unsigned short XkbDfltAccessXTimeout;
+extern unsigned int XkbDfltAccessXTimeoutMask;
+extern unsigned int XkbDfltAccessXFeedback;
+extern unsigned char XkbDfltAccessXOptions;
+
+int
+XkbProcessArguments(int argc,char *argv[],int i)
+{
+ if (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], "-xkbdir", 7) == 0) {
+ if(++i < argc) {
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (getuid() != geteuid()) {
+ LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
+ return -1;
+ } else
+#endif
+ {
+ if (strlen(argv[i]) < PATH_MAX) {
+ XkbBaseDirectory= argv[i];
+ return 2;
+ } else {
+ LogMessage(X_ERROR, "-xkbdir pathname too long\n");
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else if ((strncmp(argv[i],"-accessx",8)==0)||
+ (strncmp(argv[i],"+accessx",8)==0)) {
+ int j=1;
+ if (argv[i][0]=='-')
+ XkbWantAccessX= 0;
+ else {
+ XkbWantAccessX= 1;
+
+ if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
+ XkbDfltAccessXTimeout = atoi(argv[++i]);
+ j++;
+
+ if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
+ /*
+ * presumption that the reasonably useful range of
+ * values fits in 0..MAXINT since SunOS 4 doesn't
+ * have strtoul.
+ */
+ XkbDfltAccessXTimeoutMask=(unsigned int)
+ strtol(argv[++i],NULL,16);
+ j++;
+ }
+ if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
+ if (argv[++i][0] == '1' )
+ XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
+ else
+ XkbDfltAccessXFeedback=0;
+ j++;
+ }
+ if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
+ XkbDfltAccessXOptions=(unsigned char)
+ strtol(argv[++i],NULL,16);
+ j++;
+ }
+ }
+ }
+ return j;
+ }
+ if ((strcmp(argv[i], "-ardelay") == 0) ||
+ (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */
+ if (++i >= argc) UseMsg ();
+ XkbDfltRepeatDelay = (long)atoi(argv[i]);
+ return 2;
+ }
+ if ((strcmp(argv[i], "-arinterval") == 0) ||
+ (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */
+ if (++i >= argc) UseMsg ();
+ XkbDfltRepeatInterval = (long)atoi(argv[i]);
+ return 2;
+ }
+ return 0;
+}
+
+void
+XkbUseMsg(void)
+{
+ ErrorF("-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("-ardelay set XKB autorepeat delay\n");
+ ErrorF("-arinterval set XKB autorepeat interval\n");
+}