upload tizen2.0 source
[framework/uifw/xorg/lib/libx11.git] / src / xkb / XKBMAlloc.c
1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #elif defined(HAVE_CONFIG_H)
30 #include <config.h>
31 #endif
32
33 #ifndef XKB_IN_SERVER
34
35 #include <stdio.h>
36 #include "Xlibint.h"
37 #include <X11/extensions/XKBproto.h>
38 #include <X11/keysym.h>
39 #include "XKBlibint.h"
40
41 #else
42
43 #include <stdio.h>
44 #include <X11/X.h>
45 #include <X11/Xproto.h>
46 #include "misc.h"
47 #include "inputstr.h"
48 #include <X11/keysym.h>
49 #define XKBSRV_NEED_FILE_FUNCS
50 #include <X11/extensions/XKBsrv.h>
51
52 #endif /* XKB_IN_SERVER */
53
54 /***====================================================================***/
55
56 Status
57 XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)
58 {
59 register int    i;
60 XkbClientMapPtr map;
61
62     if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
63         return BadValue;
64     if ((which&XkbKeySymsMask)&&
65         ((!XkbIsLegalKeycode(xkb->min_key_code))||
66          (!XkbIsLegalKeycode(xkb->max_key_code))||
67          (xkb->max_key_code<xkb->min_key_code))) {
68 #ifdef DEBUG
69 fprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n",
70                                 xkb->min_key_code,xkb->max_key_code);
71 #endif
72         return BadValue;
73     }
74
75     if (xkb->map==NULL) {
76         map= _XkbTypedCalloc(1,XkbClientMapRec);
77         if (map==NULL)
78             return BadAlloc;
79         xkb->map= map;
80     }
81     else map= xkb->map;
82
83     if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
84         if (map->types==NULL) {
85             map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec);
86             if (map->types==NULL)
87                 return BadAlloc;
88             map->num_types= 0;
89             map->size_types= nTotalTypes;
90         }
91         else if (map->size_types<nTotalTypes) {
92             XkbKeyTypeRec *prev_types = map->types;
93
94             map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec);
95             if (map->types==NULL) {
96                 _XkbFree(prev_types);
97                 map->num_types= map->size_types= 0;
98                 return BadAlloc;
99             }
100             map->size_types= nTotalTypes;
101             bzero(&map->types[map->num_types],
102                   ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
103         }
104     }
105     if (which&XkbKeySymsMask) {
106         int nKeys= XkbNumKeys(xkb);
107         if (map->syms==NULL) {
108             map->size_syms= (nKeys*15)/10;
109             map->syms= _XkbTypedCalloc(map->size_syms,KeySym);
110             if (!map->syms) {
111                 map->size_syms= 0;
112                 return BadAlloc;
113             }
114             map->num_syms= 1;
115             map->syms[0]= NoSymbol;
116         }
117         if (map->key_sym_map==NULL) {
118             i= xkb->max_key_code+1;
119             map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec);
120             if (map->key_sym_map==NULL)
121                 return BadAlloc;
122         }
123     }
124     if (which&XkbModifierMapMask) {
125         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
126             (!XkbIsLegalKeycode(xkb->max_key_code))||
127             (xkb->max_key_code<xkb->min_key_code))
128             return BadMatch;
129         if (map->modmap==NULL) {
130             i= xkb->max_key_code+1;
131             map->modmap= _XkbTypedCalloc(i,unsigned char);
132             if (map->modmap==NULL)
133                 return BadAlloc;
134         }
135     }
136     return Success;
137 }
138
139 Status
140 XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)
141 {
142 register int    i;
143 XkbServerMapPtr map;
144
145     if (xkb==NULL)
146         return BadMatch;
147     if (xkb->server==NULL) {
148         map= _XkbTypedCalloc(1,XkbServerMapRec);
149         if (map==NULL)
150             return BadAlloc;
151         for (i=0;i<XkbNumVirtualMods;i++) {
152             map->vmods[i]= XkbNoModifierMask;
153         }
154         xkb->server= map;
155     }
156     else map= xkb->server;
157     if (which&XkbExplicitComponentsMask) {
158         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
159             (!XkbIsLegalKeycode(xkb->max_key_code))||
160             (xkb->max_key_code<xkb->min_key_code))
161             return BadMatch;
162         if (map->explicit==NULL) {
163             i= xkb->max_key_code+1;
164             map->explicit= _XkbTypedCalloc(i,unsigned char);
165             if (map->explicit==NULL)
166                 return BadAlloc;
167         }
168     }
169     if (which&XkbKeyActionsMask) {
170         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
171             (!XkbIsLegalKeycode(xkb->max_key_code))||
172             (xkb->max_key_code<xkb->min_key_code))
173             return BadMatch;
174         if (nNewActions<1)
175             nNewActions= 1;
176         if (map->acts==NULL) {
177             map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction);
178             if (map->acts==NULL)
179                 return BadAlloc;
180             map->num_acts= 1;
181             map->size_acts= nNewActions+1;
182         }
183         else if ((map->size_acts-map->num_acts)<nNewActions) {
184             unsigned need;
185             XkbAction *prev_acts = map->acts;
186             need= map->num_acts+nNewActions;
187             map->acts= _XkbTypedRealloc(map->acts,need,XkbAction);
188             if (map->acts==NULL) {
189                 _XkbFree(prev_acts);
190                 map->num_acts= map->size_acts= 0;
191                 return BadAlloc;
192             }
193             map->size_acts= need;
194             bzero(&map->acts[map->num_acts],
195                     ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
196         }
197         if (map->key_acts==NULL) {
198             i= xkb->max_key_code+1;
199             map->key_acts= _XkbTypedCalloc(i,unsigned short);
200             if (map->key_acts==NULL)
201                 return BadAlloc;
202         }
203     }
204     if (which&XkbKeyBehaviorsMask) {
205         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
206             (!XkbIsLegalKeycode(xkb->max_key_code))||
207             (xkb->max_key_code<xkb->min_key_code))
208             return BadMatch;
209         if (map->behaviors==NULL) {
210             i= xkb->max_key_code+1;
211             map->behaviors= _XkbTypedCalloc(i,XkbBehavior);
212             if (map->behaviors==NULL)
213                 return BadAlloc;
214         }
215     }
216     if (which&XkbVirtualModMapMask) {
217         if ((!XkbIsLegalKeycode(xkb->min_key_code))||
218             (!XkbIsLegalKeycode(xkb->max_key_code))||
219             (xkb->max_key_code<xkb->min_key_code))
220             return BadMatch;
221         if (map->vmodmap==NULL) {
222             i= xkb->max_key_code+1;
223             map->vmodmap= _XkbTypedCalloc(i,unsigned short);
224             if (map->vmodmap==NULL)
225                 return BadAlloc;
226         }
227     }
228     return Success;
229 }
230
231 /***====================================================================***/
232
233 Status
234 XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)
235 {
236     if ((!from)||(!into))
237         return BadMatch;
238     if (into->map) {
239         _XkbFree(into->map);
240         into->map= NULL;
241     }
242     if (into->preserve) {
243         _XkbFree(into->preserve);
244         into->preserve= NULL;
245     }
246     if (into->level_names) {
247         _XkbFree(into->level_names);
248         into->level_names= NULL;
249     }
250     *into= *from;
251     if ((from->map)&&(into->map_count>0)) {
252         into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec);
253         if (!into->map)
254             return BadAlloc;
255         memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec));
256     }
257     if ((from->preserve)&&(into->map_count>0)) {
258         into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec);
259         if (!into->preserve)
260             return BadAlloc;
261         memcpy(into->preserve,from->preserve,
262                                 into->map_count*sizeof(XkbModsRec));
263     }
264     if ((from->level_names)&&(into->num_levels>0)) {
265         into->level_names= _XkbTypedCalloc(into->num_levels,Atom);
266         if (!into->level_names)
267             return BadAlloc;
268         memcpy(into->level_names,from->level_names,
269                                  into->num_levels*sizeof(Atom));
270     }
271     return Success;
272 }
273
274 Status
275 XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)
276 {
277 register int i,rtrn;
278
279     if ((!from)||(!into)||(num_types<0))
280         return BadMatch;
281     for (i=0;i<num_types;i++) {
282         if ((rtrn= XkbCopyKeyType(from++,into++))!=Success)
283             return rtrn;
284     }
285     return Success;
286 }
287
288 XkbKeyTypePtr
289 XkbAddKeyType(  XkbDescPtr      xkb,
290                 Atom            name,
291                 int             map_count,
292                 Bool            want_preserve,
293                 int             num_lvls)
294 {
295 register int    i;
296 unsigned        tmp;
297 XkbKeyTypePtr   type;
298 XkbClientMapPtr map;
299
300     if ((!xkb)||(num_lvls<1))
301         return NULL;
302     map= xkb->map;
303     if ((map)&&(map->types)) {
304         for (i=0;i<map->num_types;i++) {
305             if (map->types[i].name==name) {
306                 Status status;
307                 status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
308                 return (status==Success?&map->types[i]:NULL);
309             }
310         }
311     }
312     if ((!map)||(!map->types)||(!map->num_types<XkbNumRequiredTypes)) {
313         tmp= XkbNumRequiredTypes+1;
314         if (XkbAllocClientMap(xkb,XkbKeyTypesMask,tmp)!=Success)
315             return NULL;
316         if (!map)
317             map = xkb->map;
318         tmp= 0;
319         if (map->num_types<=XkbKeypadIndex)
320             tmp|= XkbKeypadMask;
321         if (map->num_types<=XkbAlphabeticIndex)
322             tmp|= XkbAlphabeticMask;
323         if (map->num_types<=XkbTwoLevelIndex)
324             tmp|= XkbTwoLevelMask;
325         if (map->num_types<=XkbOneLevelIndex)
326             tmp|= XkbOneLevelMask;
327         if (XkbInitCanonicalKeyTypes(xkb,tmp,XkbNoModifier)==Success) {
328             for (i=0;i<map->num_types;i++) {
329                 Status status;
330                 if (map->types[i].name!=name)
331                     continue;
332                 status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
333                 return (status==Success?&map->types[i]:NULL);
334             }
335         }
336     }
337     if ((map->num_types<=map->size_types)&&
338         (XkbAllocClientMap(xkb,XkbKeyTypesMask,map->num_types+1)!=Success)) {
339         return NULL;
340     }
341     type= &map->types[map->num_types];
342     map->num_types++;
343     bzero((char *)type,sizeof(XkbKeyTypeRec));
344     type->num_levels=   num_lvls;
345     type->map_count=    map_count;
346     type->name=         name;
347     if (map_count>0) {
348         type->map=      _XkbTypedCalloc(map_count,XkbKTMapEntryRec);
349         if (!type->map) {
350             map->num_types--;
351             return NULL;
352         }
353         if (want_preserve) {
354             type->preserve=     _XkbTypedCalloc(map_count,XkbModsRec);
355             if (!type->preserve) {
356                 _XkbFree(type->map);
357                 map->num_types--;
358                 return NULL;
359             }
360         }
361     }
362     return type;
363 }
364
365 Status
366 XkbResizeKeyType(       XkbDescPtr      xkb,
367                         int             type_ndx,
368                         int             map_count,
369                         Bool            want_preserve,
370                         int             new_num_lvls)
371 {
372 XkbKeyTypePtr   type;
373 KeyCode         matchingKeys[XkbMaxKeyCount],nMatchingKeys;
374
375     if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)||
376                                                         (new_num_lvls<1))
377         return BadValue;
378     switch (type_ndx) {
379         case XkbOneLevelIndex:
380             if (new_num_lvls!=1)
381                 return BadMatch;
382             break;
383         case XkbTwoLevelIndex:
384         case XkbAlphabeticIndex:
385         case XkbKeypadIndex:
386             if (new_num_lvls!=2)
387                 return BadMatch;
388             break;
389     }
390     type= &xkb->map->types[type_ndx];
391     if (map_count==0) {
392         if (type->map!=NULL)
393             _XkbFree(type->map);
394         type->map= NULL;
395         if (type->preserve!=NULL)
396             _XkbFree(type->preserve);
397         type->preserve= NULL;
398         type->map_count= 0;
399     }
400     else {
401         XkbKTMapEntryRec *prev_map = type->map;
402
403         if ((map_count>type->map_count)||(type->map==NULL))
404             type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec);
405         if (!type->map) {
406             if (prev_map)
407                 _XkbFree(prev_map);
408             return BadAlloc;
409         }
410         if (want_preserve) {
411             XkbModsRec *prev_preserve = type->preserve;
412
413             if ((map_count>type->map_count)||(type->preserve==NULL)) {
414                 type->preserve= _XkbTypedRealloc(type->preserve,map_count,
415                                                             XkbModsRec);
416             }
417             if (!type->preserve) {
418                 if (prev_preserve)
419                     _XkbFree(prev_preserve);
420                 return BadAlloc;
421             }
422         }
423         else if (type->preserve!=NULL) {
424             _XkbFree(type->preserve);
425             type->preserve= NULL;
426         }
427         type->map_count= map_count;
428     }
429
430     if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) {
431         Atom * prev_level_names = type->level_names;
432
433         type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom);
434         if (!type->level_names) {
435             if (prev_level_names)
436                 _XkbFree(prev_level_names);
437             return BadAlloc;
438         }
439     }
440     /*
441      * Here's the theory:
442      *    If the width of the type changed, we might have to resize the symbol
443      * maps for any keys that use the type for one or more groups.  This is
444      * expensive, so we'll try to cull out any keys that are obviously okay:
445      * In any case:
446      *    - keys that have a group width <= the old width are okay (because
447      *      they could not possibly have been associated with the old type)
448      * If the key type increased in size:
449      *    - keys that already have a group width >= to the new width are okay
450      *    + keys that have a group width >= the old width but < the new width
451      *      might have to be enlarged.
452      * If the key type decreased in size:
453      *    - keys that have a group width > the old width don't have to be
454      *      resized (because they must have some other wider type associated
455      *      with some group).
456      *    + keys that have a group width == the old width might have to be
457      *      shrunk.
458      * The possibilities marked with '+' require us to examine the key types
459      * associated with each group for the key.
460      */
461     bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode));
462     nMatchingKeys= 0;
463     if (new_num_lvls>type->num_levels) {
464         int                     nTotal;
465         KeySym  *               newSyms;
466         int                     width,match,nResize;
467         register int            i,g,nSyms;
468
469         nResize= 0;
470         for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
471             width= XkbKeyGroupsWidth(xkb,i);
472             if (width<type->num_levels)
473                 continue;
474             for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
475                 if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
476                     matchingKeys[nMatchingKeys++]= i;
477                     match= 1;
478                 }
479             }
480             if ((!match)||(width>=new_num_lvls))
481                 nTotal+= XkbKeyNumSyms(xkb,i);
482             else {
483                 nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
484                 nResize++;
485             }
486         }
487         if (nResize>0) {
488             int nextMatch;
489             xkb->map->size_syms= (nTotal*12)/10;
490             newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
491             if (newSyms==NULL)
492                 return BadAlloc;
493             nextMatch= 0;
494             nSyms= 1;
495             for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
496                 if (matchingKeys[nextMatch]==i) {
497                     KeySym *pOld;
498                     nextMatch++;
499                     width= XkbKeyGroupsWidth(xkb,i);
500                     pOld= XkbKeySymsPtr(xkb,i);
501                     for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
502                         memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g],
503                                                         width*sizeof(KeySym));
504                     }
505                     xkb->map->key_sym_map[i].offset= nSyms;
506                     nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
507                 }
508                 else {
509                     memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),
510                                         XkbKeyNumSyms(xkb,i)*sizeof(KeySym));
511                     xkb->map->key_sym_map[i].offset= nSyms;
512                     nSyms+= XkbKeyNumSyms(xkb,i);
513                 }
514             }
515             type->num_levels= new_num_lvls;
516             _XkbFree(xkb->map->syms);
517             xkb->map->syms= newSyms;
518             xkb->map->num_syms= nSyms;
519             return Success;
520         }
521     }
522     else if (new_num_lvls<type->num_levels) {
523         int             width,match;
524         register int    g,i;
525         for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
526             width= XkbKeyGroupsWidth(xkb,i);
527             if (width<type->num_levels)
528                 continue;
529             for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
530                 if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
531                     matchingKeys[nMatchingKeys++]= i;
532                     match= 1;
533                 }
534             }
535         }
536     }
537     if (nMatchingKeys>0) {
538         int             key,firstClear;
539         register int    i,g;
540         if (new_num_lvls>type->num_levels)
541              firstClear= type->num_levels;
542         else firstClear= new_num_lvls;
543         for (i=0;i<nMatchingKeys;i++) {
544             KeySym *    pSyms;
545             int         width,nClear;
546
547             key= matchingKeys[i];
548             width= XkbKeyGroupsWidth(xkb,key);
549             nClear= width-firstClear;
550             pSyms= XkbKeySymsPtr(xkb,key);
551             for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) {
552                 if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) {
553                     if (nClear>0)
554                         bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym));
555                 }
556             }
557         }
558     }
559     type->num_levels= new_num_lvls;
560     return Success;
561 }
562
563 KeySym *
564 XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)
565 {
566 register int i,nSyms,nKeySyms;
567 unsigned nOldSyms;
568 KeySym  *newSyms;
569
570     if (needed==0) {
571         xkb->map->key_sym_map[key].offset= 0;
572         return xkb->map->syms;
573     }
574     nOldSyms= XkbKeyNumSyms(xkb,key);
575     if (nOldSyms>=(unsigned)needed) {
576         return XkbKeySymsPtr(xkb,key);
577     }
578     if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) {
579         if (nOldSyms>0) {
580             memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key),
581                                                 nOldSyms*sizeof(KeySym));
582         }
583         if ((needed-nOldSyms)>0) {
584             bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)],
585                                         (needed-nOldSyms)*sizeof(KeySym));
586         }
587         xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
588         xkb->map->num_syms+= needed;
589         return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
590     }
591     xkb->map->size_syms+= (needed>32?needed:32);
592     newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
593     if (newSyms==NULL)
594         return NULL;
595     newSyms[0]= NoSymbol;
596     nSyms = 1;
597     for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
598         int nCopy;
599
600         nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
601         if ((nKeySyms==0)&&(i!=key))
602             continue;
603         if (i==key)
604             nKeySyms= needed;
605         if (nCopy!=0)
606            memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym));
607         if (nKeySyms>nCopy)
608             bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym));
609         xkb->map->key_sym_map[i].offset = nSyms;
610         nSyms+= nKeySyms;
611     }
612     _XkbFree(xkb->map->syms);
613     xkb->map->syms = newSyms;
614     xkb->map->num_syms = nSyms;
615     return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
616 }
617
618 static unsigned
619 _ExtendRange(   unsigned int    old_flags,
620                 unsigned int    flag,
621                 KeyCode         newKC,
622                 KeyCode *       old_min,
623                 unsigned char * old_num)
624 {
625     if ((old_flags&flag)==0) {
626         old_flags|= flag;
627         *old_min= newKC;
628         *old_num= 1;
629     }
630     else {
631         int     last= (*old_min)+(*old_num)-1;
632         if (newKC<*old_min) {
633             *old_min= newKC;
634             *old_num= (last-newKC)+1;
635         }
636         else if (newKC>last) {
637             *old_num= (newKC-(*old_min))+1;
638         }
639     }
640     return old_flags;
641 }
642
643 Status
644 XkbChangeKeycodeRange(  XkbDescPtr      xkb,
645                         int             minKC,
646                         int             maxKC,
647                         XkbChangesPtr   changes)
648 {
649 int     tmp;
650
651     if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode))
652         return BadValue;
653     if (minKC>maxKC)
654         return BadMatch;
655     if (minKC<xkb->min_key_code) {
656         if (changes)
657             changes->map.min_key_code= minKC;
658         tmp= xkb->min_key_code-minKC;
659         if (xkb->map)  {
660             if (xkb->map->key_sym_map) {
661                 bzero((char *)&xkb->map->key_sym_map[minKC],
662                                         tmp*sizeof(XkbSymMapRec));
663                 if (changes) {
664                     changes->map.changed= _ExtendRange(changes->map.changed,
665                                                 XkbKeySymsMask,minKC,
666                                                 &changes->map.first_key_sym,
667                                                 &changes->map.num_key_syms);
668                 }
669             }
670             if (xkb->map->modmap) {
671                 bzero((char *)&xkb->map->modmap[minKC],tmp);
672                 if (changes) {
673                     changes->map.changed= _ExtendRange(changes->map.changed,
674                                                 XkbModifierMapMask,minKC,
675                                                 &changes->map.first_modmap_key,
676                                                 &changes->map.num_modmap_keys);
677                 }
678             }
679         }
680         if (xkb->server) {
681             if (xkb->server->behaviors) {
682                 bzero((char *)&xkb->server->behaviors[minKC],
683                                                 tmp*sizeof(XkbBehavior));
684                 if (changes) {
685                     changes->map.changed= _ExtendRange(changes->map.changed,
686                                         XkbKeyBehaviorsMask,minKC,
687                                         &changes->map.first_key_behavior,
688                                         &changes->map.num_key_behaviors);
689                 }
690             }
691             if (xkb->server->key_acts) {
692                 bzero((char *)&xkb->server->key_acts[minKC],
693                                                 tmp*sizeof(unsigned short));
694                 if (changes) {
695                     changes->map.changed= _ExtendRange(changes->map.changed,
696                                         XkbKeyActionsMask,minKC,
697                                         &changes->map.first_key_act,
698                                         &changes->map.num_key_acts);
699                 }
700             }
701             if (xkb->server->vmodmap) {
702                 bzero((char *)&xkb->server->vmodmap[minKC],
703                                                 tmp*sizeof(unsigned short));
704                 if (changes) {
705                     changes->map.changed= _ExtendRange(changes->map.changed,
706                                         XkbVirtualModMapMask,minKC,
707                                         &changes->map.first_modmap_key,
708                                         &changes->map.num_vmodmap_keys);
709                 }
710             }
711         }
712         if ((xkb->names)&&(xkb->names->keys)) {
713             bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec));
714             if (changes) {
715                 changes->names.changed= _ExtendRange(changes->names.changed,
716                                         XkbKeyNamesMask,minKC,
717                                         &changes->names.first_key,
718                                         &changes->names.num_keys);
719             }
720         }
721         xkb->min_key_code= minKC;
722     }
723     if (maxKC>xkb->max_key_code) {
724         if (changes)
725             changes->map.max_key_code= maxKC;
726         tmp= maxKC-xkb->max_key_code;
727         if (xkb->map)  {
728             if (xkb->map->key_sym_map) {
729                 XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
730
731                 xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map,
732                                                 (maxKC+1),XkbSymMapRec);
733                 if (!xkb->map->key_sym_map) {
734                     _XkbFree(prev_key_sym_map);
735                     return BadAlloc;
736                 }
737                 bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
738                                         tmp*sizeof(XkbSymMapRec));
739                 if (changes) {
740                     changes->map.changed= _ExtendRange(changes->map.changed,
741                                                 XkbKeySymsMask,maxKC,
742                                                 &changes->map.first_key_sym,
743                                                 &changes->map.num_key_syms);
744                 }
745             }
746             if (xkb->map->modmap) {
747                 unsigned char *prev_modmap = xkb->map->modmap;
748
749                 xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap,
750                                                 (maxKC+1),unsigned char);
751                 if (!xkb->map->modmap) {
752                     _XkbFree(prev_modmap);
753                     return BadAlloc;
754                 }
755                 bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
756                 if (changes) {
757                     changes->map.changed= _ExtendRange(changes->map.changed,
758                                                 XkbModifierMapMask,maxKC,
759                                                 &changes->map.first_modmap_key,
760                                                 &changes->map.num_modmap_keys);
761                 }
762             }
763         }
764         if (xkb->server) {
765             if (xkb->server->behaviors) {
766                 XkbBehavior *prev_behaviors = xkb->server->behaviors;
767
768                 xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors,
769                                                 (maxKC+1),XkbBehavior);
770                 if (!xkb->server->behaviors) {
771                     _XkbFree(prev_behaviors);
772                     return BadAlloc;
773                 }
774                 bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
775                                                 tmp*sizeof(XkbBehavior));
776                 if (changes) {
777                     changes->map.changed= _ExtendRange(changes->map.changed,
778                                         XkbKeyBehaviorsMask,maxKC,
779                                         &changes->map.first_key_behavior,
780                                         &changes->map.num_key_behaviors);
781                 }
782             }
783             if (xkb->server->key_acts) {
784                 unsigned short *prev_key_acts = xkb->server->key_acts;
785
786                 xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts,
787                                                 (maxKC+1),unsigned short);
788                 if (!xkb->server->key_acts) {
789                     _XkbFree(prev_key_acts);
790                     return BadAlloc;
791                 }
792                 bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
793                                                 tmp*sizeof(unsigned short));
794                 if (changes) {
795                     changes->map.changed= _ExtendRange(changes->map.changed,
796                                         XkbKeyActionsMask,maxKC,
797                                         &changes->map.first_key_act,
798                                         &changes->map.num_key_acts);
799                 }
800             }
801             if (xkb->server->vmodmap) {
802                 unsigned short *prev_vmodmap = xkb->server->vmodmap;
803
804                 xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap,
805                                                 (maxKC+1),unsigned short);
806                 if (!xkb->server->vmodmap) {
807                     _XkbFree(prev_vmodmap);
808                     return BadAlloc;
809                 }
810                 bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
811                                                 tmp*sizeof(unsigned short));
812                 if (changes) {
813                     changes->map.changed= _ExtendRange(changes->map.changed,
814                                         XkbVirtualModMapMask,maxKC,
815                                         &changes->map.first_modmap_key,
816                                         &changes->map.num_vmodmap_keys);
817                 }
818             }
819         }
820         if ((xkb->names)&&(xkb->names->keys)) {
821             XkbKeyNameRec *prev_keys = xkb->names->keys;
822
823             xkb->names->keys= _XkbTypedRealloc(xkb->names->keys,
824                                                 (maxKC+1),XkbKeyNameRec);
825             if (!xkb->names->keys) {
826                 _XkbFree(prev_keys);
827                 return BadAlloc;
828             }
829             bzero((char *)&xkb->names->keys[xkb->max_key_code],
830                                                 tmp*sizeof(XkbKeyNameRec));
831             if (changes) {
832                 changes->names.changed= _ExtendRange(changes->names.changed,
833                                         XkbKeyNamesMask,maxKC,
834                                         &changes->names.first_key,
835                                         &changes->names.num_keys);
836             }
837         }
838         xkb->max_key_code= maxKC;
839     }
840     return Success;
841 }
842
843 XkbAction *
844 XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)
845 {
846 register int i,nActs;
847 XkbAction *newActs;
848
849     if (needed==0) {
850         xkb->server->key_acts[key]= 0;
851         return NULL;
852     }
853     if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed))
854         return XkbKeyActionsPtr(xkb,key);
855     if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) {
856         xkb->server->key_acts[key]= xkb->server->num_acts;
857         xkb->server->num_acts+= needed;
858         return &xkb->server->acts[xkb->server->key_acts[key]];
859     }
860     xkb->server->size_acts= xkb->server->num_acts+needed+8;
861     newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction);
862     if (newActs==NULL)
863         return NULL;
864     newActs[0].type = XkbSA_NoAction;
865     nActs = 1;
866     for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
867         int nKeyActs,nCopy;
868
869         if ((xkb->server->key_acts[i]==0)&&(i!=key))
870             continue;
871
872         nCopy= nKeyActs= XkbKeyNumActions(xkb,i);
873         if (i==key) {
874             nKeyActs= needed;
875             if (needed<nCopy)
876                 nCopy= needed;
877         }
878
879         if (nCopy>0)
880             memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i),
881                                                 nCopy*sizeof(XkbAction));
882         if (nCopy<nKeyActs)
883             bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction));
884         xkb->server->key_acts[i]= nActs;
885         nActs+= nKeyActs;
886     }
887     _XkbFree(xkb->server->acts);
888     xkb->server->acts = newActs;
889     xkb->server->num_acts= nActs;
890     return &xkb->server->acts[xkb->server->key_acts[key]];
891 }
892
893 void
894 XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
895 {
896 XkbClientMapPtr map;
897
898     if ((xkb==NULL)||(xkb->map==NULL))
899         return;
900     if (freeMap)
901         what= XkbAllClientInfoMask;
902     map= xkb->map;
903     if (what&XkbKeyTypesMask) {
904         if (map->types!=NULL) {
905             if (map->num_types>0) {
906                 register int    i;
907                 XkbKeyTypePtr   type;
908                 for (i=0,type=map->types;i<map->num_types;i++,type++) {
909                     if (type->map!=NULL) {
910                         _XkbFree(type->map);
911                         type->map= NULL;
912                     }
913                     if (type->preserve!=NULL) {
914                         _XkbFree(type->preserve);
915                         type->preserve= NULL;
916                     }
917                     type->map_count= 0;
918                     if (type->level_names!=NULL) {
919                         _XkbFree(type->level_names);
920                         type->level_names= NULL;
921                     }
922                 }
923             }
924             _XkbFree(map->types);
925             map->num_types= map->size_types= 0;
926             map->types= NULL;
927         }
928     }
929     if (what&XkbKeySymsMask) {
930         if (map->key_sym_map!=NULL) {
931             _XkbFree(map->key_sym_map);
932             map->key_sym_map= NULL;
933         }
934         if (map->syms!=NULL) {
935             _XkbFree(map->syms);
936             map->size_syms= map->num_syms= 0;
937             map->syms= NULL;
938         }
939     }
940     if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
941         _XkbFree(map->modmap);
942         map->modmap= NULL;
943     }
944     if (freeMap) {
945         _XkbFree(xkb->map);
946         xkb->map= NULL;
947     }
948     return;
949 }
950
951 void
952 XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
953 {
954 XkbServerMapPtr map;
955
956     if ((xkb==NULL)||(xkb->server==NULL))
957         return;
958     if (freeMap)
959         what= XkbAllServerInfoMask;
960     map= xkb->server;
961     if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
962         _XkbFree(map->explicit);
963         map->explicit= NULL;
964     }
965     if (what&XkbKeyActionsMask) {
966         if (map->key_acts!=NULL) {
967             _XkbFree(map->key_acts);
968             map->key_acts= NULL;
969         }
970         if (map->acts!=NULL) {
971             _XkbFree(map->acts);
972             map->num_acts= map->size_acts= 0;
973             map->acts= NULL;
974         }
975     }
976     if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
977         _XkbFree(map->behaviors);
978         map->behaviors= NULL;
979     }
980     if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
981         _XkbFree(map->vmodmap);
982         map->vmodmap= NULL;
983     }
984
985     if (freeMap) {
986         _XkbFree(xkb->server);
987         xkb->server= NULL;
988     }
989     return;
990 }