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