18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
38c9fbc29Smrg
48c9fbc29Smrg Permission to use, copy, modify, and distribute this
58c9fbc29Smrg software and its documentation for any purpose and without
68c9fbc29Smrg fee is hereby granted, provided that the above copyright
78c9fbc29Smrg notice appear in all copies and that both that copyright
88c9fbc29Smrg notice and this permission notice appear in supporting
94cd6a3aeSmrg documentation, and that the name of Silicon Graphics not be
104cd6a3aeSmrg used in advertising or publicity pertaining to distribution
118c9fbc29Smrg of the software without specific prior written permission.
124cd6a3aeSmrg Silicon Graphics makes no representation about the suitability
138c9fbc29Smrg of this software for any purpose. It is provided "as is"
148c9fbc29Smrg without any express or implied warranty.
154cd6a3aeSmrg
164cd6a3aeSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
174cd6a3aeSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
188c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
194cd6a3aeSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
204cd6a3aeSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
214cd6a3aeSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
228c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
238c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
248c9fbc29Smrg
258c9fbc29Smrg ********************************************************/
268c9fbc29Smrg
278c9fbc29Smrg#ifdef HAVE_DIX_CONFIG_H
288c9fbc29Smrg#include <dix-config.h>
298c9fbc29Smrg#elif defined(HAVE_CONFIG_H)
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg
338c9fbc29Smrg#include <stdio.h>
348c9fbc29Smrg#include <ctype.h>
358c9fbc29Smrg#include <stdlib.h>
368c9fbc29Smrg
378c9fbc29Smrg#include <X11/Xfuncs.h>
388c9fbc29Smrg
398c9fbc29Smrg#include <X11/Xfuncs.h>
408c9fbc29Smrg
418c9fbc29Smrg
428c9fbc29Smrg#include <X11/Xos.h>
438c9fbc29Smrg#include <X11/Xlib.h>
448c9fbc29Smrg#include <X11/keysym.h>
458c9fbc29Smrg#include <X11/XKBlib.h>
468c9fbc29Smrg#include "XKBfileInt.h"
478c9fbc29Smrg
488c9fbc29Smrg
498c9fbc29Smrg#include <X11/extensions/XKBconfig.h>
508c9fbc29Smrg
518c9fbc29Smrg/***====================================================================***/
528c9fbc29Smrg
538c9fbc29Smrg#define	XKBCF_MAX_STR_LEN	100
5470728a38Smrgstatic char _XkbCF_rtrn[XKBCF_MAX_STR_LEN + 1];
558c9fbc29Smrg
568c9fbc29Smrgstatic int
5770728a38SmrgScanIdent(FILE *file, int ch, XkbCFScanResultPtr val_rtrn)
588c9fbc29Smrg{
5970728a38Smrg    register int i;
6070728a38Smrg    char *str;
618c9fbc29Smrg
6270728a38Smrg    val_rtrn->str = str = _XkbCF_rtrn;
6370728a38Smrg    for (i = 0; (isalpha(ch) || isdigit(ch) || (ch == '_')); ch = getc(file)) {
6470728a38Smrg        if (i < XKBCF_MAX_STR_LEN)
6570728a38Smrg            str[i++] = ch;
668c9fbc29Smrg    }
6770728a38Smrg    if ((ch != EOF) && (ch != ' ') && (ch != '\t'))
6870728a38Smrg        ungetc(ch, file);
6970728a38Smrg    str[i] = '\0';
708c9fbc29Smrg    return XkbCF_Ident;
718c9fbc29Smrg}
728c9fbc29Smrg
738c9fbc29Smrgstatic int
7470728a38SmrgScanString(FILE *file, int quote, XkbCFScanResultPtr val_rtrn)
758c9fbc29Smrg{
7670728a38Smrg    int ch, nInBuf;
778c9fbc29Smrg
788c9fbc29Smrg    nInBuf = 0;
7970728a38Smrg    while (((ch = getc(file)) != EOF) && (ch != '\n') && (ch != quote)) {
8070728a38Smrg        if (ch == '\\') {
8170728a38Smrg            if ((ch = getc(file)) != EOF) {
8270728a38Smrg                if (ch == 'n')
8370728a38Smrg                    ch = '\n';
8470728a38Smrg                else if (ch == 't')
8570728a38Smrg                    ch = '\t';
8670728a38Smrg                else if (ch == 'v')
8770728a38Smrg                    ch = '\v';
8870728a38Smrg                else if (ch == 'b')
8970728a38Smrg                    ch = '\b';
9070728a38Smrg                else if (ch == 'r')
9170728a38Smrg                    ch = '\r';
9270728a38Smrg                else if (ch == 'f')
9370728a38Smrg                    ch = '\f';
9470728a38Smrg                else if (ch == 'e')
9570728a38Smrg                    ch = '\033';
9670728a38Smrg                else if (ch == '0') {
9770728a38Smrg                    int tmp, stop;
9870728a38Smrg
9970728a38Smrg                    ch = stop = 0;
10070728a38Smrg                    if (((tmp = getc(file)) != EOF) && (isdigit(tmp)) &&
10170728a38Smrg                        (tmp != '8') && (tmp != '9')) {
10270728a38Smrg                        ch = (ch * 8) + (tmp - '0');
10370728a38Smrg                    }
10470728a38Smrg                    else {
10570728a38Smrg                        stop = 1;
10670728a38Smrg                        ungetc(tmp, file);
10770728a38Smrg                    }
10870728a38Smrg                    if ((!stop) && ((tmp = getc(file)) != EOF) && (isdigit(tmp))
10970728a38Smrg                        && (tmp != '8') && (tmp != '9')) {
11070728a38Smrg                        ch = (ch * 8) + (tmp - '0');
11170728a38Smrg                    }
11270728a38Smrg                    else {
11370728a38Smrg                        stop = 1;
11470728a38Smrg                        ungetc(tmp, file);
11570728a38Smrg                    }
11670728a38Smrg                    if ((!stop) && ((tmp = getc(file)) != EOF) && (isdigit(tmp))
11770728a38Smrg                        && (tmp != '8') && (tmp != '9')) {
11870728a38Smrg                        ch = (ch * 8) + (tmp - '0');
11970728a38Smrg                    }
12070728a38Smrg                    else {
12170728a38Smrg                        stop = 1;
12270728a38Smrg                        ungetc(tmp, file);
12370728a38Smrg                    }
12470728a38Smrg                }
12570728a38Smrg            }
12670728a38Smrg            else
12770728a38Smrg                return XkbCF_EOF;
12870728a38Smrg        }
12970728a38Smrg
13070728a38Smrg        if (nInBuf < XKBCF_MAX_STR_LEN - 1)
13170728a38Smrg            _XkbCF_rtrn[nInBuf++] = ch;
1328c9fbc29Smrg    }
13370728a38Smrg    if (ch == quote) {
13470728a38Smrg        _XkbCF_rtrn[nInBuf++] = '\0';
13570728a38Smrg        val_rtrn->str = _XkbCF_rtrn;
13670728a38Smrg        return XkbCF_String;
1378c9fbc29Smrg    }
1388c9fbc29Smrg    return XkbCF_UnterminatedString;
1398c9fbc29Smrg}
1408c9fbc29Smrg
1418c9fbc29Smrgstatic int
14270728a38SmrgScanInteger(FILE *file, int ch, XkbCFScanResultPtr val_rtrn)
1438c9fbc29Smrg{
14470728a38Smrg    int i;
1458c9fbc29Smrg
1468c9fbc29Smrg    if (isdigit(ch))
14770728a38Smrg        ungetc(ch, file);
14870728a38Smrg    if (fscanf(file, "%i", &i) == 1) {
14970728a38Smrg        val_rtrn->ival = i;
15070728a38Smrg        return XkbCF_Integer;
1518c9fbc29Smrg    }
1528c9fbc29Smrg    return XkbCF_Unknown;
1538c9fbc29Smrg}
1548c9fbc29Smrg
1554cd6a3aeSmrgint
15670728a38SmrgXkbCFScan(FILE *file, XkbCFScanResultPtr val_rtrn, XkbConfigRtrnPtr rtrn)
1578c9fbc29Smrg{
15870728a38Smrg    int ch;
1598c9fbc29Smrg
1608c9fbc29Smrg    do {
16170728a38Smrg        ch = getc(file);
16270728a38Smrg    } while ((ch == '\t') || (ch == ' '));
1638c9fbc29Smrg    if (isalpha(ch))
16470728a38Smrg        return ScanIdent(file, ch, val_rtrn);
1658c9fbc29Smrg    else if (isdigit(ch))
16670728a38Smrg        return ScanInteger(file, ch, val_rtrn);
16770728a38Smrg    else if (ch == '"')
16870728a38Smrg        return ScanString(file, ch, val_rtrn);
16970728a38Smrg    else if (ch == '\n') {
17070728a38Smrg        rtrn->line++;
17170728a38Smrg        return XkbCF_EOL;
1728c9fbc29Smrg    }
17370728a38Smrg    else if (ch == ';')
17470728a38Smrg        return XkbCF_Semi;
17570728a38Smrg    else if (ch == '=')
17670728a38Smrg        return XkbCF_Equals;
17770728a38Smrg    else if (ch == '+') {
17870728a38Smrg        ch = getc(file);
17970728a38Smrg        if (ch == '=')
18070728a38Smrg            return XkbCF_PlusEquals;
18170728a38Smrg        if ((ch != EOF) && (ch != ' ') && (ch != '\t'))
18270728a38Smrg            ungetc(ch, file);
18370728a38Smrg        return XkbCF_Plus;
1848c9fbc29Smrg    }
18570728a38Smrg    else if (ch == '-') {
18670728a38Smrg        ch = getc(file);
18770728a38Smrg        if (ch == '=')
18870728a38Smrg            return XkbCF_MinusEquals;
18970728a38Smrg        if ((ch != EOF) && (ch != ' ') && (ch != '\t'))
19070728a38Smrg            ungetc(ch, file);
19170728a38Smrg        return XkbCF_Minus;
1928c9fbc29Smrg    }
19370728a38Smrg    else if (ch == EOF)
19470728a38Smrg        return XkbCF_EOF;
19570728a38Smrg    else if ((ch == '#') || ((ch == '/') && (getc(file) == '/'))) {
19670728a38Smrg        while ((ch != '\n') && (ch != EOF))
19770728a38Smrg            ch = getc(file);
19870728a38Smrg        rtrn->line++;
19970728a38Smrg        return XkbCF_EOL;
2008c9fbc29Smrg    }
2018c9fbc29Smrg    return XkbCF_Unknown;
2028c9fbc29Smrg}
2038c9fbc29Smrg
2048c9fbc29Smrg/***====================================================================***/
2058c9fbc29Smrg
2068c9fbc29Smrg#define	_XkbCF_Illegal			0
2078c9fbc29Smrg#define	_XkbCF_Keymap		 	1
2088c9fbc29Smrg#define	_XkbCF_Keycodes		 	2
2098c9fbc29Smrg#define	_XkbCF_Geometry		 	3
2108c9fbc29Smrg#define	_XkbCF_PhysSymbols	 	4
2118c9fbc29Smrg#define _XkbCF_Symbols		 	5
2128c9fbc29Smrg#define	_XkbCF_Types		 	6
2138c9fbc29Smrg#define	_XkbCF_CompatMap	 	7
2148c9fbc29Smrg
2158c9fbc29Smrg#define	_XkbCF_RulesFile		8
2168c9fbc29Smrg#define	_XkbCF_Model			9
2178c9fbc29Smrg#define	_XkbCF_Layout			10
2188c9fbc29Smrg#define	_XkbCF_Variant			11
2198c9fbc29Smrg#define	_XkbCF_Options			12
2204cd6a3aeSmrg
2218c9fbc29Smrg#define	_XkbCF_InitialMods	 	13
2228c9fbc29Smrg#define	_XkbCF_InitialCtrls	 	14
2238c9fbc29Smrg
2248c9fbc29Smrg#define	_XkbCF_ClickVolume	 	15
2258c9fbc29Smrg#define	_XkbCF_BellVolume	 	16
2268c9fbc29Smrg#define	_XkbCF_BellPitch	 	17
2278c9fbc29Smrg#define	_XkbCF_BellDuration	 	18
2288c9fbc29Smrg#define	_XkbCF_RepeatDelay	 	19
2298c9fbc29Smrg#define	_XkbCF_RepeatInterval	 	20
2308c9fbc29Smrg#define	_XkbCF_SlowKeysDelay	 	21
2318c9fbc29Smrg#define	_XkbCF_DebounceDelay		22
2328c9fbc29Smrg#define	_XkbCF_MouseKeysDelay		23
2338c9fbc29Smrg#define	_XkbCF_MouseKeysInterval	24
2348c9fbc29Smrg#define	_XkbCF_MouseKeysTimeToMax	25
2358c9fbc29Smrg#define	_XkbCF_MouseKeysMaxSpeed	26
2368c9fbc29Smrg#define	_XkbCF_MouseKeysCurve		27
2378c9fbc29Smrg#define	_XkbCF_AccessXTimeout		28
2388c9fbc29Smrg#define	_XkbCF_AccessXTimeoutCtrlsOn	29
2398c9fbc29Smrg#define	_XkbCF_AccessXTimeoutCtrlsOff	30
2408c9fbc29Smrg#define	_XkbCF_AccessXTimeoutOptsOn	31
2418c9fbc29Smrg#define	_XkbCF_AccessXTimeoutOptsOff	32
2428c9fbc29Smrg
2438c9fbc29Smrg#define	_XkbCF_IgnoreLockMods		33
2448c9fbc29Smrg#define	_XkbCF_IgnoreGroupLock		34
2458c9fbc29Smrg#define	_XkbCF_InternalMods		35
2468c9fbc29Smrg
2478c9fbc29Smrg#define	_XkbCF_GroupsWrap		36
2488c9fbc29Smrg#define	_XkbCF_InitialFeedback		37
2498c9fbc29Smrg
2508c9fbc29Smrgstatic Bool
25170728a38SmrgAddCtrlByName(XkbConfigRtrnPtr rtrn, char *name, unsigned long *ctrls_rtrn)
2528c9fbc29Smrg{
25370728a38Smrg    if ((_XkbStrCaseCmp(name, "repeat") == 0) ||
25470728a38Smrg        (_XkbStrCaseCmp(name, "repeatkeys") == 0))
25570728a38Smrg        *ctrls_rtrn = XkbRepeatKeysMask;
25670728a38Smrg    else if (_XkbStrCaseCmp(name, "slowkeys") == 0)
25770728a38Smrg        *ctrls_rtrn = XkbSlowKeysMask;
25870728a38Smrg    else if (_XkbStrCaseCmp(name, "bouncekeys") == 0)
25970728a38Smrg        *ctrls_rtrn = XkbBounceKeysMask;
26070728a38Smrg    else if (_XkbStrCaseCmp(name, "stickykeys") == 0)
26170728a38Smrg        *ctrls_rtrn = XkbStickyKeysMask;
26270728a38Smrg    else if (_XkbStrCaseCmp(name, "mousekeys") == 0)
26370728a38Smrg        *ctrls_rtrn = XkbMouseKeysMask;
26470728a38Smrg    else if (_XkbStrCaseCmp(name, "mousekeysaccel") == 0)
26570728a38Smrg        *ctrls_rtrn = XkbMouseKeysAccelMask;
26670728a38Smrg    else if (_XkbStrCaseCmp(name, "accessxkeys") == 0)
26770728a38Smrg        *ctrls_rtrn = XkbAccessXKeysMask;
26870728a38Smrg    else if (_XkbStrCaseCmp(name, "accessxtimeout") == 0)
26970728a38Smrg        *ctrls_rtrn = XkbAccessXTimeoutMask;
27070728a38Smrg    else if (_XkbStrCaseCmp(name, "accessxfeedback") == 0)
27170728a38Smrg        *ctrls_rtrn = XkbAccessXFeedbackMask;
27270728a38Smrg    else if (_XkbStrCaseCmp(name, "audiblebell") == 0)
27370728a38Smrg        *ctrls_rtrn = XkbAudibleBellMask;
27470728a38Smrg    else if (_XkbStrCaseCmp(name, "overlay1") == 0)
27570728a38Smrg        *ctrls_rtrn = XkbOverlay1Mask;
27670728a38Smrg    else if (_XkbStrCaseCmp(name, "overlay2") == 0)
27770728a38Smrg        *ctrls_rtrn = XkbOverlay2Mask;
27870728a38Smrg    else if (_XkbStrCaseCmp(name, "ignoregrouplock") == 0)
27970728a38Smrg        *ctrls_rtrn = XkbIgnoreGroupLockMask;
2808c9fbc29Smrg    else {
28170728a38Smrg        rtrn->error = XkbCF_ExpectedControl;
28270728a38Smrg        return False;
2838c9fbc29Smrg    }
2848c9fbc29Smrg    return True;
2858c9fbc29Smrg}
2868c9fbc29Smrg
2878c9fbc29Smrgstatic Bool
28870728a38SmrgAddAXTimeoutOptByName(XkbConfigRtrnPtr rtrn,
28970728a38Smrg                      char *name,
29070728a38Smrg                      unsigned short *opts_rtrn)
2918c9fbc29Smrg{
29270728a38Smrg    if (_XkbStrCaseCmp(name, "slowkeyspress") == 0)
29370728a38Smrg        *opts_rtrn = XkbAX_SKPressFBMask;
29470728a38Smrg    else if (_XkbStrCaseCmp(name, "slowkeysaccept") == 0)
29570728a38Smrg        *opts_rtrn = XkbAX_SKAcceptFBMask;
29670728a38Smrg    else if (_XkbStrCaseCmp(name, "feature") == 0)
29770728a38Smrg        *opts_rtrn = XkbAX_FeatureFBMask;
29870728a38Smrg    else if (_XkbStrCaseCmp(name, "slowwarn") == 0)
29970728a38Smrg        *opts_rtrn = XkbAX_SlowWarnFBMask;
30070728a38Smrg    else if (_XkbStrCaseCmp(name, "indicator") == 0)
30170728a38Smrg        *opts_rtrn = XkbAX_IndicatorFBMask;
30270728a38Smrg    else if (_XkbStrCaseCmp(name, "stickykeys") == 0)
30370728a38Smrg        *opts_rtrn = XkbAX_StickyKeysFBMask;
30470728a38Smrg    else if (_XkbStrCaseCmp(name, "twokeys") == 0)
30570728a38Smrg        *opts_rtrn = XkbAX_TwoKeysMask;
30670728a38Smrg    else if (_XkbStrCaseCmp(name, "latchtolock") == 0)
30770728a38Smrg        *opts_rtrn = XkbAX_LatchToLockMask;
30870728a38Smrg    else if (_XkbStrCaseCmp(name, "slowkeysrelease") == 0)
30970728a38Smrg        *opts_rtrn = XkbAX_SKReleaseFBMask;
31070728a38Smrg    else if (_XkbStrCaseCmp(name, "slowkeysreject") == 0)
31170728a38Smrg        *opts_rtrn = XkbAX_SKRejectFBMask;
31270728a38Smrg    else if (_XkbStrCaseCmp(name, "bouncekeysreject") == 0)
31370728a38Smrg        *opts_rtrn = XkbAX_BKRejectFBMask;
31470728a38Smrg    else if (_XkbStrCaseCmp(name, "dumbbell") == 0)
31570728a38Smrg        *opts_rtrn = XkbAX_DumbBellFBMask;
3168c9fbc29Smrg    else {
31770728a38Smrg        rtrn->error = XkbCF_ExpectedControl;
31870728a38Smrg        return False;
3198c9fbc29Smrg    }
3208c9fbc29Smrg    return True;
3218c9fbc29Smrg}
3228c9fbc29Smrg
3238c9fbc29SmrgXkbConfigUnboundModPtr
32470728a38SmrgXkbCFAddModByName(XkbConfigRtrnPtr rtrn, int what, char *name, Bool merge,
32570728a38Smrg                  XkbConfigUnboundModPtr last)
3268c9fbc29Smrg{
32770728a38Smrg    if (rtrn->num_unbound_mods >= rtrn->sz_unbound_mods) {
32870728a38Smrg        rtrn->sz_unbound_mods += 5;
32970728a38Smrg        rtrn->unbound_mods = _XkbTypedRealloc(rtrn->unbound_mods,
33070728a38Smrg                                              rtrn->sz_unbound_mods,
33170728a38Smrg                                              XkbConfigUnboundModRec);
33270728a38Smrg        if (rtrn->unbound_mods == NULL) {
33370728a38Smrg            rtrn->error = XkbCF_BadAlloc;
33470728a38Smrg            return NULL;
33570728a38Smrg        }
3368c9fbc29Smrg    }
33770728a38Smrg    if (last == NULL) {
33870728a38Smrg        last = &rtrn->unbound_mods[rtrn->num_unbound_mods++];
33970728a38Smrg        last->what = what;
34070728a38Smrg        last->mods = 0;
34170728a38Smrg        last->vmods = 0;
34270728a38Smrg        last->merge = merge;
34370728a38Smrg        last->name = NULL;
3448c9fbc29Smrg    }
34570728a38Smrg    if (_XkbStrCaseCmp(name, "shift") == 0)
34670728a38Smrg        last->mods |= ShiftMask;
34770728a38Smrg    else if (_XkbStrCaseCmp(name, "lock") == 0)
34870728a38Smrg        last->mods |= LockMask;
34970728a38Smrg    else if ((_XkbStrCaseCmp(name, "control") == 0) ||
35070728a38Smrg             (_XkbStrCaseCmp(name, "ctrl") == 0))
35170728a38Smrg        last->mods |= ControlMask;
35270728a38Smrg    else if (_XkbStrCaseCmp(name, "mod1") == 0)
35370728a38Smrg        last->mods |= Mod1Mask;
35470728a38Smrg    else if (_XkbStrCaseCmp(name, "mod2") == 0)
35570728a38Smrg        last->mods |= Mod2Mask;
35670728a38Smrg    else if (_XkbStrCaseCmp(name, "mod3") == 0)
35770728a38Smrg        last->mods |= Mod3Mask;
35870728a38Smrg    else if (_XkbStrCaseCmp(name, "mod4") == 0)
35970728a38Smrg        last->mods |= Mod4Mask;
36070728a38Smrg    else if (_XkbStrCaseCmp(name, "mod5") == 0)
36170728a38Smrg        last->mods |= Mod5Mask;
3628c9fbc29Smrg    else {
36370728a38Smrg        if (last->name != NULL) {
36470728a38Smrg            last = &rtrn->unbound_mods[rtrn->num_unbound_mods++];
36570728a38Smrg            last->what = what;
36670728a38Smrg            last->mods = 0;
36770728a38Smrg            last->vmods = 0;
36870728a38Smrg            last->merge = merge;
36970728a38Smrg            last->name = NULL;
37070728a38Smrg        }
37170728a38Smrg        last->name = _XkbDupString(name);
3728c9fbc29Smrg    }
3738c9fbc29Smrg    return last;
3748c9fbc29Smrg}
3758c9fbc29Smrg
3768c9fbc29Smrgint
37770728a38SmrgXkbCFBindMods(XkbConfigRtrnPtr rtrn, XkbDescPtr xkb)
3788c9fbc29Smrg{
37970728a38Smrg    register int n, v;
38070728a38Smrg    Atom name;
38170728a38Smrg    XkbConfigUnboundModPtr mod;
38270728a38Smrg    int missing;
38370728a38Smrg
38470728a38Smrg    if (rtrn->num_unbound_mods < 1)
38570728a38Smrg        return 0;
38670728a38Smrg    if ((xkb == NULL) || (xkb->names == NULL))
38770728a38Smrg        return -1;
38870728a38Smrg
38970728a38Smrg    missing = 0;
39070728a38Smrg    for (n = 0, mod = rtrn->unbound_mods; n < rtrn->num_unbound_mods;
39170728a38Smrg         n++, mod++) {
39270728a38Smrg        if (mod->name != NULL) {
39370728a38Smrg            name = XkbInternAtom(xkb->dpy, mod->name, True);
39470728a38Smrg            if (name == None)
39570728a38Smrg                continue;
39670728a38Smrg            for (v = 0; v < XkbNumVirtualMods; v++) {
39770728a38Smrg                if (xkb->names->vmods[v] == name) {
39870728a38Smrg                    mod->vmods = (1 << v);
39970728a38Smrg                    _XkbFree(mod->name);
40070728a38Smrg                    mod->name = NULL;
40170728a38Smrg                    break;
40270728a38Smrg                }
40370728a38Smrg            }
40470728a38Smrg            if (mod->name != NULL)
40570728a38Smrg                missing++;
40670728a38Smrg        }
4078c9fbc29Smrg    }
4088c9fbc29Smrg    return missing;
4098c9fbc29Smrg}
4108c9fbc29Smrg
4118c9fbc29SmrgBool
41270728a38SmrgXkbCFApplyMods(XkbConfigRtrnPtr rtrn, int what, XkbConfigModInfoPtr info)
4138c9fbc29Smrg{
41470728a38Smrg    register int n;
41570728a38Smrg    XkbConfigUnboundModPtr mod;
41670728a38Smrg
41770728a38Smrg    if (rtrn->num_unbound_mods < 1)
41870728a38Smrg        return True;
41970728a38Smrg
42070728a38Smrg    for (n = 0, mod = rtrn->unbound_mods; n < rtrn->num_unbound_mods;
42170728a38Smrg         n++, mod++) {
42270728a38Smrg        if (mod->what != what)
42370728a38Smrg            continue;
42470728a38Smrg        if (mod->merge == XkbCF_MergeRemove) {
42570728a38Smrg            info->mods_clear |= mod->mods;
42670728a38Smrg            info->vmods_clear |= mod->vmods;
42770728a38Smrg        }
42870728a38Smrg        else {
42970728a38Smrg            if (mod->merge == XkbCF_MergeSet)
43070728a38Smrg                info->replace = True;
43170728a38Smrg            info->mods |= mod->mods;
43270728a38Smrg            info->vmods |= mod->vmods;
43370728a38Smrg        }
43470728a38Smrg        if (mod->name == NULL) {
43570728a38Smrg            mod->what = _XkbCF_Illegal;
43670728a38Smrg        }
43770728a38Smrg        else {
43870728a38Smrg            mod->mods = 0;
43970728a38Smrg            mod->vmods = 0;
44070728a38Smrg        }
4418c9fbc29Smrg    }
4428c9fbc29Smrg    return True;
4438c9fbc29Smrg}
4448c9fbc29Smrg
4458c9fbc29Smrg/*ARGSUSED*/
4468c9fbc29Smrgstatic Bool
44770728a38SmrgDefaultParser(FILE *             file,
44870728a38Smrg              XkbConfigFieldsPtr fields,
44970728a38Smrg              XkbConfigFieldPtr  field,
45070728a38Smrg              XkbDescPtr         xkb,
45170728a38Smrg              XkbConfigRtrnPtr   rtrn)
4528c9fbc29Smrg{
45370728a38Smrg    int tok;
45470728a38Smrg    XkbCFScanResultRec val;
45570728a38Smrg    char **str;
45670728a38Smrg    int merge;
45770728a38Smrg    unsigned long *ctrls, ctrls_mask;
45870728a38Smrg    unsigned short *opts, opts_mask;
45970728a38Smrg    int *pival, sign;
46070728a38Smrg    int onoff;
46170728a38Smrg    XkbConfigUnboundModPtr last;
46270728a38Smrg    unsigned what;
46370728a38Smrg
46470728a38Smrg    tok = XkbCFScan(file, &val, rtrn);
46570728a38Smrg    str = NULL;
46670728a38Smrg    onoff = 0;
46770728a38Smrg    pival = NULL;
4688c9fbc29Smrg    switch (field->field_id) {
46970728a38Smrg    case _XkbCF_RulesFile:      if (!str) str = &rtrn->rules_file;
47070728a38Smrg    case _XkbCF_Model:          if (!str) str = &rtrn->model;
47170728a38Smrg    case _XkbCF_Layout:         if (!str) str = &rtrn->layout;
47270728a38Smrg    case _XkbCF_Variant:        if (!str) str = &rtrn->variant;
47370728a38Smrg    case _XkbCF_Options:        if (!str) str = &rtrn->options;
47470728a38Smrg    case _XkbCF_Keymap:         if (!str) str = &rtrn->keymap;
47570728a38Smrg    case _XkbCF_Keycodes:       if (!str) str = &rtrn->keycodes;
47670728a38Smrg    case _XkbCF_Geometry:       if (!str) str = &rtrn->geometry;
47770728a38Smrg    case _XkbCF_PhysSymbols:    if (!str) str = &rtrn->phys_symbols;
47870728a38Smrg    case _XkbCF_Symbols:        if (!str) str = &rtrn->symbols;
47970728a38Smrg    case _XkbCF_Types:          if (!str) str = &rtrn->types;
48070728a38Smrg    case _XkbCF_CompatMap:      if (!str) str = &rtrn->compat;
48170728a38Smrg        if (tok != XkbCF_Equals) {
48270728a38Smrg            rtrn->error = XkbCF_MissingEquals;
48370728a38Smrg            goto BAILOUT;
48470728a38Smrg        }
48570728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
48670728a38Smrg        if ((tok != XkbCF_String) && (tok != XkbCF_Ident)) {
48770728a38Smrg            rtrn->error = XkbCF_ExpectedString;
48870728a38Smrg            return False;
48970728a38Smrg        }
49070728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
49170728a38Smrg        if ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
49270728a38Smrg            rtrn->error = XkbCF_ExpectedEOS;
49370728a38Smrg            return False;
49470728a38Smrg        }
49570728a38Smrg        if (*str != NULL)
49670728a38Smrg            _XkbFree(*str);
49770728a38Smrg        *str = _XkbDupString(val.str);
49870728a38Smrg        break;
49970728a38Smrg    case _XkbCF_InitialMods:
50070728a38Smrg    case _XkbCF_IgnoreLockMods:
50170728a38Smrg    case _XkbCF_InternalMods:
50270728a38Smrg        what = XkbCF_InitialMods;
50370728a38Smrg        if (field->field_id == _XkbCF_InitialMods)
50470728a38Smrg            rtrn->defined |= (what = XkbCF_InitialMods);
50570728a38Smrg        else if (field->field_id == _XkbCF_InternalMods)
50670728a38Smrg            rtrn->defined |= (what = XkbCF_InternalMods);
50770728a38Smrg        else if (field->field_id == _XkbCF_IgnoreLockMods)
50870728a38Smrg            rtrn->defined |= (what = XkbCF_IgnoreLockMods);
50970728a38Smrg        if (tok == XkbCF_Equals)
51070728a38Smrg            merge = XkbCF_MergeSet;
51170728a38Smrg        else if (tok == XkbCF_MinusEquals)
51270728a38Smrg            merge = XkbCF_MergeRemove;
51370728a38Smrg        else if (tok == XkbCF_PlusEquals)
51470728a38Smrg            merge = XkbCF_MergeAdd;
51570728a38Smrg        else {
51670728a38Smrg            rtrn->error = XkbCF_MissingEquals;
51770728a38Smrg            goto BAILOUT;
51870728a38Smrg        }
51970728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
52070728a38Smrg        if ((tok == XkbCF_EOL) || (tok == XkbCF_Semi) || (tok == XkbCF_EOF)) {
52170728a38Smrg            rtrn->error = XkbCF_ExpectedModifier;
52270728a38Smrg            return False;
52370728a38Smrg        }
52470728a38Smrg        last = NULL;
52570728a38Smrg        while ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
52670728a38Smrg            if ((tok != XkbCF_Ident) && (tok != XkbCF_String)) {
52770728a38Smrg                rtrn->error = XkbCF_ExpectedModifier;
52870728a38Smrg                return False;
52970728a38Smrg            }
53070728a38Smrg            last = XkbCFAddModByName(rtrn, what, val.str, merge, last);
53170728a38Smrg            if (last == NULL)
53270728a38Smrg                return False;
53370728a38Smrg            if (merge == XkbCF_MergeSet)
53470728a38Smrg                merge = XkbCF_MergeAdd;
53570728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
53670728a38Smrg            if ((tok != XkbCF_EOL) && (tok != XkbCF_EOF) && (tok != XkbCF_Semi)) {
53770728a38Smrg                if (tok != XkbCF_Plus) {
53870728a38Smrg                    rtrn->error = XkbCF_ExpectedOperator;
53970728a38Smrg                    return False;
54070728a38Smrg                }
54170728a38Smrg                tok = XkbCFScan(file, &val, rtrn);
54270728a38Smrg            }
54370728a38Smrg        }
54470728a38Smrg        break;
54570728a38Smrg    case _XkbCF_InitialCtrls:
54670728a38Smrg        rtrn->defined |= XkbCF_InitialCtrls;
54770728a38Smrg        ctrls = NULL;
54870728a38Smrg        if (tok == XkbCF_PlusEquals)
54970728a38Smrg            ctrls = &rtrn->initial_ctrls;
55070728a38Smrg        else if (tok == XkbCF_MinusEquals)
55170728a38Smrg            ctrls = &rtrn->initial_ctrls_clear;
55270728a38Smrg        else if (tok == XkbCF_Equals) {
55370728a38Smrg            ctrls = &rtrn->initial_ctrls;
55470728a38Smrg            rtrn->replace_initial_ctrls = True;
55570728a38Smrg            *ctrls = 0;
55670728a38Smrg        }
55770728a38Smrg        else {
55870728a38Smrg            rtrn->error = XkbCF_MissingEquals;
55970728a38Smrg            goto BAILOUT;
56070728a38Smrg        }
56170728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
56270728a38Smrg        if ((tok == XkbCF_EOL) || (tok == XkbCF_Semi) || (tok == XkbCF_EOF)) {
56370728a38Smrg            rtrn->error = XkbCF_ExpectedControl;
56470728a38Smrg            return False;
56570728a38Smrg        }
56670728a38Smrg        while ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
56770728a38Smrg            if ((tok != XkbCF_Ident) && (tok != XkbCF_String)) {
56870728a38Smrg                rtrn->error = XkbCF_ExpectedControl;
56970728a38Smrg                return False;
57070728a38Smrg            }
57170728a38Smrg            if (!AddCtrlByName(rtrn, val.str, &ctrls_mask)) {
57270728a38Smrg                return False;
57370728a38Smrg            }
57470728a38Smrg            *ctrls |= ctrls_mask;
57570728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
57670728a38Smrg            if ((tok != XkbCF_EOL) && (tok != XkbCF_EOF) && (tok != XkbCF_Semi)) {
57770728a38Smrg                if (tok != XkbCF_Plus) {
57870728a38Smrg                    rtrn->error = XkbCF_ExpectedOperator;
57970728a38Smrg                    return False;
58070728a38Smrg                }
58170728a38Smrg                tok = XkbCFScan(file, &val, rtrn);
58270728a38Smrg            }
58370728a38Smrg        }
58470728a38Smrg        break;
58570728a38Smrg    case _XkbCF_AccessXTimeoutCtrlsOn:
58670728a38Smrg    case _XkbCF_AccessXTimeoutCtrlsOff:
58770728a38Smrg        opts = NULL;
58870728a38Smrg        if (tok == XkbCF_MinusEquals) {
58970728a38Smrg            ctrls = &rtrn->axt_ctrls_ignore;
59070728a38Smrg            opts = &rtrn->axt_opts_ignore;
59170728a38Smrg        }
59270728a38Smrg        else if ((tok == XkbCF_PlusEquals) || (tok == XkbCF_Equals)) {
59370728a38Smrg            if (field->field_id == _XkbCF_AccessXTimeoutCtrlsOff) {
59470728a38Smrg                ctrls = &rtrn->axt_ctrls_off;
59570728a38Smrg                opts = &rtrn->axt_opts_off;
59670728a38Smrg                if (tok == XkbCF_Equals)
59770728a38Smrg                    rtrn->replace_axt_ctrls_off = True;
59870728a38Smrg            }
59970728a38Smrg            else {
60070728a38Smrg                ctrls = &rtrn->axt_ctrls_on;
60170728a38Smrg                opts = &rtrn->axt_opts_on;
60270728a38Smrg                if (tok == XkbCF_Equals)
60370728a38Smrg                    rtrn->replace_axt_ctrls_on = True;
60470728a38Smrg            }
60570728a38Smrg            *ctrls = 0;
60670728a38Smrg        }
60770728a38Smrg        else {
60870728a38Smrg            rtrn->error = XkbCF_MissingEquals;
60970728a38Smrg            goto BAILOUT;
61070728a38Smrg        }
61170728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
61270728a38Smrg        if ((tok == XkbCF_EOL) || (tok == XkbCF_Semi) || (tok == XkbCF_EOF)) {
61370728a38Smrg            rtrn->error = XkbCF_ExpectedControl;
61470728a38Smrg            return False;
61570728a38Smrg        }
61670728a38Smrg        while ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
61770728a38Smrg            if ((tok != XkbCF_Ident) && (tok != XkbCF_String)) {
61870728a38Smrg                rtrn->error = XkbCF_ExpectedControl;
61970728a38Smrg                return False;
62070728a38Smrg            }
62170728a38Smrg            if (!AddCtrlByName(rtrn, val.str, &ctrls_mask)) {
62270728a38Smrg                if (!AddAXTimeoutOptByName(rtrn, val.str, &opts_mask))
62370728a38Smrg                    return False;
62470728a38Smrg                *opts |= opts_mask;
62570728a38Smrg                if (field->field_id == _XkbCF_AccessXTimeoutCtrlsOff) {
62670728a38Smrg                    rtrn->defined |= XkbCF_AccessXTimeoutOptsOff;
62770728a38Smrg                    if (rtrn->replace_axt_ctrls_off)
62870728a38Smrg                        rtrn->replace_axt_opts_off = True;
62970728a38Smrg                }
63070728a38Smrg                else {
63170728a38Smrg                    rtrn->defined |= XkbCF_AccessXTimeoutOptsOn;
63270728a38Smrg                    if (rtrn->replace_axt_ctrls_on)
63370728a38Smrg                        rtrn->replace_axt_opts_on = True;
63470728a38Smrg                }
63570728a38Smrg            }
63670728a38Smrg            else
63770728a38Smrg                *ctrls |= ctrls_mask;
63870728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
63970728a38Smrg            if ((tok != XkbCF_EOL) && (tok != XkbCF_EOF) && (tok != XkbCF_Semi)) {
64070728a38Smrg                if (tok != XkbCF_Plus) {
64170728a38Smrg                    rtrn->error = XkbCF_ExpectedOperator;
64270728a38Smrg                    return False;
64370728a38Smrg                }
64470728a38Smrg                tok = XkbCFScan(file, &val, rtrn);
64570728a38Smrg            }
64670728a38Smrg        }
64770728a38Smrg        break;
64870728a38Smrg    case _XkbCF_InitialFeedback:
64970728a38Smrg        rtrn->defined |= XkbCF_InitialOpts;
65070728a38Smrg        opts = NULL;
65170728a38Smrg        if (tok == XkbCF_PlusEquals)
65270728a38Smrg            opts = &rtrn->initial_opts;
65370728a38Smrg        else if (tok == XkbCF_MinusEquals)
65470728a38Smrg            opts = &rtrn->initial_opts_clear;
65570728a38Smrg        else if (tok == XkbCF_Equals) {
65670728a38Smrg            opts = &rtrn->initial_opts;
65770728a38Smrg            rtrn->replace_initial_opts = True;
65870728a38Smrg            *opts = 0;
65970728a38Smrg        }
66070728a38Smrg        else {
66170728a38Smrg            rtrn->error = XkbCF_MissingEquals;
66270728a38Smrg            goto BAILOUT;
66370728a38Smrg        }
66470728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
66570728a38Smrg        if ((tok == XkbCF_EOL) || (tok == XkbCF_Semi) || (tok == XkbCF_EOF)) {
66670728a38Smrg            rtrn->error = XkbCF_ExpectedAXOption;
66770728a38Smrg            return False;
66870728a38Smrg        }
66970728a38Smrg        while ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
67070728a38Smrg            if ((tok != XkbCF_Ident) && (tok != XkbCF_String)) {
67170728a38Smrg                rtrn->error = XkbCF_ExpectedAXOption;
67270728a38Smrg                return False;
67370728a38Smrg            }
67470728a38Smrg            if (!AddAXTimeoutOptByName(rtrn, val.str, &opts_mask)) {
67570728a38Smrg                return False;
67670728a38Smrg            }
67770728a38Smrg            *opts |= opts_mask;
67870728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
67970728a38Smrg            if ((tok != XkbCF_EOL) && (tok != XkbCF_EOF) && (tok != XkbCF_Semi)) {
68070728a38Smrg                if (tok != XkbCF_Plus) {
68170728a38Smrg                    rtrn->error = XkbCF_ExpectedOperator;
68270728a38Smrg                    return False;
68370728a38Smrg                }
68470728a38Smrg                tok = XkbCFScan(file, &val, rtrn);
68570728a38Smrg            }
68670728a38Smrg        }
68770728a38Smrg        break;
68870728a38Smrg    case _XkbCF_AccessXTimeoutOptsOff:
68970728a38Smrg    case _XkbCF_AccessXTimeoutOptsOn:
69070728a38Smrg        opts = NULL;
69170728a38Smrg        if (tok == XkbCF_MinusEquals)
69270728a38Smrg            opts = &rtrn->axt_opts_ignore;
69370728a38Smrg        else if ((tok == XkbCF_PlusEquals) || (tok == XkbCF_Equals)) {
69470728a38Smrg            if (field->field_id == _XkbCF_AccessXTimeoutOptsOff) {
69570728a38Smrg                opts = &rtrn->axt_opts_off;
69670728a38Smrg                if (tok == XkbCF_Equals)
69770728a38Smrg                    rtrn->replace_axt_opts_off = True;
69870728a38Smrg            }
69970728a38Smrg            else {
70070728a38Smrg                opts = &rtrn->axt_opts_on;
70170728a38Smrg                if (tok == XkbCF_Equals)
70270728a38Smrg                    rtrn->replace_axt_opts_on = True;
70370728a38Smrg            }
70470728a38Smrg            *opts = 0;
70570728a38Smrg        }
70670728a38Smrg        else {
70770728a38Smrg            rtrn->error = XkbCF_MissingEquals;
70870728a38Smrg            goto BAILOUT;
70970728a38Smrg        }
71070728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
71170728a38Smrg        if ((tok == XkbCF_EOL) || (tok == XkbCF_Semi) || (tok == XkbCF_EOF)) {
71270728a38Smrg            rtrn->error = XkbCF_ExpectedControl;
71370728a38Smrg            return False;
71470728a38Smrg        }
71570728a38Smrg        while ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
71670728a38Smrg            if ((tok != XkbCF_Ident) && (tok != XkbCF_String)) {
71770728a38Smrg                rtrn->error = XkbCF_ExpectedControl;
71870728a38Smrg                return False;
71970728a38Smrg            }
72070728a38Smrg            if (!AddAXTimeoutOptByName(rtrn, val.str, &opts_mask))
72170728a38Smrg                return False;
72270728a38Smrg            *opts |= opts_mask;
72370728a38Smrg
72470728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
72570728a38Smrg            if ((tok != XkbCF_EOL) && (tok != XkbCF_EOF) && (tok != XkbCF_Semi)) {
72670728a38Smrg                if (tok != XkbCF_Plus) {
72770728a38Smrg                    rtrn->error = XkbCF_ExpectedOperator;
72870728a38Smrg                    return False;
72970728a38Smrg                }
73070728a38Smrg                tok = XkbCFScan(file, &val, rtrn);
73170728a38Smrg            }
73270728a38Smrg        }
73370728a38Smrg        break;
73470728a38Smrg    case _XkbCF_ClickVolume:
73570728a38Smrg        if (!pival) {
73670728a38Smrg            pival = &rtrn->click_volume;
73770728a38Smrg            onoff = 100;
73870728a38Smrg        }
73970728a38Smrg    case _XkbCF_BellVolume:
74070728a38Smrg        if (!pival) {
74170728a38Smrg            pival = &rtrn->bell_volume;
74270728a38Smrg            onoff = 100;
74370728a38Smrg        }
74470728a38Smrg    case _XkbCF_BellPitch:          if (!pival) pival = &rtrn->bell_pitch;
74570728a38Smrg    case _XkbCF_BellDuration:       if (!pival) pival = &rtrn->bell_duration;
74670728a38Smrg    case _XkbCF_RepeatDelay:        if (!pival) pival = &rtrn->repeat_delay;
74770728a38Smrg    case _XkbCF_RepeatInterval:     if (!pival) pival = &rtrn->repeat_interval;
74870728a38Smrg    case _XkbCF_SlowKeysDelay:      if (!pival) pival = &rtrn->slow_keys_delay;
74970728a38Smrg    case _XkbCF_DebounceDelay:      if (!pival) pival = &rtrn->debounce_delay;
75070728a38Smrg    case _XkbCF_MouseKeysDelay:     if (!pival) pival = &rtrn->mk_delay;
75170728a38Smrg    case _XkbCF_MouseKeysInterval:  if (!pival) pival = &rtrn->mk_interval;
75270728a38Smrg    case _XkbCF_MouseKeysTimeToMax: if (!pival) pival = &rtrn->mk_time_to_max;
75370728a38Smrg    case _XkbCF_MouseKeysMaxSpeed:  if (!pival) pival = &rtrn->mk_max_speed;
75470728a38Smrg    case _XkbCF_MouseKeysCurve:     if (!pival) pival = &rtrn->mk_curve;
75570728a38Smrg    case _XkbCF_AccessXTimeout:     if (!pival) pival = &rtrn->ax_timeout;
75670728a38Smrg        if (tok != XkbCF_Equals) {
75770728a38Smrg            rtrn->error = XkbCF_MissingEquals;
75870728a38Smrg            goto BAILOUT;
75970728a38Smrg        }
76070728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
76170728a38Smrg        if (tok == XkbCF_Minus && field->field_id == _XkbCF_MouseKeysCurve) {
76270728a38Smrg            /* This can be a negative value */
76370728a38Smrg            tok = XkbCFScan(file, &val, rtrn);
76470728a38Smrg            sign = -1;
76570728a38Smrg        }
76670728a38Smrg        else
76770728a38Smrg            sign = 1;
76870728a38Smrg        if (tok != XkbCF_Integer) {
76970728a38Smrg            Bool ok = False;
77070728a38Smrg
77170728a38Smrg            if ((onoff) && (tok == XkbCF_Ident) && (val.str != NULL)) {
77270728a38Smrg                if (_XkbStrCaseCmp(val.str, "on")) {
77370728a38Smrg                    val.ival = onoff;
77470728a38Smrg                    ok = True;
77570728a38Smrg                }
77670728a38Smrg                else if (_XkbStrCaseCmp(val.str, "off")) {
77770728a38Smrg                    val.ival = 0;
77870728a38Smrg                    ok = True;
77970728a38Smrg                }
78070728a38Smrg            }
78170728a38Smrg            if (!ok) {
78270728a38Smrg                rtrn->error = XkbCF_ExpectedInteger;
78370728a38Smrg                goto BAILOUT;
78470728a38Smrg            }
78570728a38Smrg        }
78670728a38Smrg        *pival = val.ival * sign;
78770728a38Smrg        if (field->field_id == _XkbCF_AccessXTimeout)
78870728a38Smrg            rtrn->defined |= XkbCF_AccessXTimeout;
78970728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
79070728a38Smrg        if ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
79170728a38Smrg            rtrn->error = XkbCF_ExpectedEOS;
79270728a38Smrg            return False;
79370728a38Smrg        }
79470728a38Smrg        break;
79570728a38Smrg    case _XkbCF_GroupsWrap:
79670728a38Smrg        if (tok != XkbCF_Equals) {
79770728a38Smrg            rtrn->error = XkbCF_MissingEquals;
79870728a38Smrg            goto BAILOUT;
79970728a38Smrg        }
80070728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
80170728a38Smrg        if (tok == XkbCF_Ident) {
80270728a38Smrg            if (_XkbStrCaseCmp(val.str, "wrap") == 0) {
80370728a38Smrg                rtrn->groups_wrap = XkbSetGroupInfo(0, XkbWrapIntoRange, 0);
80470728a38Smrg            }
80570728a38Smrg            else if (_XkbStrCaseCmp(val.str, "clamp") == 0) {
80670728a38Smrg                rtrn->groups_wrap = XkbSetGroupInfo(0, XkbClampIntoRange, 0);
80770728a38Smrg            }
80870728a38Smrg            else {
80970728a38Smrg                rtrn->error = XkbCF_ExpectedOORGroupBehavior;
81070728a38Smrg                return False;
81170728a38Smrg            }
81270728a38Smrg        }
81370728a38Smrg        else if ((tok == XkbCF_Integer) && (XkbIsLegalGroup(val.ival - 1))) {
81470728a38Smrg            rtrn->groups_wrap = XkbSetGroupInfo(0, XkbRedirectIntoRange,
81570728a38Smrg                                                val.ival - 1);
81670728a38Smrg        }
81770728a38Smrg        else {
81870728a38Smrg            rtrn->error = XkbCF_ExpectedOORGroupBehavior;
81970728a38Smrg            return False;
82070728a38Smrg        }
82170728a38Smrg        rtrn->defined |= XkbCF_GroupsWrap;
82270728a38Smrg        tok = XkbCFScan(file, &val, rtrn);
82370728a38Smrg        if ((tok != XkbCF_EOL) && (tok != XkbCF_Semi) && (tok != XkbCF_EOF)) {
82470728a38Smrg            rtrn->error = XkbCF_ExpectedEOS;
82570728a38Smrg            return False;
82670728a38Smrg        }
82770728a38Smrg        break;
82870728a38Smrg    default:
82970728a38Smrg        rtrn->error = XkbCF_ExpectedInteger;
83070728a38Smrg        goto BAILOUT;
8314cd6a3aeSmrg
8328c9fbc29Smrg    }
8338c9fbc29Smrg    return True;
83470728a38Smrg BAILOUT:
8358c9fbc29Smrg    return False;
8368c9fbc29Smrg}
8378c9fbc29Smrg
8388c9fbc29Smrgstatic Bool
8398c9fbc29SmrgDefaultCleanUp(XkbConfigRtrnPtr rtrn)
8408c9fbc29Smrg{
84170728a38Smrg    if (rtrn->keymap)
84270728a38Smrg        _XkbFree(rtrn->keymap);
84370728a38Smrg    if (rtrn->keycodes)
84470728a38Smrg        _XkbFree(rtrn->keycodes);
84570728a38Smrg    if (rtrn->geometry)
84670728a38Smrg        _XkbFree(rtrn->geometry);
84770728a38Smrg    if (rtrn->phys_symbols)
84870728a38Smrg        _XkbFree(rtrn->phys_symbols);
84970728a38Smrg    if (rtrn->symbols)
85070728a38Smrg        _XkbFree(rtrn->symbols);
85170728a38Smrg    if (rtrn->types)
85270728a38Smrg        _XkbFree(rtrn->types);
85370728a38Smrg    if (rtrn->compat)
85470728a38Smrg        _XkbFree(rtrn->compat);
85570728a38Smrg    rtrn->keycodes = rtrn->geometry = NULL;
85670728a38Smrg    rtrn->symbols = rtrn->phys_symbols = NULL;
85770728a38Smrg    rtrn->types = rtrn->compat = NULL;
85870728a38Smrg    if ((rtrn->unbound_mods != NULL) && (rtrn->num_unbound_mods > 0)) {
85970728a38Smrg        register int i;
86070728a38Smrg
86170728a38Smrg        for (i = 0; i < rtrn->num_unbound_mods; i++) {
86270728a38Smrg            if (rtrn->unbound_mods[i].name != NULL) {
86370728a38Smrg                _XkbFree(rtrn->unbound_mods[i].name);
86470728a38Smrg                rtrn->unbound_mods[i].name = NULL;
86570728a38Smrg            }
86670728a38Smrg        }
86770728a38Smrg        _XkbFree(rtrn->unbound_mods);
86870728a38Smrg        rtrn->sz_unbound_mods = 0;
86970728a38Smrg        rtrn->num_unbound_mods = 0;
87070728a38Smrg        rtrn->unbound_mods = NULL;
8718c9fbc29Smrg    }
8728c9fbc29Smrg    return True;
8738c9fbc29Smrg}
8748c9fbc29Smrg
8758c9fbc29Smrgstatic Bool
87670728a38SmrgDefaultApplyNames(XkbConfigRtrnPtr rtrn, XkbDescPtr xkb)
8778c9fbc29Smrg{
87870728a38Smrg    char *str;
87970728a38Smrg
88070728a38Smrg    if (XkbAllocNames(xkb, XkbComponentNamesMask, 0, 0) != Success)
88170728a38Smrg        return False;
88270728a38Smrg    if ((str = rtrn->keycodes) != NULL) {
88370728a38Smrg        xkb->names->keycodes = XkbInternAtom(xkb->dpy, str, False);
88470728a38Smrg        _XkbFree(str);
88570728a38Smrg        rtrn->keycodes = NULL;
8868c9fbc29Smrg    }
88770728a38Smrg    if ((str = rtrn->geometry) != NULL) {
88870728a38Smrg        xkb->names->geometry = XkbInternAtom(xkb->dpy, str, False);
88970728a38Smrg        _XkbFree(str);
89070728a38Smrg        rtrn->geometry = NULL;
8918c9fbc29Smrg    }
89270728a38Smrg    if ((str = rtrn->symbols) != NULL) {
89370728a38Smrg        xkb->names->symbols = XkbInternAtom(xkb->dpy, str, False);
89470728a38Smrg        _XkbFree(str);
89570728a38Smrg        rtrn->symbols = NULL;
8968c9fbc29Smrg    }
89770728a38Smrg    if ((str = rtrn->phys_symbols) != NULL) {
89870728a38Smrg        xkb->names->phys_symbols = XkbInternAtom(xkb->dpy, str, False);
89970728a38Smrg        _XkbFree(str);
90070728a38Smrg        rtrn->phys_symbols = NULL;
9018c9fbc29Smrg    }
90270728a38Smrg    if ((str = rtrn->types) != NULL) {
90370728a38Smrg        xkb->names->types = XkbInternAtom(xkb->dpy, str, False);
90470728a38Smrg        _XkbFree(str);
90570728a38Smrg        rtrn->types = NULL;
9068c9fbc29Smrg    }
90770728a38Smrg    if ((str = rtrn->compat) != NULL) {
90870728a38Smrg        xkb->names->compat = XkbInternAtom(xkb->dpy, str, False);
90970728a38Smrg        _XkbFree(str);
91070728a38Smrg        rtrn->compat = NULL;
9118c9fbc29Smrg    }
9128c9fbc29Smrg    return True;
9138c9fbc29Smrg}
9148c9fbc29Smrg
9158c9fbc29Smrgstatic Bool
91670728a38SmrgDefaultApplyControls(XkbConfigRtrnPtr rtrn, XkbDescPtr xkb)
9178c9fbc29Smrg{
91870728a38Smrg    unsigned on, off;
91970728a38Smrg    XkbControlsPtr ctrls;
92070728a38Smrg    unsigned int mask;
9218c9fbc29Smrg
92270728a38Smrg    if (XkbAllocControls(xkb, XkbAllControlsMask) != Success)
92370728a38Smrg        return False;
92470728a38Smrg    ctrls = xkb->ctrls;
9258c9fbc29Smrg    if (rtrn->replace_initial_ctrls)
92670728a38Smrg        ctrls->enabled_ctrls = rtrn->initial_ctrls;
92770728a38Smrg    else
92870728a38Smrg        ctrls->enabled_ctrls |= rtrn->initial_ctrls;
92970728a38Smrg    ctrls->enabled_ctrls &= ~rtrn->initial_ctrls_clear;
9308c9fbc29Smrg    if (rtrn->internal_mods.replace) {
93170728a38Smrg        ctrls->internal.real_mods = rtrn->internal_mods.mods;
93270728a38Smrg        ctrls->internal.vmods = rtrn->internal_mods.vmods;
9338c9fbc29Smrg    }
9348c9fbc29Smrg    else {
93570728a38Smrg        ctrls->internal.real_mods &= ~rtrn->internal_mods.mods_clear;
93670728a38Smrg        ctrls->internal.vmods &= ~rtrn->internal_mods.vmods_clear;
93770728a38Smrg        ctrls->internal.real_mods |= rtrn->internal_mods.mods;
93870728a38Smrg        ctrls->internal.vmods |= rtrn->internal_mods.vmods;
9398c9fbc29Smrg    }
94070728a38Smrg    mask = 0;
94170728a38Smrg    (void) XkbVirtualModsToReal(xkb, ctrls->internal.vmods, &mask);
94270728a38Smrg    ctrls->internal.mask = (ctrls->internal.real_mods | mask);
9438c9fbc29Smrg
9448c9fbc29Smrg    if (rtrn->ignore_lock_mods.replace) {
94570728a38Smrg        ctrls->ignore_lock.real_mods = rtrn->ignore_lock_mods.mods;
94670728a38Smrg        ctrls->ignore_lock.vmods = rtrn->ignore_lock_mods.vmods;
9478c9fbc29Smrg    }
9488c9fbc29Smrg    else {
94970728a38Smrg        ctrls->ignore_lock.real_mods &= ~rtrn->ignore_lock_mods.mods_clear;
95070728a38Smrg        ctrls->ignore_lock.vmods &= ~rtrn->ignore_lock_mods.vmods_clear;
95170728a38Smrg        ctrls->ignore_lock.real_mods |= rtrn->ignore_lock_mods.mods;
95270728a38Smrg        ctrls->ignore_lock.vmods |= rtrn->ignore_lock_mods.vmods;
9538c9fbc29Smrg    }
95470728a38Smrg    mask = 0;
95570728a38Smrg    (void) XkbVirtualModsToReal(xkb, ctrls->ignore_lock.vmods, &mask);
95670728a38Smrg    ctrls->ignore_lock.mask = (ctrls->ignore_lock.real_mods | mask);
95770728a38Smrg
95870728a38Smrg    if (rtrn->repeat_delay > 0)
95970728a38Smrg        ctrls->repeat_delay = rtrn->repeat_delay;
96070728a38Smrg    if (rtrn->repeat_interval > 0)
96170728a38Smrg        ctrls->repeat_interval = rtrn->repeat_interval;
96270728a38Smrg    if (rtrn->slow_keys_delay > 0)
96370728a38Smrg        ctrls->slow_keys_delay = rtrn->slow_keys_delay;
96470728a38Smrg    if (rtrn->debounce_delay > 0)
96570728a38Smrg        ctrls->debounce_delay = rtrn->debounce_delay;
96670728a38Smrg    if (rtrn->mk_delay > 0)
96770728a38Smrg        ctrls->mk_delay = rtrn->mk_delay;
96870728a38Smrg    if (rtrn->mk_interval > 0)
96970728a38Smrg        ctrls->mk_interval = rtrn->mk_interval;
97070728a38Smrg    if (rtrn->mk_time_to_max > 0)
97170728a38Smrg        ctrls->mk_time_to_max = rtrn->mk_time_to_max;
97270728a38Smrg    if (rtrn->mk_max_speed > 0)
97370728a38Smrg        ctrls->mk_max_speed = rtrn->mk_max_speed;
97470728a38Smrg    if (rtrn->mk_curve > 0)
97570728a38Smrg        ctrls->mk_curve = rtrn->mk_curve;
97670728a38Smrg    if (rtrn->defined & XkbCF_AccessXTimeout && rtrn->ax_timeout > 0)
97770728a38Smrg        ctrls->ax_timeout = rtrn->ax_timeout;
9788c9fbc29Smrg
9798c9fbc29Smrg    /* any value set to both off and on is reset to ignore */
98070728a38Smrg    if ((off = (rtrn->axt_ctrls_on & rtrn->axt_ctrls_off)) != 0)
98170728a38Smrg        rtrn->axt_ctrls_ignore |= off;
9828c9fbc29Smrg
9838c9fbc29Smrg    /* ignore takes priority over on and off */
98470728a38Smrg    rtrn->axt_ctrls_on &= ~rtrn->axt_ctrls_ignore;
98570728a38Smrg    rtrn->axt_ctrls_off &= ~rtrn->axt_ctrls_ignore;
9868c9fbc29Smrg
9878c9fbc29Smrg    if (!rtrn->replace_axt_ctrls_off) {
98870728a38Smrg        off = (ctrls->axt_ctrls_mask & (~ctrls->axt_ctrls_values));
98970728a38Smrg        off &= ~rtrn->axt_ctrls_on;
99070728a38Smrg        off |= rtrn->axt_ctrls_off;
9918c9fbc29Smrg    }
99270728a38Smrg    else
99370728a38Smrg        off = rtrn->axt_ctrls_off;
9948c9fbc29Smrg    if (!rtrn->replace_axt_ctrls_on) {
99570728a38Smrg        on = (ctrls->axt_ctrls_mask & ctrls->axt_ctrls_values);
99670728a38Smrg        on &= ~rtrn->axt_ctrls_off;
99770728a38Smrg        on |= rtrn->axt_ctrls_on;
9988c9fbc29Smrg    }
99970728a38Smrg    else
100070728a38Smrg        on = rtrn->axt_ctrls_on;
100170728a38Smrg    ctrls->axt_ctrls_mask = (on | off) & ~rtrn->axt_ctrls_ignore;
100270728a38Smrg    ctrls->axt_ctrls_values = on & ~rtrn->axt_ctrls_ignore;
10038c9fbc29Smrg
10048c9fbc29Smrg    /* any value set to both off and on is reset to ignore */
100570728a38Smrg    if ((off = (rtrn->axt_opts_on & rtrn->axt_opts_off)) != 0)
100670728a38Smrg        rtrn->axt_opts_ignore |= off;
10078c9fbc29Smrg
10088c9fbc29Smrg    /* ignore takes priority over on and off */
100970728a38Smrg    rtrn->axt_opts_on &= ~rtrn->axt_opts_ignore;
101070728a38Smrg    rtrn->axt_opts_off &= ~rtrn->axt_opts_ignore;
10118c9fbc29Smrg
10128c9fbc29Smrg    if (rtrn->replace_axt_opts_off) {
101370728a38Smrg        off = (ctrls->axt_opts_mask & (~ctrls->axt_opts_values));
101470728a38Smrg        off &= ~rtrn->axt_opts_on;
101570728a38Smrg        off |= rtrn->axt_opts_off;
10168c9fbc29Smrg    }
101770728a38Smrg    else
101870728a38Smrg        off = rtrn->axt_opts_off;
10198c9fbc29Smrg    if (!rtrn->replace_axt_opts_on) {
102070728a38Smrg        on = (ctrls->axt_opts_mask & ctrls->axt_opts_values);
102170728a38Smrg        on &= ~rtrn->axt_opts_off;
102270728a38Smrg        on |= rtrn->axt_opts_on;
10238c9fbc29Smrg    }
102470728a38Smrg    else
102570728a38Smrg        on = rtrn->axt_opts_on;
102670728a38Smrg    ctrls->axt_opts_mask =
102770728a38Smrg        (unsigned short) ((on | off) & ~rtrn->axt_ctrls_ignore);
102870728a38Smrg    ctrls->axt_opts_values = (unsigned short) (on & ~rtrn->axt_ctrls_ignore);
102970728a38Smrg
103070728a38Smrg    if (rtrn->defined & XkbCF_GroupsWrap) {
103170728a38Smrg        int n;
103270728a38Smrg
103370728a38Smrg        n = XkbNumGroups(ctrls->groups_wrap);
103470728a38Smrg        rtrn->groups_wrap = XkbSetNumGroups(rtrn->groups_wrap, n);
103570728a38Smrg        ctrls->groups_wrap = rtrn->groups_wrap;
10368c9fbc29Smrg    }
10378c9fbc29Smrg    return True;
10388c9fbc29Smrg}
10398c9fbc29Smrg
10408c9fbc29Smrg/*ARGSUSED*/
10418c9fbc29Smrgstatic Bool
104270728a38SmrgDefaultFinish(XkbConfigFieldsPtr fields, XkbDescPtr xkb,
104370728a38Smrg              XkbConfigRtrnPtr rtrn, int what)
10448c9fbc29Smrg{
104570728a38Smrg    if ((what == XkbCF_Destroy) || (what == XkbCF_CleanUp))
104670728a38Smrg        return DefaultCleanUp(rtrn);
104770728a38Smrg    if (what == XkbCF_Check) {
104870728a38Smrg        if ((rtrn->symbols == NULL) && (rtrn->phys_symbols != NULL))
104970728a38Smrg            rtrn->symbols = _XkbDupString(rtrn->phys_symbols);
10508c9fbc29Smrg    }
105170728a38Smrg    if ((what == XkbCF_Apply) || (what == XkbCF_Check)) {
105270728a38Smrg        if (xkb && xkb->names && (rtrn->num_unbound_mods > 0))
105370728a38Smrg            XkbCFBindMods(rtrn, xkb);
105470728a38Smrg        XkbCFApplyMods(rtrn, XkbCF_InitialMods, &rtrn->initial_mods);
105570728a38Smrg        XkbCFApplyMods(rtrn, XkbCF_InternalMods, &rtrn->internal_mods);
105670728a38Smrg        XkbCFApplyMods(rtrn, XkbCF_IgnoreLockMods, &rtrn->ignore_lock_mods);
10578c9fbc29Smrg    }
105870728a38Smrg    if (what == XkbCF_Apply) {
105970728a38Smrg        if (xkb != NULL) {
106070728a38Smrg            DefaultApplyNames(rtrn, xkb);
106170728a38Smrg            DefaultApplyControls(rtrn, xkb);
106270728a38Smrg            XkbCFBindMods(rtrn, xkb);
106370728a38Smrg        }
10648c9fbc29Smrg    }
10658c9fbc29Smrg    return True;
10668c9fbc29Smrg}
10678c9fbc29Smrg
10688c9fbc29Smrgstatic XkbConfigFieldRec _XkbCFDfltFields[] = {
106970728a38Smrg    {"rules",                   _XkbCF_RulesFile},
107070728a38Smrg    {"model",                   _XkbCF_Model},
107170728a38Smrg    {"layout",                  _XkbCF_Layout},
107270728a38Smrg    {"variant",                 _XkbCF_Variant},
107370728a38Smrg    {"options",                 _XkbCF_Options},
107470728a38Smrg    {"keymap",                  _XkbCF_Keymap},
107570728a38Smrg    {"keycodes",                _XkbCF_Keycodes},
107670728a38Smrg    {"geometry",                _XkbCF_Geometry},
107770728a38Smrg    {"realsymbols",             _XkbCF_PhysSymbols},
107870728a38Smrg    {"actualsymbols",           _XkbCF_PhysSymbols},
107970728a38Smrg    {"symbols",                 _XkbCF_Symbols},
108070728a38Smrg    {"symbolstouse",            _XkbCF_Symbols},
108170728a38Smrg    {"types",                   _XkbCF_Types},
108270728a38Smrg    {"compat",                  _XkbCF_CompatMap},
108370728a38Smrg    {"modifiers",               _XkbCF_InitialMods},
108470728a38Smrg    {"controls",                _XkbCF_InitialCtrls},
108570728a38Smrg    {"click",                   _XkbCF_ClickVolume},
108670728a38Smrg    {"clickvolume",             _XkbCF_ClickVolume},
108770728a38Smrg    {"bell",                    _XkbCF_BellVolume},
108870728a38Smrg    {"bellvolume",              _XkbCF_BellVolume},
108970728a38Smrg    {"bellpitch",               _XkbCF_BellPitch},
109070728a38Smrg    {"bellduration",            _XkbCF_BellDuration},
109170728a38Smrg    {"repeatdelay",             _XkbCF_RepeatDelay},
109270728a38Smrg    {"repeatinterval",          _XkbCF_RepeatInterval},
109370728a38Smrg    {"slowkeysdelay",           _XkbCF_SlowKeysDelay},
109470728a38Smrg    {"debouncedelay",           _XkbCF_DebounceDelay},
109570728a38Smrg    {"mousekeysdelay",          _XkbCF_MouseKeysDelay},
109670728a38Smrg    {"mousekeysinterval",       _XkbCF_MouseKeysInterval},
109770728a38Smrg    {"mousekeystimetomax",      _XkbCF_MouseKeysTimeToMax},
109870728a38Smrg    {"mousekeysmaxspeed",       _XkbCF_MouseKeysMaxSpeed},
109970728a38Smrg    {"mousekeyscurve",          _XkbCF_MouseKeysCurve},
110070728a38Smrg    {"accessxtimeout",          _XkbCF_AccessXTimeout},
110170728a38Smrg    {"axtimeout",               _XkbCF_AccessXTimeout},
110270728a38Smrg    {"accessxtimeoutctrlson",   _XkbCF_AccessXTimeoutCtrlsOn},
110370728a38Smrg    {"axtctrlson",              _XkbCF_AccessXTimeoutCtrlsOn},
110470728a38Smrg    {"accessxtimeoutctrlsoff",  _XkbCF_AccessXTimeoutCtrlsOff},
110570728a38Smrg    {"axtctrlsoff",             _XkbCF_AccessXTimeoutCtrlsOff},
110670728a38Smrg    {"accessxtimeoutfeedbackon",_XkbCF_AccessXTimeoutOptsOn},
110770728a38Smrg    {"axtfeedbackon",           _XkbCF_AccessXTimeoutOptsOn},
110870728a38Smrg    {"accessxtimeoutfeedbackoff",_XkbCF_AccessXTimeoutOptsOff},
110970728a38Smrg    {"axtfeedbackoff",          _XkbCF_AccessXTimeoutOptsOff},
111070728a38Smrg    {"ignorelockmods",          _XkbCF_IgnoreLockMods},
111170728a38Smrg    {"ignorelockmodifiers",     _XkbCF_IgnoreLockMods},
111270728a38Smrg    {"ignoregrouplock",         _XkbCF_IgnoreGroupLock},
111370728a38Smrg    {"internalmods",            _XkbCF_InternalMods},
111470728a38Smrg    {"internalmodifiers",       _XkbCF_InternalMods},
111570728a38Smrg    {"outofrangegroups",        _XkbCF_GroupsWrap},
111670728a38Smrg    {"groups",                  _XkbCF_GroupsWrap},
111770728a38Smrg    {"feedback",                _XkbCF_InitialFeedback},
11188c9fbc29Smrg};
11198c9fbc29Smrg#define	_XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec))
11208c9fbc29Smrg
11218c9fbc29Smrgstatic XkbConfigFieldsRec _XkbCFDflts = {
112270728a38Smrg    0,                          /* cfg_id */
112370728a38Smrg    _XkbCFNumDfltFields,        /* num_fields */
112470728a38Smrg    _XkbCFDfltFields,           /* fields */
112570728a38Smrg    DefaultParser,              /* parser */
112670728a38Smrg    DefaultFinish,              /* finish */
112770728a38Smrg    NULL,                       /* priv */
112870728a38Smrg    NULL                        /* next */
11298c9fbc29Smrg};
11308c9fbc29Smrg
113170728a38SmrgXkbConfigFieldsPtr XkbCFDflts = &_XkbCFDflts;
11328c9fbc29Smrg
11338c9fbc29Smrg/***====================================================================***/
11348c9fbc29Smrg
11358c9fbc29SmrgXkbConfigFieldsPtr
11368c9fbc29SmrgXkbCFDup(XkbConfigFieldsPtr fields)
11378c9fbc29Smrg{
113870728a38Smrg    XkbConfigFieldsPtr pNew;
113970728a38Smrg
114070728a38Smrg    pNew = _XkbTypedAlloc(XkbConfigFieldsRec);
114170728a38Smrg    if (pNew != NULL) {
114270728a38Smrg        memcpy(pNew, fields, sizeof(XkbConfigFieldsRec));
114370728a38Smrg        if ((pNew->fields != NULL) && (pNew->num_fields > 0)) {
114470728a38Smrg            pNew->fields = _XkbTypedCalloc(pNew->num_fields, XkbConfigFieldRec);
114570728a38Smrg            if (pNew->fields) {
114670728a38Smrg                memcpy(fields->fields, pNew->fields,
114770728a38Smrg                       (pNew->num_fields * sizeof(XkbConfigFieldRec)));
114870728a38Smrg            }
114970728a38Smrg            else {
115070728a38Smrg                _XkbFree(pNew);
115170728a38Smrg                return NULL;
115270728a38Smrg            }
115370728a38Smrg        }
115470728a38Smrg        else {
115570728a38Smrg            pNew->num_fields = 0;
115670728a38Smrg            pNew->fields = NULL;
115770728a38Smrg        }
115870728a38Smrg        pNew->next = NULL;
11598c9fbc29Smrg    }
11608c9fbc29Smrg    return pNew;
11618c9fbc29Smrg}
11628c9fbc29Smrg
11634cd6a3aeSmrgXkbConfigFieldsPtr
116470728a38SmrgXkbCFFree(XkbConfigFieldsPtr fields, Bool all)
11658c9fbc29Smrg{
116670728a38Smrg    XkbConfigFieldsPtr next;
116770728a38Smrg
116870728a38Smrg    next = NULL;
116970728a38Smrg    while (fields != NULL) {
117070728a38Smrg        next = fields->next;
117170728a38Smrg        if (fields != XkbCFDflts) {
117270728a38Smrg            if (fields->fields) {
117370728a38Smrg                _XkbFree(fields->fields);
117470728a38Smrg                fields->fields = NULL;
117570728a38Smrg                fields->num_fields = 0;
117670728a38Smrg            }
117770728a38Smrg            _XkbFree(fields);
117870728a38Smrg        }
117970728a38Smrg        fields = (all ? next : NULL);
11808c9fbc29Smrg    }
11818c9fbc29Smrg    return next;
11828c9fbc29Smrg}
11838c9fbc29Smrg
11848c9fbc29SmrgBool
118570728a38SmrgXkbCFApplyRtrnValues(XkbConfigRtrnPtr rtrn,
118670728a38Smrg                     XkbConfigFieldsPtr fields,
118770728a38Smrg                     XkbDescPtr xkb)
11888c9fbc29Smrg{
118970728a38Smrg    Bool ok;
11908c9fbc29Smrg
119170728a38Smrg    if ((fields == NULL) || (rtrn == NULL) || (xkb == NULL))
119270728a38Smrg        return False;
119370728a38Smrg    for (ok = True; fields != NULL; fields = fields->next) {
119470728a38Smrg        if (fields->finish != NULL)
119570728a38Smrg            ok = (*fields->finish) (fields, xkb, rtrn, XkbCF_Apply) && ok;
11968c9fbc29Smrg    }
11978c9fbc29Smrg    return ok;
11988c9fbc29Smrg}
11998c9fbc29Smrg
12008c9fbc29SmrgXkbConfigRtrnPrivPtr
120170728a38SmrgXkbCFAddPrivate(XkbConfigRtrnPtr rtrn, XkbConfigFieldsPtr fields, XPointer ptr)
12028c9fbc29Smrg{
120370728a38Smrg    XkbConfigRtrnPrivPtr priv;
120470728a38Smrg
120570728a38Smrg    if ((rtrn == NULL) || (fields == NULL))
120670728a38Smrg        return NULL;
120770728a38Smrg    priv = _XkbTypedAlloc(XkbConfigRtrnPrivRec);
120870728a38Smrg    if (priv != NULL) {
120970728a38Smrg        priv->cfg_id = fields->cfg_id;
121070728a38Smrg        priv->priv = ptr;
121170728a38Smrg        priv->next = rtrn->priv;
121270728a38Smrg        rtrn->priv = priv;
12138c9fbc29Smrg    }
12148c9fbc29Smrg    return priv;
12158c9fbc29Smrg}
12168c9fbc29Smrg
12178c9fbc29Smrgvoid
121870728a38SmrgXkbCFFreeRtrn(XkbConfigRtrnPtr rtrn, XkbConfigFieldsPtr fields, XkbDescPtr xkb)
12198c9fbc29Smrg{
122070728a38Smrg    XkbConfigRtrnPrivPtr tmp, next;
122170728a38Smrg
122270728a38Smrg    if ((fields == NULL) || (rtrn == NULL))
122370728a38Smrg        return;
122470728a38Smrg    while (fields != NULL) {
122570728a38Smrg        if (fields->finish != NULL)
122670728a38Smrg            (*fields->finish) (fields, xkb, rtrn, XkbCF_Destroy);
122770728a38Smrg        fields = fields->next;
12288c9fbc29Smrg    }
122970728a38Smrg    for (tmp = rtrn->priv; tmp != NULL; tmp = next) {
123070728a38Smrg        next = tmp->next;
123170728a38Smrg        bzero((char *) tmp, sizeof(XkbConfigRtrnPrivRec));
123270728a38Smrg        _XkbFree(tmp);
12338c9fbc29Smrg    }
123470728a38Smrg    bzero((char *) rtrn, sizeof(XkbConfigRtrnRec));
12358c9fbc29Smrg    return;
12368c9fbc29Smrg}
12378c9fbc29Smrg
12388c9fbc29SmrgBool
123970728a38SmrgXkbCFParse(FILE *file, XkbConfigFieldsPtr fields,
124070728a38Smrg           XkbDescPtr xkb, XkbConfigRtrnPtr rtrn)
12418c9fbc29Smrg{
124270728a38Smrg    int tok;
124370728a38Smrg    XkbCFScanResultRec val;
124470728a38Smrg    XkbConfigFieldsPtr tmp;
124570728a38Smrg
124670728a38Smrg    if ((file == NULL) || (fields == NULL) || (rtrn == NULL))
124770728a38Smrg        return False;
124870728a38Smrg    for (tok = 0, tmp = fields; tmp != NULL; tmp = tmp->next, tok++) {
124970728a38Smrg        fields->cfg_id = tok;
12508c9fbc29Smrg    }
125170728a38Smrg    bzero((char *) rtrn, sizeof(XkbConfigRtrnRec));
125270728a38Smrg    rtrn->line = 1;
125370728a38Smrg    rtrn->click_volume = -1;
125470728a38Smrg    rtrn->bell_volume = -1;
125570728a38Smrg    while ((tok = XkbCFScan(file, &val, rtrn)) != XkbCF_EOF) {
125670728a38Smrg        if (tok == XkbCF_Ident) {
125770728a38Smrg            Bool done;
125870728a38Smrg
125970728a38Smrg            for (tmp = fields, done = False; (tmp != NULL) && (!done);
126070728a38Smrg                 tmp = tmp->next) {
126170728a38Smrg                register int i;
126270728a38Smrg
126370728a38Smrg                XkbConfigFieldPtr f;
126470728a38Smrg
126570728a38Smrg                for (i = 0, f = tmp->fields; (i < tmp->num_fields) && (!done);
126670728a38Smrg                     i++, f++) {
126770728a38Smrg                    if (_XkbStrCaseCmp(val.str, f->field) != 0)
126870728a38Smrg                        continue;
126970728a38Smrg                    if ((*tmp->parser) (file, tmp, f, xkb, rtrn))
127070728a38Smrg                        done = True;
127170728a38Smrg                    else
127270728a38Smrg                        goto BAILOUT;
127370728a38Smrg                }
127470728a38Smrg            }
127570728a38Smrg        }
127670728a38Smrg        else if ((tok != XkbCF_EOL) && (tok != XkbCF_Semi)) {
127770728a38Smrg            rtrn->error = XkbCF_MissingIdent;
127870728a38Smrg            goto BAILOUT;
127970728a38Smrg        }
12808c9fbc29Smrg    }
128170728a38Smrg    for (tmp = fields; tmp != NULL; tmp = tmp->next) {
128270728a38Smrg        if ((tmp->finish) && (!(*tmp->finish) (tmp, xkb, rtrn, XkbCF_Check)))
128370728a38Smrg            goto BAILOUT;
12848c9fbc29Smrg    }
12858c9fbc29Smrg    return True;
128670728a38Smrg BAILOUT:
128770728a38Smrg    for (tmp = fields; tmp != NULL; tmp = tmp->next) {
128870728a38Smrg        if (tmp->finish)
128970728a38Smrg            (*tmp->finish) (tmp, xkb, rtrn, XkbCF_CleanUp);
12908c9fbc29Smrg    }
12918c9fbc29Smrg    return False;
12928c9fbc29Smrg}
12938c9fbc29Smrg
12948c9fbc29Smrg/*ARGSUSED*/
12958c9fbc29Smrgvoid
129670728a38SmrgXkbCFReportError(FILE *file, char *name, int error, int line)
12978c9fbc29Smrg{
129870728a38Smrg    const char *msg;
129970728a38Smrg
130070728a38Smrg    switch (error) {
130170728a38Smrg    case XkbCF_BadAlloc:
130270728a38Smrg        msg = "allocation failed\n";
130370728a38Smrg        break;
130470728a38Smrg    case XkbCF_UnterminatedString:
130570728a38Smrg        msg = "unterminated string on line %d";
130670728a38Smrg        break;
130770728a38Smrg    case XkbCF_MissingIdent:
130870728a38Smrg        msg = "expected identifier on line %d";
130970728a38Smrg        break;
131070728a38Smrg    case XkbCF_MissingEquals:
131170728a38Smrg        msg = "expected '=' on line %d";
131270728a38Smrg        break;
131370728a38Smrg    case XkbCF_ExpectedEOS:
131470728a38Smrg        msg = "expected ';' or newline on line %d";
131570728a38Smrg        break;
131670728a38Smrg    case XkbCF_ExpectedBoolean:
131770728a38Smrg        msg = "expected a boolean value on line %d";
131870728a38Smrg        break;
131970728a38Smrg    case XkbCF_ExpectedInteger:
132070728a38Smrg        msg = "expected a numeric value on line %d";
132170728a38Smrg        break;
132270728a38Smrg    case XkbCF_ExpectedString:
132370728a38Smrg        msg = "expected a string on line %d";
132470728a38Smrg        break;
132570728a38Smrg    case XkbCF_ExpectedModifier:
132670728a38Smrg        msg = "expected a modifier name on line %d";
132770728a38Smrg        break;
132870728a38Smrg    case XkbCF_ExpectedControl:
132970728a38Smrg        msg = "expected a control name on line %d";
133070728a38Smrg        break;
133170728a38Smrg    case XkbCF_ExpectedAXOption:
133270728a38Smrg        msg = "expected an AccessX option on line %d";
133370728a38Smrg        break;
133470728a38Smrg    case XkbCF_ExpectedOperator:
133570728a38Smrg        msg = "expected '+' or '-' on line %d";
133670728a38Smrg        break;
133770728a38Smrg    case XkbCF_ExpectedOORGroupBehavior:
133870728a38Smrg        msg = "expected wrap, clamp or group number on line %d";
133970728a38Smrg        break;
134070728a38Smrg    default:
134170728a38Smrg        msg = "unknown error on line %d";
134270728a38Smrg        break;
13438c9fbc29Smrg    }
134470728a38Smrg    fprintf(file, msg, line);
134570728a38Smrg    if (name)
134670728a38Smrg        fprintf(file, " of %s\n", name);
134770728a38Smrg    else
134870728a38Smrg        fprintf(file, "\n");
13498c9fbc29Smrg    return;
13508c9fbc29Smrg}
1351