symbols.c revision a57d84fe
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 9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be 10bfe6082cSmrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12bfe6082cSmrg 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. 15bfe6082cSmrg 16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21bfe6082cSmrg 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"); 361bfe6082cSmrg ACTION("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"); 372bfe6082cSmrg ACTION("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 { 407bfe6082cSmrg WARN 40834345a63Smrg ("Multiple symbols for level %d/group %d on key %s\n", 40934345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 410bfe6082cSmrg ACTION("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 { 446bfe6082cSmrg WARN 44734345a63Smrg ("Multiple actions for level %d/group %d on key %s\n", 44834345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 449bfe6082cSmrg ACTION("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 } 551bfe6082cSmrg WARN 55234345a63Smrg ("Multiple definitions for group %d type of key %s\n", 55334345a63Smrg i, longText(into->name, XkbMessage)); 554bfe6082cSmrg ACTION("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 } 591a57d84feSmrg if (collide && (warningLevel > 0)) 59234345a63Smrg { 593bfe6082cSmrg WARN("Symbol map for key %s redefined\n", 59434345a63Smrg longText(into->name, XkbMessage)); 595bfe6082cSmrg ACTION("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 } 660bfe6082cSmrg ERROR 66134345a63Smrg ("%s added to symbol map for multiple modifiers\n", 66234345a63Smrg XkbKeysymText(new->u.keySym, XkbMessage)); 663bfe6082cSmrg ACTION("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 } 686bfe6082cSmrg ERROR("Key %s added to map for multiple modifiers\n", 68734345a63Smrg longText(new->u.keyName, XkbMessage)); 688bfe6082cSmrg ACTION("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"); 700bfe6082cSmrg ACTION("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 } 905bfe6082cSmrg ERROR("Too many groups of %s for key %s (max %d)\n", name, 90634345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 907bfe6082cSmrg ACTION("Ignoring %s defined for extra groups\n", name); 90834345a63Smrg return False; 90934345a63Smrg } 91034345a63Smrg if (!ExprResolveInteger 91134345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 91234345a63Smrg { 913bfe6082cSmrg ERROR("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 { 920bfe6082cSmrg ERROR("Group index for %s of key %s is out of range (1..%d)\n", 92134345a63Smrg name, longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 922bfe6082cSmrg ACTION("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 { 947bfe6082cSmrg ERROR("Expected a list of symbols, found %s\n", 94834345a63Smrg exprOpText(value->op)); 949bfe6082cSmrg ACTION("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 { 955bfe6082cSmrg WSGO("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 { 963bfe6082cSmrg WSGO("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])) { 971a57d84feSmrg if (warningLevel > 0) 972a57d84feSmrg { 973a57d84feSmrg WARN("Could not resolve keysym %s\n", 974a57d84feSmrg value->value.list.syms[i]); 975a57d84feSmrg } 97683e5f723Smrg key->syms[ndx][i] = NoSymbol; 97783e5f723Smrg } 97883e5f723Smrg } 97934345a63Smrg for (i = key->numLevels[ndx] - 1; 98034345a63Smrg (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--) 98134345a63Smrg { 98234345a63Smrg key->numLevels[ndx]--; 983f46a6179Smrg } 984f46a6179Smrg return True; 985f46a6179Smrg} 986f46a6179Smrg 987f46a6179Smrgstatic Bool 98834345a63SmrgAddActionsToKey(KeyInfo * key, 98934345a63Smrg XkbDescPtr xkb, 990c82dfdfbSmrg const char *field, 99134345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 992f46a6179Smrg{ 99334345a63Smrg register int i; 99434345a63Smrg unsigned ndx, nActs; 99534345a63Smrg ExprDef *act; 99634345a63Smrg XkbAnyAction *toAct; 99734345a63Smrg 99834345a63Smrg if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx)) 99934345a63Smrg return False; 100034345a63Smrg 100134345a63Smrg if (value == NULL) 100234345a63Smrg { 100334345a63Smrg key->actsDefined |= (1 << ndx); 100434345a63Smrg return True; 100534345a63Smrg } 100634345a63Smrg if (value->op != ExprActionList) 100734345a63Smrg { 1008bfe6082cSmrg WSGO("Bad expression type (%d) for action list value\n", value->op); 1009bfe6082cSmrg ACTION("Ignoring actions for group %d of %s\n", ndx, 101034345a63Smrg longText(key->name, XkbMessage)); 101134345a63Smrg return False; 101234345a63Smrg } 101334345a63Smrg if (key->acts[ndx] != NULL) 101434345a63Smrg { 1015bfe6082cSmrg WSGO("Actions for key %s, group %d already defined\n", 101634345a63Smrg longText(key->name, XkbMessage), ndx); 101734345a63Smrg return False; 101834345a63Smrg } 101934345a63Smrg for (nActs = 0, act = value->value.child; act != NULL; nActs++) 102034345a63Smrg { 102134345a63Smrg act = (ExprDef *) act->common.next; 102234345a63Smrg } 102334345a63Smrg if (nActs < 1) 102434345a63Smrg { 102534345a63Smrg WSGO("Action list but not actions in AddActionsToKey\n"); 102634345a63Smrg return False; 102734345a63Smrg } 102834345a63Smrg if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) && 102934345a63Smrg (!ResizeKeyGroup(key, ndx, nActs, True))) 103034345a63Smrg { 1031bfe6082cSmrg WSGO("Could not resize group %d of key %s\n", ndx, 103234345a63Smrg longText(key->name, XkbMessage)); 103334345a63Smrg ACTION("Actions lost\n"); 103434345a63Smrg return False; 103534345a63Smrg } 103634345a63Smrg key->actsDefined |= (1 << ndx); 103734345a63Smrg 103834345a63Smrg toAct = (XkbAnyAction *) key->acts[ndx]; 103934345a63Smrg act = value->value.child; 104034345a63Smrg for (i = 0; i < nActs; i++, toAct++) 104134345a63Smrg { 104234345a63Smrg if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action)) 104334345a63Smrg { 1044bfe6082cSmrg ERROR("Illegal action definition for %s\n", 104534345a63Smrg longText(key->name, XkbMessage)); 1046bfe6082cSmrg ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1); 104734345a63Smrg } 104834345a63Smrg act = (ExprDef *) act->common.next; 1049f46a6179Smrg } 1050f46a6179Smrg return True; 1051f46a6179Smrg} 1052f46a6179Smrg 1053f46a6179Smrgstatic int 105434345a63SmrgSetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value) 1055f46a6179Smrg{ 105634345a63Smrg ExprResult tmp; 105734345a63Smrg unsigned radio_groups = 0; 105834345a63Smrg 105934345a63Smrg if (arrayNdx == NULL) 106034345a63Smrg { 106134345a63Smrg radio_groups = XkbAllRadioGroupsMask; 106234345a63Smrg } 106334345a63Smrg else 106434345a63Smrg { 106534345a63Smrg if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL)) 106634345a63Smrg { 106734345a63Smrg ERROR("Illegal index in group name definition\n"); 106834345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 106934345a63Smrg return False; 107034345a63Smrg } 107134345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 107234345a63Smrg { 1073bfe6082cSmrg ERROR("Illegal radio group specified (must be 1..%d)\n", 107434345a63Smrg XkbMaxRadioGroups + 1); 1075bfe6082cSmrg ACTION("Value of \"allow none\" for group %d ignored\n", 107634345a63Smrg tmp.uval); 107734345a63Smrg return False; 107834345a63Smrg } 107934345a63Smrg radio_groups |= (1 << (tmp.uval - 1)); 108034345a63Smrg } 108134345a63Smrg if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) 108234345a63Smrg { 1083bfe6082cSmrg ERROR("Illegal \"allow none\" value for %s\n", 108434345a63Smrg longText(key->name, XkbMessage)); 108534345a63Smrg ACTION("Non-boolean value ignored\n"); 108634345a63Smrg return False; 108734345a63Smrg } 108834345a63Smrg if (tmp.uval) 108934345a63Smrg key->allowNone |= radio_groups; 109034345a63Smrg else 109134345a63Smrg key->allowNone &= ~radio_groups; 1092f46a6179Smrg return True; 1093f46a6179Smrg} 1094f46a6179Smrg 1095f46a6179Smrg 109634345a63Smrgstatic LookupEntry lockingEntries[] = { 109734345a63Smrg {"true", XkbKB_Lock}, 109834345a63Smrg {"yes", XkbKB_Lock}, 109934345a63Smrg {"on", XkbKB_Lock}, 110034345a63Smrg {"false", XkbKB_Default}, 110134345a63Smrg {"no", XkbKB_Default}, 110234345a63Smrg {"off", XkbKB_Default}, 110334345a63Smrg {"permanent", XkbKB_Lock | XkbKB_Permanent}, 110434345a63Smrg {NULL, 0} 1105f46a6179Smrg}; 1106f46a6179Smrg 110734345a63Smrgstatic LookupEntry repeatEntries[] = { 110834345a63Smrg {"true", RepeatYes}, 110934345a63Smrg {"yes", RepeatYes}, 111034345a63Smrg {"on", RepeatYes}, 111134345a63Smrg {"false", RepeatNo}, 111234345a63Smrg {"no", RepeatNo}, 111334345a63Smrg {"off", RepeatNo}, 111434345a63Smrg {"default", RepeatUndefined}, 111534345a63Smrg {NULL, 0} 1116f46a6179Smrg}; 1117f46a6179Smrg 111834345a63Smrgstatic LookupEntry rgEntries[] = { 111934345a63Smrg {"none", 0}, 112034345a63Smrg {NULL, 0} 1121f46a6179Smrg}; 1122f46a6179Smrg 1123f46a6179Smrgstatic Bool 112434345a63SmrgSetSymbolsField(KeyInfo * key, 112534345a63Smrg XkbDescPtr xkb, 1126c82dfdfbSmrg const char *field, 112734345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 1128f46a6179Smrg{ 112934345a63Smrg Bool ok = True; 113034345a63Smrg ExprResult tmp; 113134345a63Smrg 113234345a63Smrg if (uStrCaseCmp(field, "type") == 0) 113334345a63Smrg { 113434345a63Smrg ExprResult ndx; 113534345a63Smrg if ((!ExprResolveString(value, &tmp, NULL, NULL)) 113634345a63Smrg && (warningLevel > 0)) 113734345a63Smrg { 113834345a63Smrg WARN("The type field of a key symbol map must be a string\n"); 113934345a63Smrg ACTION("Ignoring illegal type definition\n"); 114034345a63Smrg } 114134345a63Smrg if (arrayNdx == NULL) 114234345a63Smrg { 114334345a63Smrg key->dfltType = XkbInternAtom(NULL, tmp.str, False); 114434345a63Smrg key->defs.defined |= _Key_Type_Dflt; 114534345a63Smrg } 114634345a63Smrg else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup, 114734345a63Smrg (XPointer) groupNames)) 114834345a63Smrg { 1149bfe6082cSmrg ERROR("Illegal group index for type of key %s\n", 115034345a63Smrg longText(key->name, XkbMessage)); 115134345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 115234345a63Smrg return False; 115334345a63Smrg } 115434345a63Smrg else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups)) 115534345a63Smrg { 1156bfe6082cSmrg ERROR 115734345a63Smrg ("Group index for type of key %s is out of range (1..%d)\n", 115834345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 1159bfe6082cSmrg ACTION("Ignoring type for group %d\n", ndx.uval); 116034345a63Smrg return False; 116134345a63Smrg } 116234345a63Smrg else 116334345a63Smrg { 116434345a63Smrg key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False); 116534345a63Smrg key->typesDefined |= (1 << (ndx.uval - 1)); 116634345a63Smrg } 116734345a63Smrg } 116834345a63Smrg else if (uStrCaseCmp(field, "symbols") == 0) 116934345a63Smrg return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info); 117034345a63Smrg else if (uStrCaseCmp(field, "actions") == 0) 117134345a63Smrg return AddActionsToKey(key, xkb, field, arrayNdx, value, info); 117234345a63Smrg else if ((uStrCaseCmp(field, "vmods") == 0) || 117334345a63Smrg (uStrCaseCmp(field, "virtualmods") == 0) || 117434345a63Smrg (uStrCaseCmp(field, "virtualmodifiers") == 0)) 117534345a63Smrg { 117634345a63Smrg ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb); 117734345a63Smrg if (ok) 117834345a63Smrg { 117934345a63Smrg key->vmodmap = (tmp.uval >> 8); 118034345a63Smrg key->defs.defined |= _Key_VModMap; 118134345a63Smrg } 118234345a63Smrg else 118334345a63Smrg { 1184bfe6082cSmrg ERROR("Expected a virtual modifier mask, found %s\n", 118534345a63Smrg exprOpText(value->op)); 1186bfe6082cSmrg ACTION("Ignoring virtual modifiers definition for key %s\n", 118734345a63Smrg longText(key->name, XkbMessage)); 118834345a63Smrg } 118934345a63Smrg } 119034345a63Smrg else if ((uStrCaseCmp(field, "locking") == 0) 119134345a63Smrg || (uStrCaseCmp(field, "lock") == 0) 119234345a63Smrg || (uStrCaseCmp(field, "locks") == 0)) 119334345a63Smrg { 119434345a63Smrg ok = ExprResolveEnum(value, &tmp, lockingEntries); 119534345a63Smrg if (ok) 119634345a63Smrg key->behavior.type = tmp.uval; 119734345a63Smrg key->defs.defined |= _Key_Behavior; 119834345a63Smrg } 119934345a63Smrg else if ((uStrCaseCmp(field, "radiogroup") == 0) || 120034345a63Smrg (uStrCaseCmp(field, "permanentradiogroup") == 0)) 120134345a63Smrg { 120234345a63Smrg Bool permanent = False; 120334345a63Smrg if (uStrCaseCmp(field, "permanentradiogroup") == 0) 120434345a63Smrg permanent = True; 120534345a63Smrg ok = ExprResolveInteger(value, &tmp, SimpleLookup, 120634345a63Smrg (XPointer) rgEntries); 120734345a63Smrg if (!ok) 120834345a63Smrg { 1209bfe6082cSmrg ERROR("Illegal radio group specification for %s\n", 121034345a63Smrg longText(key->name, XkbMessage)); 121134345a63Smrg ACTION("Non-integer radio group ignored\n"); 121234345a63Smrg return False; 121334345a63Smrg } 121434345a63Smrg if (tmp.uval == 0) 121534345a63Smrg { 121634345a63Smrg key->behavior.type = XkbKB_Default; 121734345a63Smrg key->behavior.data = 0; 121834345a63Smrg return ok; 121934345a63Smrg } 122034345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 122134345a63Smrg { 1222bfe6082cSmrg ERROR 122334345a63Smrg ("Radio group specification for %s out of range (1..32)\n", 122434345a63Smrg longText(key->name, XkbMessage)); 1225bfe6082cSmrg ACTION("Illegal radio group %d ignored\n", tmp.uval); 122634345a63Smrg return False; 122734345a63Smrg } 122834345a63Smrg key->behavior.type = 122934345a63Smrg XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0); 123034345a63Smrg key->behavior.data = tmp.uval - 1; 123134345a63Smrg if (key->allowNone & (1 << (tmp.uval - 1))) 123234345a63Smrg key->behavior.data |= XkbKB_RGAllowNone; 123334345a63Smrg key->defs.defined |= _Key_Behavior; 123434345a63Smrg } 123534345a63Smrg else if (uStrCaseEqual(field, "allownone")) 123634345a63Smrg { 123734345a63Smrg ok = SetAllowNone(key, arrayNdx, value); 123834345a63Smrg } 123934345a63Smrg else if (uStrCasePrefix("overlay", field) || 124034345a63Smrg uStrCasePrefix("permanentoverlay", field)) 124134345a63Smrg { 124234345a63Smrg Bool permanent = False; 1243c82dfdfbSmrg const char *which; 124434345a63Smrg int overlayNdx; 124534345a63Smrg if (uStrCasePrefix("permanent", field)) 124634345a63Smrg { 124734345a63Smrg permanent = True; 124834345a63Smrg which = &field[sizeof("permanentoverlay") - 1]; 124934345a63Smrg } 125034345a63Smrg else 125134345a63Smrg { 125234345a63Smrg which = &field[sizeof("overlay") - 1]; 125334345a63Smrg } 125434345a63Smrg if (sscanf(which, "%d", &overlayNdx) == 1) 125534345a63Smrg { 125634345a63Smrg if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0)) 125734345a63Smrg { 1258bfe6082cSmrg ERROR("Illegal overlay %d specified for %s\n", 125934345a63Smrg overlayNdx, longText(key->name, XkbMessage)); 126034345a63Smrg ACTION("Ignored\n"); 126134345a63Smrg return False; 126234345a63Smrg } 126334345a63Smrg } 126434345a63Smrg else if (*which == '\0') 126534345a63Smrg overlayNdx = 1; 126634345a63Smrg else if (warningLevel > 0) 126734345a63Smrg { 1268bfe6082cSmrg ERROR("Illegal overlay \"%s\" specified for %s\n", 126934345a63Smrg which, longText(key->name, XkbMessage)); 127034345a63Smrg ACTION("Ignored\n"); 127134345a63Smrg return False; 127234345a63Smrg } 127334345a63Smrg ok = ExprResolveKeyName(value, &tmp, NULL, NULL); 127434345a63Smrg if (!ok) 127534345a63Smrg { 1276bfe6082cSmrg ERROR("Illegal overlay key specification for %s\n", 127734345a63Smrg longText(key->name, XkbMessage)); 127834345a63Smrg ACTION("Overlay key must be specified by name\n"); 127934345a63Smrg return False; 128034345a63Smrg } 128134345a63Smrg if (overlayNdx == 1) 128234345a63Smrg key->behavior.type = XkbKB_Overlay1; 128334345a63Smrg else 128434345a63Smrg key->behavior.type = XkbKB_Overlay2; 128534345a63Smrg if (permanent) 128634345a63Smrg key->behavior.type |= XkbKB_Permanent; 128734345a63Smrg 128834345a63Smrg key->behavior.data = 0; 128934345a63Smrg key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name); 129034345a63Smrg key->defs.defined |= _Key_Behavior; 129134345a63Smrg } 129234345a63Smrg else if ((uStrCaseCmp(field, "repeating") == 0) || 129334345a63Smrg (uStrCaseCmp(field, "repeats") == 0) || 129434345a63Smrg (uStrCaseCmp(field, "repeat") == 0)) 129534345a63Smrg { 129634345a63Smrg ok = ExprResolveEnum(value, &tmp, repeatEntries); 129734345a63Smrg if (!ok) 129834345a63Smrg { 1299bfe6082cSmrg ERROR("Illegal repeat setting for %s\n", 130034345a63Smrg longText(key->name, XkbMessage)); 130134345a63Smrg ACTION("Non-boolean repeat setting ignored\n"); 130234345a63Smrg return False; 130334345a63Smrg } 130434345a63Smrg key->repeat = tmp.uval; 130534345a63Smrg key->defs.defined |= _Key_Repeat; 130634345a63Smrg } 130734345a63Smrg else if ((uStrCaseCmp(field, "groupswrap") == 0) || 130834345a63Smrg (uStrCaseCmp(field, "wrapgroups") == 0)) 130934345a63Smrg { 131034345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 131134345a63Smrg if (!ok) 131234345a63Smrg { 1313bfe6082cSmrg ERROR("Illegal groupsWrap setting for %s\n", 131434345a63Smrg longText(key->name, XkbMessage)); 131534345a63Smrg ACTION("Non-boolean value ignored\n"); 131634345a63Smrg return False; 131734345a63Smrg } 131834345a63Smrg if (tmp.uval) 131934345a63Smrg key->groupInfo = XkbWrapIntoRange; 132034345a63Smrg else 132134345a63Smrg key->groupInfo = XkbClampIntoRange; 132234345a63Smrg key->defs.defined |= _Key_GroupInfo; 132334345a63Smrg } 132434345a63Smrg else if ((uStrCaseCmp(field, "groupsclamp") == 0) || 132534345a63Smrg (uStrCaseCmp(field, "clampgroups") == 0)) 132634345a63Smrg { 132734345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 132834345a63Smrg if (!ok) 132934345a63Smrg { 1330bfe6082cSmrg ERROR("Illegal groupsClamp setting for %s\n", 133134345a63Smrg longText(key->name, XkbMessage)); 133234345a63Smrg ACTION("Non-boolean value ignored\n"); 133334345a63Smrg return False; 133434345a63Smrg } 133534345a63Smrg if (tmp.uval) 133634345a63Smrg key->groupInfo = XkbClampIntoRange; 133734345a63Smrg else 133834345a63Smrg key->groupInfo = XkbWrapIntoRange; 133934345a63Smrg key->defs.defined |= _Key_GroupInfo; 134034345a63Smrg } 134134345a63Smrg else if ((uStrCaseCmp(field, "groupsredirect") == 0) || 134234345a63Smrg (uStrCaseCmp(field, "redirectgroups") == 0)) 134334345a63Smrg { 134434345a63Smrg if (!ExprResolveInteger 134534345a63Smrg (value, &tmp, SimpleLookup, (XPointer) groupNames)) 134634345a63Smrg { 1347bfe6082cSmrg ERROR("Illegal group index for redirect of key %s\n", 134834345a63Smrg longText(key->name, XkbMessage)); 134934345a63Smrg ACTION("Definition with non-integer group ignored\n"); 135034345a63Smrg return False; 135134345a63Smrg } 135234345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 135334345a63Smrg { 1354bfe6082cSmrg ERROR("Out-of-range (1..%d) group for redirect of key %s\n", 135534345a63Smrg XkbNumKbdGroups, longText(key->name, XkbMessage)); 1356bfe6082cSmrg ERROR("Ignoring illegal group %d\n", tmp.uval); 135734345a63Smrg return False; 135834345a63Smrg } 135934345a63Smrg key->groupInfo = 136034345a63Smrg XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1); 136134345a63Smrg key->defs.defined |= _Key_GroupInfo; 136234345a63Smrg } 136334345a63Smrg else 136434345a63Smrg { 1365bfe6082cSmrg ERROR("Unknown field %s in a symbol interpretation\n", field); 136634345a63Smrg ACTION("Definition ignored\n"); 136734345a63Smrg ok = False; 1368f46a6179Smrg } 1369f46a6179Smrg return ok; 1370f46a6179Smrg} 1371f46a6179Smrg 1372f46a6179Smrgstatic int 137334345a63SmrgSetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value) 1374f46a6179Smrg{ 137534345a63Smrg ExprResult tmp, name; 137634345a63Smrg 137734345a63Smrg if ((arrayNdx == NULL) && (warningLevel > 0)) 137834345a63Smrg { 137934345a63Smrg WARN("You must specify an index when specifying a group name\n"); 138034345a63Smrg ACTION("Group name definition without array subscript ignored\n"); 138134345a63Smrg return False; 138234345a63Smrg } 138334345a63Smrg if (!ExprResolveInteger 138434345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 138534345a63Smrg { 138634345a63Smrg ERROR("Illegal index in group name definition\n"); 138734345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 138834345a63Smrg return False; 138934345a63Smrg } 139034345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 139134345a63Smrg { 1392bfe6082cSmrg ERROR 139334345a63Smrg ("Attempt to specify name for illegal group (must be 1..%d)\n", 139434345a63Smrg XkbNumKbdGroups + 1); 1395bfe6082cSmrg ACTION("Name for group %d ignored\n", tmp.uval); 139634345a63Smrg return False; 139734345a63Smrg } 139834345a63Smrg if (!ExprResolveString(value, &name, NULL, NULL)) 139934345a63Smrg { 140034345a63Smrg ERROR("Group name must be a string\n"); 1401bfe6082cSmrg ACTION("Illegal name for group %d ignored\n", tmp.uval); 140234345a63Smrg return False; 140334345a63Smrg } 140434345a63Smrg info->groupNames[tmp.uval - 1 + info->explicit_group] = 140534345a63Smrg XkbInternAtom(NULL, name.str, False); 140634345a63Smrg 1407f46a6179Smrg return True; 1408f46a6179Smrg} 1409f46a6179Smrg 1410f46a6179Smrgstatic int 141134345a63SmrgHandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info) 1412f46a6179Smrg{ 141334345a63Smrg ExprResult elem, field, tmp; 141434345a63Smrg ExprDef *arrayNdx; 141534345a63Smrg 141634345a63Smrg if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0) 141734345a63Smrg return 0; /* internal error, already reported */ 141834345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) 141934345a63Smrg { 142034345a63Smrg return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx, 142134345a63Smrg stmt->value, info); 142234345a63Smrg } 142334345a63Smrg else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) || 142434345a63Smrg (uStrCaseCmp(field.str, "groupname") == 142534345a63Smrg 0))) 142634345a63Smrg { 142734345a63Smrg return SetGroupName(info, arrayNdx, stmt->value); 142834345a63Smrg } 142934345a63Smrg else if ((elem.str == NULL) 143034345a63Smrg && ((uStrCaseCmp(field.str, "groupswrap") == 0) 143134345a63Smrg || (uStrCaseCmp(field.str, "wrapgroups") == 0))) 143234345a63Smrg { 143334345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 143434345a63Smrg { 143534345a63Smrg ERROR("Illegal setting for global groupsWrap\n"); 143634345a63Smrg ACTION("Non-boolean value ignored\n"); 143734345a63Smrg return False; 143834345a63Smrg } 143934345a63Smrg if (tmp.uval) 144034345a63Smrg info->groupInfo = XkbWrapIntoRange; 144134345a63Smrg else 144234345a63Smrg info->groupInfo = XkbClampIntoRange; 144334345a63Smrg return True; 144434345a63Smrg } 144534345a63Smrg else if ((elem.str == NULL) 144634345a63Smrg && ((uStrCaseCmp(field.str, "groupsclamp") == 0) 144734345a63Smrg || (uStrCaseCmp(field.str, "clampgroups") == 0))) 144834345a63Smrg { 144934345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 145034345a63Smrg { 145134345a63Smrg ERROR("Illegal setting for global groupsClamp\n"); 145234345a63Smrg ACTION("Non-boolean value ignored\n"); 145334345a63Smrg return False; 145434345a63Smrg } 145534345a63Smrg if (tmp.uval) 145634345a63Smrg info->groupInfo = XkbClampIntoRange; 145734345a63Smrg else 145834345a63Smrg info->groupInfo = XkbWrapIntoRange; 145934345a63Smrg return True; 146034345a63Smrg } 146134345a63Smrg else if ((elem.str == NULL) 146234345a63Smrg && ((uStrCaseCmp(field.str, "groupsredirect") == 0) 146334345a63Smrg || (uStrCaseCmp(field.str, "redirectgroups") == 0))) 146434345a63Smrg { 146534345a63Smrg if (!ExprResolveInteger(stmt->value, &tmp, 146634345a63Smrg SimpleLookup, (XPointer) groupNames)) 146734345a63Smrg { 146834345a63Smrg ERROR("Illegal group index for global groupsRedirect\n"); 146934345a63Smrg ACTION("Definition with non-integer group ignored\n"); 147034345a63Smrg return False; 147134345a63Smrg } 147234345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 147334345a63Smrg { 1474bfe6082cSmrg ERROR 147534345a63Smrg ("Out-of-range (1..%d) group for global groupsRedirect\n", 147634345a63Smrg XkbNumKbdGroups); 1477bfe6082cSmrg ACTION("Ignoring illegal group %d\n", tmp.uval); 147834345a63Smrg return False; 147934345a63Smrg } 148034345a63Smrg info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval); 148134345a63Smrg return True; 148234345a63Smrg } 148334345a63Smrg else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0)) 148434345a63Smrg { 148534345a63Smrg return SetAllowNone(&info->dflt, arrayNdx, stmt->value); 148634345a63Smrg } 148734345a63Smrg return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value, 148834345a63Smrg &info->action); 1489f46a6179Smrg} 1490f46a6179Smrg 1491f46a6179Smrgstatic Bool 149234345a63SmrgHandleSymbolsBody(VarDef * def, 149334345a63Smrg XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info) 1494f46a6179Smrg{ 149534345a63Smrg Bool ok = True; 149634345a63Smrg ExprResult tmp, field; 149734345a63Smrg ExprDef *arrayNdx; 149834345a63Smrg 149934345a63Smrg for (; def != NULL; def = (VarDef *) def->common.next) 150034345a63Smrg { 150134345a63Smrg if ((def->name) && (def->name->type == ExprFieldRef)) 150234345a63Smrg { 150334345a63Smrg ok = HandleSymbolsVar(def, xkb, info); 150434345a63Smrg continue; 150534345a63Smrg } 150634345a63Smrg else 150734345a63Smrg { 150834345a63Smrg if (def->name == NULL) 150934345a63Smrg { 151034345a63Smrg if ((def->value == NULL) 151134345a63Smrg || (def->value->op == ExprKeysymList)) 151234345a63Smrg field.str = "symbols"; 151334345a63Smrg else 151434345a63Smrg field.str = "actions"; 151534345a63Smrg arrayNdx = NULL; 151634345a63Smrg } 151734345a63Smrg else 151834345a63Smrg { 151934345a63Smrg ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); 152034345a63Smrg } 152134345a63Smrg if (ok) 152234345a63Smrg ok = SetSymbolsField(key, xkb, field.str, arrayNdx, 152334345a63Smrg def->value, info); 152434345a63Smrg } 1525f46a6179Smrg } 1526f46a6179Smrg return ok; 1527f46a6179Smrg} 1528f46a6179Smrg 1529f46a6179Smrgstatic Bool 153034345a63SmrgSetExplicitGroup(SymbolsInfo * info, KeyInfo * key) 1531f46a6179Smrg{ 1532f46a6179Smrg unsigned group = info->explicit_group; 1533f46a6179Smrg 1534f46a6179Smrg if (group == 0) 153534345a63Smrg return True; 153634345a63Smrg 153734345a63Smrg if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1) 153834345a63Smrg { 153934345a63Smrg int i; 1540a57d84feSmrg if (warningLevel > 0) 1541a57d84feSmrg { 1542a57d84feSmrg WARN("For map %s an explicit group is specified\n", info->name); 1543a57d84feSmrg WARN("but key %s has more than one group defined\n", 1544a57d84feSmrg longText(key->name, XkbMessage)); 1545a57d84feSmrg ACTION("All groups except first one will be ignored\n"); 1546a57d84feSmrg } 154734345a63Smrg for (i = 1; i < XkbNumKbdGroups; i++) 154834345a63Smrg { 154934345a63Smrg key->numLevels[i] = 0; 155034345a63Smrg if (key->syms[i] != NULL) 155134345a63Smrg uFree(key->syms[i]); 155234345a63Smrg key->syms[i] = (KeySym *) NULL; 155334345a63Smrg if (key->acts[i] != NULL) 155434345a63Smrg uFree(key->acts[i]); 155534345a63Smrg key->acts[i] = (XkbAction *) NULL; 155634345a63Smrg key->types[i] = (Atom) 0; 155734345a63Smrg } 155834345a63Smrg } 155934345a63Smrg key->typesDefined = key->symsDefined = key->actsDefined = 1 << group; 156034345a63Smrg 156134345a63Smrg key->numLevels[group] = key->numLevels[0]; 156234345a63Smrg key->numLevels[0] = 0; 156334345a63Smrg key->syms[group] = key->syms[0]; 156434345a63Smrg key->syms[0] = (KeySym *) NULL; 156534345a63Smrg key->acts[group] = key->acts[0]; 156634345a63Smrg key->acts[0] = (XkbAction *) NULL; 156734345a63Smrg key->types[group] = key->types[0]; 156834345a63Smrg key->types[0] = (Atom) 0; 156934345a63Smrg return True; 1570f46a6179Smrg} 1571f46a6179Smrg 1572f46a6179Smrgstatic int 157334345a63SmrgHandleSymbolsDef(SymbolsDef * stmt, 157434345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1575f46a6179Smrg{ 157634345a63Smrg KeyInfo key; 157734345a63Smrg 1578f46a6179Smrg InitKeyInfo(&key); 157934345a63Smrg CopyKeyInfo(&info->dflt, &key, False); 158034345a63Smrg key.defs.merge = stmt->merge; 158134345a63Smrg key.name = KeyNameToLong(stmt->keyName); 158234345a63Smrg if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info)) 158334345a63Smrg { 158434345a63Smrg info->errorCount++; 158534345a63Smrg return False; 1586f46a6179Smrg } 1587f46a6179Smrg 158834345a63Smrg if (!SetExplicitGroup(info, &key)) 158934345a63Smrg { 1590f46a6179Smrg info->errorCount++; 1591f46a6179Smrg return False; 1592f46a6179Smrg } 1593f46a6179Smrg 159434345a63Smrg if (!AddKeySymbols(info, &key, xkb)) 159534345a63Smrg { 159634345a63Smrg info->errorCount++; 159734345a63Smrg return False; 1598f46a6179Smrg } 1599f46a6179Smrg return True; 1600f46a6179Smrg} 1601f46a6179Smrg 1602f46a6179Smrgstatic Bool 160334345a63SmrgHandleModMapDef(ModMapDef * def, 160434345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1605f46a6179Smrg{ 160634345a63Smrg ExprDef *key; 160734345a63Smrg ModMapEntry tmp; 160834345a63Smrg ExprResult rtrn; 160934345a63Smrg Bool ok; 161034345a63Smrg 161134345a63Smrg if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn)) 161234345a63Smrg { 161334345a63Smrg ERROR("Illegal modifier map definition\n"); 1614bfe6082cSmrg ACTION("Ignoring map for non-modifier \"%s\"\n", 161534345a63Smrg XkbAtomText(NULL, def->modifier, XkbMessage)); 161634345a63Smrg return False; 161734345a63Smrg } 161834345a63Smrg ok = True; 161934345a63Smrg tmp.modifier = rtrn.uval; 162034345a63Smrg for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) 162134345a63Smrg { 162234345a63Smrg if ((key->op == ExprValue) && (key->type == TypeKeyName)) 162334345a63Smrg { 162434345a63Smrg tmp.haveSymbol = False; 162534345a63Smrg tmp.u.keyName = KeyNameToLong(key->value.keyName); 162634345a63Smrg } 162734345a63Smrg else if (ExprResolveKeySym(key, &rtrn, NULL, NULL)) 162834345a63Smrg { 162934345a63Smrg tmp.haveSymbol = True; 163034345a63Smrg tmp.u.keySym = rtrn.uval; 163134345a63Smrg } 163234345a63Smrg else 163334345a63Smrg { 163434345a63Smrg ERROR("Modmap entries may contain only key names or keysyms\n"); 1635bfe6082cSmrg ACTION("Illegal definition for %s modifier ignored\n", 163634345a63Smrg XkbModIndexText(tmp.modifier, XkbMessage)); 163734345a63Smrg continue; 163834345a63Smrg } 163934345a63Smrg 164034345a63Smrg ok = AddModMapEntry(info, &tmp) && ok; 1641f46a6179Smrg } 1642f46a6179Smrg return ok; 1643f46a6179Smrg} 1644f46a6179Smrg 1645f46a6179Smrgstatic void 164634345a63SmrgHandleSymbolsFile(XkbFile * file, 164734345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1648f46a6179Smrg{ 164934345a63Smrg ParseCommon *stmt; 165034345a63Smrg 165134345a63Smrg info->name = uStringDup(file->name); 165234345a63Smrg stmt = file->defs; 165334345a63Smrg while (stmt) 165434345a63Smrg { 165534345a63Smrg switch (stmt->stmtType) 165634345a63Smrg { 165734345a63Smrg case StmtInclude: 165834345a63Smrg if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info, 165934345a63Smrg HandleSymbolsFile)) 166034345a63Smrg info->errorCount++; 166134345a63Smrg break; 166234345a63Smrg case StmtSymbolsDef: 166334345a63Smrg if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info)) 166434345a63Smrg info->errorCount++; 166534345a63Smrg break; 166634345a63Smrg case StmtVarDef: 166734345a63Smrg if (!HandleSymbolsVar((VarDef *) stmt, xkb, info)) 166834345a63Smrg info->errorCount++; 166934345a63Smrg break; 167034345a63Smrg case StmtVModDef: 167134345a63Smrg if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) 167234345a63Smrg info->errorCount++; 167334345a63Smrg break; 167434345a63Smrg case StmtInterpDef: 167534345a63Smrg ERROR("Interpretation files may not include other types\n"); 167634345a63Smrg ACTION("Ignoring definition of symbol interpretation\n"); 167734345a63Smrg info->errorCount++; 167834345a63Smrg break; 167934345a63Smrg case StmtKeycodeDef: 168034345a63Smrg ERROR("Interpretation files may not include other types\n"); 168134345a63Smrg ACTION("Ignoring definition of key name\n"); 168234345a63Smrg info->errorCount++; 168334345a63Smrg break; 168434345a63Smrg case StmtModMapDef: 168534345a63Smrg if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info)) 168634345a63Smrg info->errorCount++; 168734345a63Smrg break; 168834345a63Smrg default: 1689bfe6082cSmrg WSGO("Unexpected statement type %d in HandleSymbolsFile\n", 169034345a63Smrg stmt->stmtType); 169134345a63Smrg break; 169234345a63Smrg } 169334345a63Smrg stmt = stmt->next; 169434345a63Smrg if (info->errorCount > 10) 169534345a63Smrg { 1696f46a6179Smrg#ifdef NOISY 169734345a63Smrg ERROR("Too many errors\n"); 1698f46a6179Smrg#endif 1699bfe6082cSmrg ACTION("Abandoning symbols file \"%s\"\n", file->topName); 170034345a63Smrg break; 170134345a63Smrg } 1702f46a6179Smrg } 1703f46a6179Smrg return; 1704f46a6179Smrg} 1705f46a6179Smrg 1706f46a6179Smrgstatic Bool 170734345a63SmrgFindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn) 1708f46a6179Smrg{ 170934345a63Smrg register int i, j; 171034345a63Smrg register Bool gotOne; 171134345a63Smrg 171234345a63Smrg j = 0; 171334345a63Smrg do 171434345a63Smrg { 171534345a63Smrg gotOne = False; 171634345a63Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) 171734345a63Smrg { 171834345a63Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) 171934345a63Smrg { 1720f46a6179Smrg gotOne = True; 17211d8c7986Smrg if (XkbKeySym(xkb, i, j) == sym) 172234345a63Smrg { 172334345a63Smrg *kc_rtrn = i; 1724f46a6179Smrg return True; 172534345a63Smrg } 1726f46a6179Smrg } 1727f46a6179Smrg } 1728f46a6179Smrg j++; 172934345a63Smrg } 173034345a63Smrg while (gotOne); 1731f46a6179Smrg return False; 1732f46a6179Smrg} 1733f46a6179Smrg 173434345a63Smrg/** 173534345a63Smrg * Find the given name in the xkb->map->types and return its index. 173634345a63Smrg * 173734345a63Smrg * @param name The atom to search for. 173834345a63Smrg * @param type_rtrn Set to the index of the name if found. 173934345a63Smrg * 174034345a63Smrg * @return True if found, False otherwise. 174134345a63Smrg */ 1742f46a6179Smrgstatic Bool 174334345a63SmrgFindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn) 1744f46a6179Smrg{ 174534345a63Smrg register unsigned n; 174634345a63Smrg 174734345a63Smrg if (xkb && xkb->map && xkb->map->types) 174834345a63Smrg { 174934345a63Smrg for (n = 0; n < xkb->map->num_types; n++) 175034345a63Smrg { 175134345a63Smrg if (xkb->map->types[n].name == (Atom) name) 175234345a63Smrg { 175334345a63Smrg *type_rtrn = n; 175434345a63Smrg return True; 175534345a63Smrg } 175634345a63Smrg } 1757f46a6179Smrg } 1758f46a6179Smrg return False; 1759f46a6179Smrg} 1760f46a6179Smrg 1761f46a6179Smrgstatic Bool 176234345a63SmrgKSIsLower(KeySym ks) 1763f46a6179Smrg{ 1764f46a6179Smrg KeySym lower, upper; 1765f46a6179Smrg XConvertCase(ks, &lower, &upper); 1766f46a6179Smrg 1767f46a6179Smrg if (lower == upper) 1768f46a6179Smrg return False; 1769f46a6179Smrg return (ks == lower ? True : False); 1770f46a6179Smrg} 1771f46a6179Smrg 1772f46a6179Smrgstatic Bool 177334345a63SmrgKSIsUpper(KeySym ks) 1774f46a6179Smrg{ 1775f46a6179Smrg KeySym lower, upper; 1776f46a6179Smrg XConvertCase(ks, &lower, &upper); 1777f46a6179Smrg 1778f46a6179Smrg if (lower == upper) 1779f46a6179Smrg return False; 1780f46a6179Smrg return (ks == upper ? True : False); 1781f46a6179Smrg} 1782f46a6179Smrg 178334345a63Smrg/** 178434345a63Smrg * Assign a type to the given sym and return the Atom for the type assigned. 178534345a63Smrg * 178634345a63Smrg * Simple recipe: 178734345a63Smrg * - ONE_LEVEL for width 0/1 1788a57d84feSmrg * - ALPHABETIC for 2 shift levels, with lower/uppercase 178934345a63Smrg * - KEYPAD for keypad keys. 179034345a63Smrg * - TWO_LEVEL for other 2 shift level keys. 179134345a63Smrg * and the same for four level keys. 179234345a63Smrg * 179334345a63Smrg * @param width Number of sysms in syms. 179434345a63Smrg * @param syms The keysyms for the given key (must be size width). 179534345a63Smrg * @param typeNameRtrn Set to the Atom of the type name. 179634345a63Smrg * 179734345a63Smrg * @returns True if a type could be found, False otherwise. 179834345a63Smrg */ 1799f46a6179Smrgstatic Bool 180034345a63SmrgFindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn, 180134345a63Smrg Bool * autoType) 1802f46a6179Smrg{ 1803f46a6179Smrg *autoType = False; 180434345a63Smrg if ((width == 1) || (width == 0)) 180534345a63Smrg { 180634345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False); 180734345a63Smrg *autoType = True; 180834345a63Smrg } 180934345a63Smrg else if (width == 2) 181034345a63Smrg { 181134345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 181234345a63Smrg { 181334345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False); 181434345a63Smrg } 181534345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 181634345a63Smrg { 181734345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False); 181834345a63Smrg *autoType = True; 181934345a63Smrg } 182034345a63Smrg else 182134345a63Smrg { 182234345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False); 182334345a63Smrg *autoType = True; 182434345a63Smrg } 182534345a63Smrg } 182634345a63Smrg else if (width <= 4) 182734345a63Smrg { 182834345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 182934345a63Smrg if (KSIsLower(syms[2]) && KSIsUpper(syms[3])) 183034345a63Smrg *typeNameRtrn = 183134345a63Smrg XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False); 183234345a63Smrg else 183334345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, 183434345a63Smrg "FOUR_LEVEL_SEMIALPHABETIC", 183534345a63Smrg False); 183634345a63Smrg 183734345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 183834345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False); 183934345a63Smrg else 184034345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False); 184134345a63Smrg /* XXX: why not set autoType here? */ 184234345a63Smrg } 184334345a63Smrg return ((width >= 0) && (width <= 4)); 1844f46a6179Smrg} 1845f46a6179Smrg 184634345a63Smrg/** 184734345a63Smrg * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the 184834345a63Smrg * groups, and reduce to one group if all groups are identical anyway. 184934345a63Smrg */ 1850f46a6179Smrgstatic void 185134345a63SmrgPrepareKeyDef(KeyInfo * key) 1852f46a6179Smrg{ 1853f46a6179Smrg int i, j, width, defined, lastGroup; 1854f46a6179Smrg Bool identical; 185534345a63Smrg 1856f46a6179Smrg defined = key->symsDefined | key->actsDefined | key->typesDefined; 185734345a63Smrg /* get highest group number */ 185834345a63Smrg for (i = XkbNumKbdGroups - 1; i >= 0; i--) 185934345a63Smrg { 186034345a63Smrg if (defined & (1 << i)) 186134345a63Smrg break; 1862f46a6179Smrg } 1863f46a6179Smrg lastGroup = i; 1864f46a6179Smrg 1865f46a6179Smrg if (lastGroup == 0) 186634345a63Smrg return; 1867f46a6179Smrg 1868f46a6179Smrg /* If there are empty groups between non-empty ones fill them with data */ 1869f46a6179Smrg /* from the first group. */ 1870f46a6179Smrg /* We can make a wrong assumption here. But leaving gaps is worse. */ 187134345a63Smrg for (i = lastGroup; i > 0; i--) 187234345a63Smrg { 187334345a63Smrg if (defined & (1 << i)) 1874f46a6179Smrg continue; 1875f46a6179Smrg width = key->numLevels[0]; 187634345a63Smrg if (key->typesDefined & 1) 187734345a63Smrg { 187834345a63Smrg for (j = 0; j < width; j++) 187934345a63Smrg { 1880f46a6179Smrg key->types[i] = key->types[0]; 1881f46a6179Smrg } 1882f46a6179Smrg key->typesDefined |= 1 << i; 1883f46a6179Smrg } 188434345a63Smrg if ((key->actsDefined & 1) && key->acts[0]) 188534345a63Smrg { 188634345a63Smrg key->acts[i] = uTypedCalloc(width, XkbAction); 1887f46a6179Smrg if (key->acts[i] == NULL) 1888f46a6179Smrg continue; 1889f46a6179Smrg memcpy((void *) key->acts[i], (void *) key->acts[0], 1890f46a6179Smrg width * sizeof(XkbAction)); 1891f46a6179Smrg key->actsDefined |= 1 << i; 1892f46a6179Smrg } 189334345a63Smrg if ((key->symsDefined & 1) && key->syms[0]) 189434345a63Smrg { 189534345a63Smrg key->syms[i] = uTypedCalloc(width, KeySym); 1896f46a6179Smrg if (key->syms[i] == NULL) 1897f46a6179Smrg continue; 1898f46a6179Smrg memcpy((void *) key->syms[i], (void *) key->syms[0], 1899f46a6179Smrg width * sizeof(KeySym)); 1900f46a6179Smrg key->symsDefined |= 1 << i; 1901f46a6179Smrg } 190234345a63Smrg if (defined & 1) 190334345a63Smrg { 1904f46a6179Smrg key->numLevels[i] = key->numLevels[0]; 1905f46a6179Smrg } 1906f46a6179Smrg } 1907f46a6179Smrg /* If all groups are completely identical remove them all */ 1908bfe6082cSmrg /* except the first one. */ 1909f46a6179Smrg identical = True; 191034345a63Smrg for (i = lastGroup; i > 0; i--) 191134345a63Smrg { 1912f46a6179Smrg if ((key->numLevels[i] != key->numLevels[0]) || 191334345a63Smrg (key->types[i] != key->types[0])) 191434345a63Smrg { 1915f46a6179Smrg identical = False; 1916f46a6179Smrg break; 1917f46a6179Smrg } 1918f46a6179Smrg if ((key->syms[i] != key->syms[0]) && 191934345a63Smrg (key->syms[i] == NULL || key->syms[0] == NULL || 192034345a63Smrg memcmp((void *) key->syms[i], (void *) key->syms[0], 192134345a63Smrg sizeof(KeySym) * key->numLevels[0]))) 192234345a63Smrg { 192334345a63Smrg identical = False; 192434345a63Smrg break; 192534345a63Smrg } 1926f46a6179Smrg if ((key->acts[i] != key->acts[0]) && 192734345a63Smrg (key->acts[i] == NULL || key->acts[0] == NULL || 192834345a63Smrg memcmp((void *) key->acts[i], (void *) key->acts[0], 192934345a63Smrg sizeof(XkbAction) * key->numLevels[0]))) 193034345a63Smrg { 1931f46a6179Smrg identical = False; 1932f46a6179Smrg break; 193334345a63Smrg } 193434345a63Smrg } 193534345a63Smrg if (identical) 193634345a63Smrg { 193734345a63Smrg for (i = lastGroup; i > 0; i--) 193834345a63Smrg { 193934345a63Smrg key->numLevels[i] = 0; 194034345a63Smrg if (key->syms[i] != NULL) 194134345a63Smrg uFree(key->syms[i]); 194234345a63Smrg key->syms[i] = (KeySym *) NULL; 194334345a63Smrg if (key->acts[i] != NULL) 194434345a63Smrg uFree(key->acts[i]); 194534345a63Smrg key->acts[i] = (XkbAction *) NULL; 194634345a63Smrg key->types[i] = (Atom) 0; 194734345a63Smrg } 194834345a63Smrg key->symsDefined &= 1; 194934345a63Smrg key->actsDefined &= 1; 195034345a63Smrg key->typesDefined &= 1; 1951f46a6179Smrg } 1952f46a6179Smrg return; 1953f46a6179Smrg} 1954f46a6179Smrg 195534345a63Smrg/** 195634345a63Smrg * Copy the KeyInfo into result. 195734345a63Smrg * 195834345a63Smrg * This function recurses. 195934345a63Smrg */ 1960f46a6179Smrgstatic Bool 196134345a63SmrgCopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from) 1962f46a6179Smrg{ 196334345a63Smrg register int i; 196434345a63Smrg unsigned okc, kc, width, tmp, nGroups; 196534345a63Smrg XkbKeyTypePtr type; 196634345a63Smrg Bool haveActions, autoType, useAlias; 196734345a63Smrg KeySym *outSyms; 196834345a63Smrg XkbAction *outActs; 196934345a63Smrg XkbDescPtr xkb; 197034345a63Smrg unsigned types[XkbNumKbdGroups]; 197134345a63Smrg 197234345a63Smrg xkb = result->xkb; 197334345a63Smrg useAlias = (start_from == 0); 197434345a63Smrg 197534345a63Smrg /* get the keycode for the key. */ 197634345a63Smrg if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb), 197734345a63Smrg start_from)) 197834345a63Smrg { 197934345a63Smrg if ((start_from == 0) && (warningLevel >= 5)) 198034345a63Smrg { 1981bfe6082cSmrg WARN("Key %s not found in %s keycodes\n", 198234345a63Smrg longText(key->name, XkbMessage), 198334345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 198434345a63Smrg ACTION("Symbols ignored\n"); 198534345a63Smrg } 198634345a63Smrg return False; 198734345a63Smrg } 198834345a63Smrg 198934345a63Smrg haveActions = False; 199034345a63Smrg for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) 199134345a63Smrg { 199234345a63Smrg if (((i + 1) > nGroups) 199334345a63Smrg && (((key->symsDefined | key->actsDefined) & (1 << i)) 199434345a63Smrg || (key->typesDefined) & (1 << i))) 199534345a63Smrg nGroups = i + 1; 199634345a63Smrg if (key->acts[i]) 199734345a63Smrg haveActions = True; 199834345a63Smrg autoType = False; 199934345a63Smrg /* Assign the type to the key, if it is missing. */ 200034345a63Smrg if (key->types[i] == None) 200134345a63Smrg { 200234345a63Smrg if (key->dfltType != None) 200334345a63Smrg key->types[i] = key->dfltType; 200434345a63Smrg else if (FindAutomaticType(key->numLevels[i], key->syms[i], 200534345a63Smrg &key->types[i], &autoType)) 200634345a63Smrg { 200734345a63Smrg } 200834345a63Smrg else 200934345a63Smrg { 201034345a63Smrg if (warningLevel >= 5) 201134345a63Smrg { 2012bfe6082cSmrg WARN("No automatic type for %d symbols\n", 201334345a63Smrg (unsigned int) key->numLevels[i]); 2014bfe6082cSmrg ACTION("Using %s for the %s key (keycode %d)\n", 201534345a63Smrg XkbAtomText(NULL, key->types[i], 201634345a63Smrg XkbMessage), 201734345a63Smrg longText(key->name, XkbMessage), kc); 201834345a63Smrg } 201934345a63Smrg } 202034345a63Smrg } 202134345a63Smrg if (FindNamedType(xkb, key->types[i], &types[i])) 202234345a63Smrg { 202334345a63Smrg if (!autoType || key->numLevels[i] > 2) 202434345a63Smrg xkb->server->explicit[kc] |= (1 << i); 202534345a63Smrg } 202634345a63Smrg else 202734345a63Smrg { 202834345a63Smrg if (warningLevel >= 3) 202934345a63Smrg { 2030bfe6082cSmrg WARN("Type \"%s\" is not defined\n", 203134345a63Smrg XkbAtomText(NULL, key->types[i], XkbMessage)); 2032bfe6082cSmrg ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n", 203334345a63Smrg longText(key->name, XkbMessage), kc); 203434345a63Smrg } 203534345a63Smrg types[i] = XkbTwoLevelIndex; 203634345a63Smrg } 203734345a63Smrg /* if the type specifies less syms than the key has, shrink the key */ 203834345a63Smrg type = &xkb->map->types[types[i]]; 203934345a63Smrg if (type->num_levels < key->numLevels[i]) 204034345a63Smrg { 20413fb1fa07Smrg if (warningLevel > 5) 204234345a63Smrg { 2043bfe6082cSmrg WARN 204434345a63Smrg ("Type \"%s\" has %d levels, but %s has %d symbols\n", 204534345a63Smrg XkbAtomText(NULL, type->name, XkbMessage), 204634345a63Smrg (unsigned int) type->num_levels, 204734345a63Smrg longText(key->name, XkbMessage), 204834345a63Smrg (unsigned int) key->numLevels[i]); 204934345a63Smrg ACTION("Ignoring extra symbols\n"); 205034345a63Smrg } 205134345a63Smrg key->numLevels[i] = type->num_levels; 205234345a63Smrg } 205334345a63Smrg if (key->numLevels[i] > width) 205434345a63Smrg width = key->numLevels[i]; 205534345a63Smrg if (type->num_levels > width) 205634345a63Smrg width = type->num_levels; 205734345a63Smrg } 205834345a63Smrg 205934345a63Smrg /* width is now the largest width found */ 206034345a63Smrg 206134345a63Smrg i = width * nGroups; 206234345a63Smrg outSyms = XkbResizeKeySyms(xkb, kc, i); 206334345a63Smrg if (outSyms == NULL) 206434345a63Smrg { 2065bfe6082cSmrg WSGO("Could not enlarge symbols for %s (keycode %d)\n", 206634345a63Smrg longText(key->name, XkbMessage), kc); 206734345a63Smrg return False; 206834345a63Smrg } 206934345a63Smrg if (haveActions) 207034345a63Smrg { 207134345a63Smrg outActs = XkbResizeKeyActions(xkb, kc, i); 207234345a63Smrg if (outActs == NULL) 207334345a63Smrg { 2074bfe6082cSmrg WSGO("Could not enlarge actions for %s (key %d)\n", 207534345a63Smrg longText(key->name, XkbMessage), kc); 207634345a63Smrg return False; 207734345a63Smrg } 207834345a63Smrg xkb->server->explicit[kc] |= XkbExplicitInterpretMask; 207934345a63Smrg } 208034345a63Smrg else 208134345a63Smrg outActs = NULL; 208234345a63Smrg if (key->defs.defined & _Key_GroupInfo) 208334345a63Smrg i = key->groupInfo; 208434345a63Smrg else 208534345a63Smrg i = xkb->map->key_sym_map[kc].group_info; 208634345a63Smrg 208734345a63Smrg xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups); 208834345a63Smrg xkb->map->key_sym_map[kc].width = width; 208934345a63Smrg for (i = 0; i < nGroups; i++) 209034345a63Smrg { 209134345a63Smrg /* assign kt_index[i] to the index of the type in map->types. 209234345a63Smrg * kt_index[i] may have been set by a previous run (if we have two 209334345a63Smrg * layouts specified). Let's not overwrite it with the ONE_LEVEL 2094bfe6082cSmrg * default group if we don't even have keys for this group anyway. 209534345a63Smrg * 209634345a63Smrg * FIXME: There should be a better fix for this. 209734345a63Smrg */ 209834345a63Smrg if (key->numLevels[i]) 209934345a63Smrg xkb->map->key_sym_map[kc].kt_index[i] = types[i]; 210034345a63Smrg if (key->syms[i] != NULL) 210134345a63Smrg { 210234345a63Smrg /* fill key to "width" symbols*/ 210334345a63Smrg for (tmp = 0; tmp < width; tmp++) 210434345a63Smrg { 210534345a63Smrg if (tmp < key->numLevels[i]) 210634345a63Smrg outSyms[tmp] = key->syms[i][tmp]; 210734345a63Smrg else 210834345a63Smrg outSyms[tmp] = NoSymbol; 210934345a63Smrg if ((outActs != NULL) && (key->acts[i] != NULL)) 211034345a63Smrg { 211134345a63Smrg if (tmp < key->numLevels[i]) 211234345a63Smrg outActs[tmp] = key->acts[i][tmp]; 211334345a63Smrg else 211434345a63Smrg outActs[tmp].type = XkbSA_NoAction; 211534345a63Smrg } 211634345a63Smrg } 211734345a63Smrg } 211834345a63Smrg outSyms += width; 211934345a63Smrg if (outActs) 212034345a63Smrg outActs += width; 212134345a63Smrg } 212234345a63Smrg switch (key->behavior.type & XkbKB_OpMask) 212334345a63Smrg { 212434345a63Smrg case XkbKB_Default: 212534345a63Smrg break; 212634345a63Smrg case XkbKB_Overlay1: 212734345a63Smrg case XkbKB_Overlay2: 212834345a63Smrg /* find key by name! */ 212934345a63Smrg if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True, 213034345a63Smrg CreateKeyNames(xkb), 0)) 213134345a63Smrg { 213234345a63Smrg if (warningLevel >= 1) 213334345a63Smrg { 2134bfe6082cSmrg WARN("Key %s not found in %s keycodes\n", 213534345a63Smrg longText(key->nameForOverlayKey, XkbMessage), 213634345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 2137bfe6082cSmrg ACTION("Not treating %s as an overlay key \n", 213834345a63Smrg longText(key->name, XkbMessage)); 213934345a63Smrg } 214034345a63Smrg break; 214134345a63Smrg } 214234345a63Smrg key->behavior.data = okc; 214334345a63Smrg default: 214434345a63Smrg xkb->server->behaviors[kc] = key->behavior; 214534345a63Smrg xkb->server->explicit[kc] |= XkbExplicitBehaviorMask; 214634345a63Smrg break; 214734345a63Smrg } 214834345a63Smrg if (key->defs.defined & _Key_VModMap) 214934345a63Smrg { 215034345a63Smrg xkb->server->vmodmap[kc] = key->vmodmap; 215134345a63Smrg xkb->server->explicit[kc] |= XkbExplicitVModMapMask; 215234345a63Smrg } 215334345a63Smrg if (key->repeat != RepeatUndefined) 215434345a63Smrg { 215534345a63Smrg if (key->repeat == RepeatYes) 215634345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8)); 215734345a63Smrg else 215834345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8)); 215934345a63Smrg xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask; 216034345a63Smrg } 216134345a63Smrg 216234345a63Smrg /* do the same thing for the next key */ 216334345a63Smrg CopySymbolsDef(result, key, kc + 1); 2164f46a6179Smrg return True; 2165f46a6179Smrg} 2166f46a6179Smrg 2167f46a6179Smrgstatic Bool 216834345a63SmrgCopyModMapDef(XkbFileInfo * result, ModMapEntry * entry) 2169f46a6179Smrg{ 217034345a63Smrg unsigned kc; 217134345a63Smrg XkbDescPtr xkb; 217234345a63Smrg 217334345a63Smrg xkb = result->xkb; 217434345a63Smrg if ((!entry->haveSymbol) 217534345a63Smrg && 217634345a63Smrg (!FindNamedKey 217734345a63Smrg (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0))) 217834345a63Smrg { 217934345a63Smrg if (warningLevel >= 5) 218034345a63Smrg { 2181bfe6082cSmrg WARN("Key %s not found in %s keycodes\n", 218234345a63Smrg longText(entry->u.keyName, XkbMessage), 218334345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 2184bfe6082cSmrg ACTION("Modifier map entry for %s not updated\n", 218534345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 218634345a63Smrg } 218734345a63Smrg return False; 218834345a63Smrg } 218934345a63Smrg else if (entry->haveSymbol 219034345a63Smrg && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc))) 219134345a63Smrg { 219234345a63Smrg if (warningLevel > 5) 219334345a63Smrg { 2194bfe6082cSmrg WARN("Key \"%s\" not found in %s symbol map\n", 219534345a63Smrg XkbKeysymText(entry->u.keySym, XkbMessage), 219634345a63Smrg XkbAtomText(NULL, xkb->names->symbols, XkbMessage)); 2197bfe6082cSmrg ACTION("Modifier map entry for %s not updated\n", 219834345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 219934345a63Smrg } 220034345a63Smrg return False; 220134345a63Smrg } 220234345a63Smrg xkb->map->modmap[kc] |= (1 << entry->modifier); 2203f46a6179Smrg return True; 2204f46a6179Smrg} 2205f46a6179Smrg 220634345a63Smrg/** 220734345a63Smrg * Handle the xkb_symbols section of an xkb file. 220834345a63Smrg * 220934345a63Smrg * @param file The parsed xkb_symbols section of the xkb file. 221034345a63Smrg * @param result Handle to the data to store the result in. 221134345a63Smrg * @param merge Merge strategy (e.g. MergeOverride). 221234345a63Smrg */ 2213f46a6179SmrgBool 221434345a63SmrgCompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge) 2215f46a6179Smrg{ 221634345a63Smrg register int i; 221734345a63Smrg SymbolsInfo info; 221834345a63Smrg XkbDescPtr xkb; 2219f46a6179Smrg 222034345a63Smrg xkb = result->xkb; 222134345a63Smrg InitSymbolsInfo(&info, xkb); 222234345a63Smrg info.dflt.defs.fileID = file->id; 222334345a63Smrg info.dflt.defs.merge = merge; 222434345a63Smrg HandleSymbolsFile(file, xkb, merge, &info); 2225f46a6179Smrg 2226f46a6179Smrg if (info.nKeys == 0) 2227f46a6179Smrg return True; 222834345a63Smrg if (info.errorCount == 0) 222934345a63Smrg { 223034345a63Smrg KeyInfo *key; 223134345a63Smrg 223234345a63Smrg /* alloc memory in the xkb struct */ 223334345a63Smrg if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0) 223434345a63Smrg != Success) 223534345a63Smrg { 223634345a63Smrg WSGO("Can not allocate names in CompileSymbols\n"); 223734345a63Smrg ACTION("Symbols not added\n"); 223834345a63Smrg return False; 223934345a63Smrg } 224034345a63Smrg if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0) 224134345a63Smrg != Success) 224234345a63Smrg { 224334345a63Smrg WSGO("Could not allocate client map in CompileSymbols\n"); 224434345a63Smrg ACTION("Symbols not added\n"); 224534345a63Smrg return False; 224634345a63Smrg } 224734345a63Smrg if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success) 224834345a63Smrg { 224934345a63Smrg WSGO("Could not allocate server map in CompileSymbols\n"); 225034345a63Smrg ACTION("Symbols not added\n"); 225134345a63Smrg return False; 225234345a63Smrg } 225334345a63Smrg if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success) 225434345a63Smrg { 225534345a63Smrg WSGO("Could not allocate controls in CompileSymbols\n"); 225634345a63Smrg ACTION("Symbols not added\n"); 225734345a63Smrg return False; 225834345a63Smrg } 225934345a63Smrg 226034345a63Smrg /* now copy info into xkb. */ 226134345a63Smrg xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False); 226234345a63Smrg if (info.aliases) 226334345a63Smrg ApplyAliases(xkb, False, &info.aliases); 226434345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 226534345a63Smrg { 226634345a63Smrg if (info.groupNames[i] != None) 226734345a63Smrg xkb->names->groups[i] = info.groupNames[i]; 226834345a63Smrg } 226934345a63Smrg /* sanitize keys */ 227034345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 227134345a63Smrg { 227234345a63Smrg PrepareKeyDef(key); 227334345a63Smrg } 227434345a63Smrg /* copy! */ 227534345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 227634345a63Smrg { 227734345a63Smrg if (!CopySymbolsDef(result, key, 0)) 227834345a63Smrg info.errorCount++; 227934345a63Smrg } 228034345a63Smrg if (warningLevel > 3) 228134345a63Smrg { 228234345a63Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) 228334345a63Smrg { 228434345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 228534345a63Smrg continue; 228634345a63Smrg if (XkbKeyNumGroups(xkb, i) < 1) 228734345a63Smrg { 228834345a63Smrg char buf[5]; 228934345a63Smrg memcpy(buf, xkb->names->keys[i].name, 4); 229034345a63Smrg buf[4] = '\0'; 2291bfe6082cSmrg INFO("No symbols defined for <%s> (keycode %d)\n", 229234345a63Smrg buf, i); 229334345a63Smrg } 229434345a63Smrg } 229534345a63Smrg } 229634345a63Smrg if (info.modMap) 229734345a63Smrg { 229834345a63Smrg ModMapEntry *mm, *next; 229934345a63Smrg for (mm = info.modMap; mm != NULL; mm = next) 230034345a63Smrg { 230134345a63Smrg if (!CopyModMapDef(result, mm)) 230234345a63Smrg info.errorCount++; 230334345a63Smrg next = (ModMapEntry *) mm->defs.next; 230434345a63Smrg } 230534345a63Smrg } 230634345a63Smrg return True; 2307f46a6179Smrg } 2308f46a6179Smrg return False; 2309f46a6179Smrg} 2310