1 /************************************************************
2 * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
27 #include "indicators.h"
31 /***====================================================================***/
33 #define ReportIndicatorBadType(keymap, l, f, w) \
34 ReportBadType("indicator map", (f), \
35 xkb_atom_text((keymap)->ctx, (l)->name), (w))
36 #define ReportIndicatorNotArray(keymap, l, f) \
37 ReportNotArray("indicator map", (f), \
38 xkb_atom_text((keymap)->ctx, (l)->name))
40 /***====================================================================***/
43 ClearIndicatorMapInfo(struct xkb_context *ctx, LEDInfo * info)
45 info->name = xkb_atom_intern(ctx, "default");
46 info->indicator = _LED_NotBound;
47 info->flags = info->which_mods = info->real_mods = 0;
49 info->which_groups = info->groups = 0;
54 AddIndicatorMap(struct xkb_keymap *keymap, LEDInfo *oldLEDs, LEDInfo *new)
60 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next) {
61 if (old->name == new->name) {
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 old->defs.defined |= new->defs.defined;
71 if (new->defs.merge == MERGE_REPLACE) {
72 CommonInfo *next = old->defs.next;
73 if (((old->defs.file_id == new->defs.file_id)
74 && (warningLevel > 0)) || (warningLevel > 9)) {
75 WARN("Map for indicator %s redefined\n",
76 xkb_atom_text(keymap->ctx, old->name));
77 ACTION("Earlier definition ignored\n");
80 old->defs.next = next;
84 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide)) {
85 old->indicator = new->indicator;
86 old->defs.defined |= _LED_Index;
88 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide)) {
89 old->which_mods = new->which_mods;
90 old->real_mods = new->real_mods;
91 old->vmods = new->vmods;
92 old->defs.defined |= _LED_Mods;
94 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide)) {
95 old->which_groups = new->which_groups;
96 old->groups = new->groups;
97 old->defs.defined |= _LED_Groups;
99 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide)) {
100 old->ctrls = new->ctrls;
101 old->defs.defined |= _LED_Ctrls;
103 if (UseNewField(_LED_Explicit, &old->defs, &new->defs,
105 old->flags &= ~XkbIM_NoExplicit;
106 old->flags |= (new->flags & XkbIM_NoExplicit);
107 old->defs.defined |= _LED_Explicit;
109 if (UseNewField(_LED_Automatic, &old->defs, &new->defs,
111 old->flags &= ~XkbIM_NoAutomatic;
112 old->flags |= (new->flags & XkbIM_NoAutomatic);
113 old->defs.defined |= _LED_Automatic;
115 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs,
117 old->flags &= ~XkbIM_LEDDrivesKB;
118 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
119 old->defs.defined |= _LED_DrivesKbd;
122 WARN("Map for indicator %s redefined\n",
123 xkb_atom_text(keymap->ctx, old->name));
124 ACTION("Using %s definition for duplicate fields\n",
125 (new->defs.merge == MERGE_AUGMENT ? "first" : "last"));
129 if (old->defs.next == NULL)
133 old = uTypedAlloc(LEDInfo);
135 WSGO("Couldn't allocate indicator map\n");
136 ACTION("Map for indicator %s not compiled\n",
137 xkb_atom_text(keymap->ctx, new->name));
141 old->defs.next = NULL;
143 last->defs.next = &old->defs;
149 static const LookupEntry modComponentNames[] = {
150 { "base", XkbIM_UseBase },
151 { "latched", XkbIM_UseLatched },
152 { "locked", XkbIM_UseLocked },
153 { "effective", XkbIM_UseEffective },
154 { "compat", XkbIM_UseCompat },
155 { "any", XkbIM_UseAnyMods },
159 static const LookupEntry groupComponentNames[] = {
160 { "base", XkbIM_UseBase },
161 { "latched", XkbIM_UseLatched },
162 { "locked", XkbIM_UseLocked },
163 { "effective", XkbIM_UseEffective },
164 { "any", XkbIM_UseAnyGroup },
169 static const LookupEntry groupNames[] = {
184 SetIndicatorMapField(LEDInfo *led, struct xkb_keymap *keymap,
185 char *field, ExprDef *arrayNdx, ExprDef *value)
191 if ((strcasecmp(field, "modifiers") == 0) ||
192 (strcasecmp(field, "mods") == 0)) {
193 if (arrayNdx != NULL)
194 return ReportIndicatorNotArray(keymap, led, field);
195 if (!ExprResolveVModMask(value, &rtrn, keymap))
196 return ReportIndicatorBadType(keymap, led, field, "modifier mask");
197 led->real_mods = rtrn.uval & 0xff;
198 led->vmods = (rtrn.uval >> 8) & 0xff;
199 led->defs.defined |= _LED_Mods;
201 else if (strcasecmp(field, "groups") == 0) {
202 if (arrayNdx != NULL)
203 return ReportIndicatorNotArray(keymap, led, field);
204 if (!ExprResolveMask(keymap->ctx, value, &rtrn, groupNames))
205 return ReportIndicatorBadType(keymap, led, field, "group mask");
206 led->groups = rtrn.uval;
207 led->defs.defined |= _LED_Groups;
209 else if ((strcasecmp(field, "controls") == 0) ||
210 (strcasecmp(field, "ctrls") == 0)) {
211 if (arrayNdx != NULL)
212 return ReportIndicatorNotArray(keymap, led, field);
213 if (!ExprResolveMask(keymap->ctx, value, &rtrn, ctrlNames))
214 return ReportIndicatorBadType(keymap, led, field,
216 led->ctrls = rtrn.uval;
217 led->defs.defined |= _LED_Ctrls;
219 else if (strcasecmp(field, "allowexplicit") == 0) {
220 if (arrayNdx != NULL)
221 return ReportIndicatorNotArray(keymap, led, field);
222 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
223 return ReportIndicatorBadType(keymap, led, field, "boolean");
225 led->flags &= ~XkbIM_NoExplicit;
227 led->flags |= XkbIM_NoExplicit;
228 led->defs.defined |= _LED_Explicit;
230 else if ((strcasecmp(field, "whichmodstate") == 0) ||
231 (strcasecmp(field, "whichmodifierstate") == 0)) {
232 if (arrayNdx != NULL)
233 return ReportIndicatorNotArray(keymap, led, field);
234 if (!ExprResolveMask(keymap->ctx, value, &rtrn, modComponentNames)) {
235 return ReportIndicatorBadType(keymap, led, field,
236 "mask of modifier state components");
238 led->which_mods = rtrn.uval;
240 else if (strcasecmp(field, "whichgroupstate") == 0) {
241 if (arrayNdx != NULL)
242 return ReportIndicatorNotArray(keymap, led, field);
243 if (!ExprResolveMask(keymap->ctx, value, &rtrn,
244 groupComponentNames)) {
245 return ReportIndicatorBadType(keymap, led, field,
246 "mask of group state components");
248 led->which_groups = rtrn.uval;
250 else if ((strcasecmp(field, "driveskbd") == 0) ||
251 (strcasecmp(field, "driveskeyboard") == 0) ||
252 (strcasecmp(field, "leddriveskbd") == 0) ||
253 (strcasecmp(field, "leddriveskeyboard") == 0) ||
254 (strcasecmp(field, "indicatordriveskbd") == 0) ||
255 (strcasecmp(field, "indicatordriveskeyboard") == 0)) {
256 if (arrayNdx != NULL)
257 return ReportIndicatorNotArray(keymap, led, field);
258 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
259 return ReportIndicatorBadType(keymap, led, field, "boolean");
261 led->flags |= XkbIM_LEDDrivesKB;
263 led->flags &= ~XkbIM_LEDDrivesKB;
264 led->defs.defined |= _LED_DrivesKbd;
266 else if (strcasecmp(field, "index") == 0) {
267 if (arrayNdx != NULL)
268 return ReportIndicatorNotArray(keymap, led, field);
269 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
270 return ReportIndicatorBadType(keymap, led, field,
272 if ((rtrn.uval < 1) || (rtrn.uval > 32)) {
273 ERROR("Illegal indicator index %d (range 1..%d)\n",
274 rtrn.uval, XkbNumIndicators);
275 ACTION("Index definition for %s indicator ignored\n",
276 xkb_atom_text(keymap->ctx, led->name));
279 led->indicator = rtrn.uval;
280 led->defs.defined |= _LED_Index;
283 ERROR("Unknown field %s in map for %s indicator\n", field,
284 xkb_atom_text(keymap->ctx, led->name));
285 ACTION("Definition ignored\n");
292 HandleIndicatorMapDef(IndicatorMapDef *def, struct xkb_keymap *keymap,
293 LEDInfo *dflt, LEDInfo *oldLEDs, enum merge_mode merge)
299 if (def->merge != MERGE_DEFAULT)
303 led.defs.merge = merge;
304 led.name = def->name;
307 for (var = def->body; var != NULL; var = (VarDef *) var->common.next) {
308 ExprResult elem, field;
310 if (!ExprResolveLhs(keymap, var->name, &elem, &field, &arrayNdx)) {
314 if (elem.str != NULL) {
316 ("Cannot set defaults for \"%s\" element in indicator map\n",
318 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
322 ok = SetIndicatorMapField(&led, keymap, field.str, arrayNdx,
329 rtrn = AddIndicatorMap(keymap, oldLEDs, &led);
336 BindIndicators(struct xkb_keymap *keymap, LEDInfo *unbound)
339 LEDInfo *led, *next, *last;
341 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) {
342 if (led->indicator == _LED_NotBound) {
343 for (i = 0; i < XkbNumIndicators; i++) {
344 if (keymap->indicator_names[i] &&
345 strcmp(keymap->indicator_names[i],
346 xkb_atom_text(keymap->ctx, led->name)) == 0) {
347 led->indicator = i + 1;
354 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) {
355 if (led->indicator == _LED_NotBound) {
356 for (i = 0; i < XkbNumIndicators; i++) {
357 if (keymap->indicator_names[i] == NULL) {
358 keymap->indicator_names[i] =
359 xkb_atom_strdup(keymap->ctx, led->name);
360 led->indicator = i + 1;
364 if (led->indicator == _LED_NotBound) {
365 ERROR("No unnamed indicators found\n");
366 ACTION("Virtual indicator map \"%s\" not bound\n",
367 xkb_atom_text(keymap->ctx, led->name));
372 for (last = NULL, led = unbound; led != NULL; led = next) {
373 next = (LEDInfo *) led->defs.next;
374 if (led->indicator == _LED_NotBound) {
379 if (strcmp(keymap->indicator_names[led->indicator - 1],
380 xkb_atom_text(keymap->ctx, led->name)) != 0) {
381 const char *old = keymap->indicator_names[led->indicator - 1];
382 ERROR("Multiple names bound to indicator %d\n",
383 (unsigned int) led->indicator);
384 ACTION("Using %s, ignoring %s\n", old,
385 xkb_atom_text(keymap->ctx, led->name));
386 led->indicator = _LED_NotBound;
391 struct xkb_indicator_map * map;
392 map = &keymap->indicators[led->indicator - 1];
393 map->flags = led->flags;
394 map->which_groups = led->which_groups;
395 map->groups = led->groups;
396 map->which_mods = led->which_mods;
397 map->mods.mask = led->real_mods;
398 map->mods.real_mods = led->real_mods;
399 map->mods.vmods = led->vmods;
400 map->ctrls = led->ctrls;
402 last->defs.next = &next->defs;
405 led->defs.next = NULL;
411 for (led = unbound; led != NULL; led = next) {
412 next = led ? (LEDInfo *) led->defs.next : NULL;
418 CopyIndicatorMapDefs(struct xkb_keymap *keymap, LEDInfo *leds)
421 LEDInfo *unbound = NULL, *last = NULL;
423 for (led = leds; led != NULL; led = next) {
424 next = (LEDInfo *) led->defs.next;
425 if ((led->groups != 0) && (led->which_groups == 0))
426 led->which_groups = XkbIM_UseEffective;
427 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
428 led->which_mods = XkbIM_UseEffective;
429 if ((led->indicator == _LED_NotBound) || (!keymap->indicators)) {
430 led->defs.next = NULL;
432 last->defs.next = (CommonInfo *) led;
438 struct xkb_indicator_map * im;
439 im = &keymap->indicators[led->indicator - 1];
440 im->flags = led->flags;
441 im->which_groups = led->which_groups;
442 im->groups = led->groups;
443 im->which_mods = led->which_mods;
444 im->mods.mask = led->real_mods;
445 im->mods.real_mods = led->real_mods;
446 im->mods.vmods = led->vmods;
447 im->ctrls = led->ctrls;
448 free(keymap->indicator_names[led->indicator - 1]);
449 keymap->indicator_names[led->indicator - 1] =
450 xkb_atom_strdup(keymap->ctx, led->name);
456 BindIndicators(keymap, unbound);