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