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