xkbcomp: Remove duplicated macros
[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 "misc.h"
29 #include "tokens.h"
30 #include "expr.h"
31 #include "vmod.h"
32 #include "indicators.h"
33 #include "action.h"
34 #include "compat.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 = XkbcInternAtom("default", False);
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 int
199 SetIndicatorMapField(LEDInfo * led,
200                      XkbcDescPtr 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 (!ExprResolveModMask(value, &rtrn, LookupVModMask, (char *) 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
223             (value, &rtrn, SimpleLookup, (char *) groupNames))
224             return ReportIndicatorBadType(led, field, "group mask");
225         led->groups = rtrn.uval;
226         led->defs.defined |= _LED_Groups;
227     }
228     else if ((uStrCaseCmp(field, "controls") == 0) ||
229              (uStrCaseCmp(field, "ctrls") == 0))
230     {
231         if (arrayNdx != NULL)
232             return ReportIndicatorNotArray(led, field);
233         if (!ExprResolveMask
234             (value, &rtrn, SimpleLookup, (char *) ctrlNames))
235             return ReportIndicatorBadType(led, field,
236                                           "controls mask");
237         led->ctrls = rtrn.uval;
238         led->defs.defined |= _LED_Ctrls;
239     }
240     else if (uStrCaseCmp(field, "allowexplicit") == 0)
241     {
242         if (arrayNdx != NULL)
243             return ReportIndicatorNotArray(led, field);
244         if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
245             return ReportIndicatorBadType(led, field, "boolean");
246         if (rtrn.uval)
247             led->flags &= ~XkbIM_NoExplicit;
248         else
249             led->flags |= XkbIM_NoExplicit;
250         led->defs.defined |= _LED_Explicit;
251     }
252     else if ((uStrCaseCmp(field, "whichmodstate") == 0) ||
253              (uStrCaseCmp(field, "whichmodifierstate") == 0))
254     {
255         if (arrayNdx != NULL)
256             return ReportIndicatorNotArray(led, field);
257         if (!ExprResolveMask(value, &rtrn, SimpleLookup,
258                              (char *) modComponentNames))
259         {
260             return ReportIndicatorBadType(led, field,
261                                           "mask of modifier state components");
262         }
263         led->which_mods = rtrn.uval;
264     }
265     else if (uStrCaseCmp(field, "whichgroupstate") == 0)
266     {
267         if (arrayNdx != NULL)
268             return ReportIndicatorNotArray(led, field);
269         if (!ExprResolveMask(value, &rtrn, SimpleLookup,
270                              (char *) groupComponentNames))
271         {
272             return ReportIndicatorBadType(led, field,
273                                           "mask of group state components");
274         }
275         led->which_groups = rtrn.uval;
276     }
277     else if ((uStrCaseCmp(field, "driveskbd") == 0) ||
278              (uStrCaseCmp(field, "driveskeyboard") == 0) ||
279              (uStrCaseCmp(field, "leddriveskbd") == 0) ||
280              (uStrCaseCmp(field, "leddriveskeyboard") == 0) ||
281              (uStrCaseCmp(field, "indicatordriveskbd") == 0) ||
282              (uStrCaseCmp(field, "indicatordriveskeyboard") == 0))
283     {
284         if (arrayNdx != NULL)
285             return ReportIndicatorNotArray(led, field);
286         if (!ExprResolveBoolean(value, &rtrn, NULL, NULL))
287             return ReportIndicatorBadType(led, field, "boolean");
288         if (rtrn.uval)
289             led->flags |= XkbIM_LEDDrivesKB;
290         else
291             led->flags &= ~XkbIM_LEDDrivesKB;
292         led->defs.defined |= _LED_DrivesKbd;
293     }
294     else if (uStrCaseCmp(field, "index") == 0)
295     {
296         if (arrayNdx != NULL)
297             return ReportIndicatorNotArray(led, field);
298         if (!ExprResolveInteger(value, &rtrn, NULL, NULL))
299             return ReportIndicatorBadType(led, field,
300                                           "indicator index");
301         if ((rtrn.uval < 1) || (rtrn.uval > 32))
302         {
303             ERROR("Illegal indicator index %d (range 1..%d)\n",
304                    rtrn.uval, XkbNumIndicators);
305             ACTION("Index definition for %s indicator ignored\n",
306                     XkbcAtomText(led->name));
307             return False;
308         }
309         led->indicator = rtrn.uval;
310         led->defs.defined |= _LED_Index;
311     }
312     else
313     {
314         ERROR("Unknown field %s in map for %s indicator\n", field,
315                XkbcAtomText(led->name));
316         ACTION("Definition ignored\n");
317         ok = False;
318     }
319     return ok;
320 }
321
322 LEDInfo *
323 HandleIndicatorMapDef(IndicatorMapDef * def,
324                       XkbcDescPtr xkb,
325                       LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge)
326 {
327     LEDInfo led, *rtrn;
328     VarDef *var;
329     Bool ok;
330
331     if (def->merge != MergeDefault)
332         merge = def->merge;
333
334     led = *dflt;
335     led.defs.merge = merge;
336     led.name = def->name;
337
338     ok = True;
339     for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
340     {
341         ExprResult elem, field;
342         ExprDef *arrayNdx;
343         if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
344         {
345             ok = False;
346             continue;
347         }
348         if (elem.str != NULL)
349         {
350             ERROR
351                 ("Cannot set defaults for \"%s\" element in indicator map\n",
352                  elem.str);
353             ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
354             ok = False;
355         }
356         else
357         {
358             ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
359                                       var->value) && ok;
360         }
361     }
362     if (ok)
363     {
364         rtrn = AddIndicatorMap(oldLEDs, &led);
365         return rtrn;
366     }
367     return NULL;
368 }
369
370 Bool
371 CopyIndicatorMapDefs(XkbcDescPtr xkb, LEDInfo *leds, LEDInfo **unboundRtrn)
372 {
373     LEDInfo *led, *next;
374     LEDInfo *unbound, *last;
375
376     if (XkbcAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success)
377     {
378         WSGO("Couldn't allocate names\n");
379         ACTION("Indicator names may be incorrect\n");
380     }
381     if (XkbcAllocIndicatorMaps(xkb) != Success)
382     {
383         WSGO("Can't allocate indicator maps\n");
384         ACTION("Indicator map definitions may be lost\n");
385         return False;
386     }
387     last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
388     while ((last != NULL) && (last->defs.next != NULL))
389     {
390         last = (LEDInfo *) last->defs.next;
391     }
392     for (led = leds; led != NULL; led = next)
393     {
394         next = (LEDInfo *) led->defs.next;
395         if ((led->groups != 0) && (led->which_groups == 0))
396             led->which_groups = XkbIM_UseEffective;
397         if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
398             led->which_mods = XkbIM_UseEffective;
399         if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
400         {
401             if (unboundRtrn != NULL)
402             {
403                 led->defs.next = NULL;
404                 if (last != NULL)
405                     last->defs.next = (CommonInfo *) led;
406                 else
407                     unbound = led;
408                 last = led;
409             }
410             else
411                 uFree(led);
412         }
413         else
414         {
415             register XkbIndicatorMapPtr im;
416             im = &xkb->indicators->maps[led->indicator - 1];
417             im->flags = led->flags;
418             im->which_groups = led->which_groups;
419             im->groups = led->groups;
420             im->which_mods = led->which_mods;
421             im->mods.mask = led->real_mods;
422             im->mods.real_mods = led->real_mods;
423             im->mods.vmods = led->vmods;
424             im->ctrls = led->ctrls;
425             if (xkb->names != NULL)
426                 xkb->names->indicators[led->indicator - 1] = led->name;
427             uFree(led);
428         }
429     }
430     if (unboundRtrn != NULL)
431     {
432         *unboundRtrn = unbound;
433     }
434     return True;
435 }
436
437 Bool
438 BindIndicators(XkbcDescPtr xkb, Bool force, LEDInfo *unbound,
439                LEDInfo **unboundRtrn)
440 {
441     register int i;
442     register LEDInfo *led, *next, *last;
443
444     if (xkb->names != NULL)
445     {
446         for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
447         {
448             if (led->indicator == _LED_NotBound)
449             {
450                 for (i = 0; i < XkbNumIndicators; i++)
451                 {
452                     if (xkb->names->indicators[i] == led->name)
453                     {
454                         led->indicator = i + 1;
455                         break;
456                     }
457                 }
458             }
459         }
460         if (force)
461         {
462             for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
463             {
464                 if (led->indicator == _LED_NotBound)
465                 {
466                     for (i = 0; i < XkbNumIndicators; i++)
467                     {
468                         if (xkb->names->indicators[i] == None)
469                         {
470                             xkb->names->indicators[i] = led->name;
471                             led->indicator = i + 1;
472                             xkb->indicators->phys_indicators &= ~(1 << i);
473                             break;
474                         }
475                     }
476                     if (led->indicator == _LED_NotBound)
477                     {
478                         ERROR("No unnamed indicators found\n");
479                         ACTION
480                             ("Virtual indicator map \"%s\" not bound\n",
481                              XkbcAtomGetString(led->name));
482                         continue;
483                     }
484                 }
485             }
486         }
487     }
488     for (last = NULL, led = unbound; led != NULL; led = next)
489     {
490         next = (LEDInfo *) led->defs.next;
491         if (led->indicator == _LED_NotBound)
492         {
493             if (force)
494             {
495                 unbound = next;
496                 uFree(led);
497             }
498             else
499             {
500                 if (last)
501                     last->defs.next = &led->defs;
502                 else
503                     unbound = led;
504                 last = led;
505             }
506         }
507         else
508         {
509             if ((xkb->names != NULL) &&
510                 (xkb->names->indicators[led->indicator - 1] != led->name))
511             {
512                 Atom old = xkb->names->indicators[led->indicator - 1];
513                 ERROR("Multiple names bound to indicator %d\n",
514                        (unsigned int) led->indicator);
515                 ACTION("Using %s, ignoring %s\n",
516                         XkbcAtomGetString(old),
517                         XkbcAtomGetString(led->name));
518                 led->indicator = _LED_NotBound;
519                 if (force)
520                 {
521                     uFree(led);
522                     unbound = next;
523                 }
524                 else
525                 {
526                     if (last)
527                         last->defs.next = &led->defs;
528                     else
529                         unbound = led;
530                     last = led;
531                 }
532             }
533             else
534             {
535                 XkbIndicatorMapPtr map;
536                 map = &xkb->indicators->maps[led->indicator - 1];
537                 map->flags = led->flags;
538                 map->which_groups = led->which_groups;
539                 map->groups = led->groups;
540                 map->which_mods = led->which_mods;
541                 map->mods.mask = led->real_mods;
542                 map->mods.real_mods = led->real_mods;
543                 map->mods.vmods = led->vmods;
544                 map->ctrls = led->ctrls;
545                 if (last)
546                     last->defs.next = &next->defs;
547                 else
548                     unbound = next;
549                 led->defs.next = NULL;
550                 uFree(led);
551             }
552         }
553     }
554     if (unboundRtrn)
555     {
556         *unboundRtrn = unbound;
557     }
558     else if (unbound)
559     {
560         for (led = unbound; led != NULL; led = next)
561         {
562             next = (LEDInfo *) led->defs.next;
563             uFree(led);
564         }
565     }
566     return True;
567 }