1278 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1278 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
 | 
						|
 | 
						|
 Permission to use, copy, modify, and distribute this
 | 
						|
 software and its documentation for any purpose and without
 | 
						|
 fee is hereby granted, provided that the above copyright
 | 
						|
 notice appear in all copies and that both that copyright
 | 
						|
 notice and this permission notice appear in supporting
 | 
						|
 documentation, and that the name of Silicon Graphics not be
 | 
						|
 used in advertising or publicity pertaining to distribution
 | 
						|
 of the software without specific prior written permission.
 | 
						|
 Silicon Graphics makes no representation about the suitability
 | 
						|
 of this software for any purpose. It is provided "as is"
 | 
						|
 without any express or implied warranty.
 | 
						|
 | 
						|
 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 | 
						|
 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 | 
						|
 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | 
						|
 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 | 
						|
 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 | 
						|
 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 | 
						|
 THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
 ********************************************************/
 | 
						|
 | 
						|
#include <dix-config.h>
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <X11/Xos.h>
 | 
						|
#include <X11/Xfuncs.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include <X11/keysym.h>
 | 
						|
#include <X11/extensions/XKMformat.h>
 | 
						|
 | 
						|
#include "xkb/xkbfile_priv.h"
 | 
						|
#include "xkb/xkbfmisc_priv.h"
 | 
						|
 | 
						|
#include "misc.h"
 | 
						|
#include "inputstr.h"
 | 
						|
#include "xkbstr.h"
 | 
						|
#include "xkbsrv.h"
 | 
						|
#include "xkbgeom.h"
 | 
						|
 | 
						|
static Atom
 | 
						|
