aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/xkb/xkb.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
committermarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
commit3562e78743202e43aec8727005182a2558117eca (patch)
tree8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/xkb/xkb.c
downloadvcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz
vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2
vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip
Checked in the following released items:
xkeyboard-config-1.4.tar.gz ttf-bitstream-vera-1.10.tar.gz font-alias-1.0.1.tar.gz font-sun-misc-1.0.0.tar.gz font-sun-misc-1.0.0.tar.gz font-sony-misc-1.0.0.tar.gz font-schumacher-misc-1.0.0.tar.gz font-mutt-misc-1.0.0.tar.gz font-misc-misc-1.0.0.tar.gz font-misc-meltho-1.0.0.tar.gz font-micro-misc-1.0.0.tar.gz font-jis-misc-1.0.0.tar.gz font-isas-misc-1.0.0.tar.gz font-dec-misc-1.0.0.tar.gz font-daewoo-misc-1.0.0.tar.gz font-cursor-misc-1.0.0.tar.gz font-arabic-misc-1.0.0.tar.gz font-winitzki-cyrillic-1.0.0.tar.gz font-misc-cyrillic-1.0.0.tar.gz font-cronyx-cyrillic-1.0.0.tar.gz font-screen-cyrillic-1.0.1.tar.gz font-xfree86-type1-1.0.1.tar.gz font-adobe-utopia-type1-1.0.1.tar.gz font-ibm-type1-1.0.0.tar.gz font-bitstream-type1-1.0.0.tar.gz font-bitstream-speedo-1.0.0.tar.gz font-bh-ttf-1.0.0.tar.gz font-bh-type1-1.0.0.tar.gz font-bitstream-100dpi-1.0.0.tar.gz font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz font-bh-100dpi-1.0.0.tar.gz font-adobe-utopia-100dpi-1.0.1.tar.gz font-adobe-100dpi-1.0.0.tar.gz font-util-1.0.1.tar.gz font-bitstream-75dpi-1.0.0.tar.gz font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz font-adobe-utopia-75dpi-1.0.1.tar.gz font-bh-75dpi-1.0.0.tar.gz bdftopcf-1.0.1.tar.gz font-adobe-75dpi-1.0.0.tar.gz mkfontscale-1.0.6.tar.gz openssl-0.9.8k.tar.gz bigreqsproto-1.0.2.tar.gz xtrans-1.2.2.tar.gz resourceproto-1.0.2.tar.gz inputproto-1.4.4.tar.gz compositeproto-0.4.tar.gz damageproto-1.1.0.tar.gz zlib-1.2.3.tar.gz xkbcomp-1.0.5.tar.gz freetype-2.3.9.tar.gz pthreads-w32-2-8-0-release.tar.gz pixman-0.12.0.tar.gz kbproto-1.0.3.tar.gz evieext-1.0.2.tar.gz fixesproto-4.0.tar.gz recordproto-1.13.2.tar.gz randrproto-1.2.2.tar.gz scrnsaverproto-1.1.0.tar.gz renderproto-0.9.3.tar.gz xcmiscproto-1.1.2.tar.gz fontsproto-2.0.2.tar.gz xextproto-7.0.3.tar.gz xproto-7.0.14.tar.gz libXdmcp-1.0.2.tar.gz libxkbfile-1.0.5.tar.gz libfontenc-1.0.4.tar.gz libXfont-1.3.4.tar.gz libX11-1.1.5.tar.gz libXau-1.0.4.tar.gz libxcb-1.1.tar.gz xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/xkb/xkb.c')
-rw-r--r--xorg-server/xkb/xkb.c6736
1 files changed, 6736 insertions, 0 deletions
diff --git a/xorg-server/xkb/xkb.c b/xorg-server/xkb/xkb.c
new file mode 100644
index 000000000..7c569d483
--- /dev/null
+++ b/xorg-server/xkb/xkb.c
@@ -0,0 +1,6736 @@
+/************************************************************
+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
+
+#include <stdio.h>
+#include <X11/X.h>
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#define XKBSRV_NEED_FILE_FUNCS
+#include <xkbsrv.h>
+#include "extnsionst.h"
+#include "xace.h"
+#include "xkb.h"
+
+#include <X11/extensions/XI.h>
+
+ int XkbEventBase;
+static int XkbErrorBase;
+ int XkbReqCode;
+ int XkbKeyboardErrorCode;
+CARD32 xkbDebugFlags = 0;
+static CARD32 xkbDebugCtrls = 0;
+
+static RESTYPE RT_XKBCLIENT;
+
+/***====================================================================***/
+
+#define CHK_DEVICE(dev, id, client, access_mode, lf) {\
+ int why;\
+ int rc = lf(&(dev), id, client, access_mode, &why);\
+ if (rc != Success) {\
+ client->errorValue = _XkbErrCode2(why, id);\
+ return rc;\
+ }\
+}
+
+#define CHK_KBD_DEVICE(dev, id, client, mode) \
+ CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
+#define CHK_LED_DEVICE(dev, id, client, mode) \
+ CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
+#define CHK_BELL_DEVICE(dev, id, client, mode) \
+ CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
+#define CHK_ANY_DEVICE(dev, id, client, mode) \
+ CHK_DEVICE(dev, id, client, mode, _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
+ProcXkbUseExtension(ClientPtr client)
+{
+ 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;
+
+ 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%lx) (wants %d.%02d, have %d.%02d)\n",
+ client->index,
+ (long)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
+ProcXkbSelectEvents(ClientPtr client)
+{
+ 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, client, DixUseAccess);
+
+ 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;
+}
+
+/***====================================================================***/
+/**
+ * Ring a bell on the given device for the given client.
+ */
+static int
+_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
+ int bellClass, int bellID, int pitch, int duration,
+ int percent, int forceSound, int eventOnly, Atom name)
+{
+ int base;
+ pointer ctrl;
+ int oldPitch, oldDuration;
+ int newPercent;
+
+ if (bellClass == KbdFeedbackClass) {
+ KbdFeedbackPtr k;
+ if (bellID==XkbDfltXIId)
+ k= dev->kbdfeed;
+ else {
+ for (k=dev->kbdfeed; k; k=k->next) {
+ if (k->ctrl.id == bellID)
+ break;
+ }
+ }
+ if (!k) {
+ client->errorValue = _XkbErrCode2(0x5,bellID);
+ return BadValue;
+ }
+ base = k->ctrl.bell;
+ ctrl = (pointer) &(k->ctrl);
+ oldPitch= k->ctrl.bell_pitch;
+ oldDuration= k->ctrl.bell_duration;
+ if (pitch!=0) {
+ if (pitch==-1)
+ k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
+ else k->ctrl.bell_pitch= pitch;
+ }
+ if (duration!=0) {
+ if (duration==-1)
+ k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
+ else k->ctrl.bell_duration= duration;
+ }
+ }
+ else if (bellClass == BellFeedbackClass) {
+ BellFeedbackPtr b;
+ if (bellID==XkbDfltXIId)
+ b= dev->bell;
+ else {
+ for (b=dev->bell; b; b=b->next) {
+ if (b->ctrl.id == bellID)
+ break;
+ }
+ }
+ if (!b) {
+ client->errorValue = _XkbErrCode2(0x6,bellID);
+ return BadValue;
+ }
+ base = b->ctrl.percent;
+ ctrl = (pointer) &(b->ctrl);
+ oldPitch= b->ctrl.pitch;
+ oldDuration= b->ctrl.duration;
+ if (pitch!=0) {
+ if (pitch==-1)
+ b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
+ else b->ctrl.pitch= pitch;
+ }
+ if (duration!=0) {
+ if (duration==-1)
+ b->ctrl.duration= defaultKeyboardControl.bell_duration;
+ else b->ctrl.duration= duration;
+ }
+ }
+ else {
+ client->errorValue = _XkbErrCode2(0x7, bellClass);;
+ return BadValue;
+ }
+
+ newPercent = (base * percent)/100;
+ if (percent < 0)
+ newPercent = base + newPercent;
+ else newPercent = base - newPercent + percent;
+
+ XkbHandleBell(forceSound, eventOnly,
+ dev, newPercent, ctrl, bellClass,
+ name, pWin, client);
+ if ((pitch!=0)||(duration!=0)) {
+ if (bellClass == KbdFeedbackClass) {
+ KbdFeedbackPtr k;
+ k= (KbdFeedbackPtr)ctrl;
+ if (pitch!=0)
+ k->ctrl.bell_pitch= oldPitch;
+ if (duration!=0)
+ k->ctrl.bell_duration= oldDuration;
+ }
+ else {
+ BellFeedbackPtr b;
+ b= (BellFeedbackPtr)ctrl;
+ if (pitch!=0)
+ b->ctrl.pitch= oldPitch;
+ if (duration!=0)
+ b->ctrl.duration= oldDuration;
+ }
+ }
+
+ return Success;
+}
+
+int
+ProcXkbBell(ClientPtr client)
+{
+ REQUEST(xkbBellReq);
+ DeviceIntPtr dev;
+ WindowPtr pWin;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xkbBellReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
+ CHK_ATOM_OR_NONE(stuff->name);
+
+ /* device-independent checks request for sane values */
+ 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->window!=None) {
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success) {
+ client->errorValue= stuff->window;
+ return rc;
+ }
+ }
+ else pWin= NULL;
+
+ /* Client wants to ring a bell on the core keyboard?
+ Ring the bell on the core keyboard (which does nothing, but if that
+ fails the client is screwed anyway), and then on all extension devices.
+ Fail if the core keyboard fails but not the extension devices. this
+ may cause some keyboards to ding and others to stay silent. Fix
+ your client to use explicit keyboards to avoid this.
+
+ dev is the device the client requested.
+ */
+ rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
+ stuff->pitch, stuff->duration, stuff->percent,
+ stuff->forceSound, stuff->eventOnly, stuff->name);
+
+ if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
+ (stuff->deviceSpec == XkbUseCorePtr)))
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
+ if (rc == Success)
+ _XkbBell(client, other, pWin, stuff->bellClass,
+ stuff->bellID, stuff->pitch, stuff->duration,
+ stuff->percent, stuff->forceSound,
+ stuff->eventOnly, stuff->name);
+ }
+ }
+ rc = Success; /* reset to success, that's what we got for the VCK */
+ }
+
+ return rc;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbGetState(ClientPtr client)
+{
+ REQUEST(xkbGetStateReq);
+ DeviceIntPtr dev;
+ xkbGetStateReply rep;
+ XkbStateRec *xkb;
+
+ REQUEST_SIZE_MATCH(xkbGetStateReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
+
+ 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
+ProcXkbLatchLockState(ClientPtr client)
+{
+ int status;
+ DeviceIntPtr dev, tmpd;
+ XkbStateRec oldState,*newState;
+ CARD16 changed;
+ xkbStateNotify sn;
+ XkbEventCauseRec cause;
+
+ REQUEST(xkbLatchLockStateReq);
+ REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
+
+ if (!(client->xkbClientFlags & _XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
+ CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
+ CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
+
+ status = Success;
+
+ for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
+ if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
+ tmpd == dev) {
+ if (!tmpd->key->xkbInfo)
+ continue;
+
+ oldState = tmpd->key->xkbInfo->state;
+ newState = &tmpd->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(tmpd, stuff->affectModLatches,
+ stuff->modLatches);
+ if (status == Success && stuff->latchGroup)
+ status = XkbLatchGroup(tmpd, stuff->groupLatch);
+
+ if (status != Success)
+ return status;
+
+ XkbComputeDerivedState(tmpd->key->xkbInfo);
+ tmpd->key->state = XkbStateFieldFromRec(newState);
+
+ changed = XkbStateChangedFlags(&oldState, newState);
+ if (changed) {
+ sn.keycode = 0;
+ sn.eventType = 0;
+ sn.requestMajor = XkbReqCode;
+ sn.requestMinor = X_kbLatchLockState;
+ sn.changed = changed;
+ XkbSendStateNotify(tmpd, &sn);
+ changed = XkbIndicatorsToUpdate(tmpd, changed, False);
+ if (changed) {
+ XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
+ XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
+ }
+ }
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbGetControls(ClientPtr client)
+{
+ 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, client, DixGetAttrAccess);
+
+ 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
+ProcXkbSetControls(ClientPtr client)
+{
+ DeviceIntPtr dev, tmpd;
+ 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, client, DixManageAccess);
+ CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
+
+ for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) {
+ if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
+ tmpd == dev) {
+
+ xkbi = tmpd->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(tmpd, &old, ctrl);
+
+ if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) {
+ cn.keycode = 0;
+ cn.eventType = 0;
+ cn.requestMajor = XkbReqCode;
+ cn.requestMinor = X_kbSetControls;
+ XkbSendControlsNotify(tmpd, &cn);
+ }
+
+ sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
+ if (sli)
+ XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL,
+ &cause);
+
+ /* If sticky keys were disabled, clear all locks and latches */
+ if ((old.enabled_ctrls & XkbStickyKeysMask) &&
+ !(ctrl->enabled_ctrls & XkbStickyKeysMask))
+ XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause);
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+static int
+XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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 *
+XkbWriteKeyTypes( XkbDescPtr xkb,
+ xkbGetMapReply * rep,
+ char * buf,
+ ClientPtr client)
+{
+ 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
+XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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
+XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+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 *
+XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
+{
+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
+XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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 *
+XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
+ ClientPtr client)
+{
+ 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
+XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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 *
+XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
+ ClientPtr client)
+{
+ 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
+XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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 *
+XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
+{
+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
+XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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 *
+XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
+ ClientPtr client)
+{
+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
+XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+ 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-1;i++) {
+ if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
+ nRtrn++;
+ }
+ rep->totalVModMapKeys= nRtrn;
+ len= nRtrn*SIZEOF(xkbVModMapWireDesc);
+ return len;
+}
+
+static char *
+XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
+ ClientPtr client)
+{
+unsigned i;
+xkbVModMapWireDesc * wire;
+unsigned short * pMap;
+
+ wire= (xkbVModMapWireDesc *)buf;
+ pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
+ for (i=0;i<rep->nVModMapKeys-1;i++,pMap++) {
+ if (*pMap!=0) {
+ wire->key= i+rep->firstVModMapKey;
+ wire->vmods= *pMap;
+ wire++;
+ }
+ }
+ return (char *)wire;
+}
+
+static Status
+XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+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
+XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
+{
+unsigned i,len;
+char *desc,*start;
+
+ len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
+ start= desc= (char *)xalloc(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 %ld\n",
+ len, (unsigned long)(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);
+ xfree((char *)start);
+ return client->noClientException;
+}
+
+int
+ProcXkbGetMap(ClientPtr client)
+{
+ 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, client, DixGetAttrAccess);
+ 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
+CheckKeyTypes( ClientPtr client,
+ XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ xkbKeyTypeWireDesc **wireRtrn,
+ int * nMapsRtrn,
+ CARD8 * mapWidthRtrn)
+{
+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
+CheckKeySyms( ClientPtr client,
+ XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ int nTypes,
+ CARD8 * mapWidths,
+ CARD16 * symsPerKey,
+ xkbSymMapWireDesc ** wireRtrn,
+ int * errorRtrn)
+{
+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
+CheckKeyActions( XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ int nTypes,
+ CARD8 * mapWidths,
+ CARD16 * symsPerKey,
+ CARD8 ** wireRtrn,
+ int * nActsRtrn)
+{
+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
+CheckKeyBehaviors( XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ xkbBehaviorWireDesc ** wireRtrn,
+ int * errorRtrn)
+{
+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
+CheckVirtualMods( XkbDescRec * xkb,
+ xkbSetMapReq * req,
+ CARD8 ** wireRtrn,
+ int * errorRtrn)
+{
+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
+CheckKeyExplicit( XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ CARD8 ** wireRtrn,
+ int * errorRtrn)
+{
+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
+CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
+{
+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
+CheckVirtualModMap( XkbDescPtr xkb,
+ xkbSetMapReq *req,
+ xkbVModMapWireDesc **wireRtrn,
+ int *errRtrn)
+{
+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 *
+SetKeyTypes( XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ xkbKeyTypeWireDesc * wire,
+ XkbChangesPtr changes)
+{
+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 *
+SetKeySyms( ClientPtr client,
+ XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ xkbSymMapWireDesc * wire,
+ XkbChangesPtr changes,
+ DeviceIntPtr dev)
+{
+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 *
+SetKeyActions( XkbDescPtr xkb,
+ xkbSetMapReq * req,
+ CARD8 * wire,
+ XkbChangesPtr changes)
+{
+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 *
+SetKeyBehaviors( XkbSrvInfoPtr xkbi,
+ xkbSetMapReq *req,
+ xkbBehaviorWireDesc *wire,
+ XkbChangesPtr changes)
+{
+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 + 1;
+ }
+ wire++;
+ }
+
+ if (maxRG>(int)xkbi->nRadioGroups) {
+ int sz = maxRG*sizeof(XkbRadioGroupRec);
+ if (xkbi->radioGroups)
+ xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
+ else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
+ if (xkbi->radioGroups) {
+ if (xkbi->nRadioGroups)
+ bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
+ (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
+ xkbi->nRadioGroups= maxRG;
+ }
+ 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 *
+SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
+ XkbChangesPtr changes)
+{
+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 *
+SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
+ XkbChangesPtr changes)
+{
+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 *
+SetModifierMap( XkbSrvInfoPtr xkbi,
+ xkbSetMapReq * req,
+ CARD8 * wire,
+ XkbChangesPtr changes)
+{
+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 *
+SetVirtualModMap( XkbSrvInfoPtr xkbi,
+ xkbSetMapReq * req,
+ xkbVModMapWireDesc * wire,
+ XkbChangesPtr changes)
+{
+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;
+}
+
+/**
+ * Check if the given request can be applied to the given device but don't
+ * actually do anything..
+ */
+static int
+_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
+{
+ XkbSrvInfoPtr xkbi;
+ XkbDescPtr xkb;
+ int error;
+ int nTypes = 0, nActions;
+ CARD8 mapWidths[XkbMaxLegalKeyCode + 1];
+ CARD16 symsPerKey[XkbMaxLegalKeyCode + 1];
+
+ xkbi= dev->key->xkbInfo;
+ xkb = xkbi->desc;
+
+ if ((xkb->min_key_code != req->minKeyCode)||
+ (xkb->max_key_code != req->maxKeyCode)) {
+ if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
+ req->minKeyCode= xkb->min_key_code;
+ req->maxKeyCode= xkb->max_key_code;
+ }
+ else {
+ if (!XkbIsLegalKeycode(req->minKeyCode)) {
+ client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
+ return BadValue;
+ }
+ if (req->minKeyCode > req->maxKeyCode) {
+ client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
+ return BadMatch;
+ }
+ }
+ }
+
+ if ((req->present & XkbKeyTypesMask) &&
+ (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
+ &nTypes,mapWidths))) {
+ client->errorValue = nTypes;
+ return BadValue;
+ }
+ if ((req->present & XkbKeySymsMask) &&
+ (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
+ (xkbSymMapWireDesc **)&values,&error))) {
+ client->errorValue = error;
+ return BadValue;
+ }
+
+ if ((req->present & XkbKeyActionsMask) &&
+ (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
+ (CARD8 **)&values,&nActions))) {
+ client->errorValue = nActions;
+ return BadValue;
+ }
+
+ if ((req->present & XkbKeyBehaviorsMask) &&
+ (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
+ client->errorValue = error;
+ return BadValue;
+ }
+
+ if ((req->present & XkbVirtualModsMask) &&
+ (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
+ client->errorValue= error;
+ return BadValue;
+ }
+ if ((req->present&XkbExplicitComponentsMask) &&
+ (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
+ client->errorValue= error;
+ return BadValue;
+ }
+ if ((req->present&XkbModifierMapMask) &&
+ (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
+ client->errorValue= error;
+ return BadValue;
+ }
+ if ((req->present&XkbVirtualModMapMask) &&
+ (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
+ client->errorValue= error;
+ return BadValue;
+ }
+
+ if (((values-((char *)req))/4)!= req->length) {
+ ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
+ client->errorValue = values-((char *)&req[1]);
+ return BadLength;
+ }
+
+ return Success;
+}
+
+/**
+ * Apply the given request on the given device.
+ */
+static int
+_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values)
+{
+ XkbEventCauseRec cause;
+ XkbChangesRec change;
+ Bool sentNKN;
+ XkbSrvInfoPtr xkbi;
+ XkbDescPtr xkb;
+
+ xkbi= dev->key->xkbInfo;
+ xkb = xkbi->desc;
+
+ XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
+ bzero(&change, sizeof(change));
+ sentNKN = False;
+ if ((xkb->min_key_code!=req->minKeyCode)||
+ (xkb->max_key_code!=req->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, req->minKeyCode,
+ req->maxKeyCode, &change);
+ if (status != Success)
+ return status; /* oh-oh. what about the other keyboards? */
+ 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;
+ }
+
+ if (req->present&XkbKeyTypesMask) {
+ values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
+ if (!values) goto allocFailure;
+ }
+ if (req->present&XkbKeySymsMask) {
+ values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
+ if (!values) goto allocFailure;
+ }
+ if (req->present&XkbKeyActionsMask) {
+ values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
+ if (!values) goto allocFailure;
+ }
+ if (req->present&XkbKeyBehaviorsMask) {
+ values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
+ if (!values) goto allocFailure;
+ }
+ if (req->present&XkbVirtualModsMask)
+ values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
+ if (req->present&XkbExplicitComponentsMask)
+ values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
+ if (req->present&XkbModifierMapMask)
+ values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
+ if (req->present&XkbVirtualModMapMask)
+ values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
+ if (((values-((char *)req))/4)!=req->length) {
+ ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
+ client->errorValue = values-((char *)&req[1]);
+ return BadLength;
+ }
+ if (req->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 Success;
+allocFailure:
+ return BadAlloc;
+}
+
+
+int
+ProcXkbSetMap(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ char * tmp;
+ int rc;
+
+ REQUEST(xkbSetMapReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
+ CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
+
+ tmp = (char *)&stuff[1];
+
+ /* Check if we can to the SetMap on the requested device. If this
+ succeeds, do the same thing for all extension devices (if needed).
+ If any of them fails, fail. */
+ rc = _XkbSetMapChecks(client, dev, stuff, tmp);
+
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ rc = _XkbSetMapChecks(client, other, stuff, tmp);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ /* We know now that we will succed with the SetMap. In theory anyway. */
+ rc = _XkbSetMap(client, dev, stuff, tmp);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ _XkbSetMap(client, other, stuff, tmp);
+ /* ignore rc. if the SetMap failed although the check above
+ reported true there isn't much we can do. we still need to
+ set all other devices, hoping that at least they stay in
+ sync. */
+ }
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+static Status
+XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat,
+ xkbGetCompatMapReply * rep)
+{
+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
+XkbSendCompatMap( ClientPtr client,
+ XkbCompatMapPtr compat,
+ xkbGetCompatMapReply * rep)
+{
+char * data;
+int size;
+
+ size= rep->length*4;
+ if (size>0) {
+ data = (char *)xalloc(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);
+ xfree((char *)data);
+ }
+ return client->noClientException;
+}
+
+int
+ProcXkbGetCompatMap(ClientPtr client)
+{
+ 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, client, DixGetAttrAccess);
+
+ 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);
+}
+
+/**
+ * Apply the given request on the given device.
+ * If dryRun is True, then value checks are performed, but the device isn't
+ * modified.
+ */
+static int
+_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
+ xkbSetCompatMapReq *req, char* data, BOOL dryRun)
+{
+ XkbSrvInfoPtr xkbi;
+ XkbDescPtr xkb;
+ XkbCompatMapPtr compat;
+ int nGroups;
+ unsigned i,bit;
+
+ xkbi = dev->key->xkbInfo;
+ xkb = xkbi->desc;
+ compat = xkb->compat;
+
+ if ((req->nSI>0)||(req->truncateSI)) {
+ xkbSymInterpretWireDesc *wire;
+ if (req->firstSI>compat->num_si) {
+ client->errorValue = _XkbErrCode2(0x02,compat->num_si);
+ return BadValue;
+ }
+ wire= (xkbSymInterpretWireDesc *)data;
+ wire+= req->nSI;
+ data = (char *)wire;
+ }
+
+ nGroups= 0;
+ if (req->groups!=0) {
+ for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
+ if ( req->groups&bit )
+ nGroups++;
+ }
+ }
+ data+= nGroups*SIZEOF(xkbModsWireDesc);
+ if (((data-((char *)req))/4)!=req->length) {
+ return BadLength;
+ }
+
+ /* Done all the checks we can do */
+ if (dryRun)
+ return Success;
+
+ data = (char *)&req[1];
+ if (req->nSI>0) {
+ xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
+ XkbSymInterpretPtr sym;
+ if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
+ compat->num_si= req->firstSI+req->nSI;
+ compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
+ compat->num_si,
+ XkbSymInterpretRec);
+ if (!compat->sym_interpret) {
+ compat->num_si= 0;
+ return BadAlloc;
+ }
+ }
+ else if (req->truncateSI) {
+ compat->num_si = req->firstSI+req->nSI;
+ }
+ sym = &compat->sym_interpret[req->firstSI];
+ for (i=0;i<req->nSI;i++,wire++,sym++) {
+ if (client->swapped) {
+ 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 (req->truncateSI) {
+ compat->num_si = req->firstSI;
+ }
+
+ if (req->groups!=0) {
+ unsigned i, bit;
+ xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
+ for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
+ if (req->groups & bit) {
+ if (client->swapped) {
+ 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 *)req)));
+ if ((i/4)!=req->length) {
+ ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
+ return BadLength;
+ }
+
+ if (dev->xkb_interest) {
+ xkbCompatMapNotify ev;
+ ev.deviceID = dev->id;
+ ev.changedGroups = req->groups;
+ ev.firstSI = req->firstSI;
+ ev.nSI = req->nSI;
+ ev.nTotalSI = compat->num_si;
+ XkbSendCompatMapNotify(dev,&ev);
+ }
+
+ if (req->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 Success;
+}
+
+int
+ProcXkbSetCompatMap(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ char *data;
+ int rc;
+
+ REQUEST(xkbSetCompatMapReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
+
+ data = (char *)&stuff[1];
+
+ /* check first using a dry-run */
+ rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
+ if (rc != Success)
+ return rc;
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ /* dry-run */
+ rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ /* Yay, the dry-runs succeed. Let's apply */
+ rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
+ if (rc != Success)
+ return rc;
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbGetIndicatorState(ClientPtr client)
+{
+ 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, client, DixReadAccess);
+
+ 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;
+}
+
+/***====================================================================***/
+
+static Status
+XkbComputeGetIndicatorMapReplySize(
+ XkbIndicatorPtr indicators,
+ xkbGetIndicatorMapReply *rep)
+{
+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;
+}
+
+static int
+XkbSendIndicatorMap( ClientPtr client,
+ XkbIndicatorPtr indicators,
+ xkbGetIndicatorMapReply * rep)
+{
+int length;
+CARD8 * map;
+register int i;
+register unsigned bit;
+
+ length = rep->length*4;
+ if (length>0) {
+ CARD8 *to;
+ to= map= (CARD8 *)xalloc(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);
+ xfree((char *)map);
+ }
+ return client->noClientException;
+}
+
+int
+ProcXkbGetIndicatorMap(ClientPtr client)
+{
+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, client, DixGetAttrAccess);
+
+ 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);
+}
+
+/**
+ * Apply the given map to the given device. Which specifies which components
+ * to apply.
+ */
+static int
+_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
+ int which, xkbIndicatorMapWireDesc *desc)
+{
+ XkbSrvInfoPtr xkbi;
+ XkbSrvLedInfoPtr sli;
+ XkbEventCauseRec cause;
+ int i, bit;
+
+ xkbi = dev->key->xkbInfo;
+
+ sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
+ XkbXI_IndicatorMapsMask);
+ if (!sli)
+ return BadAlloc;
+
+ for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
+ if (which & bit) {
+ sli->maps[i].flags = desc->flags;
+ sli->maps[i].which_groups = desc->whichGroups;
+ sli->maps[i].groups = desc->groups;
+ sli->maps[i].which_mods = desc->whichMods;
+ sli->maps[i].mods.mask = desc->mods;
+ sli->maps[i].mods.real_mods = desc->mods;
+ sli->maps[i].mods.vmods= desc->virtualMods;
+ sli->maps[i].ctrls = desc->ctrls;
+ if (desc->virtualMods!=0) {
+ unsigned tmp;
+ tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods);
+ sli->maps[i].mods.mask= desc->mods|tmp;
+ }
+ desc++;
+ }
+ }
+
+ XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
+ XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause);
+
+ return Success;
+}
+
+int
+ProcXkbSetIndicatorMap(ClientPtr client)
+{
+ int i, bit;
+ int nIndicators;
+ DeviceIntPtr dev;
+ xkbIndicatorMapWireDesc *from;
+ int rc;
+
+ REQUEST(xkbSetIndicatorMapReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
+
+ 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;
+ }
+
+ from = (xkbIndicatorMapWireDesc *)&stuff[1];
+ for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
+ if (stuff->which&bit) {
+ if (client->swapped) {
+ 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];
+ rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
+ if (rc == Success)
+ _XkbSetIndicatorMap(client, other, stuff->which, from);
+ }
+ }
+ }
+
+ return Success;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbGetNamedIndicator(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ xkbGetNamedIndicatorReply rep;
+ register int i = 0;
+ XkbSrvLedInfoPtr sli;
+ XkbIndicatorMapPtr map = NULL;
+
+ REQUEST(xkbGetNamedIndicatorReq);
+ REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
+ CHK_ATOM_ONLY(stuff->indicator);
+
+ sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
+ if (!sli)
+ return BadAlloc;
+
+ 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) {
+ 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= True;
+ }
+ 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);
+ return client->noClientException;
+}
+
+
+/**
+ * Find the IM on the device.
+ * Returns the map, or NULL if the map doesn't exist.
+ * If the return value is NULL, led_return is undefined. Otherwise, led_return
+ * is set to the led index of the map.
+ */
+static XkbIndicatorMapPtr
+_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
+ int *led_return)
+{
+ XkbIndicatorMapPtr map;
+ int led;
+
+ /* search for the right indicator */
+ map = NULL;
+ if (sli->names && sli->maps) {
+ for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
+ if (sli->names[led] == indicator) {
+ map= &sli->maps[led];
+ break;
+ }
+ }
+ }
+
+ *led_return = led;
+ return map;
+}
+
+/**
+ * Creates an indicator map on the device. If dryRun is True, it only checks
+ * if creation is possible, but doesn't actually create it.
+ */
+static int
+_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
+ int ledClass, int ledID,
+ XkbIndicatorMapPtr *map_return, int *led_return,
+ Bool dryRun)
+{
+ XkbSrvLedInfoPtr sli;
+ XkbIndicatorMapPtr map;
+ int led;
+
+ sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
+ if (!sli)
+ return BadAlloc;
+
+ map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
+
+ if (!map)
+ {
+ /* find first unused indicator maps and assign the name to it */
+ for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
+ if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
+ (!XkbIM_InUse(&sli->maps[led])))
+ {
+ map = &sli->maps[led];
+ if (!dryRun)
+ sli->names[led] = indicator;
+ break;
+ }
+ }
+ }
+
+ if (!map)
+ return BadAlloc;
+
+ *led_return = led;
+ *map_return = map;
+ return Success;
+}
+
+static int
+_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
+ xkbSetNamedIndicatorReq *stuff)
+{
+ unsigned int extDevReason;
+ unsigned int statec, namec, mapc;
+ XkbSrvLedInfoPtr sli;
+ int led = 0;
+ XkbIndicatorMapPtr map;
+ DeviceIntPtr kbd;
+ XkbEventCauseRec cause;
+ xkbExtensionDeviceNotify ed;
+ XkbChangesRec changes;
+ int rc;
+
+ rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
+ stuff->ledID, &map, &led, FALSE);
+ if (rc != Success || !map) /* oh-oh */
+ return rc;
+
+ sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
+ XkbXI_IndicatorsMask);
+ if (!sli)
+ return BadAlloc;
+
+ namec = mapc = statec = 0;
+ extDevReason = 0;
+
+ 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 = inputInfo.keyboard;
+ XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
+
+ return Success;
+}
+
+int
+ProcXkbSetNamedIndicator(ClientPtr client)
+{
+ int rc;
+ DeviceIntPtr dev;
+ int led = 0;
+ XkbIndicatorMapPtr map;
+
+ REQUEST(xkbSetNamedIndicatorReq);
+ REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
+ CHK_ATOM_ONLY(stuff->indicator);
+ CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
+ CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
+
+ /* Dry-run for checks */
+ rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
+ stuff->ledClass, stuff->ledID,
+ &map, &led, TRUE);
+ if (rc != Success || !map) /* couldn't be created or didn't exist */
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd ||
+ stuff->deviceSpec == XkbUseCorePtr)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->coreEvents &&
+ (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
+ {
+ rc = _XkbCreateIndicatorMap(other, stuff->indicator,
+ stuff->ledClass, stuff->ledID,
+ &map, &led, TRUE);
+ if (rc != Success || !map)
+ return rc;
+ }
+ }
+ }
+
+ /* All checks passed, let's do it */
+ rc = _XkbSetNamedIndicator(client, dev, stuff);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd ||
+ stuff->deviceSpec == XkbUseCorePtr)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->coreEvents &&
+ (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
+ {
+ _XkbSetNamedIndicator(client, other, stuff);
+ }
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+static CARD32
+_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
+{
+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 *
+_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
+{
+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
+XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
+{
+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
+XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
+{
+register unsigned i,length,which;
+char * start;
+char * desc;
+register int n;
+
+ length= rep->length*4;
+ which= rep->which;
+ if (client->swapped) {
+ swaps(&rep->sequenceNumber,n);
+ swapl(&rep->length,n);
+ swapl(&rep->which,n);
+ swaps(&rep->virtualMods,n);
+ swapl(&rep->indicators,n);
+ }
+
+ start = desc = (char *)xalloc(length);
+ if ( !start )
+ return BadAlloc;
+ if (xkb->names) {
+ if (which&XkbKeycodesNameMask) {
+ *((CARD32 *)desc)= xkb->names->keycodes;
+ if (client->swapped) {
+ swapl(desc,n);
+ }
+ desc+= 4;
+ }
+ if (which&XkbGeometryNameMask) {
+ *((CARD32 *)desc)= xkb->names->geometry;
+ if (client->swapped) {
+ swapl(desc,n);
+ }
+ desc+= 4;
+ }
+ if (which&XkbSymbolsNameMask) {
+ *((CARD32 *)desc)= xkb->names->symbols;
+ if (client->swapped) {
+ swapl(desc,n);
+ }
+ desc+= 4;
+ }
+ if (which&XkbPhysSymbolsNameMask) {
+ register CARD32 *atm= (CARD32 *)desc;
+ atm[0]= (CARD32)xkb->names->phys_symbols;
+ if (client->swapped) {
+ swapl(&atm[0],n);
+ }
+ desc+= 4;
+ }
+ if (which&XkbTypesNameMask) {
+ *((CARD32 *)desc)= (CARD32)xkb->names->types;
+ if (client->swapped) {
+ swapl(desc,n);
+ }
+ desc+= 4;
+ }
+ if (which&XkbCompatNameMask) {
+ *((CARD32 *)desc)= (CARD32)xkb->names->compat;
+ if (client->swapped) {
+ 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) {
+ swapl(atm,n);
+ }
+ }
+ desc= (char *)atm;
+ }
+ if (which&XkbKTLevelNamesMask && xkb->map) {
+ 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) {
+ 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) {
+ swapl(atm,n);
+ }
+ }
+ desc+= rep->nRadioGroups*4;
+ }
+ }
+
+ if ((desc-start)!=(length)) {
+ ErrorF("BOGUS LENGTH in write names, expected %d, got %ld\n",
+ length, (unsigned long)(desc-start));
+ }
+ WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
+ WriteToClient(client, length, start);
+ xfree((char *)start);
+ return client->noClientException;
+}
+
+int
+ProcXkbGetNames(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ XkbDescPtr xkb;
+ xkbGetNamesReply rep;
+
+ REQUEST(xkbGetNamesReq);
+ REQUEST_SIZE_MATCH(xkbGetNamesReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
+ 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 *
+_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
+{
+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 *
+_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
+ Atom *pError)
+{
+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 *
+_XkbCopyMaskedAtoms( Atom *wire,
+ Atom *dest,
+ int nAtoms,
+ CARD32 present)
+{
+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
+_XkbCheckTypeName(Atom name,int typeNdx)
+{
+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;
+}
+
+/**
+ * Check the device-dependent data in the request against the device. Returns
+ * Success, or the appropriate error code.
+ */
+static int
+_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
+ xkbSetNamesReq *stuff, CARD32 *data)
+{
+ XkbDescRec *xkb;
+ XkbNamesRec *names;
+ CARD32 *tmp;
+ Atom bad;
+
+ tmp = data;
+ xkb = dev->key->xkbInfo->desc;
+ names = xkb->names;
+
+
+ if (stuff->which & XkbKeyTypeNamesMask) {
+ 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) {
+ 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;
+ }
+
+
+
+ return Success;
+}
+
+static int
+_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
+{
+ XkbDescRec *xkb;
+ XkbNamesRec *names;
+ CARD32 *tmp;
+ xkbNamesNotify nn;
+
+ tmp = (CARD32 *)&stuff[1];
+ xkb = dev->key->xkbInfo->desc;
+ names = xkb->names;
+
+ if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
+ stuff->nKeyAliases)!=Success) {
+ return BadAlloc;
+ }
+
+ 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) {
+ _XkbFree(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 Success;
+}
+
+int
+ProcXkbSetNames(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ CARD32 *tmp;
+ Atom bad;
+ int rc;
+
+ REQUEST(xkbSetNamesReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
+ CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
+
+ /* check device-independent stuff */
+ 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;
+ }
+ }
+
+ /* start of device-dependent tests */
+ rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ rc = _XkbSetNamesCheck(client, other, stuff, tmp);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ /* everything is okay -- update names */
+
+ rc = _XkbSetNames(client, dev, stuff);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ _XkbSetNames(client, other, stuff);
+ }
+ }
+ }
+
+ /* everything is okay -- update names */
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+#include "xkbgeom.h"
+
+#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4)
+
+static char *
+XkbWriteCountedString(char *wire,char *str,Bool swap)
+{
+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
+XkbSizeGeomProperties(XkbGeometryPtr geom)
+{
+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 *
+XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
+{
+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
+XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
+{
+ return geom->num_key_aliases*(2*XkbKeyNameLength);
+}
+
+static char *
+XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
+{
+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
+XkbSizeGeomColors(XkbGeometryPtr geom)
+{
+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 *
+XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
+{
+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
+XkbSizeGeomShapes(XkbGeometryPtr geom)
+{
+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 *
+XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
+{
+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
+XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
+{
+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 *
+XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
+{
+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",
+ doodad->any.type);
+ ErrorF("Ignored\n");
+ break;
+ }
+ }
+ return wire;
+}
+
+static char *
+XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
+{
+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
+XkbSizeGeomSections(XkbGeometryPtr geom)
+{
+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 *
+XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
+{
+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(&sectionWire->name,n);
+ swaps(&sectionWire->top,n);
+ swaps(&sectionWire->left,n);
+ swaps(&sectionWire->width,n);
+ swaps(&sectionWire->height,n);
+ swaps(&sectionWire->angle,n);
+ }
+ wire= (char *)&sectionWire[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,&section->overlays[o],swap);
+ }
+ }
+ }
+ return wire;
+}
+
+static Status
+XkbComputeGetGeometryReplySize( XkbGeometryPtr geom,
+ xkbGetGeometryReply * rep,
+ Atom name)
+{
+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
+XkbSendGeometry( ClientPtr client,
+ XkbGeometryPtr geom,
+ xkbGetGeometryReply * rep,
+ Bool freeGeom)
+{
+ char *desc,*start;
+ int len;
+
+ if (geom!=NULL) {
+ len= rep->length*4;
+ start= desc= (char *)xalloc(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 %ld\n",
+ len, (unsigned long)(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)
+ xfree((char *)start);
+ if (freeGeom)
+ XkbFreeGeometry(geom,XkbGeomAllMask,True);
+ return client->noClientException;
+}
+
+int
+ProcXkbGetGeometry(ClientPtr client)
+{
+ 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, client, DixGetAttrAccess);
+ 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 *
+_GetCountedString(char **wire_inout,Bool swap)
+{
+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
+_CheckSetDoodad( char ** wire_inout,
+ XkbGeometryPtr geom,
+ XkbSectionPtr section,
+ ClientPtr client)
+{
+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
+_CheckSetOverlay( char ** wire_inout,
+ XkbGeometryPtr geom,
+ XkbSectionPtr section,
+ ClientPtr client)
+{
+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
+_CheckSetSections( XkbGeometryPtr geom,
+ xkbSetGeometryReq * req,
+ char ** wire_inout,
+ ClientPtr client)
+{
+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
+_CheckSetShapes( XkbGeometryPtr geom,
+ xkbSetGeometryReq * req,
+ char ** wire_inout,
+ ClientPtr client)
+{
+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
+_CheckSetGeom( XkbGeometryPtr geom,
+ xkbSetGeometryReq * req,
+ ClientPtr client)
+{
+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);
+ if (!name)
+ return BadAlloc;
+ val= _GetCountedString(&wire,client->swapped);
+ if (!val) {
+ xfree(name);
+ return BadAlloc;
+ }
+ if (XkbAddGeomProperty(geom,name,val)==NULL) {
+ xfree(name);
+ xfree(val);
+ return BadAlloc;
+ }
+ xfree(name);
+ xfree(val);
+ }
+
+ 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)
+ return BadAlloc;
+ if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
+ xfree(name);
+ return BadAlloc;
+ }
+ xfree(name);
+ }
+ 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;
+}
+
+static int
+_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
+{
+ XkbDescPtr xkb;
+ Bool new_name;
+ xkbNewKeyboardNotify nkn;
+ XkbGeometryPtr geom,old;
+ XkbGeometrySizesRec sizes;
+ Status status;
+
+ 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
+ProcXkbSetGeometry(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST(xkbSetGeometryReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
+ CHK_ATOM_OR_NONE(stuff->name);
+
+ rc = _XkbSetGeometry(client, dev, stuff);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if ((other != dev) && other->key && other->coreEvents)
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ _XkbSetGeometry(client, other, stuff);
+ }
+ }
+ }
+
+ return Success;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbPerClientFlags(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ xkbPerClientFlagsReply rep;
+ XkbInterestPtr interest;
+ Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
+
+ REQUEST(xkbPerClientFlagsReq);
+ REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
+ 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, 0x87,
+ 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, 0x87,
+ 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 *
+GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
+{
+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 *)_XkbCalloc(1, 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 {
+ _XkbFree(str);
+ str= NULL;
+ }
+ }
+ else {
+ *errRtrn= BadAlloc;
+ }
+ }
+ else {
+ str= NULL;
+ }
+ *pWire= wire;
+ return (char *)str;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbListComponents(ClientPtr client)
+{
+ 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, client, DixGetAttrAccess);
+
+ 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
+ProcXkbGetKbdByName(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ DeviceIntPtr tmpd;
+ xkbGetKbdByNameReply rep;
+ xkbGetMapReply mrep;
+ xkbGetCompatMapReply crep;
+ xkbGetIndicatorMapReply irep;
+ xkbGetNamesReply nrep;
+ xkbGetGeometryReply grep;
+ XkbComponentNamesRec names;
+ XkbDescPtr xkb, new;
+ unsigned char * str;
+ char mapFile[PATH_MAX];
+ unsigned len;
+ unsigned fwant,fneed,reported;
+ int status;
+ Bool geom_changed;
+ XkbSrvLedInfoPtr old_sli;
+ XkbSrvLedInfoPtr sli;
+ Mask access_mode = DixGetAttrAccess | DixManageAccess;
+
+ REQUEST(xkbGetKbdByNameReq);
+ REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
+
+ 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.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;
+ }
+
+ 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;
+ }
+
+ /* We pass dev in here so we can get the old names out if needed. */
+ rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
+ mapFile,PATH_MAX);
+ rep.newKeyboard= False;
+ rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
+
+ stuff->want|= stuff->need;
+ if (new==NULL)
+ rep.reported= 0;
+ else {
+ if (stuff->load)
+ rep.loaded= True;
+ if (stuff->load ||
+ ((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
+ XkbChangesRec changes;
+ bzero(&changes,sizeof(changes));
+ XkbUpdateDescActions(new,
+ new->min_key_code,XkbNumKeys(new),
+ &changes);
+ }
+
+ if (new->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 = new->min_key_code;
+ mrep.maxKeyCode = new->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= new->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= new->min_key_code;
+ mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
+ }
+ 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 = new->min_key_code;
+ mrep.nKeyActs = mrep.nKeyBehaviors =
+ mrep.nKeyExplicit = XkbNumKeys(new);
+ }
+ else {
+ mrep.virtualMods= 0;
+ mrep.firstKeyAct= mrep.firstKeyBehavior=
+ mrep.firstKeyExplicit = 0;
+ mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
+ }
+ XkbComputeGetMapReplySize(new,&mrep);
+ rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
+ }
+ if (new->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= new->compat->num_si;
+ XkbComputeGetCompatMapReplySize(new->compat,&crep);
+ rep.length+= SIZEOF(xGenericReply)/4+crep.length;
+ }
+ if (new->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(new->indicators,&irep);
+ rep.length+= SIZEOF(xGenericReply)/4+irep.length;
+ }
+ if (new->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= new->min_key_code;
+ nrep.maxKeyCode= new->max_key_code;
+ if (rep.reported&XkbGBN_OtherNamesMask) {
+ nrep.which= XkbAllNamesMask;
+ if (new->map!=NULL)
+ nrep.nTypes= new->map->num_types;
+ else nrep.nTypes= 0;
+ nrep.nKTLevels= 0;
+ nrep.groupNames= XkbAllGroupsMask;
+ nrep.virtualMods= XkbAllVirtualModsMask;
+ nrep.indicators= XkbAllIndicatorsMask;
+ nrep.nRadioGroups= new->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= new->min_key_code;
+ nrep.nKeys= XkbNumKeys(new);
+ nrep.nKeyAliases= new->names->num_key_aliases;
+ if (nrep.nKeyAliases)
+ nrep.which|= XkbKeyAliasesMask;
+ }
+ else {
+ nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
+ nrep.firstKey= nrep.nKeys= 0;
+ nrep.nKeyAliases= 0;
+ }
+ XkbComputeGetNamesReplySize(new,&nrep);
+ rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
+ }
+ if (new->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(new->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,new,&mrep);
+ if (reported&XkbGBN_CompatMapMask)
+ XkbSendCompatMap(client,new->compat,&crep);
+ if (reported&XkbGBN_IndicatorMapMask)
+ XkbSendIndicatorMap(client,new->indicators,&irep);
+ if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
+ XkbSendNames(client,new,&nrep);
+ if (reported&XkbGBN_GeometryMask)
+ XkbSendGeometry(client,new->geom,&grep,False);
+ if (rep.loaded) {
+ XkbDescPtr old_xkb;
+ xkbNewKeyboardNotify nkn;
+ int i,nG,nTG;
+ old_xkb= xkb;
+ xkb= new;
+ dev->key->xkbInfo->desc= xkb;
+ new= old_xkb; /* so it'll get freed automatically */
+
+ *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;
+
+ for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
+ if (tmpd == dev ||
+ (dev->id == inputInfo.keyboard->id && tmpd->key &&
+ tmpd->coreEvents)) {
+
+ memcpy(tmpd->key->modifierMap, xkb->map->modmap,
+ xkb->max_key_code + 1);
+ if (tmpd != dev)
+ XkbCopyKeymap(dev->key->xkbInfo->desc,
+ tmpd->key->xkbInfo->desc, True);
+ XkbUpdateCoreDescription(tmpd, True);
+
+ if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
+ old_sli = tmpd->kbdfeed->xkb_sli;
+ tmpd->kbdfeed->xkb_sli = NULL;
+ sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
+ if (sli) {
+ sli->explicitState = old_sli->explicitState;
+ sli->effectiveState = old_sli->effectiveState;
+ }
+ tmpd->kbdfeed->xkb_sli = sli;
+ XkbFreeSrvLedInfo(old_sli);
+ }
+ }
+ }
+
+ /* this should be either a MN or an NKN, depending on whether or not
+ * the keycode range changed? */
+ nkn.deviceID= nkn.oldDeviceID= dev->id;
+ nkn.minKeyCode= new->min_key_code;
+ nkn.maxKeyCode= new->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 ((new!=NULL)&&(new!=xkb)) {
+ XkbFreeKeyboard(new,XkbAllComponentsMask,True);
+ new= NULL;
+ }
+ if (names.keymap) { _XkbFree(names.keymap); names.keymap= 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.symbols) { _XkbFree(names.symbols); names.symbols= NULL; }
+ if (names.geometry) { _XkbFree(names.geometry); names.geometry= NULL; }
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+static int
+ComputeDeviceLedInfoSize( DeviceIntPtr dev,
+ unsigned int what,
+ XkbSrvLedInfoPtr sli)
+{
+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
+CheckDeviceLedFBs( DeviceIntPtr dev,
+ int class,
+ int id,
+ xkbGetDeviceInfoReply * rep,
+ ClientPtr client)
+{
+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
+SendDeviceLedInfo( XkbSrvLedInfoPtr sli,
+ ClientPtr client)
+{
+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
+SendDeviceLedFBs( DeviceIntPtr dev,
+ int class,
+ int id,
+ unsigned wantLength,
+ ClientPtr client)
+{
+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
+ProcXkbGetDeviceInfo(ClientPtr client)
+{
+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, client, DixGetAttrAccess);
+ 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;
+
+ 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;
+ rep.unsupported = 0;
+ 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*) xalloc(nameLen);
+ if (!str)
+ return BadAlloc;
+ XkbWriteCountedString(str,dev->name,client->swapped);
+ WriteToClient(client,nameLen,str);
+ xfree(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) {
+ ErrorF("Internal Error! BadLength in ProcXkbGetDeviceInfo\n");
+ ErrorF(" Wrote %d fewer bytes than expected\n",length);
+ 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 *
+CheckSetDeviceIndicators( char * wire,
+ DeviceIntPtr dev,
+ int num,
+ int * status_rtrn,
+ ClientPtr client)
+{
+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 *
+SetDeviceIndicators( char * wire,
+ DeviceIntPtr dev,
+ unsigned changed,
+ int num,
+ int * status_rtrn,
+ ClientPtr client,
+ xkbExtensionDeviceNotify *ev)
+{
+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 = inputInfo.keyboard;
+
+ XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
+ ledWire= (xkbDeviceLedsWireDesc *)mapWire;
+ }
+ return (char *)ledWire;
+}
+
+
+static int
+_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
+ xkbSetDeviceInfoReq *stuff)
+{
+ char *wire;
+
+ wire= (char *)&stuff[1];
+ if (stuff->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;
+
+ return Success;
+}
+
+static int
+_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
+ xkbSetDeviceInfoReq *stuff)
+{
+ char *wire;
+ xkbExtensionDeviceNotify ed;
+
+ bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
+ ed.deviceID= dev->id;
+ wire= (char *)&stuff[1];
+ if (stuff->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= inputInfo.keyboard;
+ 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,stuff->change,
+ stuff->nDeviceLedFBs, &status,client,&ed);
+ if (status!=Success)
+ return status;
+ }
+ if ((stuff->change)&&(ed.reason))
+ XkbSendExtensionDeviceNotify(dev,client,&ed);
+ return Success;
+}
+
+int
+ProcXkbSetDeviceInfo(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST(xkbSetDeviceInfoReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
+
+ if (!(client->xkbClientFlags&_XkbClientInitialized))
+ return BadAccess;
+
+ CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
+ CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
+
+ rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
+
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if (((other != dev) && other->coreEvents) &&
+ ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
+ (stuff->deviceSpec == XkbUseCorePtr && other->button)))
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ rc = _XkbSetDeviceInfoCheck(client, other, stuff);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ /* checks done, apply */
+ rc = _XkbSetDeviceInfo(client, dev, stuff);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
+ {
+ DeviceIntPtr other;
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if (((other != dev) && other->coreEvents) &&
+ ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
+ (stuff->deviceSpec == XkbUseCorePtr && other->button)))
+ {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
+ if (rc == Success)
+ {
+ rc = _XkbSetDeviceInfo(client, other, stuff);
+ if (rc != Success)
+ return rc;
+ }
+ }
+ }
+ }
+
+ return client->noClientException;
+}
+
+/***====================================================================***/
+
+int
+ProcXkbSetDebuggingFlags(ClientPtr client)
+{
+CARD32 newFlags,newCtrls,extraLength;
+xkbSetDebuggingFlagsReply rep;
+int rc;
+
+ REQUEST(xkbSetDebuggingFlagsReq);
+ REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
+
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
+ if (rc != Success)
+ return rc;
+
+ 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%lx\n",(long)newFlags);
+ if (newCtrls!=xkbDebugCtrls)
+ ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
+ }
+ extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
+ if (stuff->msgLength>0) {
+ char *msg;
+ if (extraLength<XkbPaddedSize(stuff->msgLength)) {
+ ErrorF("XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
+ stuff->msgLength,(long)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
+ProcXkbDispatch (ClientPtr client)
+{
+ 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
+XkbClientGone(pointer data,XID id)
+{
+ DevicePtr pXDev = (DevicePtr)data;
+
+ if (!XkbRemoveResourceClient(pXDev,id)) {
+ ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n");
+ }
+ return 1;
+}
+
+/*ARGSUSED*/
+static void
+XkbResetProc(ExtensionEntry *extEntry)
+{
+}
+
+void
+XkbExtensionInit(void)
+{
+ 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;
+}
+
+