symbols.c revision 1d8c7986
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)); 34234345a63Smrg if (into->numLevels[group] >= from->numLevels[group]) 34334345a63Smrg { 34434345a63Smrg resultSyms = into->syms[group]; 34534345a63Smrg resultActs = into->acts[group]; 34634345a63Smrg resultWidth = into->numLevels[group]; 34734345a63Smrg } 34834345a63Smrg else 34934345a63Smrg { 35034345a63Smrg resultSyms = from->syms[group]; 35134345a63Smrg resultActs = from->acts[group]; 35234345a63Smrg resultWidth = from->numLevels[group]; 35334345a63Smrg } 35434345a63Smrg if (resultSyms == NULL) 35534345a63Smrg { 35634345a63Smrg resultSyms = uTypedCalloc(resultWidth, KeySym); 35734345a63Smrg if (!resultSyms) 35834345a63Smrg { 35934345a63Smrg WSGO("Could not allocate symbols for group merge\n"); 36034345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 36134345a63Smrg longText(into->name, XkbMessage)); 36234345a63Smrg return False; 36334345a63Smrg } 36434345a63Smrg } 36534345a63Smrg if ((resultActs == NULL) && (into->acts[group] || from->acts[group])) 36634345a63Smrg { 36734345a63Smrg resultActs = uTypedCalloc(resultWidth, XkbAction); 36834345a63Smrg if (!resultActs) 36934345a63Smrg { 37034345a63Smrg WSGO("Could not allocate actions for group merge\n"); 37134345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 37234345a63Smrg longText(into->name, XkbMessage)); 37334345a63Smrg return False; 37434345a63Smrg } 37534345a63Smrg } 37634345a63Smrg for (i = 0; i < resultWidth; i++) 37734345a63Smrg { 37834345a63Smrg KeySym fromSym, toSym; 37934345a63Smrg if (from->syms[group] && (i < from->numLevels[group])) 38034345a63Smrg fromSym = from->syms[group][i]; 38134345a63Smrg else 38234345a63Smrg fromSym = NoSymbol; 38334345a63Smrg if (into->syms[group] && (i < into->numLevels[group])) 38434345a63Smrg toSym = into->syms[group][i]; 38534345a63Smrg else 38634345a63Smrg toSym = NoSymbol; 38734345a63Smrg if ((fromSym == NoSymbol) || (fromSym == toSym)) 38834345a63Smrg resultSyms[i] = toSym; 38934345a63Smrg else if (toSym == NoSymbol) 39034345a63Smrg resultSyms[i] = fromSym; 39134345a63Smrg else 39234345a63Smrg { 39334345a63Smrg KeySym use, ignore; 39434345a63Smrg if (clobber) 39534345a63Smrg { 39634345a63Smrg use = fromSym; 39734345a63Smrg ignore = toSym; 39834345a63Smrg } 39934345a63Smrg else 40034345a63Smrg { 40134345a63Smrg use = toSym; 40234345a63Smrg ignore = fromSym; 40334345a63Smrg } 40434345a63Smrg if (report) 40534345a63Smrg { 40634345a63Smrg WARN3 40734345a63Smrg ("Multiple symbols for level %d/group %d on key %s\n", 40834345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 40934345a63Smrg ACTION2("Using %s, ignoring %s\n", 41034345a63Smrg XkbKeysymText(use, XkbMessage), 41134345a63Smrg XkbKeysymText(ignore, XkbMessage)); 41234345a63Smrg } 41334345a63Smrg resultSyms[i] = use; 41434345a63Smrg } 41534345a63Smrg if (resultActs != NULL) 41634345a63Smrg { 41734345a63Smrg XkbAction *fromAct, *toAct; 41834345a63Smrg fromAct = (from->acts[group] ? &from->acts[group][i] : NULL); 41934345a63Smrg toAct = (into->acts[group] ? &into->acts[group][i] : NULL); 42034345a63Smrg if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction)) 42134345a63Smrg && (toAct != NULL)) 42234345a63Smrg { 42334345a63Smrg resultActs[i] = *toAct; 42434345a63Smrg } 42534345a63Smrg else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction)) 42634345a63Smrg && (fromAct != NULL)) 42734345a63Smrg { 42834345a63Smrg resultActs[i] = *fromAct; 42934345a63Smrg } 43034345a63Smrg else 43134345a63Smrg { 43234345a63Smrg XkbAction *use, *ignore; 43334345a63Smrg if (clobber) 43434345a63Smrg { 43534345a63Smrg use = fromAct; 43634345a63Smrg ignore = toAct; 43734345a63Smrg } 43834345a63Smrg else 43934345a63Smrg { 44034345a63Smrg use = toAct; 44134345a63Smrg ignore = fromAct; 44234345a63Smrg } 44334345a63Smrg if (report) 44434345a63Smrg { 44534345a63Smrg WARN3 44634345a63Smrg ("Multiple actions for level %d/group %d on key %s\n", 44734345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 44834345a63Smrg ACTION2("Using %s, ignoring %s\n", 44934345a63Smrg XkbActionTypeText(use->type, XkbMessage), 45034345a63Smrg XkbActionTypeText(ignore->type, XkbMessage)); 45134345a63Smrg } 45234345a63Smrg resultActs[i] = *use; 45334345a63Smrg } 45434345a63Smrg } 45534345a63Smrg } 45634345a63Smrg if ((into->syms[group] != NULL) && (resultSyms != into->syms[group])) 45734345a63Smrg uFree(into->syms[group]); 45834345a63Smrg if ((from->syms[group] != NULL) && (resultSyms != from->syms[group])) 45934345a63Smrg uFree(from->syms[group]); 46034345a63Smrg if ((into->acts[group] != NULL) && (resultActs != into->acts[group])) 46134345a63Smrg uFree(into->acts[group]); 46234345a63Smrg if ((from->acts[group] != NULL) && (resultActs != from->acts[group])) 46334345a63Smrg uFree(from->acts[group]); 46434345a63Smrg into->numLevels[group] = resultWidth; 46534345a63Smrg into->syms[group] = resultSyms; 46634345a63Smrg from->syms[group] = NULL; 46734345a63Smrg into->acts[group] = resultActs; 46834345a63Smrg from->acts[group] = NULL; 46934345a63Smrg into->symsDefined |= (1 << group); 47034345a63Smrg from->symsDefined &= ~(1 << group); 47134345a63Smrg into->actsDefined |= (1 << group); 47234345a63Smrg from->actsDefined &= ~(1 << group); 473f46a6179Smrg return True; 474f46a6179Smrg} 475f46a6179Smrg 476f46a6179Smrgstatic Bool 47734345a63SmrgMergeKeys(SymbolsInfo * info, KeyInfo * into, KeyInfo * from) 478f46a6179Smrg{ 47934345a63Smrg register int i; 48034345a63Smrg unsigned collide = 0; 48134345a63Smrg Bool report; 48234345a63Smrg 48334345a63Smrg if (from->defs.merge == MergeReplace) 48434345a63Smrg { 48534345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 48634345a63Smrg { 48734345a63Smrg if (into->numLevels[i] != 0) 48834345a63Smrg { 48934345a63Smrg if (into->syms[i]) 49034345a63Smrg uFree(into->syms[i]); 49134345a63Smrg if (into->acts[i]) 49234345a63Smrg uFree(into->acts[i]); 49334345a63Smrg } 49434345a63Smrg } 49534345a63Smrg *into = *from; 49634345a63Smrg bzero(from, sizeof(KeyInfo)); 49734345a63Smrg return True; 49834345a63Smrg } 49934345a63Smrg report = ((warningLevel > 9) || 50034345a63Smrg ((into->defs.fileID == from->defs.fileID) 50134345a63Smrg && (warningLevel > 0))); 50234345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 50334345a63Smrg { 50434345a63Smrg if (from->numLevels[i] > 0) 50534345a63Smrg { 50634345a63Smrg if (into->numLevels[i] == 0) 50734345a63Smrg { 50834345a63Smrg into->numLevels[i] = from->numLevels[i]; 50934345a63Smrg into->syms[i] = from->syms[i]; 51034345a63Smrg into->acts[i] = from->acts[i]; 51134345a63Smrg into->symsDefined |= (1 << i); 51234345a63Smrg from->syms[i] = NULL; 51334345a63Smrg from->acts[i] = NULL; 51434345a63Smrg from->numLevels[i] = 0; 51534345a63Smrg from->symsDefined &= ~(1 << i); 51634345a63Smrg if (into->syms[i]) 51734345a63Smrg into->defs.defined |= _Key_Syms; 51834345a63Smrg if (into->acts[i]) 51934345a63Smrg into->defs.defined |= _Key_Acts; 52034345a63Smrg } 52134345a63Smrg else 52234345a63Smrg { 52334345a63Smrg if (report) 52434345a63Smrg { 52534345a63Smrg if (into->syms[i]) 52634345a63Smrg collide |= _Key_Syms; 52734345a63Smrg if (into->acts[i]) 52834345a63Smrg collide |= _Key_Acts; 52934345a63Smrg } 53034345a63Smrg MergeKeyGroups(info, into, from, (unsigned) i); 53134345a63Smrg } 53234345a63Smrg } 53334345a63Smrg if (from->types[i] != None) 53434345a63Smrg { 53534345a63Smrg if ((into->types[i] != None) && (report) && 53634345a63Smrg (into->types[i] != from->types[i])) 53734345a63Smrg { 53834345a63Smrg Atom use, ignore; 53934345a63Smrg collide |= _Key_Types; 54034345a63Smrg if (from->defs.merge != MergeAugment) 54134345a63Smrg { 54234345a63Smrg use = from->types[i]; 54334345a63Smrg ignore = into->types[i]; 54434345a63Smrg } 54534345a63Smrg else 54634345a63Smrg { 54734345a63Smrg use = into->types[i]; 54834345a63Smrg ignore = from->types[i]; 54934345a63Smrg } 55034345a63Smrg WARN2 55134345a63Smrg ("Multiple definitions for group %d type of key %s\n", 55234345a63Smrg i, longText(into->name, XkbMessage)); 55334345a63Smrg ACTION2("Using %s, ignoring %s\n", 55434345a63Smrg XkbAtomText(NULL, use, XkbMessage), 55534345a63Smrg XkbAtomText(NULL, ignore, XkbMessage)); 55634345a63Smrg } 55734345a63Smrg if ((from->defs.merge != MergeAugment) 55834345a63Smrg || (into->types[i] == None)) 55934345a63Smrg { 56034345a63Smrg into->types[i] = from->types[i]; 56134345a63Smrg } 56234345a63Smrg } 56334345a63Smrg } 56434345a63Smrg if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide)) 56534345a63Smrg { 56634345a63Smrg into->behavior = from->behavior; 56734345a63Smrg into->nameForOverlayKey = from->nameForOverlayKey; 56834345a63Smrg into->defs.defined |= _Key_Behavior; 56934345a63Smrg } 57034345a63Smrg if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide)) 57134345a63Smrg { 57234345a63Smrg into->vmodmap = from->vmodmap; 57334345a63Smrg into->defs.defined |= _Key_VModMap; 57434345a63Smrg } 57534345a63Smrg if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide)) 57634345a63Smrg { 57734345a63Smrg into->repeat = from->repeat; 57834345a63Smrg into->defs.defined |= _Key_Repeat; 57934345a63Smrg } 58034345a63Smrg if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide)) 58134345a63Smrg { 58234345a63Smrg into->dfltType = from->dfltType; 58334345a63Smrg into->defs.defined |= _Key_Type_Dflt; 58434345a63Smrg } 58534345a63Smrg if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide)) 58634345a63Smrg { 58734345a63Smrg into->groupInfo = from->groupInfo; 58834345a63Smrg into->defs.defined |= _Key_GroupInfo; 58934345a63Smrg } 59034345a63Smrg if (collide) 59134345a63Smrg { 59234345a63Smrg WARN1("Symbol map for key %s redefined\n", 59334345a63Smrg longText(into->name, XkbMessage)); 59434345a63Smrg ACTION1("Using %s definition for conflicting fields\n", 59534345a63Smrg (from->defs.merge == MergeAugment ? "first" : "last")); 596f46a6179Smrg } 597f46a6179Smrg return True; 598f46a6179Smrg} 599f46a6179Smrg 600f46a6179Smrgstatic Bool 60134345a63SmrgAddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbDescPtr xkb) 602f46a6179Smrg{ 60334345a63Smrg register int i; 60434345a63Smrg unsigned long real_name; 60534345a63Smrg 60634345a63Smrg for (i = 0; i < info->nKeys; i++) 60734345a63Smrg { 60834345a63Smrg if (info->keys[i].name == key->name) 60934345a63Smrg return MergeKeys(info, &info->keys[i], key); 61034345a63Smrg } 61134345a63Smrg if (FindKeyNameForAlias(xkb, key->name, &real_name)) 61234345a63Smrg { 61334345a63Smrg for (i = 0; i < info->nKeys; i++) 61434345a63Smrg { 61534345a63Smrg if (info->keys[i].name == real_name) 61634345a63Smrg return MergeKeys(info, &info->keys[i], key); 617f46a6179Smrg } 618f46a6179Smrg } 61934345a63Smrg if (info->nKeys >= info->szKeys) 62034345a63Smrg { 62134345a63Smrg info->szKeys += SYMBOLS_CHUNK; 62234345a63Smrg info->keys = 62334345a63Smrg uTypedRecalloc(info->keys, info->nKeys, info->szKeys, KeyInfo); 62434345a63Smrg if (!info->keys) 62534345a63Smrg { 62634345a63Smrg WSGO("Could not allocate key symbols descriptions\n"); 62734345a63Smrg ACTION("Some key symbols definitions may be lost\n"); 62834345a63Smrg return False; 62934345a63Smrg } 630f46a6179Smrg } 63134345a63Smrg return CopyKeyInfo(key, &info->keys[info->nKeys++], True); 632f46a6179Smrg} 633f46a6179Smrg 634f46a6179Smrgstatic Bool 63534345a63SmrgAddModMapEntry(SymbolsInfo * info, ModMapEntry * new) 636f46a6179Smrg{ 63734345a63Smrg ModMapEntry *mm; 63834345a63Smrg Bool clobber; 63934345a63Smrg 64034345a63Smrg clobber = (new->defs.merge != MergeAugment); 64134345a63Smrg for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next) 64234345a63Smrg { 64334345a63Smrg if (new->haveSymbol && mm->haveSymbol 64434345a63Smrg && (new->u.keySym == mm->u.keySym)) 64534345a63Smrg { 64634345a63Smrg unsigned use, ignore; 64734345a63Smrg if (mm->modifier != new->modifier) 64834345a63Smrg { 64934345a63Smrg if (clobber) 65034345a63Smrg { 65134345a63Smrg use = new->modifier; 65234345a63Smrg ignore = mm->modifier; 65334345a63Smrg } 65434345a63Smrg else 65534345a63Smrg { 65634345a63Smrg use = mm->modifier; 65734345a63Smrg ignore = new->modifier; 65834345a63Smrg } 65934345a63Smrg ERROR1 66034345a63Smrg ("%s added to symbol map for multiple modifiers\n", 66134345a63Smrg XkbKeysymText(new->u.keySym, XkbMessage)); 66234345a63Smrg ACTION2("Using %s, ignoring %s.\n", 66334345a63Smrg XkbModIndexText(use, XkbMessage), 66434345a63Smrg XkbModIndexText(ignore, XkbMessage)); 66534345a63Smrg mm->modifier = use; 66634345a63Smrg } 66734345a63Smrg return True; 66834345a63Smrg } 66934345a63Smrg if ((!new->haveSymbol) && (!mm->haveSymbol) && 67034345a63Smrg (new->u.keyName == mm->u.keyName)) 67134345a63Smrg { 67234345a63Smrg unsigned use, ignore; 67334345a63Smrg if (mm->modifier != new->modifier) 67434345a63Smrg { 67534345a63Smrg if (clobber) 67634345a63Smrg { 67734345a63Smrg use = new->modifier; 67834345a63Smrg ignore = mm->modifier; 67934345a63Smrg } 68034345a63Smrg else 68134345a63Smrg { 68234345a63Smrg use = mm->modifier; 68334345a63Smrg ignore = new->modifier; 68434345a63Smrg } 68534345a63Smrg ERROR1("Key %s added to map for multiple modifiers\n", 68634345a63Smrg longText(new->u.keyName, XkbMessage)); 68734345a63Smrg ACTION2("Using %s, ignoring %s.\n", 68834345a63Smrg XkbModIndexText(use, XkbMessage), 68934345a63Smrg XkbModIndexText(ignore, XkbMessage)); 69034345a63Smrg mm->modifier = use; 69134345a63Smrg } 69234345a63Smrg return True; 69334345a63Smrg } 69434345a63Smrg } 69534345a63Smrg mm = uTypedAlloc(ModMapEntry); 69634345a63Smrg if (mm == NULL) 69734345a63Smrg { 69834345a63Smrg WSGO("Could not allocate modifier map entry\n"); 69934345a63Smrg ACTION1("Modifier map for %s will be incomplete\n", 70034345a63Smrg XkbModIndexText(new->modifier, XkbMessage)); 70134345a63Smrg return False; 70234345a63Smrg } 70334345a63Smrg *mm = *new; 70434345a63Smrg mm->defs.next = &info->modMap->defs; 70534345a63Smrg info->modMap = mm; 706f46a6179Smrg return True; 707f46a6179Smrg} 708f46a6179Smrg 709f46a6179Smrg/***====================================================================***/ 710f46a6179Smrg 711f46a6179Smrgstatic void 71234345a63SmrgMergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from, 71334345a63Smrg unsigned merge, XkbDescPtr xkb) 714f46a6179Smrg{ 71534345a63Smrg register int i; 71634345a63Smrg KeyInfo *key; 71734345a63Smrg 71834345a63Smrg if (from->errorCount > 0) 71934345a63Smrg { 72034345a63Smrg into->errorCount += from->errorCount; 72134345a63Smrg return; 72234345a63Smrg } 72334345a63Smrg if (into->name == NULL) 72434345a63Smrg { 72534345a63Smrg into->name = from->name; 72634345a63Smrg from->name = NULL; 72734345a63Smrg } 72834345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 72934345a63Smrg { 73034345a63Smrg if (from->groupNames[i] != None) 73134345a63Smrg { 73234345a63Smrg if ((merge != MergeAugment) || (into->groupNames[i] == None)) 73334345a63Smrg into->groupNames[i] = from->groupNames[i]; 73434345a63Smrg } 73534345a63Smrg } 73634345a63Smrg for (i = 0, key = from->keys; i < from->nKeys; i++, key++) 73734345a63Smrg { 73834345a63Smrg if (merge != MergeDefault) 73934345a63Smrg key->defs.merge = merge; 74034345a63Smrg if (!AddKeySymbols(into, key, xkb)) 74134345a63Smrg into->errorCount++; 74234345a63Smrg } 74334345a63Smrg if (from->modMap != NULL) 74434345a63Smrg { 74534345a63Smrg ModMapEntry *mm, *next; 74634345a63Smrg for (mm = from->modMap; mm != NULL; mm = next) 74734345a63Smrg { 74834345a63Smrg if (merge != MergeDefault) 74934345a63Smrg mm->defs.merge = merge; 75034345a63Smrg if (!AddModMapEntry(into, mm)) 75134345a63Smrg into->errorCount++; 75234345a63Smrg next = (ModMapEntry *) mm->defs.next; 75334345a63Smrg uFree(mm); 75434345a63Smrg } 75534345a63Smrg from->modMap = NULL; 75634345a63Smrg } 75734345a63Smrg if (!MergeAliases(&into->aliases, &from->aliases, merge)) 75834345a63Smrg into->errorCount++; 759f46a6179Smrg return; 760f46a6179Smrg} 761f46a6179Smrg 76234345a63Smrgtypedef void (*FileHandler) (XkbFile * /* rtrn */ , 76334345a63Smrg XkbDescPtr /* xkb */ , 76434345a63Smrg unsigned /* merge */ , 76534345a63Smrg SymbolsInfo * /* included */ 76634345a63Smrg ); 767f46a6179Smrg 768f46a6179Smrgstatic Bool 76934345a63SmrgHandleIncludeSymbols(IncludeStmt * stmt, 77034345a63Smrg XkbDescPtr xkb, SymbolsInfo * info, FileHandler hndlr) 771f46a6179Smrg{ 77234345a63Smrg unsigned newMerge; 77334345a63Smrg XkbFile *rtrn; 77434345a63Smrg SymbolsInfo included; 77534345a63Smrg Bool haveSelf; 77634345a63Smrg 77734345a63Smrg haveSelf = False; 77834345a63Smrg if ((stmt->file == NULL) && (stmt->map == NULL)) 77934345a63Smrg { 78034345a63Smrg haveSelf = True; 78134345a63Smrg included = *info; 78234345a63Smrg bzero(info, sizeof(SymbolsInfo)); 78334345a63Smrg } 78434345a63Smrg else if (ProcessIncludeFile(stmt, XkmSymbolsIndex, &rtrn, &newMerge)) 78534345a63Smrg { 78634345a63Smrg InitSymbolsInfo(&included, xkb); 78734345a63Smrg included.fileID = included.dflt.defs.fileID = rtrn->id; 78834345a63Smrg included.merge = included.dflt.defs.merge = MergeOverride; 78934345a63Smrg if (stmt->modifier) 79034345a63Smrg { 79134345a63Smrg included.explicit_group = atoi(stmt->modifier) - 1; 79234345a63Smrg } 79334345a63Smrg else 79434345a63Smrg { 79534345a63Smrg included.explicit_group = info->explicit_group; 79634345a63Smrg } 79734345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &included); 79834345a63Smrg if (stmt->stmt != NULL) 79934345a63Smrg { 80034345a63Smrg if (included.name != NULL) 80134345a63Smrg uFree(included.name); 80234345a63Smrg included.name = stmt->stmt; 80334345a63Smrg stmt->stmt = NULL; 80434345a63Smrg } 80534345a63Smrg } 80634345a63Smrg else 80734345a63Smrg { 80834345a63Smrg info->errorCount += 10; 80934345a63Smrg return False; 81034345a63Smrg } 81134345a63Smrg if ((stmt->next != NULL) && (included.errorCount < 1)) 81234345a63Smrg { 81334345a63Smrg IncludeStmt *next; 81434345a63Smrg unsigned op; 81534345a63Smrg SymbolsInfo next_incl; 81634345a63Smrg 81734345a63Smrg for (next = stmt->next; next != NULL; next = next->next) 81834345a63Smrg { 81934345a63Smrg if ((next->file == NULL) && (next->map == NULL)) 82034345a63Smrg { 82134345a63Smrg haveSelf = True; 82234345a63Smrg MergeIncludedSymbols(&included, info, next->merge, xkb); 82334345a63Smrg FreeSymbolsInfo(info); 82434345a63Smrg } 82534345a63Smrg else if (ProcessIncludeFile(next, XkmSymbolsIndex, &rtrn, &op)) 82634345a63Smrg { 82734345a63Smrg InitSymbolsInfo(&next_incl, xkb); 82834345a63Smrg next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id; 82934345a63Smrg next_incl.merge = next_incl.dflt.defs.merge = MergeOverride; 83034345a63Smrg if (next->modifier) 83134345a63Smrg { 83234345a63Smrg next_incl.explicit_group = atoi(next->modifier) - 1; 83334345a63Smrg } 83434345a63Smrg else 83534345a63Smrg { 83634345a63Smrg next_incl.explicit_group = info->explicit_group; 837f46a6179Smrg } 83834345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); 83934345a63Smrg MergeIncludedSymbols(&included, &next_incl, op, xkb); 84034345a63Smrg FreeSymbolsInfo(&next_incl); 84134345a63Smrg } 84234345a63Smrg else 84334345a63Smrg { 84434345a63Smrg info->errorCount += 10; 84534345a63Smrg return False; 84634345a63Smrg } 84734345a63Smrg } 848f46a6179Smrg } 849f46a6179Smrg if (haveSelf) 85034345a63Smrg *info = included; 85134345a63Smrg else 85234345a63Smrg { 85334345a63Smrg MergeIncludedSymbols(info, &included, newMerge, xkb); 85434345a63Smrg FreeSymbolsInfo(&included); 855f46a6179Smrg } 85634345a63Smrg return (info->errorCount == 0); 857f46a6179Smrg} 858f46a6179Smrg 85934345a63Smrgstatic LookupEntry groupNames[] = { 86034345a63Smrg {"group1", 1}, 86134345a63Smrg {"group2", 2}, 86234345a63Smrg {"group3", 3}, 86334345a63Smrg {"group4", 4}, 86434345a63Smrg {"group5", 5}, 86534345a63Smrg {"group6", 6}, 86634345a63Smrg {"group7", 7}, 86734345a63Smrg {"group8", 8}, 86834345a63Smrg {NULL, 0} 869f46a6179Smrg}; 870f46a6179Smrg 871f46a6179Smrg 872f46a6179Smrg#define SYMBOLS 1 873f46a6179Smrg#define ACTIONS 2 874f46a6179Smrg 875f46a6179Smrgstatic Bool 87634345a63SmrgGetGroupIndex(KeyInfo * key, 87734345a63Smrg ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn) 878f46a6179Smrg{ 87934345a63Smrg const char *name; 88034345a63Smrg ExprResult tmp; 88134345a63Smrg 88234345a63Smrg if (what == SYMBOLS) 88334345a63Smrg name = "symbols"; 88434345a63Smrg else 88534345a63Smrg name = "actions"; 88634345a63Smrg 88734345a63Smrg if (arrayNdx == NULL) 88834345a63Smrg { 88934345a63Smrg register int i; 89034345a63Smrg unsigned defined; 89134345a63Smrg if (what == SYMBOLS) 89234345a63Smrg defined = key->symsDefined; 89334345a63Smrg else 89434345a63Smrg defined = key->actsDefined; 89534345a63Smrg 89634345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 89734345a63Smrg { 89834345a63Smrg if ((defined & (1 << i)) == 0) 89934345a63Smrg { 90034345a63Smrg *ndx_rtrn = i; 90134345a63Smrg return True; 90234345a63Smrg } 90334345a63Smrg } 90434345a63Smrg ERROR3("Too many groups of %s for key %s (max %d)\n", name, 90534345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 90634345a63Smrg ACTION1("Ignoring %s defined for extra groups\n", name); 90734345a63Smrg return False; 90834345a63Smrg } 90934345a63Smrg if (!ExprResolveInteger 91034345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 91134345a63Smrg { 91234345a63Smrg ERROR2("Illegal group index for %s of key %s\n", name, 91334345a63Smrg longText(key->name, XkbMessage)); 91434345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 91534345a63Smrg return False; 91634345a63Smrg } 91734345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 91834345a63Smrg { 91934345a63Smrg ERROR3("Group index for %s of key %s is out of range (1..%d)\n", 92034345a63Smrg name, longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 92134345a63Smrg ACTION2("Ignoring %s for group %d\n", name, tmp.uval); 92234345a63Smrg return False; 92334345a63Smrg } 92434345a63Smrg *ndx_rtrn = tmp.uval - 1; 925f46a6179Smrg return True; 926f46a6179Smrg} 927f46a6179Smrg 928f46a6179Smrgstatic Bool 92934345a63SmrgAddSymbolsToKey(KeyInfo * key, 93034345a63Smrg XkbDescPtr xkb, 93134345a63Smrg char *field, 93234345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 933f46a6179Smrg{ 93434345a63Smrg unsigned ndx, nSyms; 93534345a63Smrg int i; 93634345a63Smrg 93734345a63Smrg if (!GetGroupIndex(key, arrayNdx, SYMBOLS, &ndx)) 93834345a63Smrg return False; 93934345a63Smrg if (value == NULL) 94034345a63Smrg { 94134345a63Smrg key->symsDefined |= (1 << ndx); 94234345a63Smrg return True; 94334345a63Smrg } 94434345a63Smrg if (value->op != ExprKeysymList) 94534345a63Smrg { 94634345a63Smrg ERROR1("Expected a list of symbols, found %s\n", 94734345a63Smrg exprOpText(value->op)); 94834345a63Smrg ACTION2("Ignoring symbols for group %d of %s\n", ndx, 94934345a63Smrg longText(key->name, XkbMessage)); 95034345a63Smrg return False; 95134345a63Smrg } 95234345a63Smrg if (key->syms[ndx] != NULL) 95334345a63Smrg { 95434345a63Smrg WSGO2("Symbols for key %s, group %d already defined\n", 95534345a63Smrg longText(key->name, XkbMessage), ndx); 95634345a63Smrg return False; 95734345a63Smrg } 95834345a63Smrg nSyms = value->value.list.nSyms; 95934345a63Smrg if (((key->numLevels[ndx] < nSyms) || (key->syms[ndx] == NULL)) && 96034345a63Smrg (!ResizeKeyGroup(key, ndx, nSyms, False))) 96134345a63Smrg { 96234345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 96334345a63Smrg longText(key->name, XkbMessage)); 96434345a63Smrg ACTION("Symbols lost\n"); 96534345a63Smrg return False; 96634345a63Smrg } 96734345a63Smrg key->symsDefined |= (1 << ndx); 96883e5f723Smrg for (i = 0; i < nSyms; i++) { 96983e5f723Smrg if (!LookupKeysym(value->value.list.syms[i], &key->syms[ndx][i])) { 97083e5f723Smrg WSGO1("Could not resolve keysym %s\n", value->value.list.syms[i]); 97183e5f723Smrg key->syms[ndx][i] = NoSymbol; 97283e5f723Smrg } 97383e5f723Smrg } 97434345a63Smrg for (i = key->numLevels[ndx] - 1; 97534345a63Smrg (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--) 97634345a63Smrg { 97734345a63Smrg key->numLevels[ndx]--; 978f46a6179Smrg } 979f46a6179Smrg return True; 980f46a6179Smrg} 981f46a6179Smrg 982f46a6179Smrgstatic Bool 98334345a63SmrgAddActionsToKey(KeyInfo * key, 98434345a63Smrg XkbDescPtr xkb, 98534345a63Smrg char *field, 98634345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 987f46a6179Smrg{ 98834345a63Smrg register int i; 98934345a63Smrg unsigned ndx, nActs; 99034345a63Smrg ExprDef *act; 99134345a63Smrg XkbAnyAction *toAct; 99234345a63Smrg 99334345a63Smrg if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx)) 99434345a63Smrg return False; 99534345a63Smrg 99634345a63Smrg if (value == NULL) 99734345a63Smrg { 99834345a63Smrg key->actsDefined |= (1 << ndx); 99934345a63Smrg return True; 100034345a63Smrg } 100134345a63Smrg if (value->op != ExprActionList) 100234345a63Smrg { 100334345a63Smrg WSGO1("Bad expression type (%d) for action list value\n", value->op); 100434345a63Smrg ACTION2("Ignoring actions for group %d of %s\n", ndx, 100534345a63Smrg longText(key->name, XkbMessage)); 100634345a63Smrg return False; 100734345a63Smrg } 100834345a63Smrg if (key->acts[ndx] != NULL) 100934345a63Smrg { 101034345a63Smrg WSGO2("Actions for key %s, group %d already defined\n", 101134345a63Smrg longText(key->name, XkbMessage), ndx); 101234345a63Smrg return False; 101334345a63Smrg } 101434345a63Smrg for (nActs = 0, act = value->value.child; act != NULL; nActs++) 101534345a63Smrg { 101634345a63Smrg act = (ExprDef *) act->common.next; 101734345a63Smrg } 101834345a63Smrg if (nActs < 1) 101934345a63Smrg { 102034345a63Smrg WSGO("Action list but not actions in AddActionsToKey\n"); 102134345a63Smrg return False; 102234345a63Smrg } 102334345a63Smrg if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) && 102434345a63Smrg (!ResizeKeyGroup(key, ndx, nActs, True))) 102534345a63Smrg { 102634345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 102734345a63Smrg longText(key->name, XkbMessage)); 102834345a63Smrg ACTION("Actions lost\n"); 102934345a63Smrg return False; 103034345a63Smrg } 103134345a63Smrg key->actsDefined |= (1 << ndx); 103234345a63Smrg 103334345a63Smrg toAct = (XkbAnyAction *) key->acts[ndx]; 103434345a63Smrg act = value->value.child; 103534345a63Smrg for (i = 0; i < nActs; i++, toAct++) 103634345a63Smrg { 103734345a63Smrg if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action)) 103834345a63Smrg { 103934345a63Smrg ERROR1("Illegal action definition for %s\n", 104034345a63Smrg longText(key->name, XkbMessage)); 104134345a63Smrg ACTION2("Action for group %d/level %d ignored\n", ndx + 1, i + 1); 104234345a63Smrg } 104334345a63Smrg act = (ExprDef *) act->common.next; 1044f46a6179Smrg } 1045f46a6179Smrg return True; 1046f46a6179Smrg} 1047f46a6179Smrg 1048f46a6179Smrgstatic int 104934345a63SmrgSetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value) 1050f46a6179Smrg{ 105134345a63Smrg ExprResult tmp; 105234345a63Smrg unsigned radio_groups = 0; 105334345a63Smrg 105434345a63Smrg if (arrayNdx == NULL) 105534345a63Smrg { 105634345a63Smrg radio_groups = XkbAllRadioGroupsMask; 105734345a63Smrg } 105834345a63Smrg else 105934345a63Smrg { 106034345a63Smrg if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL)) 106134345a63Smrg { 106234345a63Smrg ERROR("Illegal index in group name definition\n"); 106334345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 106434345a63Smrg return False; 106534345a63Smrg } 106634345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 106734345a63Smrg { 106834345a63Smrg ERROR1("Illegal radio group specified (must be 1..%d)\n", 106934345a63Smrg XkbMaxRadioGroups + 1); 107034345a63Smrg ACTION1("Value of \"allow none\" for group %d ignored\n", 107134345a63Smrg tmp.uval); 107234345a63Smrg return False; 107334345a63Smrg } 107434345a63Smrg radio_groups |= (1 << (tmp.uval - 1)); 107534345a63Smrg } 107634345a63Smrg if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) 107734345a63Smrg { 107834345a63Smrg ERROR1("Illegal \"allow none\" value for %s\n", 107934345a63Smrg longText(key->name, XkbMessage)); 108034345a63Smrg ACTION("Non-boolean value ignored\n"); 108134345a63Smrg return False; 108234345a63Smrg } 108334345a63Smrg if (tmp.uval) 108434345a63Smrg key->allowNone |= radio_groups; 108534345a63Smrg else 108634345a63Smrg key->allowNone &= ~radio_groups; 1087f46a6179Smrg return True; 1088f46a6179Smrg} 1089f46a6179Smrg 1090f46a6179Smrg 109134345a63Smrgstatic LookupEntry lockingEntries[] = { 109234345a63Smrg {"true", XkbKB_Lock}, 109334345a63Smrg {"yes", XkbKB_Lock}, 109434345a63Smrg {"on", XkbKB_Lock}, 109534345a63Smrg {"false", XkbKB_Default}, 109634345a63Smrg {"no", XkbKB_Default}, 109734345a63Smrg {"off", XkbKB_Default}, 109834345a63Smrg {"permanent", XkbKB_Lock | XkbKB_Permanent}, 109934345a63Smrg {NULL, 0} 1100f46a6179Smrg}; 1101f46a6179Smrg 110234345a63Smrgstatic LookupEntry repeatEntries[] = { 110334345a63Smrg {"true", RepeatYes}, 110434345a63Smrg {"yes", RepeatYes}, 110534345a63Smrg {"on", RepeatYes}, 110634345a63Smrg {"false", RepeatNo}, 110734345a63Smrg {"no", RepeatNo}, 110834345a63Smrg {"off", RepeatNo}, 110934345a63Smrg {"default", RepeatUndefined}, 111034345a63Smrg {NULL, 0} 1111f46a6179Smrg}; 1112f46a6179Smrg 111334345a63Smrgstatic LookupEntry rgEntries[] = { 111434345a63Smrg {"none", 0}, 111534345a63Smrg {NULL, 0} 1116f46a6179Smrg}; 1117f46a6179Smrg 1118f46a6179Smrgstatic Bool 111934345a63SmrgSetSymbolsField(KeyInfo * key, 112034345a63Smrg XkbDescPtr xkb, 112134345a63Smrg char *field, 112234345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 1123f46a6179Smrg{ 112434345a63Smrg Bool ok = True; 112534345a63Smrg ExprResult tmp; 112634345a63Smrg 112734345a63Smrg if (uStrCaseCmp(field, "type") == 0) 112834345a63Smrg { 112934345a63Smrg ExprResult ndx; 113034345a63Smrg if ((!ExprResolveString(value, &tmp, NULL, NULL)) 113134345a63Smrg && (warningLevel > 0)) 113234345a63Smrg { 113334345a63Smrg WARN("The type field of a key symbol map must be a string\n"); 113434345a63Smrg ACTION("Ignoring illegal type definition\n"); 113534345a63Smrg } 113634345a63Smrg if (arrayNdx == NULL) 113734345a63Smrg { 113834345a63Smrg key->dfltType = XkbInternAtom(NULL, tmp.str, False); 113934345a63Smrg key->defs.defined |= _Key_Type_Dflt; 114034345a63Smrg } 114134345a63Smrg else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup, 114234345a63Smrg (XPointer) groupNames)) 114334345a63Smrg { 114434345a63Smrg ERROR1("Illegal group index for type of key %s\n", 114534345a63Smrg longText(key->name, XkbMessage)); 114634345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 114734345a63Smrg return False; 114834345a63Smrg } 114934345a63Smrg else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups)) 115034345a63Smrg { 115134345a63Smrg ERROR2 115234345a63Smrg ("Group index for type of key %s is out of range (1..%d)\n", 115334345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 115434345a63Smrg ACTION1("Ignoring type for group %d\n", ndx.uval); 115534345a63Smrg return False; 115634345a63Smrg } 115734345a63Smrg else 115834345a63Smrg { 115934345a63Smrg key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False); 116034345a63Smrg key->typesDefined |= (1 << (ndx.uval - 1)); 116134345a63Smrg } 116234345a63Smrg } 116334345a63Smrg else if (uStrCaseCmp(field, "symbols") == 0) 116434345a63Smrg return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info); 116534345a63Smrg else if (uStrCaseCmp(field, "actions") == 0) 116634345a63Smrg return AddActionsToKey(key, xkb, field, arrayNdx, value, info); 116734345a63Smrg else if ((uStrCaseCmp(field, "vmods") == 0) || 116834345a63Smrg (uStrCaseCmp(field, "virtualmods") == 0) || 116934345a63Smrg (uStrCaseCmp(field, "virtualmodifiers") == 0)) 117034345a63Smrg { 117134345a63Smrg ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb); 117234345a63Smrg if (ok) 117334345a63Smrg { 117434345a63Smrg key->vmodmap = (tmp.uval >> 8); 117534345a63Smrg key->defs.defined |= _Key_VModMap; 117634345a63Smrg } 117734345a63Smrg else 117834345a63Smrg { 117934345a63Smrg ERROR1("Expected a virtual modifier mask, found %s\n", 118034345a63Smrg exprOpText(value->op)); 118134345a63Smrg ACTION1("Ignoring virtual modifiers definition for key %s\n", 118234345a63Smrg longText(key->name, XkbMessage)); 118334345a63Smrg } 118434345a63Smrg } 118534345a63Smrg else if ((uStrCaseCmp(field, "locking") == 0) 118634345a63Smrg || (uStrCaseCmp(field, "lock") == 0) 118734345a63Smrg || (uStrCaseCmp(field, "locks") == 0)) 118834345a63Smrg { 118934345a63Smrg ok = ExprResolveEnum(value, &tmp, lockingEntries); 119034345a63Smrg if (ok) 119134345a63Smrg key->behavior.type = tmp.uval; 119234345a63Smrg key->defs.defined |= _Key_Behavior; 119334345a63Smrg } 119434345a63Smrg else if ((uStrCaseCmp(field, "radiogroup") == 0) || 119534345a63Smrg (uStrCaseCmp(field, "permanentradiogroup") == 0)) 119634345a63Smrg { 119734345a63Smrg Bool permanent = False; 119834345a63Smrg if (uStrCaseCmp(field, "permanentradiogroup") == 0) 119934345a63Smrg permanent = True; 120034345a63Smrg ok = ExprResolveInteger(value, &tmp, SimpleLookup, 120134345a63Smrg (XPointer) rgEntries); 120234345a63Smrg if (!ok) 120334345a63Smrg { 120434345a63Smrg ERROR1("Illegal radio group specification for %s\n", 120534345a63Smrg longText(key->name, XkbMessage)); 120634345a63Smrg ACTION("Non-integer radio group ignored\n"); 120734345a63Smrg return False; 120834345a63Smrg } 120934345a63Smrg if (tmp.uval == 0) 121034345a63Smrg { 121134345a63Smrg key->behavior.type = XkbKB_Default; 121234345a63Smrg key->behavior.data = 0; 121334345a63Smrg return ok; 121434345a63Smrg } 121534345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 121634345a63Smrg { 121734345a63Smrg ERROR1 121834345a63Smrg ("Radio group specification for %s out of range (1..32)\n", 121934345a63Smrg longText(key->name, XkbMessage)); 122034345a63Smrg ACTION1("Illegal radio group %d ignored\n", tmp.uval); 122134345a63Smrg return False; 122234345a63Smrg } 122334345a63Smrg key->behavior.type = 122434345a63Smrg XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0); 122534345a63Smrg key->behavior.data = tmp.uval - 1; 122634345a63Smrg if (key->allowNone & (1 << (tmp.uval - 1))) 122734345a63Smrg key->behavior.data |= XkbKB_RGAllowNone; 122834345a63Smrg key->defs.defined |= _Key_Behavior; 122934345a63Smrg } 123034345a63Smrg else if (uStrCaseEqual(field, "allownone")) 123134345a63Smrg { 123234345a63Smrg ok = SetAllowNone(key, arrayNdx, value); 123334345a63Smrg } 123434345a63Smrg else if (uStrCasePrefix("overlay", field) || 123534345a63Smrg uStrCasePrefix("permanentoverlay", field)) 123634345a63Smrg { 123734345a63Smrg Bool permanent = False; 123834345a63Smrg char *which; 123934345a63Smrg int overlayNdx; 124034345a63Smrg if (uStrCasePrefix("permanent", field)) 124134345a63Smrg { 124234345a63Smrg permanent = True; 124334345a63Smrg which = &field[sizeof("permanentoverlay") - 1]; 124434345a63Smrg } 124534345a63Smrg else 124634345a63Smrg { 124734345a63Smrg which = &field[sizeof("overlay") - 1]; 124834345a63Smrg } 124934345a63Smrg if (sscanf(which, "%d", &overlayNdx) == 1) 125034345a63Smrg { 125134345a63Smrg if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0)) 125234345a63Smrg { 125334345a63Smrg ERROR2("Illegal overlay %d specified for %s\n", 125434345a63Smrg overlayNdx, longText(key->name, XkbMessage)); 125534345a63Smrg ACTION("Ignored\n"); 125634345a63Smrg return False; 125734345a63Smrg } 125834345a63Smrg } 125934345a63Smrg else if (*which == '\0') 126034345a63Smrg overlayNdx = 1; 126134345a63Smrg else if (warningLevel > 0) 126234345a63Smrg { 126334345a63Smrg ERROR2("Illegal overlay \"%s\" specified for %s\n", 126434345a63Smrg which, longText(key->name, XkbMessage)); 126534345a63Smrg ACTION("Ignored\n"); 126634345a63Smrg return False; 126734345a63Smrg } 126834345a63Smrg ok = ExprResolveKeyName(value, &tmp, NULL, NULL); 126934345a63Smrg if (!ok) 127034345a63Smrg { 127134345a63Smrg ERROR1("Illegal overlay key specification for %s\n", 127234345a63Smrg longText(key->name, XkbMessage)); 127334345a63Smrg ACTION("Overlay key must be specified by name\n"); 127434345a63Smrg return False; 127534345a63Smrg } 127634345a63Smrg if (overlayNdx == 1) 127734345a63Smrg key->behavior.type = XkbKB_Overlay1; 127834345a63Smrg else 127934345a63Smrg key->behavior.type = XkbKB_Overlay2; 128034345a63Smrg if (permanent) 128134345a63Smrg key->behavior.type |= XkbKB_Permanent; 128234345a63Smrg 128334345a63Smrg key->behavior.data = 0; 128434345a63Smrg key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name); 128534345a63Smrg key->defs.defined |= _Key_Behavior; 128634345a63Smrg } 128734345a63Smrg else if ((uStrCaseCmp(field, "repeating") == 0) || 128834345a63Smrg (uStrCaseCmp(field, "repeats") == 0) || 128934345a63Smrg (uStrCaseCmp(field, "repeat") == 0)) 129034345a63Smrg { 129134345a63Smrg ok = ExprResolveEnum(value, &tmp, repeatEntries); 129234345a63Smrg if (!ok) 129334345a63Smrg { 129434345a63Smrg ERROR1("Illegal repeat setting for %s\n", 129534345a63Smrg longText(key->name, XkbMessage)); 129634345a63Smrg ACTION("Non-boolean repeat setting ignored\n"); 129734345a63Smrg return False; 129834345a63Smrg } 129934345a63Smrg key->repeat = tmp.uval; 130034345a63Smrg key->defs.defined |= _Key_Repeat; 130134345a63Smrg } 130234345a63Smrg else if ((uStrCaseCmp(field, "groupswrap") == 0) || 130334345a63Smrg (uStrCaseCmp(field, "wrapgroups") == 0)) 130434345a63Smrg { 130534345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 130634345a63Smrg if (!ok) 130734345a63Smrg { 130834345a63Smrg ERROR1("Illegal groupsWrap setting for %s\n", 130934345a63Smrg longText(key->name, XkbMessage)); 131034345a63Smrg ACTION("Non-boolean value ignored\n"); 131134345a63Smrg return False; 131234345a63Smrg } 131334345a63Smrg if (tmp.uval) 131434345a63Smrg key->groupInfo = XkbWrapIntoRange; 131534345a63Smrg else 131634345a63Smrg key->groupInfo = XkbClampIntoRange; 131734345a63Smrg key->defs.defined |= _Key_GroupInfo; 131834345a63Smrg } 131934345a63Smrg else if ((uStrCaseCmp(field, "groupsclamp") == 0) || 132034345a63Smrg (uStrCaseCmp(field, "clampgroups") == 0)) 132134345a63Smrg { 132234345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 132334345a63Smrg if (!ok) 132434345a63Smrg { 132534345a63Smrg ERROR1("Illegal groupsClamp setting for %s\n", 132634345a63Smrg longText(key->name, XkbMessage)); 132734345a63Smrg ACTION("Non-boolean value ignored\n"); 132834345a63Smrg return False; 132934345a63Smrg } 133034345a63Smrg if (tmp.uval) 133134345a63Smrg key->groupInfo = XkbClampIntoRange; 133234345a63Smrg else 133334345a63Smrg key->groupInfo = XkbWrapIntoRange; 133434345a63Smrg key->defs.defined |= _Key_GroupInfo; 133534345a63Smrg } 133634345a63Smrg else if ((uStrCaseCmp(field, "groupsredirect") == 0) || 133734345a63Smrg (uStrCaseCmp(field, "redirectgroups") == 0)) 133834345a63Smrg { 133934345a63Smrg if (!ExprResolveInteger 134034345a63Smrg (value, &tmp, SimpleLookup, (XPointer) groupNames)) 134134345a63Smrg { 134234345a63Smrg ERROR1("Illegal group index for redirect of key %s\n", 134334345a63Smrg longText(key->name, XkbMessage)); 134434345a63Smrg ACTION("Definition with non-integer group ignored\n"); 134534345a63Smrg return False; 134634345a63Smrg } 134734345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 134834345a63Smrg { 134934345a63Smrg ERROR2("Out-of-range (1..%d) group for redirect of key %s\n", 135034345a63Smrg XkbNumKbdGroups, longText(key->name, XkbMessage)); 135134345a63Smrg ERROR1("Ignoring illegal group %d\n", tmp.uval); 135234345a63Smrg return False; 135334345a63Smrg } 135434345a63Smrg key->groupInfo = 135534345a63Smrg XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1); 135634345a63Smrg key->defs.defined |= _Key_GroupInfo; 135734345a63Smrg } 135834345a63Smrg else 135934345a63Smrg { 136034345a63Smrg ERROR1("Unknown field %s in a symbol interpretation\n", field); 136134345a63Smrg ACTION("Definition ignored\n"); 136234345a63Smrg ok = False; 1363f46a6179Smrg } 1364f46a6179Smrg return ok; 1365f46a6179Smrg} 1366f46a6179Smrg 1367f46a6179Smrgstatic int 136834345a63SmrgSetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value) 1369f46a6179Smrg{ 137034345a63Smrg ExprResult tmp, name; 137134345a63Smrg 137234345a63Smrg if ((arrayNdx == NULL) && (warningLevel > 0)) 137334345a63Smrg { 137434345a63Smrg WARN("You must specify an index when specifying a group name\n"); 137534345a63Smrg ACTION("Group name definition without array subscript ignored\n"); 137634345a63Smrg return False; 137734345a63Smrg } 137834345a63Smrg if (!ExprResolveInteger 137934345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 138034345a63Smrg { 138134345a63Smrg ERROR("Illegal index in group name definition\n"); 138234345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 138334345a63Smrg return False; 138434345a63Smrg } 138534345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 138634345a63Smrg { 138734345a63Smrg ERROR1 138834345a63Smrg ("Attempt to specify name for illegal group (must be 1..%d)\n", 138934345a63Smrg XkbNumKbdGroups + 1); 139034345a63Smrg ACTION1("Name for group %d ignored\n", tmp.uval); 139134345a63Smrg return False; 139234345a63Smrg } 139334345a63Smrg if (!ExprResolveString(value, &name, NULL, NULL)) 139434345a63Smrg { 139534345a63Smrg ERROR("Group name must be a string\n"); 139634345a63Smrg ACTION1("Illegal name for group %d ignored\n", tmp.uval); 139734345a63Smrg return False; 139834345a63Smrg } 139934345a63Smrg info->groupNames[tmp.uval - 1 + info->explicit_group] = 140034345a63Smrg XkbInternAtom(NULL, name.str, False); 140134345a63Smrg 1402f46a6179Smrg return True; 1403f46a6179Smrg} 1404f46a6179Smrg 1405f46a6179Smrgstatic int 140634345a63SmrgHandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info) 1407f46a6179Smrg{ 140834345a63Smrg ExprResult elem, field, tmp; 140934345a63Smrg ExprDef *arrayNdx; 141034345a63Smrg 141134345a63Smrg if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0) 141234345a63Smrg return 0; /* internal error, already reported */ 141334345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) 141434345a63Smrg { 141534345a63Smrg return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx, 141634345a63Smrg stmt->value, info); 141734345a63Smrg } 141834345a63Smrg else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) || 141934345a63Smrg (uStrCaseCmp(field.str, "groupname") == 142034345a63Smrg 0))) 142134345a63Smrg { 142234345a63Smrg return SetGroupName(info, arrayNdx, stmt->value); 142334345a63Smrg } 142434345a63Smrg else if ((elem.str == NULL) 142534345a63Smrg && ((uStrCaseCmp(field.str, "groupswrap") == 0) 142634345a63Smrg || (uStrCaseCmp(field.str, "wrapgroups") == 0))) 142734345a63Smrg { 142834345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 142934345a63Smrg { 143034345a63Smrg ERROR("Illegal setting for global groupsWrap\n"); 143134345a63Smrg ACTION("Non-boolean value ignored\n"); 143234345a63Smrg return False; 143334345a63Smrg } 143434345a63Smrg if (tmp.uval) 143534345a63Smrg info->groupInfo = XkbWrapIntoRange; 143634345a63Smrg else 143734345a63Smrg info->groupInfo = XkbClampIntoRange; 143834345a63Smrg return True; 143934345a63Smrg } 144034345a63Smrg else if ((elem.str == NULL) 144134345a63Smrg && ((uStrCaseCmp(field.str, "groupsclamp") == 0) 144234345a63Smrg || (uStrCaseCmp(field.str, "clampgroups") == 0))) 144334345a63Smrg { 144434345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 144534345a63Smrg { 144634345a63Smrg ERROR("Illegal setting for global groupsClamp\n"); 144734345a63Smrg ACTION("Non-boolean value ignored\n"); 144834345a63Smrg return False; 144934345a63Smrg } 145034345a63Smrg if (tmp.uval) 145134345a63Smrg info->groupInfo = XkbClampIntoRange; 145234345a63Smrg else 145334345a63Smrg info->groupInfo = XkbWrapIntoRange; 145434345a63Smrg return True; 145534345a63Smrg } 145634345a63Smrg else if ((elem.str == NULL) 145734345a63Smrg && ((uStrCaseCmp(field.str, "groupsredirect") == 0) 145834345a63Smrg || (uStrCaseCmp(field.str, "redirectgroups") == 0))) 145934345a63Smrg { 146034345a63Smrg if (!ExprResolveInteger(stmt->value, &tmp, 146134345a63Smrg SimpleLookup, (XPointer) groupNames)) 146234345a63Smrg { 146334345a63Smrg ERROR("Illegal group index for global groupsRedirect\n"); 146434345a63Smrg ACTION("Definition with non-integer group ignored\n"); 146534345a63Smrg return False; 146634345a63Smrg } 146734345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 146834345a63Smrg { 146934345a63Smrg ERROR1 147034345a63Smrg ("Out-of-range (1..%d) group for global groupsRedirect\n", 147134345a63Smrg XkbNumKbdGroups); 147234345a63Smrg ACTION1("Ignoring illegal group %d\n", tmp.uval); 147334345a63Smrg return False; 147434345a63Smrg } 147534345a63Smrg info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval); 147634345a63Smrg return True; 147734345a63Smrg } 147834345a63Smrg else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0)) 147934345a63Smrg { 148034345a63Smrg return SetAllowNone(&info->dflt, arrayNdx, stmt->value); 148134345a63Smrg } 148234345a63Smrg return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value, 148334345a63Smrg &info->action); 1484f46a6179Smrg} 1485f46a6179Smrg 1486f46a6179Smrgstatic Bool 148734345a63SmrgHandleSymbolsBody(VarDef * def, 148834345a63Smrg XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info) 1489f46a6179Smrg{ 149034345a63Smrg Bool ok = True; 149134345a63Smrg ExprResult tmp, field; 149234345a63Smrg ExprDef *arrayNdx; 149334345a63Smrg 149434345a63Smrg for (; def != NULL; def = (VarDef *) def->common.next) 149534345a63Smrg { 149634345a63Smrg if ((def->name) && (def->name->type == ExprFieldRef)) 149734345a63Smrg { 149834345a63Smrg ok = HandleSymbolsVar(def, xkb, info); 149934345a63Smrg continue; 150034345a63Smrg } 150134345a63Smrg else 150234345a63Smrg { 150334345a63Smrg if (def->name == NULL) 150434345a63Smrg { 150534345a63Smrg if ((def->value == NULL) 150634345a63Smrg || (def->value->op == ExprKeysymList)) 150734345a63Smrg field.str = "symbols"; 150834345a63Smrg else 150934345a63Smrg field.str = "actions"; 151034345a63Smrg arrayNdx = NULL; 151134345a63Smrg } 151234345a63Smrg else 151334345a63Smrg { 151434345a63Smrg ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); 151534345a63Smrg } 151634345a63Smrg if (ok) 151734345a63Smrg ok = SetSymbolsField(key, xkb, field.str, arrayNdx, 151834345a63Smrg def->value, info); 151934345a63Smrg } 1520f46a6179Smrg } 1521f46a6179Smrg return ok; 1522f46a6179Smrg} 1523f46a6179Smrg 1524f46a6179Smrgstatic Bool 152534345a63SmrgSetExplicitGroup(SymbolsInfo * info, KeyInfo * key) 1526f46a6179Smrg{ 1527f46a6179Smrg unsigned group = info->explicit_group; 1528f46a6179Smrg 1529f46a6179Smrg if (group == 0) 153034345a63Smrg return True; 153134345a63Smrg 153234345a63Smrg if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1) 153334345a63Smrg { 153434345a63Smrg int i; 153534345a63Smrg WARN1("For the map %s an explicit group specified\n", info->name); 153634345a63Smrg WARN1("but key %s has more than one group defined\n", 153734345a63Smrg longText(key->name, XkbMessage)); 153834345a63Smrg ACTION("All groups except first one will be ignored\n"); 153934345a63Smrg for (i = 1; i < XkbNumKbdGroups; i++) 154034345a63Smrg { 154134345a63Smrg key->numLevels[i] = 0; 154234345a63Smrg if (key->syms[i] != NULL) 154334345a63Smrg uFree(key->syms[i]); 154434345a63Smrg key->syms[i] = (KeySym *) NULL; 154534345a63Smrg if (key->acts[i] != NULL) 154634345a63Smrg uFree(key->acts[i]); 154734345a63Smrg key->acts[i] = (XkbAction *) NULL; 154834345a63Smrg key->types[i] = (Atom) 0; 154934345a63Smrg } 155034345a63Smrg } 155134345a63Smrg key->typesDefined = key->symsDefined = key->actsDefined = 1 << group; 155234345a63Smrg 155334345a63Smrg key->numLevels[group] = key->numLevels[0]; 155434345a63Smrg key->numLevels[0] = 0; 155534345a63Smrg key->syms[group] = key->syms[0]; 155634345a63Smrg key->syms[0] = (KeySym *) NULL; 155734345a63Smrg key->acts[group] = key->acts[0]; 155834345a63Smrg key->acts[0] = (XkbAction *) NULL; 155934345a63Smrg key->types[group] = key->types[0]; 156034345a63Smrg key->types[0] = (Atom) 0; 156134345a63Smrg return True; 1562f46a6179Smrg} 1563f46a6179Smrg 1564f46a6179Smrgstatic int 156534345a63SmrgHandleSymbolsDef(SymbolsDef * stmt, 156634345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1567f46a6179Smrg{ 156834345a63Smrg KeyInfo key; 156934345a63Smrg 1570f46a6179Smrg InitKeyInfo(&key); 157134345a63Smrg CopyKeyInfo(&info->dflt, &key, False); 157234345a63Smrg key.defs.merge = stmt->merge; 157334345a63Smrg key.name = KeyNameToLong(stmt->keyName); 157434345a63Smrg if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info)) 157534345a63Smrg { 157634345a63Smrg info->errorCount++; 157734345a63Smrg return False; 1578f46a6179Smrg } 1579f46a6179Smrg 158034345a63Smrg if (!SetExplicitGroup(info, &key)) 158134345a63Smrg { 1582f46a6179Smrg info->errorCount++; 1583f46a6179Smrg return False; 1584f46a6179Smrg } 1585f46a6179Smrg 158634345a63Smrg if (!AddKeySymbols(info, &key, xkb)) 158734345a63Smrg { 158834345a63Smrg info->errorCount++; 158934345a63Smrg return False; 1590f46a6179Smrg } 1591f46a6179Smrg return True; 1592f46a6179Smrg} 1593f46a6179Smrg 1594f46a6179Smrgstatic Bool 159534345a63SmrgHandleModMapDef(ModMapDef * def, 159634345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1597f46a6179Smrg{ 159834345a63Smrg ExprDef *key; 159934345a63Smrg ModMapEntry tmp; 160034345a63Smrg ExprResult rtrn; 160134345a63Smrg Bool ok; 160234345a63Smrg 160334345a63Smrg if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn)) 160434345a63Smrg { 160534345a63Smrg ERROR("Illegal modifier map definition\n"); 160634345a63Smrg ACTION1("Ignoring map for non-modifier \"%s\"\n", 160734345a63Smrg XkbAtomText(NULL, def->modifier, XkbMessage)); 160834345a63Smrg return False; 160934345a63Smrg } 161034345a63Smrg ok = True; 161134345a63Smrg tmp.modifier = rtrn.uval; 161234345a63Smrg for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) 161334345a63Smrg { 161434345a63Smrg if ((key->op == ExprValue) && (key->type == TypeKeyName)) 161534345a63Smrg { 161634345a63Smrg tmp.haveSymbol = False; 161734345a63Smrg tmp.u.keyName = KeyNameToLong(key->value.keyName); 161834345a63Smrg } 161934345a63Smrg else if (ExprResolveKeySym(key, &rtrn, NULL, NULL)) 162034345a63Smrg { 162134345a63Smrg tmp.haveSymbol = True; 162234345a63Smrg tmp.u.keySym = rtrn.uval; 162334345a63Smrg } 162434345a63Smrg else 162534345a63Smrg { 162634345a63Smrg ERROR("Modmap entries may contain only key names or keysyms\n"); 162734345a63Smrg ACTION1("Illegal definition for %s modifier ignored\n", 162834345a63Smrg XkbModIndexText(tmp.modifier, XkbMessage)); 162934345a63Smrg continue; 163034345a63Smrg } 163134345a63Smrg 163234345a63Smrg ok = AddModMapEntry(info, &tmp) && ok; 1633f46a6179Smrg } 1634f46a6179Smrg return ok; 1635f46a6179Smrg} 1636f46a6179Smrg 1637f46a6179Smrgstatic void 163834345a63SmrgHandleSymbolsFile(XkbFile * file, 163934345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1640f46a6179Smrg{ 164134345a63Smrg ParseCommon *stmt; 164234345a63Smrg 164334345a63Smrg info->name = uStringDup(file->name); 164434345a63Smrg stmt = file->defs; 164534345a63Smrg while (stmt) 164634345a63Smrg { 164734345a63Smrg switch (stmt->stmtType) 164834345a63Smrg { 164934345a63Smrg case StmtInclude: 165034345a63Smrg if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info, 165134345a63Smrg HandleSymbolsFile)) 165234345a63Smrg info->errorCount++; 165334345a63Smrg break; 165434345a63Smrg case StmtSymbolsDef: 165534345a63Smrg if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info)) 165634345a63Smrg info->errorCount++; 165734345a63Smrg break; 165834345a63Smrg case StmtVarDef: 165934345a63Smrg if (!HandleSymbolsVar((VarDef *) stmt, xkb, info)) 166034345a63Smrg info->errorCount++; 166134345a63Smrg break; 166234345a63Smrg case StmtVModDef: 166334345a63Smrg if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) 166434345a63Smrg info->errorCount++; 166534345a63Smrg break; 166634345a63Smrg case StmtInterpDef: 166734345a63Smrg ERROR("Interpretation files may not include other types\n"); 166834345a63Smrg ACTION("Ignoring definition of symbol interpretation\n"); 166934345a63Smrg info->errorCount++; 167034345a63Smrg break; 167134345a63Smrg case StmtKeycodeDef: 167234345a63Smrg ERROR("Interpretation files may not include other types\n"); 167334345a63Smrg ACTION("Ignoring definition of key name\n"); 167434345a63Smrg info->errorCount++; 167534345a63Smrg break; 167634345a63Smrg case StmtModMapDef: 167734345a63Smrg if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info)) 167834345a63Smrg info->errorCount++; 167934345a63Smrg break; 168034345a63Smrg default: 168134345a63Smrg WSGO1("Unexpected statement type %d in HandleSymbolsFile\n", 168234345a63Smrg stmt->stmtType); 168334345a63Smrg break; 168434345a63Smrg } 168534345a63Smrg stmt = stmt->next; 168634345a63Smrg if (info->errorCount > 10) 168734345a63Smrg { 1688f46a6179Smrg#ifdef NOISY 168934345a63Smrg ERROR("Too many errors\n"); 1690f46a6179Smrg#endif 169134345a63Smrg ACTION1("Abandoning symbols file \"%s\"\n", file->topName); 169234345a63Smrg break; 169334345a63Smrg } 1694f46a6179Smrg } 1695f46a6179Smrg return; 1696f46a6179Smrg} 1697f46a6179Smrg 1698f46a6179Smrgstatic Bool 169934345a63SmrgFindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn) 1700f46a6179Smrg{ 170134345a63Smrg register int i, j; 170234345a63Smrg register Bool gotOne; 170334345a63Smrg 170434345a63Smrg j = 0; 170534345a63Smrg do 170634345a63Smrg { 170734345a63Smrg gotOne = False; 170834345a63Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) 170934345a63Smrg { 171034345a63Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) 171134345a63Smrg { 1712f46a6179Smrg gotOne = True; 17131d8c7986Smrg if (XkbKeySym(xkb, i, j) == sym) 171434345a63Smrg { 171534345a63Smrg *kc_rtrn = i; 1716f46a6179Smrg return True; 171734345a63Smrg } 1718f46a6179Smrg } 1719f46a6179Smrg } 1720f46a6179Smrg j++; 172134345a63Smrg } 172234345a63Smrg while (gotOne); 1723f46a6179Smrg return False; 1724f46a6179Smrg} 1725f46a6179Smrg 172634345a63Smrg/** 172734345a63Smrg * Find the given name in the xkb->map->types and return its index. 172834345a63Smrg * 172934345a63Smrg * @param name The atom to search for. 173034345a63Smrg * @param type_rtrn Set to the index of the name if found. 173134345a63Smrg * 173234345a63Smrg * @return True if found, False otherwise. 173334345a63Smrg */ 1734f46a6179Smrgstatic Bool 173534345a63SmrgFindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn) 1736f46a6179Smrg{ 173734345a63Smrg register unsigned n; 173834345a63Smrg 173934345a63Smrg if (xkb && xkb->map && xkb->map->types) 174034345a63Smrg { 174134345a63Smrg for (n = 0; n < xkb->map->num_types; n++) 174234345a63Smrg { 174334345a63Smrg if (xkb->map->types[n].name == (Atom) name) 174434345a63Smrg { 174534345a63Smrg *type_rtrn = n; 174634345a63Smrg return True; 174734345a63Smrg } 174834345a63Smrg } 1749f46a6179Smrg } 1750f46a6179Smrg return False; 1751f46a6179Smrg} 1752f46a6179Smrg 1753f46a6179Smrgstatic Bool 175434345a63SmrgKSIsLower(KeySym ks) 1755f46a6179Smrg{ 1756f46a6179Smrg KeySym lower, upper; 1757f46a6179Smrg XConvertCase(ks, &lower, &upper); 1758f46a6179Smrg 1759f46a6179Smrg if (lower == upper) 1760f46a6179Smrg return False; 1761f46a6179Smrg return (ks == lower ? True : False); 1762f46a6179Smrg} 1763f46a6179Smrg 1764f46a6179Smrgstatic Bool 176534345a63SmrgKSIsUpper(KeySym ks) 1766f46a6179Smrg{ 1767f46a6179Smrg KeySym lower, upper; 1768f46a6179Smrg XConvertCase(ks, &lower, &upper); 1769f46a6179Smrg 1770f46a6179Smrg if (lower == upper) 1771f46a6179Smrg return False; 1772f46a6179Smrg return (ks == upper ? True : False); 1773f46a6179Smrg} 1774f46a6179Smrg 177534345a63Smrg/** 177634345a63Smrg * Assign a type to the given sym and return the Atom for the type assigned. 177734345a63Smrg * 177834345a63Smrg * Simple recipe: 177934345a63Smrg * - ONE_LEVEL for width 0/1 178034345a63Smrg * - ALPHABETIC for 2 shift levels, with lower/upercase 178134345a63Smrg * - KEYPAD for keypad keys. 178234345a63Smrg * - TWO_LEVEL for other 2 shift level keys. 178334345a63Smrg * and the same for four level keys. 178434345a63Smrg * 178534345a63Smrg * @param width Number of sysms in syms. 178634345a63Smrg * @param syms The keysyms for the given key (must be size width). 178734345a63Smrg * @param typeNameRtrn Set to the Atom of the type name. 178834345a63Smrg * 178934345a63Smrg * @returns True if a type could be found, False otherwise. 179034345a63Smrg */ 1791f46a6179Smrgstatic Bool 179234345a63SmrgFindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn, 179334345a63Smrg Bool * autoType) 1794f46a6179Smrg{ 1795f46a6179Smrg *autoType = False; 179634345a63Smrg if ((width == 1) || (width == 0)) 179734345a63Smrg { 179834345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False); 179934345a63Smrg *autoType = True; 180034345a63Smrg } 180134345a63Smrg else if (width == 2) 180234345a63Smrg { 180334345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 180434345a63Smrg { 180534345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False); 180634345a63Smrg } 180734345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 180834345a63Smrg { 180934345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False); 181034345a63Smrg *autoType = True; 181134345a63Smrg } 181234345a63Smrg else 181334345a63Smrg { 181434345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False); 181534345a63Smrg *autoType = True; 181634345a63Smrg } 181734345a63Smrg } 181834345a63Smrg else if (width <= 4) 181934345a63Smrg { 182034345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 182134345a63Smrg if (KSIsLower(syms[2]) && KSIsUpper(syms[3])) 182234345a63Smrg *typeNameRtrn = 182334345a63Smrg XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False); 182434345a63Smrg else 182534345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, 182634345a63Smrg "FOUR_LEVEL_SEMIALPHABETIC", 182734345a63Smrg False); 182834345a63Smrg 182934345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 183034345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False); 183134345a63Smrg else 183234345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False); 183334345a63Smrg /* XXX: why not set autoType here? */ 183434345a63Smrg } 183534345a63Smrg return ((width >= 0) && (width <= 4)); 1836f46a6179Smrg} 1837f46a6179Smrg 183834345a63Smrg/** 183934345a63Smrg * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the 184034345a63Smrg * groups, and reduce to one group if all groups are identical anyway. 184134345a63Smrg */ 1842f46a6179Smrgstatic void 184334345a63SmrgPrepareKeyDef(KeyInfo * key) 1844f46a6179Smrg{ 1845f46a6179Smrg int i, j, width, defined, lastGroup; 1846f46a6179Smrg Bool identical; 184734345a63Smrg 1848f46a6179Smrg defined = key->symsDefined | key->actsDefined | key->typesDefined; 184934345a63Smrg /* get highest group number */ 185034345a63Smrg for (i = XkbNumKbdGroups - 1; i >= 0; i--) 185134345a63Smrg { 185234345a63Smrg if (defined & (1 << i)) 185334345a63Smrg break; 1854f46a6179Smrg } 1855f46a6179Smrg lastGroup = i; 1856f46a6179Smrg 1857f46a6179Smrg if (lastGroup == 0) 185834345a63Smrg return; 1859f46a6179Smrg 1860f46a6179Smrg /* If there are empty groups between non-empty ones fill them with data */ 1861f46a6179Smrg /* from the first group. */ 1862f46a6179Smrg /* We can make a wrong assumption here. But leaving gaps is worse. */ 186334345a63Smrg for (i = lastGroup; i > 0; i--) 186434345a63Smrg { 186534345a63Smrg if (defined & (1 << i)) 1866f46a6179Smrg continue; 1867f46a6179Smrg width = key->numLevels[0]; 186834345a63Smrg if (key->typesDefined & 1) 186934345a63Smrg { 187034345a63Smrg for (j = 0; j < width; j++) 187134345a63Smrg { 1872f46a6179Smrg key->types[i] = key->types[0]; 1873f46a6179Smrg } 1874f46a6179Smrg key->typesDefined |= 1 << i; 1875f46a6179Smrg } 187634345a63Smrg if ((key->actsDefined & 1) && key->acts[0]) 187734345a63Smrg { 187834345a63Smrg key->acts[i] = uTypedCalloc(width, XkbAction); 1879f46a6179Smrg if (key->acts[i] == NULL) 1880f46a6179Smrg continue; 1881f46a6179Smrg memcpy((void *) key->acts[i], (void *) key->acts[0], 1882f46a6179Smrg width * sizeof(XkbAction)); 1883f46a6179Smrg key->actsDefined |= 1 << i; 1884f46a6179Smrg } 188534345a63Smrg if ((key->symsDefined & 1) && key->syms[0]) 188634345a63Smrg { 188734345a63Smrg key->syms[i] = uTypedCalloc(width, KeySym); 1888f46a6179Smrg if (key->syms[i] == NULL) 1889f46a6179Smrg continue; 1890f46a6179Smrg memcpy((void *) key->syms[i], (void *) key->syms[0], 1891f46a6179Smrg width * sizeof(KeySym)); 1892f46a6179Smrg key->symsDefined |= 1 << i; 1893f46a6179Smrg } 189434345a63Smrg if (defined & 1) 189534345a63Smrg { 1896f46a6179Smrg key->numLevels[i] = key->numLevels[0]; 1897f46a6179Smrg } 1898f46a6179Smrg } 1899f46a6179Smrg /* If all groups are completely identical remove them all */ 1900f46a6179Smrg /* exept the first one. */ 1901f46a6179Smrg identical = True; 190234345a63Smrg for (i = lastGroup; i > 0; i--) 190334345a63Smrg { 1904f46a6179Smrg if ((key->numLevels[i] != key->numLevels[0]) || 190534345a63Smrg (key->types[i] != key->types[0])) 190634345a63Smrg { 1907f46a6179Smrg identical = False; 1908f46a6179Smrg break; 1909f46a6179Smrg } 1910f46a6179Smrg if ((key->syms[i] != key->syms[0]) && 191134345a63Smrg (key->syms[i] == NULL || key->syms[0] == NULL || 191234345a63Smrg memcmp((void *) key->syms[i], (void *) key->syms[0], 191334345a63Smrg sizeof(KeySym) * key->numLevels[0]))) 191434345a63Smrg { 191534345a63Smrg identical = False; 191634345a63Smrg break; 191734345a63Smrg } 1918f46a6179Smrg if ((key->acts[i] != key->acts[0]) && 191934345a63Smrg (key->acts[i] == NULL || key->acts[0] == NULL || 192034345a63Smrg memcmp((void *) key->acts[i], (void *) key->acts[0], 192134345a63Smrg sizeof(XkbAction) * key->numLevels[0]))) 192234345a63Smrg { 1923f46a6179Smrg identical = False; 1924f46a6179Smrg break; 192534345a63Smrg } 192634345a63Smrg } 192734345a63Smrg if (identical) 192834345a63Smrg { 192934345a63Smrg for (i = lastGroup; i > 0; i--) 193034345a63Smrg { 193134345a63Smrg key->numLevels[i] = 0; 193234345a63Smrg if (key->syms[i] != NULL) 193334345a63Smrg uFree(key->syms[i]); 193434345a63Smrg key->syms[i] = (KeySym *) NULL; 193534345a63Smrg if (key->acts[i] != NULL) 193634345a63Smrg uFree(key->acts[i]); 193734345a63Smrg key->acts[i] = (XkbAction *) NULL; 193834345a63Smrg key->types[i] = (Atom) 0; 193934345a63Smrg } 194034345a63Smrg key->symsDefined &= 1; 194134345a63Smrg key->actsDefined &= 1; 194234345a63Smrg key->typesDefined &= 1; 1943f46a6179Smrg } 1944f46a6179Smrg return; 1945f46a6179Smrg} 1946f46a6179Smrg 194734345a63Smrg/** 194834345a63Smrg * Copy the KeyInfo into result. 194934345a63Smrg * 195034345a63Smrg * This function recurses. 195134345a63Smrg */ 1952f46a6179Smrgstatic Bool 195334345a63SmrgCopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from) 1954f46a6179Smrg{ 195534345a63Smrg register int i; 195634345a63Smrg unsigned okc, kc, width, tmp, nGroups; 195734345a63Smrg XkbKeyTypePtr type; 195834345a63Smrg Bool haveActions, autoType, useAlias; 195934345a63Smrg KeySym *outSyms; 196034345a63Smrg XkbAction *outActs; 196134345a63Smrg XkbDescPtr xkb; 196234345a63Smrg unsigned types[XkbNumKbdGroups]; 196334345a63Smrg 196434345a63Smrg xkb = result->xkb; 196534345a63Smrg useAlias = (start_from == 0); 196634345a63Smrg 196734345a63Smrg /* get the keycode for the key. */ 196834345a63Smrg if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb), 196934345a63Smrg start_from)) 197034345a63Smrg { 197134345a63Smrg if ((start_from == 0) && (warningLevel >= 5)) 197234345a63Smrg { 197334345a63Smrg WARN2("Key %s not found in %s keycodes\n", 197434345a63Smrg longText(key->name, XkbMessage), 197534345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 197634345a63Smrg ACTION("Symbols ignored\n"); 197734345a63Smrg } 197834345a63Smrg return False; 197934345a63Smrg } 198034345a63Smrg 198134345a63Smrg haveActions = False; 198234345a63Smrg for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) 198334345a63Smrg { 198434345a63Smrg if (((i + 1) > nGroups) 198534345a63Smrg && (((key->symsDefined | key->actsDefined) & (1 << i)) 198634345a63Smrg || (key->typesDefined) & (1 << i))) 198734345a63Smrg nGroups = i + 1; 198834345a63Smrg if (key->acts[i]) 198934345a63Smrg haveActions = True; 199034345a63Smrg autoType = False; 199134345a63Smrg /* Assign the type to the key, if it is missing. */ 199234345a63Smrg if (key->types[i] == None) 199334345a63Smrg { 199434345a63Smrg if (key->dfltType != None) 199534345a63Smrg key->types[i] = key->dfltType; 199634345a63Smrg else if (FindAutomaticType(key->numLevels[i], key->syms[i], 199734345a63Smrg &key->types[i], &autoType)) 199834345a63Smrg { 199934345a63Smrg } 200034345a63Smrg else 200134345a63Smrg { 200234345a63Smrg if (warningLevel >= 5) 200334345a63Smrg { 200434345a63Smrg WARN1("No automatic type for %d symbols\n", 200534345a63Smrg (unsigned int) key->numLevels[i]); 200634345a63Smrg ACTION3("Using %s for the %s key (keycode %d)\n", 200734345a63Smrg XkbAtomText(NULL, key->types[i], 200834345a63Smrg XkbMessage), 200934345a63Smrg longText(key->name, XkbMessage), kc); 201034345a63Smrg } 201134345a63Smrg } 201234345a63Smrg } 201334345a63Smrg if (FindNamedType(xkb, key->types[i], &types[i])) 201434345a63Smrg { 201534345a63Smrg if (!autoType || key->numLevels[i] > 2) 201634345a63Smrg xkb->server->explicit[kc] |= (1 << i); 201734345a63Smrg } 201834345a63Smrg else 201934345a63Smrg { 202034345a63Smrg if (warningLevel >= 3) 202134345a63Smrg { 202234345a63Smrg WARN1("Type \"%s\" is not defined\n", 202334345a63Smrg XkbAtomText(NULL, key->types[i], XkbMessage)); 202434345a63Smrg ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n", 202534345a63Smrg longText(key->name, XkbMessage), kc); 202634345a63Smrg } 202734345a63Smrg types[i] = XkbTwoLevelIndex; 202834345a63Smrg } 202934345a63Smrg /* if the type specifies less syms than the key has, shrink the key */ 203034345a63Smrg type = &xkb->map->types[types[i]]; 203134345a63Smrg if (type->num_levels < key->numLevels[i]) 203234345a63Smrg { 203334345a63Smrg if (warningLevel > 0) 203434345a63Smrg { 203534345a63Smrg WARN4 203634345a63Smrg ("Type \"%s\" has %d levels, but %s has %d symbols\n", 203734345a63Smrg XkbAtomText(NULL, type->name, XkbMessage), 203834345a63Smrg (unsigned int) type->num_levels, 203934345a63Smrg longText(key->name, XkbMessage), 204034345a63Smrg (unsigned int) key->numLevels[i]); 204134345a63Smrg ACTION("Ignoring extra symbols\n"); 204234345a63Smrg } 204334345a63Smrg key->numLevels[i] = type->num_levels; 204434345a63Smrg } 204534345a63Smrg if (key->numLevels[i] > width) 204634345a63Smrg width = key->numLevels[i]; 204734345a63Smrg if (type->num_levels > width) 204834345a63Smrg width = type->num_levels; 204934345a63Smrg } 205034345a63Smrg 205134345a63Smrg /* width is now the largest width found */ 205234345a63Smrg 205334345a63Smrg i = width * nGroups; 205434345a63Smrg outSyms = XkbResizeKeySyms(xkb, kc, i); 205534345a63Smrg if (outSyms == NULL) 205634345a63Smrg { 205734345a63Smrg WSGO2("Could not enlarge symbols for %s (keycode %d)\n", 205834345a63Smrg longText(key->name, XkbMessage), kc); 205934345a63Smrg return False; 206034345a63Smrg } 206134345a63Smrg if (haveActions) 206234345a63Smrg { 206334345a63Smrg outActs = XkbResizeKeyActions(xkb, kc, i); 206434345a63Smrg if (outActs == NULL) 206534345a63Smrg { 206634345a63Smrg WSGO2("Could not enlarge actions for %s (key %d)\n", 206734345a63Smrg longText(key->name, XkbMessage), kc); 206834345a63Smrg return False; 206934345a63Smrg } 207034345a63Smrg xkb->server->explicit[kc] |= XkbExplicitInterpretMask; 207134345a63Smrg } 207234345a63Smrg else 207334345a63Smrg outActs = NULL; 207434345a63Smrg if (key->defs.defined & _Key_GroupInfo) 207534345a63Smrg i = key->groupInfo; 207634345a63Smrg else 207734345a63Smrg i = xkb->map->key_sym_map[kc].group_info; 207834345a63Smrg 207934345a63Smrg xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups); 208034345a63Smrg xkb->map->key_sym_map[kc].width = width; 208134345a63Smrg for (i = 0; i < nGroups; i++) 208234345a63Smrg { 208334345a63Smrg /* assign kt_index[i] to the index of the type in map->types. 208434345a63Smrg * kt_index[i] may have been set by a previous run (if we have two 208534345a63Smrg * layouts specified). Let's not overwrite it with the ONE_LEVEL 208634345a63Smrg * default group if we dont even have keys for this group anyway. 208734345a63Smrg * 208834345a63Smrg * FIXME: There should be a better fix for this. 208934345a63Smrg */ 209034345a63Smrg if (key->numLevels[i]) 209134345a63Smrg xkb->map->key_sym_map[kc].kt_index[i] = types[i]; 209234345a63Smrg if (key->syms[i] != NULL) 209334345a63Smrg { 209434345a63Smrg /* fill key to "width" symbols*/ 209534345a63Smrg for (tmp = 0; tmp < width; tmp++) 209634345a63Smrg { 209734345a63Smrg if (tmp < key->numLevels[i]) 209834345a63Smrg outSyms[tmp] = key->syms[i][tmp]; 209934345a63Smrg else 210034345a63Smrg outSyms[tmp] = NoSymbol; 210134345a63Smrg if ((outActs != NULL) && (key->acts[i] != NULL)) 210234345a63Smrg { 210334345a63Smrg if (tmp < key->numLevels[i]) 210434345a63Smrg outActs[tmp] = key->acts[i][tmp]; 210534345a63Smrg else 210634345a63Smrg outActs[tmp].type = XkbSA_NoAction; 210734345a63Smrg } 210834345a63Smrg } 210934345a63Smrg } 211034345a63Smrg outSyms += width; 211134345a63Smrg if (outActs) 211234345a63Smrg outActs += width; 211334345a63Smrg } 211434345a63Smrg switch (key->behavior.type & XkbKB_OpMask) 211534345a63Smrg { 211634345a63Smrg case XkbKB_Default: 211734345a63Smrg break; 211834345a63Smrg case XkbKB_Overlay1: 211934345a63Smrg case XkbKB_Overlay2: 212034345a63Smrg /* find key by name! */ 212134345a63Smrg if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True, 212234345a63Smrg CreateKeyNames(xkb), 0)) 212334345a63Smrg { 212434345a63Smrg if (warningLevel >= 1) 212534345a63Smrg { 212634345a63Smrg WARN2("Key %s not found in %s keycodes\n", 212734345a63Smrg longText(key->nameForOverlayKey, XkbMessage), 212834345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 212934345a63Smrg ACTION1("Not treating %s as an overlay key \n", 213034345a63Smrg longText(key->name, XkbMessage)); 213134345a63Smrg } 213234345a63Smrg break; 213334345a63Smrg } 213434345a63Smrg key->behavior.data = okc; 213534345a63Smrg default: 213634345a63Smrg xkb->server->behaviors[kc] = key->behavior; 213734345a63Smrg xkb->server->explicit[kc] |= XkbExplicitBehaviorMask; 213834345a63Smrg break; 213934345a63Smrg } 214034345a63Smrg if (key->defs.defined & _Key_VModMap) 214134345a63Smrg { 214234345a63Smrg xkb->server->vmodmap[kc] = key->vmodmap; 214334345a63Smrg xkb->server->explicit[kc] |= XkbExplicitVModMapMask; 214434345a63Smrg } 214534345a63Smrg if (key->repeat != RepeatUndefined) 214634345a63Smrg { 214734345a63Smrg if (key->repeat == RepeatYes) 214834345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8)); 214934345a63Smrg else 215034345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8)); 215134345a63Smrg xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask; 215234345a63Smrg } 215334345a63Smrg 215434345a63Smrg /* do the same thing for the next key */ 215534345a63Smrg CopySymbolsDef(result, key, kc + 1); 2156f46a6179Smrg return True; 2157f46a6179Smrg} 2158f46a6179Smrg 2159f46a6179Smrgstatic Bool 216034345a63SmrgCopyModMapDef(XkbFileInfo * result, ModMapEntry * entry) 2161f46a6179Smrg{ 216234345a63Smrg unsigned kc; 216334345a63Smrg XkbDescPtr xkb; 216434345a63Smrg 216534345a63Smrg xkb = result->xkb; 216634345a63Smrg if ((!entry->haveSymbol) 216734345a63Smrg && 216834345a63Smrg (!FindNamedKey 216934345a63Smrg (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0))) 217034345a63Smrg { 217134345a63Smrg if (warningLevel >= 5) 217234345a63Smrg { 217334345a63Smrg WARN2("Key %s not found in %s keycodes\n", 217434345a63Smrg longText(entry->u.keyName, XkbMessage), 217534345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 217634345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 217734345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 217834345a63Smrg } 217934345a63Smrg return False; 218034345a63Smrg } 218134345a63Smrg else if (entry->haveSymbol 218234345a63Smrg && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc))) 218334345a63Smrg { 218434345a63Smrg if (warningLevel > 5) 218534345a63Smrg { 218634345a63Smrg WARN2("Key \"%s\" not found in %s symbol map\n", 218734345a63Smrg XkbKeysymText(entry->u.keySym, XkbMessage), 218834345a63Smrg XkbAtomText(NULL, xkb->names->symbols, XkbMessage)); 218934345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 219034345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 219134345a63Smrg } 219234345a63Smrg return False; 219334345a63Smrg } 219434345a63Smrg xkb->map->modmap[kc] |= (1 << entry->modifier); 2195f46a6179Smrg return True; 2196f46a6179Smrg} 2197f46a6179Smrg 219834345a63Smrg/** 219934345a63Smrg * Handle the xkb_symbols section of an xkb file. 220034345a63Smrg * 220134345a63Smrg * @param file The parsed xkb_symbols section of the xkb file. 220234345a63Smrg * @param result Handle to the data to store the result in. 220334345a63Smrg * @param merge Merge strategy (e.g. MergeOverride). 220434345a63Smrg */ 2205f46a6179SmrgBool 220634345a63SmrgCompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge) 2207f46a6179Smrg{ 220834345a63Smrg register int i; 220934345a63Smrg SymbolsInfo info; 221034345a63Smrg XkbDescPtr xkb; 2211f46a6179Smrg 221234345a63Smrg xkb = result->xkb; 221334345a63Smrg InitSymbolsInfo(&info, xkb); 221434345a63Smrg info.dflt.defs.fileID = file->id; 221534345a63Smrg info.dflt.defs.merge = merge; 221634345a63Smrg HandleSymbolsFile(file, xkb, merge, &info); 2217f46a6179Smrg 2218f46a6179Smrg if (info.nKeys == 0) 2219f46a6179Smrg return True; 222034345a63Smrg if (info.errorCount == 0) 222134345a63Smrg { 222234345a63Smrg KeyInfo *key; 222334345a63Smrg 222434345a63Smrg /* alloc memory in the xkb struct */ 222534345a63Smrg if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0) 222634345a63Smrg != Success) 222734345a63Smrg { 222834345a63Smrg WSGO("Can not allocate names in CompileSymbols\n"); 222934345a63Smrg ACTION("Symbols not added\n"); 223034345a63Smrg return False; 223134345a63Smrg } 223234345a63Smrg if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0) 223334345a63Smrg != Success) 223434345a63Smrg { 223534345a63Smrg WSGO("Could not allocate client map in CompileSymbols\n"); 223634345a63Smrg ACTION("Symbols not added\n"); 223734345a63Smrg return False; 223834345a63Smrg } 223934345a63Smrg if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success) 224034345a63Smrg { 224134345a63Smrg WSGO("Could not allocate server map in CompileSymbols\n"); 224234345a63Smrg ACTION("Symbols not added\n"); 224334345a63Smrg return False; 224434345a63Smrg } 224534345a63Smrg if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success) 224634345a63Smrg { 224734345a63Smrg WSGO("Could not allocate controls in CompileSymbols\n"); 224834345a63Smrg ACTION("Symbols not added\n"); 224934345a63Smrg return False; 225034345a63Smrg } 225134345a63Smrg 225234345a63Smrg /* now copy info into xkb. */ 225334345a63Smrg xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False); 225434345a63Smrg if (info.aliases) 225534345a63Smrg ApplyAliases(xkb, False, &info.aliases); 225634345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 225734345a63Smrg { 225834345a63Smrg if (info.groupNames[i] != None) 225934345a63Smrg xkb->names->groups[i] = info.groupNames[i]; 226034345a63Smrg } 226134345a63Smrg /* sanitize keys */ 226234345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 226334345a63Smrg { 226434345a63Smrg PrepareKeyDef(key); 226534345a63Smrg } 226634345a63Smrg /* copy! */ 226734345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 226834345a63Smrg { 226934345a63Smrg if (!CopySymbolsDef(result, key, 0)) 227034345a63Smrg info.errorCount++; 227134345a63Smrg } 227234345a63Smrg if (warningLevel > 3) 227334345a63Smrg { 227434345a63Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) 227534345a63Smrg { 227634345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 227734345a63Smrg continue; 227834345a63Smrg if (XkbKeyNumGroups(xkb, i) < 1) 227934345a63Smrg { 228034345a63Smrg char buf[5]; 228134345a63Smrg memcpy(buf, xkb->names->keys[i].name, 4); 228234345a63Smrg buf[4] = '\0'; 228334345a63Smrg WARN2 228434345a63Smrg ("No symbols defined for <%s> (keycode %d)\n", 228534345a63Smrg buf, i); 228634345a63Smrg } 228734345a63Smrg } 228834345a63Smrg } 228934345a63Smrg if (info.modMap) 229034345a63Smrg { 229134345a63Smrg ModMapEntry *mm, *next; 229234345a63Smrg for (mm = info.modMap; mm != NULL; mm = next) 229334345a63Smrg { 229434345a63Smrg if (!CopyModMapDef(result, mm)) 229534345a63Smrg info.errorCount++; 229634345a63Smrg next = (ModMapEntry *) mm->defs.next; 229734345a63Smrg } 229834345a63Smrg } 229934345a63Smrg return True; 2300f46a6179Smrg } 2301f46a6179Smrg return False; 2302f46a6179Smrg} 2303