#define DEBUG_VAR debugFlags
#include <stdio.h>
#include "xkbcomp.h"
#include "tokens.h"
#include "expr.h"
#include "misc.h"
#include <X11/extensions/XKB.h>
#include <X11/extensions/XKBstr.h>
#include "vmod.h"
void
InitVModInfo(VModInfo * info, XkbDescPtr xkb)
{
ClearVModInfo(info, xkb);
info->errorCount = 0;
return;
}
void
ClearVModInfo(VModInfo * info, XkbDescPtr xkb)
{
register int i;
if (XkbAllocNames(xkb, XkbVirtualModNamesMask, 0, 0) != Success)
return;
if (XkbAllocServerMap(xkb, XkbVirtualModsMask, 0) != Success)
return;
info->xkb = xkb;
info->newlyDefined = info->defined = info->available = 0;
if (xkb && xkb->names)
{
register int bit;
for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1)
{
if (xkb->names->vmods[i] != None)
info->defined |= bit;
}
}
return;
}
Bool
HandleVModDef(VModDef * stmt, unsigned mergeMode, VModInfo * info)
{
register int i, bit, nextFree;
ExprResult mod;
XkbServerMapPtr srv;
XkbNamesPtr names;
Atom stmtName;
srv = info->xkb->server;
names = info->xkb->names;
stmtName =
XkbInternAtom(info->xkb->dpy, XkbAtomGetString(NULL, stmt->name),
False);
for (i = 0, bit = 1, nextFree = -1; i < XkbNumVirtualMods; i++, bit <<= 1)
{
if (info->defined & bit)
{
if (names->vmods[i] == stmtName)
{
info->available |= bit;
if (stmt->value == NULL)
return True;
else
{
char *str1;
const char *str2 = "";
if (!ExprResolveModMask(stmt->value, &mod, NULL, NULL))
{
str1 = XkbAtomText(NULL, stmt->name, XkbMessage);
ACTION1("Declaration of %s ignored\n", str1);
return False;
}
if (mod.uval == srv->vmods[i])
return True;
str1 = XkbAtomText(NULL, stmt->name, XkbMessage);
WARN1("Virtual modifier %s multiply defined\n", str1);
str1 = XkbModMaskText(srv->vmods[i], XkbCFile);
if (mergeMode == MergeOverride)
{
str2 = str1;
str1 = XkbModMaskText(mod.uval, XkbCFile);
}
ACTION2("Using %s, ignoring %s\n", str1, str2);
if (mergeMode == MergeOverride)
srv->vmods[i] = mod.uval;
return True;
}
}
}
else if (nextFree < 0)
nextFree = i;
}
if (nextFree < 0)
{
ERROR1("Too many virtual modifiers defined (maximum %d)\n",
XkbNumVirtualMods);
ACTION("Exiting\n");
return False;
}
info->defined |= (1 << nextFree);
info->newlyDefined |= (1 << nextFree);
info->available |= (1 << nextFree);
names->vmods[nextFree] = stmtName;
if (stmt->value == NULL)
return True;
if (ExprResolveModMask(stmt->value, &mod, NULL, NULL))
{
srv->vmods[nextFree] = mod.uval;
return True;
}
ACTION1("Declaration of %s ignored\n",
XkbAtomText(NULL, stmt->name, XkbMessage));
return False;
}
int
LookupVModIndex(XPointer priv,
Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
{
register int i;
register char *fieldStr;
register char *modStr;
XkbDescPtr xkb;
xkb = (XkbDescPtr) priv;
if ((xkb == NULL) || (xkb->names == NULL) || (elem != None)
|| (type != TypeInt))
{
return False;
}
fieldStr = XkbAtomGetString(xkb->dpy, field);
if (fieldStr == NULL)
return False;
for (i = 0; i < XkbNumVirtualMods; i++)
{
modStr = XkbAtomGetString(xkb->dpy, xkb->names->vmods[i]);
if ((modStr != NULL) && (uStrCaseCmp(fieldStr, modStr) == 0))
{
val_rtrn->uval = i;
return True;
}
}
return False;
}
int
LookupVModMask(XPointer priv,
Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
{
if (LookupVModIndex(priv, elem, field, type, val_rtrn))
{
register unsigned ndx = val_rtrn->uval;
val_rtrn->uval = (1 << (XkbNumModifiers + ndx));
return True;
}
return False;
}
int
FindKeypadVMod(XkbDescPtr xkb)
{
Atom name;
ExprResult rtrn;
name = XkbInternAtom(xkb->dpy, "NumLock", False);
if ((xkb) && LookupVModIndex((XPointer) xkb, None, name, TypeInt, &rtrn))
{
return rtrn.ival;
}
return -1;
}
Bool
ResolveVirtualModifier(ExprDef * def, ExprResult * val_rtrn, VModInfo * info)
{
XkbNamesPtr names;
names = info->xkb->names;
if (def->op == ExprIdent)
{
register int i, bit;
for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1)
{
char *str1, *str2;
str1 = XkbAtomGetString(info->xkb->dpy, names->vmods[i]);
str2 = XkbAtomGetString(NULL, def->value.str);
if ((info->available & bit) && (uStrCaseCmp(str1, str2) == Equal))
{
val_rtrn->uval = i;
return True;
}
}
}
if (ExprResolveInteger(def, val_rtrn, NULL, NULL))
{
if (val_rtrn->uval < XkbNumVirtualMods)
return True;
ERROR2("Illegal virtual modifier %d (must be 0..%d inclusive)\n",
val_rtrn->uval, XkbNumVirtualMods - 1);
}
return False;
}