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