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