symbols.c revision f757b1e9
1f46a6179Smrg/************************************************************ 2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3f46a6179Smrg 4f46a6179Smrg Permission to use, copy, modify, and distribute this 5f46a6179Smrg software and its documentation for any purpose and without 6f46a6179Smrg fee is hereby granted, provided that the above copyright 7f46a6179Smrg notice appear in all copies and that both that copyright 8f46a6179Smrg notice and this permission notice appear in supporting 9f46a6179Smrg documentation, and that the name of Silicon Graphics not be 10f46a6179Smrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12f46a6179Smrg Silicon Graphics makes no representation about the suitability 13f46a6179Smrg of this software for any purpose. It is provided "as is" 14f46a6179Smrg without any express or implied warranty. 15f46a6179Smrg 16f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24f46a6179Smrg 25f46a6179Smrg ********************************************************/ 26f46a6179Smrg 27f46a6179Smrg#include "xkbcomp.h" 28f46a6179Smrg#include "tokens.h" 29f46a6179Smrg#include "expr.h" 3083e5f723Smrg#include "parseutils.h" 31f46a6179Smrg 32f46a6179Smrg#include <X11/keysym.h> 33f46a6179Smrg#include <X11/Xutil.h> 34f46a6179Smrg#include <stdlib.h> 35f46a6179Smrg 36f46a6179Smrg#include "expr.h" 37f46a6179Smrg#include "vmod.h" 38f46a6179Smrg#include "action.h" 39f46a6179Smrg#include "keycodes.h" 40f46a6179Smrg#include "misc.h" 41f46a6179Smrg#include "alias.h" 42f46a6179Smrg 43f46a6179Smrg/***====================================================================***/ 44f46a6179Smrg 45f46a6179Smrg#define RepeatYes 1 46f46a6179Smrg#define RepeatNo 0 47f46a6179Smrg#define RepeatUndefined ~((unsigned)0) 48f46a6179Smrg 49f46a6179Smrg#define _Key_Syms (1<<0) 50f46a6179Smrg#define _Key_Acts (1<<1) 51f46a6179Smrg#define _Key_Repeat (1<<2) 52f46a6179Smrg#define _Key_Behavior (1<<3) 53f46a6179Smrg#define _Key_Type_Dflt (1<<4) 54f46a6179Smrg#define _Key_Types (1<<5) 55f46a6179Smrg#define _Key_GroupInfo (1<<6) 56f46a6179Smrg#define _Key_VModMap (1<<7) 57f46a6179Smrg 5834345a63Smrgtypedef struct _KeyInfo 5934345a63Smrg{ 6034345a63Smrg CommonInfo defs; 6134345a63Smrg unsigned long name; /* the 4 chars of the key name, as long */ 6234345a63Smrg unsigned char groupInfo; 6334345a63Smrg unsigned char typesDefined; 6434345a63Smrg unsigned char symsDefined; 6534345a63Smrg unsigned char actsDefined; 6634345a63Smrg short numLevels[XkbNumKbdGroups]; 6734345a63Smrg KeySym *syms[XkbNumKbdGroups]; 6834345a63Smrg XkbAction *acts[XkbNumKbdGroups]; 6934345a63Smrg Atom types[XkbNumKbdGroups]; 7034345a63Smrg unsigned repeat; 7134345a63Smrg XkbBehavior behavior; 7234345a63Smrg unsigned short vmodmap; 7334345a63Smrg unsigned long nameForOverlayKey; 7434345a63Smrg unsigned long allowNone; 7534345a63Smrg Atom dfltType; 76f46a6179Smrg} KeyInfo; 77f46a6179Smrg 7834345a63Smrg/** 7934345a63Smrg * Init the given key info to sane values. 8034345a63Smrg */ 81f46a6179Smrgstatic void 8234345a63SmrgInitKeyInfo(KeyInfo * info) 83f46a6179Smrg{ 8434345a63Smrg register int i; 8534345a63Smrg static char dflt[4] = "*"; 8634345a63Smrg 8734345a63Smrg info->defs.defined = 0; 8834345a63Smrg info->defs.fileID = 0; 8934345a63Smrg info->defs.merge = MergeOverride; 9034345a63Smrg info->defs.next = NULL; 9134345a63Smrg info->name = KeyNameToLong(dflt); 9234345a63Smrg info->groupInfo = 0; 9334345a63Smrg info->typesDefined = info->symsDefined = info->actsDefined = 0; 9434345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 9534345a63Smrg { 9634345a63Smrg info->numLevels[i] = 0; 9734345a63Smrg info->types[i] = None; 9834345a63Smrg info->syms[i] = NULL; 9934345a63Smrg info->acts[i] = NULL; 10034345a63Smrg } 10134345a63Smrg info->dfltType = None; 10234345a63Smrg info->behavior.type = XkbKB_Default; 10334345a63Smrg info->behavior.data = 0; 10434345a63Smrg info->vmodmap = 0; 10534345a63Smrg info->nameForOverlayKey = 0; 10634345a63Smrg info->repeat = RepeatUndefined; 10734345a63Smrg info->allowNone = 0; 108f46a6179Smrg return; 109f46a6179Smrg} 110f46a6179Smrg 11134345a63Smrg/** 11234345a63Smrg * Free memory associated with this key info and reset to sane values. 11334345a63Smrg */ 114f46a6179Smrgstatic void 11534345a63SmrgFreeKeyInfo(KeyInfo * info) 116f46a6179Smrg{ 11734345a63Smrg register int i; 11834345a63Smrg 11934345a63Smrg info->defs.defined = 0; 12034345a63Smrg info->defs.fileID = 0; 12134345a63Smrg info->defs.merge = MergeOverride; 12234345a63Smrg info->defs.next = NULL; 12334345a63Smrg info->groupInfo = 0; 12434345a63Smrg info->typesDefined = info->symsDefined = info->actsDefined = 0; 12534345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 12634345a63Smrg { 12734345a63Smrg info->numLevels[i] = 0; 12834345a63Smrg info->types[i] = None; 12934345a63Smrg if (info->syms[i] != NULL) 13034345a63Smrg uFree(info->syms[i]); 13134345a63Smrg info->syms[i] = NULL; 13234345a63Smrg if (info->acts[i] != NULL) 13334345a63Smrg uFree(info->acts[i]); 13434345a63Smrg info->acts[i] = NULL; 13534345a63Smrg } 13634345a63Smrg info->dfltType = None; 13734345a63Smrg info->behavior.type = XkbKB_Default; 13834345a63Smrg info->behavior.data = 0; 13934345a63Smrg info->vmodmap = 0; 14034345a63Smrg info->nameForOverlayKey = 0; 14134345a63Smrg info->repeat = RepeatUndefined; 14234345a63Smrg info->allowNone = 0; 143f46a6179Smrg return; 144f46a6179Smrg} 145f46a6179Smrg 14634345a63Smrg/** 14734345a63Smrg * Copy old into new, optionally reset old to 0. 14834345a63Smrg * If old is reset, new simply re-uses old's memory. Otherwise, the memory is 14934345a63Smrg * newly allocated and new points to the new memory areas. 15034345a63Smrg */ 151f46a6179Smrgstatic Bool 15234345a63SmrgCopyKeyInfo(KeyInfo * old, KeyInfo * new, Bool clearOld) 153f46a6179Smrg{ 15434345a63Smrg register int i; 15534345a63Smrg 15634345a63Smrg *new = *old; 15734345a63Smrg new->defs.next = NULL; 15834345a63Smrg if (clearOld) 15934345a63Smrg { 16034345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 16134345a63Smrg { 16234345a63Smrg old->numLevels[i] = 0; 16334345a63Smrg old->syms[i] = NULL; 16434345a63Smrg old->acts[i] = NULL; 16534345a63Smrg } 16634345a63Smrg } 16734345a63Smrg else 16834345a63Smrg { 16934345a63Smrg int width; 17034345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 17134345a63Smrg { 17234345a63Smrg width = new->numLevels[i]; 17334345a63Smrg if (old->syms[i] != NULL) 17434345a63Smrg { 17534345a63Smrg new->syms[i] = uTypedCalloc(width, KeySym); 17634345a63Smrg if (!new->syms[i]) 17734345a63Smrg { 17834345a63Smrg new->syms[i] = NULL; 17934345a63Smrg new->numLevels[i] = 0; 18034345a63Smrg return False; 18134345a63Smrg } 18234345a63Smrg memcpy((char *) new->syms[i], (char *) old->syms[i], 18334345a63Smrg width * sizeof(KeySym)); 18434345a63Smrg } 18534345a63Smrg if (old->acts[i] != NULL) 18634345a63Smrg { 18734345a63Smrg new->acts[i] = uTypedCalloc(width, XkbAction); 18834345a63Smrg if (!new->acts[i]) 18934345a63Smrg { 19034345a63Smrg new->acts[i] = NULL; 19134345a63Smrg return False; 19234345a63Smrg } 19334345a63Smrg memcpy((char *) new->acts[i], (char *) old->acts[i], 19434345a63Smrg width * sizeof(XkbAction)); 19534345a63Smrg } 19634345a63Smrg } 197f46a6179Smrg } 198f46a6179Smrg return True; 199f46a6179Smrg} 200f46a6179Smrg 201f46a6179Smrg/***====================================================================***/ 202f46a6179Smrg 20334345a63Smrgtypedef struct _ModMapEntry 20434345a63Smrg{ 20534345a63Smrg CommonInfo defs; 20634345a63Smrg Bool haveSymbol; 20734345a63Smrg int modifier; 20834345a63Smrg union 20934345a63Smrg { 21034345a63Smrg unsigned long keyName; 21134345a63Smrg KeySym keySym; 212f46a6179Smrg } u; 213f46a6179Smrg} ModMapEntry; 214f46a6179Smrg 215f46a6179Smrg#define SYMBOLS_INIT_SIZE 110 216f46a6179Smrg#define SYMBOLS_CHUNK 20 21734345a63Smrgtypedef struct _SymbolsInfo 21834345a63Smrg{ 21934345a63Smrg char *name; /* e.g. pc+us+inet(evdev) */ 22034345a63Smrg int errorCount; 22134345a63Smrg unsigned fileID; 22234345a63Smrg unsigned merge; 22334345a63Smrg unsigned explicit_group; 22434345a63Smrg unsigned groupInfo; 22534345a63Smrg unsigned szKeys; 22634345a63Smrg unsigned nKeys; 22734345a63Smrg KeyInfo *keys; 22834345a63Smrg KeyInfo dflt; 22934345a63Smrg VModInfo vmods; 23034345a63Smrg ActionInfo *action; 23134345a63Smrg Atom groupNames[XkbNumKbdGroups]; 23234345a63Smrg 23334345a63Smrg ModMapEntry *modMap; 23434345a63Smrg AliasInfo *aliases; 235f46a6179Smrg} SymbolsInfo; 236f46a6179Smrg 237f46a6179Smrgstatic void 23834345a63SmrgInitSymbolsInfo(SymbolsInfo * info, XkbDescPtr xkb) 239f46a6179Smrg{ 24034345a63Smrg register int i; 24134345a63Smrg 24234345a63Smrg tok_ONE_LEVEL = XkbInternAtom(NULL, "ONE_LEVEL", False); 24334345a63Smrg tok_TWO_LEVEL = XkbInternAtom(NULL, "TWO_LEVEL", False); 24434345a63Smrg tok_KEYPAD = XkbInternAtom(NULL, "KEYPAD", False); 24534345a63Smrg info->name = NULL; 24634345a63Smrg info->explicit_group = 0; 24734345a63Smrg info->errorCount = 0; 24834345a63Smrg info->fileID = 0; 24934345a63Smrg info->merge = MergeOverride; 25034345a63Smrg info->groupInfo = 0; 25134345a63Smrg info->szKeys = SYMBOLS_INIT_SIZE; 25234345a63Smrg info->nKeys = 0; 25334345a63Smrg info->keys = uTypedCalloc(SYMBOLS_INIT_SIZE, KeyInfo); 25434345a63Smrg info->modMap = NULL; 25534345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 25634345a63Smrg info->groupNames[i] = None; 257f46a6179Smrg InitKeyInfo(&info->dflt); 25834345a63Smrg InitVModInfo(&info->vmods, xkb); 25934345a63Smrg info->action = NULL; 26034345a63Smrg info->aliases = NULL; 261f46a6179Smrg return; 262f46a6179Smrg} 263f46a6179Smrg 264f46a6179Smrgstatic void 26534345a63SmrgFreeSymbolsInfo(SymbolsInfo * info) 266f46a6179Smrg{ 26734345a63Smrg register int i; 268f46a6179Smrg 269f46a6179Smrg if (info->name) 27034345a63Smrg uFree(info->name); 27134345a63Smrg info->name = NULL; 27234345a63Smrg if (info->keys) 27334345a63Smrg { 27434345a63Smrg for (i = 0; i < info->nKeys; i++) 27534345a63Smrg { 27634345a63Smrg FreeKeyInfo(&info->keys[i]); 27734345a63Smrg } 27834345a63Smrg uFree(info->keys); 27934345a63Smrg info->keys = NULL; 28034345a63Smrg } 28134345a63Smrg if (info->modMap) 28234345a63Smrg { 28334345a63Smrg ClearCommonInfo(&info->modMap->defs); 28434345a63Smrg info->modMap = NULL; 28534345a63Smrg } 28634345a63Smrg if (info->aliases) 28734345a63Smrg { 28834345a63Smrg ClearAliases(&info->aliases); 28934345a63Smrg info->aliases = NULL; 29034345a63Smrg } 29134345a63Smrg bzero((char *) info, sizeof(SymbolsInfo)); 292f46a6179Smrg return; 293f46a6179Smrg} 294f46a6179Smrg 295f46a6179Smrgstatic Bool 29634345a63SmrgResizeKeyGroup(KeyInfo * key, 29734345a63Smrg unsigned group, unsigned atLeastSize, Bool forceActions) 298f46a6179Smrg{ 29934345a63Smrg Bool tooSmall; 30034345a63Smrg unsigned newWidth; 30134345a63Smrg 30234345a63Smrg tooSmall = (key->numLevels[group] < atLeastSize); 30334345a63Smrg if (tooSmall) 30434345a63Smrg newWidth = atLeastSize; 30534345a63Smrg else 30634345a63Smrg newWidth = key->numLevels[group]; 30734345a63Smrg 30834345a63Smrg if ((key->syms[group] == NULL) || tooSmall) 30934345a63Smrg { 31034345a63Smrg key->syms[group] = uTypedRecalloc(key->syms[group], 31134345a63Smrg key->numLevels[group], newWidth, 31234345a63Smrg KeySym); 31334345a63Smrg if (!key->syms[group]) 31434345a63Smrg return False; 31534345a63Smrg } 31634345a63Smrg if (((forceActions) && (tooSmall || (key->acts[group] == NULL))) || 31734345a63Smrg (tooSmall && (key->acts[group] != NULL))) 31834345a63Smrg { 31934345a63Smrg key->acts[group] = uTypedRecalloc(key->acts[group], 32034345a63Smrg key->numLevels[group], newWidth, 32134345a63Smrg XkbAction); 32234345a63Smrg if (!key->acts[group]) 32334345a63Smrg return False; 32434345a63Smrg } 32534345a63Smrg key->numLevels[group] = newWidth; 326f46a6179Smrg return True; 327f46a6179Smrg} 328f46a6179Smrg 329f46a6179Smrgstatic Bool 33034345a63SmrgMergeKeyGroups(SymbolsInfo * info, 33134345a63Smrg KeyInfo * into, KeyInfo * from, unsigned group) 332f46a6179Smrg{ 33334345a63Smrg KeySym *resultSyms; 33434345a63Smrg XkbAction *resultActs; 33534345a63Smrg int resultWidth; 33634345a63Smrg register int i; 33734345a63Smrg Bool report, clobber; 33834345a63Smrg 33934345a63Smrg clobber = (from->defs.merge != MergeAugment); 34034345a63Smrg report = (warningLevel > 9) || 34134345a63Smrg ((into->defs.fileID == from->defs.fileID) && (warningLevel > 0)); 342f757b1e9Smrg if ((from->numLevels[group] > into->numLevels[group]) 343f757b1e9Smrg || (clobber && (from->types[group] != None))) 34434345a63Smrg { 34534345a63Smrg resultSyms = from->syms[group]; 34634345a63Smrg resultActs = from->acts[group]; 34734345a63Smrg resultWidth = from->numLevels[group]; 34834345a63Smrg } 349f757b1e9Smrg else 350f757b1e9Smrg { 351f757b1e9Smrg resultSyms = into->syms[group]; 352f757b1e9Smrg resultActs = into->acts[group]; 353f757b1e9Smrg resultWidth = into->numLevels[group]; 354f757b1e9Smrg } 35534345a63Smrg if (resultSyms == NULL) 35634345a63Smrg { 35734345a63Smrg resultSyms = uTypedCalloc(resultWidth, KeySym); 35834345a63Smrg if (!resultSyms) 35934345a63Smrg { 36034345a63Smrg WSGO("Could not allocate symbols for group merge\n"); 36134345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 36234345a63Smrg longText(into->name, XkbMessage)); 36334345a63Smrg return False; 36434345a63Smrg } 36534345a63Smrg } 36634345a63Smrg if ((resultActs == NULL) && (into->acts[group] || from->acts[group])) 36734345a63Smrg { 36834345a63Smrg resultActs = uTypedCalloc(resultWidth, XkbAction); 36934345a63Smrg if (!resultActs) 37034345a63Smrg { 37134345a63Smrg WSGO("Could not allocate actions for group merge\n"); 37234345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 37334345a63Smrg longText(into->name, XkbMessage)); 37434345a63Smrg return False; 37534345a63Smrg } 37634345a63Smrg } 37734345a63Smrg for (i = 0; i < resultWidth; i++) 37834345a63Smrg { 37934345a63Smrg KeySym fromSym, toSym; 38034345a63Smrg if (from->syms[group] && (i < from->numLevels[group])) 38134345a63Smrg fromSym = from->syms[group][i]; 38234345a63Smrg else 38334345a63Smrg fromSym = NoSymbol; 38434345a63Smrg if (into->syms[group] && (i < into->numLevels[group])) 38534345a63Smrg toSym = into->syms[group][i]; 38634345a63Smrg else 38734345a63Smrg toSym = NoSymbol; 38834345a63Smrg if ((fromSym == NoSymbol) || (fromSym == toSym)) 38934345a63Smrg resultSyms[i] = toSym; 39034345a63Smrg else if (toSym == NoSymbol) 39134345a63Smrg resultSyms[i] = fromSym; 39234345a63Smrg else 39334345a63Smrg { 39434345a63Smrg KeySym use, ignore; 39534345a63Smrg if (clobber) 39634345a63Smrg { 39734345a63Smrg use = fromSym; 39834345a63Smrg ignore = toSym; 39934345a63Smrg } 40034345a63Smrg else 40134345a63Smrg { 40234345a63Smrg use = toSym; 40334345a63Smrg ignore = fromSym; 40434345a63Smrg } 40534345a63Smrg if (report) 40634345a63Smrg { 40734345a63Smrg WARN3 40834345a63Smrg ("Multiple symbols for level %d/group %d on key %s\n", 40934345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 41034345a63Smrg ACTION2("Using %s, ignoring %s\n", 41134345a63Smrg XkbKeysymText(use, XkbMessage), 41234345a63Smrg XkbKeysymText(ignore, XkbMessage)); 41334345a63Smrg } 41434345a63Smrg resultSyms[i] = use; 41534345a63Smrg } 41634345a63Smrg if (resultActs != NULL) 41734345a63Smrg { 41834345a63Smrg XkbAction *fromAct, *toAct; 41934345a63Smrg fromAct = (from->acts[group] ? &from->acts[group][i] : NULL); 42034345a63Smrg toAct = (into->acts[group] ? &into->acts[group][i] : NULL); 42134345a63Smrg if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction)) 42234345a63Smrg && (toAct != NULL)) 42334345a63Smrg { 42434345a63Smrg resultActs[i] = *toAct; 42534345a63Smrg } 42634345a63Smrg else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction)) 42734345a63Smrg && (fromAct != NULL)) 42834345a63Smrg { 42934345a63Smrg resultActs[i] = *fromAct; 43034345a63Smrg } 43134345a63Smrg else 43234345a63Smrg { 43334345a63Smrg XkbAction *use, *ignore; 43434345a63Smrg if (clobber) 43534345a63Smrg { 43634345a63Smrg use = fromAct; 43734345a63Smrg ignore = toAct; 43834345a63Smrg } 43934345a63Smrg else 44034345a63Smrg { 44134345a63Smrg use = toAct; 44234345a63Smrg ignore = fromAct; 44334345a63Smrg } 44434345a63Smrg if (report) 44534345a63Smrg { 44634345a63Smrg WARN3 44734345a63Smrg ("Multiple actions for level %d/group %d on key %s\n", 44834345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 44934345a63Smrg ACTION2("Using %s, ignoring %s\n", 45034345a63Smrg XkbActionTypeText(use->type, XkbMessage), 45134345a63Smrg XkbActionTypeText(ignore->type, XkbMessage)); 45234345a63Smrg } 45334345a63Smrg resultActs[i] = *use; 45434345a63Smrg } 45534345a63Smrg } 45634345a63Smrg } 45734345a63Smrg if ((into->syms[group] != NULL) && (resultSyms != into->syms[group])) 45834345a63Smrg uFree(into->syms[group]); 45934345a63Smrg if ((from->syms[group] != NULL) && (resultSyms != from->syms[group])) 46034345a63Smrg uFree(from->syms[group]); 46134345a63Smrg if ((into->acts[group] != NULL) && (resultActs != into->acts[group])) 46234345a63Smrg uFree(into->acts[group]); 46334345a63Smrg if ((from->acts[group] != NULL) && (resultActs != from->acts[group])) 46434345a63Smrg uFree(from->acts[group]); 46534345a63Smrg into->numLevels[group] = resultWidth; 46634345a63Smrg into->syms[group] = resultSyms; 46734345a63Smrg from->syms[group] = NULL; 46834345a63Smrg into->acts[group] = resultActs; 46934345a63Smrg from->acts[group] = NULL; 47034345a63Smrg into->symsDefined |= (1 << group); 47134345a63Smrg from->symsDefined &= ~(1 << group); 47234345a63Smrg into->actsDefined |= (1 << group); 47334345a63Smrg from->actsDefined &= ~(1 << group); 474f46a6179Smrg return True; 475f46a6179Smrg} 476f46a6179Smrg 477f46a6179Smrgstatic Bool 47834345a63SmrgMergeKeys(SymbolsInfo * info, KeyInfo * into, KeyInfo * from) 479f46a6179Smrg{ 48034345a63Smrg register int i; 48134345a63Smrg unsigned collide = 0; 48234345a63Smrg Bool report; 48334345a63Smrg 48434345a63Smrg if (from->defs.merge == MergeReplace) 48534345a63Smrg { 48634345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 48734345a63Smrg { 48834345a63Smrg if (into->numLevels[i] != 0) 48934345a63Smrg { 49034345a63Smrg if (into->syms[i]) 49134345a63Smrg uFree(into->syms[i]); 49234345a63Smrg if (into->acts[i]) 49334345a63Smrg uFree(into->acts[i]); 49434345a63Smrg } 49534345a63Smrg } 49634345a63Smrg *into = *from; 49734345a63Smrg bzero(from, sizeof(KeyInfo)); 49834345a63Smrg return True; 49934345a63Smrg } 50034345a63Smrg report = ((warningLevel > 9) || 50134345a63Smrg ((into->defs.fileID == from->defs.fileID) 50234345a63Smrg && (warningLevel > 0))); 50334345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 50434345a63Smrg { 50534345a63Smrg if (from->numLevels[i] > 0) 50634345a63Smrg { 50734345a63Smrg if (into->numLevels[i] == 0) 50834345a63Smrg { 50934345a63Smrg into->numLevels[i] = from->numLevels[i]; 51034345a63Smrg into->syms[i] = from->syms[i]; 51134345a63Smrg into->acts[i] = from->acts[i]; 51234345a63Smrg into->symsDefined |= (1 << i); 51334345a63Smrg from->syms[i] = NULL; 51434345a63Smrg from->acts[i] = NULL; 51534345a63Smrg from->numLevels[i] = 0; 51634345a63Smrg from->symsDefined &= ~(1 << i); 51734345a63Smrg if (into->syms[i]) 51834345a63Smrg into->defs.defined |= _Key_Syms; 51934345a63Smrg if (into->acts[i]) 52034345a63Smrg into->defs.defined |= _Key_Acts; 52134345a63Smrg } 52234345a63Smrg else 52334345a63Smrg { 52434345a63Smrg if (report) 52534345a63Smrg { 52634345a63Smrg if (into->syms[i]) 52734345a63Smrg collide |= _Key_Syms; 52834345a63Smrg if (into->acts[i]) 52934345a63Smrg collide |= _Key_Acts; 53034345a63Smrg } 53134345a63Smrg MergeKeyGroups(info, into, from, (unsigned) i); 53234345a63Smrg } 53334345a63Smrg } 53434345a63Smrg if (from->types[i] != None) 53534345a63Smrg { 53634345a63Smrg if ((into->types[i] != None) && (report) && 53734345a63Smrg (into->types[i] != from->types[i])) 53834345a63Smrg { 53934345a63Smrg Atom use, ignore; 54034345a63Smrg collide |= _Key_Types; 54134345a63Smrg if (from->defs.merge != MergeAugment) 54234345a63Smrg { 54334345a63Smrg use = from->types[i]; 54434345a63Smrg ignore = into->types[i]; 54534345a63Smrg } 54634345a63Smrg else 54734345a63Smrg { 54834345a63Smrg use = into->types[i]; 54934345a63Smrg ignore = from->types[i]; 55034345a63Smrg } 55134345a63Smrg WARN2 55234345a63Smrg ("Multiple definitions for group %d type of key %s\n", 55334345a63Smrg i, longText(into->name, XkbMessage)); 55434345a63Smrg ACTION2("Using %s, ignoring %s\n", 55534345a63Smrg XkbAtomText(NULL, use, XkbMessage), 55634345a63Smrg XkbAtomText(NULL, ignore, XkbMessage)); 55734345a63Smrg } 55834345a63Smrg if ((from->defs.merge != MergeAugment) 55934345a63Smrg || (into->types[i] == None)) 56034345a63Smrg { 56134345a63Smrg into->types[i] = from->types[i]; 56234345a63Smrg } 56334345a63Smrg } 56434345a63Smrg } 56534345a63Smrg if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide)) 56634345a63Smrg { 56734345a63Smrg into->behavior = from->behavior; 56834345a63Smrg into->nameForOverlayKey = from->nameForOverlayKey; 56934345a63Smrg into->defs.defined |= _Key_Behavior; 57034345a63Smrg } 57134345a63Smrg if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide)) 57234345a63Smrg { 57334345a63Smrg into->vmodmap = from->vmodmap; 57434345a63Smrg into->defs.defined |= _Key_VModMap; 57534345a63Smrg } 57634345a63Smrg if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide)) 57734345a63Smrg { 57834345a63Smrg into->repeat = from->repeat; 57934345a63Smrg into->defs.defined |= _Key_Repeat; 58034345a63Smrg } 58134345a63Smrg if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide)) 58234345a63Smrg { 58334345a63Smrg into->dfltType = from->dfltType; 58434345a63Smrg into->defs.defined |= _Key_Type_Dflt; 58534345a63Smrg } 58634345a63Smrg if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide)) 58734345a63Smrg { 58834345a63Smrg into->groupInfo = from->groupInfo; 58934345a63Smrg into->defs.defined |= _Key_GroupInfo; 59034345a63Smrg } 59134345a63Smrg if (collide) 59234345a63Smrg { 59334345a63Smrg WARN1("Symbol map for key %s redefined\n", 59434345a63Smrg longText(into->name, XkbMessage)); 59534345a63Smrg ACTION1("Using %s definition for conflicting fields\n", 59634345a63Smrg (from->defs.merge == MergeAugment ? "first" : "last")); 597f46a6179Smrg } 598f46a6179Smrg return True; 599f46a6179Smrg} 600f46a6179Smrg 601f46a6179Smrgstatic Bool 60234345a63SmrgAddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbDescPtr xkb) 603f46a6179Smrg{ 60434345a63Smrg register int i; 60534345a63Smrg unsigned long real_name; 60634345a63Smrg 60734345a63Smrg for (i = 0; i < info->nKeys; i++) 60834345a63Smrg { 60934345a63Smrg if (info->keys[i].name == key->name) 61034345a63Smrg return MergeKeys(info, &info->keys[i], key); 61134345a63Smrg } 61234345a63Smrg if (FindKeyNameForAlias(xkb, key->name, &real_name)) 61334345a63Smrg { 61434345a63Smrg for (i = 0; i < info->nKeys; i++) 61534345a63Smrg { 61634345a63Smrg if (info->keys[i].name == real_name) 61734345a63Smrg return MergeKeys(info, &info->keys[i], key); 618f46a6179Smrg } 619f46a6179Smrg } 62034345a63Smrg if (info->nKeys >= info->szKeys) 62134345a63Smrg { 62234345a63Smrg info->szKeys += SYMBOLS_CHUNK; 62334345a63Smrg info->keys = 62434345a63Smrg uTypedRecalloc(info->keys, info->nKeys, info->szKeys, KeyInfo); 62534345a63Smrg if (!info->keys) 62634345a63Smrg { 62734345a63Smrg WSGO("Could not allocate key symbols descriptions\n"); 62834345a63Smrg ACTION("Some key symbols definitions may be lost\n"); 62934345a63Smrg return False; 63034345a63Smrg } 631f46a6179Smrg } 63234345a63Smrg return CopyKeyInfo(key, &info->keys[info->nKeys++], True); 633f46a6179Smrg} 634f46a6179Smrg 635f46a6179Smrgstatic Bool 63634345a63SmrgAddModMapEntry(SymbolsInfo * info, ModMapEntry * new) 637f46a6179Smrg{ 63834345a63Smrg ModMapEntry *mm; 63934345a63Smrg Bool clobber; 64034345a63Smrg 64134345a63Smrg clobber = (new->defs.merge != MergeAugment); 64234345a63Smrg for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next) 64334345a63Smrg { 64434345a63Smrg if (new->haveSymbol && mm->haveSymbol 64534345a63Smrg && (new->u.keySym == mm->u.keySym)) 64634345a63Smrg { 64734345a63Smrg unsigned use, ignore; 64834345a63Smrg if (mm->modifier != new->modifier) 64934345a63Smrg { 65034345a63Smrg if (clobber) 65134345a63Smrg { 65234345a63Smrg use = new->modifier; 65334345a63Smrg ignore = mm->modifier; 65434345a63Smrg } 65534345a63Smrg else 65634345a63Smrg { 65734345a63Smrg use = mm->modifier; 65834345a63Smrg ignore = new->modifier; 65934345a63Smrg } 66034345a63Smrg ERROR1 66134345a63Smrg ("%s added to symbol map for multiple modifiers\n", 66234345a63Smrg XkbKeysymText(new->u.keySym, XkbMessage)); 66334345a63Smrg ACTION2("Using %s, ignoring %s.\n", 66434345a63Smrg XkbModIndexText(use, XkbMessage), 66534345a63Smrg XkbModIndexText(ignore, XkbMessage)); 66634345a63Smrg mm->modifier = use; 66734345a63Smrg } 66834345a63Smrg return True; 66934345a63Smrg } 67034345a63Smrg if ((!new->haveSymbol) && (!mm->haveSymbol) && 67134345a63Smrg (new->u.keyName == mm->u.keyName)) 67234345a63Smrg { 67334345a63Smrg unsigned use, ignore; 67434345a63Smrg if (mm->modifier != new->modifier) 67534345a63Smrg { 67634345a63Smrg if (clobber) 67734345a63Smrg { 67834345a63Smrg use = new->modifier; 67934345a63Smrg ignore = mm->modifier; 68034345a63Smrg } 68134345a63Smrg else 68234345a63Smrg { 68334345a63Smrg use = mm->modifier; 68434345a63Smrg ignore = new->modifier; 68534345a63Smrg } 68634345a63Smrg ERROR1("Key %s added to map for multiple modifiers\n", 68734345a63Smrg longText(new->u.keyName, XkbMessage)); 68834345a63Smrg ACTION2("Using %s, ignoring %s.\n", 68934345a63Smrg XkbModIndexText(use, XkbMessage), 69034345a63Smrg XkbModIndexText(ignore, XkbMessage)); 69134345a63Smrg mm->modifier = use; 69234345a63Smrg } 69334345a63Smrg return True; 69434345a63Smrg } 69534345a63Smrg } 69634345a63Smrg mm = uTypedAlloc(ModMapEntry); 69734345a63Smrg if (mm == NULL) 69834345a63Smrg { 69934345a63Smrg WSGO("Could not allocate modifier map entry\n"); 70034345a63Smrg ACTION1("Modifier map for %s will be incomplete\n", 70134345a63Smrg XkbModIndexText(new->modifier, XkbMessage)); 70234345a63Smrg return False; 70334345a63Smrg } 70434345a63Smrg *mm = *new; 70534345a63Smrg mm->defs.next = &info->modMap->defs; 70634345a63Smrg info->modMap = mm; 707f46a6179Smrg return True; 708f46a6179Smrg} 709f46a6179Smrg 710f46a6179Smrg/***====================================================================***/ 711f46a6179Smrg 712f46a6179Smrgstatic void 71334345a63SmrgMergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from, 71434345a63Smrg unsigned merge, XkbDescPtr xkb) 715f46a6179Smrg{ 71634345a63Smrg register int i; 71734345a63Smrg KeyInfo *key; 71834345a63Smrg 71934345a63Smrg if (from->errorCount > 0) 72034345a63Smrg { 72134345a63Smrg into->errorCount += from->errorCount; 72234345a63Smrg return; 72334345a63Smrg } 72434345a63Smrg if (into->name == NULL) 72534345a63Smrg { 72634345a63Smrg into->name = from->name; 72734345a63Smrg from->name = NULL; 72834345a63Smrg } 72934345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 73034345a63Smrg { 73134345a63Smrg if (from->groupNames[i] != None) 73234345a63Smrg { 73334345a63Smrg if ((merge != MergeAugment) || (into->groupNames[i] == None)) 73434345a63Smrg into->groupNames[i] = from->groupNames[i]; 73534345a63Smrg } 73634345a63Smrg } 73734345a63Smrg for (i = 0, key = from->keys; i < from->nKeys; i++, key++) 73834345a63Smrg { 73934345a63Smrg if (merge != MergeDefault) 74034345a63Smrg key->defs.merge = merge; 74134345a63Smrg if (!AddKeySymbols(into, key, xkb)) 74234345a63Smrg into->errorCount++; 74334345a63Smrg } 74434345a63Smrg if (from->modMap != NULL) 74534345a63Smrg { 74634345a63Smrg ModMapEntry *mm, *next; 74734345a63Smrg for (mm = from->modMap; mm != NULL; mm = next) 74834345a63Smrg { 74934345a63Smrg if (merge != MergeDefault) 75034345a63Smrg mm->defs.merge = merge; 75134345a63Smrg if (!AddModMapEntry(into, mm)) 75234345a63Smrg into->errorCount++; 75334345a63Smrg next = (ModMapEntry *) mm->defs.next; 75434345a63Smrg uFree(mm); 75534345a63Smrg } 75634345a63Smrg from->modMap = NULL; 75734345a63Smrg } 75834345a63Smrg if (!MergeAliases(&into->aliases, &from->aliases, merge)) 75934345a63Smrg into->errorCount++; 760f46a6179Smrg return; 761f46a6179Smrg} 762f46a6179Smrg 76334345a63Smrgtypedef void (*FileHandler) (XkbFile * /* rtrn */ , 76434345a63Smrg XkbDescPtr /* xkb */ , 76534345a63Smrg unsigned /* merge */ , 76634345a63Smrg SymbolsInfo * /* included */ 76734345a63Smrg ); 768f46a6179Smrg 769f46a6179Smrgstatic Bool 77034345a63SmrgHandleIncludeSymbols(IncludeStmt * stmt, 77134345a63Smrg XkbDescPtr xkb, SymbolsInfo * info, FileHandler hndlr) 772f46a6179Smrg{ 77334345a63Smrg unsigned newMerge; 77434345a63Smrg XkbFile *rtrn; 77534345a63Smrg SymbolsInfo included; 77634345a63Smrg Bool haveSelf; 77734345a63Smrg 77834345a63Smrg haveSelf = False; 77934345a63Smrg if ((stmt->file == NULL) && (stmt->map == NULL)) 78034345a63Smrg { 78134345a63Smrg haveSelf = True; 78234345a63Smrg included = *info; 78334345a63Smrg bzero(info, sizeof(SymbolsInfo)); 78434345a63Smrg } 78534345a63Smrg else if (ProcessIncludeFile(stmt, XkmSymbolsIndex, &rtrn, &newMerge)) 78634345a63Smrg { 78734345a63Smrg InitSymbolsInfo(&included, xkb); 78834345a63Smrg included.fileID = included.dflt.defs.fileID = rtrn->id; 78934345a63Smrg included.merge = included.dflt.defs.merge = MergeOverride; 79034345a63Smrg if (stmt->modifier) 79134345a63Smrg { 79234345a63Smrg included.explicit_group = atoi(stmt->modifier) - 1; 79334345a63Smrg } 79434345a63Smrg else 79534345a63Smrg { 79634345a63Smrg included.explicit_group = info->explicit_group; 79734345a63Smrg } 79834345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &included); 79934345a63Smrg if (stmt->stmt != NULL) 80034345a63Smrg { 80134345a63Smrg if (included.name != NULL) 80234345a63Smrg uFree(included.name); 80334345a63Smrg included.name = stmt->stmt; 80434345a63Smrg stmt->stmt = NULL; 80534345a63Smrg } 80634345a63Smrg } 80734345a63Smrg else 80834345a63Smrg { 80934345a63Smrg info->errorCount += 10; 81034345a63Smrg return False; 81134345a63Smrg } 81234345a63Smrg if ((stmt->next != NULL) && (included.errorCount < 1)) 81334345a63Smrg { 81434345a63Smrg IncludeStmt *next; 81534345a63Smrg unsigned op; 81634345a63Smrg SymbolsInfo next_incl; 81734345a63Smrg 81834345a63Smrg for (next = stmt->next; next != NULL; next = next->next) 81934345a63Smrg { 82034345a63Smrg if ((next->file == NULL) && (next->map == NULL)) 82134345a63Smrg { 82234345a63Smrg haveSelf = True; 82334345a63Smrg MergeIncludedSymbols(&included, info, next->merge, xkb); 82434345a63Smrg FreeSymbolsInfo(info); 82534345a63Smrg } 82634345a63Smrg else if (ProcessIncludeFile(next, XkmSymbolsIndex, &rtrn, &op)) 82734345a63Smrg { 82834345a63Smrg InitSymbolsInfo(&next_incl, xkb); 82934345a63Smrg next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id; 83034345a63Smrg next_incl.merge = next_incl.dflt.defs.merge = MergeOverride; 83134345a63Smrg if (next->modifier) 83234345a63Smrg { 83334345a63Smrg next_incl.explicit_group = atoi(next->modifier) - 1; 83434345a63Smrg } 83534345a63Smrg else 83634345a63Smrg { 83734345a63Smrg next_incl.explicit_group = info->explicit_group; 838f46a6179Smrg } 83934345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); 84034345a63Smrg MergeIncludedSymbols(&included, &next_incl, op, xkb); 84134345a63Smrg FreeSymbolsInfo(&next_incl); 84234345a63Smrg } 84334345a63Smrg else 84434345a63Smrg { 84534345a63Smrg info->errorCount += 10; 84634345a63Smrg return False; 84734345a63Smrg } 84834345a63Smrg } 849f46a6179Smrg } 850f46a6179Smrg if (haveSelf) 85134345a63Smrg *info = included; 85234345a63Smrg else 85334345a63Smrg { 85434345a63Smrg MergeIncludedSymbols(info, &included, newMerge, xkb); 85534345a63Smrg FreeSymbolsInfo(&included); 856f46a6179Smrg } 85734345a63Smrg return (info->errorCount == 0); 858f46a6179Smrg} 859f46a6179Smrg 86034345a63Smrgstatic LookupEntry groupNames[] = { 86134345a63Smrg {"group1", 1}, 86234345a63Smrg {"group2", 2}, 86334345a63Smrg {"group3", 3}, 86434345a63Smrg {"group4", 4}, 86534345a63Smrg {"group5", 5}, 86634345a63Smrg {"group6", 6}, 86734345a63Smrg {"group7", 7}, 86834345a63Smrg {"group8", 8}, 86934345a63Smrg {NULL, 0} 870f46a6179Smrg}; 871f46a6179Smrg 872f46a6179Smrg 873f46a6179Smrg#define SYMBOLS 1 874f46a6179Smrg#define ACTIONS 2 875f46a6179Smrg 876f46a6179Smrgstatic Bool 87734345a63SmrgGetGroupIndex(KeyInfo * key, 87834345a63Smrg ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn) 879f46a6179Smrg{ 88034345a63Smrg const char *name; 88134345a63Smrg ExprResult tmp; 88234345a63Smrg 88334345a63Smrg if (what == SYMBOLS) 88434345a63Smrg name = "symbols"; 88534345a63Smrg else 88634345a63Smrg name = "actions"; 88734345a63Smrg 88834345a63Smrg if (arrayNdx == NULL) 88934345a63Smrg { 89034345a63Smrg register int i; 89134345a63Smrg unsigned defined; 89234345a63Smrg if (what == SYMBOLS) 89334345a63Smrg defined = key->symsDefined; 89434345a63Smrg else 89534345a63Smrg defined = key->actsDefined; 89634345a63Smrg 89734345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 89834345a63Smrg { 89934345a63Smrg if ((defined & (1 << i)) == 0) 90034345a63Smrg { 90134345a63Smrg *ndx_rtrn = i; 90234345a63Smrg return True; 90334345a63Smrg } 90434345a63Smrg } 90534345a63Smrg ERROR3("Too many groups of %s for key %s (max %d)\n", name, 90634345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 90734345a63Smrg ACTION1("Ignoring %s defined for extra groups\n", name); 90834345a63Smrg return False; 90934345a63Smrg } 91034345a63Smrg if (!ExprResolveInteger 91134345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 91234345a63Smrg { 91334345a63Smrg ERROR2("Illegal group index for %s of key %s\n", name, 91434345a63Smrg longText(key->name, XkbMessage)); 91534345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 91634345a63Smrg return False; 91734345a63Smrg } 91834345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 91934345a63Smrg { 92034345a63Smrg ERROR3("Group index for %s of key %s is out of range (1..%d)\n", 92134345a63Smrg name, longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 92234345a63Smrg ACTION2("Ignoring %s for group %d\n", name, tmp.uval); 92334345a63Smrg return False; 92434345a63Smrg } 92534345a63Smrg *ndx_rtrn = tmp.uval - 1; 926f46a6179Smrg return True; 927f46a6179Smrg} 928f46a6179Smrg 929f46a6179Smrgstatic Bool 93034345a63SmrgAddSymbolsToKey(KeyInfo * key, 93134345a63Smrg XkbDescPtr xkb, 932c82dfdfbSmrg const char *field, 93334345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 934f46a6179Smrg{ 93534345a63Smrg unsigned ndx, nSyms; 93634345a63Smrg int i; 93734345a63Smrg 93834345a63Smrg if (!GetGroupIndex(key, arrayNdx, SYMBOLS, &ndx)) 93934345a63Smrg return False; 94034345a63Smrg if (value == NULL) 94134345a63Smrg { 94234345a63Smrg key->symsDefined |= (1 << ndx); 94334345a63Smrg return True; 94434345a63Smrg } 94534345a63Smrg if (value->op != ExprKeysymList) 94634345a63Smrg { 94734345a63Smrg ERROR1("Expected a list of symbols, found %s\n", 94834345a63Smrg exprOpText(value->op)); 94934345a63Smrg ACTION2("Ignoring symbols for group %d of %s\n", ndx, 95034345a63Smrg longText(key->name, XkbMessage)); 95134345a63Smrg return False; 95234345a63Smrg } 95334345a63Smrg if (key->syms[ndx] != NULL) 95434345a63Smrg { 95534345a63Smrg WSGO2("Symbols for key %s, group %d already defined\n", 95634345a63Smrg longText(key->name, XkbMessage), ndx); 95734345a63Smrg return False; 95834345a63Smrg } 95934345a63Smrg nSyms = value->value.list.nSyms; 96034345a63Smrg if (((key->numLevels[ndx] < nSyms) || (key->syms[ndx] == NULL)) && 96134345a63Smrg (!ResizeKeyGroup(key, ndx, nSyms, False))) 96234345a63Smrg { 96334345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 96434345a63Smrg longText(key->name, XkbMessage)); 96534345a63Smrg ACTION("Symbols lost\n"); 96634345a63Smrg return False; 96734345a63Smrg } 96834345a63Smrg key->symsDefined |= (1 << ndx); 96983e5f723Smrg for (i = 0; i < nSyms; i++) { 97083e5f723Smrg if (!LookupKeysym(value->value.list.syms[i], &key->syms[ndx][i])) { 97183e5f723Smrg WSGO1("Could not resolve keysym %s\n", value->value.list.syms[i]); 97283e5f723Smrg key->syms[ndx][i] = NoSymbol; 97383e5f723Smrg } 97483e5f723Smrg } 97534345a63Smrg for (i = key->numLevels[ndx] - 1; 97634345a63Smrg (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--) 97734345a63Smrg { 97834345a63Smrg key->numLevels[ndx]--; 979f46a6179Smrg } 980f46a6179Smrg return True; 981f46a6179Smrg} 982f46a6179Smrg 983f46a6179Smrgstatic Bool 98434345a63SmrgAddActionsToKey(KeyInfo * key, 98534345a63Smrg XkbDescPtr xkb, 986c82dfdfbSmrg const char *field, 98734345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 988f46a6179Smrg{ 98934345a63Smrg register int i; 99034345a63Smrg unsigned ndx, nActs; 99134345a63Smrg ExprDef *act; 99234345a63Smrg XkbAnyAction *toAct; 99334345a63Smrg 99434345a63Smrg if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx)) 99534345a63Smrg return False; 99634345a63Smrg 99734345a63Smrg if (value == NULL) 99834345a63Smrg { 99934345a63Smrg key->actsDefined |= (1 << ndx); 100034345a63Smrg return True; 100134345a63Smrg } 100234345a63Smrg if (value->op != ExprActionList) 100334345a63Smrg { 100434345a63Smrg WSGO1("Bad expression type (%d) for action list value\n", value->op); 100534345a63Smrg ACTION2("Ignoring actions for group %d of %s\n", ndx, 100634345a63Smrg longText(key->name, XkbMessage)); 100734345a63Smrg return False; 100834345a63Smrg } 100934345a63Smrg if (key->acts[ndx] != NULL) 101034345a63Smrg { 101134345a63Smrg WSGO2("Actions for key %s, group %d already defined\n", 101234345a63Smrg longText(key->name, XkbMessage), ndx); 101334345a63Smrg return False; 101434345a63Smrg } 101534345a63Smrg for (nActs = 0, act = value->value.child; act != NULL; nActs++) 101634345a63Smrg { 101734345a63Smrg act = (ExprDef *) act->common.next; 101834345a63Smrg } 101934345a63Smrg if (nActs < 1) 102034345a63Smrg { 102134345a63Smrg WSGO("Action list but not actions in AddActionsToKey\n"); 102234345a63Smrg return False; 102334345a63Smrg } 102434345a63Smrg if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) && 102534345a63Smrg (!ResizeKeyGroup(key, ndx, nActs, True))) 102634345a63Smrg { 102734345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 102834345a63Smrg longText(key->name, XkbMessage)); 102934345a63Smrg ACTION("Actions lost\n"); 103034345a63Smrg return False; 103134345a63Smrg } 103234345a63Smrg key->actsDefined |= (1 << ndx); 103334345a63Smrg 103434345a63Smrg toAct = (XkbAnyAction *) key->acts[ndx]; 103534345a63Smrg act = value->value.child; 103634345a63Smrg for (i = 0; i < nActs; i++, toAct++) 103734345a63Smrg { 103834345a63Smrg if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action)) 103934345a63Smrg { 104034345a63Smrg ERROR1("Illegal action definition for %s\n", 104134345a63Smrg longText(key->name, XkbMessage)); 104234345a63Smrg ACTION2("Action for group %d/level %d ignored\n", ndx + 1, i + 1); 104334345a63Smrg } 104434345a63Smrg act = (ExprDef *) act->common.next; 1045f46a6179Smrg } 1046f46a6179Smrg return True; 1047f46a6179Smrg} 1048f46a6179Smrg 1049f46a6179Smrgstatic int 105034345a63SmrgSetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value) 1051f46a6179Smrg{ 105234345a63Smrg ExprResult tmp; 105334345a63Smrg unsigned radio_groups = 0; 105434345a63Smrg 105534345a63Smrg if (arrayNdx == NULL) 105634345a63Smrg { 105734345a63Smrg radio_groups = XkbAllRadioGroupsMask; 105834345a63Smrg } 105934345a63Smrg else 106034345a63Smrg { 106134345a63Smrg if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL)) 106234345a63Smrg { 106334345a63Smrg ERROR("Illegal index in group name definition\n"); 106434345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 106534345a63Smrg return False; 106634345a63Smrg } 106734345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 106834345a63Smrg { 106934345a63Smrg ERROR1("Illegal radio group specified (must be 1..%d)\n", 107034345a63Smrg XkbMaxRadioGroups + 1); 107134345a63Smrg ACTION1("Value of \"allow none\" for group %d ignored\n", 107234345a63Smrg tmp.uval); 107334345a63Smrg return False; 107434345a63Smrg } 107534345a63Smrg radio_groups |= (1 << (tmp.uval - 1)); 107634345a63Smrg } 107734345a63Smrg if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) 107834345a63Smrg { 107934345a63Smrg ERROR1("Illegal \"allow none\" value for %s\n", 108034345a63Smrg longText(key->name, XkbMessage)); 108134345a63Smrg ACTION("Non-boolean value ignored\n"); 108234345a63Smrg return False; 108334345a63Smrg } 108434345a63Smrg if (tmp.uval) 108534345a63Smrg key->allowNone |= radio_groups; 108634345a63Smrg else 108734345a63Smrg key->allowNone &= ~radio_groups; 1088f46a6179Smrg return True; 1089f46a6179Smrg} 1090f46a6179Smrg 1091f46a6179Smrg 109234345a63Smrgstatic LookupEntry lockingEntries[] = { 109334345a63Smrg {"true", XkbKB_Lock}, 109434345a63Smrg {"yes", XkbKB_Lock}, 109534345a63Smrg {"on", XkbKB_Lock}, 109634345a63Smrg {"false", XkbKB_Default}, 109734345a63Smrg {"no", XkbKB_Default}, 109834345a63Smrg {"off", XkbKB_Default}, 109934345a63Smrg {"permanent", XkbKB_Lock | XkbKB_Permanent}, 110034345a63Smrg {NULL, 0} 1101f46a6179Smrg}; 1102f46a6179Smrg 110334345a63Smrgstatic LookupEntry repeatEntries[] = { 110434345a63Smrg {"true", RepeatYes}, 110534345a63Smrg {"yes", RepeatYes}, 110634345a63Smrg {"on", RepeatYes}, 110734345a63Smrg {"false", RepeatNo}, 110834345a63Smrg {"no", RepeatNo}, 110934345a63Smrg {"off", RepeatNo}, 111034345a63Smrg {"default", RepeatUndefined}, 111134345a63Smrg {NULL, 0} 1112f46a6179Smrg}; 1113f46a6179Smrg 111434345a63Smrgstatic LookupEntry rgEntries[] = { 111534345a63Smrg {"none", 0}, 111634345a63Smrg {NULL, 0} 1117f46a6179Smrg}; 1118f46a6179Smrg 1119f46a6179Smrgstatic Bool 112034345a63SmrgSetSymbolsField(KeyInfo * key, 112134345a63Smrg XkbDescPtr xkb, 1122c82dfdfbSmrg const char *field, 112334345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 1124f46a6179Smrg{ 112534345a63Smrg Bool ok = True; 112634345a63Smrg ExprResult tmp; 112734345a63Smrg 112834345a63Smrg if (uStrCaseCmp(field, "type") == 0) 112934345a63Smrg { 113034345a63Smrg ExprResult ndx; 113134345a63Smrg if ((!ExprResolveString(value, &tmp, NULL, NULL)) 113234345a63Smrg && (warningLevel > 0)) 113334345a63Smrg { 113434345a63Smrg WARN("The type field of a key symbol map must be a string\n"); 113534345a63Smrg ACTION("Ignoring illegal type definition\n"); 113634345a63Smrg } 113734345a63Smrg if (arrayNdx == NULL) 113834345a63Smrg { 113934345a63Smrg key->dfltType = XkbInternAtom(NULL, tmp.str, False); 114034345a63Smrg key->defs.defined |= _Key_Type_Dflt; 114134345a63Smrg } 114234345a63Smrg else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup, 114334345a63Smrg (XPointer) groupNames)) 114434345a63Smrg { 114534345a63Smrg ERROR1("Illegal group index for type of key %s\n", 114634345a63Smrg longText(key->name, XkbMessage)); 114734345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 114834345a63Smrg return False; 114934345a63Smrg } 115034345a63Smrg else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups)) 115134345a63Smrg { 115234345a63Smrg ERROR2 115334345a63Smrg ("Group index for type of key %s is out of range (1..%d)\n", 115434345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 115534345a63Smrg ACTION1("Ignoring type for group %d\n", ndx.uval); 115634345a63Smrg return False; 115734345a63Smrg } 115834345a63Smrg else 115934345a63Smrg { 116034345a63Smrg key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False); 116134345a63Smrg key->typesDefined |= (1 << (ndx.uval - 1)); 116234345a63Smrg } 116334345a63Smrg } 116434345a63Smrg else if (uStrCaseCmp(field, "symbols") == 0) 116534345a63Smrg return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info); 116634345a63Smrg else if (uStrCaseCmp(field, "actions") == 0) 116734345a63Smrg return AddActionsToKey(key, xkb, field, arrayNdx, value, info); 116834345a63Smrg else if ((uStrCaseCmp(field, "vmods") == 0) || 116934345a63Smrg (uStrCaseCmp(field, "virtualmods") == 0) || 117034345a63Smrg (uStrCaseCmp(field, "virtualmodifiers") == 0)) 117134345a63Smrg { 117234345a63Smrg ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb); 117334345a63Smrg if (ok) 117434345a63Smrg { 117534345a63Smrg key->vmodmap = (tmp.uval >> 8); 117634345a63Smrg key->defs.defined |= _Key_VModMap; 117734345a63Smrg } 117834345a63Smrg else 117934345a63Smrg { 118034345a63Smrg ERROR1("Expected a virtual modifier mask, found %s\n", 118134345a63Smrg exprOpText(value->op)); 118234345a63Smrg ACTION1("Ignoring virtual modifiers definition for key %s\n", 118334345a63Smrg longText(key->name, XkbMessage)); 118434345a63Smrg } 118534345a63Smrg } 118634345a63Smrg else if ((uStrCaseCmp(field, "locking") == 0) 118734345a63Smrg || (uStrCaseCmp(field, "lock") == 0) 118834345a63Smrg || (uStrCaseCmp(field, "locks") == 0)) 118934345a63Smrg { 119034345a63Smrg ok = ExprResolveEnum(value, &tmp, lockingEntries); 119134345a63Smrg if (ok) 119234345a63Smrg key->behavior.type = tmp.uval; 119334345a63Smrg key->defs.defined |= _Key_Behavior; 119434345a63Smrg } 119534345a63Smrg else if ((uStrCaseCmp(field, "radiogroup") == 0) || 119634345a63Smrg (uStrCaseCmp(field, "permanentradiogroup") == 0)) 119734345a63Smrg { 119834345a63Smrg Bool permanent = False; 119934345a63Smrg if (uStrCaseCmp(field, "permanentradiogroup") == 0) 120034345a63Smrg permanent = True; 120134345a63Smrg ok = ExprResolveInteger(value, &tmp, SimpleLookup, 120234345a63Smrg (XPointer) rgEntries); 120334345a63Smrg if (!ok) 120434345a63Smrg { 120534345a63Smrg ERROR1("Illegal radio group specification for %s\n", 120634345a63Smrg longText(key->name, XkbMessage)); 120734345a63Smrg ACTION("Non-integer radio group ignored\n"); 120834345a63Smrg return False; 120934345a63Smrg } 121034345a63Smrg if (tmp.uval == 0) 121134345a63Smrg { 121234345a63Smrg key->behavior.type = XkbKB_Default; 121334345a63Smrg key->behavior.data = 0; 121434345a63Smrg return ok; 121534345a63Smrg } 121634345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 121734345a63Smrg { 121834345a63Smrg ERROR1 121934345a63Smrg ("Radio group specification for %s out of range (1..32)\n", 122034345a63Smrg longText(key->name, XkbMessage)); 122134345a63Smrg ACTION1("Illegal radio group %d ignored\n", tmp.uval); 122234345a63Smrg return False; 122334345a63Smrg } 122434345a63Smrg key->behavior.type = 122534345a63Smrg XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0); 122634345a63Smrg key->behavior.data = tmp.uval - 1; 122734345a63Smrg if (key->allowNone & (1 << (tmp.uval - 1))) 122834345a63Smrg key->behavior.data |= XkbKB_RGAllowNone; 122934345a63Smrg key->defs.defined |= _Key_Behavior; 123034345a63Smrg } 123134345a63Smrg else if (uStrCaseEqual(field, "allownone")) 123234345a63Smrg { 123334345a63Smrg ok = SetAllowNone(key, arrayNdx, value); 123434345a63Smrg } 123534345a63Smrg else if (uStrCasePrefix("overlay", field) || 123634345a63Smrg uStrCasePrefix("permanentoverlay", field)) 123734345a63Smrg { 123834345a63Smrg Bool permanent = False; 1239c82dfdfbSmrg const char *which; 124034345a63Smrg int overlayNdx; 124134345a63Smrg if (uStrCasePrefix("permanent", field)) 124234345a63Smrg { 124334345a63Smrg permanent = True; 124434345a63Smrg which = &field[sizeof("permanentoverlay") - 1]; 124534345a63Smrg } 124634345a63Smrg else 124734345a63Smrg { 124834345a63Smrg which = &field[sizeof("overlay") - 1]; 124934345a63Smrg } 125034345a63Smrg if (sscanf(which, "%d", &overlayNdx) == 1) 125134345a63Smrg { 125234345a63Smrg if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0)) 125334345a63Smrg { 125434345a63Smrg ERROR2("Illegal overlay %d specified for %s\n", 125534345a63Smrg overlayNdx, longText(key->name, XkbMessage)); 125634345a63Smrg ACTION("Ignored\n"); 125734345a63Smrg return False; 125834345a63Smrg } 125934345a63Smrg } 126034345a63Smrg else if (*which == '\0') 126134345a63Smrg overlayNdx = 1; 126234345a63Smrg else if (warningLevel > 0) 126334345a63Smrg { 126434345a63Smrg ERROR2("Illegal overlay \"%s\" specified for %s\n", 126534345a63Smrg which, longText(key->name, XkbMessage)); 126634345a63Smrg ACTION("Ignored\n"); 126734345a63Smrg return False; 126834345a63Smrg } 126934345a63Smrg ok = ExprResolveKeyName(value, &tmp, NULL, NULL); 127034345a63Smrg if (!ok) 127134345a63Smrg { 127234345a63Smrg ERROR1("Illegal overlay key specification for %s\n", 127334345a63Smrg longText(key->name, XkbMessage)); 127434345a63Smrg ACTION("Overlay key must be specified by name\n"); 127534345a63Smrg return False; 127634345a63Smrg } 127734345a63Smrg if (overlayNdx == 1) 127834345a63Smrg key->behavior.type = XkbKB_Overlay1; 127934345a63Smrg else 128034345a63Smrg key->behavior.type = XkbKB_Overlay2; 128134345a63Smrg if (permanent) 128234345a63Smrg key->behavior.type |= XkbKB_Permanent; 128334345a63Smrg 128434345a63Smrg key->behavior.data = 0; 128534345a63Smrg key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name); 128634345a63Smrg key->defs.defined |= _Key_Behavior; 128734345a63Smrg } 128834345a63Smrg else if ((uStrCaseCmp(field, "repeating") == 0) || 128934345a63Smrg (uStrCaseCmp(field, "repeats") == 0) || 129034345a63Smrg (uStrCaseCmp(field, "repeat") == 0)) 129134345a63Smrg { 129234345a63Smrg ok = ExprResolveEnum(value, &tmp, repeatEntries); 129334345a63Smrg if (!ok) 129434345a63Smrg { 129534345a63Smrg ERROR1("Illegal repeat setting for %s\n", 129634345a63Smrg longText(key->name, XkbMessage)); 129734345a63Smrg ACTION("Non-boolean repeat setting ignored\n"); 129834345a63Smrg return False; 129934345a63Smrg } 130034345a63Smrg key->repeat = tmp.uval; 130134345a63Smrg key->defs.defined |= _Key_Repeat; 130234345a63Smrg } 130334345a63Smrg else if ((uStrCaseCmp(field, "groupswrap") == 0) || 130434345a63Smrg (uStrCaseCmp(field, "wrapgroups") == 0)) 130534345a63Smrg { 130634345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 130734345a63Smrg if (!ok) 130834345a63Smrg { 130934345a63Smrg ERROR1("Illegal groupsWrap setting for %s\n", 131034345a63Smrg longText(key->name, XkbMessage)); 131134345a63Smrg ACTION("Non-boolean value ignored\n"); 131234345a63Smrg return False; 131334345a63Smrg } 131434345a63Smrg if (tmp.uval) 131534345a63Smrg key->groupInfo = XkbWrapIntoRange; 131634345a63Smrg else 131734345a63Smrg key->groupInfo = XkbClampIntoRange; 131834345a63Smrg key->defs.defined |= _Key_GroupInfo; 131934345a63Smrg } 132034345a63Smrg else if ((uStrCaseCmp(field, "groupsclamp") == 0) || 132134345a63Smrg (uStrCaseCmp(field, "clampgroups") == 0)) 132234345a63Smrg { 132334345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 132434345a63Smrg if (!ok) 132534345a63Smrg { 132634345a63Smrg ERROR1("Illegal groupsClamp setting for %s\n", 132734345a63Smrg longText(key->name, XkbMessage)); 132834345a63Smrg ACTION("Non-boolean value ignored\n"); 132934345a63Smrg return False; 133034345a63Smrg } 133134345a63Smrg if (tmp.uval) 133234345a63Smrg key->groupInfo = XkbClampIntoRange; 133334345a63Smrg else 133434345a63Smrg key->groupInfo = XkbWrapIntoRange; 133534345a63Smrg key->defs.defined |= _Key_GroupInfo; 133634345a63Smrg } 133734345a63Smrg else if ((uStrCaseCmp(field, "groupsredirect") == 0) || 133834345a63Smrg (uStrCaseCmp(field, "redirectgroups") == 0)) 133934345a63Smrg { 134034345a63Smrg if (!ExprResolveInteger 134134345a63Smrg (value, &tmp, SimpleLookup, (XPointer) groupNames)) 134234345a63Smrg { 134334345a63Smrg ERROR1("Illegal group index for redirect of key %s\n", 134434345a63Smrg longText(key->name, XkbMessage)); 134534345a63Smrg ACTION("Definition with non-integer group ignored\n"); 134634345a63Smrg return False; 134734345a63Smrg } 134834345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 134934345a63Smrg { 135034345a63Smrg ERROR2("Out-of-range (1..%d) group for redirect of key %s\n", 135134345a63Smrg XkbNumKbdGroups, longText(key->name, XkbMessage)); 135234345a63Smrg ERROR1("Ignoring illegal group %d\n", tmp.uval); 135334345a63Smrg return False; 135434345a63Smrg } 135534345a63Smrg key->groupInfo = 135634345a63Smrg XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1); 135734345a63Smrg key->defs.defined |= _Key_GroupInfo; 135834345a63Smrg } 135934345a63Smrg else 136034345a63Smrg { 136134345a63Smrg ERROR1("Unknown field %s in a symbol interpretation\n", field); 136234345a63Smrg ACTION("Definition ignored\n"); 136334345a63Smrg ok = False; 1364f46a6179Smrg } 1365f46a6179Smrg return ok; 1366f46a6179Smrg} 1367f46a6179Smrg 1368f46a6179Smrgstatic int 136934345a63SmrgSetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value) 1370f46a6179Smrg{ 137134345a63Smrg ExprResult tmp, name; 137234345a63Smrg 137334345a63Smrg if ((arrayNdx == NULL) && (warningLevel > 0)) 137434345a63Smrg { 137534345a63Smrg WARN("You must specify an index when specifying a group name\n"); 137634345a63Smrg ACTION("Group name definition without array subscript ignored\n"); 137734345a63Smrg return False; 137834345a63Smrg } 137934345a63Smrg if (!ExprResolveInteger 138034345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 138134345a63Smrg { 138234345a63Smrg ERROR("Illegal index in group name definition\n"); 138334345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 138434345a63Smrg return False; 138534345a63Smrg } 138634345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 138734345a63Smrg { 138834345a63Smrg ERROR1 138934345a63Smrg ("Attempt to specify name for illegal group (must be 1..%d)\n", 139034345a63Smrg XkbNumKbdGroups + 1); 139134345a63Smrg ACTION1("Name for group %d ignored\n", tmp.uval); 139234345a63Smrg return False; 139334345a63Smrg } 139434345a63Smrg if (!ExprResolveString(value, &name, NULL, NULL)) 139534345a63Smrg { 139634345a63Smrg ERROR("Group name must be a string\n"); 139734345a63Smrg ACTION1("Illegal name for group %d ignored\n", tmp.uval); 139834345a63Smrg return False; 139934345a63Smrg } 140034345a63Smrg info->groupNames[tmp.uval - 1 + info->explicit_group] = 140134345a63Smrg XkbInternAtom(NULL, name.str, False); 140234345a63Smrg 1403f46a6179Smrg return True; 1404f46a6179Smrg} 1405f46a6179Smrg 1406f46a6179Smrgstatic int 140734345a63SmrgHandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info) 1408f46a6179Smrg{ 140934345a63Smrg ExprResult elem, field, tmp; 141034345a63Smrg ExprDef *arrayNdx; 141134345a63Smrg 141234345a63Smrg if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0) 141334345a63Smrg return 0; /* internal error, already reported */ 141434345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) 141534345a63Smrg { 141634345a63Smrg return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx, 141734345a63Smrg stmt->value, info); 141834345a63Smrg } 141934345a63Smrg else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) || 142034345a63Smrg (uStrCaseCmp(field.str, "groupname") == 142134345a63Smrg 0))) 142234345a63Smrg { 142334345a63Smrg return SetGroupName(info, arrayNdx, stmt->value); 142434345a63Smrg } 142534345a63Smrg else if ((elem.str == NULL) 142634345a63Smrg && ((uStrCaseCmp(field.str, "groupswrap") == 0) 142734345a63Smrg || (uStrCaseCmp(field.str, "wrapgroups") == 0))) 142834345a63Smrg { 142934345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 143034345a63Smrg { 143134345a63Smrg ERROR("Illegal setting for global groupsWrap\n"); 143234345a63Smrg ACTION("Non-boolean value ignored\n"); 143334345a63Smrg return False; 143434345a63Smrg } 143534345a63Smrg if (tmp.uval) 143634345a63Smrg info->groupInfo = XkbWrapIntoRange; 143734345a63Smrg else 143834345a63Smrg info->groupInfo = XkbClampIntoRange; 143934345a63Smrg return True; 144034345a63Smrg } 144134345a63Smrg else if ((elem.str == NULL) 144234345a63Smrg && ((uStrCaseCmp(field.str, "groupsclamp") == 0) 144334345a63Smrg || (uStrCaseCmp(field.str, "clampgroups") == 0))) 144434345a63Smrg { 144534345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 144634345a63Smrg { 144734345a63Smrg ERROR("Illegal setting for global groupsClamp\n"); 144834345a63Smrg ACTION("Non-boolean value ignored\n"); 144934345a63Smrg return False; 145034345a63Smrg } 145134345a63Smrg if (tmp.uval) 145234345a63Smrg info->groupInfo = XkbClampIntoRange; 145334345a63Smrg else 145434345a63Smrg info->groupInfo = XkbWrapIntoRange; 145534345a63Smrg return True; 145634345a63Smrg } 145734345a63Smrg else if ((elem.str == NULL) 145834345a63Smrg && ((uStrCaseCmp(field.str, "groupsredirect") == 0) 145934345a63Smrg || (uStrCaseCmp(field.str, "redirectgroups") == 0))) 146034345a63Smrg { 146134345a63Smrg if (!ExprResolveInteger(stmt->value, &tmp, 146234345a63Smrg SimpleLookup, (XPointer) groupNames)) 146334345a63Smrg { 146434345a63Smrg ERROR("Illegal group index for global groupsRedirect\n"); 146534345a63Smrg ACTION("Definition with non-integer group ignored\n"); 146634345a63Smrg return False; 146734345a63Smrg } 146834345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 146934345a63Smrg { 147034345a63Smrg ERROR1 147134345a63Smrg ("Out-of-range (1..%d) group for global groupsRedirect\n", 147234345a63Smrg XkbNumKbdGroups); 147334345a63Smrg ACTION1("Ignoring illegal group %d\n", tmp.uval); 147434345a63Smrg return False; 147534345a63Smrg } 147634345a63Smrg info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval); 147734345a63Smrg return True; 147834345a63Smrg } 147934345a63Smrg else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0)) 148034345a63Smrg { 148134345a63Smrg return SetAllowNone(&info->dflt, arrayNdx, stmt->value); 148234345a63Smrg } 148334345a63Smrg return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value, 148434345a63Smrg &info->action); 1485f46a6179Smrg} 1486f46a6179Smrg 1487f46a6179Smrgstatic Bool 148834345a63SmrgHandleSymbolsBody(VarDef * def, 148934345a63Smrg XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info) 1490f46a6179Smrg{ 149134345a63Smrg Bool ok = True; 149234345a63Smrg ExprResult tmp, field; 149334345a63Smrg ExprDef *arrayNdx; 149434345a63Smrg 149534345a63Smrg for (; def != NULL; def = (VarDef *) def->common.next) 149634345a63Smrg { 149734345a63Smrg if ((def->name) && (def->name->type == ExprFieldRef)) 149834345a63Smrg { 149934345a63Smrg ok = HandleSymbolsVar(def, xkb, info); 150034345a63Smrg continue; 150134345a63Smrg } 150234345a63Smrg else 150334345a63Smrg { 150434345a63Smrg if (def->name == NULL) 150534345a63Smrg { 150634345a63Smrg if ((def->value == NULL) 150734345a63Smrg || (def->value->op == ExprKeysymList)) 150834345a63Smrg field.str = "symbols"; 150934345a63Smrg else 151034345a63Smrg field.str = "actions"; 151134345a63Smrg arrayNdx = NULL; 151234345a63Smrg } 151334345a63Smrg else 151434345a63Smrg { 151534345a63Smrg ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); 151634345a63Smrg } 151734345a63Smrg if (ok) 151834345a63Smrg ok = SetSymbolsField(key, xkb, field.str, arrayNdx, 151934345a63Smrg def->value, info); 152034345a63Smrg } 1521f46a6179Smrg } 1522f46a6179Smrg return ok; 1523f46a6179Smrg} 1524f46a6179Smrg 1525f46a6179Smrgstatic Bool 152634345a63SmrgSetExplicitGroup(SymbolsInfo * info, KeyInfo * key) 1527f46a6179Smrg{ 1528f46a6179Smrg unsigned group = info->explicit_group; 1529f46a6179Smrg 1530f46a6179Smrg if (group == 0) 153134345a63Smrg return True; 153234345a63Smrg 153334345a63Smrg if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1) 153434345a63Smrg { 153534345a63Smrg int i; 153634345a63Smrg WARN1("For the map %s an explicit group specified\n", info->name); 153734345a63Smrg WARN1("but key %s has more than one group defined\n", 153834345a63Smrg longText(key->name, XkbMessage)); 153934345a63Smrg ACTION("All groups except first one will be ignored\n"); 154034345a63Smrg for (i = 1; i < XkbNumKbdGroups; i++) 154134345a63Smrg { 154234345a63Smrg key->numLevels[i] = 0; 154334345a63Smrg if (key->syms[i] != NULL) 154434345a63Smrg uFree(key->syms[i]); 154534345a63Smrg key->syms[i] = (KeySym *) NULL; 154634345a63Smrg if (key->acts[i] != NULL) 154734345a63Smrg uFree(key->acts[i]); 154834345a63Smrg key->acts[i] = (XkbAction *) NULL; 154934345a63Smrg key->types[i] = (Atom) 0; 155034345a63Smrg } 155134345a63Smrg } 155234345a63Smrg key->typesDefined = key->symsDefined = key->actsDefined = 1 << group; 155334345a63Smrg 155434345a63Smrg key->numLevels[group] = key->numLevels[0]; 155534345a63Smrg key->numLevels[0] = 0; 155634345a63Smrg key->syms[group] = key->syms[0]; 155734345a63Smrg key->syms[0] = (KeySym *) NULL; 155834345a63Smrg key->acts[group] = key->acts[0]; 155934345a63Smrg key->acts[0] = (XkbAction *) NULL; 156034345a63Smrg key->types[group] = key->types[0]; 156134345a63Smrg key->types[0] = (Atom) 0; 156234345a63Smrg return True; 1563f46a6179Smrg} 1564f46a6179Smrg 1565f46a6179Smrgstatic int 156634345a63SmrgHandleSymbolsDef(SymbolsDef * stmt, 156734345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1568f46a6179Smrg{ 156934345a63Smrg KeyInfo key; 157034345a63Smrg 1571f46a6179Smrg InitKeyInfo(&key); 157234345a63Smrg CopyKeyInfo(&info->dflt, &key, False); 157334345a63Smrg key.defs.merge = stmt->merge; 157434345a63Smrg key.name = KeyNameToLong(stmt->keyName); 157534345a63Smrg if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info)) 157634345a63Smrg { 157734345a63Smrg info->errorCount++; 157834345a63Smrg return False; 1579f46a6179Smrg } 1580f46a6179Smrg 158134345a63Smrg if (!SetExplicitGroup(info, &key)) 158234345a63Smrg { 1583f46a6179Smrg info->errorCount++; 1584f46a6179Smrg return False; 1585f46a6179Smrg } 1586f46a6179Smrg 158734345a63Smrg if (!AddKeySymbols(info, &key, xkb)) 158834345a63Smrg { 158934345a63Smrg info->errorCount++; 159034345a63Smrg return False; 1591f46a6179Smrg } 1592f46a6179Smrg return True; 1593f46a6179Smrg} 1594f46a6179Smrg 1595f46a6179Smrgstatic Bool 159634345a63SmrgHandleModMapDef(ModMapDef * def, 159734345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1598f46a6179Smrg{ 159934345a63Smrg ExprDef *key; 160034345a63Smrg ModMapEntry tmp; 160134345a63Smrg ExprResult rtrn; 160234345a63Smrg Bool ok; 160334345a63Smrg 160434345a63Smrg if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn)) 160534345a63Smrg { 160634345a63Smrg ERROR("Illegal modifier map definition\n"); 160734345a63Smrg ACTION1("Ignoring map for non-modifier \"%s\"\n", 160834345a63Smrg XkbAtomText(NULL, def->modifier, XkbMessage)); 160934345a63Smrg return False; 161034345a63Smrg } 161134345a63Smrg ok = True; 161234345a63Smrg tmp.modifier = rtrn.uval; 161334345a63Smrg for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) 161434345a63Smrg { 161534345a63Smrg if ((key->op == ExprValue) && (key->type == TypeKeyName)) 161634345a63Smrg { 161734345a63Smrg tmp.haveSymbol = False; 161834345a63Smrg tmp.u.keyName = KeyNameToLong(key->value.keyName); 161934345a63Smrg } 162034345a63Smrg else if (ExprResolveKeySym(key, &rtrn, NULL, NULL)) 162134345a63Smrg { 162234345a63Smrg tmp.haveSymbol = True; 162334345a63Smrg tmp.u.keySym = rtrn.uval; 162434345a63Smrg } 162534345a63Smrg else 162634345a63Smrg { 162734345a63Smrg ERROR("Modmap entries may contain only key names or keysyms\n"); 162834345a63Smrg ACTION1("Illegal definition for %s modifier ignored\n", 162934345a63Smrg XkbModIndexText(tmp.modifier, XkbMessage)); 163034345a63Smrg continue; 163134345a63Smrg } 163234345a63Smrg 163334345a63Smrg ok = AddModMapEntry(info, &tmp) && ok; 1634f46a6179Smrg } 1635f46a6179Smrg return ok; 1636f46a6179Smrg} 1637f46a6179Smrg 1638f46a6179Smrgstatic void 163934345a63SmrgHandleSymbolsFile(XkbFile * file, 164034345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1641f46a6179Smrg{ 164234345a63Smrg ParseCommon *stmt; 164334345a63Smrg 164434345a63Smrg info->name = uStringDup(file->name); 164534345a63Smrg stmt = file->defs; 164634345a63Smrg while (stmt) 164734345a63Smrg { 164834345a63Smrg switch (stmt->stmtType) 164934345a63Smrg { 165034345a63Smrg case StmtInclude: 165134345a63Smrg if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info, 165234345a63Smrg HandleSymbolsFile)) 165334345a63Smrg info->errorCount++; 165434345a63Smrg break; 165534345a63Smrg case StmtSymbolsDef: 165634345a63Smrg if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info)) 165734345a63Smrg info->errorCount++; 165834345a63Smrg break; 165934345a63Smrg case StmtVarDef: 166034345a63Smrg if (!HandleSymbolsVar((VarDef *) stmt, xkb, info)) 166134345a63Smrg info->errorCount++; 166234345a63Smrg break; 166334345a63Smrg case StmtVModDef: 166434345a63Smrg if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) 166534345a63Smrg info->errorCount++; 166634345a63Smrg break; 166734345a63Smrg case StmtInterpDef: 166834345a63Smrg ERROR("Interpretation files may not include other types\n"); 166934345a63Smrg ACTION("Ignoring definition of symbol interpretation\n"); 167034345a63Smrg info->errorCount++; 167134345a63Smrg break; 167234345a63Smrg case StmtKeycodeDef: 167334345a63Smrg ERROR("Interpretation files may not include other types\n"); 167434345a63Smrg ACTION("Ignoring definition of key name\n"); 167534345a63Smrg info->errorCount++; 167634345a63Smrg break; 167734345a63Smrg case StmtModMapDef: 167834345a63Smrg if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info)) 167934345a63Smrg info->errorCount++; 168034345a63Smrg break; 168134345a63Smrg default: 168234345a63Smrg WSGO1("Unexpected statement type %d in HandleSymbolsFile\n", 168334345a63Smrg stmt->stmtType); 168434345a63Smrg break; 168534345a63Smrg } 168634345a63Smrg stmt = stmt->next; 168734345a63Smrg if (info->errorCount > 10) 168834345a63Smrg { 1689f46a6179Smrg#ifdef NOISY 169034345a63Smrg ERROR("Too many errors\n"); 1691f46a6179Smrg#endif 169234345a63Smrg ACTION1("Abandoning symbols file \"%s\"\n", file->topName); 169334345a63Smrg break; 169434345a63Smrg } 1695f46a6179Smrg } 1696f46a6179Smrg return; 1697f46a6179Smrg} 1698f46a6179Smrg 1699f46a6179Smrgstatic Bool 170034345a63SmrgFindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn) 1701f46a6179Smrg{ 170234345a63Smrg register int i, j; 170334345a63Smrg register Bool gotOne; 170434345a63Smrg 170534345a63Smrg j = 0; 170634345a63Smrg do 170734345a63Smrg { 170834345a63Smrg gotOne = False; 170934345a63Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) 171034345a63Smrg { 171134345a63Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) 171234345a63Smrg { 1713f46a6179Smrg gotOne = True; 17141d8c7986Smrg if (XkbKeySym(xkb, i, j) == sym) 171534345a63Smrg { 171634345a63Smrg *kc_rtrn = i; 1717f46a6179Smrg return True; 171834345a63Smrg } 1719f46a6179Smrg } 1720f46a6179Smrg } 1721f46a6179Smrg j++; 172234345a63Smrg } 172334345a63Smrg while (gotOne); 1724f46a6179Smrg return False; 1725f46a6179Smrg} 1726f46a6179Smrg 172734345a63Smrg/** 172834345a63Smrg * Find the given name in the xkb->map->types and return its index. 172934345a63Smrg * 173034345a63Smrg * @param name The atom to search for. 173134345a63Smrg * @param type_rtrn Set to the index of the name if found. 173234345a63Smrg * 173334345a63Smrg * @return True if found, False otherwise. 173434345a63Smrg */ 1735f46a6179Smrgstatic Bool 173634345a63SmrgFindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn) 1737f46a6179Smrg{ 173834345a63Smrg register unsigned n; 173934345a63Smrg 174034345a63Smrg if (xkb && xkb->map && xkb->map->types) 174134345a63Smrg { 174234345a63Smrg for (n = 0; n < xkb->map->num_types; n++) 174334345a63Smrg { 174434345a63Smrg if (xkb->map->types[n].name == (Atom) name) 174534345a63Smrg { 174634345a63Smrg *type_rtrn = n; 174734345a63Smrg return True; 174834345a63Smrg } 174934345a63Smrg } 1750f46a6179Smrg } 1751f46a6179Smrg return False; 1752f46a6179Smrg} 1753f46a6179Smrg 1754f46a6179Smrgstatic Bool 175534345a63SmrgKSIsLower(KeySym ks) 1756f46a6179Smrg{ 1757f46a6179Smrg KeySym lower, upper; 1758f46a6179Smrg XConvertCase(ks, &lower, &upper); 1759f46a6179Smrg 1760f46a6179Smrg if (lower == upper) 1761f46a6179Smrg return False; 1762f46a6179Smrg return (ks == lower ? True : False); 1763f46a6179Smrg} 1764f46a6179Smrg 1765f46a6179Smrgstatic Bool 176634345a63SmrgKSIsUpper(KeySym ks) 1767f46a6179Smrg{ 1768f46a6179Smrg KeySym lower, upper; 1769f46a6179Smrg XConvertCase(ks, &lower, &upper); 1770f46a6179Smrg 1771f46a6179Smrg if (lower == upper) 1772f46a6179Smrg return False; 1773f46a6179Smrg return (ks == upper ? True : False); 1774f46a6179Smrg} 1775f46a6179Smrg 177634345a63Smrg/** 177734345a63Smrg * Assign a type to the given sym and return the Atom for the type assigned. 177834345a63Smrg * 177934345a63Smrg * Simple recipe: 178034345a63Smrg * - ONE_LEVEL for width 0/1 178134345a63Smrg * - ALPHABETIC for 2 shift levels, with lower/upercase 178234345a63Smrg * - KEYPAD for keypad keys. 178334345a63Smrg * - TWO_LEVEL for other 2 shift level keys. 178434345a63Smrg * and the same for four level keys. 178534345a63Smrg * 178634345a63Smrg * @param width Number of sysms in syms. 178734345a63Smrg * @param syms The keysyms for the given key (must be size width). 178834345a63Smrg * @param typeNameRtrn Set to the Atom of the type name. 178934345a63Smrg * 179034345a63Smrg * @returns True if a type could be found, False otherwise. 179134345a63Smrg */ 1792f46a6179Smrgstatic Bool 179334345a63SmrgFindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn, 179434345a63Smrg Bool * autoType) 1795f46a6179Smrg{ 1796f46a6179Smrg *autoType = False; 179734345a63Smrg if ((width == 1) || (width == 0)) 179834345a63Smrg { 179934345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False); 180034345a63Smrg *autoType = True; 180134345a63Smrg } 180234345a63Smrg else if (width == 2) 180334345a63Smrg { 180434345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 180534345a63Smrg { 180634345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False); 180734345a63Smrg } 180834345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 180934345a63Smrg { 181034345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False); 181134345a63Smrg *autoType = True; 181234345a63Smrg } 181334345a63Smrg else 181434345a63Smrg { 181534345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False); 181634345a63Smrg *autoType = True; 181734345a63Smrg } 181834345a63Smrg } 181934345a63Smrg else if (width <= 4) 182034345a63Smrg { 182134345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 182234345a63Smrg if (KSIsLower(syms[2]) && KSIsUpper(syms[3])) 182334345a63Smrg *typeNameRtrn = 182434345a63Smrg XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False); 182534345a63Smrg else 182634345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, 182734345a63Smrg "FOUR_LEVEL_SEMIALPHABETIC", 182834345a63Smrg False); 182934345a63Smrg 183034345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 183134345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False); 183234345a63Smrg else 183334345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False); 183434345a63Smrg /* XXX: why not set autoType here? */ 183534345a63Smrg } 183634345a63Smrg return ((width >= 0) && (width <= 4)); 1837f46a6179Smrg} 1838f46a6179Smrg 183934345a63Smrg/** 184034345a63Smrg * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the 184134345a63Smrg * groups, and reduce to one group if all groups are identical anyway. 184234345a63Smrg */ 1843f46a6179Smrgstatic void 184434345a63SmrgPrepareKeyDef(KeyInfo * key) 1845f46a6179Smrg{ 1846f46a6179Smrg int i, j, width, defined, lastGroup; 1847f46a6179Smrg Bool identical; 184834345a63Smrg 1849f46a6179Smrg defined = key->symsDefined | key->actsDefined | key->typesDefined; 185034345a63Smrg /* get highest group number */ 185134345a63Smrg for (i = XkbNumKbdGroups - 1; i >= 0; i--) 185234345a63Smrg { 185334345a63Smrg if (defined & (1 << i)) 185434345a63Smrg break; 1855f46a6179Smrg } 1856f46a6179Smrg lastGroup = i; 1857f46a6179Smrg 1858f46a6179Smrg if (lastGroup == 0) 185934345a63Smrg return; 1860f46a6179Smrg 1861f46a6179Smrg /* If there are empty groups between non-empty ones fill them with data */ 1862f46a6179Smrg /* from the first group. */ 1863f46a6179Smrg /* We can make a wrong assumption here. But leaving gaps is worse. */ 186434345a63Smrg for (i = lastGroup; i > 0; i--) 186534345a63Smrg { 186634345a63Smrg if (defined & (1 << i)) 1867f46a6179Smrg continue; 1868f46a6179Smrg width = key->numLevels[0]; 186934345a63Smrg if (key->typesDefined & 1) 187034345a63Smrg { 187134345a63Smrg for (j = 0; j < width; j++) 187234345a63Smrg { 1873f46a6179Smrg key->types[i] = key->types[0]; 1874f46a6179Smrg } 1875f46a6179Smrg key->typesDefined |= 1 << i; 1876f46a6179Smrg } 187734345a63Smrg if ((key->actsDefined & 1) && key->acts[0]) 187834345a63Smrg { 187934345a63Smrg key->acts[i] = uTypedCalloc(width, XkbAction); 1880f46a6179Smrg if (key->acts[i] == NULL) 1881f46a6179Smrg continue; 1882f46a6179Smrg memcpy((void *) key->acts[i], (void *) key->acts[0], 1883f46a6179Smrg width * sizeof(XkbAction)); 1884f46a6179Smrg key->actsDefined |= 1 << i; 1885f46a6179Smrg } 188634345a63Smrg if ((key->symsDefined & 1) && key->syms[0]) 188734345a63Smrg { 188834345a63Smrg key->syms[i] = uTypedCalloc(width, KeySym); 1889f46a6179Smrg if (key->syms[i] == NULL) 1890f46a6179Smrg continue; 1891f46a6179Smrg memcpy((void *) key->syms[i], (void *) key->syms[0], 1892f46a6179Smrg width * sizeof(KeySym)); 1893f46a6179Smrg key->symsDefined |= 1 << i; 1894f46a6179Smrg } 189534345a63Smrg if (defined & 1) 189634345a63Smrg { 1897f46a6179Smrg key->numLevels[i] = key->numLevels[0]; 1898f46a6179Smrg } 1899f46a6179Smrg } 1900f46a6179Smrg /* If all groups are completely identical remove them all */ 1901f46a6179Smrg /* exept the first one. */ 1902f46a6179Smrg identical = True; 190334345a63Smrg for (i = lastGroup; i > 0; i--) 190434345a63Smrg { 1905f46a6179Smrg if ((key->numLevels[i] != key->numLevels[0]) || 190634345a63Smrg (key->types[i] != key->types[0])) 190734345a63Smrg { 1908f46a6179Smrg identical = False; 1909f46a6179Smrg break; 1910f46a6179Smrg } 1911f46a6179Smrg if ((key->syms[i] != key->syms[0]) && 191234345a63Smrg (key->syms[i] == NULL || key->syms[0] == NULL || 191334345a63Smrg memcmp((void *) key->syms[i], (void *) key->syms[0], 191434345a63Smrg sizeof(KeySym) * key->numLevels[0]))) 191534345a63Smrg { 191634345a63Smrg identical = False; 191734345a63Smrg break; 191834345a63Smrg } 1919f46a6179Smrg if ((key->acts[i] != key->acts[0]) && 192034345a63Smrg (key->acts[i] == NULL || key->acts[0] == NULL || 192134345a63Smrg memcmp((void *) key->acts[i], (void *) key->acts[0], 192234345a63Smrg sizeof(XkbAction) * key->numLevels[0]))) 192334345a63Smrg { 1924f46a6179Smrg identical = False; 1925f46a6179Smrg break; 192634345a63Smrg } 192734345a63Smrg } 192834345a63Smrg if (identical) 192934345a63Smrg { 193034345a63Smrg for (i = lastGroup; i > 0; i--) 193134345a63Smrg { 193234345a63Smrg key->numLevels[i] = 0; 193334345a63Smrg if (key->syms[i] != NULL) 193434345a63Smrg uFree(key->syms[i]); 193534345a63Smrg key->syms[i] = (KeySym *) NULL; 193634345a63Smrg if (key->acts[i] != NULL) 193734345a63Smrg uFree(key->acts[i]); 193834345a63Smrg key->acts[i] = (XkbAction *) NULL; 193934345a63Smrg key->types[i] = (Atom) 0; 194034345a63Smrg } 194134345a63Smrg key->symsDefined &= 1; 194234345a63Smrg key->actsDefined &= 1; 194334345a63Smrg key->typesDefined &= 1; 1944f46a6179Smrg } 1945f46a6179Smrg return; 1946f46a6179Smrg} 1947f46a6179Smrg 194834345a63Smrg/** 194934345a63Smrg * Copy the KeyInfo into result. 195034345a63Smrg * 195134345a63Smrg * This function recurses. 195234345a63Smrg */ 1953f46a6179Smrgstatic Bool 195434345a63SmrgCopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from) 1955f46a6179Smrg{ 195634345a63Smrg register int i; 195734345a63Smrg unsigned okc, kc, width, tmp, nGroups; 195834345a63Smrg XkbKeyTypePtr type; 195934345a63Smrg Bool haveActions, autoType, useAlias; 196034345a63Smrg KeySym *outSyms; 196134345a63Smrg XkbAction *outActs; 196234345a63Smrg XkbDescPtr xkb; 196334345a63Smrg unsigned types[XkbNumKbdGroups]; 196434345a63Smrg 196534345a63Smrg xkb = result->xkb; 196634345a63Smrg useAlias = (start_from == 0); 196734345a63Smrg 196834345a63Smrg /* get the keycode for the key. */ 196934345a63Smrg if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb), 197034345a63Smrg start_from)) 197134345a63Smrg { 197234345a63Smrg if ((start_from == 0) && (warningLevel >= 5)) 197334345a63Smrg { 197434345a63Smrg WARN2("Key %s not found in %s keycodes\n", 197534345a63Smrg longText(key->name, XkbMessage), 197634345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 197734345a63Smrg ACTION("Symbols ignored\n"); 197834345a63Smrg } 197934345a63Smrg return False; 198034345a63Smrg } 198134345a63Smrg 198234345a63Smrg haveActions = False; 198334345a63Smrg for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) 198434345a63Smrg { 198534345a63Smrg if (((i + 1) > nGroups) 198634345a63Smrg && (((key->symsDefined | key->actsDefined) & (1 << i)) 198734345a63Smrg || (key->typesDefined) & (1 << i))) 198834345a63Smrg nGroups = i + 1; 198934345a63Smrg if (key->acts[i]) 199034345a63Smrg haveActions = True; 199134345a63Smrg autoType = False; 199234345a63Smrg /* Assign the type to the key, if it is missing. */ 199334345a63Smrg if (key->types[i] == None) 199434345a63Smrg { 199534345a63Smrg if (key->dfltType != None) 199634345a63Smrg key->types[i] = key->dfltType; 199734345a63Smrg else if (FindAutomaticType(key->numLevels[i], key->syms[i], 199834345a63Smrg &key->types[i], &autoType)) 199934345a63Smrg { 200034345a63Smrg } 200134345a63Smrg else 200234345a63Smrg { 200334345a63Smrg if (warningLevel >= 5) 200434345a63Smrg { 200534345a63Smrg WARN1("No automatic type for %d symbols\n", 200634345a63Smrg (unsigned int) key->numLevels[i]); 200734345a63Smrg ACTION3("Using %s for the %s key (keycode %d)\n", 200834345a63Smrg XkbAtomText(NULL, key->types[i], 200934345a63Smrg XkbMessage), 201034345a63Smrg longText(key->name, XkbMessage), kc); 201134345a63Smrg } 201234345a63Smrg } 201334345a63Smrg } 201434345a63Smrg if (FindNamedType(xkb, key->types[i], &types[i])) 201534345a63Smrg { 201634345a63Smrg if (!autoType || key->numLevels[i] > 2) 201734345a63Smrg xkb->server->explicit[kc] |= (1 << i); 201834345a63Smrg } 201934345a63Smrg else 202034345a63Smrg { 202134345a63Smrg if (warningLevel >= 3) 202234345a63Smrg { 202334345a63Smrg WARN1("Type \"%s\" is not defined\n", 202434345a63Smrg XkbAtomText(NULL, key->types[i], XkbMessage)); 202534345a63Smrg ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n", 202634345a63Smrg longText(key->name, XkbMessage), kc); 202734345a63Smrg } 202834345a63Smrg types[i] = XkbTwoLevelIndex; 202934345a63Smrg } 203034345a63Smrg /* if the type specifies less syms than the key has, shrink the key */ 203134345a63Smrg type = &xkb->map->types[types[i]]; 203234345a63Smrg if (type->num_levels < key->numLevels[i]) 203334345a63Smrg { 20343fb1fa07Smrg if (warningLevel > 5) 203534345a63Smrg { 203634345a63Smrg WARN4 203734345a63Smrg ("Type \"%s\" has %d levels, but %s has %d symbols\n", 203834345a63Smrg XkbAtomText(NULL, type->name, XkbMessage), 203934345a63Smrg (unsigned int) type->num_levels, 204034345a63Smrg longText(key->name, XkbMessage), 204134345a63Smrg (unsigned int) key->numLevels[i]); 204234345a63Smrg ACTION("Ignoring extra symbols\n"); 204334345a63Smrg } 204434345a63Smrg key->numLevels[i] = type->num_levels; 204534345a63Smrg } 204634345a63Smrg if (key->numLevels[i] > width) 204734345a63Smrg width = key->numLevels[i]; 204834345a63Smrg if (type->num_levels > width) 204934345a63Smrg width = type->num_levels; 205034345a63Smrg } 205134345a63Smrg 205234345a63Smrg /* width is now the largest width found */ 205334345a63Smrg 205434345a63Smrg i = width * nGroups; 205534345a63Smrg outSyms = XkbResizeKeySyms(xkb, kc, i); 205634345a63Smrg if (outSyms == NULL) 205734345a63Smrg { 205834345a63Smrg WSGO2("Could not enlarge symbols for %s (keycode %d)\n", 205934345a63Smrg longText(key->name, XkbMessage), kc); 206034345a63Smrg return False; 206134345a63Smrg } 206234345a63Smrg if (haveActions) 206334345a63Smrg { 206434345a63Smrg outActs = XkbResizeKeyActions(xkb, kc, i); 206534345a63Smrg if (outActs == NULL) 206634345a63Smrg { 206734345a63Smrg WSGO2("Could not enlarge actions for %s (key %d)\n", 206834345a63Smrg longText(key->name, XkbMessage), kc); 206934345a63Smrg return False; 207034345a63Smrg } 207134345a63Smrg xkb->server->explicit[kc] |= XkbExplicitInterpretMask; 207234345a63Smrg } 207334345a63Smrg else 207434345a63Smrg outActs = NULL; 207534345a63Smrg if (key->defs.defined & _Key_GroupInfo) 207634345a63Smrg i = key->groupInfo; 207734345a63Smrg else 207834345a63Smrg i = xkb->map->key_sym_map[kc].group_info; 207934345a63Smrg 208034345a63Smrg xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups); 208134345a63Smrg xkb->map->key_sym_map[kc].width = width; 208234345a63Smrg for (i = 0; i < nGroups; i++) 208334345a63Smrg { 208434345a63Smrg /* assign kt_index[i] to the index of the type in map->types. 208534345a63Smrg * kt_index[i] may have been set by a previous run (if we have two 208634345a63Smrg * layouts specified). Let's not overwrite it with the ONE_LEVEL 208734345a63Smrg * default group if we dont even have keys for this group anyway. 208834345a63Smrg * 208934345a63Smrg * FIXME: There should be a better fix for this. 209034345a63Smrg */ 209134345a63Smrg if (key->numLevels[i]) 209234345a63Smrg xkb->map->key_sym_map[kc].kt_index[i] = types[i]; 209334345a63Smrg if (key->syms[i] != NULL) 209434345a63Smrg { 209534345a63Smrg /* fill key to "width" symbols*/ 209634345a63Smrg for (tmp = 0; tmp < width; tmp++) 209734345a63Smrg { 209834345a63Smrg if (tmp < key->numLevels[i]) 209934345a63Smrg outSyms[tmp] = key->syms[i][tmp]; 210034345a63Smrg else 210134345a63Smrg outSyms[tmp] = NoSymbol; 210234345a63Smrg if ((outActs != NULL) && (key->acts[i] != NULL)) 210334345a63Smrg { 210434345a63Smrg if (tmp < key->numLevels[i]) 210534345a63Smrg outActs[tmp] = key->acts[i][tmp]; 210634345a63Smrg else 210734345a63Smrg outActs[tmp].type = XkbSA_NoAction; 210834345a63Smrg } 210934345a63Smrg } 211034345a63Smrg } 211134345a63Smrg outSyms += width; 211234345a63Smrg if (outActs) 211334345a63Smrg outActs += width; 211434345a63Smrg } 211534345a63Smrg switch (key->behavior.type & XkbKB_OpMask) 211634345a63Smrg { 211734345a63Smrg case XkbKB_Default: 211834345a63Smrg break; 211934345a63Smrg case XkbKB_Overlay1: 212034345a63Smrg case XkbKB_Overlay2: 212134345a63Smrg /* find key by name! */ 212234345a63Smrg if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True, 212334345a63Smrg CreateKeyNames(xkb), 0)) 212434345a63Smrg { 212534345a63Smrg if (warningLevel >= 1) 212634345a63Smrg { 212734345a63Smrg WARN2("Key %s not found in %s keycodes\n", 212834345a63Smrg longText(key->nameForOverlayKey, XkbMessage), 212934345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 213034345a63Smrg ACTION1("Not treating %s as an overlay key \n", 213134345a63Smrg longText(key->name, XkbMessage)); 213234345a63Smrg } 213334345a63Smrg break; 213434345a63Smrg } 213534345a63Smrg key->behavior.data = okc; 213634345a63Smrg default: 213734345a63Smrg xkb->server->behaviors[kc] = key->behavior; 213834345a63Smrg xkb->server->explicit[kc] |= XkbExplicitBehaviorMask; 213934345a63Smrg break; 214034345a63Smrg } 214134345a63Smrg if (key->defs.defined & _Key_VModMap) 214234345a63Smrg { 214334345a63Smrg xkb->server->vmodmap[kc] = key->vmodmap; 214434345a63Smrg xkb->server->explicit[kc] |= XkbExplicitVModMapMask; 214534345a63Smrg } 214634345a63Smrg if (key->repeat != RepeatUndefined) 214734345a63Smrg { 214834345a63Smrg if (key->repeat == RepeatYes) 214934345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8)); 215034345a63Smrg else 215134345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8)); 215234345a63Smrg xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask; 215334345a63Smrg } 215434345a63Smrg 215534345a63Smrg /* do the same thing for the next key */ 215634345a63Smrg CopySymbolsDef(result, key, kc + 1); 2157f46a6179Smrg return True; 2158f46a6179Smrg} 2159f46a6179Smrg 2160f46a6179Smrgstatic Bool 216134345a63SmrgCopyModMapDef(XkbFileInfo * result, ModMapEntry * entry) 2162f46a6179Smrg{ 216334345a63Smrg unsigned kc; 216434345a63Smrg XkbDescPtr xkb; 216534345a63Smrg 216634345a63Smrg xkb = result->xkb; 216734345a63Smrg if ((!entry->haveSymbol) 216834345a63Smrg && 216934345a63Smrg (!FindNamedKey 217034345a63Smrg (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0))) 217134345a63Smrg { 217234345a63Smrg if (warningLevel >= 5) 217334345a63Smrg { 217434345a63Smrg WARN2("Key %s not found in %s keycodes\n", 217534345a63Smrg longText(entry->u.keyName, XkbMessage), 217634345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 217734345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 217834345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 217934345a63Smrg } 218034345a63Smrg return False; 218134345a63Smrg } 218234345a63Smrg else if (entry->haveSymbol 218334345a63Smrg && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc))) 218434345a63Smrg { 218534345a63Smrg if (warningLevel > 5) 218634345a63Smrg { 218734345a63Smrg WARN2("Key \"%s\" not found in %s symbol map\n", 218834345a63Smrg XkbKeysymText(entry->u.keySym, XkbMessage), 218934345a63Smrg XkbAtomText(NULL, xkb->names->symbols, XkbMessage)); 219034345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 219134345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 219234345a63Smrg } 219334345a63Smrg return False; 219434345a63Smrg } 219534345a63Smrg xkb->map->modmap[kc] |= (1 << entry->modifier); 2196f46a6179Smrg return True; 2197f46a6179Smrg} 2198f46a6179Smrg 219934345a63Smrg/** 220034345a63Smrg * Handle the xkb_symbols section of an xkb file. 220134345a63Smrg * 220234345a63Smrg * @param file The parsed xkb_symbols section of the xkb file. 220334345a63Smrg * @param result Handle to the data to store the result in. 220434345a63Smrg * @param merge Merge strategy (e.g. MergeOverride). 220534345a63Smrg */ 2206f46a6179SmrgBool 220734345a63SmrgCompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge) 2208f46a6179Smrg{ 220934345a63Smrg register int i; 221034345a63Smrg SymbolsInfo info; 221134345a63Smrg XkbDescPtr xkb; 2212f46a6179Smrg 221334345a63Smrg xkb = result->xkb; 221434345a63Smrg InitSymbolsInfo(&info, xkb); 221534345a63Smrg info.dflt.defs.fileID = file->id; 221634345a63Smrg info.dflt.defs.merge = merge; 221734345a63Smrg HandleSymbolsFile(file, xkb, merge, &info); 2218f46a6179Smrg 2219f46a6179Smrg if (info.nKeys == 0) 2220f46a6179Smrg return True; 222134345a63Smrg if (info.errorCount == 0) 222234345a63Smrg { 222334345a63Smrg KeyInfo *key; 222434345a63Smrg 222534345a63Smrg /* alloc memory in the xkb struct */ 222634345a63Smrg if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0) 222734345a63Smrg != Success) 222834345a63Smrg { 222934345a63Smrg WSGO("Can not allocate names in CompileSymbols\n"); 223034345a63Smrg ACTION("Symbols not added\n"); 223134345a63Smrg return False; 223234345a63Smrg } 223334345a63Smrg if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0) 223434345a63Smrg != Success) 223534345a63Smrg { 223634345a63Smrg WSGO("Could not allocate client map in CompileSymbols\n"); 223734345a63Smrg ACTION("Symbols not added\n"); 223834345a63Smrg return False; 223934345a63Smrg } 224034345a63Smrg if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success) 224134345a63Smrg { 224234345a63Smrg WSGO("Could not allocate server map in CompileSymbols\n"); 224334345a63Smrg ACTION("Symbols not added\n"); 224434345a63Smrg return False; 224534345a63Smrg } 224634345a63Smrg if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success) 224734345a63Smrg { 224834345a63Smrg WSGO("Could not allocate controls in CompileSymbols\n"); 224934345a63Smrg ACTION("Symbols not added\n"); 225034345a63Smrg return False; 225134345a63Smrg } 225234345a63Smrg 225334345a63Smrg /* now copy info into xkb. */ 225434345a63Smrg xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False); 225534345a63Smrg if (info.aliases) 225634345a63Smrg ApplyAliases(xkb, False, &info.aliases); 225734345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 225834345a63Smrg { 225934345a63Smrg if (info.groupNames[i] != None) 226034345a63Smrg xkb->names->groups[i] = info.groupNames[i]; 226134345a63Smrg } 226234345a63Smrg /* sanitize keys */ 226334345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 226434345a63Smrg { 226534345a63Smrg PrepareKeyDef(key); 226634345a63Smrg } 226734345a63Smrg /* copy! */ 226834345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 226934345a63Smrg { 227034345a63Smrg if (!CopySymbolsDef(result, key, 0)) 227134345a63Smrg info.errorCount++; 227234345a63Smrg } 227334345a63Smrg if (warningLevel > 3) 227434345a63Smrg { 227534345a63Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) 227634345a63Smrg { 227734345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 227834345a63Smrg continue; 227934345a63Smrg if (XkbKeyNumGroups(xkb, i) < 1) 228034345a63Smrg { 228134345a63Smrg char buf[5]; 228234345a63Smrg memcpy(buf, xkb->names->keys[i].name, 4); 228334345a63Smrg buf[4] = '\0'; 228434345a63Smrg WARN2 228534345a63Smrg ("No symbols defined for <%s> (keycode %d)\n", 228634345a63Smrg buf, i); 228734345a63Smrg } 228834345a63Smrg } 228934345a63Smrg } 229034345a63Smrg if (info.modMap) 229134345a63Smrg { 229234345a63Smrg ModMapEntry *mm, *next; 229334345a63Smrg for (mm = info.modMap; mm != NULL; mm = next) 229434345a63Smrg { 229534345a63Smrg if (!CopyModMapDef(result, mm)) 229634345a63Smrg info.errorCount++; 229734345a63Smrg next = (ModMapEntry *) mm->defs.next; 229834345a63Smrg } 229934345a63Smrg } 230034345a63Smrg return True; 2301f46a6179Smrg } 2302f46a6179Smrg return False; 2303f46a6179Smrg} 2304