Remove KcCGST names from the map
[platform/upstream/libxkbcommon.git] / src / xkbcomp / indicators.c
1 /************************************************************
2  Copyright (c) 1994 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 #include "xkbcomp.h"
28 #include "xkballoc.h"
29 #include "xkbmisc.h"
30 #include "misc.h"
31 #include "expr.h"
32 #include "vmod.h"
33 #include "indicators.h"
34 #include "action.h"
35
36 /***====================================================================***/
37
38 #define ReportIndicatorBadType(l, f, w) \
39     ReportBadType("indicator map", (f), XkbcAtomText((l)->name), (w))
40 #define ReportIndicatorNotArray(l, f) \
41     ReportNotArray("indicator map", (f), XkbcAtomText((l)->name))
42
43 /***====================================================================***/
44
45 void
46 ClearIndicatorMapInfo(LEDInfo * info)
47 {
48     info->name = xkb_intern_atom("default");
49     info->indicator = _LED_NotBound;
50     info->flags = info->which_mods = info->real_mods = 0;
51     info->vmods = 0;
52     info->which_groups = info->groups = 0;
53     info->ctrls = 0;
54 }
55
56 LEDInfo *
57 AddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new)
58 {
59     LEDInfo *old, *last;
60     unsigned collide;
61
62     last = NULL;
63     for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
64     {
65         if (old->name == new->name)
66         {
67             if ((old->real_mods == new->real_mods) &&
68                 (old->vmods == new->vmods) &&
69                 (old->groups == new->groups) &&
70                 (old->ctrls == new->ctrls) &&
71                 (old->which_mods == new->which_mods) &&
72                 (old->which_groups == new->which_groups))
73             {
74                 old->defs.defined |= new->defs.defined;
75                 return oldLEDs;
76             }
77             if (new->defs.merge == MergeReplace)
78             {
79                 CommonInfo *next = old->defs.next;
80                 if (((old->defs.fileID == new->defs.fileID)
81                      && (warningLevel > 0)) || (warningLevel > 9))
82                 {
83                     WARN("Map for indicator %s redefined\n",
84                           XkbcAtomText(old->name));
85                     ACTION("Earlier definition ignored\n");
86                 }
87                 *old = *new;
88                 old->defs.next = next;
89                 return oldLEDs;
90             }
91             collide = 0;
92             if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
93             {
94                 old->indicator = new->indicator;
95                 old->defs.defined |= _LED_Index;
96             }
97             if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
98             {
99                 old->which_mods = new->which_mods;
100                 old->real_mods = new->real_mods;
101                 old->vmods = new->vmods;
102                 old->defs.defined |= _LED_Mods;
103             }
104             if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
105             {
106                 old->which_groups = new->which_groups;
107                 old->groups = new->groups;
108                 old->defs.defined |= _LED_Groups;
109             }
110             if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
111             {
112                 old->ctrls = new->ctrls;
113                 old->defs.defined |= _LED_Ctrls;
114             }
115             if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
116             {
117                 old->flags &= ~XkbIM_NoExplicit;
118                 old->flags |= (new->flags & XkbIM_NoExplicit);
119                 old->defs.defined |= _LED_Explicit;
120             }
121             if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
122             {
123                 old->flags &= ~XkbIM_NoAutomatic;
124                 old->flags |= (new->flags & XkbIM_NoAutomatic);
125                 old->defs.defined |= _LED_Automatic;
126             }
127             if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
128             {
129                 old->flags &= ~XkbIM_LEDDrivesKB;
130                 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
131                 old->defs.defined |= _LED_DrivesKbd;
132             }
133             if (collide)
134             {
135                 WARN("Map for indicator %s redefined\n",
136                       XkbcAtomText(old->name));
137                 ACTION("Using %s definition for duplicate fields\n",
138                         (new->defs.merge == MergeAugment ? "first" : "last"));
139             }
140             return oldLEDs;
141         }
142         if (old->defs.next == NULL)
143             last = old;
144     }
145     /* new definition */
146     old = uTypedAlloc(LEDInfo);
147     if (!old)
148     {
149         WSGO("Couldn't allocate indicator map\n");
150         ACTION("Map for indicator %s not compiled\n",
151                 XkbcAtomText(new->name));
152         return NULL;
153     }
154     *old = *new;
155     old->defs.next = NULL;
156     if (last)
157     {
158         last->defs.next = &old->defs;
159         return oldLEDs;
160     }
161     return old;
162 }
163
164 static const LookupEntry modComponentNames[] = {
165     {"base", XkbIM_UseBase},
166     {"latched", XkbIM_UseLatched},
167     {"locked", XkbIM_UseLocked},
168     {"effective", XkbIM_UseEffective},
169     {"compat", XkbIM_UseCompat},
170     {"any", XkbIM_UseAnyMods},
171     {"none", 0},
172     {NULL, 0}
173 };
174 static const LookupEntry groupComponentNames[] = {
175     {"base", XkbIM_UseBase},
176     {"latched", XkbIM_UseLatched},
177     {"locked", XkbIM_UseLocked},
178     {"effective", XkbIM_UseEffective},
179     {"any", XkbIM_UseAnyGroup},
180     {"none", 0},
181     {NULL, 0}
182 };
183
184 static const LookupEntry groupNames[] = {
185     {"group1", 0x01},
186     {"group2", 0x02},
187     {"group3", 0x04},
188     {"group4", 0x08},
189     {"group5", 0x10},
190     {"group6", 0x20},
191     {"group7", 0x40},
192     {"group8", 0x80},
193     {"none", 0x00},
194     {"all", 0xff},
195     {NULL, 0}
196 };
197
198 int
199 SetIndicatorMapField(LEDInfo * led,
200                      struct xkb_desc * xkb,
201                      char *field, ExprDef * arrayNdx, ExprDef * value)
202 {
203     ExprResult rtrn;
204     Bool ok;
205
206     ok = True;
207     if ((uStrCaseCmp(field, "modifiers") == 0)
208         || (uStrCaseCmp(field, "mods") == 0))
209     {
210         if (arrayNdx != NULL)
211             return ReportIndicatorNotArray(led, field);
212         if (!ExprResolveVModMask(value, &rtrn, xkb))
213             return ReportIndicatorBadType(led, field, "modifier mask");
214         led->real_mods = rtrn.uval & 0xff;
215         led->vmods = (rtrn.uval >> 8) & 0xff;
216         led->defs.defined |= _LED_Mods;
217     }
218     else if (uStrCaseCmp(field, "groups") == 0)
219     {
220         if (arrayNdx != NULL)
221             return ReportIndicatorNotArray(led, field);
222         if (!ExprResolveMask(value, &rtrn, groupNames))
223             return ReportIndicatorBadType(led, field, "group mask");
224         led->groups = rtrn.uval;
225         led->defs.defined |= _LED_Groups;
226     }
227     else if ((uStrCaseCmp(field, "controls") == 0) ||
228              (uStrCaseCmp(field, "ctrls") == 0))
229     {
230         if (arrayNdx != NULL)
231             return ReportIndicatorNotArray(led, field);
232         if (!ExprResolveMask(value, &rtrn, ctrlNames))
233             return ReportIndicatorBadType(led, field,
234                                           "controls mask");
235         led->ctrls = rtrn.uval;
236         led->defs.defined |= _LED_Ctrls;
237     }
238     else if (uStrCaseCmp(field, "allowexplicit") == 0)
239     {
240         if (arrayNdx != NULL)
241             return ReportIndicatorNotArray(led, field);
242         if (!ExprResolveBoolean(value, &rtrn))
243             return ReportIndicatorBadType(led, field, "boolean");
244         if (rtrn.uval)
245             led->flags &= ~XkbIM_NoExplicit;
246         else
247             led->flags |= XkbIM_NoExplicit;
248         led->defs.defined |= _LED_Explicit;
249     }
250     else if ((uStrCaseCmp(field, "whichmodstate") == 0) ||
251              (uStrCaseCmp(field, "whichmodifierstate") == 0))
252     {
253         if (arrayNdx != NULL)
254             return ReportIndicatorNotArray(led, field);
255         if (!ExprResolveMask(value, &rtrn, modComponentNames))
256         {
257             return ReportIndicatorBadType(led, field,
258                                           "mask of modifier state components");
259         }
260         led->which_mods = rtrn.uval;
261     }
262     else if (uStrCaseCmp(field, "whichgroupstate") == 0)
263     {
264         if (arrayNdx != NULL)
265             return ReportIndicatorNotArray(led, field);
266         if (!ExprResolveMask(value, &rtrn, groupComponentNames))
267         {
268             return ReportIndicatorBadType(led, field,
269                                           "mask of group state components");
270         }
271         led->which_groups = rtrn.uval;
272     }
273     else if ((uStrCaseCmp(field, "driveskbd") == 0) ||
274              (uStrCaseCmp(field, "driveskeyboard") == 0) ||
275              (uStrCaseCmp(field, "leddriveskbd") == 0) ||
276              (uStrCaseCmp(field, "leddriveskeyboard") == 0) ||
277              (uStrCaseCmp(field, "indicatordriveskbd") == 0) ||
278              (uStrCaseCmp(field, "indicatordriveskeyboard") == 0))
279     {
280         if (arrayNdx != NULL)
281             return ReportIndicatorNotArray(led, field);
282         if (!ExprResolveBoolean(value, &rtrn))
283             return ReportIndicatorBadType(led, field, "boolean");
284         if (rtrn.uval)
285             led->flags |= XkbIM_LEDDrivesKB;
286         else
287             led->flags &= ~XkbIM_LEDDrivesKB;
288         led->defs.defined |= _LED_DrivesKbd;
289     }
290     else if (uStrCaseCmp(field, "index") == 0)
291     {
292         if (arrayNdx != NULL)
293             return ReportIndicatorNotArray(led, field);
294         if (!ExprResolveInteger(value, &rtrn))
295             return ReportIndicatorBadType(led, field,
296                                           "indicator index");
297         if ((rtrn.uval < 1) || (rtrn.uval > 32))
298         {
299             ERROR("Illegal indicator index %d (range 1..%d)\n",
300                    rtrn.uval, XkbNumIndicators);
301             ACTION("Index definition for %s indicator ignored\n",
302                     XkbcAtomText(led->name));
303             return False;
304         }
305         led->indicator = rtrn.uval;
306         led->defs.defined |= _LED_Index;
307     }
308     else
309     {
310         ERROR("Unknown field %s in map for %s indicator\n", field,
311                XkbcAtomText(led->name));
312         ACTION("Definition ignored\n");
313         ok = False;
314     }
315     return ok;
316 }
317
318 LEDInfo *
319 HandleIndicatorMapDef(IndicatorMapDef * def,
320                       struct xkb_desc * xkb,
321                       LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge)
322 {
323     LEDInfo led, *rtrn;
324     VarDef *var;
325     Bool ok;
326
327     if (def->merge != MergeDefault)
328         merge = def->merge;
329
330     led = *dflt;
331     led.defs.merge = merge;
332     led.name = def->name;
333
334     ok = True;
335     for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
336     {
337         ExprResult elem, field;
338         ExprDef *arrayNdx;
339         if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
340         {
341             ok = False;
342             continue;
343         }
344         if (elem.str != NULL)
345         {
346             ERROR
347                 ("Cannot set defaults for \"%s\" element in indicator map\n",
348                  elem.str);
349             ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
350             ok = False;
351         }
352         else
353         {
354             ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
355                                       var->value) && ok;
356         }
357         free(elem.str);
358         free(field.str);
359     }
360     if (ok)
361     {
362         rtrn = AddIndicatorMap(oldLEDs, &led);
363         return rtrn;
364     }
365     return NULL;
366 }
367
368 Bool
369 CopyIndicatorMapDefs(struct xkb_desc * xkb, LEDInfo *leds, LEDInfo **unboundRtrn)
370 {
371     LEDInfo *led, *next;
372     LEDInfo *unbound, *last;
373
374     if (XkbcAllocNames(xkb, XkbIndicatorNamesMask, 0) != Success)
375     {
376         WSGO("Couldn't allocate names\n");
377         ACTION("Indicator names may be incorrect\n");
378     }
379     if (XkbcAllocIndicatorMaps(xkb) != Success)
380     {
381         WSGO("Can't allocate indicator maps\n");
382         ACTION("Indicator map definitions may be lost\n");
383         return False;
384     }
385     last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
386     while ((last != NULL) && (last->defs.next != NULL))
387     {
388         last = (LEDInfo *) last->defs.next;
389     }
390     for (led = leds; led != NULL; led = next)
391     {
392         next = (LEDInfo *) led->defs.next;
393         if ((led->groups != 0) && (led->which_groups == 0))
394             led->which_groups = XkbIM_UseEffective;
395         if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
396             led->which_mods = XkbIM_UseEffective;
397         if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
398         {
399             if (unboundRtrn != NULL)
400             {
401                 led->defs.next = NULL;
402                 if (last != NULL)
403                     last->defs.next = (CommonInfo *) led;
404                 else
405                     unbound = led;
406                 last = led;
407             }
408             else
409                 free(led);
410         }
411         else
412         {
413             struct xkb_indicator_map * im;
414             im = &xkb->indicators->maps[led->indicator - 1];
415             im->flags = led->flags;
416             im->which_groups = led->which_groups;
417             im->groups = led->groups;
418             im->which_mods = led->which_mods;
419             im->mods.mask = led->real_mods;
420             im->mods.real_mods = led->real_mods;
421             im->mods.vmods = led->vmods;
422             im->ctrls = led->ctrls;
423             if (xkb->names != NULL)
424                 xkb->names->indicators[led->indicator - 1] = led->name;
425             free(led);
426         }
427     }
428     if (unboundRtrn != NULL)
429     {
430         *unboundRtrn = unbound;
431     }
432     return True;
433 }
434
435 Bool
436 BindIndicators(struct xkb_desc * xkb, Bool force, LEDInfo *unbound,
437                LEDInfo **unboundRtrn)
438 {
439     int i;
440     LEDInfo *led, *next, *last;
441
442     if (xkb->names != NULL)
443     {
444         for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
445         {
446             if (led->indicator == _LED_NotBound)
447             {
448                 for (i = 0; i < XkbNumIndicators; i++)
449                 {
450                     if (xkb->names->indicators[i] == led->name)
451                     {
452                         led->indicator = i + 1;
453                         break;
454                     }
455                 }
456             }
457         }
458         if (force)
459         {
460             for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
461             {
462                 if (led->indicator == _LED_NotBound)
463                 {
464                     for (i = 0; i < XkbNumIndicators; i++)
465                     {
466                         if (xkb->names->indicators[i] == None)
467                         {
468                             xkb->names->indicators[i] = led->name;
469                             led->indicator = i + 1;
470                             xkb->indicators->phys_indicators &= ~(1 << i);
471                             break;
472                         }
473                     }
474                     if (led->indicator == _LED_NotBound)
475                     {
476                         ERROR("No unnamed indicators found\n");
477                         ACTION
478                             ("Virtual indicator map \"%s\" not bound\n",
479                              XkbcAtomText(led->name));
480                         continue;
481                     }
482                 }
483             }
484         }
485     }
486     for (last = NULL, led = unbound; led != NULL; led = next)
487     {
488         next = (LEDInfo *) led->defs.next;
489         if (led->indicator == _LED_NotBound)
490         {
491             if (force)
492             {
493                 unbound = next;
494                 free(led);
495             }
496             else
497             {
498                 if (last)
499                     last->defs.next = &led->defs;
500                 else
501                     unbound = led;
502                 last = led;
503             }
504         }
505         else
506         {
507             if ((xkb->names != NULL) &&
508                 (xkb->names->indicators[led->indicator - 1] != led->name))
509             {
510                 uint32_t old = xkb->names->indicators[led->indicator - 1];
511                 ERROR("Multiple names bound to indicator %d\n",
512                        (unsigned int) led->indicator);
513                 ACTION("Using %s, ignoring %s\n",
514                         XkbcAtomText(old),
515                         XkbcAtomText(led->name));
516                 led->indicator = _LED_NotBound;
517                 if (force)
518                 {
519                     free(led);
520                     unbound = next;
521                 }
522                 else
523                 {
524                     if (last)
525                         last->defs.next = &led->defs;
526                     else
527                         unbound = led;
528                     last = led;
529                 }
530             }
531             else
532             {
533                 struct xkb_indicator_map * map;
534                 map = &xkb->indicators->maps[led->indicator - 1];
535                 map->flags = led->flags;
536                 map->which_groups = led->which_groups;
537                 map->groups = led->groups;
538                 map->which_mods = led->which_mods;
539                 map->mods.mask = led->real_mods;
540                 map->mods.real_mods = led->real_mods;
541                 map->mods.vmods = led->vmods;
542                 map->ctrls = led->ctrls;
543                 if (last)
544                     last->defs.next = &next->defs;
545                 else
546                     unbound = next;
547                 led->defs.next = NULL;
548                 free(led);
549             }
550         }
551     }
552     if (unboundRtrn)
553     {
554         *unboundRtrn = unbound;
555     }
556     else
557     {
558         for (led = unbound; led != NULL; led = next)
559         {
560             next = led ? (LEDInfo *) led->defs.next : NULL;
561             free(led);
562         }
563     }
564     return True;
565 }