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#ifdef HAVE_DIX_CONFIG_H 28706f2543Smrg#include <dix-config.h> 29706f2543Smrg#elif defined(HAVE_CONFIG_H) 30706f2543Smrg#include <config.h> 31706f2543Smrg#endif 32706f2543Smrg 33706f2543Smrg#include <stdio.h> 34706f2543Smrg#include <X11/X.h> 35706f2543Smrg#include <X11/Xproto.h> 36706f2543Smrg#include "misc.h" 37706f2543Smrg#include "inputstr.h" 38706f2543Smrg#include <X11/keysym.h> 39706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS 40706f2543Smrg#include <xkbsrv.h> 41706f2543Smrg 42706f2543Smrg/***====================================================================***/ 43706f2543Smrg 44706f2543SmrgStatus 45706f2543SmrgXkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes) 46706f2543Smrg{ 47706f2543Smrgregister int i; 48706f2543SmrgXkbClientMapPtr map; 49706f2543Smrg 50706f2543Smrg if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes))) 51706f2543Smrg return BadValue; 52706f2543Smrg if ((which&XkbKeySymsMask)&& 53706f2543Smrg ((!XkbIsLegalKeycode(xkb->min_key_code))|| 54706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 55706f2543Smrg (xkb->max_key_code<xkb->min_key_code))) { 56706f2543Smrg DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n", 57706f2543Smrg xkb->min_key_code,xkb->max_key_code); 58706f2543Smrg return BadValue; 59706f2543Smrg } 60706f2543Smrg 61706f2543Smrg if (xkb->map==NULL) { 62706f2543Smrg map= calloc(1, sizeof(XkbClientMapRec)); 63706f2543Smrg if (map==NULL) 64706f2543Smrg return BadAlloc; 65706f2543Smrg xkb->map= map; 66706f2543Smrg } 67706f2543Smrg else map= xkb->map; 68706f2543Smrg 69706f2543Smrg if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) { 70706f2543Smrg if (map->types==NULL) { 71706f2543Smrg map->types= calloc(nTotalTypes, sizeof(XkbKeyTypeRec)); 72706f2543Smrg if (map->types==NULL) 73706f2543Smrg return BadAlloc; 74706f2543Smrg map->num_types= 0; 75706f2543Smrg map->size_types= nTotalTypes; 76706f2543Smrg } 77706f2543Smrg else if (map->size_types<nTotalTypes) { 78706f2543Smrg XkbKeyTypeRec *prev_types = map->types; 79706f2543Smrg 80706f2543Smrg map->types= realloc(map->types,nTotalTypes * sizeof(XkbKeyTypeRec)); 81706f2543Smrg if (map->types==NULL) { 82706f2543Smrg free(prev_types); 83706f2543Smrg map->num_types= map->size_types= 0; 84706f2543Smrg return BadAlloc; 85706f2543Smrg } 86706f2543Smrg map->size_types= nTotalTypes; 87706f2543Smrg memset(&map->types[map->num_types], 0, 88706f2543Smrg ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec))); 89706f2543Smrg } 90706f2543Smrg } 91706f2543Smrg if (which&XkbKeySymsMask) { 92706f2543Smrg int nKeys= XkbNumKeys(xkb); 93706f2543Smrg if (map->syms==NULL) { 94706f2543Smrg map->size_syms= (nKeys*15)/10; 95706f2543Smrg map->syms= calloc(map->size_syms, sizeof(KeySym)); 96706f2543Smrg if (!map->syms) { 97706f2543Smrg map->size_syms= 0; 98706f2543Smrg return BadAlloc; 99706f2543Smrg } 100706f2543Smrg map->num_syms= 1; 101706f2543Smrg map->syms[0]= NoSymbol; 102706f2543Smrg } 103706f2543Smrg if (map->key_sym_map==NULL) { 104706f2543Smrg i= xkb->max_key_code+1; 105706f2543Smrg map->key_sym_map= calloc(i, sizeof(XkbSymMapRec)); 106706f2543Smrg if (map->key_sym_map==NULL) 107706f2543Smrg return BadAlloc; 108706f2543Smrg } 109706f2543Smrg } 110706f2543Smrg if (which&XkbModifierMapMask) { 111706f2543Smrg if ((!XkbIsLegalKeycode(xkb->min_key_code))|| 112706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 113706f2543Smrg (xkb->max_key_code<xkb->min_key_code)) 114706f2543Smrg return BadMatch; 115706f2543Smrg if (map->modmap==NULL) { 116706f2543Smrg i= xkb->max_key_code+1; 117706f2543Smrg map->modmap= calloc(i, sizeof(unsigned char)); 118706f2543Smrg if (map->modmap==NULL) 119706f2543Smrg return BadAlloc; 120706f2543Smrg } 121706f2543Smrg } 122706f2543Smrg return Success; 123706f2543Smrg} 124706f2543Smrg 125706f2543SmrgStatus 126706f2543SmrgXkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions) 127706f2543Smrg{ 128706f2543Smrgregister int i; 129706f2543SmrgXkbServerMapPtr map; 130706f2543Smrg 131706f2543Smrg if (xkb==NULL) 132706f2543Smrg return BadMatch; 133706f2543Smrg if (xkb->server==NULL) { 134706f2543Smrg map= calloc(1, sizeof(XkbServerMapRec)); 135706f2543Smrg if (map==NULL) 136706f2543Smrg return BadAlloc; 137706f2543Smrg for (i=0;i<XkbNumVirtualMods;i++) { 138706f2543Smrg map->vmods[i]= XkbNoModifierMask; 139706f2543Smrg } 140706f2543Smrg xkb->server= map; 141706f2543Smrg } 142706f2543Smrg else map= xkb->server; 143706f2543Smrg if (which&XkbExplicitComponentsMask) { 144706f2543Smrg if ((!XkbIsLegalKeycode(xkb->min_key_code))|| 145706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 146706f2543Smrg (xkb->max_key_code<xkb->min_key_code)) 147706f2543Smrg return BadMatch; 148706f2543Smrg if (map->explicit==NULL) { 149706f2543Smrg i= xkb->max_key_code+1; 150706f2543Smrg map->explicit= calloc(i, sizeof(unsigned char)); 151706f2543Smrg if (map->explicit==NULL) 152706f2543Smrg return BadAlloc; 153706f2543Smrg } 154706f2543Smrg } 155706f2543Smrg if (which&XkbKeyActionsMask) { 156706f2543Smrg if ((!XkbIsLegalKeycode(xkb->min_key_code))|| 157706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 158706f2543Smrg (xkb->max_key_code<xkb->min_key_code)) 159706f2543Smrg return BadMatch; 160706f2543Smrg if (nNewActions<1) 161706f2543Smrg nNewActions= 1; 162706f2543Smrg if (map->acts==NULL) { 163706f2543Smrg map->acts= calloc((nNewActions+1), sizeof(XkbAction)); 164706f2543Smrg if (map->acts==NULL) 165706f2543Smrg return BadAlloc; 166706f2543Smrg map->num_acts= 1; 167706f2543Smrg map->size_acts= nNewActions+1; 168706f2543Smrg } 169706f2543Smrg else if ((map->size_acts-map->num_acts)<nNewActions) { 170706f2543Smrg unsigned need; 171706f2543Smrg XkbAction *prev_acts = map->acts; 172706f2543Smrg need= map->num_acts+nNewActions; 173706f2543Smrg map->acts= realloc(map->acts,need * sizeof(XkbAction)); 174706f2543Smrg if (map->acts==NULL) { 175706f2543Smrg free(prev_acts); 176706f2543Smrg map->num_acts= map->size_acts= 0; 177706f2543Smrg return BadAlloc; 178706f2543Smrg } 179706f2543Smrg map->size_acts= need; 180706f2543Smrg memset(&map->acts[map->num_acts], 0, 181706f2543Smrg ((map->size_acts-map->num_acts)*sizeof(XkbAction))); 182706f2543Smrg } 183706f2543Smrg if (map->key_acts==NULL) { 184706f2543Smrg i= xkb->max_key_code+1; 185706f2543Smrg map->key_acts= calloc(i, sizeof(unsigned short)); 186706f2543Smrg if (map->key_acts==NULL) 187706f2543Smrg return BadAlloc; 188706f2543Smrg } 189706f2543Smrg } 190706f2543Smrg if (which&XkbKeyBehaviorsMask) { 191706f2543Smrg if ((!XkbIsLegalKeycode(xkb->min_key_code))|| 192706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 193706f2543Smrg (xkb->max_key_code<xkb->min_key_code)) 194706f2543Smrg return BadMatch; 195706f2543Smrg if (map->behaviors==NULL) { 196706f2543Smrg i= xkb->max_key_code+1; 197706f2543Smrg map->behaviors= calloc(i, sizeof(XkbBehavior)); 198706f2543Smrg if (map->behaviors==NULL) 199706f2543Smrg return BadAlloc; 200706f2543Smrg } 201706f2543Smrg } 202706f2543Smrg if (which&XkbVirtualModMapMask) { 203706f2543Smrg if ((!XkbIsLegalKeycode(xkb->min_key_code))|| 204706f2543Smrg (!XkbIsLegalKeycode(xkb->max_key_code))|| 205706f2543Smrg (xkb->max_key_code<xkb->min_key_code)) 206706f2543Smrg return BadMatch; 207706f2543Smrg if (map->vmodmap==NULL) { 208706f2543Smrg i= xkb->max_key_code+1; 209706f2543Smrg map->vmodmap= calloc(i, sizeof(unsigned short)); 210706f2543Smrg if (map->vmodmap==NULL) 211706f2543Smrg return BadAlloc; 212706f2543Smrg } 213706f2543Smrg } 214706f2543Smrg return Success; 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrg/***====================================================================***/ 218706f2543Smrg 219706f2543Smrgstatic Status 220706f2543SmrgXkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into) 221706f2543Smrg{ 222706f2543Smrg if ((!from)||(!into)) 223706f2543Smrg return BadMatch; 224706f2543Smrg free(into->map); 225706f2543Smrg into->map = NULL; 226706f2543Smrg free(into->preserve); 227706f2543Smrg into->preserve = NULL; 228706f2543Smrg free(into->level_names); 229706f2543Smrg into->level_names = NULL; 230706f2543Smrg *into= *from; 231706f2543Smrg if ((from->map)&&(into->map_count>0)) { 232706f2543Smrg into->map= calloc(into->map_count, sizeof(XkbKTMapEntryRec)); 233706f2543Smrg if (!into->map) 234706f2543Smrg return BadAlloc; 235706f2543Smrg memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec)); 236706f2543Smrg } 237706f2543Smrg if ((from->preserve)&&(into->map_count>0)) { 238706f2543Smrg into->preserve= calloc(into->map_count, sizeof(XkbModsRec)); 239706f2543Smrg if (!into->preserve) 240706f2543Smrg return BadAlloc; 241706f2543Smrg memcpy(into->preserve,from->preserve, 242706f2543Smrg into->map_count*sizeof(XkbModsRec)); 243706f2543Smrg } 244706f2543Smrg if ((from->level_names)&&(into->num_levels>0)) { 245706f2543Smrg into->level_names= calloc(into->num_levels, sizeof(Atom)); 246706f2543Smrg if (!into->level_names) 247706f2543Smrg return BadAlloc; 248706f2543Smrg memcpy(into->level_names,from->level_names, 249706f2543Smrg into->num_levels*sizeof(Atom)); 250706f2543Smrg } 251706f2543Smrg return Success; 252706f2543Smrg} 253706f2543Smrg 254706f2543SmrgStatus 255706f2543SmrgXkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types) 256706f2543Smrg{ 257706f2543Smrgregister int i,rtrn; 258706f2543Smrg 259706f2543Smrg if ((!from)||(!into)||(num_types<0)) 260706f2543Smrg return BadMatch; 261706f2543Smrg for (i=0;i<num_types;i++) { 262706f2543Smrg if ((rtrn= XkbCopyKeyType(from++,into++))!=Success) 263706f2543Smrg return rtrn; 264706f2543Smrg } 265706f2543Smrg return Success; 266706f2543Smrg} 267706f2543Smrg 268706f2543SmrgStatus 269706f2543SmrgXkbResizeKeyType( XkbDescPtr xkb, 270706f2543Smrg int type_ndx, 271706f2543Smrg int map_count, 272706f2543Smrg Bool want_preserve, 273706f2543Smrg int new_num_lvls) 274706f2543Smrg{ 275706f2543SmrgXkbKeyTypePtr type; 276706f2543SmrgKeyCode matchingKeys[XkbMaxKeyCount],nMatchingKeys; 277706f2543Smrg 278706f2543Smrg if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)|| 279706f2543Smrg (new_num_lvls<1)) 280706f2543Smrg return BadValue; 281706f2543Smrg switch (type_ndx) { 282706f2543Smrg case XkbOneLevelIndex: 283706f2543Smrg if (new_num_lvls!=1) 284706f2543Smrg return BadMatch; 285706f2543Smrg break; 286706f2543Smrg case XkbTwoLevelIndex: 287706f2543Smrg case XkbAlphabeticIndex: 288706f2543Smrg case XkbKeypadIndex: 289706f2543Smrg if (new_num_lvls!=2) 290706f2543Smrg return BadMatch; 291706f2543Smrg break; 292706f2543Smrg } 293706f2543Smrg type= &xkb->map->types[type_ndx]; 294706f2543Smrg if (map_count==0) { 295706f2543Smrg free(type->map); 296706f2543Smrg type->map= NULL; 297706f2543Smrg free(type->preserve); 298706f2543Smrg type->preserve= NULL; 299706f2543Smrg type->map_count= 0; 300706f2543Smrg } 301706f2543Smrg else { 302706f2543Smrg XkbKTMapEntryRec *prev_map = type->map; 303706f2543Smrg 304706f2543Smrg if ((map_count>type->map_count)||(type->map==NULL)) 305706f2543Smrg type->map = realloc(type->map,map_count * sizeof(XkbKTMapEntryRec)); 306706f2543Smrg if (!type->map) { 307706f2543Smrg free(prev_map); 308706f2543Smrg return BadAlloc; 309706f2543Smrg } 310706f2543Smrg if (want_preserve) { 311706f2543Smrg XkbModsRec *prev_preserve = type->preserve; 312706f2543Smrg 313706f2543Smrg if ((map_count>type->map_count)||(type->preserve==NULL)) { 314706f2543Smrg type->preserve = realloc(type->preserve, 315706f2543Smrg map_count * sizeof(XkbModsRec)); 316706f2543Smrg } 317706f2543Smrg if (!type->preserve) { 318706f2543Smrg free(prev_preserve); 319706f2543Smrg return BadAlloc; 320706f2543Smrg } 321706f2543Smrg } 322706f2543Smrg else { 323706f2543Smrg free(type->preserve); 324706f2543Smrg type->preserve = NULL; 325706f2543Smrg } 326706f2543Smrg type->map_count= map_count; 327706f2543Smrg } 328706f2543Smrg 329706f2543Smrg if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) { 330706f2543Smrg Atom * prev_level_names = type->level_names; 331706f2543Smrg 332706f2543Smrg type->level_names = realloc(type->level_names, 333706f2543Smrg new_num_lvls * sizeof(Atom)); 334706f2543Smrg if (!type->level_names) { 335706f2543Smrg free(prev_level_names); 336706f2543Smrg return BadAlloc; 337706f2543Smrg } 338706f2543Smrg } 339706f2543Smrg /* 340706f2543Smrg * Here's the theory: 341706f2543Smrg * If the width of the type changed, we might have to resize the symbol 342706f2543Smrg * maps for any keys that use the type for one or more groups. This is 343706f2543Smrg * expensive, so we'll try to cull out any keys that are obviously okay: 344706f2543Smrg * In any case: 345706f2543Smrg * - keys that have a group width <= the old width are okay (because 346706f2543Smrg * they could not possibly have been associated with the old type) 347706f2543Smrg * If the key type increased in size: 348706f2543Smrg * - keys that already have a group width >= to the new width are okay 349706f2543Smrg * + keys that have a group width >= the old width but < the new width 350706f2543Smrg * might have to be enlarged. 351706f2543Smrg * If the key type decreased in size: 352706f2543Smrg * - keys that have a group width > the old width don't have to be 353706f2543Smrg * resized (because they must have some other wider type associated 354706f2543Smrg * with some group). 355706f2543Smrg * + keys that have a group width == the old width might have to be 356706f2543Smrg * shrunk. 357706f2543Smrg * The possibilities marked with '+' require us to examine the key types 358706f2543Smrg * associated with each group for the key. 359706f2543Smrg */ 360706f2543Smrg memset(matchingKeys, 0, XkbMaxKeyCount*sizeof(KeyCode)); 361706f2543Smrg nMatchingKeys= 0; 362706f2543Smrg if (new_num_lvls>type->num_levels) { 363706f2543Smrg int nTotal; 364706f2543Smrg KeySym * newSyms; 365706f2543Smrg int width,match,nResize; 366706f2543Smrg register int i,g,nSyms; 367706f2543Smrg 368706f2543Smrg nResize= 0; 369706f2543Smrg for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 370706f2543Smrg width= XkbKeyGroupsWidth(xkb,i); 371706f2543Smrg if (width<type->num_levels) 372706f2543Smrg continue; 373706f2543Smrg for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { 374706f2543Smrg if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { 375706f2543Smrg matchingKeys[nMatchingKeys++]= i; 376706f2543Smrg match= 1; 377706f2543Smrg } 378706f2543Smrg } 379706f2543Smrg if ((!match)||(width>=new_num_lvls)) 380706f2543Smrg nTotal+= XkbKeyNumSyms(xkb,i); 381706f2543Smrg else { 382706f2543Smrg nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls; 383706f2543Smrg nResize++; 384706f2543Smrg } 385706f2543Smrg } 386706f2543Smrg if (nResize>0) { 387706f2543Smrg int nextMatch; 388706f2543Smrg xkb->map->size_syms= (nTotal*15)/10; 389706f2543Smrg newSyms = calloc(xkb->map->size_syms, sizeof(KeySym)); 390706f2543Smrg if (newSyms==NULL) 391706f2543Smrg return BadAlloc; 392706f2543Smrg nextMatch= 0; 393706f2543Smrg nSyms= 1; 394706f2543Smrg for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 395706f2543Smrg if (matchingKeys[nextMatch]==i) { 396706f2543Smrg KeySym *pOld; 397706f2543Smrg nextMatch++; 398706f2543Smrg width= XkbKeyGroupsWidth(xkb,i); 399706f2543Smrg pOld= XkbKeySymsPtr(xkb,i); 400706f2543Smrg for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) { 401706f2543Smrg memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g], 402706f2543Smrg width*sizeof(KeySym)); 403706f2543Smrg } 404706f2543Smrg xkb->map->key_sym_map[i].offset= nSyms; 405706f2543Smrg nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls; 406706f2543Smrg } 407706f2543Smrg else { 408706f2543Smrg memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i), 409706f2543Smrg XkbKeyNumSyms(xkb,i)*sizeof(KeySym)); 410706f2543Smrg xkb->map->key_sym_map[i].offset= nSyms; 411706f2543Smrg nSyms+= XkbKeyNumSyms(xkb,i); 412706f2543Smrg } 413706f2543Smrg } 414706f2543Smrg type->num_levels= new_num_lvls; 415706f2543Smrg free(xkb->map->syms); 416706f2543Smrg xkb->map->syms= newSyms; 417706f2543Smrg xkb->map->num_syms= nSyms; 418706f2543Smrg return Success; 419706f2543Smrg } 420706f2543Smrg } 421706f2543Smrg else if (new_num_lvls<type->num_levels) { 422706f2543Smrg int width,match; 423706f2543Smrg register int g,i; 424706f2543Smrg for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 425706f2543Smrg width= XkbKeyGroupsWidth(xkb,i); 426706f2543Smrg if (width<type->num_levels) 427706f2543Smrg continue; 428706f2543Smrg for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) { 429706f2543Smrg if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) { 430706f2543Smrg matchingKeys[nMatchingKeys++]= i; 431706f2543Smrg match= 1; 432706f2543Smrg } 433706f2543Smrg } 434706f2543Smrg } 435706f2543Smrg } 436706f2543Smrg if (nMatchingKeys>0) { 437706f2543Smrg int key,firstClear; 438706f2543Smrg register int i,g; 439706f2543Smrg if (new_num_lvls>type->num_levels) 440706f2543Smrg firstClear= type->num_levels; 441706f2543Smrg else firstClear= new_num_lvls; 442706f2543Smrg for (i=0;i<nMatchingKeys;i++) { 443706f2543Smrg KeySym * pSyms; 444706f2543Smrg int width,nClear; 445706f2543Smrg 446706f2543Smrg key= matchingKeys[i]; 447706f2543Smrg width= XkbKeyGroupsWidth(xkb,key); 448706f2543Smrg nClear= width-firstClear; 449706f2543Smrg pSyms= XkbKeySymsPtr(xkb,key); 450706f2543Smrg for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) { 451706f2543Smrg if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) { 452706f2543Smrg if (nClear>0) 453706f2543Smrg memset(&pSyms[g*width+firstClear], 0, nClear*sizeof(KeySym)); 454706f2543Smrg } 455706f2543Smrg } 456706f2543Smrg } 457706f2543Smrg } 458706f2543Smrg type->num_levels= new_num_lvls; 459706f2543Smrg return Success; 460706f2543Smrg} 461706f2543Smrg 462706f2543SmrgKeySym * 463706f2543SmrgXkbResizeKeySyms(XkbDescPtr xkb,int key,int needed) 464706f2543Smrg{ 465706f2543Smrgregister int i,nSyms,nKeySyms; 466706f2543Smrgunsigned nOldSyms; 467706f2543SmrgKeySym *newSyms; 468706f2543Smrg 469706f2543Smrg if (needed==0) { 470706f2543Smrg xkb->map->key_sym_map[key].offset= 0; 471706f2543Smrg return xkb->map->syms; 472706f2543Smrg } 473706f2543Smrg nOldSyms= XkbKeyNumSyms(xkb,key); 474706f2543Smrg if (nOldSyms>=(unsigned)needed) { 475706f2543Smrg return XkbKeySymsPtr(xkb,key); 476706f2543Smrg } 477706f2543Smrg if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) { 478706f2543Smrg if (nOldSyms>0) { 479706f2543Smrg memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key), 480706f2543Smrg nOldSyms*sizeof(KeySym)); 481706f2543Smrg } 482706f2543Smrg if ((needed-nOldSyms)>0) { 483706f2543Smrg memset(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb, key)], 484706f2543Smrg 0, (needed-nOldSyms)*sizeof(KeySym)); 485706f2543Smrg } 486706f2543Smrg xkb->map->key_sym_map[key].offset = xkb->map->num_syms; 487706f2543Smrg xkb->map->num_syms+= needed; 488706f2543Smrg return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; 489706f2543Smrg } 490706f2543Smrg xkb->map->size_syms+= (needed>32?needed:32); 491706f2543Smrg newSyms = calloc(xkb->map->size_syms, sizeof(KeySym)); 492706f2543Smrg if (newSyms==NULL) 493706f2543Smrg return NULL; 494706f2543Smrg newSyms[0]= NoSymbol; 495706f2543Smrg nSyms = 1; 496706f2543Smrg for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { 497706f2543Smrg int nCopy; 498706f2543Smrg 499706f2543Smrg nCopy= nKeySyms= XkbKeyNumSyms(xkb,i); 500706f2543Smrg if ((nKeySyms==0)&&(i!=key)) 501706f2543Smrg continue; 502706f2543Smrg if (i==key) 503706f2543Smrg nKeySyms= needed; 504706f2543Smrg if (nCopy!=0) 505706f2543Smrg memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym)); 506706f2543Smrg if (nKeySyms>nCopy) 507706f2543Smrg memset(&newSyms[nSyms+nCopy], 0, (nKeySyms-nCopy)*sizeof(KeySym)); 508706f2543Smrg xkb->map->key_sym_map[i].offset = nSyms; 509706f2543Smrg nSyms+= nKeySyms; 510706f2543Smrg } 511706f2543Smrg free(xkb->map->syms); 512706f2543Smrg xkb->map->syms = newSyms; 513706f2543Smrg xkb->map->num_syms = nSyms; 514706f2543Smrg return &xkb->map->syms[xkb->map->key_sym_map[key].offset]; 515706f2543Smrg} 516706f2543Smrg 517706f2543Smrgstatic unsigned 518706f2543Smrg_ExtendRange( unsigned int old_flags, 519706f2543Smrg unsigned int flag, 520706f2543Smrg KeyCode newKC, 521706f2543Smrg KeyCode * old_min, 522706f2543Smrg unsigned char * old_num) 523706f2543Smrg{ 524706f2543Smrg if ((old_flags&flag)==0) { 525706f2543Smrg old_flags|= flag; 526706f2543Smrg *old_min= newKC; 527706f2543Smrg *old_num= 1; 528706f2543Smrg } 529706f2543Smrg else { 530706f2543Smrg int last= (*old_min)+(*old_num)-1; 531706f2543Smrg if (newKC<*old_min) { 532706f2543Smrg *old_min= newKC; 533706f2543Smrg *old_num= (last-newKC)+1; 534706f2543Smrg } 535706f2543Smrg else if (newKC>last) { 536706f2543Smrg *old_num= (newKC-(*old_min))+1; 537706f2543Smrg } 538706f2543Smrg } 539706f2543Smrg return old_flags; 540706f2543Smrg} 541706f2543Smrg 542706f2543SmrgStatus 543706f2543SmrgXkbChangeKeycodeRange( XkbDescPtr xkb, 544706f2543Smrg int minKC, 545706f2543Smrg int maxKC, 546706f2543Smrg XkbChangesPtr changes) 547706f2543Smrg{ 548706f2543Smrgint tmp; 549706f2543Smrg 550706f2543Smrg if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode)) 551706f2543Smrg return BadValue; 552706f2543Smrg if (minKC>maxKC) 553706f2543Smrg return BadMatch; 554706f2543Smrg if (minKC<xkb->min_key_code) { 555706f2543Smrg if (changes) 556706f2543Smrg changes->map.min_key_code= minKC; 557706f2543Smrg tmp= xkb->min_key_code-minKC; 558706f2543Smrg if (xkb->map) { 559706f2543Smrg if (xkb->map->key_sym_map) { 560706f2543Smrg memset((char *)&xkb->map->key_sym_map[minKC], 0, 561706f2543Smrg tmp*sizeof(XkbSymMapRec)); 562706f2543Smrg if (changes) { 563706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 564706f2543Smrg XkbKeySymsMask,minKC, 565706f2543Smrg &changes->map.first_key_sym, 566706f2543Smrg &changes->map.num_key_syms); 567706f2543Smrg } 568706f2543Smrg } 569706f2543Smrg if (xkb->map->modmap) { 570706f2543Smrg memset((char *)&xkb->map->modmap[minKC], 0, tmp); 571706f2543Smrg if (changes) { 572706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 573706f2543Smrg XkbModifierMapMask,minKC, 574706f2543Smrg &changes->map.first_modmap_key, 575706f2543Smrg &changes->map.num_modmap_keys); 576706f2543Smrg } 577706f2543Smrg } 578706f2543Smrg } 579706f2543Smrg if (xkb->server) { 580706f2543Smrg if (xkb->server->behaviors) { 581706f2543Smrg memset((char *)&xkb->server->behaviors[minKC], 0, 582706f2543Smrg tmp*sizeof(XkbBehavior)); 583706f2543Smrg if (changes) { 584706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 585706f2543Smrg XkbKeyBehaviorsMask,minKC, 586706f2543Smrg &changes->map.first_key_behavior, 587706f2543Smrg &changes->map.num_key_behaviors); 588706f2543Smrg } 589706f2543Smrg } 590706f2543Smrg if (xkb->server->key_acts) { 591706f2543Smrg memset((char *)&xkb->server->key_acts[minKC], 0, 592706f2543Smrg tmp*sizeof(unsigned short)); 593706f2543Smrg if (changes) { 594706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 595706f2543Smrg XkbKeyActionsMask,minKC, 596706f2543Smrg &changes->map.first_key_act, 597706f2543Smrg &changes->map.num_key_acts); 598706f2543Smrg } 599706f2543Smrg } 600706f2543Smrg if (xkb->server->vmodmap) { 601706f2543Smrg memset((char *)&xkb->server->vmodmap[minKC], 0, 602706f2543Smrg tmp*sizeof(unsigned short)); 603706f2543Smrg if (changes) { 604706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 605706f2543Smrg XkbVirtualModMapMask,minKC, 606706f2543Smrg &changes->map.first_modmap_key, 607706f2543Smrg &changes->map.num_vmodmap_keys); 608706f2543Smrg } 609706f2543Smrg } 610706f2543Smrg } 611706f2543Smrg if ((xkb->names)&&(xkb->names->keys)) { 612706f2543Smrg memset((char *)&xkb->names->keys[minKC], 0, tmp*sizeof(XkbKeyNameRec)); 613706f2543Smrg if (changes) { 614706f2543Smrg changes->names.changed= _ExtendRange(changes->names.changed, 615706f2543Smrg XkbKeyNamesMask,minKC, 616706f2543Smrg &changes->names.first_key, 617706f2543Smrg &changes->names.num_keys); 618706f2543Smrg } 619706f2543Smrg } 620706f2543Smrg xkb->min_key_code= minKC; 621706f2543Smrg } 622706f2543Smrg if (maxKC>xkb->max_key_code) { 623706f2543Smrg if (changes) 624706f2543Smrg changes->map.max_key_code= maxKC; 625706f2543Smrg tmp= maxKC-xkb->max_key_code; 626706f2543Smrg if (xkb->map) { 627706f2543Smrg if (xkb->map->key_sym_map) { 628706f2543Smrg XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map; 629706f2543Smrg 630706f2543Smrg xkb->map->key_sym_map = realloc(xkb->map->key_sym_map, 631706f2543Smrg (maxKC+1) * sizeof(XkbSymMapRec)); 632706f2543Smrg if (!xkb->map->key_sym_map) { 633706f2543Smrg free(prev_key_sym_map); 634706f2543Smrg return BadAlloc; 635706f2543Smrg } 636706f2543Smrg memset((char *)&xkb->map->key_sym_map[xkb->max_key_code], 0, 637706f2543Smrg tmp*sizeof(XkbSymMapRec)); 638706f2543Smrg if (changes) { 639706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 640706f2543Smrg XkbKeySymsMask,maxKC, 641706f2543Smrg &changes->map.first_key_sym, 642706f2543Smrg &changes->map.num_key_syms); 643706f2543Smrg } 644706f2543Smrg } 645706f2543Smrg if (xkb->map->modmap) { 646706f2543Smrg unsigned char *prev_modmap = xkb->map->modmap; 647706f2543Smrg 648706f2543Smrg xkb->map->modmap = realloc(xkb->map->modmap, 649706f2543Smrg (maxKC+1) * sizeof(unsigned char)); 650706f2543Smrg if (!xkb->map->modmap) { 651706f2543Smrg free(prev_modmap); 652706f2543Smrg return BadAlloc; 653706f2543Smrg } 654706f2543Smrg memset((char *)&xkb->map->modmap[xkb->max_key_code], 0, tmp); 655706f2543Smrg if (changes) { 656706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 657706f2543Smrg XkbModifierMapMask,maxKC, 658706f2543Smrg &changes->map.first_modmap_key, 659706f2543Smrg &changes->map.num_modmap_keys); 660706f2543Smrg } 661706f2543Smrg } 662706f2543Smrg } 663706f2543Smrg if (xkb->server) { 664706f2543Smrg if (xkb->server->behaviors) { 665706f2543Smrg XkbBehavior *prev_behaviors = xkb->server->behaviors; 666706f2543Smrg 667706f2543Smrg xkb->server->behaviors = realloc(xkb->server->behaviors, 668706f2543Smrg (maxKC+1) * sizeof(XkbBehavior)); 669706f2543Smrg if (!xkb->server->behaviors) { 670706f2543Smrg free(prev_behaviors); 671706f2543Smrg return BadAlloc; 672706f2543Smrg } 673706f2543Smrg memset((char *)&xkb->server->behaviors[xkb->max_key_code], 0, 674706f2543Smrg tmp*sizeof(XkbBehavior)); 675706f2543Smrg if (changes) { 676706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 677706f2543Smrg XkbKeyBehaviorsMask,maxKC, 678706f2543Smrg &changes->map.first_key_behavior, 679706f2543Smrg &changes->map.num_key_behaviors); 680706f2543Smrg } 681706f2543Smrg } 682706f2543Smrg if (xkb->server->key_acts) { 683706f2543Smrg unsigned short *prev_key_acts = xkb->server->key_acts; 684706f2543Smrg 685706f2543Smrg xkb->server->key_acts= realloc(xkb->server->key_acts, 686706f2543Smrg (maxKC+1) * sizeof(unsigned short)); 687706f2543Smrg if (!xkb->server->key_acts) { 688706f2543Smrg free(prev_key_acts); 689706f2543Smrg return BadAlloc; 690706f2543Smrg } 691706f2543Smrg memset((char *)&xkb->server->key_acts[xkb->max_key_code], 0, 692706f2543Smrg tmp*sizeof(unsigned short)); 693706f2543Smrg if (changes) { 694706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 695706f2543Smrg XkbKeyActionsMask,maxKC, 696706f2543Smrg &changes->map.first_key_act, 697706f2543Smrg &changes->map.num_key_acts); 698706f2543Smrg } 699706f2543Smrg } 700706f2543Smrg if (xkb->server->vmodmap) { 701706f2543Smrg unsigned short *prev_vmodmap = xkb->server->vmodmap; 702706f2543Smrg 703706f2543Smrg xkb->server->vmodmap= realloc(xkb->server->vmodmap, 704706f2543Smrg (maxKC+1) * sizeof(unsigned short)); 705706f2543Smrg if (!xkb->server->vmodmap) { 706706f2543Smrg free(prev_vmodmap); 707706f2543Smrg return BadAlloc; 708706f2543Smrg } 709706f2543Smrg memset((char *)&xkb->server->vmodmap[xkb->max_key_code], 0, 710706f2543Smrg tmp*sizeof(unsigned short)); 711706f2543Smrg if (changes) { 712706f2543Smrg changes->map.changed= _ExtendRange(changes->map.changed, 713706f2543Smrg XkbVirtualModMapMask,maxKC, 714706f2543Smrg &changes->map.first_modmap_key, 715706f2543Smrg &changes->map.num_vmodmap_keys); 716706f2543Smrg } 717706f2543Smrg } 718706f2543Smrg } 719706f2543Smrg if ((xkb->names)&&(xkb->names->keys)) { 720706f2543Smrg XkbKeyNameRec *prev_keys = xkb->names->keys; 721706f2543Smrg 722706f2543Smrg xkb->names->keys = realloc(xkb->names->keys, 723706f2543Smrg (maxKC+1) * sizeof(XkbKeyNameRec)); 724706f2543Smrg if (!xkb->names->keys) { 725706f2543Smrg free(prev_keys); 726706f2543Smrg return BadAlloc; 727706f2543Smrg } 728706f2543Smrg memset((char *)&xkb->names->keys[xkb->max_key_code], 0, 729706f2543Smrg tmp*sizeof(XkbKeyNameRec)); 730706f2543Smrg if (changes) { 731706f2543Smrg changes->names.changed= _ExtendRange(changes->names.changed, 732706f2543Smrg XkbKeyNamesMask,maxKC, 733706f2543Smrg &changes->names.first_key, 734706f2543Smrg &changes->names.num_keys); 735706f2543Smrg } 736706f2543Smrg } 737706f2543Smrg xkb->max_key_code= maxKC; 738706f2543Smrg } 739706f2543Smrg return Success; 740706f2543Smrg} 741706f2543Smrg 742706f2543SmrgXkbAction * 743706f2543SmrgXkbResizeKeyActions(XkbDescPtr xkb,int key,int needed) 744706f2543Smrg{ 745706f2543Smrgregister int i,nActs; 746706f2543SmrgXkbAction *newActs; 747706f2543Smrg 748706f2543Smrg if (needed==0) { 749706f2543Smrg xkb->server->key_acts[key]= 0; 750706f2543Smrg return NULL; 751706f2543Smrg } 752706f2543Smrg if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed)) 753706f2543Smrg return XkbKeyActionsPtr(xkb,key); 754706f2543Smrg if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) { 755706f2543Smrg xkb->server->key_acts[key]= xkb->server->num_acts; 756706f2543Smrg xkb->server->num_acts+= needed; 757706f2543Smrg return &xkb->server->acts[xkb->server->key_acts[key]]; 758706f2543Smrg } 759706f2543Smrg xkb->server->size_acts= xkb->server->num_acts+needed+8; 760706f2543Smrg newActs = calloc(xkb->server->size_acts, sizeof(XkbAction)); 761706f2543Smrg if (newActs==NULL) 762706f2543Smrg return NULL; 763706f2543Smrg newActs[0].type = XkbSA_NoAction; 764706f2543Smrg nActs = 1; 765706f2543Smrg for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) { 766706f2543Smrg int nKeyActs,nCopy; 767706f2543Smrg 768706f2543Smrg if ((xkb->server->key_acts[i]==0)&&(i!=key)) 769706f2543Smrg continue; 770706f2543Smrg 771706f2543Smrg nCopy= nKeyActs= XkbKeyNumActions(xkb,i); 772706f2543Smrg if (i==key) { 773706f2543Smrg nKeyActs= needed; 774706f2543Smrg if (needed<nCopy) 775706f2543Smrg nCopy= needed; 776706f2543Smrg } 777706f2543Smrg 778706f2543Smrg if (nCopy>0) 779706f2543Smrg memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i), 780706f2543Smrg nCopy*sizeof(XkbAction)); 781706f2543Smrg if (nCopy<nKeyActs) 782706f2543Smrg memset(&newActs[nActs+nCopy], 0, (nKeyActs-nCopy)*sizeof(XkbAction)); 783706f2543Smrg xkb->server->key_acts[i]= nActs; 784706f2543Smrg nActs+= nKeyActs; 785706f2543Smrg } 786706f2543Smrg free(xkb->server->acts); 787706f2543Smrg xkb->server->acts = newActs; 788706f2543Smrg xkb->server->num_acts= nActs; 789706f2543Smrg return &xkb->server->acts[xkb->server->key_acts[key]]; 790706f2543Smrg} 791706f2543Smrg 792706f2543Smrgvoid 793706f2543SmrgXkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap) 794706f2543Smrg{ 795706f2543SmrgXkbClientMapPtr map; 796706f2543Smrg 797706f2543Smrg if ((xkb==NULL)||(xkb->map==NULL)) 798706f2543Smrg return; 799706f2543Smrg if (freeMap) 800706f2543Smrg what= XkbAllClientInfoMask; 801706f2543Smrg map= xkb->map; 802706f2543Smrg if (what&XkbKeyTypesMask) { 803706f2543Smrg if (map->types!=NULL) { 804706f2543Smrg if (map->num_types>0) { 805706f2543Smrg register int i; 806706f2543Smrg XkbKeyTypePtr type; 807706f2543Smrg for (i=0,type=map->types;i<map->num_types;i++,type++) { 808706f2543Smrg free(type->map); 809706f2543Smrg type->map = NULL; 810706f2543Smrg free(type->preserve); 811706f2543Smrg type->preserve = NULL; 812706f2543Smrg type->map_count= 0; 813706f2543Smrg free(type->level_names); 814706f2543Smrg type->level_names = NULL; 815706f2543Smrg } 816706f2543Smrg } 817706f2543Smrg free(map->types); 818706f2543Smrg map->num_types= map->size_types= 0; 819706f2543Smrg map->types= NULL; 820706f2543Smrg } 821706f2543Smrg } 822706f2543Smrg if (what&XkbKeySymsMask) { 823706f2543Smrg free(map->key_sym_map); 824706f2543Smrg map->key_sym_map = NULL; 825706f2543Smrg if (map->syms!=NULL) { 826706f2543Smrg free(map->syms); 827706f2543Smrg map->size_syms= map->num_syms= 0; 828706f2543Smrg map->syms= NULL; 829706f2543Smrg } 830706f2543Smrg } 831706f2543Smrg if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) { 832706f2543Smrg free(map->modmap); 833706f2543Smrg map->modmap= NULL; 834706f2543Smrg } 835706f2543Smrg if (freeMap) { 836706f2543Smrg free(xkb->map); 837706f2543Smrg xkb->map= NULL; 838706f2543Smrg } 839706f2543Smrg return; 840706f2543Smrg} 841706f2543Smrg 842706f2543Smrgvoid 843706f2543SmrgXkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap) 844706f2543Smrg{ 845706f2543SmrgXkbServerMapPtr map; 846706f2543Smrg 847706f2543Smrg if ((xkb==NULL)||(xkb->server==NULL)) 848706f2543Smrg return; 849706f2543Smrg if (freeMap) 850706f2543Smrg what= XkbAllServerInfoMask; 851706f2543Smrg map= xkb->server; 852706f2543Smrg if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) { 853706f2543Smrg free(map->explicit); 854706f2543Smrg map->explicit= NULL; 855706f2543Smrg } 856706f2543Smrg if (what&XkbKeyActionsMask) { 857706f2543Smrg free(map->key_acts); 858706f2543Smrg map->key_acts = NULL; 859706f2543Smrg if (map->acts!=NULL) { 860706f2543Smrg free(map->acts); 861706f2543Smrg map->num_acts= map->size_acts= 0; 862706f2543Smrg map->acts= NULL; 863706f2543Smrg } 864706f2543Smrg } 865706f2543Smrg if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) { 866706f2543Smrg free(map->behaviors); 867706f2543Smrg map->behaviors= NULL; 868706f2543Smrg } 869706f2543Smrg if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) { 870706f2543Smrg free(map->vmodmap); 871706f2543Smrg map->vmodmap= NULL; 872706f2543Smrg } 873706f2543Smrg 874706f2543Smrg if (freeMap) { 875706f2543Smrg free(xkb->server); 876706f2543Smrg xkb->server= NULL; 877706f2543Smrg } 878706f2543Smrg return; 879706f2543Smrg} 880