symbols.c revision 83e5f723
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 4334345a63Smrgextern Atom tok_ONE_LEVEL; 4434345a63Smrgextern Atom tok_TWO_LEVEL; 4534345a63Smrgextern Atom tok_KEYPAD; 46f46a6179Smrg 47f46a6179Smrg/***====================================================================***/ 48f46a6179Smrg 49f46a6179Smrg#define RepeatYes 1 50f46a6179Smrg#define RepeatNo 0 51f46a6179Smrg#define RepeatUndefined ~((unsigned)0) 52f46a6179Smrg 53f46a6179Smrg#define _Key_Syms (1<<0) 54f46a6179Smrg#define _Key_Acts (1<<1) 55f46a6179Smrg#define _Key_Repeat (1<<2) 56f46a6179Smrg#define _Key_Behavior (1<<3) 57f46a6179Smrg#define _Key_Type_Dflt (1<<4) 58f46a6179Smrg#define _Key_Types (1<<5) 59f46a6179Smrg#define _Key_GroupInfo (1<<6) 60f46a6179Smrg#define _Key_VModMap (1<<7) 61f46a6179Smrg 6234345a63Smrgtypedef struct _KeyInfo 6334345a63Smrg{ 6434345a63Smrg CommonInfo defs; 6534345a63Smrg unsigned long name; /* the 4 chars of the key name, as long */ 6634345a63Smrg unsigned char groupInfo; 6734345a63Smrg unsigned char typesDefined; 6834345a63Smrg unsigned char symsDefined; 6934345a63Smrg unsigned char actsDefined; 7034345a63Smrg short numLevels[XkbNumKbdGroups]; 7134345a63Smrg KeySym *syms[XkbNumKbdGroups]; 7234345a63Smrg XkbAction *acts[XkbNumKbdGroups]; 7334345a63Smrg Atom types[XkbNumKbdGroups]; 7434345a63Smrg unsigned repeat; 7534345a63Smrg XkbBehavior behavior; 7634345a63Smrg unsigned short vmodmap; 7734345a63Smrg unsigned long nameForOverlayKey; 7834345a63Smrg unsigned long allowNone; 7934345a63Smrg Atom dfltType; 80f46a6179Smrg} KeyInfo; 81f46a6179Smrg 8234345a63Smrg/** 8334345a63Smrg * Init the given key info to sane values. 8434345a63Smrg */ 85f46a6179Smrgstatic void 8634345a63SmrgInitKeyInfo(KeyInfo * info) 87f46a6179Smrg{ 8834345a63Smrg register int i; 8934345a63Smrg static char dflt[4] = "*"; 9034345a63Smrg 9134345a63Smrg info->defs.defined = 0; 9234345a63Smrg info->defs.fileID = 0; 9334345a63Smrg info->defs.merge = MergeOverride; 9434345a63Smrg info->defs.next = NULL; 9534345a63Smrg info->name = KeyNameToLong(dflt); 9634345a63Smrg info->groupInfo = 0; 9734345a63Smrg info->typesDefined = info->symsDefined = info->actsDefined = 0; 9834345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 9934345a63Smrg { 10034345a63Smrg info->numLevels[i] = 0; 10134345a63Smrg info->types[i] = None; 10234345a63Smrg info->syms[i] = NULL; 10334345a63Smrg info->acts[i] = NULL; 10434345a63Smrg } 10534345a63Smrg info->dfltType = None; 10634345a63Smrg info->behavior.type = XkbKB_Default; 10734345a63Smrg info->behavior.data = 0; 10834345a63Smrg info->vmodmap = 0; 10934345a63Smrg info->nameForOverlayKey = 0; 11034345a63Smrg info->repeat = RepeatUndefined; 11134345a63Smrg info->allowNone = 0; 112f46a6179Smrg return; 113f46a6179Smrg} 114f46a6179Smrg 11534345a63Smrg/** 11634345a63Smrg * Free memory associated with this key info and reset to sane values. 11734345a63Smrg */ 118f46a6179Smrgstatic void 11934345a63SmrgFreeKeyInfo(KeyInfo * info) 120f46a6179Smrg{ 12134345a63Smrg register int i; 12234345a63Smrg 12334345a63Smrg info->defs.defined = 0; 12434345a63Smrg info->defs.fileID = 0; 12534345a63Smrg info->defs.merge = MergeOverride; 12634345a63Smrg info->defs.next = NULL; 12734345a63Smrg info->groupInfo = 0; 12834345a63Smrg info->typesDefined = info->symsDefined = info->actsDefined = 0; 12934345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 13034345a63Smrg { 13134345a63Smrg info->numLevels[i] = 0; 13234345a63Smrg info->types[i] = None; 13334345a63Smrg if (info->syms[i] != NULL) 13434345a63Smrg uFree(info->syms[i]); 13534345a63Smrg info->syms[i] = NULL; 13634345a63Smrg if (info->acts[i] != NULL) 13734345a63Smrg uFree(info->acts[i]); 13834345a63Smrg info->acts[i] = NULL; 13934345a63Smrg } 14034345a63Smrg info->dfltType = None; 14134345a63Smrg info->behavior.type = XkbKB_Default; 14234345a63Smrg info->behavior.data = 0; 14334345a63Smrg info->vmodmap = 0; 14434345a63Smrg info->nameForOverlayKey = 0; 14534345a63Smrg info->repeat = RepeatUndefined; 14634345a63Smrg info->allowNone = 0; 147f46a6179Smrg return; 148f46a6179Smrg} 149f46a6179Smrg 15034345a63Smrg/** 15134345a63Smrg * Copy old into new, optionally reset old to 0. 15234345a63Smrg * If old is reset, new simply re-uses old's memory. Otherwise, the memory is 15334345a63Smrg * newly allocated and new points to the new memory areas. 15434345a63Smrg */ 155f46a6179Smrgstatic Bool 15634345a63SmrgCopyKeyInfo(KeyInfo * old, KeyInfo * new, Bool clearOld) 157f46a6179Smrg{ 15834345a63Smrg register int i; 15934345a63Smrg 16034345a63Smrg *new = *old; 16134345a63Smrg new->defs.next = NULL; 16234345a63Smrg if (clearOld) 16334345a63Smrg { 16434345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 16534345a63Smrg { 16634345a63Smrg old->numLevels[i] = 0; 16734345a63Smrg old->syms[i] = NULL; 16834345a63Smrg old->acts[i] = NULL; 16934345a63Smrg } 17034345a63Smrg } 17134345a63Smrg else 17234345a63Smrg { 17334345a63Smrg int width; 17434345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 17534345a63Smrg { 17634345a63Smrg width = new->numLevels[i]; 17734345a63Smrg if (old->syms[i] != NULL) 17834345a63Smrg { 17934345a63Smrg new->syms[i] = uTypedCalloc(width, KeySym); 18034345a63Smrg if (!new->syms[i]) 18134345a63Smrg { 18234345a63Smrg new->syms[i] = NULL; 18334345a63Smrg new->numLevels[i] = 0; 18434345a63Smrg return False; 18534345a63Smrg } 18634345a63Smrg memcpy((char *) new->syms[i], (char *) old->syms[i], 18734345a63Smrg width * sizeof(KeySym)); 18834345a63Smrg } 18934345a63Smrg if (old->acts[i] != NULL) 19034345a63Smrg { 19134345a63Smrg new->acts[i] = uTypedCalloc(width, XkbAction); 19234345a63Smrg if (!new->acts[i]) 19334345a63Smrg { 19434345a63Smrg new->acts[i] = NULL; 19534345a63Smrg return False; 19634345a63Smrg } 19734345a63Smrg memcpy((char *) new->acts[i], (char *) old->acts[i], 19834345a63Smrg width * sizeof(XkbAction)); 19934345a63Smrg } 20034345a63Smrg } 201f46a6179Smrg } 202f46a6179Smrg return True; 203f46a6179Smrg} 204f46a6179Smrg 205f46a6179Smrg/***====================================================================***/ 206f46a6179Smrg 20734345a63Smrgtypedef struct _ModMapEntry 20834345a63Smrg{ 20934345a63Smrg CommonInfo defs; 21034345a63Smrg Bool haveSymbol; 21134345a63Smrg int modifier; 21234345a63Smrg union 21334345a63Smrg { 21434345a63Smrg unsigned long keyName; 21534345a63Smrg KeySym keySym; 216f46a6179Smrg } u; 217f46a6179Smrg} ModMapEntry; 218f46a6179Smrg 219f46a6179Smrg#define SYMBOLS_INIT_SIZE 110 220f46a6179Smrg#define SYMBOLS_CHUNK 20 22134345a63Smrgtypedef struct _SymbolsInfo 22234345a63Smrg{ 22334345a63Smrg char *name; /* e.g. pc+us+inet(evdev) */ 22434345a63Smrg int errorCount; 22534345a63Smrg unsigned fileID; 22634345a63Smrg unsigned merge; 22734345a63Smrg unsigned explicit_group; 22834345a63Smrg unsigned groupInfo; 22934345a63Smrg unsigned szKeys; 23034345a63Smrg unsigned nKeys; 23134345a63Smrg KeyInfo *keys; 23234345a63Smrg KeyInfo dflt; 23334345a63Smrg VModInfo vmods; 23434345a63Smrg ActionInfo *action; 23534345a63Smrg Atom groupNames[XkbNumKbdGroups]; 23634345a63Smrg 23734345a63Smrg ModMapEntry *modMap; 23834345a63Smrg AliasInfo *aliases; 239f46a6179Smrg} SymbolsInfo; 240f46a6179Smrg 241f46a6179Smrgstatic void 24234345a63SmrgInitSymbolsInfo(SymbolsInfo * info, XkbDescPtr xkb) 243f46a6179Smrg{ 24434345a63Smrg register int i; 24534345a63Smrg 24634345a63Smrg tok_ONE_LEVEL = XkbInternAtom(NULL, "ONE_LEVEL", False); 24734345a63Smrg tok_TWO_LEVEL = XkbInternAtom(NULL, "TWO_LEVEL", False); 24834345a63Smrg tok_KEYPAD = XkbInternAtom(NULL, "KEYPAD", False); 24934345a63Smrg info->name = NULL; 25034345a63Smrg info->explicit_group = 0; 25134345a63Smrg info->errorCount = 0; 25234345a63Smrg info->fileID = 0; 25334345a63Smrg info->merge = MergeOverride; 25434345a63Smrg info->groupInfo = 0; 25534345a63Smrg info->szKeys = SYMBOLS_INIT_SIZE; 25634345a63Smrg info->nKeys = 0; 25734345a63Smrg info->keys = uTypedCalloc(SYMBOLS_INIT_SIZE, KeyInfo); 25834345a63Smrg info->modMap = NULL; 25934345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 26034345a63Smrg info->groupNames[i] = None; 261f46a6179Smrg InitKeyInfo(&info->dflt); 26234345a63Smrg InitVModInfo(&info->vmods, xkb); 26334345a63Smrg info->action = NULL; 26434345a63Smrg info->aliases = NULL; 265f46a6179Smrg return; 266f46a6179Smrg} 267f46a6179Smrg 268f46a6179Smrgstatic void 26934345a63SmrgFreeSymbolsInfo(SymbolsInfo * info) 270f46a6179Smrg{ 27134345a63Smrg register int i; 272f46a6179Smrg 273f46a6179Smrg if (info->name) 27434345a63Smrg uFree(info->name); 27534345a63Smrg info->name = NULL; 27634345a63Smrg if (info->keys) 27734345a63Smrg { 27834345a63Smrg for (i = 0; i < info->nKeys; i++) 27934345a63Smrg { 28034345a63Smrg FreeKeyInfo(&info->keys[i]); 28134345a63Smrg } 28234345a63Smrg uFree(info->keys); 28334345a63Smrg info->keys = NULL; 28434345a63Smrg } 28534345a63Smrg if (info->modMap) 28634345a63Smrg { 28734345a63Smrg ClearCommonInfo(&info->modMap->defs); 28834345a63Smrg info->modMap = NULL; 28934345a63Smrg } 29034345a63Smrg if (info->aliases) 29134345a63Smrg { 29234345a63Smrg ClearAliases(&info->aliases); 29334345a63Smrg info->aliases = NULL; 29434345a63Smrg } 29534345a63Smrg bzero((char *) info, sizeof(SymbolsInfo)); 296f46a6179Smrg return; 297f46a6179Smrg} 298f46a6179Smrg 299f46a6179Smrgstatic Bool 30034345a63SmrgResizeKeyGroup(KeyInfo * key, 30134345a63Smrg unsigned group, unsigned atLeastSize, Bool forceActions) 302f46a6179Smrg{ 30334345a63Smrg Bool tooSmall; 30434345a63Smrg unsigned newWidth; 30534345a63Smrg 30634345a63Smrg tooSmall = (key->numLevels[group] < atLeastSize); 30734345a63Smrg if (tooSmall) 30834345a63Smrg newWidth = atLeastSize; 30934345a63Smrg else 31034345a63Smrg newWidth = key->numLevels[group]; 31134345a63Smrg 31234345a63Smrg if ((key->syms[group] == NULL) || tooSmall) 31334345a63Smrg { 31434345a63Smrg key->syms[group] = uTypedRecalloc(key->syms[group], 31534345a63Smrg key->numLevels[group], newWidth, 31634345a63Smrg KeySym); 31734345a63Smrg if (!key->syms[group]) 31834345a63Smrg return False; 31934345a63Smrg } 32034345a63Smrg if (((forceActions) && (tooSmall || (key->acts[group] == NULL))) || 32134345a63Smrg (tooSmall && (key->acts[group] != NULL))) 32234345a63Smrg { 32334345a63Smrg key->acts[group] = uTypedRecalloc(key->acts[group], 32434345a63Smrg key->numLevels[group], newWidth, 32534345a63Smrg XkbAction); 32634345a63Smrg if (!key->acts[group]) 32734345a63Smrg return False; 32834345a63Smrg } 32934345a63Smrg key->numLevels[group] = newWidth; 330f46a6179Smrg return True; 331f46a6179Smrg} 332f46a6179Smrg 333f46a6179Smrgstatic Bool 33434345a63SmrgMergeKeyGroups(SymbolsInfo * info, 33534345a63Smrg KeyInfo * into, KeyInfo * from, unsigned group) 336f46a6179Smrg{ 33734345a63Smrg KeySym *resultSyms; 33834345a63Smrg XkbAction *resultActs; 33934345a63Smrg int resultWidth; 34034345a63Smrg register int i; 34134345a63Smrg Bool report, clobber; 34234345a63Smrg 34334345a63Smrg clobber = (from->defs.merge != MergeAugment); 34434345a63Smrg report = (warningLevel > 9) || 34534345a63Smrg ((into->defs.fileID == from->defs.fileID) && (warningLevel > 0)); 34634345a63Smrg if (into->numLevels[group] >= from->numLevels[group]) 34734345a63Smrg { 34834345a63Smrg resultSyms = into->syms[group]; 34934345a63Smrg resultActs = into->acts[group]; 35034345a63Smrg resultWidth = into->numLevels[group]; 35134345a63Smrg } 35234345a63Smrg else 35334345a63Smrg { 35434345a63Smrg resultSyms = from->syms[group]; 35534345a63Smrg resultActs = from->acts[group]; 35634345a63Smrg resultWidth = from->numLevels[group]; 35734345a63Smrg } 35834345a63Smrg if (resultSyms == NULL) 35934345a63Smrg { 36034345a63Smrg resultSyms = uTypedCalloc(resultWidth, KeySym); 36134345a63Smrg if (!resultSyms) 36234345a63Smrg { 36334345a63Smrg WSGO("Could not allocate symbols for group merge\n"); 36434345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 36534345a63Smrg longText(into->name, XkbMessage)); 36634345a63Smrg return False; 36734345a63Smrg } 36834345a63Smrg } 36934345a63Smrg if ((resultActs == NULL) && (into->acts[group] || from->acts[group])) 37034345a63Smrg { 37134345a63Smrg resultActs = uTypedCalloc(resultWidth, XkbAction); 37234345a63Smrg if (!resultActs) 37334345a63Smrg { 37434345a63Smrg WSGO("Could not allocate actions for group merge\n"); 37534345a63Smrg ACTION2("Group %d of key %s not merged\n", group, 37634345a63Smrg longText(into->name, XkbMessage)); 37734345a63Smrg return False; 37834345a63Smrg } 37934345a63Smrg } 38034345a63Smrg for (i = 0; i < resultWidth; i++) 38134345a63Smrg { 38234345a63Smrg KeySym fromSym, toSym; 38334345a63Smrg if (from->syms[group] && (i < from->numLevels[group])) 38434345a63Smrg fromSym = from->syms[group][i]; 38534345a63Smrg else 38634345a63Smrg fromSym = NoSymbol; 38734345a63Smrg if (into->syms[group] && (i < into->numLevels[group])) 38834345a63Smrg toSym = into->syms[group][i]; 38934345a63Smrg else 39034345a63Smrg toSym = NoSymbol; 39134345a63Smrg if ((fromSym == NoSymbol) || (fromSym == toSym)) 39234345a63Smrg resultSyms[i] = toSym; 39334345a63Smrg else if (toSym == NoSymbol) 39434345a63Smrg resultSyms[i] = fromSym; 39534345a63Smrg else 39634345a63Smrg { 39734345a63Smrg KeySym use, ignore; 39834345a63Smrg if (clobber) 39934345a63Smrg { 40034345a63Smrg use = fromSym; 40134345a63Smrg ignore = toSym; 40234345a63Smrg } 40334345a63Smrg else 40434345a63Smrg { 40534345a63Smrg use = toSym; 40634345a63Smrg ignore = fromSym; 40734345a63Smrg } 40834345a63Smrg if (report) 40934345a63Smrg { 41034345a63Smrg WARN3 41134345a63Smrg ("Multiple symbols for level %d/group %d on key %s\n", 41234345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 41334345a63Smrg ACTION2("Using %s, ignoring %s\n", 41434345a63Smrg XkbKeysymText(use, XkbMessage), 41534345a63Smrg XkbKeysymText(ignore, XkbMessage)); 41634345a63Smrg } 41734345a63Smrg resultSyms[i] = use; 41834345a63Smrg } 41934345a63Smrg if (resultActs != NULL) 42034345a63Smrg { 42134345a63Smrg XkbAction *fromAct, *toAct; 42234345a63Smrg fromAct = (from->acts[group] ? &from->acts[group][i] : NULL); 42334345a63Smrg toAct = (into->acts[group] ? &into->acts[group][i] : NULL); 42434345a63Smrg if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction)) 42534345a63Smrg && (toAct != NULL)) 42634345a63Smrg { 42734345a63Smrg resultActs[i] = *toAct; 42834345a63Smrg } 42934345a63Smrg else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction)) 43034345a63Smrg && (fromAct != NULL)) 43134345a63Smrg { 43234345a63Smrg resultActs[i] = *fromAct; 43334345a63Smrg } 43434345a63Smrg else 43534345a63Smrg { 43634345a63Smrg XkbAction *use, *ignore; 43734345a63Smrg if (clobber) 43834345a63Smrg { 43934345a63Smrg use = fromAct; 44034345a63Smrg ignore = toAct; 44134345a63Smrg } 44234345a63Smrg else 44334345a63Smrg { 44434345a63Smrg use = toAct; 44534345a63Smrg ignore = fromAct; 44634345a63Smrg } 44734345a63Smrg if (report) 44834345a63Smrg { 44934345a63Smrg WARN3 45034345a63Smrg ("Multiple actions for level %d/group %d on key %s\n", 45134345a63Smrg i + 1, group + 1, longText(into->name, XkbMessage)); 45234345a63Smrg ACTION2("Using %s, ignoring %s\n", 45334345a63Smrg XkbActionTypeText(use->type, XkbMessage), 45434345a63Smrg XkbActionTypeText(ignore->type, XkbMessage)); 45534345a63Smrg } 45634345a63Smrg resultActs[i] = *use; 45734345a63Smrg } 45834345a63Smrg } 45934345a63Smrg } 46034345a63Smrg if ((into->syms[group] != NULL) && (resultSyms != into->syms[group])) 46134345a63Smrg uFree(into->syms[group]); 46234345a63Smrg if ((from->syms[group] != NULL) && (resultSyms != from->syms[group])) 46334345a63Smrg uFree(from->syms[group]); 46434345a63Smrg if ((into->acts[group] != NULL) && (resultActs != into->acts[group])) 46534345a63Smrg uFree(into->acts[group]); 46634345a63Smrg if ((from->acts[group] != NULL) && (resultActs != from->acts[group])) 46734345a63Smrg uFree(from->acts[group]); 46834345a63Smrg into->numLevels[group] = resultWidth; 46934345a63Smrg into->syms[group] = resultSyms; 47034345a63Smrg from->syms[group] = NULL; 47134345a63Smrg into->acts[group] = resultActs; 47234345a63Smrg from->acts[group] = NULL; 47334345a63Smrg into->symsDefined |= (1 << group); 47434345a63Smrg from->symsDefined &= ~(1 << group); 47534345a63Smrg into->actsDefined |= (1 << group); 47634345a63Smrg from->actsDefined &= ~(1 << group); 477f46a6179Smrg return True; 478f46a6179Smrg} 479f46a6179Smrg 480f46a6179Smrgstatic Bool 48134345a63SmrgMergeKeys(SymbolsInfo * info, KeyInfo * into, KeyInfo * from) 482f46a6179Smrg{ 48334345a63Smrg register int i; 48434345a63Smrg unsigned collide = 0; 48534345a63Smrg Bool report; 48634345a63Smrg 48734345a63Smrg if (from->defs.merge == MergeReplace) 48834345a63Smrg { 48934345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 49034345a63Smrg { 49134345a63Smrg if (into->numLevels[i] != 0) 49234345a63Smrg { 49334345a63Smrg if (into->syms[i]) 49434345a63Smrg uFree(into->syms[i]); 49534345a63Smrg if (into->acts[i]) 49634345a63Smrg uFree(into->acts[i]); 49734345a63Smrg } 49834345a63Smrg } 49934345a63Smrg *into = *from; 50034345a63Smrg bzero(from, sizeof(KeyInfo)); 50134345a63Smrg return True; 50234345a63Smrg } 50334345a63Smrg report = ((warningLevel > 9) || 50434345a63Smrg ((into->defs.fileID == from->defs.fileID) 50534345a63Smrg && (warningLevel > 0))); 50634345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 50734345a63Smrg { 50834345a63Smrg if (from->numLevels[i] > 0) 50934345a63Smrg { 51034345a63Smrg if (into->numLevels[i] == 0) 51134345a63Smrg { 51234345a63Smrg into->numLevels[i] = from->numLevels[i]; 51334345a63Smrg into->syms[i] = from->syms[i]; 51434345a63Smrg into->acts[i] = from->acts[i]; 51534345a63Smrg into->symsDefined |= (1 << i); 51634345a63Smrg from->syms[i] = NULL; 51734345a63Smrg from->acts[i] = NULL; 51834345a63Smrg from->numLevels[i] = 0; 51934345a63Smrg from->symsDefined &= ~(1 << i); 52034345a63Smrg if (into->syms[i]) 52134345a63Smrg into->defs.defined |= _Key_Syms; 52234345a63Smrg if (into->acts[i]) 52334345a63Smrg into->defs.defined |= _Key_Acts; 52434345a63Smrg } 52534345a63Smrg else 52634345a63Smrg { 52734345a63Smrg if (report) 52834345a63Smrg { 52934345a63Smrg if (into->syms[i]) 53034345a63Smrg collide |= _Key_Syms; 53134345a63Smrg if (into->acts[i]) 53234345a63Smrg collide |= _Key_Acts; 53334345a63Smrg } 53434345a63Smrg MergeKeyGroups(info, into, from, (unsigned) i); 53534345a63Smrg } 53634345a63Smrg } 53734345a63Smrg if (from->types[i] != None) 53834345a63Smrg { 53934345a63Smrg if ((into->types[i] != None) && (report) && 54034345a63Smrg (into->types[i] != from->types[i])) 54134345a63Smrg { 54234345a63Smrg Atom use, ignore; 54334345a63Smrg collide |= _Key_Types; 54434345a63Smrg if (from->defs.merge != MergeAugment) 54534345a63Smrg { 54634345a63Smrg use = from->types[i]; 54734345a63Smrg ignore = into->types[i]; 54834345a63Smrg } 54934345a63Smrg else 55034345a63Smrg { 55134345a63Smrg use = into->types[i]; 55234345a63Smrg ignore = from->types[i]; 55334345a63Smrg } 55434345a63Smrg WARN2 55534345a63Smrg ("Multiple definitions for group %d type of key %s\n", 55634345a63Smrg i, longText(into->name, XkbMessage)); 55734345a63Smrg ACTION2("Using %s, ignoring %s\n", 55834345a63Smrg XkbAtomText(NULL, use, XkbMessage), 55934345a63Smrg XkbAtomText(NULL, ignore, XkbMessage)); 56034345a63Smrg } 56134345a63Smrg if ((from->defs.merge != MergeAugment) 56234345a63Smrg || (into->types[i] == None)) 56334345a63Smrg { 56434345a63Smrg into->types[i] = from->types[i]; 56534345a63Smrg } 56634345a63Smrg } 56734345a63Smrg } 56834345a63Smrg if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide)) 56934345a63Smrg { 57034345a63Smrg into->behavior = from->behavior; 57134345a63Smrg into->nameForOverlayKey = from->nameForOverlayKey; 57234345a63Smrg into->defs.defined |= _Key_Behavior; 57334345a63Smrg } 57434345a63Smrg if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide)) 57534345a63Smrg { 57634345a63Smrg into->vmodmap = from->vmodmap; 57734345a63Smrg into->defs.defined |= _Key_VModMap; 57834345a63Smrg } 57934345a63Smrg if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide)) 58034345a63Smrg { 58134345a63Smrg into->repeat = from->repeat; 58234345a63Smrg into->defs.defined |= _Key_Repeat; 58334345a63Smrg } 58434345a63Smrg if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide)) 58534345a63Smrg { 58634345a63Smrg into->dfltType = from->dfltType; 58734345a63Smrg into->defs.defined |= _Key_Type_Dflt; 58834345a63Smrg } 58934345a63Smrg if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide)) 59034345a63Smrg { 59134345a63Smrg into->groupInfo = from->groupInfo; 59234345a63Smrg into->defs.defined |= _Key_GroupInfo; 59334345a63Smrg } 59434345a63Smrg if (collide) 59534345a63Smrg { 59634345a63Smrg WARN1("Symbol map for key %s redefined\n", 59734345a63Smrg longText(into->name, XkbMessage)); 59834345a63Smrg ACTION1("Using %s definition for conflicting fields\n", 59934345a63Smrg (from->defs.merge == MergeAugment ? "first" : "last")); 600f46a6179Smrg } 601f46a6179Smrg return True; 602f46a6179Smrg} 603f46a6179Smrg 604f46a6179Smrgstatic Bool 60534345a63SmrgAddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbDescPtr xkb) 606f46a6179Smrg{ 60734345a63Smrg register int i; 60834345a63Smrg unsigned long real_name; 60934345a63Smrg 61034345a63Smrg for (i = 0; i < info->nKeys; i++) 61134345a63Smrg { 61234345a63Smrg if (info->keys[i].name == key->name) 61334345a63Smrg return MergeKeys(info, &info->keys[i], key); 61434345a63Smrg } 61534345a63Smrg if (FindKeyNameForAlias(xkb, key->name, &real_name)) 61634345a63Smrg { 61734345a63Smrg for (i = 0; i < info->nKeys; i++) 61834345a63Smrg { 61934345a63Smrg if (info->keys[i].name == real_name) 62034345a63Smrg return MergeKeys(info, &info->keys[i], key); 621f46a6179Smrg } 622f46a6179Smrg } 62334345a63Smrg if (info->nKeys >= info->szKeys) 62434345a63Smrg { 62534345a63Smrg info->szKeys += SYMBOLS_CHUNK; 62634345a63Smrg info->keys = 62734345a63Smrg uTypedRecalloc(info->keys, info->nKeys, info->szKeys, KeyInfo); 62834345a63Smrg if (!info->keys) 62934345a63Smrg { 63034345a63Smrg WSGO("Could not allocate key symbols descriptions\n"); 63134345a63Smrg ACTION("Some key symbols definitions may be lost\n"); 63234345a63Smrg return False; 63334345a63Smrg } 634f46a6179Smrg } 63534345a63Smrg return CopyKeyInfo(key, &info->keys[info->nKeys++], True); 636f46a6179Smrg} 637f46a6179Smrg 638f46a6179Smrgstatic Bool 63934345a63SmrgAddModMapEntry(SymbolsInfo * info, ModMapEntry * new) 640f46a6179Smrg{ 64134345a63Smrg ModMapEntry *mm; 64234345a63Smrg Bool clobber; 64334345a63Smrg 64434345a63Smrg clobber = (new->defs.merge != MergeAugment); 64534345a63Smrg for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next) 64634345a63Smrg { 64734345a63Smrg if (new->haveSymbol && mm->haveSymbol 64834345a63Smrg && (new->u.keySym == mm->u.keySym)) 64934345a63Smrg { 65034345a63Smrg unsigned use, ignore; 65134345a63Smrg if (mm->modifier != new->modifier) 65234345a63Smrg { 65334345a63Smrg if (clobber) 65434345a63Smrg { 65534345a63Smrg use = new->modifier; 65634345a63Smrg ignore = mm->modifier; 65734345a63Smrg } 65834345a63Smrg else 65934345a63Smrg { 66034345a63Smrg use = mm->modifier; 66134345a63Smrg ignore = new->modifier; 66234345a63Smrg } 66334345a63Smrg ERROR1 66434345a63Smrg ("%s added to symbol map for multiple modifiers\n", 66534345a63Smrg XkbKeysymText(new->u.keySym, XkbMessage)); 66634345a63Smrg ACTION2("Using %s, ignoring %s.\n", 66734345a63Smrg XkbModIndexText(use, XkbMessage), 66834345a63Smrg XkbModIndexText(ignore, XkbMessage)); 66934345a63Smrg mm->modifier = use; 67034345a63Smrg } 67134345a63Smrg return True; 67234345a63Smrg } 67334345a63Smrg if ((!new->haveSymbol) && (!mm->haveSymbol) && 67434345a63Smrg (new->u.keyName == mm->u.keyName)) 67534345a63Smrg { 67634345a63Smrg unsigned use, ignore; 67734345a63Smrg if (mm->modifier != new->modifier) 67834345a63Smrg { 67934345a63Smrg if (clobber) 68034345a63Smrg { 68134345a63Smrg use = new->modifier; 68234345a63Smrg ignore = mm->modifier; 68334345a63Smrg } 68434345a63Smrg else 68534345a63Smrg { 68634345a63Smrg use = mm->modifier; 68734345a63Smrg ignore = new->modifier; 68834345a63Smrg } 68934345a63Smrg ERROR1("Key %s added to map for multiple modifiers\n", 69034345a63Smrg longText(new->u.keyName, XkbMessage)); 69134345a63Smrg ACTION2("Using %s, ignoring %s.\n", 69234345a63Smrg XkbModIndexText(use, XkbMessage), 69334345a63Smrg XkbModIndexText(ignore, XkbMessage)); 69434345a63Smrg mm->modifier = use; 69534345a63Smrg } 69634345a63Smrg return True; 69734345a63Smrg } 69834345a63Smrg } 69934345a63Smrg mm = uTypedAlloc(ModMapEntry); 70034345a63Smrg if (mm == NULL) 70134345a63Smrg { 70234345a63Smrg WSGO("Could not allocate modifier map entry\n"); 70334345a63Smrg ACTION1("Modifier map for %s will be incomplete\n", 70434345a63Smrg XkbModIndexText(new->modifier, XkbMessage)); 70534345a63Smrg return False; 70634345a63Smrg } 70734345a63Smrg *mm = *new; 70834345a63Smrg mm->defs.next = &info->modMap->defs; 70934345a63Smrg info->modMap = mm; 710f46a6179Smrg return True; 711f46a6179Smrg} 712f46a6179Smrg 713f46a6179Smrg/***====================================================================***/ 714f46a6179Smrg 715f46a6179Smrgstatic void 71634345a63SmrgMergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from, 71734345a63Smrg unsigned merge, XkbDescPtr xkb) 718f46a6179Smrg{ 71934345a63Smrg register int i; 72034345a63Smrg KeyInfo *key; 72134345a63Smrg 72234345a63Smrg if (from->errorCount > 0) 72334345a63Smrg { 72434345a63Smrg into->errorCount += from->errorCount; 72534345a63Smrg return; 72634345a63Smrg } 72734345a63Smrg if (into->name == NULL) 72834345a63Smrg { 72934345a63Smrg into->name = from->name; 73034345a63Smrg from->name = NULL; 73134345a63Smrg } 73234345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 73334345a63Smrg { 73434345a63Smrg if (from->groupNames[i] != None) 73534345a63Smrg { 73634345a63Smrg if ((merge != MergeAugment) || (into->groupNames[i] == None)) 73734345a63Smrg into->groupNames[i] = from->groupNames[i]; 73834345a63Smrg } 73934345a63Smrg } 74034345a63Smrg for (i = 0, key = from->keys; i < from->nKeys; i++, key++) 74134345a63Smrg { 74234345a63Smrg if (merge != MergeDefault) 74334345a63Smrg key->defs.merge = merge; 74434345a63Smrg if (!AddKeySymbols(into, key, xkb)) 74534345a63Smrg into->errorCount++; 74634345a63Smrg } 74734345a63Smrg if (from->modMap != NULL) 74834345a63Smrg { 74934345a63Smrg ModMapEntry *mm, *next; 75034345a63Smrg for (mm = from->modMap; mm != NULL; mm = next) 75134345a63Smrg { 75234345a63Smrg if (merge != MergeDefault) 75334345a63Smrg mm->defs.merge = merge; 75434345a63Smrg if (!AddModMapEntry(into, mm)) 75534345a63Smrg into->errorCount++; 75634345a63Smrg next = (ModMapEntry *) mm->defs.next; 75734345a63Smrg uFree(mm); 75834345a63Smrg } 75934345a63Smrg from->modMap = NULL; 76034345a63Smrg } 76134345a63Smrg if (!MergeAliases(&into->aliases, &from->aliases, merge)) 76234345a63Smrg into->errorCount++; 763f46a6179Smrg return; 764f46a6179Smrg} 765f46a6179Smrg 76634345a63Smrgtypedef void (*FileHandler) (XkbFile * /* rtrn */ , 76734345a63Smrg XkbDescPtr /* xkb */ , 76834345a63Smrg unsigned /* merge */ , 76934345a63Smrg SymbolsInfo * /* included */ 77034345a63Smrg ); 771f46a6179Smrg 772f46a6179Smrgstatic Bool 77334345a63SmrgHandleIncludeSymbols(IncludeStmt * stmt, 77434345a63Smrg XkbDescPtr xkb, SymbolsInfo * info, FileHandler hndlr) 775f46a6179Smrg{ 77634345a63Smrg unsigned newMerge; 77734345a63Smrg XkbFile *rtrn; 77834345a63Smrg SymbolsInfo included; 77934345a63Smrg Bool haveSelf; 78034345a63Smrg 78134345a63Smrg haveSelf = False; 78234345a63Smrg if ((stmt->file == NULL) && (stmt->map == NULL)) 78334345a63Smrg { 78434345a63Smrg haveSelf = True; 78534345a63Smrg included = *info; 78634345a63Smrg bzero(info, sizeof(SymbolsInfo)); 78734345a63Smrg } 78834345a63Smrg else if (ProcessIncludeFile(stmt, XkmSymbolsIndex, &rtrn, &newMerge)) 78934345a63Smrg { 79034345a63Smrg InitSymbolsInfo(&included, xkb); 79134345a63Smrg included.fileID = included.dflt.defs.fileID = rtrn->id; 79234345a63Smrg included.merge = included.dflt.defs.merge = MergeOverride; 79334345a63Smrg if (stmt->modifier) 79434345a63Smrg { 79534345a63Smrg included.explicit_group = atoi(stmt->modifier) - 1; 79634345a63Smrg } 79734345a63Smrg else 79834345a63Smrg { 79934345a63Smrg included.explicit_group = info->explicit_group; 80034345a63Smrg } 80134345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &included); 80234345a63Smrg if (stmt->stmt != NULL) 80334345a63Smrg { 80434345a63Smrg if (included.name != NULL) 80534345a63Smrg uFree(included.name); 80634345a63Smrg included.name = stmt->stmt; 80734345a63Smrg stmt->stmt = NULL; 80834345a63Smrg } 80934345a63Smrg } 81034345a63Smrg else 81134345a63Smrg { 81234345a63Smrg info->errorCount += 10; 81334345a63Smrg return False; 81434345a63Smrg } 81534345a63Smrg if ((stmt->next != NULL) && (included.errorCount < 1)) 81634345a63Smrg { 81734345a63Smrg IncludeStmt *next; 81834345a63Smrg unsigned op; 81934345a63Smrg SymbolsInfo next_incl; 82034345a63Smrg 82134345a63Smrg for (next = stmt->next; next != NULL; next = next->next) 82234345a63Smrg { 82334345a63Smrg if ((next->file == NULL) && (next->map == NULL)) 82434345a63Smrg { 82534345a63Smrg haveSelf = True; 82634345a63Smrg MergeIncludedSymbols(&included, info, next->merge, xkb); 82734345a63Smrg FreeSymbolsInfo(info); 82834345a63Smrg } 82934345a63Smrg else if (ProcessIncludeFile(next, XkmSymbolsIndex, &rtrn, &op)) 83034345a63Smrg { 83134345a63Smrg InitSymbolsInfo(&next_incl, xkb); 83234345a63Smrg next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id; 83334345a63Smrg next_incl.merge = next_incl.dflt.defs.merge = MergeOverride; 83434345a63Smrg if (next->modifier) 83534345a63Smrg { 83634345a63Smrg next_incl.explicit_group = atoi(next->modifier) - 1; 83734345a63Smrg } 83834345a63Smrg else 83934345a63Smrg { 84034345a63Smrg next_incl.explicit_group = info->explicit_group; 841f46a6179Smrg } 84234345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); 84334345a63Smrg MergeIncludedSymbols(&included, &next_incl, op, xkb); 84434345a63Smrg FreeSymbolsInfo(&next_incl); 84534345a63Smrg } 84634345a63Smrg else 84734345a63Smrg { 84834345a63Smrg info->errorCount += 10; 84934345a63Smrg return False; 85034345a63Smrg } 85134345a63Smrg } 852f46a6179Smrg } 853f46a6179Smrg if (haveSelf) 85434345a63Smrg *info = included; 85534345a63Smrg else 85634345a63Smrg { 85734345a63Smrg MergeIncludedSymbols(info, &included, newMerge, xkb); 85834345a63Smrg FreeSymbolsInfo(&included); 859f46a6179Smrg } 86034345a63Smrg return (info->errorCount == 0); 861f46a6179Smrg} 862f46a6179Smrg 86334345a63Smrgstatic LookupEntry groupNames[] = { 86434345a63Smrg {"group1", 1}, 86534345a63Smrg {"group2", 2}, 86634345a63Smrg {"group3", 3}, 86734345a63Smrg {"group4", 4}, 86834345a63Smrg {"group5", 5}, 86934345a63Smrg {"group6", 6}, 87034345a63Smrg {"group7", 7}, 87134345a63Smrg {"group8", 8}, 87234345a63Smrg {NULL, 0} 873f46a6179Smrg}; 874f46a6179Smrg 875f46a6179Smrg 876f46a6179Smrg#define SYMBOLS 1 877f46a6179Smrg#define ACTIONS 2 878f46a6179Smrg 879f46a6179Smrgstatic Bool 88034345a63SmrgGetGroupIndex(KeyInfo * key, 88134345a63Smrg ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn) 882f46a6179Smrg{ 88334345a63Smrg const char *name; 88434345a63Smrg ExprResult tmp; 88534345a63Smrg 88634345a63Smrg if (what == SYMBOLS) 88734345a63Smrg name = "symbols"; 88834345a63Smrg else 88934345a63Smrg name = "actions"; 89034345a63Smrg 89134345a63Smrg if (arrayNdx == NULL) 89234345a63Smrg { 89334345a63Smrg register int i; 89434345a63Smrg unsigned defined; 89534345a63Smrg if (what == SYMBOLS) 89634345a63Smrg defined = key->symsDefined; 89734345a63Smrg else 89834345a63Smrg defined = key->actsDefined; 89934345a63Smrg 90034345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 90134345a63Smrg { 90234345a63Smrg if ((defined & (1 << i)) == 0) 90334345a63Smrg { 90434345a63Smrg *ndx_rtrn = i; 90534345a63Smrg return True; 90634345a63Smrg } 90734345a63Smrg } 90834345a63Smrg ERROR3("Too many groups of %s for key %s (max %d)\n", name, 90934345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 91034345a63Smrg ACTION1("Ignoring %s defined for extra groups\n", name); 91134345a63Smrg return False; 91234345a63Smrg } 91334345a63Smrg if (!ExprResolveInteger 91434345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 91534345a63Smrg { 91634345a63Smrg ERROR2("Illegal group index for %s of key %s\n", name, 91734345a63Smrg longText(key->name, XkbMessage)); 91834345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 91934345a63Smrg return False; 92034345a63Smrg } 92134345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 92234345a63Smrg { 92334345a63Smrg ERROR3("Group index for %s of key %s is out of range (1..%d)\n", 92434345a63Smrg name, longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 92534345a63Smrg ACTION2("Ignoring %s for group %d\n", name, tmp.uval); 92634345a63Smrg return False; 92734345a63Smrg } 92834345a63Smrg *ndx_rtrn = tmp.uval - 1; 929f46a6179Smrg return True; 930f46a6179Smrg} 931f46a6179Smrg 932f46a6179Smrgstatic Bool 93334345a63SmrgAddSymbolsToKey(KeyInfo * key, 93434345a63Smrg XkbDescPtr xkb, 93534345a63Smrg char *field, 93634345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 937f46a6179Smrg{ 93834345a63Smrg unsigned ndx, nSyms; 93934345a63Smrg int i; 94034345a63Smrg 94134345a63Smrg if (!GetGroupIndex(key, arrayNdx, SYMBOLS, &ndx)) 94234345a63Smrg return False; 94334345a63Smrg if (value == NULL) 94434345a63Smrg { 94534345a63Smrg key->symsDefined |= (1 << ndx); 94634345a63Smrg return True; 94734345a63Smrg } 94834345a63Smrg if (value->op != ExprKeysymList) 94934345a63Smrg { 95034345a63Smrg ERROR1("Expected a list of symbols, found %s\n", 95134345a63Smrg exprOpText(value->op)); 95234345a63Smrg ACTION2("Ignoring symbols for group %d of %s\n", ndx, 95334345a63Smrg longText(key->name, XkbMessage)); 95434345a63Smrg return False; 95534345a63Smrg } 95634345a63Smrg if (key->syms[ndx] != NULL) 95734345a63Smrg { 95834345a63Smrg WSGO2("Symbols for key %s, group %d already defined\n", 95934345a63Smrg longText(key->name, XkbMessage), ndx); 96034345a63Smrg return False; 96134345a63Smrg } 96234345a63Smrg nSyms = value->value.list.nSyms; 96334345a63Smrg if (((key->numLevels[ndx] < nSyms) || (key->syms[ndx] == NULL)) && 96434345a63Smrg (!ResizeKeyGroup(key, ndx, nSyms, False))) 96534345a63Smrg { 96634345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 96734345a63Smrg longText(key->name, XkbMessage)); 96834345a63Smrg ACTION("Symbols lost\n"); 96934345a63Smrg return False; 97034345a63Smrg } 97134345a63Smrg key->symsDefined |= (1 << ndx); 97283e5f723Smrg for (i = 0; i < nSyms; i++) { 97383e5f723Smrg if (!LookupKeysym(value->value.list.syms[i], &key->syms[ndx][i])) { 97483e5f723Smrg WSGO1("Could not resolve keysym %s\n", value->value.list.syms[i]); 97583e5f723Smrg key->syms[ndx][i] = NoSymbol; 97683e5f723Smrg } 97783e5f723Smrg } 97834345a63Smrg for (i = key->numLevels[ndx] - 1; 97934345a63Smrg (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--) 98034345a63Smrg { 98134345a63Smrg key->numLevels[ndx]--; 982f46a6179Smrg } 983f46a6179Smrg return True; 984f46a6179Smrg} 985f46a6179Smrg 986f46a6179Smrgstatic Bool 98734345a63SmrgAddActionsToKey(KeyInfo * key, 98834345a63Smrg XkbDescPtr xkb, 98934345a63Smrg char *field, 99034345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 991f46a6179Smrg{ 99234345a63Smrg register int i; 99334345a63Smrg unsigned ndx, nActs; 99434345a63Smrg ExprDef *act; 99534345a63Smrg XkbAnyAction *toAct; 99634345a63Smrg 99734345a63Smrg if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx)) 99834345a63Smrg return False; 99934345a63Smrg 100034345a63Smrg if (value == NULL) 100134345a63Smrg { 100234345a63Smrg key->actsDefined |= (1 << ndx); 100334345a63Smrg return True; 100434345a63Smrg } 100534345a63Smrg if (value->op != ExprActionList) 100634345a63Smrg { 100734345a63Smrg WSGO1("Bad expression type (%d) for action list value\n", value->op); 100834345a63Smrg ACTION2("Ignoring actions for group %d of %s\n", ndx, 100934345a63Smrg longText(key->name, XkbMessage)); 101034345a63Smrg return False; 101134345a63Smrg } 101234345a63Smrg if (key->acts[ndx] != NULL) 101334345a63Smrg { 101434345a63Smrg WSGO2("Actions for key %s, group %d already defined\n", 101534345a63Smrg longText(key->name, XkbMessage), ndx); 101634345a63Smrg return False; 101734345a63Smrg } 101834345a63Smrg for (nActs = 0, act = value->value.child; act != NULL; nActs++) 101934345a63Smrg { 102034345a63Smrg act = (ExprDef *) act->common.next; 102134345a63Smrg } 102234345a63Smrg if (nActs < 1) 102334345a63Smrg { 102434345a63Smrg WSGO("Action list but not actions in AddActionsToKey\n"); 102534345a63Smrg return False; 102634345a63Smrg } 102734345a63Smrg if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) && 102834345a63Smrg (!ResizeKeyGroup(key, ndx, nActs, True))) 102934345a63Smrg { 103034345a63Smrg WSGO2("Could not resize group %d of key %s\n", ndx, 103134345a63Smrg longText(key->name, XkbMessage)); 103234345a63Smrg ACTION("Actions lost\n"); 103334345a63Smrg return False; 103434345a63Smrg } 103534345a63Smrg key->actsDefined |= (1 << ndx); 103634345a63Smrg 103734345a63Smrg toAct = (XkbAnyAction *) key->acts[ndx]; 103834345a63Smrg act = value->value.child; 103934345a63Smrg for (i = 0; i < nActs; i++, toAct++) 104034345a63Smrg { 104134345a63Smrg if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action)) 104234345a63Smrg { 104334345a63Smrg ERROR1("Illegal action definition for %s\n", 104434345a63Smrg longText(key->name, XkbMessage)); 104534345a63Smrg ACTION2("Action for group %d/level %d ignored\n", ndx + 1, i + 1); 104634345a63Smrg } 104734345a63Smrg act = (ExprDef *) act->common.next; 1048f46a6179Smrg } 1049f46a6179Smrg return True; 1050f46a6179Smrg} 1051f46a6179Smrg 1052f46a6179Smrgstatic int 105334345a63SmrgSetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value) 1054f46a6179Smrg{ 105534345a63Smrg ExprResult tmp; 105634345a63Smrg unsigned radio_groups = 0; 105734345a63Smrg 105834345a63Smrg if (arrayNdx == NULL) 105934345a63Smrg { 106034345a63Smrg radio_groups = XkbAllRadioGroupsMask; 106134345a63Smrg } 106234345a63Smrg else 106334345a63Smrg { 106434345a63Smrg if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL)) 106534345a63Smrg { 106634345a63Smrg ERROR("Illegal index in group name definition\n"); 106734345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 106834345a63Smrg return False; 106934345a63Smrg } 107034345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 107134345a63Smrg { 107234345a63Smrg ERROR1("Illegal radio group specified (must be 1..%d)\n", 107334345a63Smrg XkbMaxRadioGroups + 1); 107434345a63Smrg ACTION1("Value of \"allow none\" for group %d ignored\n", 107534345a63Smrg tmp.uval); 107634345a63Smrg return False; 107734345a63Smrg } 107834345a63Smrg radio_groups |= (1 << (tmp.uval - 1)); 107934345a63Smrg } 108034345a63Smrg if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) 108134345a63Smrg { 108234345a63Smrg ERROR1("Illegal \"allow none\" value for %s\n", 108334345a63Smrg longText(key->name, XkbMessage)); 108434345a63Smrg ACTION("Non-boolean value ignored\n"); 108534345a63Smrg return False; 108634345a63Smrg } 108734345a63Smrg if (tmp.uval) 108834345a63Smrg key->allowNone |= radio_groups; 108934345a63Smrg else 109034345a63Smrg key->allowNone &= ~radio_groups; 1091f46a6179Smrg return True; 1092f46a6179Smrg} 1093f46a6179Smrg 1094f46a6179Smrg 109534345a63Smrgstatic LookupEntry lockingEntries[] = { 109634345a63Smrg {"true", XkbKB_Lock}, 109734345a63Smrg {"yes", XkbKB_Lock}, 109834345a63Smrg {"on", XkbKB_Lock}, 109934345a63Smrg {"false", XkbKB_Default}, 110034345a63Smrg {"no", XkbKB_Default}, 110134345a63Smrg {"off", XkbKB_Default}, 110234345a63Smrg {"permanent", XkbKB_Lock | XkbKB_Permanent}, 110334345a63Smrg {NULL, 0} 1104f46a6179Smrg}; 1105f46a6179Smrg 110634345a63Smrgstatic LookupEntry repeatEntries[] = { 110734345a63Smrg {"true", RepeatYes}, 110834345a63Smrg {"yes", RepeatYes}, 110934345a63Smrg {"on", RepeatYes}, 111034345a63Smrg {"false", RepeatNo}, 111134345a63Smrg {"no", RepeatNo}, 111234345a63Smrg {"off", RepeatNo}, 111334345a63Smrg {"default", RepeatUndefined}, 111434345a63Smrg {NULL, 0} 1115f46a6179Smrg}; 1116f46a6179Smrg 111734345a63Smrgstatic LookupEntry rgEntries[] = { 111834345a63Smrg {"none", 0}, 111934345a63Smrg {NULL, 0} 1120f46a6179Smrg}; 1121f46a6179Smrg 1122f46a6179Smrgstatic Bool 112334345a63SmrgSetSymbolsField(KeyInfo * key, 112434345a63Smrg XkbDescPtr xkb, 112534345a63Smrg char *field, 112634345a63Smrg ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) 1127f46a6179Smrg{ 112834345a63Smrg Bool ok = True; 112934345a63Smrg ExprResult tmp; 113034345a63Smrg 113134345a63Smrg if (uStrCaseCmp(field, "type") == 0) 113234345a63Smrg { 113334345a63Smrg ExprResult ndx; 113434345a63Smrg if ((!ExprResolveString(value, &tmp, NULL, NULL)) 113534345a63Smrg && (warningLevel > 0)) 113634345a63Smrg { 113734345a63Smrg WARN("The type field of a key symbol map must be a string\n"); 113834345a63Smrg ACTION("Ignoring illegal type definition\n"); 113934345a63Smrg } 114034345a63Smrg if (arrayNdx == NULL) 114134345a63Smrg { 114234345a63Smrg key->dfltType = XkbInternAtom(NULL, tmp.str, False); 114334345a63Smrg key->defs.defined |= _Key_Type_Dflt; 114434345a63Smrg } 114534345a63Smrg else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup, 114634345a63Smrg (XPointer) groupNames)) 114734345a63Smrg { 114834345a63Smrg ERROR1("Illegal group index for type of key %s\n", 114934345a63Smrg longText(key->name, XkbMessage)); 115034345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 115134345a63Smrg return False; 115234345a63Smrg } 115334345a63Smrg else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups)) 115434345a63Smrg { 115534345a63Smrg ERROR2 115634345a63Smrg ("Group index for type of key %s is out of range (1..%d)\n", 115734345a63Smrg longText(key->name, XkbMessage), XkbNumKbdGroups + 1); 115834345a63Smrg ACTION1("Ignoring type for group %d\n", ndx.uval); 115934345a63Smrg return False; 116034345a63Smrg } 116134345a63Smrg else 116234345a63Smrg { 116334345a63Smrg key->types[ndx.uval - 1] = XkbInternAtom(NULL, tmp.str, False); 116434345a63Smrg key->typesDefined |= (1 << (ndx.uval - 1)); 116534345a63Smrg } 116634345a63Smrg } 116734345a63Smrg else if (uStrCaseCmp(field, "symbols") == 0) 116834345a63Smrg return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info); 116934345a63Smrg else if (uStrCaseCmp(field, "actions") == 0) 117034345a63Smrg return AddActionsToKey(key, xkb, field, arrayNdx, value, info); 117134345a63Smrg else if ((uStrCaseCmp(field, "vmods") == 0) || 117234345a63Smrg (uStrCaseCmp(field, "virtualmods") == 0) || 117334345a63Smrg (uStrCaseCmp(field, "virtualmodifiers") == 0)) 117434345a63Smrg { 117534345a63Smrg ok = ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb); 117634345a63Smrg if (ok) 117734345a63Smrg { 117834345a63Smrg key->vmodmap = (tmp.uval >> 8); 117934345a63Smrg key->defs.defined |= _Key_VModMap; 118034345a63Smrg } 118134345a63Smrg else 118234345a63Smrg { 118334345a63Smrg ERROR1("Expected a virtual modifier mask, found %s\n", 118434345a63Smrg exprOpText(value->op)); 118534345a63Smrg ACTION1("Ignoring virtual modifiers definition for key %s\n", 118634345a63Smrg longText(key->name, XkbMessage)); 118734345a63Smrg } 118834345a63Smrg } 118934345a63Smrg else if ((uStrCaseCmp(field, "locking") == 0) 119034345a63Smrg || (uStrCaseCmp(field, "lock") == 0) 119134345a63Smrg || (uStrCaseCmp(field, "locks") == 0)) 119234345a63Smrg { 119334345a63Smrg ok = ExprResolveEnum(value, &tmp, lockingEntries); 119434345a63Smrg if (ok) 119534345a63Smrg key->behavior.type = tmp.uval; 119634345a63Smrg key->defs.defined |= _Key_Behavior; 119734345a63Smrg } 119834345a63Smrg else if ((uStrCaseCmp(field, "radiogroup") == 0) || 119934345a63Smrg (uStrCaseCmp(field, "permanentradiogroup") == 0)) 120034345a63Smrg { 120134345a63Smrg Bool permanent = False; 120234345a63Smrg if (uStrCaseCmp(field, "permanentradiogroup") == 0) 120334345a63Smrg permanent = True; 120434345a63Smrg ok = ExprResolveInteger(value, &tmp, SimpleLookup, 120534345a63Smrg (XPointer) rgEntries); 120634345a63Smrg if (!ok) 120734345a63Smrg { 120834345a63Smrg ERROR1("Illegal radio group specification for %s\n", 120934345a63Smrg longText(key->name, XkbMessage)); 121034345a63Smrg ACTION("Non-integer radio group ignored\n"); 121134345a63Smrg return False; 121234345a63Smrg } 121334345a63Smrg if (tmp.uval == 0) 121434345a63Smrg { 121534345a63Smrg key->behavior.type = XkbKB_Default; 121634345a63Smrg key->behavior.data = 0; 121734345a63Smrg return ok; 121834345a63Smrg } 121934345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups)) 122034345a63Smrg { 122134345a63Smrg ERROR1 122234345a63Smrg ("Radio group specification for %s out of range (1..32)\n", 122334345a63Smrg longText(key->name, XkbMessage)); 122434345a63Smrg ACTION1("Illegal radio group %d ignored\n", tmp.uval); 122534345a63Smrg return False; 122634345a63Smrg } 122734345a63Smrg key->behavior.type = 122834345a63Smrg XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0); 122934345a63Smrg key->behavior.data = tmp.uval - 1; 123034345a63Smrg if (key->allowNone & (1 << (tmp.uval - 1))) 123134345a63Smrg key->behavior.data |= XkbKB_RGAllowNone; 123234345a63Smrg key->defs.defined |= _Key_Behavior; 123334345a63Smrg } 123434345a63Smrg else if (uStrCaseEqual(field, "allownone")) 123534345a63Smrg { 123634345a63Smrg ok = SetAllowNone(key, arrayNdx, value); 123734345a63Smrg } 123834345a63Smrg else if (uStrCasePrefix("overlay", field) || 123934345a63Smrg uStrCasePrefix("permanentoverlay", field)) 124034345a63Smrg { 124134345a63Smrg Bool permanent = False; 124234345a63Smrg char *which; 124334345a63Smrg int overlayNdx; 124434345a63Smrg if (uStrCasePrefix("permanent", field)) 124534345a63Smrg { 124634345a63Smrg permanent = True; 124734345a63Smrg which = &field[sizeof("permanentoverlay") - 1]; 124834345a63Smrg } 124934345a63Smrg else 125034345a63Smrg { 125134345a63Smrg which = &field[sizeof("overlay") - 1]; 125234345a63Smrg } 125334345a63Smrg if (sscanf(which, "%d", &overlayNdx) == 1) 125434345a63Smrg { 125534345a63Smrg if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0)) 125634345a63Smrg { 125734345a63Smrg ERROR2("Illegal overlay %d specified for %s\n", 125834345a63Smrg overlayNdx, longText(key->name, XkbMessage)); 125934345a63Smrg ACTION("Ignored\n"); 126034345a63Smrg return False; 126134345a63Smrg } 126234345a63Smrg } 126334345a63Smrg else if (*which == '\0') 126434345a63Smrg overlayNdx = 1; 126534345a63Smrg else if (warningLevel > 0) 126634345a63Smrg { 126734345a63Smrg ERROR2("Illegal overlay \"%s\" specified for %s\n", 126834345a63Smrg which, longText(key->name, XkbMessage)); 126934345a63Smrg ACTION("Ignored\n"); 127034345a63Smrg return False; 127134345a63Smrg } 127234345a63Smrg ok = ExprResolveKeyName(value, &tmp, NULL, NULL); 127334345a63Smrg if (!ok) 127434345a63Smrg { 127534345a63Smrg ERROR1("Illegal overlay key specification for %s\n", 127634345a63Smrg longText(key->name, XkbMessage)); 127734345a63Smrg ACTION("Overlay key must be specified by name\n"); 127834345a63Smrg return False; 127934345a63Smrg } 128034345a63Smrg if (overlayNdx == 1) 128134345a63Smrg key->behavior.type = XkbKB_Overlay1; 128234345a63Smrg else 128334345a63Smrg key->behavior.type = XkbKB_Overlay2; 128434345a63Smrg if (permanent) 128534345a63Smrg key->behavior.type |= XkbKB_Permanent; 128634345a63Smrg 128734345a63Smrg key->behavior.data = 0; 128834345a63Smrg key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name); 128934345a63Smrg key->defs.defined |= _Key_Behavior; 129034345a63Smrg } 129134345a63Smrg else if ((uStrCaseCmp(field, "repeating") == 0) || 129234345a63Smrg (uStrCaseCmp(field, "repeats") == 0) || 129334345a63Smrg (uStrCaseCmp(field, "repeat") == 0)) 129434345a63Smrg { 129534345a63Smrg ok = ExprResolveEnum(value, &tmp, repeatEntries); 129634345a63Smrg if (!ok) 129734345a63Smrg { 129834345a63Smrg ERROR1("Illegal repeat setting for %s\n", 129934345a63Smrg longText(key->name, XkbMessage)); 130034345a63Smrg ACTION("Non-boolean repeat setting ignored\n"); 130134345a63Smrg return False; 130234345a63Smrg } 130334345a63Smrg key->repeat = tmp.uval; 130434345a63Smrg key->defs.defined |= _Key_Repeat; 130534345a63Smrg } 130634345a63Smrg else if ((uStrCaseCmp(field, "groupswrap") == 0) || 130734345a63Smrg (uStrCaseCmp(field, "wrapgroups") == 0)) 130834345a63Smrg { 130934345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 131034345a63Smrg if (!ok) 131134345a63Smrg { 131234345a63Smrg ERROR1("Illegal groupsWrap setting for %s\n", 131334345a63Smrg longText(key->name, XkbMessage)); 131434345a63Smrg ACTION("Non-boolean value ignored\n"); 131534345a63Smrg return False; 131634345a63Smrg } 131734345a63Smrg if (tmp.uval) 131834345a63Smrg key->groupInfo = XkbWrapIntoRange; 131934345a63Smrg else 132034345a63Smrg key->groupInfo = XkbClampIntoRange; 132134345a63Smrg key->defs.defined |= _Key_GroupInfo; 132234345a63Smrg } 132334345a63Smrg else if ((uStrCaseCmp(field, "groupsclamp") == 0) || 132434345a63Smrg (uStrCaseCmp(field, "clampgroups") == 0)) 132534345a63Smrg { 132634345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 132734345a63Smrg if (!ok) 132834345a63Smrg { 132934345a63Smrg ERROR1("Illegal groupsClamp setting for %s\n", 133034345a63Smrg longText(key->name, XkbMessage)); 133134345a63Smrg ACTION("Non-boolean value ignored\n"); 133234345a63Smrg return False; 133334345a63Smrg } 133434345a63Smrg if (tmp.uval) 133534345a63Smrg key->groupInfo = XkbClampIntoRange; 133634345a63Smrg else 133734345a63Smrg key->groupInfo = XkbWrapIntoRange; 133834345a63Smrg key->defs.defined |= _Key_GroupInfo; 133934345a63Smrg } 134034345a63Smrg else if ((uStrCaseCmp(field, "groupsredirect") == 0) || 134134345a63Smrg (uStrCaseCmp(field, "redirectgroups") == 0)) 134234345a63Smrg { 134334345a63Smrg if (!ExprResolveInteger 134434345a63Smrg (value, &tmp, SimpleLookup, (XPointer) groupNames)) 134534345a63Smrg { 134634345a63Smrg ERROR1("Illegal group index for redirect of key %s\n", 134734345a63Smrg longText(key->name, XkbMessage)); 134834345a63Smrg ACTION("Definition with non-integer group ignored\n"); 134934345a63Smrg return False; 135034345a63Smrg } 135134345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 135234345a63Smrg { 135334345a63Smrg ERROR2("Out-of-range (1..%d) group for redirect of key %s\n", 135434345a63Smrg XkbNumKbdGroups, longText(key->name, XkbMessage)); 135534345a63Smrg ERROR1("Ignoring illegal group %d\n", tmp.uval); 135634345a63Smrg return False; 135734345a63Smrg } 135834345a63Smrg key->groupInfo = 135934345a63Smrg XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1); 136034345a63Smrg key->defs.defined |= _Key_GroupInfo; 136134345a63Smrg } 136234345a63Smrg else 136334345a63Smrg { 136434345a63Smrg ERROR1("Unknown field %s in a symbol interpretation\n", field); 136534345a63Smrg ACTION("Definition ignored\n"); 136634345a63Smrg ok = False; 1367f46a6179Smrg } 1368f46a6179Smrg return ok; 1369f46a6179Smrg} 1370f46a6179Smrg 1371f46a6179Smrgstatic int 137234345a63SmrgSetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value) 1373f46a6179Smrg{ 137434345a63Smrg ExprResult tmp, name; 137534345a63Smrg 137634345a63Smrg if ((arrayNdx == NULL) && (warningLevel > 0)) 137734345a63Smrg { 137834345a63Smrg WARN("You must specify an index when specifying a group name\n"); 137934345a63Smrg ACTION("Group name definition without array subscript ignored\n"); 138034345a63Smrg return False; 138134345a63Smrg } 138234345a63Smrg if (!ExprResolveInteger 138334345a63Smrg (arrayNdx, &tmp, SimpleLookup, (XPointer) groupNames)) 138434345a63Smrg { 138534345a63Smrg ERROR("Illegal index in group name definition\n"); 138634345a63Smrg ACTION("Definition with non-integer array index ignored\n"); 138734345a63Smrg return False; 138834345a63Smrg } 138934345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 139034345a63Smrg { 139134345a63Smrg ERROR1 139234345a63Smrg ("Attempt to specify name for illegal group (must be 1..%d)\n", 139334345a63Smrg XkbNumKbdGroups + 1); 139434345a63Smrg ACTION1("Name for group %d ignored\n", tmp.uval); 139534345a63Smrg return False; 139634345a63Smrg } 139734345a63Smrg if (!ExprResolveString(value, &name, NULL, NULL)) 139834345a63Smrg { 139934345a63Smrg ERROR("Group name must be a string\n"); 140034345a63Smrg ACTION1("Illegal name for group %d ignored\n", tmp.uval); 140134345a63Smrg return False; 140234345a63Smrg } 140334345a63Smrg info->groupNames[tmp.uval - 1 + info->explicit_group] = 140434345a63Smrg XkbInternAtom(NULL, name.str, False); 140534345a63Smrg 1406f46a6179Smrg return True; 1407f46a6179Smrg} 1408f46a6179Smrg 1409f46a6179Smrgstatic int 141034345a63SmrgHandleSymbolsVar(VarDef * stmt, XkbDescPtr xkb, SymbolsInfo * info) 1411f46a6179Smrg{ 141234345a63Smrg ExprResult elem, field, tmp; 141334345a63Smrg ExprDef *arrayNdx; 141434345a63Smrg 141534345a63Smrg if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0) 141634345a63Smrg return 0; /* internal error, already reported */ 141734345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) 141834345a63Smrg { 141934345a63Smrg return SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx, 142034345a63Smrg stmt->value, info); 142134345a63Smrg } 142234345a63Smrg else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) || 142334345a63Smrg (uStrCaseCmp(field.str, "groupname") == 142434345a63Smrg 0))) 142534345a63Smrg { 142634345a63Smrg return SetGroupName(info, arrayNdx, stmt->value); 142734345a63Smrg } 142834345a63Smrg else if ((elem.str == NULL) 142934345a63Smrg && ((uStrCaseCmp(field.str, "groupswrap") == 0) 143034345a63Smrg || (uStrCaseCmp(field.str, "wrapgroups") == 0))) 143134345a63Smrg { 143234345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 143334345a63Smrg { 143434345a63Smrg ERROR("Illegal setting for global groupsWrap\n"); 143534345a63Smrg ACTION("Non-boolean value ignored\n"); 143634345a63Smrg return False; 143734345a63Smrg } 143834345a63Smrg if (tmp.uval) 143934345a63Smrg info->groupInfo = XkbWrapIntoRange; 144034345a63Smrg else 144134345a63Smrg info->groupInfo = XkbClampIntoRange; 144234345a63Smrg return True; 144334345a63Smrg } 144434345a63Smrg else if ((elem.str == NULL) 144534345a63Smrg && ((uStrCaseCmp(field.str, "groupsclamp") == 0) 144634345a63Smrg || (uStrCaseCmp(field.str, "clampgroups") == 0))) 144734345a63Smrg { 144834345a63Smrg if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL)) 144934345a63Smrg { 145034345a63Smrg ERROR("Illegal setting for global groupsClamp\n"); 145134345a63Smrg ACTION("Non-boolean value ignored\n"); 145234345a63Smrg return False; 145334345a63Smrg } 145434345a63Smrg if (tmp.uval) 145534345a63Smrg info->groupInfo = XkbClampIntoRange; 145634345a63Smrg else 145734345a63Smrg info->groupInfo = XkbWrapIntoRange; 145834345a63Smrg return True; 145934345a63Smrg } 146034345a63Smrg else if ((elem.str == NULL) 146134345a63Smrg && ((uStrCaseCmp(field.str, "groupsredirect") == 0) 146234345a63Smrg || (uStrCaseCmp(field.str, "redirectgroups") == 0))) 146334345a63Smrg { 146434345a63Smrg if (!ExprResolveInteger(stmt->value, &tmp, 146534345a63Smrg SimpleLookup, (XPointer) groupNames)) 146634345a63Smrg { 146734345a63Smrg ERROR("Illegal group index for global groupsRedirect\n"); 146834345a63Smrg ACTION("Definition with non-integer group ignored\n"); 146934345a63Smrg return False; 147034345a63Smrg } 147134345a63Smrg if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups)) 147234345a63Smrg { 147334345a63Smrg ERROR1 147434345a63Smrg ("Out-of-range (1..%d) group for global groupsRedirect\n", 147534345a63Smrg XkbNumKbdGroups); 147634345a63Smrg ACTION1("Ignoring illegal group %d\n", tmp.uval); 147734345a63Smrg return False; 147834345a63Smrg } 147934345a63Smrg info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval); 148034345a63Smrg return True; 148134345a63Smrg } 148234345a63Smrg else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0)) 148334345a63Smrg { 148434345a63Smrg return SetAllowNone(&info->dflt, arrayNdx, stmt->value); 148534345a63Smrg } 148634345a63Smrg return SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value, 148734345a63Smrg &info->action); 1488f46a6179Smrg} 1489f46a6179Smrg 1490f46a6179Smrgstatic Bool 149134345a63SmrgHandleSymbolsBody(VarDef * def, 149234345a63Smrg XkbDescPtr xkb, KeyInfo * key, SymbolsInfo * info) 1493f46a6179Smrg{ 149434345a63Smrg Bool ok = True; 149534345a63Smrg ExprResult tmp, field; 149634345a63Smrg ExprDef *arrayNdx; 149734345a63Smrg 149834345a63Smrg for (; def != NULL; def = (VarDef *) def->common.next) 149934345a63Smrg { 150034345a63Smrg if ((def->name) && (def->name->type == ExprFieldRef)) 150134345a63Smrg { 150234345a63Smrg ok = HandleSymbolsVar(def, xkb, info); 150334345a63Smrg continue; 150434345a63Smrg } 150534345a63Smrg else 150634345a63Smrg { 150734345a63Smrg if (def->name == NULL) 150834345a63Smrg { 150934345a63Smrg if ((def->value == NULL) 151034345a63Smrg || (def->value->op == ExprKeysymList)) 151134345a63Smrg field.str = "symbols"; 151234345a63Smrg else 151334345a63Smrg field.str = "actions"; 151434345a63Smrg arrayNdx = NULL; 151534345a63Smrg } 151634345a63Smrg else 151734345a63Smrg { 151834345a63Smrg ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); 151934345a63Smrg } 152034345a63Smrg if (ok) 152134345a63Smrg ok = SetSymbolsField(key, xkb, field.str, arrayNdx, 152234345a63Smrg def->value, info); 152334345a63Smrg } 1524f46a6179Smrg } 1525f46a6179Smrg return ok; 1526f46a6179Smrg} 1527f46a6179Smrg 1528f46a6179Smrgstatic Bool 152934345a63SmrgSetExplicitGroup(SymbolsInfo * info, KeyInfo * key) 1530f46a6179Smrg{ 1531f46a6179Smrg unsigned group = info->explicit_group; 1532f46a6179Smrg 1533f46a6179Smrg if (group == 0) 153434345a63Smrg return True; 153534345a63Smrg 153634345a63Smrg if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1) 153734345a63Smrg { 153834345a63Smrg int i; 153934345a63Smrg WARN1("For the map %s an explicit group specified\n", info->name); 154034345a63Smrg WARN1("but key %s has more than one group defined\n", 154134345a63Smrg longText(key->name, XkbMessage)); 154234345a63Smrg ACTION("All groups except first one will be ignored\n"); 154334345a63Smrg for (i = 1; i < XkbNumKbdGroups; i++) 154434345a63Smrg { 154534345a63Smrg key->numLevels[i] = 0; 154634345a63Smrg if (key->syms[i] != NULL) 154734345a63Smrg uFree(key->syms[i]); 154834345a63Smrg key->syms[i] = (KeySym *) NULL; 154934345a63Smrg if (key->acts[i] != NULL) 155034345a63Smrg uFree(key->acts[i]); 155134345a63Smrg key->acts[i] = (XkbAction *) NULL; 155234345a63Smrg key->types[i] = (Atom) 0; 155334345a63Smrg } 155434345a63Smrg } 155534345a63Smrg key->typesDefined = key->symsDefined = key->actsDefined = 1 << group; 155634345a63Smrg 155734345a63Smrg key->numLevels[group] = key->numLevels[0]; 155834345a63Smrg key->numLevels[0] = 0; 155934345a63Smrg key->syms[group] = key->syms[0]; 156034345a63Smrg key->syms[0] = (KeySym *) NULL; 156134345a63Smrg key->acts[group] = key->acts[0]; 156234345a63Smrg key->acts[0] = (XkbAction *) NULL; 156334345a63Smrg key->types[group] = key->types[0]; 156434345a63Smrg key->types[0] = (Atom) 0; 156534345a63Smrg return True; 1566f46a6179Smrg} 1567f46a6179Smrg 1568f46a6179Smrgstatic int 156934345a63SmrgHandleSymbolsDef(SymbolsDef * stmt, 157034345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1571f46a6179Smrg{ 157234345a63Smrg KeyInfo key; 157334345a63Smrg 1574f46a6179Smrg InitKeyInfo(&key); 157534345a63Smrg CopyKeyInfo(&info->dflt, &key, False); 157634345a63Smrg key.defs.merge = stmt->merge; 157734345a63Smrg key.name = KeyNameToLong(stmt->keyName); 157834345a63Smrg if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info)) 157934345a63Smrg { 158034345a63Smrg info->errorCount++; 158134345a63Smrg return False; 1582f46a6179Smrg } 1583f46a6179Smrg 158434345a63Smrg if (!SetExplicitGroup(info, &key)) 158534345a63Smrg { 1586f46a6179Smrg info->errorCount++; 1587f46a6179Smrg return False; 1588f46a6179Smrg } 1589f46a6179Smrg 159034345a63Smrg if (!AddKeySymbols(info, &key, xkb)) 159134345a63Smrg { 159234345a63Smrg info->errorCount++; 159334345a63Smrg return False; 1594f46a6179Smrg } 1595f46a6179Smrg return True; 1596f46a6179Smrg} 1597f46a6179Smrg 1598f46a6179Smrgstatic Bool 159934345a63SmrgHandleModMapDef(ModMapDef * def, 160034345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1601f46a6179Smrg{ 160234345a63Smrg ExprDef *key; 160334345a63Smrg ModMapEntry tmp; 160434345a63Smrg ExprResult rtrn; 160534345a63Smrg Bool ok; 160634345a63Smrg 160734345a63Smrg if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn)) 160834345a63Smrg { 160934345a63Smrg ERROR("Illegal modifier map definition\n"); 161034345a63Smrg ACTION1("Ignoring map for non-modifier \"%s\"\n", 161134345a63Smrg XkbAtomText(NULL, def->modifier, XkbMessage)); 161234345a63Smrg return False; 161334345a63Smrg } 161434345a63Smrg ok = True; 161534345a63Smrg tmp.modifier = rtrn.uval; 161634345a63Smrg for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) 161734345a63Smrg { 161834345a63Smrg if ((key->op == ExprValue) && (key->type == TypeKeyName)) 161934345a63Smrg { 162034345a63Smrg tmp.haveSymbol = False; 162134345a63Smrg tmp.u.keyName = KeyNameToLong(key->value.keyName); 162234345a63Smrg } 162334345a63Smrg else if (ExprResolveKeySym(key, &rtrn, NULL, NULL)) 162434345a63Smrg { 162534345a63Smrg tmp.haveSymbol = True; 162634345a63Smrg tmp.u.keySym = rtrn.uval; 162734345a63Smrg } 162834345a63Smrg else 162934345a63Smrg { 163034345a63Smrg ERROR("Modmap entries may contain only key names or keysyms\n"); 163134345a63Smrg ACTION1("Illegal definition for %s modifier ignored\n", 163234345a63Smrg XkbModIndexText(tmp.modifier, XkbMessage)); 163334345a63Smrg continue; 163434345a63Smrg } 163534345a63Smrg 163634345a63Smrg ok = AddModMapEntry(info, &tmp) && ok; 1637f46a6179Smrg } 1638f46a6179Smrg return ok; 1639f46a6179Smrg} 1640f46a6179Smrg 1641f46a6179Smrgstatic void 164234345a63SmrgHandleSymbolsFile(XkbFile * file, 164334345a63Smrg XkbDescPtr xkb, unsigned merge, SymbolsInfo * info) 1644f46a6179Smrg{ 164534345a63Smrg ParseCommon *stmt; 164634345a63Smrg 164734345a63Smrg info->name = uStringDup(file->name); 164834345a63Smrg stmt = file->defs; 164934345a63Smrg while (stmt) 165034345a63Smrg { 165134345a63Smrg switch (stmt->stmtType) 165234345a63Smrg { 165334345a63Smrg case StmtInclude: 165434345a63Smrg if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info, 165534345a63Smrg HandleSymbolsFile)) 165634345a63Smrg info->errorCount++; 165734345a63Smrg break; 165834345a63Smrg case StmtSymbolsDef: 165934345a63Smrg if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info)) 166034345a63Smrg info->errorCount++; 166134345a63Smrg break; 166234345a63Smrg case StmtVarDef: 166334345a63Smrg if (!HandleSymbolsVar((VarDef *) stmt, xkb, info)) 166434345a63Smrg info->errorCount++; 166534345a63Smrg break; 166634345a63Smrg case StmtVModDef: 166734345a63Smrg if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) 166834345a63Smrg info->errorCount++; 166934345a63Smrg break; 167034345a63Smrg case StmtInterpDef: 167134345a63Smrg ERROR("Interpretation files may not include other types\n"); 167234345a63Smrg ACTION("Ignoring definition of symbol interpretation\n"); 167334345a63Smrg info->errorCount++; 167434345a63Smrg break; 167534345a63Smrg case StmtKeycodeDef: 167634345a63Smrg ERROR("Interpretation files may not include other types\n"); 167734345a63Smrg ACTION("Ignoring definition of key name\n"); 167834345a63Smrg info->errorCount++; 167934345a63Smrg break; 168034345a63Smrg case StmtModMapDef: 168134345a63Smrg if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info)) 168234345a63Smrg info->errorCount++; 168334345a63Smrg break; 168434345a63Smrg default: 168534345a63Smrg WSGO1("Unexpected statement type %d in HandleSymbolsFile\n", 168634345a63Smrg stmt->stmtType); 168734345a63Smrg break; 168834345a63Smrg } 168934345a63Smrg stmt = stmt->next; 169034345a63Smrg if (info->errorCount > 10) 169134345a63Smrg { 1692f46a6179Smrg#ifdef NOISY 169334345a63Smrg ERROR("Too many errors\n"); 1694f46a6179Smrg#endif 169534345a63Smrg ACTION1("Abandoning symbols file \"%s\"\n", file->topName); 169634345a63Smrg break; 169734345a63Smrg } 1698f46a6179Smrg } 1699f46a6179Smrg return; 1700f46a6179Smrg} 1701f46a6179Smrg 1702f46a6179Smrgstatic Bool 170334345a63SmrgFindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn) 1704f46a6179Smrg{ 170534345a63Smrg register int i, j; 170634345a63Smrg register Bool gotOne; 170734345a63Smrg 170834345a63Smrg j = 0; 170934345a63Smrg do 171034345a63Smrg { 171134345a63Smrg gotOne = False; 171234345a63Smrg for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) 171334345a63Smrg { 171434345a63Smrg if (j < (int) XkbKeyNumSyms(xkb, i)) 171534345a63Smrg { 1716f46a6179Smrg gotOne = True; 171734345a63Smrg if ((XkbKeySym(xkb, i, j) == sym)) 171834345a63Smrg { 171934345a63Smrg *kc_rtrn = i; 1720f46a6179Smrg return True; 172134345a63Smrg } 1722f46a6179Smrg } 1723f46a6179Smrg } 1724f46a6179Smrg j++; 172534345a63Smrg } 172634345a63Smrg while (gotOne); 1727f46a6179Smrg return False; 1728f46a6179Smrg} 1729f46a6179Smrg 173034345a63Smrg/** 173134345a63Smrg * Find the given name in the xkb->map->types and return its index. 173234345a63Smrg * 173334345a63Smrg * @param name The atom to search for. 173434345a63Smrg * @param type_rtrn Set to the index of the name if found. 173534345a63Smrg * 173634345a63Smrg * @return True if found, False otherwise. 173734345a63Smrg */ 1738f46a6179Smrgstatic Bool 173934345a63SmrgFindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn) 1740f46a6179Smrg{ 174134345a63Smrg register unsigned n; 174234345a63Smrg 174334345a63Smrg if (xkb && xkb->map && xkb->map->types) 174434345a63Smrg { 174534345a63Smrg for (n = 0; n < xkb->map->num_types; n++) 174634345a63Smrg { 174734345a63Smrg if (xkb->map->types[n].name == (Atom) name) 174834345a63Smrg { 174934345a63Smrg *type_rtrn = n; 175034345a63Smrg return True; 175134345a63Smrg } 175234345a63Smrg } 1753f46a6179Smrg } 1754f46a6179Smrg return False; 1755f46a6179Smrg} 1756f46a6179Smrg 1757f46a6179Smrgstatic Bool 175834345a63SmrgKSIsLower(KeySym ks) 1759f46a6179Smrg{ 1760f46a6179Smrg KeySym lower, upper; 1761f46a6179Smrg XConvertCase(ks, &lower, &upper); 1762f46a6179Smrg 1763f46a6179Smrg if (lower == upper) 1764f46a6179Smrg return False; 1765f46a6179Smrg return (ks == lower ? True : False); 1766f46a6179Smrg} 1767f46a6179Smrg 1768f46a6179Smrgstatic Bool 176934345a63SmrgKSIsUpper(KeySym ks) 1770f46a6179Smrg{ 1771f46a6179Smrg KeySym lower, upper; 1772f46a6179Smrg XConvertCase(ks, &lower, &upper); 1773f46a6179Smrg 1774f46a6179Smrg if (lower == upper) 1775f46a6179Smrg return False; 1776f46a6179Smrg return (ks == upper ? True : False); 1777f46a6179Smrg} 1778f46a6179Smrg 177934345a63Smrg/** 178034345a63Smrg * Assign a type to the given sym and return the Atom for the type assigned. 178134345a63Smrg * 178234345a63Smrg * Simple recipe: 178334345a63Smrg * - ONE_LEVEL for width 0/1 178434345a63Smrg * - ALPHABETIC for 2 shift levels, with lower/upercase 178534345a63Smrg * - KEYPAD for keypad keys. 178634345a63Smrg * - TWO_LEVEL for other 2 shift level keys. 178734345a63Smrg * and the same for four level keys. 178834345a63Smrg * 178934345a63Smrg * @param width Number of sysms in syms. 179034345a63Smrg * @param syms The keysyms for the given key (must be size width). 179134345a63Smrg * @param typeNameRtrn Set to the Atom of the type name. 179234345a63Smrg * 179334345a63Smrg * @returns True if a type could be found, False otherwise. 179434345a63Smrg */ 1795f46a6179Smrgstatic Bool 179634345a63SmrgFindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn, 179734345a63Smrg Bool * autoType) 1798f46a6179Smrg{ 1799f46a6179Smrg *autoType = False; 180034345a63Smrg if ((width == 1) || (width == 0)) 180134345a63Smrg { 180234345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ONE_LEVEL", False); 180334345a63Smrg *autoType = True; 180434345a63Smrg } 180534345a63Smrg else if (width == 2) 180634345a63Smrg { 180734345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 180834345a63Smrg { 180934345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "ALPHABETIC", False); 181034345a63Smrg } 181134345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 181234345a63Smrg { 181334345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "KEYPAD", False); 181434345a63Smrg *autoType = True; 181534345a63Smrg } 181634345a63Smrg else 181734345a63Smrg { 181834345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "TWO_LEVEL", False); 181934345a63Smrg *autoType = True; 182034345a63Smrg } 182134345a63Smrg } 182234345a63Smrg else if (width <= 4) 182334345a63Smrg { 182434345a63Smrg if (syms && KSIsLower(syms[0]) && KSIsUpper(syms[1])) 182534345a63Smrg if (KSIsLower(syms[2]) && KSIsUpper(syms[3])) 182634345a63Smrg *typeNameRtrn = 182734345a63Smrg XkbInternAtom(NULL, "FOUR_LEVEL_ALPHABETIC", False); 182834345a63Smrg else 182934345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, 183034345a63Smrg "FOUR_LEVEL_SEMIALPHABETIC", 183134345a63Smrg False); 183234345a63Smrg 183334345a63Smrg else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))) 183434345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False); 183534345a63Smrg else 183634345a63Smrg *typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False); 183734345a63Smrg /* XXX: why not set autoType here? */ 183834345a63Smrg } 183934345a63Smrg return ((width >= 0) && (width <= 4)); 1840f46a6179Smrg} 1841f46a6179Smrg 184234345a63Smrg/** 184334345a63Smrg * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the 184434345a63Smrg * groups, and reduce to one group if all groups are identical anyway. 184534345a63Smrg */ 1846f46a6179Smrgstatic void 184734345a63SmrgPrepareKeyDef(KeyInfo * key) 1848f46a6179Smrg{ 1849f46a6179Smrg int i, j, width, defined, lastGroup; 1850f46a6179Smrg Bool identical; 185134345a63Smrg 1852f46a6179Smrg defined = key->symsDefined | key->actsDefined | key->typesDefined; 185334345a63Smrg /* get highest group number */ 185434345a63Smrg for (i = XkbNumKbdGroups - 1; i >= 0; i--) 185534345a63Smrg { 185634345a63Smrg if (defined & (1 << i)) 185734345a63Smrg break; 1858f46a6179Smrg } 1859f46a6179Smrg lastGroup = i; 1860f46a6179Smrg 1861f46a6179Smrg if (lastGroup == 0) 186234345a63Smrg return; 1863f46a6179Smrg 1864f46a6179Smrg /* If there are empty groups between non-empty ones fill them with data */ 1865f46a6179Smrg /* from the first group. */ 1866f46a6179Smrg /* We can make a wrong assumption here. But leaving gaps is worse. */ 186734345a63Smrg for (i = lastGroup; i > 0; i--) 186834345a63Smrg { 186934345a63Smrg if (defined & (1 << i)) 1870f46a6179Smrg continue; 1871f46a6179Smrg width = key->numLevels[0]; 187234345a63Smrg if (key->typesDefined & 1) 187334345a63Smrg { 187434345a63Smrg for (j = 0; j < width; j++) 187534345a63Smrg { 1876f46a6179Smrg key->types[i] = key->types[0]; 1877f46a6179Smrg } 1878f46a6179Smrg key->typesDefined |= 1 << i; 1879f46a6179Smrg } 188034345a63Smrg if ((key->actsDefined & 1) && key->acts[0]) 188134345a63Smrg { 188234345a63Smrg key->acts[i] = uTypedCalloc(width, XkbAction); 1883f46a6179Smrg if (key->acts[i] == NULL) 1884f46a6179Smrg continue; 1885f46a6179Smrg memcpy((void *) key->acts[i], (void *) key->acts[0], 1886f46a6179Smrg width * sizeof(XkbAction)); 1887f46a6179Smrg key->actsDefined |= 1 << i; 1888f46a6179Smrg } 188934345a63Smrg if ((key->symsDefined & 1) && key->syms[0]) 189034345a63Smrg { 189134345a63Smrg key->syms[i] = uTypedCalloc(width, KeySym); 1892f46a6179Smrg if (key->syms[i] == NULL) 1893f46a6179Smrg continue; 1894f46a6179Smrg memcpy((void *) key->syms[i], (void *) key->syms[0], 1895f46a6179Smrg width * sizeof(KeySym)); 1896f46a6179Smrg key->symsDefined |= 1 << i; 1897f46a6179Smrg } 189834345a63Smrg if (defined & 1) 189934345a63Smrg { 1900f46a6179Smrg key->numLevels[i] = key->numLevels[0]; 1901f46a6179Smrg } 1902f46a6179Smrg } 1903f46a6179Smrg /* If all groups are completely identical remove them all */ 1904f46a6179Smrg /* exept the first one. */ 1905f46a6179Smrg identical = True; 190634345a63Smrg for (i = lastGroup; i > 0; i--) 190734345a63Smrg { 1908f46a6179Smrg if ((key->numLevels[i] != key->numLevels[0]) || 190934345a63Smrg (key->types[i] != key->types[0])) 191034345a63Smrg { 1911f46a6179Smrg identical = False; 1912f46a6179Smrg break; 1913f46a6179Smrg } 1914f46a6179Smrg if ((key->syms[i] != key->syms[0]) && 191534345a63Smrg (key->syms[i] == NULL || key->syms[0] == NULL || 191634345a63Smrg memcmp((void *) key->syms[i], (void *) key->syms[0], 191734345a63Smrg sizeof(KeySym) * key->numLevels[0]))) 191834345a63Smrg { 191934345a63Smrg identical = False; 192034345a63Smrg break; 192134345a63Smrg } 1922f46a6179Smrg if ((key->acts[i] != key->acts[0]) && 192334345a63Smrg (key->acts[i] == NULL || key->acts[0] == NULL || 192434345a63Smrg memcmp((void *) key->acts[i], (void *) key->acts[0], 192534345a63Smrg sizeof(XkbAction) * key->numLevels[0]))) 192634345a63Smrg { 1927f46a6179Smrg identical = False; 1928f46a6179Smrg break; 192934345a63Smrg } 193034345a63Smrg } 193134345a63Smrg if (identical) 193234345a63Smrg { 193334345a63Smrg for (i = lastGroup; i > 0; i--) 193434345a63Smrg { 193534345a63Smrg key->numLevels[i] = 0; 193634345a63Smrg if (key->syms[i] != NULL) 193734345a63Smrg uFree(key->syms[i]); 193834345a63Smrg key->syms[i] = (KeySym *) NULL; 193934345a63Smrg if (key->acts[i] != NULL) 194034345a63Smrg uFree(key->acts[i]); 194134345a63Smrg key->acts[i] = (XkbAction *) NULL; 194234345a63Smrg key->types[i] = (Atom) 0; 194334345a63Smrg } 194434345a63Smrg key->symsDefined &= 1; 194534345a63Smrg key->actsDefined &= 1; 194634345a63Smrg key->typesDefined &= 1; 1947f46a6179Smrg } 1948f46a6179Smrg return; 1949f46a6179Smrg} 1950f46a6179Smrg 195134345a63Smrg/** 195234345a63Smrg * Copy the KeyInfo into result. 195334345a63Smrg * 195434345a63Smrg * This function recurses. 195534345a63Smrg */ 1956f46a6179Smrgstatic Bool 195734345a63SmrgCopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from) 1958f46a6179Smrg{ 195934345a63Smrg register int i; 196034345a63Smrg unsigned okc, kc, width, tmp, nGroups; 196134345a63Smrg XkbKeyTypePtr type; 196234345a63Smrg Bool haveActions, autoType, useAlias; 196334345a63Smrg KeySym *outSyms; 196434345a63Smrg XkbAction *outActs; 196534345a63Smrg XkbDescPtr xkb; 196634345a63Smrg unsigned types[XkbNumKbdGroups]; 196734345a63Smrg 196834345a63Smrg xkb = result->xkb; 196934345a63Smrg useAlias = (start_from == 0); 197034345a63Smrg 197134345a63Smrg /* get the keycode for the key. */ 197234345a63Smrg if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb), 197334345a63Smrg start_from)) 197434345a63Smrg { 197534345a63Smrg if ((start_from == 0) && (warningLevel >= 5)) 197634345a63Smrg { 197734345a63Smrg WARN2("Key %s not found in %s keycodes\n", 197834345a63Smrg longText(key->name, XkbMessage), 197934345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 198034345a63Smrg ACTION("Symbols ignored\n"); 198134345a63Smrg } 198234345a63Smrg return False; 198334345a63Smrg } 198434345a63Smrg 198534345a63Smrg haveActions = False; 198634345a63Smrg for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) 198734345a63Smrg { 198834345a63Smrg if (((i + 1) > nGroups) 198934345a63Smrg && (((key->symsDefined | key->actsDefined) & (1 << i)) 199034345a63Smrg || (key->typesDefined) & (1 << i))) 199134345a63Smrg nGroups = i + 1; 199234345a63Smrg if (key->acts[i]) 199334345a63Smrg haveActions = True; 199434345a63Smrg autoType = False; 199534345a63Smrg /* Assign the type to the key, if it is missing. */ 199634345a63Smrg if (key->types[i] == None) 199734345a63Smrg { 199834345a63Smrg if (key->dfltType != None) 199934345a63Smrg key->types[i] = key->dfltType; 200034345a63Smrg else if (FindAutomaticType(key->numLevels[i], key->syms[i], 200134345a63Smrg &key->types[i], &autoType)) 200234345a63Smrg { 200334345a63Smrg } 200434345a63Smrg else 200534345a63Smrg { 200634345a63Smrg if (warningLevel >= 5) 200734345a63Smrg { 200834345a63Smrg WARN1("No automatic type for %d symbols\n", 200934345a63Smrg (unsigned int) key->numLevels[i]); 201034345a63Smrg ACTION3("Using %s for the %s key (keycode %d)\n", 201134345a63Smrg XkbAtomText(NULL, key->types[i], 201234345a63Smrg XkbMessage), 201334345a63Smrg longText(key->name, XkbMessage), kc); 201434345a63Smrg } 201534345a63Smrg } 201634345a63Smrg } 201734345a63Smrg if (FindNamedType(xkb, key->types[i], &types[i])) 201834345a63Smrg { 201934345a63Smrg if (!autoType || key->numLevels[i] > 2) 202034345a63Smrg xkb->server->explicit[kc] |= (1 << i); 202134345a63Smrg } 202234345a63Smrg else 202334345a63Smrg { 202434345a63Smrg if (warningLevel >= 3) 202534345a63Smrg { 202634345a63Smrg WARN1("Type \"%s\" is not defined\n", 202734345a63Smrg XkbAtomText(NULL, key->types[i], XkbMessage)); 202834345a63Smrg ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n", 202934345a63Smrg longText(key->name, XkbMessage), kc); 203034345a63Smrg } 203134345a63Smrg types[i] = XkbTwoLevelIndex; 203234345a63Smrg } 203334345a63Smrg /* if the type specifies less syms than the key has, shrink the key */ 203434345a63Smrg type = &xkb->map->types[types[i]]; 203534345a63Smrg if (type->num_levels < key->numLevels[i]) 203634345a63Smrg { 203734345a63Smrg if (warningLevel > 0) 203834345a63Smrg { 203934345a63Smrg WARN4 204034345a63Smrg ("Type \"%s\" has %d levels, but %s has %d symbols\n", 204134345a63Smrg XkbAtomText(NULL, type->name, XkbMessage), 204234345a63Smrg (unsigned int) type->num_levels, 204334345a63Smrg longText(key->name, XkbMessage), 204434345a63Smrg (unsigned int) key->numLevels[i]); 204534345a63Smrg ACTION("Ignoring extra symbols\n"); 204634345a63Smrg } 204734345a63Smrg key->numLevels[i] = type->num_levels; 204834345a63Smrg } 204934345a63Smrg if (key->numLevels[i] > width) 205034345a63Smrg width = key->numLevels[i]; 205134345a63Smrg if (type->num_levels > width) 205234345a63Smrg width = type->num_levels; 205334345a63Smrg } 205434345a63Smrg 205534345a63Smrg /* width is now the largest width found */ 205634345a63Smrg 205734345a63Smrg i = width * nGroups; 205834345a63Smrg outSyms = XkbResizeKeySyms(xkb, kc, i); 205934345a63Smrg if (outSyms == NULL) 206034345a63Smrg { 206134345a63Smrg WSGO2("Could not enlarge symbols for %s (keycode %d)\n", 206234345a63Smrg longText(key->name, XkbMessage), kc); 206334345a63Smrg return False; 206434345a63Smrg } 206534345a63Smrg if (haveActions) 206634345a63Smrg { 206734345a63Smrg outActs = XkbResizeKeyActions(xkb, kc, i); 206834345a63Smrg if (outActs == NULL) 206934345a63Smrg { 207034345a63Smrg WSGO2("Could not enlarge actions for %s (key %d)\n", 207134345a63Smrg longText(key->name, XkbMessage), kc); 207234345a63Smrg return False; 207334345a63Smrg } 207434345a63Smrg xkb->server->explicit[kc] |= XkbExplicitInterpretMask; 207534345a63Smrg } 207634345a63Smrg else 207734345a63Smrg outActs = NULL; 207834345a63Smrg if (key->defs.defined & _Key_GroupInfo) 207934345a63Smrg i = key->groupInfo; 208034345a63Smrg else 208134345a63Smrg i = xkb->map->key_sym_map[kc].group_info; 208234345a63Smrg 208334345a63Smrg xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups); 208434345a63Smrg xkb->map->key_sym_map[kc].width = width; 208534345a63Smrg for (i = 0; i < nGroups; i++) 208634345a63Smrg { 208734345a63Smrg /* assign kt_index[i] to the index of the type in map->types. 208834345a63Smrg * kt_index[i] may have been set by a previous run (if we have two 208934345a63Smrg * layouts specified). Let's not overwrite it with the ONE_LEVEL 209034345a63Smrg * default group if we dont even have keys for this group anyway. 209134345a63Smrg * 209234345a63Smrg * FIXME: There should be a better fix for this. 209334345a63Smrg */ 209434345a63Smrg if (key->numLevels[i]) 209534345a63Smrg xkb->map->key_sym_map[kc].kt_index[i] = types[i]; 209634345a63Smrg if (key->syms[i] != NULL) 209734345a63Smrg { 209834345a63Smrg /* fill key to "width" symbols*/ 209934345a63Smrg for (tmp = 0; tmp < width; tmp++) 210034345a63Smrg { 210134345a63Smrg if (tmp < key->numLevels[i]) 210234345a63Smrg outSyms[tmp] = key->syms[i][tmp]; 210334345a63Smrg else 210434345a63Smrg outSyms[tmp] = NoSymbol; 210534345a63Smrg if ((outActs != NULL) && (key->acts[i] != NULL)) 210634345a63Smrg { 210734345a63Smrg if (tmp < key->numLevels[i]) 210834345a63Smrg outActs[tmp] = key->acts[i][tmp]; 210934345a63Smrg else 211034345a63Smrg outActs[tmp].type = XkbSA_NoAction; 211134345a63Smrg } 211234345a63Smrg } 211334345a63Smrg } 211434345a63Smrg outSyms += width; 211534345a63Smrg if (outActs) 211634345a63Smrg outActs += width; 211734345a63Smrg } 211834345a63Smrg switch (key->behavior.type & XkbKB_OpMask) 211934345a63Smrg { 212034345a63Smrg case XkbKB_Default: 212134345a63Smrg break; 212234345a63Smrg case XkbKB_Overlay1: 212334345a63Smrg case XkbKB_Overlay2: 212434345a63Smrg /* find key by name! */ 212534345a63Smrg if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True, 212634345a63Smrg CreateKeyNames(xkb), 0)) 212734345a63Smrg { 212834345a63Smrg if (warningLevel >= 1) 212934345a63Smrg { 213034345a63Smrg WARN2("Key %s not found in %s keycodes\n", 213134345a63Smrg longText(key->nameForOverlayKey, XkbMessage), 213234345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 213334345a63Smrg ACTION1("Not treating %s as an overlay key \n", 213434345a63Smrg longText(key->name, XkbMessage)); 213534345a63Smrg } 213634345a63Smrg break; 213734345a63Smrg } 213834345a63Smrg key->behavior.data = okc; 213934345a63Smrg default: 214034345a63Smrg xkb->server->behaviors[kc] = key->behavior; 214134345a63Smrg xkb->server->explicit[kc] |= XkbExplicitBehaviorMask; 214234345a63Smrg break; 214334345a63Smrg } 214434345a63Smrg if (key->defs.defined & _Key_VModMap) 214534345a63Smrg { 214634345a63Smrg xkb->server->vmodmap[kc] = key->vmodmap; 214734345a63Smrg xkb->server->explicit[kc] |= XkbExplicitVModMapMask; 214834345a63Smrg } 214934345a63Smrg if (key->repeat != RepeatUndefined) 215034345a63Smrg { 215134345a63Smrg if (key->repeat == RepeatYes) 215234345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8)); 215334345a63Smrg else 215434345a63Smrg xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8)); 215534345a63Smrg xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask; 215634345a63Smrg } 215734345a63Smrg 215834345a63Smrg /* do the same thing for the next key */ 215934345a63Smrg CopySymbolsDef(result, key, kc + 1); 2160f46a6179Smrg return True; 2161f46a6179Smrg} 2162f46a6179Smrg 2163f46a6179Smrgstatic Bool 216434345a63SmrgCopyModMapDef(XkbFileInfo * result, ModMapEntry * entry) 2165f46a6179Smrg{ 216634345a63Smrg unsigned kc; 216734345a63Smrg XkbDescPtr xkb; 216834345a63Smrg 216934345a63Smrg xkb = result->xkb; 217034345a63Smrg if ((!entry->haveSymbol) 217134345a63Smrg && 217234345a63Smrg (!FindNamedKey 217334345a63Smrg (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0))) 217434345a63Smrg { 217534345a63Smrg if (warningLevel >= 5) 217634345a63Smrg { 217734345a63Smrg WARN2("Key %s not found in %s keycodes\n", 217834345a63Smrg longText(entry->u.keyName, XkbMessage), 217934345a63Smrg XkbAtomText(NULL, xkb->names->keycodes, XkbMessage)); 218034345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 218134345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 218234345a63Smrg } 218334345a63Smrg return False; 218434345a63Smrg } 218534345a63Smrg else if (entry->haveSymbol 218634345a63Smrg && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc))) 218734345a63Smrg { 218834345a63Smrg if (warningLevel > 5) 218934345a63Smrg { 219034345a63Smrg WARN2("Key \"%s\" not found in %s symbol map\n", 219134345a63Smrg XkbKeysymText(entry->u.keySym, XkbMessage), 219234345a63Smrg XkbAtomText(NULL, xkb->names->symbols, XkbMessage)); 219334345a63Smrg ACTION1("Modifier map entry for %s not updated\n", 219434345a63Smrg XkbModIndexText(entry->modifier, XkbMessage)); 219534345a63Smrg } 219634345a63Smrg return False; 219734345a63Smrg } 219834345a63Smrg xkb->map->modmap[kc] |= (1 << entry->modifier); 2199f46a6179Smrg return True; 2200f46a6179Smrg} 2201f46a6179Smrg 220234345a63Smrg/** 220334345a63Smrg * Handle the xkb_symbols section of an xkb file. 220434345a63Smrg * 220534345a63Smrg * @param file The parsed xkb_symbols section of the xkb file. 220634345a63Smrg * @param result Handle to the data to store the result in. 220734345a63Smrg * @param merge Merge strategy (e.g. MergeOverride). 220834345a63Smrg */ 2209f46a6179SmrgBool 221034345a63SmrgCompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge) 2211f46a6179Smrg{ 221234345a63Smrg register int i; 221334345a63Smrg SymbolsInfo info; 221434345a63Smrg XkbDescPtr xkb; 2215f46a6179Smrg 221634345a63Smrg xkb = result->xkb; 221734345a63Smrg InitSymbolsInfo(&info, xkb); 221834345a63Smrg info.dflt.defs.fileID = file->id; 221934345a63Smrg info.dflt.defs.merge = merge; 222034345a63Smrg HandleSymbolsFile(file, xkb, merge, &info); 2221f46a6179Smrg 2222f46a6179Smrg if (info.nKeys == 0) 2223f46a6179Smrg return True; 222434345a63Smrg if (info.errorCount == 0) 222534345a63Smrg { 222634345a63Smrg KeyInfo *key; 222734345a63Smrg 222834345a63Smrg /* alloc memory in the xkb struct */ 222934345a63Smrg if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0) 223034345a63Smrg != Success) 223134345a63Smrg { 223234345a63Smrg WSGO("Can not allocate names in CompileSymbols\n"); 223334345a63Smrg ACTION("Symbols not added\n"); 223434345a63Smrg return False; 223534345a63Smrg } 223634345a63Smrg if (XkbAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0) 223734345a63Smrg != Success) 223834345a63Smrg { 223934345a63Smrg WSGO("Could not allocate client map in CompileSymbols\n"); 224034345a63Smrg ACTION("Symbols not added\n"); 224134345a63Smrg return False; 224234345a63Smrg } 224334345a63Smrg if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success) 224434345a63Smrg { 224534345a63Smrg WSGO("Could not allocate server map in CompileSymbols\n"); 224634345a63Smrg ACTION("Symbols not added\n"); 224734345a63Smrg return False; 224834345a63Smrg } 224934345a63Smrg if (XkbAllocControls(xkb, XkbPerKeyRepeatMask) != Success) 225034345a63Smrg { 225134345a63Smrg WSGO("Could not allocate controls in CompileSymbols\n"); 225234345a63Smrg ACTION("Symbols not added\n"); 225334345a63Smrg return False; 225434345a63Smrg } 225534345a63Smrg 225634345a63Smrg /* now copy info into xkb. */ 225734345a63Smrg xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False); 225834345a63Smrg if (info.aliases) 225934345a63Smrg ApplyAliases(xkb, False, &info.aliases); 226034345a63Smrg for (i = 0; i < XkbNumKbdGroups; i++) 226134345a63Smrg { 226234345a63Smrg if (info.groupNames[i] != None) 226334345a63Smrg xkb->names->groups[i] = info.groupNames[i]; 226434345a63Smrg } 226534345a63Smrg /* sanitize keys */ 226634345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 226734345a63Smrg { 226834345a63Smrg PrepareKeyDef(key); 226934345a63Smrg } 227034345a63Smrg /* copy! */ 227134345a63Smrg for (key = info.keys, i = 0; i < info.nKeys; i++, key++) 227234345a63Smrg { 227334345a63Smrg if (!CopySymbolsDef(result, key, 0)) 227434345a63Smrg info.errorCount++; 227534345a63Smrg } 227634345a63Smrg if (warningLevel > 3) 227734345a63Smrg { 227834345a63Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) 227934345a63Smrg { 228034345a63Smrg if (xkb->names->keys[i].name[0] == '\0') 228134345a63Smrg continue; 228234345a63Smrg if (XkbKeyNumGroups(xkb, i) < 1) 228334345a63Smrg { 228434345a63Smrg char buf[5]; 228534345a63Smrg memcpy(buf, xkb->names->keys[i].name, 4); 228634345a63Smrg buf[4] = '\0'; 228734345a63Smrg WARN2 228834345a63Smrg ("No symbols defined for <%s> (keycode %d)\n", 228934345a63Smrg buf, i); 229034345a63Smrg } 229134345a63Smrg } 229234345a63Smrg } 229334345a63Smrg if (info.modMap) 229434345a63Smrg { 229534345a63Smrg ModMapEntry *mm, *next; 229634345a63Smrg for (mm = info.modMap; mm != NULL; mm = next) 229734345a63Smrg { 229834345a63Smrg if (!CopyModMapDef(result, mm)) 229934345a63Smrg info.errorCount++; 230034345a63Smrg next = (ModMapEntry *) mm->defs.next; 230134345a63Smrg } 230234345a63Smrg } 230334345a63Smrg return True; 2304f46a6179Smrg } 2305f46a6179Smrg return False; 2306f46a6179Smrg} 2307