XkbInternAtom(char *str, Bool only_if_exists)
 | 
						|
{
 | 
						|
    if (str == NULL)
 | 
						|
        return None;
 | 
						|
    return MakeAtom(str, strlen(str), !only_if_exists);
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static void *
 | 
						|
XkmInsureSize(void *oldPtr, int oldCount, int *newCountRtrn, int elemSize)
 | 
						|
{
 | 
						|
    int newCount = *newCountRtrn;
 | 
						|
 | 
						|
    if (oldPtr == NULL) {
 | 
						|
        if (newCount == 0)
 | 
						|
            return NULL;
 | 
						|
        oldPtr = calloc(newCount, elemSize);
 | 
						|
    }
 | 
						|
    else if (oldCount < newCount) {
 | 
						|
        oldPtr = reallocarray(oldPtr, newCount, elemSize);
 | 
						|
        if (oldPtr != NULL) {
 | 
						|
            char *tmp = (char *) oldPtr;
 | 
						|
 | 
						|
            memset(&tmp[oldCount * elemSize], 0,
 | 
						|
                   (newCount - oldCount) * elemSize);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (newCount < oldCount) {
 | 
						|
        *newCountRtrn = oldCount;
 | 
						|
    }
 | 
						|
    return oldPtr;
 | 
						|
}
 | 
						|
 | 
						|
#define	XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t))))
 | 
						|
 | 
						|
static CARD8
 | 
						|
XkmGetCARD8(FILE * file, int *pNRead)
 | 
						|
{
 | 
						|
    int tmp;
 | 
						|
 | 
						|
    tmp = getc(file);
 | 
						|
    if (pNRead && (tmp != EOF))
 | 
						|
        (*pNRead) += 1;
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
static CARD16
 | 
						|
XkmGetCARD16(FILE * file, int *pNRead)
 | 
						|
{
 | 
						|
    CARD16 val;
 | 
						|
 | 
						|
    if ((fread(&val, 2, 1, file) == 1) && (pNRead))
 | 
						|
        (*pNRead) += 2;
 | 
						|
    return val;
 | 
						|
}
 | 
						|
 | 
						|
static CARD32
 | 
						|
XkmGetCARD32(FILE * file, int *pNRead)
 | 
						|
{
 | 
						|
    CARD32 val;
 | 
						|
 | 
						|
    if ((fread(&val, 4, 1, file) == 1) && (pNRead))
 | 
						|
        (*pNRead) += 4;
 | 
						|
    return val;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XkmSkipPadding(FILE * file, unsigned pad)
 | 
						|
{
 | 
						|
    register int i, nRead = 0;
 | 
						|
 | 
						|
    for (i = 0; i < pad; i++) {
 | 
						|
        if (getc(file) != EOF)
 | 
						|
            nRead++;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XkmGetCountedString(FILE * file, char *str, int max_len)
 | 
						|
{
 | 
						|
    int count, nRead = 0;
 | 
						|
 | 
						|
    count = XkmGetCARD16(file, &nRead);
 | 
						|
    if (count > 0) {
 | 
						|
        int tmp;
 | 
						|
 | 
						|
        if (count > max_len) {
 | 
						|
            tmp = fread(str, 1, max_len, file);
 | 
						|
            while (tmp < count) {
 | 
						|
                if ((getc(file)) != EOF)
 | 
						|
                    tmp++;
 | 
						|
                else
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            tmp = fread(str, 1, count, file);
 | 
						|
        }
 | 
						|
        nRead += tmp;
 | 
						|
    }
 | 
						|
    if (count >= max_len)
 | 
						|
        str[max_len - 1] = '\0';
 | 
						|
    else
 | 
						|
        str[count] = '\0';
 | 
						|
    count = XkbPaddedSize(nRead) - nRead;
 | 
						|
    if (count > 0)
 | 
						|
        nRead += XkmSkipPadding(file, count);
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmVirtualMods(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
 | 
						|
{
 | 
						|
    register unsigned int i, bit;
 | 
						|
    unsigned int bound, named, tmp;
 | 
						|
    int nRead = 0;
 | 
						|
 | 
						|
    if (XkbAllocServerMap(xkb, XkbVirtualModsMask, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmVirtualMods", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    bound = XkmGetCARD16(file, &nRead);
 | 
						|
    named = XkmGetCARD16(file, &nRead);
 | 
						|
    for (i = tmp = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
 | 
						|
        if (bound & bit) {
 | 
						|
            xkb->server->vmods[i] = XkmGetCARD8(file, &nRead);
 | 
						|
            if (changes)
 | 
						|
                changes->map.vmods |= bit;
 | 
						|
            tmp++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ((i = XkbPaddedSize(tmp) - tmp) > 0)
 | 
						|
        nRead += XkmSkipPadding(file, i);
 | 
						|
    if (XkbAllocNames(xkb, XkbVirtualModNamesMask, 0, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmVirtualMods", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
 | 
						|
        char name[100];
 | 
						|
 | 
						|
        if (named & bit) {
 | 
						|
            if (nRead += XkmGetCountedString(file, name, 100)) {
 | 
						|
                xkb->names->vmods[i] = XkbInternAtom(name, FALSE);
 | 
						|
                if (changes)
 | 
						|
                    changes->names.changed_vmods |= bit;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmKeycodes(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
 | 
						|
{
 | 
						|
    register int i;
 | 
						|
    unsigned minKC, maxKC, nAl;
 | 
						|
    int nRead = 0;
 | 
						|
    char name[100];
 | 
						|
    XkbKeyNamePtr pN;
 | 
						|
 | 
						|
    name[0] = '\0';
 | 
						|
    nRead += XkmGetCountedString(file, name, 100);
 | 
						|
    minKC = XkmGetCARD8(file, &nRead);
 | 
						|
    maxKC = XkmGetCARD8(file, &nRead);
 | 
						|
    if (xkb->min_key_code == 0) {
 | 
						|
        xkb->min_key_code = minKC;
 | 
						|
        xkb->max_key_code = maxKC;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        if (minKC < xkb->min_key_code)
 | 
						|
            xkb->min_key_code = minKC;
 | 
						|
        if (maxKC > xkb->max_key_code) {
 | 
						|
            _XkbLibError(_XkbErrBadValue, "ReadXkmKeycodes", maxKC);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    nAl = XkmGetCARD8(file, &nRead);
 | 
						|
    nRead += XkmSkipPadding(file, 1);
 | 
						|
 | 
						|
#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask)
 | 
						|
    if (XkbAllocNames(xkb, WANTED, 0, nAl) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeycodes", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (name[0] != '\0') {
 | 
						|
        xkb->names->keycodes = XkbInternAtom(name, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    for (pN = &xkb->names->keys[minKC], i = minKC; i <= (int) maxKC; i++, pN++) {
 | 
						|
        if (fread(pN, 1, XkbKeyNameLength, file) != XkbKeyNameLength) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += XkbKeyNameLength;
 | 
						|
    }
 | 
						|
    if (nAl > 0) {
 | 
						|
        XkbKeyAliasPtr pAl;
 | 
						|
 | 
						|
        for (pAl = xkb->names->key_aliases, i = 0; i < nAl; i++, pAl++) {
 | 
						|
            int tmp;
 | 
						|
 | 
						|
            tmp = fread(pAl, 1, 2 * XkbKeyNameLength, file);
 | 
						|
            if (tmp != 2 * XkbKeyNameLength) {
 | 
						|
                _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            nRead += 2 * XkbKeyNameLength;
 | 
						|
        }
 | 
						|
        if (changes)
 | 
						|
            changes->names.changed |= XkbKeyAliasesMask;
 | 
						|
    }
 | 
						|
    if (changes)
 | 
						|
        changes->names.changed |= XkbKeyNamesMask;
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmKeyTypes(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
 | 
						|
{
 | 
						|
    register unsigned i, n;
 | 
						|
    unsigned num_types;
 | 
						|
    int nRead = 0;
 | 
						|
    int tmp;
 | 
						|
    XkbKeyTypePtr type;
 | 
						|
    xkmKeyTypeDesc wire;
 | 
						|
    XkbKTMapEntryPtr entry;
 | 
						|
    xkmKTMapEntryDesc wire_entry;
 | 
						|
    char buf[100];
 | 
						|
 | 
						|
    if ((tmp = XkmGetCountedString(file, buf, 100)) < 1) {
 | 
						|
        _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    nRead += tmp;
 | 
						|
    if (buf[0] != '\0') {
 | 
						|
        if (XkbAllocNames(xkb, XkbTypesNameMask, 0, 0) != Success) {
 | 
						|
            _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeyTypes", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        xkb->names->types = XkbInternAtom(buf, FALSE);
 | 
						|
    }
 | 
						|
    num_types = XkmGetCARD16(file, &nRead);
 | 
						|
    nRead += XkmSkipPadding(file, 2);
 | 
						|
    if (num_types < 1)
 | 
						|
        return nRead;
 | 
						|
    if (XkbAllocClientMap(xkb, XkbKeyTypesMask, num_types) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeyTypes", 0);
 | 
						|
        return nRead;
 | 
						|
    }
 | 
						|
    xkb->map->num_types = num_types;
 | 
						|
    if (num_types < XkbNumRequiredTypes) {
 | 
						|
        _XkbLibError(_XkbErrMissingReqTypes, "ReadXkmKeyTypes", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    type = xkb->map->types;
 | 
						|
    for (i = 0; i < num_types; i++, type++) {
 | 
						|
        if ((int) fread(&wire, SIZEOF(xkmKeyTypeDesc), 1, file) < 1) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += SIZEOF(xkmKeyTypeDesc);
 | 
						|
        if (((i == XkbOneLevelIndex) && (wire.numLevels != 1)) ||
 | 
						|
            (((i == XkbTwoLevelIndex) || (i == XkbAlphabeticIndex) ||
 | 
						|
              ((i) == XkbKeypadIndex)) && (wire.numLevels != 2))) {
 | 
						|
            _XkbLibError(_XkbErrBadTypeWidth, "ReadXkmKeyTypes", i);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        tmp = wire.nMapEntries;
 | 
						|
        XkmInsureTypedSize(type->map, type->map_count, &tmp, XkbKTMapEntryRec);
 | 
						|
        if ((wire.nMapEntries > 0) && (type->map == NULL)) {
 | 
						|
            _XkbLibError(_XkbErrBadValue, "ReadXkmKeyTypes", wire.nMapEntries);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        for (n = 0, entry = type->map; n < wire.nMapEntries; n++, entry++) {
 | 
						|
            if (fread(&wire_entry, SIZEOF(xkmKTMapEntryDesc), 1, file) <
 | 
						|
                (int) 1) {
 | 
						|
                _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            nRead += SIZEOF(xkmKTMapEntryDesc);
 | 
						|
            entry->active = (wire_entry.virtualMods == 0);
 | 
						|
            entry->level = wire_entry.level;
 | 
						|
            entry->mods.mask = wire_entry.realMods;
 | 
						|
            entry->mods.real_mods = wire_entry.realMods;
 | 
						|
            entry->mods.vmods = wire_entry.virtualMods;
 | 
						|
        }
 | 
						|
        nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
        if (((i == XkbOneLevelIndex) && (strcmp(buf, "ONE_LEVEL") != 0)) ||
 | 
						|
            ((i == XkbTwoLevelIndex) && (strcmp(buf, "TWO_LEVEL") != 0)) ||
 | 
						|
            ((i == XkbAlphabeticIndex) && (strcmp(buf, "ALPHABETIC") != 0)) ||
 | 
						|
            ((i == XkbKeypadIndex) && (strcmp(buf, "KEYPAD") != 0))) {
 | 
						|
            _XkbLibError(_XkbErrBadTypeName, "ReadXkmKeyTypes", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        if (buf[0] != '\0') {
 | 
						|
            type->name = XkbInternAtom(buf, FALSE);
 | 
						|
        }
 | 
						|
        else
 | 
						|
            type->name = None;
 | 
						|
 | 
						|
        if (wire.preserve) {
 | 
						|
            xkmModsDesc p_entry;
 | 
						|
            XkbModsPtr pre;
 | 
						|
 | 
						|
            XkmInsureTypedSize(type->preserve, type->map_count, &tmp,
 | 
						|
                               XkbModsRec);
 | 
						|
            if (type->preserve == NULL) {
 | 
						|
                _XkbLibError(_XkbErrBadMatch, "ReadXkmKeycodes", 0);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            for (n = 0, pre = type->preserve; n < wire.nMapEntries; n++, pre++) {
 | 
						|
                if (fread(&p_entry, SIZEOF(xkmModsDesc), 1, file) < 1) {
 | 
						|
                    _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
 | 
						|
                    return -1;
 | 
						|
                }
 | 
						|
                nRead += SIZEOF(xkmModsDesc);
 | 
						|
                pre->mask = p_entry.realMods;
 | 
						|
                pre->real_mods = p_entry.realMods;
 | 
						|
                pre->vmods = p_entry.virtualMods;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (wire.nLevelNames > 0) {
 | 
						|
            int width = wire.numLevels;
 | 
						|
 | 
						|
            if (wire.nLevelNames > (unsigned) width) {
 | 
						|
                _XkbLibError(_XkbErrBadMatch, "ReadXkmKeycodes", 0);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            XkmInsureTypedSize(type->level_names, type->num_levels, &width,
 | 
						|
                               Atom);
 | 
						|
            if (type->level_names != NULL) {
 | 
						|
                for (n = 0; n < wire.nLevelNames; n++) {
 | 
						|
                    if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
 | 
						|
                        return -1;
 | 
						|
                    nRead += tmp;
 | 
						|
                    if (strlen(buf) == 0)
 | 
						|
                        type->level_names[n] = None;
 | 
						|
                    else
 | 
						|
                        type->level_names[n] = XkbInternAtom(buf, 0);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        type->mods.mask = wire.realMods;
 | 
						|
        type->mods.real_mods = wire.realMods;
 | 
						|
        type->mods.vmods = wire.virtualMods;
 | 
						|
        type->num_levels = wire.numLevels;
 | 
						|
        type->map_count = wire.nMapEntries;
 | 
						|
    }
 | 
						|
    if (changes) {
 | 
						|
        changes->map.changed |= XkbKeyTypesMask;
 | 
						|
        changes->map.first_type = 0;
 | 
						|
        changes->map.num_types = xkb->map->num_types;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmCompatMap(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
 | 
						|
{
 | 
						|
    register int i;
 | 
						|
    unsigned num_si, groups;
 | 
						|
    char name[100];
 | 
						|
    XkbSymInterpretPtr interp;
 | 
						|
    xkmSymInterpretDesc wire;
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
    XkbCompatMapPtr compat;
 | 
						|
    XkbAction *act;
 | 
						|
 | 
						|
    if ((tmp = XkmGetCountedString(file, name, 100)) < 1) {
 | 
						|
        _XkbLibError(_XkbErrBadLength, "ReadXkmCompatMap", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    nRead += tmp;
 | 
						|
    if (name[0] != '\0') {
 | 
						|
        if (XkbAllocNames(xkb, XkbCompatNameMask, 0, 0) != Success) {
 | 
						|
            _XkbLibError(_XkbErrBadAlloc, "ReadXkmCompatMap", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        xkb->names->compat = XkbInternAtom(name, FALSE);
 | 
						|
    }
 | 
						|
    num_si = XkmGetCARD16(file, &nRead);
 | 
						|
    groups = XkmGetCARD8(file, &nRead);
 | 
						|
    nRead += XkmSkipPadding(file, 1);
 | 
						|
    if (XkbAllocCompatMap(xkb, XkbAllCompatMask, num_si) != Success)
 | 
						|
        return -1;
 | 
						|
    compat = xkb->compat;
 | 
						|
    compat->num_si = 0;
 | 
						|
    interp = compat->sym_interpret;
 | 
						|
    for (i = 0; i < num_si; i++) {
 | 
						|
        tmp = fread(&wire, SIZEOF(xkmSymInterpretDesc), 1, file);
 | 
						|
        nRead += tmp * SIZEOF(xkmSymInterpretDesc);
 | 
						|
        interp->sym = wire.sym;
 | 
						|
        interp->mods = wire.mods;
 | 
						|
        interp->match = wire.match;
 | 
						|
        interp->virtual_mod = wire.virtualMod;
 | 
						|
        interp->flags = wire.flags;
 | 
						|
        interp->act.type = wire.actionType;
 | 
						|
        act = (XkbAction *) &interp->act;
 | 
						|
 | 
						|
        switch (interp->act.type) {
 | 
						|
        case XkbSA_SetMods:
 | 
						|
        case XkbSA_LatchMods:
 | 
						|
        case XkbSA_LockMods:
 | 
						|
            act->mods.flags = wire.actionData[0];
 | 
						|
            act->mods.mask = wire.actionData[1];
 | 
						|
            act->mods.real_mods = wire.actionData[2];
 | 
						|
            act->mods.vmods1 = wire.actionData[3];
 | 
						|
            act->mods.vmods2 = wire.actionData[4];
 | 
						|
            break;
 | 
						|
        case XkbSA_SetGroup:
 | 
						|
        case XkbSA_LatchGroup:
 | 
						|
        case XkbSA_LockGroup:
 | 
						|
            act->group.flags = wire.actionData[0];
 | 
						|
            act->group.group_XXX = wire.actionData[1];
 | 
						|
            break;
 | 
						|
        case XkbSA_MovePtr:
 | 
						|
            act->ptr.flags = wire.actionData[0];
 | 
						|
            act->ptr.high_XXX = wire.actionData[1];
 | 
						|
            act->ptr.low_XXX = wire.actionData[2];
 | 
						|
            act->ptr.high_YYY = wire.actionData[3];
 | 
						|
            act->ptr.low_YYY = wire.actionData[4];
 | 
						|
            break;
 | 
						|
        case XkbSA_PtrBtn:
 | 
						|
        case XkbSA_LockPtrBtn:
 | 
						|
            act->btn.flags = wire.actionData[0];
 | 
						|
            act->btn.count = wire.actionData[1];
 | 
						|
            act->btn.button = wire.actionData[2];
 | 
						|
            break;
 | 
						|
        case XkbSA_DeviceBtn:
 | 
						|
        case XkbSA_LockDeviceBtn:
 | 
						|
            act->devbtn.flags = wire.actionData[0];
 | 
						|
            act->devbtn.count = wire.actionData[1];
 | 
						|
            act->devbtn.button = wire.actionData[2];
 | 
						|
            act->devbtn.device = wire.actionData[3];
 | 
						|
            break;
 | 
						|
        case XkbSA_SetPtrDflt:
 | 
						|
            act->dflt.flags = wire.actionData[0];
 | 
						|
            act->dflt.affect = wire.actionData[1];
 | 
						|
            act->dflt.valueXXX = wire.actionData[2];
 | 
						|
            break;
 | 
						|
        case XkbSA_ISOLock:
 | 
						|
            act->iso.flags = wire.actionData[0];
 | 
						|
            act->iso.mask = wire.actionData[1];
 | 
						|
            act->iso.real_mods = wire.actionData[2];
 | 
						|
            act->iso.group_XXX = wire.actionData[3];
 | 
						|
            act->iso.affect = wire.actionData[4];
 | 
						|
            act->iso.vmods1 = wire.actionData[5];
 | 
						|
            act->iso.vmods2 = wire.actionData[6];
 | 
						|
            break;
 | 
						|
        case XkbSA_SwitchScreen:
 | 
						|
            act->screen.flags = wire.actionData[0];
 | 
						|
            act->screen.screenXXX = wire.actionData[1];
 | 
						|
            break;
 | 
						|
        case XkbSA_SetControls:
 | 
						|
        case XkbSA_LockControls:
 | 
						|
            act->ctrls.flags = wire.actionData[0];
 | 
						|
            act->ctrls.ctrls3 = wire.actionData[1];
 | 
						|
            act->ctrls.ctrls2 = wire.actionData[2];
 | 
						|
            act->ctrls.ctrls1 = wire.actionData[3];
 | 
						|
            act->ctrls.ctrls0 = wire.actionData[4];
 | 
						|
            break;
 | 
						|
        case XkbSA_RedirectKey:
 | 
						|
            act->redirect.new_key = wire.actionData[0];
 | 
						|
            act->redirect.mods_mask = wire.actionData[1];
 | 
						|
            act->redirect.mods = wire.actionData[2];
 | 
						|
            act->redirect.vmods_mask0 = wire.actionData[3];
 | 
						|
            act->redirect.vmods_mask1 = wire.actionData[4];
 | 
						|
            act->redirect.vmods0 = wire.actionData[4];
 | 
						|
            act->redirect.vmods1 = wire.actionData[5];
 | 
						|
            break;
 | 
						|
        case XkbSA_DeviceValuator:
 | 
						|
            act->devval.device = wire.actionData[0];
 | 
						|
            act->devval.v1_what = wire.actionData[1];
 | 
						|
            act->devval.v1_ndx = wire.actionData[2];
 | 
						|
            act->devval.v1_value = wire.actionData[3];
 | 
						|
            act->devval.v2_what = wire.actionData[4];
 | 
						|
            act->devval.v2_ndx = wire.actionData[5];
 | 
						|
            act->devval.v2_value = wire.actionData[6];
 | 
						|
            break;
 | 
						|
 | 
						|
        case XkbSA_XFree86Private:
 | 
						|
            /*
 | 
						|
             * Bugfix for broken xkbcomp: if we encounter an XFree86Private
 | 
						|
             * action with Any+AnyOfOrNone(All), then we skip the interp as
 | 
						|
             * broken.  Versions of xkbcomp below 1.2.2 had a bug where they
 | 
						|
             * would interpret a symbol that couldn't be found in an interpret
 | 
						|
             * as Any.  So, an XF86LogWindowTree+AnyOfOrNone(All) interp that
 | 
						|
             * triggered the PrWins action would make every key without an
 | 
						|
             * action trigger PrWins if libX11 didn't yet know about the
 | 
						|
             * XF86LogWindowTree keysym.  None too useful.
 | 
						|
             *
 | 
						|
             * We only do this for XFree86 actions, as the current XKB
 | 
						|
             * dataset relies on Any+AnyOfOrNone(All) -> SetMods for Ctrl in
 | 
						|
             * particular.
 | 
						|
             *
 | 
						|
             * See xkbcomp commits 2a473b906943ffd807ad81960c47530ee7ae9a60 and
 | 
						|
             * 3caab5aa37decb7b5dc1642a0452efc3e1f5100e for more details.
 | 
						|
             */
 | 
						|
            if (interp->sym == NoSymbol && interp->match == XkbSI_AnyOfOrNone &&
 | 
						|
                (interp->mods & 0xff) == 0xff) {
 | 
						|
                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
 | 
						|
                       "action from compiled keymap\n");
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            /* copy the kind of action */
 | 
						|
            memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize);
 | 
						|
            break;
 | 
						|
 | 
						|
        case XkbSA_Terminate:
 | 
						|
            /* no args, kinda (note: untrue for xfree86). */
 | 
						|
            break;
 | 
						|
        case XkbSA_ActionMessage:
 | 
						|
            /* unsupported. */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        interp++;
 | 
						|
        compat->num_si++;
 | 
						|
    }
 | 
						|
    if ((num_si > 0) && (changes)) {
 | 
						|
        changes->compat.first_si = 0;
 | 
						|
        changes->compat.num_si = compat->num_si;
 | 
						|
    }
 | 
						|
    if (groups) {
 | 
						|
        register unsigned bit;
 | 
						|
 | 
						|
        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
 | 
						|
            xkmModsDesc md;
 | 
						|
 | 
						|
            if (groups & bit) {
 | 
						|
                tmp = fread(&md, SIZEOF(xkmModsDesc), 1, file);
 | 
						|
                nRead += tmp * SIZEOF(xkmModsDesc);
 | 
						|
                xkb->compat->groups[i].real_mods = md.realMods;
 | 
						|
                xkb->compat->groups[i].vmods = md.virtualMods;
 | 
						|
                if (md.virtualMods != 0) {
 | 
						|
                    unsigned mask;
 | 
						|
 | 
						|
                    if (XkbVirtualModsToReal(xkb, md.virtualMods, &mask))
 | 
						|
                        xkb->compat->groups[i].mask = md.realMods | mask;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                    xkb->compat->groups[i].mask = md.realMods;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (changes)
 | 
						|
            changes->compat.changed_groups |= groups;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmIndicators(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
 | 
						|
{
 | 
						|
    register unsigned nLEDs;
 | 
						|
    xkmIndicatorMapDesc wire;
 | 
						|
    char buf[100];
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
 | 
						|
    if ((xkb->indicators == NULL) && (XkbAllocIndicatorMaps(xkb) != Success)) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "indicator rec", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (XkbAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "indicator names", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    nLEDs = XkmGetCARD8(file, &nRead);
 | 
						|
    nRead += XkmSkipPadding(file, 3);
 | 
						|
    xkb->indicators->phys_indicators = XkmGetCARD32(file, &nRead);
 | 
						|
    while (nLEDs-- > 0) {
 | 
						|
        Atom name;
 | 
						|
        XkbIndicatorMapPtr map;
 | 
						|
 | 
						|
        if ((tmp = XkmGetCountedString(file, buf, 100)) < 1) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmIndicators", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += tmp;
 | 
						|
        if (buf[0] != '\0')
 | 
						|
            name = XkbInternAtom(buf, FALSE);
 | 
						|
        else
 | 
						|
            name = None;
 | 
						|
        if ((tmp = fread(&wire, SIZEOF(xkmIndicatorMapDesc), 1, file)) < 1) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmIndicators", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += tmp * SIZEOF(xkmIndicatorMapDesc);
 | 
						|
        if (xkb->names) {
 | 
						|
            xkb->names->indicators[wire.indicator - 1] = name;
 | 
						|
            if (changes)
 | 
						|
                changes->names.changed_indicators |=
 | 
						|
                    (1 << (wire.indicator - 1));
 | 
						|
        }
 | 
						|
        map = &xkb->indicators->maps[wire.indicator - 1];
 | 
						|
        map->flags = wire.flags;
 | 
						|
        map->which_groups = wire.which_groups;
 | 
						|
        map->groups = wire.groups;
 | 
						|
        map->which_mods = wire.which_mods;
 | 
						|
        map->mods.mask = wire.real_mods;
 | 
						|
        map->mods.real_mods = wire.real_mods;
 | 
						|
        map->mods.vmods = wire.vmods;
 | 
						|
        map->ctrls = wire.ctrls;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static XkbKeyTypePtr
 | 
						|
FindTypeForKey(XkbDescPtr xkb, Atom name, unsigned width, KeySym * syms)
 | 
						|
{
 | 
						|
    if ((!xkb) || (!xkb->map))
 | 
						|
        return NULL;
 | 
						|
    if (name != None) {
 | 
						|
        register unsigned i;
 | 
						|
 | 
						|
        for (i = 0; i < xkb->map->num_types; i++) {
 | 
						|
            if (xkb->map->types[i].name == name) {
 | 
						|
                if (xkb->map->types[i].num_levels != width)
 | 
						|
                    DebugF("Group width mismatch between key and type\n");
 | 
						|
                return &xkb->map->types[i];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ((width < 2) || ((syms != NULL) && (syms[1] == NoSymbol)))
 | 
						|
        return &xkb->map->types[XkbOneLevelIndex];
 | 
						|
    if (syms != NULL) {
 | 
						|
        if (XkbKSIsLower(syms[0]) && XkbKSIsUpper(syms[1]))
 | 
						|
            return &xkb->map->types[XkbAlphabeticIndex];
 | 
						|
        else if (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))
 | 
						|
            return &xkb->map->types[XkbKeypadIndex];
 | 
						|
    }
 | 
						|
    return &xkb->map->types[XkbTwoLevelIndex];
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmSymbols(FILE * file, XkbDescPtr xkb)
 | 
						|
{
 | 
						|
    register int i, g, s, totalVModMaps;
 | 
						|
    xkmKeySymMapDesc wireMap;
 | 
						|
    char buf[100];
 | 
						|
    unsigned minKC, maxKC, groupNames, tmp;
 | 
						|
    int nRead = 0;
 | 
						|
 | 
						|
    if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
 | 
						|
        return -1;
 | 
						|
    nRead += tmp;
 | 
						|
    minKC = XkmGetCARD8(file, &nRead);
 | 
						|
    maxKC = XkmGetCARD8(file, &nRead);
 | 
						|
    groupNames = XkmGetCARD8(file, &nRead);
 | 
						|
    totalVModMaps = XkmGetCARD8(file, &nRead);
 | 
						|
    if (XkbAllocNames(xkb,
 | 
						|
                      XkbSymbolsNameMask | XkbPhysSymbolsNameMask |
 | 
						|
                      XkbGroupNamesMask, 0, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "physical names", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if ((buf[0] != '\0') && (xkb->names)) {
 | 
						|
        Atom name;
 | 
						|
 | 
						|
        name = XkbInternAtom(buf, 0);
 | 
						|
        xkb->names->symbols = name;
 | 
						|
        xkb->names->phys_symbols = name;
 | 
						|
    }
 | 
						|
    for (i = 0, g = 1; i < XkbNumKbdGroups; i++, g <<= 1) {
 | 
						|
        if (groupNames & g) {
 | 
						|
            if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
 | 
						|
                return -1;
 | 
						|
            nRead += tmp;
 | 
						|
 | 
						|
            if (!xkb->names)
 | 
						|
                continue;
 | 
						|
 | 
						|
            if (buf[0] != '\0') {
 | 
						|
                Atom name;
 | 
						|
 | 
						|
                name = XkbInternAtom(buf, 0);
 | 
						|
                xkb->names->groups[i] = name;
 | 
						|
            }
 | 
						|
            else
 | 
						|
                xkb->names->groups[i] = None;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "server map", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "client map", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (XkbAllocControls(xkb, XkbAllControlsMask) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "controls", 0);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if ((xkb->map == NULL) || (xkb->server == NULL))
 | 
						|
        return -1;
 | 
						|
    if (xkb->min_key_code < 8)
 | 
						|
        xkb->min_key_code = minKC;
 | 
						|
    if (xkb->max_key_code < 8)
 | 
						|
        xkb->max_key_code = maxKC;
 | 
						|
    if ((minKC >= 8) && (minKC < xkb->min_key_code))
 | 
						|
        xkb->min_key_code = minKC;
 | 
						|
    if ((maxKC >= 8) && (maxKC > xkb->max_key_code)) {
 | 
						|
        _XkbLibError(_XkbErrBadValue, "keys in symbol map", maxKC);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    for (i = minKC; i <= (int) maxKC; i++) {
 | 
						|
        Atom typeName[XkbNumKbdGroups];
 | 
						|
        XkbKeyTypePtr type[XkbNumKbdGroups];
 | 
						|
 | 
						|
        if ((tmp = fread(&wireMap, SIZEOF(xkmKeySymMapDesc), 1, file)) < 1) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmSymbols", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += tmp * SIZEOF(xkmKeySymMapDesc);
 | 
						|
        memset((char *) typeName, 0, XkbNumKbdGroups * sizeof(Atom));
 | 
						|
        memset((char *) type, 0, XkbNumKbdGroups * sizeof(XkbKeyTypePtr));
 | 
						|
        if (wireMap.flags & XkmKeyHasTypes) {
 | 
						|
            for (g = 0; g < XkbNumKbdGroups; g++) {
 | 
						|
                if ((wireMap.flags & (1 << g)) &&
 | 
						|
                    ((tmp = XkmGetCountedString(file, buf, 100)) > 0)) {
 | 
						|
                    typeName[g] = XkbInternAtom(buf, 1);
 | 
						|
                    nRead += tmp;
 | 
						|
                }
 | 
						|
                type[g] = FindTypeForKey(xkb, typeName[g], wireMap.width, NULL);
 | 
						|
                if (type[g] == NULL) {
 | 
						|
                    _XkbLibError(_XkbErrMissingTypes, "ReadXkmSymbols", 0);
 | 
						|
                    return -1;
 | 
						|
                }
 | 
						|
                if (typeName[g] == type[g]->name)
 | 
						|
                    xkb->server->explicit[i] |= (1 << g);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (wireMap.flags & XkmRepeatingKey) {
 | 
						|
            xkb->ctrls->per_key_repeat[i / 8] |= (1 << (i % 8));
 | 
						|
            xkb->server->explicit[i] |= XkbExplicitAutoRepeatMask;
 | 
						|
        }
 | 
						|
        else if (wireMap.flags & XkmNonRepeatingKey) {
 | 
						|
            xkb->ctrls->per_key_repeat[i / 8] &= ~(1 << (i % 8));
 | 
						|
            xkb->server->explicit[i] |= XkbExplicitAutoRepeatMask;
 | 
						|
        }
 | 
						|
        xkb->map->modmap[i] = wireMap.modifier_map;
 | 
						|
        if (XkbNumGroups(wireMap.num_groups) > 0) {
 | 
						|
            KeySym *sym;
 | 
						|
            int nSyms;
 | 
						|
 | 
						|
            if (XkbNumGroups(wireMap.num_groups) > xkb->ctrls->num_groups)
 | 
						|
                xkb->ctrls->num_groups = wireMap.num_groups;
 | 
						|
            nSyms = XkbNumGroups(wireMap.num_groups) * wireMap.width;
 | 
						|
            sym = XkbResizeKeySyms(xkb, i, nSyms);
 | 
						|
            if (!sym)
 | 
						|
                return -1;
 | 
						|
            for (s = 0; s < nSyms; s++) {
 | 
						|
                *sym++ = XkmGetCARD32(file, &nRead);
 | 
						|
            }
 | 
						|
            if (wireMap.flags & XkmKeyHasActions) {
 | 
						|
                XkbAction *act;
 | 
						|
 | 
						|
                act = XkbResizeKeyActions(xkb, i, nSyms);
 | 
						|
                for (s = 0; s < nSyms; s++, act++) {
 | 
						|
                    tmp = fread(act, SIZEOF(xkmActionDesc), 1, file);
 | 
						|
                    nRead += tmp * SIZEOF(xkmActionDesc);
 | 
						|
                }
 | 
						|
                xkb->server->explicit[i] |= XkbExplicitInterpretMask;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        for (g = 0; g < XkbNumGroups(wireMap.num_groups); g++) {
 | 
						|
            if (((xkb->server->explicit[i] & (1 << g)) == 0) ||
 | 
						|
                (type[g] == NULL)) {
 | 
						|
                KeySym *tmpSyms;
 | 
						|
 | 
						|
                tmpSyms = XkbKeySymsPtr(xkb, i) + (wireMap.width * g);
 | 
						|
                type[g] = FindTypeForKey(xkb, None, wireMap.width, tmpSyms);
 | 
						|
            }
 | 
						|
            xkb->map->key_sym_map[i].kt_index[g] =
 | 
						|
                type[g] - (&xkb->map->types[0]);
 | 
						|
        }
 | 
						|
        xkb->map->key_sym_map[i].group_info = wireMap.num_groups;
 | 
						|
        xkb->map->key_sym_map[i].width = wireMap.width;
 | 
						|
        if (wireMap.flags & XkmKeyHasBehavior) {
 | 
						|
            xkmBehaviorDesc b;
 | 
						|
 | 
						|
            tmp = fread(&b, SIZEOF(xkmBehaviorDesc), 1, file);
 | 
						|
            nRead += tmp * SIZEOF(xkmBehaviorDesc);
 | 
						|
            xkb->server->behaviors[i].type = b.type;
 | 
						|
            xkb->server->behaviors[i].data = b.data;
 | 
						|
            xkb->server->explicit[i] |= XkbExplicitBehaviorMask;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (totalVModMaps > 0) {
 | 
						|
        xkmVModMapDesc v;
 | 
						|
 | 
						|
        for (i = 0; i < totalVModMaps; i++) {
 | 
						|
            tmp = fread(&v, SIZEOF(xkmVModMapDesc), 1, file);
 | 
						|
            nRead += tmp * SIZEOF(xkmVModMapDesc);
 | 
						|
            if (tmp > 0)
 | 
						|
                xkb->server->vmodmap[v.key] = v.vmods;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmGeomDoodad(FILE * file, XkbGeometryPtr geom, XkbSectionPtr section)
 | 
						|
{
 | 
						|
    XkbDoodadPtr doodad;
 | 
						|
    xkmDoodadDesc doodadWire;
 | 
						|
    char buf[100];
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
 | 
						|
    nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
    tmp = fread(&doodadWire, SIZEOF(xkmDoodadDesc), 1, file);
 | 
						|
    nRead += SIZEOF(xkmDoodadDesc) * tmp;
 | 
						|
    doodad = XkbAddGeomDoodad(geom, section, XkbInternAtom(buf, FALSE));
 | 
						|
    if (!doodad)
 | 
						|
        return nRead;
 | 
						|
    doodad->any.type = doodadWire.any.type;
 | 
						|
    doodad->any.priority = doodadWire.any.priority;
 | 
						|
    doodad->any.top = doodadWire.any.top;
 | 
						|
    doodad->any.left = doodadWire.any.left;
 | 
						|
    switch (doodadWire.any.type) {
 | 
						|
    case XkbOutlineDoodad:
 | 
						|
    case XkbSolidDoodad:
 | 
						|
        doodad->shape.angle = doodadWire.shape.angle;
 | 
						|
        doodad->shape.color_ndx = doodadWire.shape.color_ndx;
 | 
						|
        doodad->shape.shape_ndx = doodadWire.shape.shape_ndx;
 | 
						|
        break;
 | 
						|
    case XkbTextDoodad:
 | 
						|
        doodad->text.angle = doodadWire.text.angle;
 | 
						|
        doodad->text.width = doodadWire.text.width;
 | 
						|
        doodad->text.height = doodadWire.text.height;
 | 
						|
        doodad->text.color_ndx = doodadWire.text.color_ndx;
 | 
						|
        nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
        doodad->text.text = Xstrdup(buf);
 | 
						|
        nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
        doodad->text.font = Xstrdup(buf);
 | 
						|
        break;
 | 
						|
    case XkbIndicatorDoodad:
 | 
						|
        doodad->indicator.shape_ndx = doodadWire.indicator.shape_ndx;
 | 
						|
        doodad->indicator.on_color_ndx = doodadWire.indicator.on_color_ndx;
 | 
						|
        doodad->indicator.off_color_ndx = doodadWire.indicator.off_color_ndx;
 | 
						|
        break;
 | 
						|
    case XkbLogoDoodad:
 | 
						|
        doodad->logo.angle = doodadWire.logo.angle;
 | 
						|
        doodad->logo.color_ndx = doodadWire.logo.color_ndx;
 | 
						|
        doodad->logo.shape_ndx = doodadWire.logo.shape_ndx;
 | 
						|
        nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
        doodad->logo.logo_name = Xstrdup(buf);
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        /* report error? */
 | 
						|
        return nRead;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmGeomOverlay(FILE * file, XkbGeometryPtr geom, XkbSectionPtr section)
 | 
						|
{
 | 
						|
    char buf[100];
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
    XkbOverlayPtr ol;
 | 
						|
    XkbOverlayRowPtr row;
 | 
						|
    xkmOverlayDesc olWire;
 | 
						|
    xkmOverlayRowDesc rowWire;
 | 
						|
    register int r;
 | 
						|
 | 
						|
    nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
    tmp = fread(&olWire, SIZEOF(xkmOverlayDesc), 1, file);
 | 
						|
    nRead += tmp * SIZEOF(xkmOverlayDesc);
 | 
						|
    ol = XkbAddGeomOverlay(section, XkbInternAtom(buf, FALSE), olWire.num_rows);
 | 
						|
    if (!ol)
 | 
						|
        return nRead;
 | 
						|
    for (r = 0; r < olWire.num_rows; r++) {
 | 
						|
        int k;
 | 
						|
        xkmOverlayKeyDesc keyWire;
 | 
						|
 | 
						|
        tmp = fread(&rowWire, SIZEOF(xkmOverlayRowDesc), 1, file);
 | 
						|
        nRead += tmp * SIZEOF(xkmOverlayRowDesc);
 | 
						|
        row = XkbAddGeomOverlayRow(ol, rowWire.row_under, rowWire.num_keys);
 | 
						|
        if (!row) {
 | 
						|
            _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomOverlay", 0);
 | 
						|
            return nRead;
 | 
						|
        }
 | 
						|
        for (k = 0; k < rowWire.num_keys; k++) {
 | 
						|
            tmp = fread(&keyWire, SIZEOF(xkmOverlayKeyDesc), 1, file);
 | 
						|
            nRead += tmp * SIZEOF(xkmOverlayKeyDesc);
 | 
						|
            memcpy(row->keys[k].over.name, keyWire.over, XkbKeyNameLength);
 | 
						|
            memcpy(row->keys[k].under.name, keyWire.under, XkbKeyNameLength);
 | 
						|
        }
 | 
						|
        row->num_keys = rowWire.num_keys;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmGeomSection(FILE * file, XkbGeometryPtr geom)
 | 
						|
{
 | 
						|
    register int i;
 | 
						|
    XkbSectionPtr section;
 | 
						|
    xkmSectionDesc sectionWire;
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
    char buf[100];
 | 
						|
    Atom nameAtom;
 | 
						|
 | 
						|
    nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
    nameAtom = XkbInternAtom(buf, FALSE);
 | 
						|
    tmp = fread(§ionWire, SIZEOF(xkmSectionDesc), 1, file);
 | 
						|
    nRead += SIZEOF(xkmSectionDesc) * tmp;
 | 
						|
    section = XkbAddGeomSection(geom, nameAtom, sectionWire.num_rows,
 | 
						|
                                sectionWire.num_doodads,
 | 
						|
                                sectionWire.num_overlays);
 | 
						|
    if (!section) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomSection", 0);
 | 
						|
        return nRead;
 | 
						|
    }
 | 
						|
    section->top = sectionWire.top;
 | 
						|
    section->left = sectionWire.left;
 | 
						|
    section->width = sectionWire.width;
 | 
						|
    section->height = sectionWire.height;
 | 
						|
    section->angle = sectionWire.angle;
 | 
						|
    section->priority = sectionWire.priority;
 | 
						|
    if (sectionWire.num_rows > 0) {
 | 
						|
        register int k;
 | 
						|
        XkbRowPtr row;
 | 
						|
        xkmRowDesc rowWire;
 | 
						|
        XkbKeyPtr key;
 | 
						|
        xkmKeyDesc keyWire;
 | 
						|
 | 
						|
        for (i = 0; i < sectionWire.num_rows; i++) {
 | 
						|
            tmp = fread(&rowWire, SIZEOF(xkmRowDesc), 1, file);
 | 
						|
            nRead += SIZEOF(xkmRowDesc) * tmp;
 | 
						|
            row = XkbAddGeomRow(section, rowWire.num_keys);
 | 
						|
            if (!row) {
 | 
						|
                _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeycodes", 0);
 | 
						|
                return nRead;
 | 
						|
            }
 | 
						|
            row->top = rowWire.top;
 | 
						|
            row->left = rowWire.left;
 | 
						|
            row->vertical = rowWire.vertical;
 | 
						|
            for (k = 0; k < rowWire.num_keys; k++) {
 | 
						|
                tmp = fread(&keyWire, SIZEOF(xkmKeyDesc), 1, file);
 | 
						|
                nRead += SIZEOF(xkmKeyDesc) * tmp;
 | 
						|
                key = XkbAddGeomKey(row);
 | 
						|
                if (!key) {
 | 
						|
                    _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomSection", 0);
 | 
						|
                    return nRead;
 | 
						|
                }
 | 
						|
                memcpy(key->name.name, keyWire.name, XkbKeyNameLength);
 | 
						|
                key->gap = keyWire.gap;
 | 
						|
                key->shape_ndx = keyWire.shape_ndx;
 | 
						|
                key->color_ndx = keyWire.color_ndx;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (sectionWire.num_doodads > 0) {
 | 
						|
        for (i = 0; i < sectionWire.num_doodads; i++) {
 | 
						|
            tmp = ReadXkmGeomDoodad(file, geom, section);
 | 
						|
            nRead += tmp;
 | 
						|
            if (tmp < 1)
 | 
						|
                return nRead;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (sectionWire.num_overlays > 0) {
 | 
						|
        for (i = 0; i < sectionWire.num_overlays; i++) {
 | 
						|
            tmp = ReadXkmGeomOverlay(file, geom, section);
 | 
						|
            nRead += tmp;
 | 
						|
            if (tmp < 1)
 | 
						|
                return nRead;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ReadXkmGeometry(FILE * file, XkbDescPtr xkb)
 | 
						|
{
 | 
						|
    register int i;
 | 
						|
    char buf[100];
 | 
						|
    unsigned tmp;
 | 
						|
    int nRead = 0;
 | 
						|
    xkmGeometryDesc wireGeom;
 | 
						|
    XkbGeometryPtr geom;
 | 
						|
    XkbGeometrySizesRec sizes;
 | 
						|
 | 
						|
    nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
    tmp = fread(&wireGeom, SIZEOF(xkmGeometryDesc), 1, file);
 | 
						|
    nRead += tmp * SIZEOF(xkmGeometryDesc);
 | 
						|
    sizes.which = XkbGeomAllMask;
 | 
						|
    sizes.num_properties = wireGeom.num_properties;
 | 
						|
    sizes.num_colors = wireGeom.num_colors;
 | 
						|
    sizes.num_shapes = wireGeom.num_shapes;
 | 
						|
    sizes.num_sections = wireGeom.num_sections;
 | 
						|
    sizes.num_doodads = wireGeom.num_doodads;
 | 
						|
    sizes.num_key_aliases = wireGeom.num_key_aliases;
 | 
						|
    if (XkbAllocGeometry(xkb, &sizes) != Success) {
 | 
						|
        _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
 | 
						|
        return nRead;
 | 
						|
    }
 | 
						|
    geom = xkb->geom;
 | 
						|
    geom->name = XkbInternAtom(buf, FALSE);
 | 
						|
    geom->width_mm = wireGeom.width_mm;
 | 
						|
    geom->height_mm = wireGeom.height_mm;
 | 
						|
    nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
    geom->label_font = Xstrdup(buf);
 | 
						|
    if (wireGeom.num_properties > 0) {
 | 
						|
        char val[1024];
 | 
						|
 | 
						|
        for (i = 0; i < wireGeom.num_properties; i++) {
 | 
						|
            nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
            nRead += XkmGetCountedString(file, val, 1024);
 | 
						|
            if (XkbAddGeomProperty(geom, buf, val) == NULL) {
 | 
						|
                _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
 | 
						|
                return nRead;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (wireGeom.num_colors > 0) {
 | 
						|
        for (i = 0; i < wireGeom.num_colors; i++) {
 | 
						|
            nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
            if (XkbAddGeomColor(geom, buf, i) == NULL) {
 | 
						|
                _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
 | 
						|
                return nRead;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    geom->base_color = &geom->colors[wireGeom.base_color_ndx];
 | 
						|
    geom->label_color = &geom->colors[wireGeom.label_color_ndx];
 | 
						|
    if (wireGeom.num_shapes > 0) {
 | 
						|
        XkbShapePtr shape;
 | 
						|
        xkmShapeDesc shapeWire;
 | 
						|
        Atom nameAtom;
 | 
						|
 | 
						|
        for (i = 0; i < wireGeom.num_shapes; i++) {
 | 
						|
            register int n;
 | 
						|
            XkbOutlinePtr ol;
 | 
						|
            xkmOutlineDesc olWire;
 | 
						|
 | 
						|
            nRead += XkmGetCountedString(file, buf, 100);
 | 
						|
            nameAtom = XkbInternAtom(buf, FALSE);
 | 
						|
            tmp = fread(&shapeWire, SIZEOF(xkmShapeDesc), 1, file);
 | 
						|
            nRead += tmp * SIZEOF(xkmShapeDesc);
 | 
						|
            shape = XkbAddGeomShape(geom, nameAtom, shapeWire.num_outlines);
 | 
						|
            if (!shape) {
 | 
						|
                _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
 | 
						|
                return nRead;
 | 
						|
            }
 | 
						|
            for (n = 0; n < shapeWire.num_outlines; n++) {
 | 
						|
                register int p;
 | 
						|
                xkmPointDesc ptWire;
 | 
						|
 | 
						|
                tmp = fread(&olWire, SIZEOF(xkmOutlineDesc), 1, file);
 | 
						|
                nRead += tmp * SIZEOF(xkmOutlineDesc);
 | 
						|
                ol = XkbAddGeomOutline(shape, olWire.num_points);
 | 
						|
                if (!ol) {
 | 
						|
                    _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
 | 
						|
                    return nRead;
 | 
						|
                }
 | 
						|
                ol->num_points = olWire.num_points;
 | 
						|
                ol->corner_radius = olWire.corner_radius;
 | 
						|
                for (p = 0; p < olWire.num_points; p++) {
 | 
						|
                    tmp = fread(&ptWire, SIZEOF(xkmPointDesc), 1, file);
 | 
						|
                    nRead += tmp * SIZEOF(xkmPointDesc);
 | 
						|
                    ol->points[p].x = ptWire.x;
 | 
						|
                    ol->points[p].y = ptWire.y;
 | 
						|
                    if (ptWire.x < shape->bounds.x1)
 | 
						|
                        shape->bounds.x1 = ptWire.x;
 | 
						|
                    if (ptWire.x > shape->bounds.x2)
 | 
						|
                        shape->bounds.x2 = ptWire.x;
 | 
						|
                    if (ptWire.y < shape->bounds.y1)
 | 
						|
                        shape->bounds.y1 = ptWire.y;
 | 
						|
                    if (ptWire.y > shape->bounds.y2)
 | 
						|
                        shape->bounds.y2 = ptWire.y;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (shapeWire.primary_ndx != XkbNoShape)
 | 
						|
                shape->primary = &shape->outlines[shapeWire.primary_ndx];
 | 
						|
            if (shapeWire.approx_ndx != XkbNoShape)
 | 
						|
                shape->approx = &shape->outlines[shapeWire.approx_ndx];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (wireGeom.num_sections > 0) {
 | 
						|
        for (i = 0; i < wireGeom.num_sections; i++) {
 | 
						|
            tmp = ReadXkmGeomSection(file, geom);
 | 
						|
            nRead += tmp;
 | 
						|
            if (tmp == 0)
 | 
						|
                return nRead;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (wireGeom.num_doodads > 0) {
 | 
						|
        for (i = 0; i < wireGeom.num_doodads; i++) {
 | 
						|
            tmp = ReadXkmGeomDoodad(file, geom, NULL);
 | 
						|
            nRead += tmp;
 | 
						|
            if (tmp == 0)
 | 
						|
                return nRead;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ((wireGeom.num_key_aliases > 0) && (geom->key_aliases)) {
 | 
						|
        int sz = XkbKeyNameLength * 2;
 | 
						|
        int num = wireGeom.num_key_aliases;
 | 
						|
 | 
						|
        if (fread(geom->key_aliases, sz, num, file) != num) {
 | 
						|
            _XkbLibError(_XkbErrBadLength, "ReadXkmGeometry", 0);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        nRead += (num * sz);
 | 
						|
        geom->num_key_aliases = num;
 | 
						|
    }
 | 
						|
    return nRead;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
XkmReadTOC(FILE * file, xkmFileInfo * file_info, int max_toc,
 | 
						|
           xkmSectionInfo * toc)
 | 
						|
{
 | 
						|
    unsigned hdr, tmp;
 | 
						|
    int nRead = 0;
 | 
						|
    unsigned i, size_toc;
 | 
						|
 | 
						|
    hdr = (('x' << 24) | ('k' << 16) | ('m' << 8) | XkmFileVersion);
 | 
						|
    tmp = XkmGetCARD32(file, &nRead);
 | 
						|
    if (tmp != hdr) {
 | 
						|
        if ((tmp & (~0xff)) == (hdr & (~0xff))) {
 | 
						|
            _XkbLibError(_XkbErrBadFileVersion, "XkmReadTOC", tmp & 0xff);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            _XkbLibError(_XkbErrBadFileType, "XkmReadTOC", tmp);
 | 
						|
        }
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    if (fread(file_info, SIZEOF(xkmFileInfo), 1, file) != 1)
 | 
						|
        return 0;
 | 
						|
    size_toc = file_info->num_toc;
 | 
						|
    if (size_toc > max_toc) {
 | 
						|
        DebugF("Warning! Too many TOC entries; last %d ignored\n",
 | 
						|
               size_toc - max_toc);
 | 
						|
        size_toc = max_toc;
 | 
						|
    }
 | 
						|
    for (i = 0; i < size_toc; i++) {
 | 
						|
        if (fread(&toc[i], SIZEOF(xkmSectionInfo), 1, file) != 1)
 | 
						|
            return 0;
 | 
						|
    }
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
#define	MAX_TOC	16
 | 
						|
unsigned
 | 
						|
XkmReadFile(FILE * file, unsigned need, unsigned want, XkbDescPtr *xkb)
 | 
						|
{
 | 
						|
    register unsigned i;
 | 
						|
    xkmSectionInfo toc[MAX_TOC] = { 0 }, tmpTOC = { 0 };
 | 
						|
    xkmFileInfo fileInfo;
 | 
						|
    unsigned tmp, nRead = 0;
 | 
						|
    unsigned which = need | want;
 | 
						|
 | 
						|
    if (!XkmReadTOC(file, &fileInfo, MAX_TOC, toc))
 | 
						|
        return which;
 | 
						|
    if ((fileInfo.present & need) != need) {
 | 
						|
        _XkbLibError(_XkbErrIllegalContents, "XkmReadFile",
 | 
						|
                     need & (~fileInfo.present));
 | 
						|
        return which;
 | 
						|
    }
 | 
						|
    if (*xkb == NULL)
 | 
						|
        *xkb = XkbAllocKeyboard();
 | 
						|
    for (i = 0; i < fileInfo.num_toc; i++) {
 | 
						|
        fseek(file, toc[i].offset, SEEK_SET);
 | 
						|
        tmp = fread(&tmpTOC, SIZEOF(xkmSectionInfo), 1, file);
 | 
						|
        nRead = tmp * SIZEOF(xkmSectionInfo);
 | 
						|
        if ((tmpTOC.type != toc[i].type) || (tmpTOC.format != toc[i].format) ||
 | 
						|
            (tmpTOC.size != toc[i].size) || (tmpTOC.offset != toc[i].offset)) {
 | 
						|
            return which;
 | 
						|
        }
 | 
						|
        if ((which & (1 << tmpTOC.type)) == 0) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        switch (tmpTOC.type) {
 | 
						|
        case XkmVirtualModsIndex:
 | 
						|
            tmp = ReadXkmVirtualMods(file, *xkb, NULL);
 | 
						|
            break;
 | 
						|
        case XkmTypesIndex:
 | 
						|
            tmp = ReadXkmKeyTypes(file, *xkb, NULL);
 | 
						|
            break;
 | 
						|
        case XkmCompatMapIndex:
 | 
						|
            tmp = ReadXkmCompatMap(file, *xkb, NULL);
 | 
						|
            break;
 | 
						|
        case XkmKeyNamesIndex:
 | 
						|
            tmp = ReadXkmKeycodes(file, *xkb, NULL);
 | 
						|
            break;
 | 
						|
        case XkmIndicatorsIndex:
 | 
						|
            tmp = ReadXkmIndicators(file, *xkb, NULL);
 | 
						|
            break;
 | 
						|
        case XkmSymbolsIndex:
 | 
						|
            tmp = ReadXkmSymbols(file, *xkb);
 | 
						|
            break;
 | 
						|
        case XkmGeometryIndex:
 | 
						|
            tmp = ReadXkmGeometry(file, *xkb);
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            _XkbLibError(_XkbErrBadImplementation,
 | 
						|
                         XkbConfigText(tmpTOC.type, XkbMessage), 0);
 | 
						|
            tmp = 0;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (tmp > 0) {
 | 
						|
            nRead += tmp;
 | 
						|
            which &= ~(1 << toc[i].type);
 | 
						|
            (*xkb)->defined |= (1 << toc[i].type);
 | 
						|
        }
 | 
						|
        if (nRead != tmpTOC.size) {
 | 
						|
            _XkbLibError(_XkbErrBadLength,
 | 
						|
                         XkbConfigText(tmpTOC.type, XkbMessage),
 | 
						|
                         nRead - tmpTOC.size);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return which;
 | 
						|
}
 |