1706f2543Smrg/************************************************************ 2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3706f2543Smrg 4706f2543SmrgPermission to use, copy, modify, and distribute this 5706f2543Smrgsoftware and its documentation for any purpose and without 6706f2543Smrgfee is hereby granted, provided that the above copyright 7706f2543Smrgnotice appear in all copies and that both that copyright 8706f2543Smrgnotice and this permission notice appear in supporting 9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be 10706f2543Smrgused in advertising or publicity pertaining to distribution 11706f2543Smrgof the software without specific prior written permission. 12706f2543SmrgSilicon Graphics makes no representation about the suitability 13706f2543Smrgof this software for any purpose. It is provided "as is" 14706f2543Smrgwithout any express or implied warranty. 15706f2543Smrg 16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 24706f2543Smrg 25706f2543Smrg********************************************************/ 26706f2543Smrg/* 27706f2543Smrg 28706f2543SmrgCopyright © 2008 Red Hat Inc. 29706f2543Smrg 30706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a 31706f2543Smrgcopy of this software and associated documentation files (the "Software"), 32706f2543Smrgto deal in the Software without restriction, including without limitation 33706f2543Smrgthe rights to use, copy, modify, merge, publish, distribute, sublicense, 34706f2543Smrgand/or sell copies of the Software, and to permit persons to whom the 35706f2543SmrgSoftware is furnished to do so, subject to the following conditions: 36706f2543Smrg 37706f2543SmrgThe above copyright notice and this permission notice (including the next 38706f2543Smrgparagraph) shall be included in all copies or substantial portions of the 39706f2543SmrgSoftware. 40706f2543Smrg 41706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 44706f2543SmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45706f2543SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46706f2543SmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 47706f2543SmrgDEALINGS IN THE SOFTWARE. 48706f2543Smrg 49706f2543Smrg*/ 50706f2543Smrg 51706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 52706f2543Smrg#include <dix-config.h> 53706f2543Smrg#endif 54706f2543Smrg 55706f2543Smrg#include "os.h" 56706f2543Smrg#include <stdio.h> 57706f2543Smrg#include <ctype.h> 58706f2543Smrg#include <math.h> 59706f2543Smrg#include <X11/X.h> 60706f2543Smrg#include <X11/Xproto.h> 61706f2543Smrg#define XK_CYRILLIC 62706f2543Smrg#include <X11/keysym.h> 63706f2543Smrg#include "misc.h" 64706f2543Smrg#include "inputstr.h" 65706f2543Smrg#include "eventstr.h" 66706f2543Smrg 67706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS 68706f2543Smrg#include <xkbsrv.h> 69706f2543Smrg#include "xkbgeom.h" 70706f2543Smrg#include "xkb.h" 71706f2543Smrg 72706f2543Smrg/***====================================================================***/ 73706f2543Smrg 74706f2543Smrgint 75706f2543Smrg_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 76706f2543Smrg Mask access_mode, int *xkb_err) 77706f2543Smrg{ 78706f2543Smrg int rc = XkbKeyboardErrorCode; 79706f2543Smrg 80706f2543Smrg if (id == XkbUseCoreKbd) 81706f2543Smrg id = PickKeyboard(client)->id; 82706f2543Smrg else if (id == XkbUseCorePtr) 83706f2543Smrg id = PickPointer(client)->id; 84706f2543Smrg 85706f2543Smrg rc = dixLookupDevice(pDev, id, client, access_mode); 86706f2543Smrg if (rc != Success) 87706f2543Smrg *xkb_err = XkbErr_BadDevice; 88706f2543Smrg 89706f2543Smrg return rc; 90706f2543Smrg} 91706f2543Smrg 92706f2543Smrgint 93706f2543Smrg_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client, 94706f2543Smrg Mask access_mode, int *xkb_err) 95706f2543Smrg{ 96706f2543Smrg DeviceIntPtr dev; 97706f2543Smrg int rc; 98706f2543Smrg 99706f2543Smrg if (id == XkbDfltXIId) 100706f2543Smrg id = XkbUseCoreKbd; 101706f2543Smrg 102706f2543Smrg rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 103706f2543Smrg if (rc != Success) 104706f2543Smrg return rc; 105706f2543Smrg 106706f2543Smrg dev = *pDev; 107706f2543Smrg if (!dev->key || !dev->key->xkbInfo) { 108706f2543Smrg *pDev = NULL; 109706f2543Smrg *xkb_err= XkbErr_BadClass; 110706f2543Smrg return XkbKeyboardErrorCode; 111706f2543Smrg } 112706f2543Smrg return Success; 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgint 116706f2543Smrg_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 117706f2543Smrg Mask access_mode, int *xkb_err) 118706f2543Smrg{ 119706f2543Smrg DeviceIntPtr dev; 120706f2543Smrg int rc; 121706f2543Smrg 122706f2543Smrg rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 123706f2543Smrg if (rc != Success) 124706f2543Smrg return rc; 125706f2543Smrg 126706f2543Smrg dev = *pDev; 127706f2543Smrg if (!dev->kbdfeed && !dev->bell) { 128706f2543Smrg *pDev = NULL; 129706f2543Smrg *xkb_err= XkbErr_BadClass; 130706f2543Smrg return XkbKeyboardErrorCode; 131706f2543Smrg } 132706f2543Smrg return Success; 133706f2543Smrg} 134706f2543Smrg 135706f2543Smrgint 136706f2543Smrg_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 137706f2543Smrg Mask access_mode, int *xkb_err) 138706f2543Smrg{ 139706f2543Smrg DeviceIntPtr dev; 140706f2543Smrg int rc; 141706f2543Smrg 142706f2543Smrg if (id == XkbDfltXIId) 143706f2543Smrg id = XkbUseCorePtr; 144706f2543Smrg 145706f2543Smrg rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 146706f2543Smrg if (rc != Success) 147706f2543Smrg return rc; 148706f2543Smrg 149706f2543Smrg dev = *pDev; 150706f2543Smrg if (!dev->kbdfeed && !dev->leds) { 151706f2543Smrg *pDev = NULL; 152706f2543Smrg *xkb_err= XkbErr_BadClass; 153706f2543Smrg return XkbKeyboardErrorCode; 154706f2543Smrg } 155706f2543Smrg return Success; 156706f2543Smrg} 157706f2543Smrg 158706f2543Smrgint 159706f2543Smrg_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client, 160706f2543Smrg Mask access_mode, int *xkb_err) 161706f2543Smrg{ 162706f2543Smrg DeviceIntPtr dev; 163706f2543Smrg int rc; 164706f2543Smrg 165706f2543Smrg rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err); 166706f2543Smrg if (rc != Success) 167706f2543Smrg return rc; 168706f2543Smrg 169706f2543Smrg dev = *pDev; 170706f2543Smrg if (!dev->button) { 171706f2543Smrg *pDev = NULL; 172706f2543Smrg *xkb_err= XkbErr_BadClass; 173706f2543Smrg return XkbKeyboardErrorCode; 174706f2543Smrg } 175706f2543Smrg return Success; 176706f2543Smrg} 177706f2543Smrg 178706f2543Smrgvoid 179706f2543SmrgXkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 180706f2543Smrg{ 181706f2543Smrgregister unsigned tmp; 182706f2543Smrg 183706f2543Smrg switch (act->type) { 184706f2543Smrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 185706f2543Smrg if (act->mods.flags&XkbSA_UseModMapMods) 186706f2543Smrg act->mods.real_mods= act->mods.mask= mods; 187706f2543Smrg if ((tmp= XkbModActionVMods(&act->mods))!=0) 188706f2543Smrg act->mods.mask|= XkbMaskForVMask(xkb,tmp); 189706f2543Smrg break; 190706f2543Smrg case XkbSA_ISOLock: 191706f2543Smrg if (act->iso.flags&XkbSA_UseModMapMods) 192706f2543Smrg act->iso.real_mods= act->iso.mask= mods; 193706f2543Smrg if ((tmp= XkbModActionVMods(&act->iso))!=0) 194706f2543Smrg act->iso.mask|= XkbMaskForVMask(xkb,tmp); 195706f2543Smrg break; 196706f2543Smrg } 197706f2543Smrg return; 198706f2543Smrg} 199706f2543Smrg 200706f2543Smrgunsigned 201706f2543SmrgXkbMaskForVMask(XkbDescPtr xkb,unsigned vmask) 202706f2543Smrg{ 203706f2543Smrgregister int i,bit; 204706f2543Smrgregister unsigned mask; 205706f2543Smrg 206706f2543Smrg for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 207706f2543Smrg if (vmask&bit) 208706f2543Smrg mask|= xkb->server->vmods[i]; 209706f2543Smrg } 210706f2543Smrg return mask; 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrg/***====================================================================***/ 214706f2543Smrg 215706f2543Smrgvoid 216706f2543SmrgXkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev, 217706f2543Smrg KeySymsPtr pCore, 218706f2543Smrg KeyCode first, 219706f2543Smrg CARD8 num, 220706f2543Smrg XkbChangesPtr changes) 221706f2543Smrg{ 222706f2543SmrgXkbDescPtr xkb; 223706f2543Smrgunsigned key,nG,explicit; 224706f2543Smrgint types[XkbNumKbdGroups]; 225706f2543SmrgKeySym tsyms[XkbMaxSymsPerKey],*syms; 226706f2543SmrgXkbMapChangesPtr mc; 227706f2543Smrg 228706f2543Smrg xkb= pXDev->key->xkbInfo->desc; 229706f2543Smrg if (first+num-1>xkb->max_key_code) { 230706f2543Smrg /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */ 231706f2543Smrg num= xkb->max_key_code-first+1; 232706f2543Smrg } 233706f2543Smrg 234706f2543Smrg mc= (changes?(&changes->map):NULL); 235706f2543Smrg 236706f2543Smrg syms= &pCore->map[(first - pCore->minKeyCode) * pCore->mapWidth]; 237706f2543Smrg for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) { 238706f2543Smrg explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; 239706f2543Smrg types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 240706f2543Smrg types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); 241706f2543Smrg types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); 242706f2543Smrg types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); 243706f2543Smrg nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types, 244706f2543Smrg tsyms); 245706f2543Smrg XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); 246706f2543Smrg memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, 247706f2543Smrg XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 248706f2543Smrg } 249706f2543Smrg if (changes->map.changed&XkbKeySymsMask) { 250706f2543Smrg CARD8 oldLast,newLast; 251706f2543Smrg oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1; 252706f2543Smrg newLast = first+num-1; 253706f2543Smrg 254706f2543Smrg if (first<changes->map.first_key_sym) 255706f2543Smrg changes->map.first_key_sym = first; 256706f2543Smrg if (oldLast>newLast) 257706f2543Smrg newLast= oldLast; 258706f2543Smrg changes->map.num_key_syms = newLast-changes->map.first_key_sym+1; 259706f2543Smrg } 260706f2543Smrg else { 261706f2543Smrg changes->map.changed|= XkbKeySymsMask; 262706f2543Smrg changes->map.first_key_sym = first; 263706f2543Smrg changes->map.num_key_syms = num; 264706f2543Smrg } 265706f2543Smrg return; 266706f2543Smrg} 267706f2543Smrg 268706f2543Smrgvoid 269706f2543SmrgXkbUpdateDescActions( XkbDescPtr xkb, 270706f2543Smrg KeyCode first, 271706f2543Smrg CARD8 num, 272706f2543Smrg XkbChangesPtr changes) 273706f2543Smrg{ 274706f2543Smrgregister unsigned key; 275706f2543Smrg 276706f2543Smrg for (key=first;key<(first+num);key++) { 277706f2543Smrg XkbApplyCompatMapToKey(xkb,key,changes); 278706f2543Smrg } 279706f2543Smrg 280706f2543Smrg if (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask)) { 281706f2543Smrg unsigned char newVMods[XkbNumVirtualMods]; 282706f2543Smrg register unsigned bit,i; 283706f2543Smrg unsigned present; 284706f2543Smrg 285706f2543Smrg memset(newVMods, 0, XkbNumVirtualMods); 286706f2543Smrg present= 0; 287706f2543Smrg for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { 288706f2543Smrg if (xkb->server->vmodmap[key]==0) 289706f2543Smrg continue; 290706f2543Smrg for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 291706f2543Smrg if (bit&xkb->server->vmodmap[key]) { 292706f2543Smrg present|= bit; 293706f2543Smrg newVMods[i]|= xkb->map->modmap[key]; 294706f2543Smrg } 295706f2543Smrg } 296706f2543Smrg } 297706f2543Smrg for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 298706f2543Smrg if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { 299706f2543Smrg changes->map.changed|= XkbVirtualModsMask; 300706f2543Smrg changes->map.vmods|= bit; 301706f2543Smrg xkb->server->vmods[i]= newVMods[i]; 302706f2543Smrg } 303706f2543Smrg } 304706f2543Smrg } 305706f2543Smrg if (changes->map.changed&XkbVirtualModsMask) 306706f2543Smrg XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); 307706f2543Smrg 308706f2543Smrg if (changes->map.changed&XkbKeyActionsMask) { 309706f2543Smrg CARD8 oldLast,newLast; 310706f2543Smrg oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; 311706f2543Smrg newLast = first+num-1; 312706f2543Smrg 313706f2543Smrg if (first<changes->map.first_key_act) 314706f2543Smrg changes->map.first_key_act = first; 315706f2543Smrg if (newLast>oldLast) 316706f2543Smrg newLast= oldLast; 317706f2543Smrg changes->map.num_key_acts= newLast-changes->map.first_key_act+1; 318706f2543Smrg } 319706f2543Smrg else { 320706f2543Smrg changes->map.changed|= XkbKeyActionsMask; 321706f2543Smrg changes->map.first_key_act = first; 322706f2543Smrg changes->map.num_key_acts = num; 323706f2543Smrg } 324706f2543Smrg return; 325706f2543Smrg} 326706f2543Smrg 327706f2543Smrgvoid 328706f2543SmrgXkbUpdateActions( DeviceIntPtr pXDev, 329706f2543Smrg KeyCode first, 330706f2543Smrg CARD8 num, 331706f2543Smrg XkbChangesPtr changes, 332706f2543Smrg unsigned * needChecksRtrn, 333706f2543Smrg XkbEventCausePtr cause) 334706f2543Smrg{ 335706f2543SmrgXkbSrvInfoPtr xkbi; 336706f2543SmrgXkbDescPtr xkb; 337706f2543SmrgCARD8 * repeat; 338706f2543Smrg 339706f2543Smrg if (needChecksRtrn) 340706f2543Smrg *needChecksRtrn= 0; 341706f2543Smrg xkbi= pXDev->key->xkbInfo; 342706f2543Smrg xkb= xkbi->desc; 343706f2543Smrg repeat= xkb->ctrls->per_key_repeat; 344706f2543Smrg 345706f2543Smrg /* before letting XKB do any changes, copy the current core values */ 346706f2543Smrg if (pXDev->kbdfeed) 347706f2543Smrg memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,XkbPerKeyBitArraySize); 348706f2543Smrg 349706f2543Smrg XkbUpdateDescActions(xkb,first,num,changes); 350706f2543Smrg 351706f2543Smrg if ((pXDev->kbdfeed)&& 352706f2543Smrg (changes->ctrls.changed_ctrls&XkbPerKeyRepeatMask)) { 353706f2543Smrg /* now copy the modified changes back to core */ 354706f2543Smrg memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, XkbPerKeyBitArraySize); 355706f2543Smrg if (pXDev->kbdfeed->CtrlProc) 356706f2543Smrg (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); 357706f2543Smrg } 358706f2543Smrg return; 359706f2543Smrg} 360706f2543Smrg 361706f2543SmrgKeySymsPtr 362706f2543SmrgXkbGetCoreMap(DeviceIntPtr keybd) 363706f2543Smrg{ 364706f2543Smrgregister int key,tmp; 365706f2543Smrgint maxSymsPerKey, maxGroup1Width; 366706f2543SmrgXkbDescPtr xkb; 367706f2543SmrgKeySymsPtr syms; 368706f2543Smrgint maxNumberOfGroups; 369706f2543Smrg 370706f2543Smrg if (!keybd || !keybd->key || !keybd->key->xkbInfo) 371706f2543Smrg return NULL; 372706f2543Smrg 373706f2543Smrg xkb= keybd->key->xkbInfo->desc; 374706f2543Smrg maxSymsPerKey= maxGroup1Width= 0; 375706f2543Smrg maxNumberOfGroups = 0; 376706f2543Smrg 377706f2543Smrg /* determine sizes */ 378706f2543Smrg for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { 379706f2543Smrg if (XkbKeycodeInRange(xkb,key)) { 380706f2543Smrg int nGroups; 381706f2543Smrg int w; 382706f2543Smrg nGroups= XkbKeyNumGroups(xkb,key); 383706f2543Smrg tmp= 0; 384706f2543Smrg if (nGroups>0) { 385706f2543Smrg if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<=2) 386706f2543Smrg tmp+= 2; 387706f2543Smrg else tmp+= w + 2; 388706f2543Smrg /* remember highest G1 width */ 389706f2543Smrg if (w > maxGroup1Width) 390706f2543Smrg maxGroup1Width = w; 391706f2543Smrg } 392706f2543Smrg if (nGroups>1) { 393706f2543Smrg if (tmp <= 2) { 394706f2543Smrg if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2) 395706f2543Smrg tmp+= 2; 396706f2543Smrg else tmp+= w; 397706f2543Smrg } else { 398706f2543Smrg if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2) 399706f2543Smrg tmp+= w - 2; 400706f2543Smrg } 401706f2543Smrg } 402706f2543Smrg if (nGroups>2) 403706f2543Smrg tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index); 404706f2543Smrg if (nGroups>3) 405706f2543Smrg tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index); 406706f2543Smrg if (tmp>maxSymsPerKey) 407706f2543Smrg maxSymsPerKey= tmp; 408706f2543Smrg if (nGroups > maxNumberOfGroups) 409706f2543Smrg maxNumberOfGroups = nGroups; 410706f2543Smrg } 411706f2543Smrg } 412706f2543Smrg 413706f2543Smrg if (maxSymsPerKey <= 0) 414706f2543Smrg return NULL; 415706f2543Smrg 416706f2543Smrg syms = calloc(1, sizeof(*syms)); 417706f2543Smrg if (!syms) 418706f2543Smrg return NULL; 419706f2543Smrg 420706f2543Smrg /* See Section 12.4 of the XKB Protocol spec. Because of the 421706f2543Smrg * single-group distribution for multi-group keyboards, we have to 422706f2543Smrg * have enough symbols for the largest group 1 to replicate across the 423706f2543Smrg * number of groups on the keyboard. e.g. a single-group key with 4 424706f2543Smrg * symbols on a keyboard that has 3 groups -> 12 syms per key */ 425706f2543Smrg if (maxSymsPerKey < maxNumberOfGroups * maxGroup1Width) 426706f2543Smrg maxSymsPerKey = maxNumberOfGroups * maxGroup1Width; 427706f2543Smrg 428706f2543Smrg syms->mapWidth = maxSymsPerKey; 429706f2543Smrg syms->minKeyCode = xkb->min_key_code; 430706f2543Smrg syms->maxKeyCode = xkb->max_key_code; 431706f2543Smrg 432706f2543Smrg tmp = syms->mapWidth * (xkb->max_key_code - xkb->min_key_code + 1); 433706f2543Smrg syms->map = calloc(tmp, sizeof(*syms->map)); 434706f2543Smrg if (!syms->map) { 435706f2543Smrg free(syms); 436706f2543Smrg return NULL; 437706f2543Smrg } 438706f2543Smrg 439706f2543Smrg for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { 440706f2543Smrg KeySym *pCore,*pXKB; 441706f2543Smrg unsigned nGroups,groupWidth,n,nOut; 442706f2543Smrg 443706f2543Smrg nGroups= XkbKeyNumGroups(xkb,key); 444706f2543Smrg n= (key-xkb->min_key_code)*syms->mapWidth; 445706f2543Smrg pCore= &syms->map[n]; 446706f2543Smrg pXKB= XkbKeySymsPtr(xkb,key); 447706f2543Smrg nOut= 2; 448706f2543Smrg if (nGroups>0) { 449706f2543Smrg groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index); 450706f2543Smrg if (groupWidth>0) pCore[0]= pXKB[0]; 451706f2543Smrg if (groupWidth>1) pCore[1]= pXKB[1]; 452706f2543Smrg for (n=2;n<groupWidth;n++) 453706f2543Smrg pCore[2+n]= pXKB[n]; 454706f2543Smrg if (groupWidth>2) 455706f2543Smrg nOut= groupWidth; 456706f2543Smrg } 457706f2543Smrg 458706f2543Smrg /* See XKB Protocol Sec, Section 12.4. 459706f2543Smrg A 1-group key with ABCDE on a 2 group keyboard must be 460706f2543Smrg duplicated across all groups as ABABCDECDE. 461706f2543Smrg */ 462706f2543Smrg if (nGroups == 1) 463706f2543Smrg { 464706f2543Smrg int idx, j; 465706f2543Smrg 466706f2543Smrg groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index); 467706f2543Smrg 468706f2543Smrg /* AB..CDE... -> ABABCDE... */ 469706f2543Smrg if (groupWidth > 0 && syms->mapWidth >= 3) 470706f2543Smrg pCore[2] = pCore[0]; 471706f2543Smrg if (groupWidth > 1 && syms->mapWidth >= 4) 472706f2543Smrg pCore[3] = pCore[1]; 473706f2543Smrg 474706f2543Smrg /* ABABCDE... -> ABABCDECDE */ 475706f2543Smrg idx = 2 + groupWidth; 476706f2543Smrg while (groupWidth > 2 && idx < syms->mapWidth && 477706f2543Smrg idx < groupWidth * 2) 478706f2543Smrg { 479706f2543Smrg pCore[idx] = pCore[idx - groupWidth + 2]; 480706f2543Smrg idx++; 481706f2543Smrg } 482706f2543Smrg idx = 2 * groupWidth; 483706f2543Smrg if (idx < 4) 484706f2543Smrg idx = 4; 485706f2543Smrg /* 3 or more groups: ABABCDECDEABCDEABCDE */ 486706f2543Smrg for (j = 3; j <= maxNumberOfGroups; j++) 487706f2543Smrg for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++) 488706f2543Smrg pCore[idx++] = pXKB[n]; 489706f2543Smrg } 490706f2543Smrg 491706f2543Smrg pXKB+= XkbKeyGroupsWidth(xkb,key); 492706f2543Smrg nOut+= 2; 493706f2543Smrg if (nGroups>1) { 494706f2543Smrg groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index); 495706f2543Smrg if (groupWidth>0) pCore[2]= pXKB[0]; 496706f2543Smrg if (groupWidth>1) pCore[3]= pXKB[1]; 497706f2543Smrg for (n=2;n<groupWidth;n++) { 498706f2543Smrg pCore[nOut+(n-2)]= pXKB[n]; 499706f2543Smrg } 500706f2543Smrg if (groupWidth>2) 501706f2543Smrg nOut+= (groupWidth-2); 502706f2543Smrg } 503706f2543Smrg pXKB+= XkbKeyGroupsWidth(xkb,key); 504706f2543Smrg for (n=XkbGroup3Index;n<nGroups;n++) { 505706f2543Smrg register int s; 506706f2543Smrg groupWidth= XkbKeyGroupWidth(xkb,key,n); 507706f2543Smrg for (s=0;s<groupWidth;s++) { 508706f2543Smrg pCore[nOut++]= pXKB[s]; 509706f2543Smrg } 510706f2543Smrg pXKB+= XkbKeyGroupsWidth(xkb,key); 511706f2543Smrg } 512706f2543Smrg } 513706f2543Smrg 514706f2543Smrg return syms; 515706f2543Smrg} 516706f2543Smrg 517706f2543Smrgvoid 518706f2543SmrgXkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) 519706f2543Smrg{ 520706f2543Smrg if (pXDev && pXDev->key && pXDev->key->xkbInfo) { 521706f2543Smrg xkbControlsNotify cn; 522706f2543Smrg XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls; 523706f2543Smrg XkbControlsRec old; 524706f2543Smrg old = *ctrls; 525706f2543Smrg 526706f2543Smrg if (key== -1) { /* global autorepeat setting changed */ 527706f2543Smrg if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask; 528706f2543Smrg else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask; 529706f2543Smrg } 530706f2543Smrg else if (pXDev->kbdfeed) { 531706f2543Smrg ctrls->per_key_repeat[key/8] = 532706f2543Smrg pXDev->kbdfeed->ctrl.autoRepeats[key/8]; 533706f2543Smrg } 534706f2543Smrg 535706f2543Smrg if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,TRUE)) 536706f2543Smrg XkbSendControlsNotify(pXDev,&cn); 537706f2543Smrg } 538706f2543Smrg return; 539706f2543Smrg} 540706f2543Smrg 541706f2543Smrg/* Applies a change to a single device, does not traverse the device tree. */ 542706f2543Smrgvoid 543706f2543SmrgXkbApplyMappingChange(DeviceIntPtr kbd, KeySymsPtr map, KeyCode first_key, 544706f2543Smrg CARD8 num_keys, CARD8 *modmap, ClientPtr client) 545706f2543Smrg{ 546706f2543Smrg XkbDescPtr xkb = kbd->key->xkbInfo->desc; 547706f2543Smrg XkbEventCauseRec cause; 548706f2543Smrg XkbChangesRec changes; 549706f2543Smrg unsigned int check; 550706f2543Smrg 551706f2543Smrg memset(&changes, 0, sizeof(changes)); 552706f2543Smrg memset(&cause, 0, sizeof(cause)); 553706f2543Smrg 554706f2543Smrg if (map && first_key && num_keys) { 555706f2543Smrg check = 0; 556706f2543Smrg XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, client); 557706f2543Smrg 558706f2543Smrg XkbUpdateKeyTypesFromCore(kbd, map, first_key, num_keys, &changes); 559706f2543Smrg XkbUpdateActions(kbd, first_key, num_keys, &changes, &check, &cause); 560706f2543Smrg 561706f2543Smrg if (check) 562706f2543Smrg XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause); 563706f2543Smrg } 564706f2543Smrg 565706f2543Smrg if (modmap) { 566706f2543Smrg /* A keymap change can imply a modmap change, se we prefer the 567706f2543Smrg * former. */ 568706f2543Smrg if (!cause.mjr) 569706f2543Smrg XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); 570706f2543Smrg 571706f2543Smrg check = 0; 572706f2543Smrg num_keys = xkb->max_key_code - xkb->min_key_code + 1; 573706f2543Smrg changes.map.changed |= XkbModifierMapMask; 574706f2543Smrg changes.map.first_modmap_key = xkb->min_key_code; 575706f2543Smrg changes.map.num_modmap_keys = num_keys; 576706f2543Smrg memcpy(kbd->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH); 577706f2543Smrg XkbUpdateActions(kbd, xkb->min_key_code, num_keys, &changes, &check, 578706f2543Smrg &cause); 579706f2543Smrg 580706f2543Smrg if (check) 581706f2543Smrg XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause); 582706f2543Smrg } 583706f2543Smrg 584706f2543Smrg XkbSendNotification(kbd, &changes, &cause); 585706f2543Smrg} 586706f2543Smrg 587706f2543Smrgvoid 588706f2543SmrgXkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key) 589706f2543Smrg{ 590706f2543SmrgXkbSrvInfoPtr xkbi = dev->key->xkbInfo; 591706f2543SmrgxkbMapNotify mn; 592706f2543Smrg 593706f2543Smrg xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask; 594706f2543Smrg memset(&mn, 0, sizeof(mn)); 595706f2543Smrg mn.changed= XkbExplicitComponentsMask; 596706f2543Smrg mn.firstKeyExplicit= key; 597706f2543Smrg mn.nKeyExplicit= 1; 598706f2543Smrg XkbSendMapNotify(dev,&mn); 599706f2543Smrg return; 600706f2543Smrg} 601706f2543Smrg 602706f2543Smrgunsigned 603706f2543SmrgXkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new) 604706f2543Smrg{ 605706f2543Smrgint changed; 606706f2543Smrg 607706f2543Smrg changed=(old->group!=new->group?XkbGroupStateMask:0); 608706f2543Smrg changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0); 609706f2543Smrg changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0); 610706f2543Smrg changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0); 611706f2543Smrg changed|=(old->mods!=new->mods?XkbModifierStateMask:0); 612706f2543Smrg changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0); 613706f2543Smrg changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0); 614706f2543Smrg changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0); 615706f2543Smrg changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0); 616706f2543Smrg changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0); 617706f2543Smrg if (old->compat_grab_mods!=new->compat_grab_mods) 618706f2543Smrg changed|= XkbCompatGrabModsMask; 619706f2543Smrg changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0); 620706f2543Smrg if (old->compat_lookup_mods!=new->compat_lookup_mods) 621706f2543Smrg changed|= XkbCompatLookupModsMask; 622706f2543Smrg changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0); 623706f2543Smrg return changed; 624706f2543Smrg} 625706f2543Smrg 626706f2543Smrgstatic void 627706f2543SmrgXkbComputeCompatState(XkbSrvInfoPtr xkbi) 628706f2543Smrg{ 629706f2543SmrgCARD16 grp_mask; 630706f2543SmrgXkbStatePtr state= &xkbi->state; 631706f2543SmrgXkbCompatMapPtr map; 632706f2543Smrg 633706f2543Smrg if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat) 634706f2543Smrg return; 635706f2543Smrg 636706f2543Smrg map= xkbi->desc->compat; 637706f2543Smrg grp_mask= map->groups[state->group].mask; 638706f2543Smrg state->compat_state = state->mods|grp_mask; 639706f2543Smrg state->compat_lookup_mods= state->lookup_mods|grp_mask; 640706f2543Smrg 641706f2543Smrg if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask) 642706f2543Smrg grp_mask= map->groups[state->base_group].mask; 643706f2543Smrg state->compat_grab_mods= state->grab_mods|grp_mask; 644706f2543Smrg return; 645706f2543Smrg} 646706f2543Smrg 647706f2543Smrgunsigned 648706f2543SmrgXkbAdjustGroup(int group,XkbControlsPtr ctrls) 649706f2543Smrg{ 650706f2543Smrgunsigned act; 651706f2543Smrg 652706f2543Smrg act= XkbOutOfRangeGroupAction(ctrls->groups_wrap); 653706f2543Smrg if (group<0) { 654706f2543Smrg while ( group < 0 ) { 655706f2543Smrg if (act==XkbClampIntoRange) { 656706f2543Smrg group= XkbGroup1Index; 657706f2543Smrg } 658706f2543Smrg else if (act==XkbRedirectIntoRange) { 659706f2543Smrg int newGroup; 660706f2543Smrg newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); 661706f2543Smrg if (newGroup>=ctrls->num_groups) 662706f2543Smrg group= XkbGroup1Index; 663706f2543Smrg else group= newGroup; 664706f2543Smrg } 665706f2543Smrg else { 666706f2543Smrg group+= ctrls->num_groups; 667706f2543Smrg } 668706f2543Smrg } 669706f2543Smrg } 670706f2543Smrg else if (group>=ctrls->num_groups) { 671706f2543Smrg if (act==XkbClampIntoRange) { 672706f2543Smrg group= ctrls->num_groups-1; 673706f2543Smrg } 674706f2543Smrg else if (act==XkbRedirectIntoRange) { 675706f2543Smrg int newGroup; 676706f2543Smrg newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap); 677706f2543Smrg if (newGroup>=ctrls->num_groups) 678706f2543Smrg group= XkbGroup1Index; 679706f2543Smrg else group= newGroup; 680706f2543Smrg } 681706f2543Smrg else { 682706f2543Smrg group%= ctrls->num_groups; 683706f2543Smrg } 684706f2543Smrg } 685706f2543Smrg return group; 686706f2543Smrg} 687706f2543Smrg 688706f2543Smrgvoid 689706f2543SmrgXkbComputeDerivedState(XkbSrvInfoPtr xkbi) 690706f2543Smrg{ 691706f2543SmrgXkbStatePtr state= &xkbi->state; 692706f2543SmrgXkbControlsPtr ctrls= xkbi->desc->ctrls; 693706f2543Smrgunsigned char grp; 694706f2543Smrg 695706f2543Smrg if (!state || !ctrls) 696706f2543Smrg return; 697706f2543Smrg 698706f2543Smrg state->mods= (state->base_mods|state->latched_mods|state->locked_mods); 699706f2543Smrg state->lookup_mods= state->mods&(~ctrls->internal.mask); 700706f2543Smrg state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask); 701706f2543Smrg state->grab_mods|= 702706f2543Smrg ((state->base_mods|state->latched_mods)&ctrls->ignore_lock.mask); 703706f2543Smrg 704706f2543Smrg 705706f2543Smrg grp= state->locked_group; 706706f2543Smrg if (grp>=ctrls->num_groups) 707706f2543Smrg state->locked_group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); 708706f2543Smrg 709706f2543Smrg grp= state->locked_group+state->base_group+state->latched_group; 710706f2543Smrg if (grp>=ctrls->num_groups) 711706f2543Smrg state->group= XkbAdjustGroup(XkbCharToInt(grp),ctrls); 712706f2543Smrg else state->group= grp; 713706f2543Smrg XkbComputeCompatState(xkbi); 714706f2543Smrg return; 715706f2543Smrg} 716706f2543Smrg 717706f2543Smrg/***====================================================================***/ 718706f2543Smrg 719706f2543Smrgvoid 720706f2543SmrgXkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi, 721706f2543Smrg unsigned which, 722706f2543Smrg XkbChangesPtr changes, 723706f2543Smrg XkbEventCausePtr cause) 724706f2543Smrg{ 725706f2543Smrg if (which&XkbStateNotifyMask) { 726706f2543Smrg XkbStateRec old; 727706f2543Smrg old= xkbi->state; 728706f2543Smrg changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state); 729706f2543Smrg XkbComputeDerivedState(xkbi); 730706f2543Smrg } 731706f2543Smrg if (which&XkbIndicatorStateNotifyMask) 732706f2543Smrg XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,TRUE,changes, 733706f2543Smrg cause); 734706f2543Smrg return; 735706f2543Smrg} 736706f2543Smrg 737706f2543Smrg/***====================================================================***/ 738706f2543Smrg 739706f2543SmrgBool 740706f2543SmrgXkbEnableDisableControls( XkbSrvInfoPtr xkbi, 741706f2543Smrg unsigned long change, 742706f2543Smrg unsigned long newValues, 743706f2543Smrg XkbChangesPtr changes, 744706f2543Smrg XkbEventCausePtr cause) 745706f2543Smrg{ 746706f2543SmrgXkbControlsPtr ctrls; 747706f2543Smrgunsigned old; 748706f2543SmrgXkbSrvLedInfoPtr sli; 749706f2543Smrg 750706f2543Smrg ctrls= xkbi->desc->ctrls; 751706f2543Smrg old= ctrls->enabled_ctrls; 752706f2543Smrg ctrls->enabled_ctrls&= ~change; 753706f2543Smrg ctrls->enabled_ctrls|= (change&newValues); 754706f2543Smrg if (old==ctrls->enabled_ctrls) 755706f2543Smrg return FALSE; 756706f2543Smrg if (cause!=NULL) { 757706f2543Smrg xkbControlsNotify cn; 758706f2543Smrg cn.numGroups= ctrls->num_groups; 759706f2543Smrg cn.changedControls= XkbControlsEnabledMask; 760706f2543Smrg cn.enabledControls= ctrls->enabled_ctrls; 761706f2543Smrg cn.enabledControlChanges= (ctrls->enabled_ctrls^old); 762706f2543Smrg cn.keycode= cause->kc; 763706f2543Smrg cn.eventType= cause->event; 764706f2543Smrg cn.requestMajor= cause->mjr; 765706f2543Smrg cn.requestMinor= cause->mnr; 766706f2543Smrg XkbSendControlsNotify(xkbi->device,&cn); 767706f2543Smrg } 768706f2543Smrg else { 769706f2543Smrg /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/ 770706f2543Smrg /* is non-zero, the controls in question changed already in "this" */ 771706f2543Smrg /* request and this change merely undoes the previous one. By the */ 772706f2543Smrg /* same token, we have to figure out whether or not ControlsEnabled */ 773706f2543Smrg /* should be set or not in the changes structure */ 774706f2543Smrg changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old); 775706f2543Smrg if (changes->ctrls.enabled_ctrls_changes) 776706f2543Smrg changes->ctrls.changed_ctrls|= XkbControlsEnabledMask; 777706f2543Smrg else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask; 778706f2543Smrg } 779706f2543Smrg sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); 780706f2543Smrg XkbUpdateIndicators(xkbi->device,sli->usesControls,TRUE,changes,cause); 781706f2543Smrg return TRUE; 782706f2543Smrg} 783706f2543Smrg 784706f2543Smrg/***====================================================================***/ 785706f2543Smrg 786706f2543Smrg#define MAX_TOC 16 787706f2543Smrg 788706f2543SmrgXkbGeometryPtr 789706f2543SmrgXkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree) 790706f2543Smrg{ 791706f2543SmrgXkbSrvInfoPtr xkbi= dev->key->xkbInfo; 792706f2543SmrgXkbDescPtr xkb= xkbi->desc; 793706f2543Smrg 794706f2543Smrg *shouldFree= 0; 795706f2543Smrg if (name==None) { 796706f2543Smrg if (xkb->geom!=NULL) 797706f2543Smrg return xkb->geom; 798706f2543Smrg name= xkb->names->geometry; 799706f2543Smrg } 800706f2543Smrg if ((xkb->geom!=NULL)&&(xkb->geom->name==name)) 801706f2543Smrg return xkb->geom; 802706f2543Smrg *shouldFree= 1; 803706f2543Smrg return NULL; 804706f2543Smrg} 805706f2543Smrg 806706f2543Smrgvoid 807706f2543SmrgXkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper) 808706f2543Smrg{ 809706f2543Smrg *lower = sym; 810706f2543Smrg *upper = sym; 811706f2543Smrg switch(sym >> 8) { 812706f2543Smrg case 0: /* Latin 1 */ 813706f2543Smrg if ((sym >= XK_A) && (sym <= XK_Z)) 814706f2543Smrg *lower += (XK_a - XK_A); 815706f2543Smrg else if ((sym >= XK_a) && (sym <= XK_z)) 816706f2543Smrg *upper -= (XK_a - XK_A); 817706f2543Smrg else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) 818706f2543Smrg *lower += (XK_agrave - XK_Agrave); 819706f2543Smrg else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) 820706f2543Smrg *upper -= (XK_agrave - XK_Agrave); 821706f2543Smrg else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) 822706f2543Smrg *lower += (XK_oslash - XK_Ooblique); 823706f2543Smrg else if ((sym >= XK_oslash) && (sym <= XK_thorn)) 824706f2543Smrg *upper -= (XK_oslash - XK_Ooblique); 825706f2543Smrg break; 826706f2543Smrg case 1: /* Latin 2 */ 827706f2543Smrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 828706f2543Smrg if (sym == XK_Aogonek) 829706f2543Smrg *lower = XK_aogonek; 830706f2543Smrg else if (sym >= XK_Lstroke && sym <= XK_Sacute) 831706f2543Smrg *lower += (XK_lstroke - XK_Lstroke); 832706f2543Smrg else if (sym >= XK_Scaron && sym <= XK_Zacute) 833706f2543Smrg *lower += (XK_scaron - XK_Scaron); 834706f2543Smrg else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) 835706f2543Smrg *lower += (XK_zcaron - XK_Zcaron); 836706f2543Smrg else if (sym == XK_aogonek) 837706f2543Smrg *upper = XK_Aogonek; 838706f2543Smrg else if (sym >= XK_lstroke && sym <= XK_sacute) 839706f2543Smrg *upper -= (XK_lstroke - XK_Lstroke); 840706f2543Smrg else if (sym >= XK_scaron && sym <= XK_zacute) 841706f2543Smrg *upper -= (XK_scaron - XK_Scaron); 842706f2543Smrg else if (sym >= XK_zcaron && sym <= XK_zabovedot) 843706f2543Smrg *upper -= (XK_zcaron - XK_Zcaron); 844706f2543Smrg else if (sym >= XK_Racute && sym <= XK_Tcedilla) 845706f2543Smrg *lower += (XK_racute - XK_Racute); 846706f2543Smrg else if (sym >= XK_racute && sym <= XK_tcedilla) 847706f2543Smrg *upper -= (XK_racute - XK_Racute); 848706f2543Smrg break; 849706f2543Smrg case 2: /* Latin 3 */ 850706f2543Smrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 851706f2543Smrg if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) 852706f2543Smrg *lower += (XK_hstroke - XK_Hstroke); 853706f2543Smrg else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) 854706f2543Smrg *lower += (XK_gbreve - XK_Gbreve); 855706f2543Smrg else if (sym >= XK_hstroke && sym <= XK_hcircumflex) 856706f2543Smrg *upper -= (XK_hstroke - XK_Hstroke); 857706f2543Smrg else if (sym >= XK_gbreve && sym <= XK_jcircumflex) 858706f2543Smrg *upper -= (XK_gbreve - XK_Gbreve); 859706f2543Smrg else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) 860706f2543Smrg *lower += (XK_cabovedot - XK_Cabovedot); 861706f2543Smrg else if (sym >= XK_cabovedot && sym <= XK_scircumflex) 862706f2543Smrg *upper -= (XK_cabovedot - XK_Cabovedot); 863706f2543Smrg break; 864706f2543Smrg case 3: /* Latin 4 */ 865706f2543Smrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 866706f2543Smrg if (sym >= XK_Rcedilla && sym <= XK_Tslash) 867706f2543Smrg *lower += (XK_rcedilla - XK_Rcedilla); 868706f2543Smrg else if (sym >= XK_rcedilla && sym <= XK_tslash) 869706f2543Smrg *upper -= (XK_rcedilla - XK_Rcedilla); 870706f2543Smrg else if (sym == XK_ENG) 871706f2543Smrg *lower = XK_eng; 872706f2543Smrg else if (sym == XK_eng) 873706f2543Smrg *upper = XK_ENG; 874706f2543Smrg else if (sym >= XK_Amacron && sym <= XK_Umacron) 875706f2543Smrg *lower += (XK_amacron - XK_Amacron); 876706f2543Smrg else if (sym >= XK_amacron && sym <= XK_umacron) 877706f2543Smrg *upper -= (XK_amacron - XK_Amacron); 878706f2543Smrg break; 879706f2543Smrg case 6: /* Cyrillic */ 880706f2543Smrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 881706f2543Smrg if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) 882706f2543Smrg *lower -= (XK_Serbian_DJE - XK_Serbian_dje); 883706f2543Smrg else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) 884706f2543Smrg *upper += (XK_Serbian_DJE - XK_Serbian_dje); 885706f2543Smrg else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) 886706f2543Smrg *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); 887706f2543Smrg else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) 888706f2543Smrg *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); 889706f2543Smrg break; 890706f2543Smrg case 7: /* Greek */ 891706f2543Smrg /* Assume the KeySym is a legal value (ignore discontinuities) */ 892706f2543Smrg if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) 893706f2543Smrg *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 894706f2543Smrg else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && 895706f2543Smrg sym != XK_Greek_iotaaccentdieresis && 896706f2543Smrg sym != XK_Greek_upsilonaccentdieresis) 897706f2543Smrg *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 898706f2543Smrg else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) 899706f2543Smrg *lower += (XK_Greek_alpha - XK_Greek_ALPHA); 900706f2543Smrg else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && 901706f2543Smrg sym != XK_Greek_finalsmallsigma) 902706f2543Smrg *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); 903706f2543Smrg break; 904706f2543Smrg } 905706f2543Smrg} 906706f2543Smrg 907706f2543Smrgstatic Bool 908706f2543Smrg_XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst) 909706f2543Smrg{ 910706f2543Smrg void *tmp = NULL; 911706f2543Smrg int i; 912706f2543Smrg XkbKeyTypePtr stype = NULL, dtype = NULL; 913706f2543Smrg 914706f2543Smrg /* client map */ 915706f2543Smrg if (src->map) { 916706f2543Smrg if (!dst->map) { 917706f2543Smrg tmp = calloc(1, sizeof(XkbClientMapRec)); 918706f2543Smrg if (!tmp) 919706f2543Smrg return FALSE; 920706f2543Smrg dst->map = tmp; 921706f2543Smrg } 922706f2543Smrg 923706f2543Smrg if (src->map->syms) { 924706f2543Smrg if (src->map->size_syms != dst->map->size_syms) { 925706f2543Smrg tmp = realloc(dst->map->syms, 926706f2543Smrg src->map->size_syms * sizeof(KeySym)); 927706f2543Smrg if (!tmp) 928706f2543Smrg return FALSE; 929706f2543Smrg dst->map->syms = tmp; 930706f2543Smrg 931706f2543Smrg } 932706f2543Smrg memcpy(dst->map->syms, src->map->syms, 933706f2543Smrg src->map->size_syms * sizeof(KeySym)); 934706f2543Smrg } 935706f2543Smrg else { 936706f2543Smrg free(dst->map->syms); 937706f2543Smrg dst->map->syms = NULL; 938706f2543Smrg } 939706f2543Smrg dst->map->num_syms = src->map->num_syms; 940706f2543Smrg dst->map->size_syms = src->map->size_syms; 941706f2543Smrg 942706f2543Smrg if (src->map->key_sym_map) { 943706f2543Smrg if (src->max_key_code != dst->max_key_code) { 944706f2543Smrg tmp = realloc(dst->map->key_sym_map, 945706f2543Smrg (src->max_key_code + 1) * sizeof(XkbSymMapRec)); 946706f2543Smrg if (!tmp) 947706f2543Smrg return FALSE; 948706f2543Smrg dst->map->key_sym_map = tmp; 949706f2543Smrg } 950706f2543Smrg memcpy(dst->map->key_sym_map, src->map->key_sym_map, 951706f2543Smrg (src->max_key_code + 1) * sizeof(XkbSymMapRec)); 952706f2543Smrg } 953706f2543Smrg else { 954706f2543Smrg free(dst->map->key_sym_map); 955706f2543Smrg dst->map->key_sym_map = NULL; 956706f2543Smrg } 957706f2543Smrg 958706f2543Smrg if (src->map->types && src->map->num_types) { 959706f2543Smrg if (src->map->num_types > dst->map->size_types || 960706f2543Smrg !dst->map->types || !dst->map->size_types) { 961706f2543Smrg if (dst->map->types && dst->map->size_types) { 962706f2543Smrg tmp = realloc(dst->map->types, 963706f2543Smrg src->map->num_types * sizeof(XkbKeyTypeRec)); 964706f2543Smrg if (!tmp) 965706f2543Smrg return FALSE; 966706f2543Smrg dst->map->types = tmp; 967706f2543Smrg memset(dst->map->types + dst->map->num_types, 0, 968706f2543Smrg (src->map->num_types - dst->map->num_types) * 969706f2543Smrg sizeof(XkbKeyTypeRec)); 970706f2543Smrg } 971706f2543Smrg else { 972706f2543Smrg tmp = calloc(src->map->num_types, sizeof(XkbKeyTypeRec)); 973706f2543Smrg if (!tmp) 974706f2543Smrg return FALSE; 975706f2543Smrg dst->map->types = tmp; 976706f2543Smrg } 977706f2543Smrg } 978706f2543Smrg else if (src->map->num_types < dst->map->num_types && 979706f2543Smrg dst->map->types) { 980706f2543Smrg for (i = src->map->num_types, dtype = (dst->map->types + i); 981706f2543Smrg i < dst->map->num_types; i++, dtype++) { 982706f2543Smrg free(dtype->level_names); 983706f2543Smrg dtype->level_names = NULL; 984706f2543Smrg dtype->num_levels = 0; 985706f2543Smrg if (dtype->map_count) { 986706f2543Smrg free(dtype->map); 987706f2543Smrg free(dtype->preserve); 988706f2543Smrg } 989706f2543Smrg } 990706f2543Smrg } 991706f2543Smrg 992706f2543Smrg stype = src->map->types; 993706f2543Smrg dtype = dst->map->types; 994706f2543Smrg for (i = 0; i < src->map->num_types; i++, dtype++, stype++) { 995706f2543Smrg if (stype->num_levels && stype->level_names) { 996706f2543Smrg if (stype->num_levels != dtype->num_levels && 997706f2543Smrg dtype->num_levels && dtype->level_names && 998706f2543Smrg i < dst->map->num_types) { 999706f2543Smrg tmp = realloc(dtype->level_names, 1000706f2543Smrg stype->num_levels * sizeof(Atom)); 1001706f2543Smrg if (!tmp) 1002706f2543Smrg continue; 1003706f2543Smrg dtype->level_names = tmp; 1004706f2543Smrg } 1005706f2543Smrg else if (!dtype->num_levels || !dtype->level_names || 1006706f2543Smrg i >= dst->map->num_types) { 1007706f2543Smrg tmp = malloc(stype->num_levels * sizeof(Atom)); 1008706f2543Smrg if (!tmp) 1009706f2543Smrg continue; 1010706f2543Smrg dtype->level_names = tmp; 1011706f2543Smrg } 1012706f2543Smrg dtype->num_levels = stype->num_levels; 1013706f2543Smrg memcpy(dtype->level_names, stype->level_names, 1014706f2543Smrg stype->num_levels * sizeof(Atom)); 1015706f2543Smrg } 1016706f2543Smrg else { 1017706f2543Smrg if (dtype->num_levels && dtype->level_names && 1018706f2543Smrg i < dst->map->num_types) 1019706f2543Smrg free(dtype->level_names); 1020706f2543Smrg dtype->num_levels = 0; 1021706f2543Smrg dtype->level_names = NULL; 1022706f2543Smrg } 1023706f2543Smrg 1024706f2543Smrg dtype->name = stype->name; 1025706f2543Smrg memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec)); 1026706f2543Smrg 1027706f2543Smrg if (stype->map_count) { 1028706f2543Smrg if (stype->map) { 1029706f2543Smrg if (stype->map_count != dtype->map_count && 1030706f2543Smrg dtype->map_count && dtype->map && 1031706f2543Smrg i < dst->map->num_types) { 1032706f2543Smrg tmp = realloc(dtype->map, 1033706f2543Smrg stype->map_count * 1034706f2543Smrg sizeof(XkbKTMapEntryRec)); 1035706f2543Smrg if (!tmp) 1036706f2543Smrg return FALSE; 1037706f2543Smrg dtype->map = tmp; 1038706f2543Smrg } 1039706f2543Smrg else if (!dtype->map_count || !dtype->map || 1040706f2543Smrg i >= dst->map->num_types) { 1041706f2543Smrg tmp = malloc(stype->map_count * 1042706f2543Smrg sizeof(XkbKTMapEntryRec)); 1043706f2543Smrg if (!tmp) 1044706f2543Smrg return FALSE; 1045706f2543Smrg dtype->map = tmp; 1046706f2543Smrg } 1047706f2543Smrg 1048706f2543Smrg memcpy(dtype->map, stype->map, 1049706f2543Smrg stype->map_count * sizeof(XkbKTMapEntryRec)); 1050706f2543Smrg } 1051706f2543Smrg else { 1052706f2543Smrg if (dtype->map && i < dst->map->num_types) 1053706f2543Smrg free(dtype->map); 1054706f2543Smrg dtype->map = NULL; 1055706f2543Smrg } 1056706f2543Smrg 1057706f2543Smrg if (stype->preserve) { 1058706f2543Smrg if (stype->map_count != dtype->map_count && 1059706f2543Smrg dtype->map_count && dtype->preserve && 1060706f2543Smrg i < dst->map->num_types) { 1061706f2543Smrg tmp = realloc(dtype->preserve, 1062706f2543Smrg stype->map_count * 1063706f2543Smrg sizeof(XkbModsRec)); 1064706f2543Smrg if (!tmp) 1065706f2543Smrg return FALSE; 1066706f2543Smrg dtype->preserve = tmp; 1067706f2543Smrg } 1068706f2543Smrg else if (!dtype->preserve || !dtype->map_count || 1069706f2543Smrg i >= dst->map->num_types) { 1070706f2543Smrg tmp = malloc(stype->map_count * 1071706f2543Smrg sizeof(XkbModsRec)); 1072706f2543Smrg if (!tmp) 1073706f2543Smrg return FALSE; 1074706f2543Smrg dtype->preserve = tmp; 1075706f2543Smrg } 1076706f2543Smrg 1077706f2543Smrg memcpy(dtype->preserve, stype->preserve, 1078706f2543Smrg stype->map_count * sizeof(XkbModsRec)); 1079706f2543Smrg } 1080706f2543Smrg else { 1081706f2543Smrg if (dtype->preserve && i < dst->map->num_types) 1082706f2543Smrg free(dtype->preserve); 1083706f2543Smrg dtype->preserve = NULL; 1084706f2543Smrg } 1085706f2543Smrg 1086706f2543Smrg dtype->map_count = stype->map_count; 1087706f2543Smrg } 1088706f2543Smrg else { 1089706f2543Smrg if (dtype->map_count && i < dst->map->num_types) { 1090706f2543Smrg free(dtype->map); 1091706f2543Smrg free(dtype->preserve); 1092706f2543Smrg } 1093706f2543Smrg dtype->map_count = 0; 1094706f2543Smrg dtype->map = NULL; 1095706f2543Smrg dtype->preserve = NULL; 1096706f2543Smrg } 1097706f2543Smrg } 1098706f2543Smrg 1099706f2543Smrg dst->map->size_types = src->map->num_types; 1100706f2543Smrg dst->map->num_types = src->map->num_types; 1101706f2543Smrg } 1102706f2543Smrg else { 1103706f2543Smrg if (dst->map->types) { 1104706f2543Smrg for (i = 0, dtype = dst->map->types; i < dst->map->num_types; 1105706f2543Smrg i++, dtype++) { 1106706f2543Smrg free(dtype->level_names); 1107706f2543Smrg if (dtype->map && dtype->map_count) 1108706f2543Smrg free(dtype->map); 1109706f2543Smrg if (dtype->preserve && dtype->map_count) 1110706f2543Smrg free(dtype->preserve); 1111706f2543Smrg } 1112706f2543Smrg } 1113706f2543Smrg free(dst->map->types); 1114706f2543Smrg dst->map->types = NULL; 1115706f2543Smrg dst->map->num_types = 0; 1116706f2543Smrg dst->map->size_types = 0; 1117706f2543Smrg } 1118706f2543Smrg 1119706f2543Smrg if (src->map->modmap) { 1120706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1121706f2543Smrg tmp = realloc(dst->map->modmap, src->max_key_code + 1); 1122706f2543Smrg if (!tmp) 1123706f2543Smrg return FALSE; 1124706f2543Smrg dst->map->modmap = tmp; 1125706f2543Smrg } 1126706f2543Smrg memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1); 1127706f2543Smrg } 1128706f2543Smrg else { 1129706f2543Smrg free(dst->map->modmap); 1130706f2543Smrg dst->map->modmap = NULL; 1131706f2543Smrg } 1132706f2543Smrg } 1133706f2543Smrg else { 1134706f2543Smrg if (dst->map) 1135706f2543Smrg XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE); 1136706f2543Smrg } 1137706f2543Smrg 1138706f2543Smrg return TRUE; 1139706f2543Smrg} 1140706f2543Smrg 1141706f2543Smrgstatic Bool 1142706f2543Smrg_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst) 1143706f2543Smrg{ 1144706f2543Smrg void *tmp = NULL; 1145706f2543Smrg 1146706f2543Smrg /* server map */ 1147706f2543Smrg if (src->server) { 1148706f2543Smrg if (!dst->server) { 1149706f2543Smrg tmp = calloc(1, sizeof(XkbServerMapRec)); 1150706f2543Smrg if (!tmp) 1151706f2543Smrg return FALSE; 1152706f2543Smrg dst->server = tmp; 1153706f2543Smrg } 1154706f2543Smrg 1155706f2543Smrg if (src->server->explicit) { 1156706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1157706f2543Smrg tmp = realloc(dst->server->explicit, src->max_key_code + 1); 1158706f2543Smrg if (!tmp) 1159706f2543Smrg return FALSE; 1160706f2543Smrg dst->server->explicit = tmp; 1161706f2543Smrg } 1162706f2543Smrg memcpy(dst->server->explicit, src->server->explicit, 1163706f2543Smrg src->max_key_code + 1); 1164706f2543Smrg } 1165706f2543Smrg else { 1166706f2543Smrg free(dst->server->explicit); 1167706f2543Smrg dst->server->explicit = NULL; 1168706f2543Smrg } 1169706f2543Smrg 1170706f2543Smrg if (src->server->acts) { 1171706f2543Smrg if (src->server->size_acts != dst->server->size_acts) { 1172706f2543Smrg tmp = realloc(dst->server->acts, 1173706f2543Smrg src->server->size_acts * sizeof(XkbAction)); 1174706f2543Smrg if (!tmp) 1175706f2543Smrg return FALSE; 1176706f2543Smrg dst->server->acts = tmp; 1177706f2543Smrg } 1178706f2543Smrg memcpy(dst->server->acts, src->server->acts, 1179706f2543Smrg src->server->size_acts * sizeof(XkbAction)); 1180706f2543Smrg } 1181706f2543Smrg else { 1182706f2543Smrg free(dst->server->acts); 1183706f2543Smrg dst->server->acts = NULL; 1184706f2543Smrg } 1185706f2543Smrg dst->server->size_acts = src->server->size_acts; 1186706f2543Smrg dst->server->num_acts = src->server->num_acts; 1187706f2543Smrg 1188706f2543Smrg if (src->server->key_acts) { 1189706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1190706f2543Smrg tmp = realloc(dst->server->key_acts, 1191706f2543Smrg (src->max_key_code + 1) * sizeof(unsigned short)); 1192706f2543Smrg if (!tmp) 1193706f2543Smrg return FALSE; 1194706f2543Smrg dst->server->key_acts = tmp; 1195706f2543Smrg } 1196706f2543Smrg memcpy(dst->server->key_acts, src->server->key_acts, 1197706f2543Smrg (src->max_key_code + 1) * sizeof(unsigned short)); 1198706f2543Smrg } 1199706f2543Smrg else { 1200706f2543Smrg free(dst->server->key_acts); 1201706f2543Smrg dst->server->key_acts = NULL; 1202706f2543Smrg } 1203706f2543Smrg 1204706f2543Smrg if (src->server->behaviors) { 1205706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1206706f2543Smrg tmp = realloc(dst->server->behaviors, 1207706f2543Smrg (src->max_key_code + 1) * sizeof(XkbBehavior)); 1208706f2543Smrg if (!tmp) 1209706f2543Smrg return FALSE; 1210706f2543Smrg dst->server->behaviors = tmp; 1211706f2543Smrg } 1212706f2543Smrg memcpy(dst->server->behaviors, src->server->behaviors, 1213706f2543Smrg (src->max_key_code + 1) * sizeof(XkbBehavior)); 1214706f2543Smrg } 1215706f2543Smrg else { 1216706f2543Smrg free(dst->server->behaviors); 1217706f2543Smrg dst->server->behaviors = NULL; 1218706f2543Smrg } 1219706f2543Smrg 1220706f2543Smrg memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods); 1221706f2543Smrg 1222706f2543Smrg if (src->server->vmodmap) { 1223706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1224706f2543Smrg tmp = realloc(dst->server->vmodmap, 1225706f2543Smrg (src->max_key_code + 1) * sizeof(unsigned short)); 1226706f2543Smrg if (!tmp) 1227706f2543Smrg return FALSE; 1228706f2543Smrg dst->server->vmodmap = tmp; 1229706f2543Smrg } 1230706f2543Smrg memcpy(dst->server->vmodmap, src->server->vmodmap, 1231706f2543Smrg (src->max_key_code + 1) * sizeof(unsigned short)); 1232706f2543Smrg } 1233706f2543Smrg else { 1234706f2543Smrg free(dst->server->vmodmap); 1235706f2543Smrg dst->server->vmodmap = NULL; 1236706f2543Smrg } 1237706f2543Smrg } 1238706f2543Smrg else { 1239706f2543Smrg if (dst->server) 1240706f2543Smrg XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE); 1241706f2543Smrg } 1242706f2543Smrg 1243706f2543Smrg return TRUE; 1244706f2543Smrg} 1245706f2543Smrg 1246706f2543Smrgstatic Bool 1247706f2543Smrg_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst) 1248706f2543Smrg{ 1249706f2543Smrg void *tmp = NULL; 1250706f2543Smrg 1251706f2543Smrg /* names */ 1252706f2543Smrg if (src->names) { 1253706f2543Smrg if (!dst->names) { 1254706f2543Smrg dst->names = calloc(1, sizeof(XkbNamesRec)); 1255706f2543Smrg if (!dst->names) 1256706f2543Smrg return FALSE; 1257706f2543Smrg } 1258706f2543Smrg 1259706f2543Smrg if (src->names->keys) { 1260706f2543Smrg if (src->max_key_code != dst->max_key_code) { 1261706f2543Smrg tmp = realloc(dst->names->keys, 1262706f2543Smrg (src->max_key_code + 1) * sizeof(XkbKeyNameRec)); 1263706f2543Smrg if (!tmp) 1264706f2543Smrg return FALSE; 1265706f2543Smrg dst->names->keys = tmp; 1266706f2543Smrg } 1267706f2543Smrg memcpy(dst->names->keys, src->names->keys, 1268706f2543Smrg (src->max_key_code + 1) * sizeof(XkbKeyNameRec)); 1269706f2543Smrg } 1270706f2543Smrg else { 1271706f2543Smrg free(dst->names->keys); 1272706f2543Smrg dst->names->keys = NULL; 1273706f2543Smrg } 1274706f2543Smrg 1275706f2543Smrg if (src->names->num_key_aliases) { 1276706f2543Smrg if (src->names->num_key_aliases != dst->names->num_key_aliases) { 1277706f2543Smrg tmp = realloc(dst->names->key_aliases, 1278706f2543Smrg src->names->num_key_aliases * 1279706f2543Smrg sizeof(XkbKeyAliasRec)); 1280706f2543Smrg if (!tmp) 1281706f2543Smrg return FALSE; 1282706f2543Smrg dst->names->key_aliases = tmp; 1283706f2543Smrg } 1284706f2543Smrg memcpy(dst->names->key_aliases, src->names->key_aliases, 1285706f2543Smrg src->names->num_key_aliases * sizeof(XkbKeyAliasRec)); 1286706f2543Smrg } 1287706f2543Smrg else { 1288706f2543Smrg free(dst->names->key_aliases); 1289706f2543Smrg dst->names->key_aliases = NULL; 1290706f2543Smrg } 1291706f2543Smrg dst->names->num_key_aliases = src->names->num_key_aliases; 1292706f2543Smrg 1293706f2543Smrg if (src->names->num_rg) { 1294706f2543Smrg if (src->names->num_rg != dst->names->num_rg) { 1295706f2543Smrg tmp = realloc(dst->names->radio_groups, 1296706f2543Smrg src->names->num_rg * sizeof(Atom)); 1297706f2543Smrg if (!tmp) 1298706f2543Smrg return FALSE; 1299706f2543Smrg dst->names->radio_groups = tmp; 1300706f2543Smrg } 1301706f2543Smrg memcpy(dst->names->radio_groups, src->names->radio_groups, 1302706f2543Smrg src->names->num_rg * sizeof(Atom)); 1303706f2543Smrg } 1304706f2543Smrg else { 1305706f2543Smrg free(dst->names->radio_groups); 1306706f2543Smrg } 1307706f2543Smrg dst->names->num_rg = src->names->num_rg; 1308706f2543Smrg 1309706f2543Smrg dst->names->keycodes = src->names->keycodes; 1310706f2543Smrg dst->names->geometry = src->names->geometry; 1311706f2543Smrg dst->names->symbols = src->names->symbols; 1312706f2543Smrg dst->names->types = src->names->types; 1313706f2543Smrg dst->names->compat = src->names->compat; 1314706f2543Smrg dst->names->phys_symbols = src->names->phys_symbols; 1315706f2543Smrg 1316706f2543Smrg memcpy(dst->names->vmods, src->names->vmods, 1317706f2543Smrg XkbNumVirtualMods * sizeof(Atom)); 1318706f2543Smrg memcpy(dst->names->indicators, src->names->indicators, 1319706f2543Smrg XkbNumIndicators * sizeof(Atom)); 1320706f2543Smrg memcpy(dst->names->groups, src->names->groups, 1321706f2543Smrg XkbNumKbdGroups * sizeof(Atom)); 1322706f2543Smrg } 1323706f2543Smrg else { 1324706f2543Smrg if (dst->names) 1325706f2543Smrg XkbFreeNames(dst, XkbAllNamesMask, TRUE); 1326706f2543Smrg } 1327706f2543Smrg 1328706f2543Smrg return TRUE; 1329706f2543Smrg} 1330706f2543Smrg 1331706f2543Smrgstatic Bool 1332706f2543Smrg_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst) 1333706f2543Smrg{ 1334706f2543Smrg void *tmp = NULL; 1335706f2543Smrg 1336706f2543Smrg /* compat */ 1337706f2543Smrg if (src->compat) { 1338706f2543Smrg if (!dst->compat) { 1339706f2543Smrg dst->compat = calloc(1, sizeof(XkbCompatMapRec)); 1340706f2543Smrg if (!dst->compat) 1341706f2543Smrg return FALSE; 1342706f2543Smrg } 1343706f2543Smrg 1344706f2543Smrg if (src->compat->sym_interpret && src->compat->num_si) { 1345706f2543Smrg if (src->compat->num_si != dst->compat->size_si) { 1346706f2543Smrg tmp = realloc(dst->compat->sym_interpret, 1347706f2543Smrg src->compat->num_si * sizeof(XkbSymInterpretRec)); 1348706f2543Smrg if (!tmp) 1349706f2543Smrg return FALSE; 1350706f2543Smrg dst->compat->sym_interpret = tmp; 1351706f2543Smrg } 1352706f2543Smrg memcpy(dst->compat->sym_interpret, src->compat->sym_interpret, 1353706f2543Smrg src->compat->num_si * sizeof(XkbSymInterpretRec)); 1354706f2543Smrg 1355706f2543Smrg dst->compat->num_si = src->compat->num_si; 1356706f2543Smrg dst->compat->size_si = src->compat->num_si; 1357706f2543Smrg } 1358706f2543Smrg else { 1359706f2543Smrg if (dst->compat->sym_interpret && dst->compat->size_si) 1360706f2543Smrg free(dst->compat->sym_interpret); 1361706f2543Smrg 1362706f2543Smrg dst->compat->sym_interpret = NULL; 1363706f2543Smrg dst->compat->num_si = 0; 1364706f2543Smrg dst->compat->size_si = 0; 1365706f2543Smrg } 1366706f2543Smrg 1367706f2543Smrg memcpy(dst->compat->groups, src->compat->groups, 1368706f2543Smrg XkbNumKbdGroups * sizeof(XkbModsRec)); 1369706f2543Smrg } 1370706f2543Smrg else { 1371706f2543Smrg if (dst->compat) 1372706f2543Smrg XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE); 1373706f2543Smrg } 1374706f2543Smrg 1375706f2543Smrg return TRUE; 1376706f2543Smrg} 1377706f2543Smrg 1378706f2543Smrgstatic Bool 1379706f2543Smrg_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst) 1380706f2543Smrg{ 1381706f2543Smrg void *tmp = NULL; 1382706f2543Smrg int i = 0, j = 0, k = 0; 1383706f2543Smrg XkbColorPtr scolor = NULL, dcolor = NULL; 1384706f2543Smrg XkbDoodadPtr sdoodad = NULL, ddoodad = NULL; 1385706f2543Smrg XkbOutlinePtr soutline = NULL, doutline = NULL; 1386706f2543Smrg XkbPropertyPtr sprop = NULL, dprop = NULL; 1387706f2543Smrg XkbRowPtr srow = NULL, drow = NULL; 1388706f2543Smrg XkbSectionPtr ssection = NULL, dsection = NULL; 1389706f2543Smrg XkbShapePtr sshape = NULL, dshape = NULL; 1390706f2543Smrg 1391706f2543Smrg /* geometry */ 1392706f2543Smrg if (src->geom) { 1393706f2543Smrg if (!dst->geom) { 1394706f2543Smrg dst->geom = calloc(sizeof(XkbGeometryRec), 1); 1395706f2543Smrg if (!dst->geom) 1396706f2543Smrg return FALSE; 1397706f2543Smrg } 1398706f2543Smrg 1399706f2543Smrg /* properties */ 1400706f2543Smrg if (src->geom->num_properties) { 1401706f2543Smrg if (src->geom->num_properties != dst->geom->sz_properties) { 1402706f2543Smrg /* If we've got more properties in the destination than 1403706f2543Smrg * the source, run through and free all the excess ones 1404706f2543Smrg * first. */ 1405706f2543Smrg if (src->geom->num_properties < dst->geom->sz_properties) { 1406706f2543Smrg for (i = src->geom->num_properties, 1407706f2543Smrg dprop = dst->geom->properties + i; 1408706f2543Smrg i < dst->geom->num_properties; 1409706f2543Smrg i++, dprop++) { 1410706f2543Smrg free(dprop->name); 1411706f2543Smrg free(dprop->value); 1412706f2543Smrg } 1413706f2543Smrg } 1414706f2543Smrg 1415706f2543Smrg if (dst->geom->sz_properties) 1416706f2543Smrg tmp = realloc(dst->geom->properties, 1417706f2543Smrg src->geom->num_properties * 1418706f2543Smrg sizeof(XkbPropertyRec)); 1419706f2543Smrg else 1420706f2543Smrg tmp = malloc(src->geom->num_properties * 1421706f2543Smrg sizeof(XkbPropertyRec)); 1422706f2543Smrg if (!tmp) 1423706f2543Smrg return FALSE; 1424706f2543Smrg dst->geom->properties = tmp; 1425706f2543Smrg } 1426706f2543Smrg 1427706f2543Smrg /* We don't set num_properties as we need it to try and avoid 1428706f2543Smrg * too much reallocing. */ 1429706f2543Smrg dst->geom->sz_properties = src->geom->num_properties; 1430706f2543Smrg 1431706f2543Smrg if (dst->geom->sz_properties > dst->geom->num_properties) { 1432706f2543Smrg memset(dst->geom->properties + dst->geom->num_properties, 0, 1433706f2543Smrg (dst->geom->sz_properties - dst->geom->num_properties) * 1434706f2543Smrg sizeof(XkbPropertyRec)); 1435706f2543Smrg } 1436706f2543Smrg 1437706f2543Smrg for (i = 0, 1438706f2543Smrg sprop = src->geom->properties, 1439706f2543Smrg dprop = dst->geom->properties; 1440706f2543Smrg i < src->geom->num_properties; 1441706f2543Smrg i++, sprop++, dprop++) { 1442706f2543Smrg if (i < dst->geom->num_properties) { 1443706f2543Smrg if (strlen(sprop->name) != strlen(dprop->name)) { 1444706f2543Smrg tmp = realloc(dprop->name, strlen(sprop->name) + 1); 1445706f2543Smrg if (!tmp) 1446706f2543Smrg return FALSE; 1447706f2543Smrg dprop->name = tmp; 1448706f2543Smrg } 1449706f2543Smrg if (strlen(sprop->value) != strlen(dprop->value)) { 1450706f2543Smrg tmp = realloc(dprop->value, strlen(sprop->value) + 1); 1451706f2543Smrg if (!tmp) 1452706f2543Smrg return FALSE; 1453706f2543Smrg dprop->value = tmp; 1454706f2543Smrg } 1455706f2543Smrg strcpy(dprop->name, sprop->name); 1456706f2543Smrg strcpy(dprop->value, sprop->value); 1457706f2543Smrg } 1458706f2543Smrg else { 1459706f2543Smrg dprop->name = xstrdup(sprop->name); 1460706f2543Smrg dprop->value = xstrdup(sprop->value); 1461706f2543Smrg } 1462706f2543Smrg } 1463706f2543Smrg 1464706f2543Smrg /* ... which is already src->geom->num_properties. */ 1465706f2543Smrg dst->geom->num_properties = dst->geom->sz_properties; 1466706f2543Smrg } 1467706f2543Smrg else { 1468706f2543Smrg if (dst->geom->sz_properties) { 1469706f2543Smrg for (i = 0, dprop = dst->geom->properties; 1470706f2543Smrg i < dst->geom->num_properties; 1471706f2543Smrg i++, dprop++) { 1472706f2543Smrg free(dprop->name); 1473706f2543Smrg free(dprop->value); 1474706f2543Smrg } 1475706f2543Smrg free(dst->geom->properties); 1476706f2543Smrg dst->geom->properties = NULL; 1477706f2543Smrg } 1478706f2543Smrg 1479706f2543Smrg dst->geom->num_properties = 0; 1480706f2543Smrg dst->geom->sz_properties = 0; 1481706f2543Smrg } 1482706f2543Smrg 1483706f2543Smrg /* colors */ 1484706f2543Smrg if (src->geom->num_colors) { 1485706f2543Smrg if (src->geom->num_colors != dst->geom->sz_colors) { 1486706f2543Smrg if (src->geom->num_colors < dst->geom->sz_colors) { 1487706f2543Smrg for (i = src->geom->num_colors, 1488706f2543Smrg dcolor = dst->geom->colors + i; 1489706f2543Smrg i < dst->geom->num_colors; 1490706f2543Smrg i++, dcolor++) { 1491706f2543Smrg free(dcolor->spec); 1492706f2543Smrg } 1493706f2543Smrg } 1494706f2543Smrg 1495706f2543Smrg if (dst->geom->sz_colors) 1496706f2543Smrg tmp = realloc(dst->geom->colors, 1497706f2543Smrg src->geom->num_colors * 1498706f2543Smrg sizeof(XkbColorRec)); 1499706f2543Smrg else 1500706f2543Smrg tmp = malloc(src->geom->num_colors * 1501706f2543Smrg sizeof(XkbColorRec)); 1502706f2543Smrg if (!tmp) 1503706f2543Smrg return FALSE; 1504706f2543Smrg dst->geom->colors = tmp; 1505706f2543Smrg } 1506706f2543Smrg 1507706f2543Smrg dst->geom->sz_colors = src->geom->num_colors; 1508706f2543Smrg 1509706f2543Smrg if (dst->geom->sz_colors > dst->geom->num_colors) { 1510706f2543Smrg memset(dst->geom->colors + dst->geom->num_colors, 0, 1511706f2543Smrg (dst->geom->sz_colors - dst->geom->num_colors) * 1512706f2543Smrg sizeof(XkbColorRec)); 1513706f2543Smrg } 1514706f2543Smrg 1515706f2543Smrg for (i = 0, 1516706f2543Smrg scolor = src->geom->colors, 1517706f2543Smrg dcolor = dst->geom->colors; 1518706f2543Smrg i < src->geom->num_colors; 1519706f2543Smrg i++, scolor++, dcolor++) { 1520706f2543Smrg if (i < dst->geom->num_colors) { 1521706f2543Smrg if (strlen(scolor->spec) != strlen(dcolor->spec)) { 1522706f2543Smrg tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1); 1523706f2543Smrg if (!tmp) 1524706f2543Smrg return FALSE; 1525706f2543Smrg dcolor->spec = tmp; 1526706f2543Smrg } 1527706f2543Smrg strcpy(dcolor->spec, scolor->spec); 1528706f2543Smrg } 1529706f2543Smrg else { 1530706f2543Smrg dcolor->spec = xstrdup(scolor->spec); 1531706f2543Smrg } 1532706f2543Smrg dcolor->pixel = scolor->pixel; 1533706f2543Smrg } 1534706f2543Smrg 1535706f2543Smrg dst->geom->num_colors = dst->geom->sz_colors; 1536706f2543Smrg } 1537706f2543Smrg else { 1538706f2543Smrg if (dst->geom->sz_colors) { 1539706f2543Smrg for (i = 0, dcolor = dst->geom->colors; 1540706f2543Smrg i < dst->geom->num_colors; 1541706f2543Smrg i++, dcolor++) { 1542706f2543Smrg free(dcolor->spec); 1543706f2543Smrg } 1544706f2543Smrg free(dst->geom->colors); 1545706f2543Smrg dst->geom->colors = NULL; 1546706f2543Smrg } 1547706f2543Smrg 1548706f2543Smrg dst->geom->num_colors = 0; 1549706f2543Smrg dst->geom->sz_colors = 0; 1550706f2543Smrg } 1551706f2543Smrg 1552706f2543Smrg /* shapes */ 1553706f2543Smrg /* shapes break down into outlines, which break down into points. */ 1554706f2543Smrg if (dst->geom->num_shapes) { 1555706f2543Smrg for (i = 0, dshape = dst->geom->shapes; 1556706f2543Smrg i < dst->geom->num_shapes; 1557706f2543Smrg i++, dshape++) { 1558706f2543Smrg for (j = 0, doutline = dshape->outlines; 1559706f2543Smrg j < dshape->num_outlines; 1560706f2543Smrg j++, doutline++) { 1561706f2543Smrg if (doutline->sz_points) 1562706f2543Smrg free(doutline->points); 1563706f2543Smrg } 1564706f2543Smrg 1565706f2543Smrg if (dshape->sz_outlines) { 1566706f2543Smrg free(dshape->outlines); 1567706f2543Smrg dshape->outlines = NULL; 1568706f2543Smrg } 1569706f2543Smrg 1570706f2543Smrg dshape->num_outlines = 0; 1571706f2543Smrg dshape->sz_outlines = 0; 1572706f2543Smrg } 1573706f2543Smrg } 1574706f2543Smrg 1575706f2543Smrg if (src->geom->num_shapes) { 1576706f2543Smrg tmp = calloc(src->geom->num_shapes, sizeof(XkbShapeRec)); 1577706f2543Smrg if (!tmp) 1578706f2543Smrg return FALSE; 1579706f2543Smrg dst->geom->shapes = tmp; 1580706f2543Smrg 1581706f2543Smrg for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes; 1582706f2543Smrg i < src->geom->num_shapes; 1583706f2543Smrg i++, sshape++, dshape++) { 1584706f2543Smrg if (sshape->num_outlines) { 1585706f2543Smrg tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec)); 1586706f2543Smrg if (!tmp) 1587706f2543Smrg return FALSE; 1588706f2543Smrg dshape->outlines = tmp; 1589706f2543Smrg 1590706f2543Smrg for (j = 0, 1591706f2543Smrg soutline = sshape->outlines, 1592706f2543Smrg doutline = dshape->outlines; 1593706f2543Smrg j < sshape->num_outlines; 1594706f2543Smrg j++, soutline++, doutline++) { 1595706f2543Smrg if (soutline->num_points) { 1596706f2543Smrg tmp = malloc(soutline->num_points * 1597706f2543Smrg sizeof(XkbPointRec)); 1598706f2543Smrg if (!tmp) 1599706f2543Smrg return FALSE; 1600706f2543Smrg doutline->points = tmp; 1601706f2543Smrg 1602706f2543Smrg memcpy(doutline->points, soutline->points, 1603706f2543Smrg soutline->num_points * sizeof(XkbPointRec)); 1604706f2543Smrg 1605706f2543Smrg doutline->corner_radius = soutline->corner_radius; 1606706f2543Smrg } 1607706f2543Smrg 1608706f2543Smrg doutline->num_points = soutline->num_points; 1609706f2543Smrg doutline->sz_points = soutline->num_points; 1610706f2543Smrg } 1611706f2543Smrg } 1612706f2543Smrg 1613706f2543Smrg dshape->num_outlines = sshape->num_outlines; 1614706f2543Smrg dshape->sz_outlines = sshape->num_outlines; 1615706f2543Smrg dshape->name = sshape->name; 1616706f2543Smrg dshape->bounds = sshape->bounds; 1617706f2543Smrg 1618706f2543Smrg dshape->approx = NULL; 1619706f2543Smrg if (sshape->approx && sshape->num_outlines > 0) { 1620706f2543Smrg 1621706f2543Smrg const ptrdiff_t approx_idx = 1622706f2543Smrg sshape->approx - sshape->outlines; 1623706f2543Smrg 1624706f2543Smrg if (approx_idx < dshape->num_outlines) { 1625706f2543Smrg dshape->approx = dshape->outlines + approx_idx; 1626706f2543Smrg } else { 1627706f2543Smrg LogMessage(X_WARNING, "XKB: approx outline " 1628706f2543Smrg "index is out of range\n"); 1629706f2543Smrg } 1630706f2543Smrg } 1631706f2543Smrg 1632706f2543Smrg dshape->primary = NULL; 1633706f2543Smrg if (sshape->primary && sshape->num_outlines > 0) { 1634706f2543Smrg 1635706f2543Smrg const ptrdiff_t primary_idx = 1636706f2543Smrg sshape->primary - sshape->outlines; 1637706f2543Smrg 1638706f2543Smrg if (primary_idx < dshape->num_outlines) { 1639706f2543Smrg dshape->primary = dshape->outlines + primary_idx; 1640706f2543Smrg } else { 1641706f2543Smrg LogMessage(X_WARNING, "XKB: primary outline " 1642706f2543Smrg "index is out of range\n"); 1643706f2543Smrg } 1644706f2543Smrg } 1645706f2543Smrg } 1646706f2543Smrg 1647706f2543Smrg dst->geom->num_shapes = src->geom->num_shapes; 1648706f2543Smrg dst->geom->sz_shapes = src->geom->num_shapes; 1649706f2543Smrg } 1650706f2543Smrg else { 1651706f2543Smrg if (dst->geom->sz_shapes) { 1652706f2543Smrg free(dst->geom->shapes); 1653706f2543Smrg } 1654706f2543Smrg dst->geom->shapes = NULL; 1655706f2543Smrg dst->geom->num_shapes = 0; 1656706f2543Smrg dst->geom->sz_shapes = 0; 1657706f2543Smrg } 1658706f2543Smrg 1659706f2543Smrg /* sections */ 1660706f2543Smrg /* sections break down into doodads, and also into rows, which break 1661706f2543Smrg * down into keys. */ 1662706f2543Smrg if (dst->geom->num_sections) { 1663706f2543Smrg for (i = 0, dsection = dst->geom->sections; 1664706f2543Smrg i < dst->geom->num_sections; 1665706f2543Smrg i++, dsection++) { 1666706f2543Smrg for (j = 0, drow = dsection->rows; 1667706f2543Smrg j < dsection->num_rows; 1668706f2543Smrg j++, drow++) { 1669706f2543Smrg if (drow->num_keys) 1670706f2543Smrg free(drow->keys); 1671706f2543Smrg } 1672706f2543Smrg 1673706f2543Smrg if (dsection->num_rows) 1674706f2543Smrg free(dsection->rows); 1675706f2543Smrg 1676706f2543Smrg /* cut and waste from geom/doodad below. */ 1677706f2543Smrg for (j = 0, ddoodad = dsection->doodads; 1678706f2543Smrg j < dsection->num_doodads; 1679706f2543Smrg j++, ddoodad++) { 1680706f2543Smrg if (ddoodad->any.type == XkbTextDoodad) { 1681706f2543Smrg free(ddoodad->text.text); 1682706f2543Smrg ddoodad->text.text = NULL; 1683706f2543Smrg free(ddoodad->text.font); 1684706f2543Smrg ddoodad->text.font = NULL; 1685706f2543Smrg } 1686706f2543Smrg else if (ddoodad->any.type == XkbLogoDoodad) { 1687706f2543Smrg free(ddoodad->logo.logo_name); 1688706f2543Smrg ddoodad->logo.logo_name = NULL; 1689706f2543Smrg } 1690706f2543Smrg } 1691706f2543Smrg 1692706f2543Smrg free(dsection->doodads); 1693706f2543Smrg } 1694706f2543Smrg 1695706f2543Smrg dst->geom->num_sections = 0; 1696706f2543Smrg dst->geom->sections = NULL; 1697706f2543Smrg } 1698706f2543Smrg 1699706f2543Smrg if (src->geom->num_sections) { 1700706f2543Smrg if (dst->geom->sz_sections) 1701706f2543Smrg tmp = realloc(dst->geom->sections, 1702706f2543Smrg src->geom->num_sections * 1703706f2543Smrg sizeof(XkbSectionRec)); 1704706f2543Smrg else 1705706f2543Smrg tmp = malloc(src->geom->num_sections * sizeof(XkbSectionRec)); 1706706f2543Smrg if (!tmp) 1707706f2543Smrg return FALSE; 1708706f2543Smrg memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec)); 1709706f2543Smrg dst->geom->sections = tmp; 1710706f2543Smrg dst->geom->num_sections = src->geom->num_sections; 1711706f2543Smrg dst->geom->sz_sections = src->geom->num_sections; 1712706f2543Smrg 1713706f2543Smrg for (i = 0, 1714706f2543Smrg ssection = src->geom->sections, 1715706f2543Smrg dsection = dst->geom->sections; 1716706f2543Smrg i < src->geom->num_sections; 1717706f2543Smrg i++, ssection++, dsection++) { 1718706f2543Smrg *dsection = *ssection; 1719706f2543Smrg if (ssection->num_rows) { 1720706f2543Smrg tmp = calloc(ssection->num_rows, sizeof(XkbRowRec)); 1721706f2543Smrg if (!tmp) 1722706f2543Smrg return FALSE; 1723706f2543Smrg dsection->rows = tmp; 1724706f2543Smrg } 1725706f2543Smrg dsection->num_rows = ssection->num_rows; 1726706f2543Smrg dsection->sz_rows = ssection->num_rows; 1727706f2543Smrg 1728706f2543Smrg for (j = 0, srow = ssection->rows, drow = dsection->rows; 1729706f2543Smrg j < ssection->num_rows; 1730706f2543Smrg j++, srow++, drow++) { 1731706f2543Smrg if (srow->num_keys) { 1732706f2543Smrg tmp = malloc(srow->num_keys * sizeof(XkbKeyRec)); 1733706f2543Smrg if (!tmp) 1734706f2543Smrg return FALSE; 1735706f2543Smrg drow->keys = tmp; 1736706f2543Smrg memcpy(drow->keys, srow->keys, 1737706f2543Smrg srow->num_keys * sizeof(XkbKeyRec)); 1738706f2543Smrg } 1739706f2543Smrg drow->num_keys = srow->num_keys; 1740706f2543Smrg drow->sz_keys = srow->num_keys; 1741706f2543Smrg drow->top = srow->top; 1742706f2543Smrg drow->left = srow->left; 1743706f2543Smrg drow->vertical = srow->vertical; 1744706f2543Smrg drow->bounds = srow->bounds; 1745706f2543Smrg } 1746706f2543Smrg 1747706f2543Smrg if (ssection->num_doodads) { 1748706f2543Smrg tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec)); 1749706f2543Smrg if (!tmp) 1750706f2543Smrg return FALSE; 1751706f2543Smrg dsection->doodads = tmp; 1752706f2543Smrg } 1753706f2543Smrg else { 1754706f2543Smrg dsection->doodads = NULL; 1755706f2543Smrg } 1756706f2543Smrg 1757706f2543Smrg dsection->sz_doodads = ssection->num_doodads; 1758706f2543Smrg for (k = 0, 1759706f2543Smrg sdoodad = ssection->doodads, 1760706f2543Smrg ddoodad = dsection->doodads; 1761706f2543Smrg k < ssection->num_doodads; 1762706f2543Smrg k++, sdoodad++, ddoodad++) { 1763706f2543Smrg memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec)); 1764706f2543Smrg if (sdoodad->any.type == XkbTextDoodad) { 1765706f2543Smrg if (sdoodad->text.text) 1766706f2543Smrg ddoodad->text.text = 1767706f2543Smrg strdup(sdoodad->text.text); 1768706f2543Smrg if (sdoodad->text.font) 1769706f2543Smrg ddoodad->text.font = 1770706f2543Smrg strdup(sdoodad->text.font); 1771706f2543Smrg } 1772706f2543Smrg else if (sdoodad->any.type == XkbLogoDoodad) { 1773706f2543Smrg if (sdoodad->logo.logo_name) 1774706f2543Smrg ddoodad->logo.logo_name = 1775706f2543Smrg strdup(sdoodad->logo.logo_name); 1776706f2543Smrg } 1777706f2543Smrg } 1778706f2543Smrg dsection->overlays = NULL; 1779706f2543Smrg dsection->sz_overlays = 0; 1780706f2543Smrg dsection->num_overlays = 0; 1781706f2543Smrg } 1782706f2543Smrg } 1783706f2543Smrg else { 1784706f2543Smrg if (dst->geom->sz_sections) { 1785706f2543Smrg free(dst->geom->sections); 1786706f2543Smrg } 1787706f2543Smrg 1788706f2543Smrg dst->geom->sections = NULL; 1789706f2543Smrg dst->geom->num_sections = 0; 1790706f2543Smrg dst->geom->sz_sections = 0; 1791706f2543Smrg } 1792706f2543Smrg 1793706f2543Smrg /* doodads */ 1794706f2543Smrg if (dst->geom->num_doodads) { 1795706f2543Smrg for (i = src->geom->num_doodads, 1796706f2543Smrg ddoodad = dst->geom->doodads + 1797706f2543Smrg src->geom->num_doodads; 1798706f2543Smrg i < dst->geom->num_doodads; 1799706f2543Smrg i++, ddoodad++) { 1800706f2543Smrg if (ddoodad->any.type == XkbTextDoodad) { 1801706f2543Smrg free(ddoodad->text.text); 1802706f2543Smrg ddoodad->text.text = NULL; 1803706f2543Smrg free(ddoodad->text.font); 1804706f2543Smrg ddoodad->text.font = NULL; 1805706f2543Smrg } 1806706f2543Smrg else if (ddoodad->any.type == XkbLogoDoodad) { 1807706f2543Smrg free(ddoodad->logo.logo_name); 1808706f2543Smrg ddoodad->logo.logo_name = NULL; 1809706f2543Smrg } 1810706f2543Smrg } 1811706f2543Smrg dst->geom->num_doodads = 0; 1812706f2543Smrg dst->geom->doodads = NULL; 1813706f2543Smrg } 1814706f2543Smrg 1815706f2543Smrg if (src->geom->num_doodads) { 1816706f2543Smrg if (dst->geom->sz_doodads) 1817706f2543Smrg tmp = realloc(dst->geom->doodads, 1818706f2543Smrg src->geom->num_doodads * 1819706f2543Smrg sizeof(XkbDoodadRec)); 1820706f2543Smrg else 1821706f2543Smrg tmp = malloc(src->geom->num_doodads * 1822706f2543Smrg sizeof(XkbDoodadRec)); 1823706f2543Smrg if (!tmp) 1824706f2543Smrg return FALSE; 1825706f2543Smrg memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec)); 1826706f2543Smrg dst->geom->doodads = tmp; 1827706f2543Smrg 1828706f2543Smrg dst->geom->sz_doodads = src->geom->num_doodads; 1829706f2543Smrg 1830706f2543Smrg for (i = 0, 1831706f2543Smrg sdoodad = src->geom->doodads, 1832706f2543Smrg ddoodad = dst->geom->doodads; 1833706f2543Smrg i < src->geom->num_doodads; 1834706f2543Smrg i++, sdoodad++, ddoodad++) { 1835706f2543Smrg memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec)); 1836706f2543Smrg if (sdoodad->any.type == XkbTextDoodad) { 1837706f2543Smrg if (sdoodad->text.text) 1838706f2543Smrg ddoodad->text.text = strdup(sdoodad->text.text); 1839706f2543Smrg if (sdoodad->text.font) 1840706f2543Smrg ddoodad->text.font = strdup(sdoodad->text.font); 1841706f2543Smrg } 1842706f2543Smrg else if (sdoodad->any.type == XkbLogoDoodad) { 1843706f2543Smrg if (sdoodad->logo.logo_name) 1844706f2543Smrg ddoodad->logo.logo_name = 1845706f2543Smrg strdup(sdoodad->logo.logo_name); 1846706f2543Smrg } 1847706f2543Smrg } 1848706f2543Smrg 1849706f2543Smrg dst->geom->num_doodads = dst->geom->sz_doodads; 1850706f2543Smrg } 1851706f2543Smrg else { 1852706f2543Smrg if (dst->geom->sz_doodads) { 1853706f2543Smrg free(dst->geom->doodads); 1854706f2543Smrg } 1855706f2543Smrg 1856706f2543Smrg dst->geom->doodads = NULL; 1857706f2543Smrg dst->geom->num_doodads = 0; 1858706f2543Smrg dst->geom->sz_doodads = 0; 1859706f2543Smrg } 1860706f2543Smrg 1861706f2543Smrg /* key aliases */ 1862706f2543Smrg if (src->geom->num_key_aliases) { 1863706f2543Smrg if (src->geom->num_key_aliases != dst->geom->sz_key_aliases) { 1864706f2543Smrg if (dst->geom->sz_key_aliases) 1865706f2543Smrg tmp = realloc(dst->geom->key_aliases, 1866706f2543Smrg src->geom->num_key_aliases * 1867706f2543Smrg 2 * XkbKeyNameLength); 1868706f2543Smrg else 1869706f2543Smrg tmp = malloc(src->geom->num_key_aliases * 1870706f2543Smrg 2 * XkbKeyNameLength); 1871706f2543Smrg if (!tmp) 1872706f2543Smrg return FALSE; 1873706f2543Smrg dst->geom->key_aliases = tmp; 1874706f2543Smrg 1875706f2543Smrg dst->geom->sz_key_aliases = src->geom->num_key_aliases; 1876706f2543Smrg } 1877706f2543Smrg 1878706f2543Smrg memcpy(dst->geom->key_aliases, src->geom->key_aliases, 1879706f2543Smrg src->geom->num_key_aliases * 2 * XkbKeyNameLength); 1880706f2543Smrg 1881706f2543Smrg dst->geom->num_key_aliases = dst->geom->sz_key_aliases; 1882706f2543Smrg } 1883706f2543Smrg else { 1884706f2543Smrg free(dst->geom->key_aliases); 1885706f2543Smrg dst->geom->key_aliases = NULL; 1886706f2543Smrg dst->geom->num_key_aliases = 0; 1887706f2543Smrg dst->geom->sz_key_aliases = 0; 1888706f2543Smrg } 1889706f2543Smrg 1890706f2543Smrg /* font */ 1891706f2543Smrg if (src->geom->label_font) { 1892706f2543Smrg if (!dst->geom->label_font) { 1893706f2543Smrg tmp = malloc(strlen(src->geom->label_font) + 1); 1894706f2543Smrg if (!tmp) 1895706f2543Smrg return FALSE; 1896706f2543Smrg dst->geom->label_font = tmp; 1897706f2543Smrg } 1898706f2543Smrg else if (strlen(src->geom->label_font) != 1899706f2543Smrg strlen(dst->geom->label_font)) { 1900706f2543Smrg tmp = realloc(dst->geom->label_font, 1901706f2543Smrg strlen(src->geom->label_font) + 1); 1902706f2543Smrg if (!tmp) 1903706f2543Smrg return FALSE; 1904706f2543Smrg dst->geom->label_font = tmp; 1905706f2543Smrg } 1906706f2543Smrg 1907706f2543Smrg strcpy(dst->geom->label_font, src->geom->label_font); 1908706f2543Smrg i = XkbGeomColorIndex(src->geom, src->geom->label_color); 1909706f2543Smrg dst->geom->label_color = &(dst->geom->colors[i]); 1910706f2543Smrg i = XkbGeomColorIndex(src->geom, src->geom->base_color); 1911706f2543Smrg dst->geom->base_color = &(dst->geom->colors[i]); 1912706f2543Smrg } 1913706f2543Smrg else { 1914706f2543Smrg free(dst->geom->label_font); 1915706f2543Smrg dst->geom->label_font = NULL; 1916706f2543Smrg dst->geom->label_color = NULL; 1917706f2543Smrg dst->geom->base_color = NULL; 1918706f2543Smrg } 1919706f2543Smrg 1920706f2543Smrg dst->geom->name = src->geom->name; 1921706f2543Smrg dst->geom->width_mm = src->geom->width_mm; 1922706f2543Smrg dst->geom->height_mm = src->geom->height_mm; 1923706f2543Smrg } 1924706f2543Smrg else 1925706f2543Smrg { 1926706f2543Smrg if (dst->geom) { 1927706f2543Smrg /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */ 1928706f2543Smrg XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE); 1929706f2543Smrg dst->geom = NULL; 1930706f2543Smrg } 1931706f2543Smrg } 1932706f2543Smrg 1933706f2543Smrg return TRUE; 1934706f2543Smrg} 1935706f2543Smrg 1936706f2543Smrgstatic Bool 1937706f2543Smrg_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst) 1938706f2543Smrg{ 1939706f2543Smrg /* indicators */ 1940706f2543Smrg if (src->indicators) { 1941706f2543Smrg if (!dst->indicators) { 1942706f2543Smrg dst->indicators = malloc(sizeof(XkbIndicatorRec)); 1943706f2543Smrg if (!dst->indicators) 1944706f2543Smrg return FALSE; 1945706f2543Smrg } 1946706f2543Smrg memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec)); 1947706f2543Smrg } 1948706f2543Smrg else { 1949706f2543Smrg free(dst->indicators); 1950706f2543Smrg dst->indicators = NULL; 1951706f2543Smrg } 1952706f2543Smrg return TRUE; 1953706f2543Smrg} 1954706f2543Smrg 1955706f2543Smrgstatic Bool 1956706f2543Smrg_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst) 1957706f2543Smrg{ 1958706f2543Smrg /* controls */ 1959706f2543Smrg if (src->ctrls) { 1960706f2543Smrg if (!dst->ctrls) { 1961706f2543Smrg dst->ctrls = malloc(sizeof(XkbControlsRec)); 1962706f2543Smrg if (!dst->ctrls) 1963706f2543Smrg return FALSE; 1964706f2543Smrg } 1965706f2543Smrg memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec)); 1966706f2543Smrg } 1967706f2543Smrg else { 1968706f2543Smrg free(dst->ctrls); 1969706f2543Smrg dst->ctrls = NULL; 1970706f2543Smrg } 1971706f2543Smrg return TRUE; 1972706f2543Smrg} 1973706f2543Smrg 1974706f2543Smrg/** 1975706f2543Smrg * Copy an XKB map from src to dst, reallocating when necessary: if some 1976706f2543Smrg * map components are present in one, but not in the other, the destination 1977706f2543Smrg * components will be allocated or freed as necessary. 1978706f2543Smrg * 1979706f2543Smrg * Basic map consistency is assumed on both sides, so maps with random 1980706f2543Smrg * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19) 1981706f2543Smrg * _will_ cause failures. You've been warned. 1982706f2543Smrg * 1983706f2543Smrg * Returns TRUE on success, or FALSE on failure. If this function fails, 1984706f2543Smrg * dst may be in an inconsistent state: all its pointers are guaranteed 1985706f2543Smrg * to remain valid, but part of the map may be from src and part from dst. 1986706f2543Smrg * 1987706f2543Smrg */ 1988706f2543Smrg 1989706f2543SmrgBool 1990706f2543SmrgXkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) 1991706f2543Smrg{ 1992706f2543Smrg 1993706f2543Smrg if (!src || !dst) { 1994706f2543Smrg DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst); 1995706f2543Smrg return FALSE; 1996706f2543Smrg } 1997706f2543Smrg 1998706f2543Smrg if (src == dst) 1999706f2543Smrg return TRUE; 2000706f2543Smrg 2001706f2543Smrg if (!_XkbCopyClientMap(src, dst)) { 2002706f2543Smrg DebugF("XkbCopyKeymap: failed to copy client map\n"); 2003706f2543Smrg return FALSE; 2004706f2543Smrg } 2005706f2543Smrg if (!_XkbCopyServerMap(src, dst)) { 2006706f2543Smrg DebugF("XkbCopyKeymap: failed to copy server map\n"); 2007706f2543Smrg return FALSE; 2008706f2543Smrg } 2009706f2543Smrg if (!_XkbCopyIndicators(src, dst)) { 2010706f2543Smrg DebugF("XkbCopyKeymap: failed to copy indicators\n"); 2011706f2543Smrg return FALSE; 2012706f2543Smrg } 2013706f2543Smrg if (!_XkbCopyControls(src, dst)) { 2014706f2543Smrg DebugF("XkbCopyKeymap: failed to copy controls\n"); 2015706f2543Smrg return FALSE; 2016706f2543Smrg } 2017706f2543Smrg if (!_XkbCopyNames(src, dst)) { 2018706f2543Smrg DebugF("XkbCopyKeymap: failed to copy names\n"); 2019706f2543Smrg return FALSE; 2020706f2543Smrg } 2021706f2543Smrg if (!_XkbCopyCompat(src, dst)) { 2022706f2543Smrg DebugF("XkbCopyKeymap: failed to copy compat map\n"); 2023706f2543Smrg return FALSE; 2024706f2543Smrg } 2025706f2543Smrg if (!_XkbCopyGeom(src, dst)) { 2026706f2543Smrg DebugF("XkbCopyKeymap: failed to copy geometry\n"); 2027706f2543Smrg return FALSE; 2028706f2543Smrg } 2029706f2543Smrg 2030706f2543Smrg dst->min_key_code = src->min_key_code; 2031706f2543Smrg dst->max_key_code = src->max_key_code; 2032706f2543Smrg 2033706f2543Smrg return TRUE; 2034706f2543Smrg} 2035706f2543Smrg 2036706f2543SmrgBool 2037706f2543SmrgXkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) 2038706f2543Smrg{ 2039706f2543Smrg xkbNewKeyboardNotify nkn; 2040706f2543Smrg Bool ret; 2041706f2543Smrg 2042706f2543Smrg if (!dst->key || !src->key) 2043706f2543Smrg return FALSE; 2044706f2543Smrg 2045706f2543Smrg memset(&nkn, 0, sizeof(xkbNewKeyboardNotify)); 2046706f2543Smrg nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; 2047706f2543Smrg nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; 2048706f2543Smrg nkn.deviceID = dst->id; 2049706f2543Smrg nkn.oldDeviceID = dst->id; /* maybe src->id? */ 2050706f2543Smrg nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code; 2051706f2543Smrg nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code; 2052706f2543Smrg nkn.requestMajor = XkbReqCode; 2053706f2543Smrg nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ 2054706f2543Smrg nkn.changed = XkbNKN_KeycodesMask; 2055706f2543Smrg if (src->key->xkbInfo->desc->geom) 2056706f2543Smrg nkn.changed |= XkbNKN_GeometryMask; 2057706f2543Smrg 2058706f2543Smrg ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc); 2059706f2543Smrg if (ret) 2060706f2543Smrg XkbSendNewKeyboardNotify(dst, &nkn); 2061706f2543Smrg 2062706f2543Smrg return ret; 2063706f2543Smrg} 2064706f2543Smrg 2065706f2543Smrgint 2066706f2543SmrgXkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode) 2067706f2543Smrg{ 2068706f2543Smrg XkbDescPtr xkb = xkbi->desc; 2069706f2543Smrg int effectiveGroup = xkbState->group; 2070706f2543Smrg 2071706f2543Smrg if (!XkbKeycodeInRange(xkb, keycode)) 2072706f2543Smrg return -1; 2073706f2543Smrg 2074706f2543Smrg if (effectiveGroup == XkbGroup1Index) 2075706f2543Smrg return effectiveGroup; 2076706f2543Smrg 2077706f2543Smrg if (XkbKeyNumGroups(xkb,keycode) > 1U) { 2078706f2543Smrg if (effectiveGroup >= XkbKeyNumGroups(xkb,keycode)) { 2079706f2543Smrg unsigned int gi = XkbKeyGroupInfo(xkb,keycode); 2080706f2543Smrg switch (XkbOutOfRangeGroupAction(gi)) { 2081706f2543Smrg default: 2082706f2543Smrg case XkbWrapIntoRange: 2083706f2543Smrg effectiveGroup %= XkbKeyNumGroups(xkb, keycode); 2084706f2543Smrg break; 2085706f2543Smrg case XkbClampIntoRange: 2086706f2543Smrg effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1; 2087706f2543Smrg break; 2088706f2543Smrg case XkbRedirectIntoRange: 2089706f2543Smrg effectiveGroup = XkbOutOfRangeGroupInfo(gi); 2090706f2543Smrg if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode)) 2091706f2543Smrg effectiveGroup = 0; 2092706f2543Smrg break; 2093706f2543Smrg } 2094706f2543Smrg } 2095706f2543Smrg } 2096706f2543Smrg else effectiveGroup = XkbGroup1Index; 2097706f2543Smrg 2098706f2543Smrg return effectiveGroup; 2099706f2543Smrg} 2100706f2543Smrg 2101706f2543Smrg/* Merge the lockedPtrButtons from all attached SDs for the given master 2102706f2543Smrg * device into the MD's state. 2103706f2543Smrg */ 2104706f2543Smrgvoid 2105706f2543SmrgXkbMergeLockedPtrBtns(DeviceIntPtr master) 2106706f2543Smrg{ 2107706f2543Smrg DeviceIntPtr d = inputInfo.devices; 2108706f2543Smrg XkbSrvInfoPtr xkbi = NULL; 2109706f2543Smrg 2110706f2543Smrg if (!IsMaster(master)) 2111706f2543Smrg return; 2112706f2543Smrg 2113706f2543Smrg if (!master->key) 2114706f2543Smrg return; 2115706f2543Smrg 2116706f2543Smrg xkbi = master->key->xkbInfo; 2117706f2543Smrg xkbi->lockedPtrButtons = 0; 2118706f2543Smrg 2119706f2543Smrg for (; d; d = d->next) { 2120706f2543Smrg if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key) 2121706f2543Smrg continue; 2122706f2543Smrg 2123706f2543Smrg xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons; 2124706f2543Smrg } 2125706f2543Smrg} 2126