2003-11-14 16:54:54 +01:00
|
|
|
/************************************************************
|
|
|
|
Copyright (c) 1996 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
|
2014-10-31 00:45:12 +01:00
|
|
|
documentation, and that the name of Silicon Graphics not be
|
|
|
|
used in advertising or publicity pertaining to distribution
|
2003-11-14 16:54:54 +01:00
|
|
|
of the software without specific prior written permission.
|
2014-10-31 00:45:12 +01:00
|
|
|
Silicon Graphics makes no representation about the suitability
|
2003-11-14 16:54:54 +01:00
|
|
|
of this software for any purpose. It is provided "as is"
|
|
|
|
without any express or implied warranty.
|
2014-10-31 00:45:12 +01:00
|
|
|
|
|
|
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
2003-11-14 16:54:54 +01:00
|
|
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
2014-10-31 00:45:12 +01:00
|
|
|
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
|
2003-11-14 16:54:54 +01:00
|
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
|
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
********************************************************/
|
|
|
|
|
2005-07-03 09:02:09 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
2005-06-13 23:51:46 +02:00
|
|
|
#endif
|
2005-07-03 09:37:35 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#define X_INCLUDE_STRING_H
|
|
|
|
#define XOS_USE_NO_LOCKING
|
|
|
|
#include <X11/Xos_r.h>
|
|
|
|
|
|
|
|
#include <X11/Xproto.h>
|
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Xfuncs.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include "misc.h"
|
|
|
|
#include "inputstr.h"
|
|
|
|
#include "dix.h"
|
2008-08-10 23:07:46 +02:00
|
|
|
#include "os.h"
|
2008-02-03 13:12:15 +01:00
|
|
|
#include "xkbstr.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
#define XKBSRV_NEED_FILE_FUNCS
|
2007-03-18 21:31:19 +01:00
|
|
|
#include <xkbsrv.h>
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
#define DFLT_LINE_SIZE 128
|
|
|
|
|
|
|
|
typedef struct {
|
2012-03-21 20:55:09 +01:00
|
|
|
int line_num;
|
|
|
|
int sz_line;
|
|
|
|
int num_line;
|
|
|
|
char buf[DFLT_LINE_SIZE];
|
|
|
|
char *line;
|
2003-11-14 16:54:54 +01:00
|
|
|
} InputLine;
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
InitInputLine(InputLine * line)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
line->line_num = 1;
|
|
|
|
line->num_line = 0;
|
|
|
|
line->sz_line = DFLT_LINE_SIZE;
|
|
|
|
line->line = line->buf;
|
2003-11-14 16:54:54 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
FreeInputLine(InputLine * line)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (line->line != line->buf)
|
|
|
|
free(line->line);
|
|
|
|
line->line_num = 1;
|
|
|
|
line->num_line = 0;
|
|
|
|
line->sz_line = DFLT_LINE_SIZE;
|
|
|
|
line->line = line->buf;
|
2003-11-14 16:54:54 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
InputLineAddChar(InputLine * line, int ch)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (line->num_line >= line->sz_line) {
|
|
|
|
if (line->line == line->buf) {
|
|
|
|
line->line = malloc(line->sz_line * 2);
|
|
|
|
memcpy(line->line, line->buf, line->sz_line);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
line->line = realloc((char *) line->line, line->sz_line * 2);
|
|
|
|
}
|
|
|
|
line->sz_line *= 2;
|
|
|
|
}
|
|
|
|
line->line[line->num_line++] = ch;
|
2003-11-14 16:54:54 +01:00
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\
|
|
|
|
(int)((l)->line[(l)->num_line++]= (c)):\
|
|
|
|
InputLineAddChar(l,c))
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
GetInputLine(FILE * file, InputLine * line, Bool checkbang)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int ch;
|
|
|
|
Bool endOfFile, spacePending, slashPending, inComment;
|
|
|
|
|
|
|
|
endOfFile = FALSE;
|
|
|
|
while ((!endOfFile) && (line->num_line == 0)) {
|
|
|
|
spacePending = slashPending = inComment = FALSE;
|
|
|
|
while (((ch = getc(file)) != '\n') && (ch != EOF)) {
|
|
|
|
if (ch == '\\') {
|
|
|
|
if ((ch = getc(file)) == EOF)
|
|
|
|
break;
|
|
|
|
if (ch == '\n') {
|
|
|
|
inComment = FALSE;
|
|
|
|
ch = ' ';
|
|
|
|
line->line_num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (inComment)
|
|
|
|
continue;
|
|
|
|
if (ch == '/') {
|
|
|
|
if (slashPending) {
|
|
|
|
inComment = TRUE;
|
|
|
|
slashPending = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
slashPending = TRUE;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (slashPending) {
|
|
|
|
if (spacePending) {
|
|
|
|
ADD_CHAR(line, ' ');
|
|
|
|
spacePending = FALSE;
|
|
|
|
}
|
|
|
|
ADD_CHAR(line, '/');
|
|
|
|
slashPending = FALSE;
|
|
|
|
}
|
|
|
|
if (isspace(ch)) {
|
|
|
|
while (isspace(ch) && (ch != '\n') && (ch != EOF)) {
|
|
|
|
ch = getc(file);
|
|
|
|
}
|
|
|
|
if (ch == EOF)
|
|
|
|
break;
|
|
|
|
if ((ch != '\n') && (line->num_line > 0))
|
|
|
|
spacePending = TRUE;
|
|
|
|
ungetc(ch, file);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (spacePending) {
|
|
|
|
ADD_CHAR(line, ' ');
|
|
|
|
spacePending = FALSE;
|
|
|
|
}
|
|
|
|
if (checkbang && ch == '!') {
|
|
|
|
if (line->num_line != 0) {
|
|
|
|
DebugF("The '!' legal only at start of line\n");
|
|
|
|
DebugF("Line containing '!' ignored\n");
|
|
|
|
line->num_line = 0;
|
|
|
|
inComment = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
ADD_CHAR(line, ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ch == EOF)
|
|
|
|
endOfFile = TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
/* else line->num_line++;*/
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
if ((line->num_line == 0) && (endOfFile))
|
|
|
|
return FALSE;
|
|
|
|
ADD_CHAR(line, '\0');
|
|
|
|
return TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
#define MODEL 0
|
|
|
|
#define LAYOUT 1
|
|
|
|
#define VARIANT 2
|
|
|
|
#define OPTION 3
|
|
|
|
#define KEYCODES 4
|
|
|
|
#define SYMBOLS 5
|
|
|
|
#define TYPES 6
|
|
|
|
#define COMPAT 7
|
|
|
|
#define GEOMETRY 8
|
2008-07-18 15:29:35 +02:00
|
|
|
#define MAX_WORDS 9
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
#define PART_MASK 0x000F
|
|
|
|
#define COMPONENT_MASK 0x03F0
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
static const char *cname[MAX_WORDS] = {
|
|
|
|
"model", "layout", "variant", "option",
|
|
|
|
"keycodes", "symbols", "types", "compat", "geometry"
|
2003-11-14 16:54:54 +01:00
|
|
|
};
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
typedef struct _RemapSpec {
|
|
|
|
int number;
|
|
|
|
int num_remap;
|
|
|
|
struct {
|
|
|
|
int word;
|
|
|
|
int index;
|
|
|
|
} remap[MAX_WORDS];
|
2003-11-14 16:54:54 +01:00
|
|
|
} RemapSpec;
|
|
|
|
|
|
|
|
typedef struct _FileSpec {
|
2012-03-21 20:55:09 +01:00
|
|
|
char *name[MAX_WORDS];
|
|
|
|
struct _FileSpec *pending;
|
2003-11-14 16:54:54 +01:00
|
|
|
} FileSpec;
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
typedef struct {
|
2013-11-15 14:28:47 +01:00
|
|
|
const char *model;
|
|
|
|
const char *layout[XkbNumKbdGroups + 1];
|
|
|
|
const char *variant[XkbNumKbdGroups + 1];
|
|
|
|
const char *options;
|
2003-11-14 17:49:22 +01:00
|
|
|
} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr;
|
|
|
|
|
|
|
|
#define NDX_BUFF_SIZE 4
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/***====================================================================***/
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
static char *
|
2003-11-14 17:49:22 +01:00
|
|
|
get_index(char *str, int *ndx)
|
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
char ndx_buf[NDX_BUFF_SIZE];
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
if (*str != '[') {
|
|
|
|
*ndx = 0;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
str++;
|
|
|
|
end = strchr(str, ']');
|
|
|
|
if (end == NULL) {
|
|
|
|
*ndx = -1;
|
|
|
|
return str - 1;
|
|
|
|
}
|
|
|
|
if ((end - str) >= NDX_BUFF_SIZE) {
|
|
|
|
*ndx = -1;
|
|
|
|
return end + 1;
|
|
|
|
}
|
|
|
|
strlcpy(ndx_buf, str, 1 + end - str);
|
|
|
|
*ndx = atoi(ndx_buf);
|
|
|
|
return end + 1;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SetUpRemap(InputLine * line, RemapSpec * remap)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
char *tok, *str;
|
|
|
|
unsigned present, l_ndx_present, v_ndx_present;
|
|
|
|
register int i;
|
|
|
|
int len, ndx;
|
|
|
|
_Xstrtokparams strtok_buf;
|
|
|
|
Bool found;
|
|
|
|
|
|
|
|
l_ndx_present = v_ndx_present = present = 0;
|
|
|
|
str = &line->line[1];
|
|
|
|
len = remap->number;
|
|
|
|
memset((char *) remap, 0, sizeof(RemapSpec));
|
|
|
|
remap->number = len;
|
|
|
|
while ((tok = _XStrtok(str, " ", strtok_buf)) != NULL) {
|
|
|
|
found = FALSE;
|
|
|
|
str = NULL;
|
|
|
|
if (strcmp(tok, "=") == 0)
|
|
|
|
continue;
|
|
|
|
for (i = 0; i < MAX_WORDS; i++) {
|
2003-11-14 17:49:22 +01:00
|
|
|
len = strlen(cname[i]);
|
2012-03-21 20:55:09 +01:00
|
|
|
if (strncmp(cname[i], tok, len) == 0) {
|
|
|
|
if (strlen(tok) > len) {
|
|
|
|
char *end = get_index(tok + len, &ndx);
|
|
|
|
|
|
|
|
if ((i != LAYOUT && i != VARIANT) ||
|
|
|
|
*end != '\0' || ndx == -1)
|
|
|
|
break;
|
|
|
|
if (ndx < 1 || ndx > XkbNumKbdGroups) {
|
|
|
|
DebugF("Illegal %s index: %d\n", cname[i], ndx);
|
|
|
|
DebugF("Index must be in range 1..%d\n",
|
|
|
|
XkbNumKbdGroups);
|
|
|
|
break;
|
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
ndx = 0;
|
|
|
|
}
|
|
|
|
found = TRUE;
|
|
|
|
if (present & (1 << i)) {
|
|
|
|
if ((i == LAYOUT && l_ndx_present & (1 << ndx)) ||
|
|
|
|
(i == VARIANT && v_ndx_present & (1 << ndx))) {
|
|
|
|
DebugF("Component \"%s\" listed twice\n", tok);
|
|
|
|
DebugF("Second definition ignored\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
present |= (1 << i);
|
2003-11-14 17:49:22 +01:00
|
|
|
if (i == LAYOUT)
|
|
|
|
l_ndx_present |= 1 << ndx;
|
|
|
|
if (i == VARIANT)
|
|
|
|
v_ndx_present |= 1 << ndx;
|
2012-03-21 20:55:09 +01:00
|
|
|
remap->remap[remap->num_remap].word = i;
|
|
|
|
remap->remap[remap->num_remap++].index = ndx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
fprintf(stderr, "Unknown component \"%s\" ignored\n", tok);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((present & PART_MASK) == 0) {
|
|
|
|
unsigned mask = PART_MASK;
|
|
|
|
|
|
|
|
ErrorF("Mapping needs at least one of ");
|
|
|
|
for (i = 0; (i < MAX_WORDS); i++) {
|
|
|
|
if ((1L << i) & mask) {
|
|
|
|
mask &= ~(1L << i);
|
|
|
|
if (mask)
|
|
|
|
DebugF("\"%s,\" ", cname[i]);
|
|
|
|
else
|
|
|
|
DebugF("or \"%s\"\n", cname[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DebugF("Illegal mapping ignored\n");
|
|
|
|
remap->num_remap = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((present & COMPONENT_MASK) == 0) {
|
|
|
|
DebugF("Mapping needs at least one component\n");
|
|
|
|
DebugF("Illegal mapping ignored\n");
|
|
|
|
remap->num_remap = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
remap->number++;
|
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2013-11-15 14:28:47 +01:00
|
|
|
MatchOneOf(const char *wanted, const char *vals_defined)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2013-11-15 14:28:47 +01:00
|
|
|
const char *str, *next;
|
2012-03-21 20:55:09 +01:00
|
|
|
int want_len = strlen(wanted);
|
|
|
|
|
|
|
|
for (str = vals_defined, next = NULL; str != NULL; str = next) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
next = strchr(str, ',');
|
|
|
|
if (next) {
|
|
|
|
len = next - str;
|
|
|
|
next++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len = strlen(str);
|
|
|
|
}
|
|
|
|
if ((len == want_len) && (strncmp(wanted, str, len) == 0))
|
|
|
|
return TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-01-15 01:07:38 +01:00
|
|
|
return FALSE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
CheckLine(InputLine * line,
|
|
|
|
RemapSpec * remap, XkbRF_RulePtr rule, XkbRF_GroupPtr group)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
char *str, *tok;
|
|
|
|
register int nread, i;
|
|
|
|
FileSpec tmp;
|
|
|
|
_Xstrtokparams strtok_buf;
|
|
|
|
Bool append = FALSE;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (line->line[0] == '!') {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (line->line[1] == '$' ||
|
|
|
|
(line->line[1] == ' ' && line->line[2] == '$')) {
|
|
|
|
char *gname = strchr(line->line, '$');
|
|
|
|
char *words = strchr(gname, ' ');
|
2012-03-21 20:55:09 +01:00
|
|
|
|
|
|
|
if (!words)
|
2010-01-15 01:07:38 +01:00
|
|
|
return FALSE;
|
2003-11-14 17:49:22 +01:00
|
|
|
*words++ = '\0';
|
|
|
|
for (; *words; words++) {
|
|
|
|
if (*words != '=' && *words != ' ')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*words == '\0')
|
2010-01-15 01:07:38 +01:00
|
|
|
return FALSE;
|
2011-02-14 06:36:03 +01:00
|
|
|
group->name = Xstrdup(gname);
|
|
|
|
group->words = Xstrdup(words);
|
2003-11-14 17:49:22 +01:00
|
|
|
for (i = 1, words = group->words; *words; words++) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (*words == ' ') {
|
|
|
|
*words++ = '\0';
|
|
|
|
i++;
|
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
group->number = i;
|
2010-01-15 01:07:38 +01:00
|
|
|
return TRUE;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
SetUpRemap(line, remap);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remap->num_remap == 0) {
|
|
|
|
DebugF("Must have a mapping before first line of data\n");
|
|
|
|
DebugF("Illegal line of data ignored\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
memset((char *) &tmp, 0, sizeof(FileSpec));
|
|
|
|
str = line->line;
|
|
|
|
for (nread = 0; (tok = _XStrtok(str, " ", strtok_buf)) != NULL; nread++) {
|
|
|
|
str = NULL;
|
|
|
|
if (strcmp(tok, "=") == 0) {
|
|
|
|
nread--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (nread > remap->num_remap) {
|
|
|
|
DebugF("Too many words on a line\n");
|
|
|
|
DebugF("Extra word \"%s\" ignored\n", tok);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
tmp.name[remap->remap[nread].word] = tok;
|
|
|
|
if (*tok == '+' || *tok == '|')
|
|
|
|
append = TRUE;
|
|
|
|
}
|
|
|
|
if (nread < remap->num_remap) {
|
|
|
|
DebugF("Too few words on a line: %s\n", line->line);
|
|
|
|
DebugF("line ignored\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rule->flags = 0;
|
2003-11-14 17:49:22 +01:00
|
|
|
rule->number = remap->number;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (tmp.name[OPTION])
|
2012-03-21 20:55:09 +01:00
|
|
|
rule->flags |= XkbRF_Option;
|
2003-11-14 17:49:22 +01:00
|
|
|
else if (append)
|
2012-03-21 20:55:09 +01:00
|
|
|
rule->flags |= XkbRF_Append;
|
2003-11-14 17:49:22 +01:00
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
rule->flags |= XkbRF_Normal;
|
|
|
|
rule->model = Xstrdup(tmp.name[MODEL]);
|
|
|
|
rule->layout = Xstrdup(tmp.name[LAYOUT]);
|
|
|
|
rule->variant = Xstrdup(tmp.name[VARIANT]);
|
|
|
|
rule->option = Xstrdup(tmp.name[OPTION]);
|
|
|
|
|
|
|
|
rule->keycodes = Xstrdup(tmp.name[KEYCODES]);
|
|
|
|
rule->symbols = Xstrdup(tmp.name[SYMBOLS]);
|
|
|
|
rule->types = Xstrdup(tmp.name[TYPES]);
|
|
|
|
rule->compat = Xstrdup(tmp.name[COMPAT]);
|
|
|
|
rule->geometry = Xstrdup(tmp.name[GEOMETRY]);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
|
|
|
rule->layout_num = rule->variant_num = 0;
|
|
|
|
for (i = 0; i < nread; i++) {
|
|
|
|
if (remap->remap[i].index) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (remap->remap[i].word == LAYOUT)
|
|
|
|
rule->layout_num = remap->remap[i].index;
|
|
|
|
if (remap->remap[i].word == VARIANT)
|
|
|
|
rule->variant_num = remap->remap[i].index;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
}
|
2010-01-15 01:07:38 +01:00
|
|
|
return TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-11-15 14:28:47 +01:00
|
|
|
_Concat(char *str1, const char *str2)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int len;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((!str1) || (!str2))
|
|
|
|
return str1;
|
|
|
|
len = strlen(str1) + strlen(str2) + 1;
|
|
|
|
str1 = realloc(str1, len * sizeof(char));
|
2003-11-14 16:54:54 +01:00
|
|
|
if (str1)
|
2012-03-21 20:55:09 +01:00
|
|
|
strcat(str1, str2);
|
2003-11-14 16:54:54 +01:00
|
|
|
return str1;
|
|
|
|
}
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static void
|
|
|
|
squeeze_spaces(char *p1)
|
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
char *p2;
|
|
|
|
|
|
|
|
for (p2 = p1; *p2; p2++) {
|
|
|
|
*p1 = *p2;
|
|
|
|
if (*p1 != ' ')
|
|
|
|
p1++;
|
|
|
|
}
|
|
|
|
*p1 = '\0';
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
|
|
|
|
{
|
2013-11-15 14:28:47 +01:00
|
|
|
char *options;
|
2012-03-21 20:55:09 +01:00
|
|
|
memset((char *) mdefs, 0, sizeof(XkbRF_MultiDefsRec));
|
|
|
|
mdefs->model = defs->model;
|
2013-11-15 14:28:47 +01:00
|
|
|
options = Xstrdup(defs->options);
|
|
|
|
if (options)
|
|
|
|
squeeze_spaces(options);
|
|
|
|
mdefs->options = options;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
|
|
|
if (defs->layout) {
|
|
|
|
if (!strchr(defs->layout, ',')) {
|
|
|
|
mdefs->layout[0] = defs->layout;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *p;
|
2013-11-15 14:28:47 +01:00
|
|
|
char *layout;
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
|
2013-11-15 14:28:47 +01:00
|
|
|
layout = Xstrdup(defs->layout);
|
|
|
|
if (layout == NULL)
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2013-11-15 14:28:47 +01:00
|
|
|
squeeze_spaces(layout);
|
|
|
|
mdefs->layout[1] = layout;
|
|
|
|
p = layout;
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 2; i <= XkbNumKbdGroups; i++) {
|
|
|
|
if ((p = strchr(p, ','))) {
|
|
|
|
*p++ = '\0';
|
|
|
|
mdefs->layout[i] = p;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p && (p = strchr(p, ',')))
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defs->variant) {
|
|
|
|
if (!strchr(defs->variant, ',')) {
|
|
|
|
mdefs->variant[0] = defs->variant;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *p;
|
2013-11-15 14:28:47 +01:00
|
|
|
char *variant;
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
|
2013-11-15 14:28:47 +01:00
|
|
|
variant = Xstrdup(defs->variant);
|
|
|
|
if (variant == NULL)
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2013-11-15 14:28:47 +01:00
|
|
|
squeeze_spaces(variant);
|
|
|
|
mdefs->variant[1] = variant;
|
|
|
|
p = variant;
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 2; i <= XkbNumKbdGroups; i++) {
|
|
|
|
if ((p = strchr(p, ','))) {
|
|
|
|
*p++ = '\0';
|
|
|
|
mdefs->variant[i] = p;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p && (p = strchr(p, ',')))
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FreeMultiDefs(XkbRF_MultiDefsPtr defs)
|
|
|
|
{
|
2013-11-15 14:28:47 +01:00
|
|
|
free((void *) defs->options);
|
|
|
|
free((void *) defs->layout[1]);
|
|
|
|
free((void *) defs->variant[1]);
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-11-15 14:28:47 +01:00
|
|
|
Apply(const char *src, char **dst)
|
2003-11-14 17:49:22 +01:00
|
|
|
{
|
|
|
|
if (src) {
|
|
|
|
if (*src == '+' || *src == '!') {
|
2012-03-21 20:55:09 +01:00
|
|
|
*dst = _Concat(*dst, src);
|
|
|
|
}
|
|
|
|
else {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (*dst == NULL)
|
2012-03-21 20:55:09 +01:00
|
|
|
*dst = Xstrdup(src);
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_ApplyRule(XkbRF_RulePtr rule, XkbComponentNamesPtr names)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
rule->flags &= ~XkbRF_PendingMatch; /* clear the flag because it's applied */
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
Apply(rule->keycodes, &names->keycodes);
|
2012-03-21 20:55:09 +01:00
|
|
|
Apply(rule->symbols, &names->symbols);
|
|
|
|
Apply(rule->types, &names->types);
|
|
|
|
Apply(rule->compat, &names->compat);
|
2003-11-14 17:49:22 +01:00
|
|
|
Apply(rule->geometry, &names->geometry);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static Bool
|
2013-11-15 14:28:47 +01:00
|
|
|
CheckGroup(XkbRF_RulesPtr rules, const char *group_name, const char *name)
|
2003-11-14 17:49:22 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
char *p;
|
|
|
|
XkbRF_GroupPtr group;
|
|
|
|
|
|
|
|
for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) {
|
|
|
|
if (!strcmp(group->name, group_name)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == rules->num_groups)
|
|
|
|
return FALSE;
|
|
|
|
for (i = 0, p = group->words; i < group->number; i++, p += strlen(p) + 1) {
|
|
|
|
if (!strcmp(p, name)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_CheckApplyRule(XkbRF_RulePtr rule,
|
|
|
|
XkbRF_MultiDefsPtr mdefs,
|
|
|
|
XkbComponentNamesPtr names, XkbRF_RulesPtr rules)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-01-15 01:07:38 +01:00
|
|
|
Bool pending = FALSE;
|
2003-11-14 17:49:22 +01:00
|
|
|
|
|
|
|
if (rule->model != NULL) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (mdefs->model == NULL)
|
2003-11-14 17:49:22 +01:00
|
|
|
return 0;
|
|
|
|
if (strcmp(rule->model, "*") == 0) {
|
2010-01-15 01:07:38 +01:00
|
|
|
pending = TRUE;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (rule->model[0] == '$') {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!CheckGroup(rules, rule->model, mdefs->model))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (strcmp(rule->model, mdefs->model) != 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
if (rule->option != NULL) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (mdefs->options == NULL)
|
|
|
|
return 0;
|
|
|
|
if ((!MatchOneOf(rule->option, mdefs->options)))
|
|
|
|
return 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
|
|
|
|
if (rule->layout != NULL) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (mdefs->layout[rule->layout_num] == NULL ||
|
|
|
|
*mdefs->layout[rule->layout_num] == '\0')
|
|
|
|
return 0;
|
2003-11-14 17:49:22 +01:00
|
|
|
if (strcmp(rule->layout, "*") == 0) {
|
2010-01-15 01:07:38 +01:00
|
|
|
pending = TRUE;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (rule->layout[0] == '$') {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!CheckGroup(rules, rule->layout,
|
|
|
|
mdefs->layout[rule->layout_num]))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
if (rule->variant != NULL) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (mdefs->variant[rule->variant_num] == NULL ||
|
|
|
|
*mdefs->variant[rule->variant_num] == '\0')
|
|
|
|
return 0;
|
2003-11-14 17:49:22 +01:00
|
|
|
if (strcmp(rule->variant, "*") == 0) {
|
2010-01-15 01:07:38 +01:00
|
|
|
pending = TRUE;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (rule->variant[0] == '$') {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!CheckGroup(rules, rule->variant,
|
|
|
|
mdefs->variant[rule->variant_num]))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (strcmp(rule->variant,
|
|
|
|
mdefs->variant[rule->variant_num]) != 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
if (pending) {
|
2012-03-21 20:55:09 +01:00
|
|
|
rule->flags |= XkbRF_PendingMatch;
|
|
|
|
return rule->number;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
/* exact match, apply it now */
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_ApplyRule(rule, names);
|
2003-11-14 17:49:22 +01:00
|
|
|
return rule->number;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static void
|
2003-11-14 16:54:54 +01:00
|
|
|
XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules)
|
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
register int i;
|
|
|
|
XkbRF_RulePtr rule;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) {
|
|
|
|
rule->flags &= ~XkbRF_PendingMatch;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules, XkbComponentNamesPtr names)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
XkbRF_RulePtr rule;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((rule->flags & XkbRF_PendingMatch) == 0)
|
|
|
|
continue;
|
|
|
|
XkbRF_ApplyRule(rule, names);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_CheckApplyRules(XkbRF_RulesPtr rules,
|
|
|
|
XkbRF_MultiDefsPtr mdefs,
|
|
|
|
XkbComponentNamesPtr names, int flags)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
XkbRF_RulePtr rule;
|
|
|
|
int skip;
|
|
|
|
|
|
|
|
for (rule = rules->rules, i = 0; i < rules->num_rules; rule++, i++) {
|
|
|
|
if ((rule->flags & flags) != flags)
|
|
|
|
continue;
|
|
|
|
skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules);
|
|
|
|
if (skip && !(flags & XkbRF_Option)) {
|
|
|
|
for (; (i < rules->num_rules) && (rule->number == skip);
|
|
|
|
rule++, i++);
|
|
|
|
rule--;
|
|
|
|
i--;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
static char *
|
|
|
|
XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
char *str, *outstr, *orig, *var;
|
|
|
|
int len, ndx;
|
|
|
|
|
|
|
|
orig = name;
|
|
|
|
str = index(name, '%');
|
|
|
|
if (str == NULL)
|
|
|
|
return name;
|
|
|
|
len = strlen(name);
|
|
|
|
while (str != NULL) {
|
|
|
|
char pfx = str[1];
|
|
|
|
int extra_len = 0;
|
|
|
|
|
|
|
|
if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) {
|
|
|
|
extra_len = 1;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
else if (pfx == '(') {
|
|
|
|
extra_len = 2;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
var = str + 1;
|
|
|
|
str = get_index(var + 1, &ndx);
|
|
|
|
if (ndx == -1) {
|
|
|
|
str = index(str, '%');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx])
|
|
|
|
len += strlen(mdefs->layout[ndx]) + extra_len;
|
|
|
|
else if ((*var == 'm') && mdefs->model)
|
|
|
|
len += strlen(mdefs->model) + extra_len;
|
|
|
|
else if ((*var == 'v') && mdefs->variant[ndx] && *mdefs->variant[ndx])
|
|
|
|
len += strlen(mdefs->variant[ndx]) + extra_len;
|
|
|
|
if ((pfx == '(') && (*str == ')')) {
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
str = index(&str[0], '%');
|
|
|
|
}
|
|
|
|
name = malloc(len + 1);
|
|
|
|
str = orig;
|
|
|
|
outstr = name;
|
|
|
|
while (*str != '\0') {
|
|
|
|
if (str[0] == '%') {
|
|
|
|
char pfx, sfx;
|
|
|
|
|
|
|
|
str++;
|
|
|
|
pfx = str[0];
|
|
|
|
sfx = '\0';
|
|
|
|
if ((pfx == '+') || (pfx == '|') || (pfx == '_') || (pfx == '-')) {
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
else if (pfx == '(') {
|
|
|
|
sfx = ')';
|
|
|
|
str++;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else
|
|
|
|
pfx = '\0';
|
|
|
|
|
|
|
|
var = str;
|
|
|
|
str = get_index(var + 1, &ndx);
|
|
|
|
if (ndx == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((*var == 'l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) {
|
|
|
|
if (pfx)
|
|
|
|
*outstr++ = pfx;
|
|
|
|
strcpy(outstr, mdefs->layout[ndx]);
|
|
|
|
outstr += strlen(mdefs->layout[ndx]);
|
|
|
|
if (sfx)
|
|
|
|
*outstr++ = sfx;
|
|
|
|
}
|
|
|
|
else if ((*var == 'm') && (mdefs->model)) {
|
|
|
|
if (pfx)
|
|
|
|
*outstr++ = pfx;
|
|
|
|
strcpy(outstr, mdefs->model);
|
|
|
|
outstr += strlen(mdefs->model);
|
|
|
|
if (sfx)
|
|
|
|
*outstr++ = sfx;
|
|
|
|
}
|
|
|
|
else if ((*var == 'v') && mdefs->variant[ndx] &&
|
|
|
|
*mdefs->variant[ndx]) {
|
|
|
|
if (pfx)
|
|
|
|
*outstr++ = pfx;
|
|
|
|
strcpy(outstr, mdefs->variant[ndx]);
|
|
|
|
outstr += strlen(mdefs->variant[ndx]);
|
|
|
|
if (sfx)
|
|
|
|
*outstr++ = sfx;
|
|
|
|
}
|
|
|
|
if ((pfx == '(') && (*str == ')'))
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*outstr++ = *str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*outstr++ = '\0';
|
|
|
|
if (orig != name)
|
|
|
|
free(orig);
|
2003-11-14 16:54:54 +01:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_GetComponents(XkbRF_RulesPtr rules,
|
|
|
|
XkbRF_VarDefsPtr defs, XkbComponentNamesPtr names)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2003-11-14 17:49:22 +01:00
|
|
|
XkbRF_MultiDefsRec mdefs;
|
|
|
|
|
|
|
|
MakeMultiDefs(&mdefs, defs);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
memset((char *) names, 0, sizeof(XkbComponentNamesRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
XkbRF_ClearPartialMatches(rules);
|
2003-11-14 17:49:22 +01:00
|
|
|
XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal);
|
|
|
|
XkbRF_ApplyPartialMatches(rules, names);
|
|
|
|
XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append);
|
|
|
|
XkbRF_ApplyPartialMatches(rules, names);
|
|
|
|
XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option);
|
2012-10-23 10:32:31 +02:00
|
|
|
XkbRF_ApplyPartialMatches(rules, names);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
if (names->keycodes)
|
2012-03-21 20:55:09 +01:00
|
|
|
names->keycodes = XkbRF_SubstituteVars(names->keycodes, &mdefs);
|
|
|
|
if (names->symbols)
|
|
|
|
names->symbols = XkbRF_SubstituteVars(names->symbols, &mdefs);
|
2003-11-14 16:54:54 +01:00
|
|
|
if (names->types)
|
2012-03-21 20:55:09 +01:00
|
|
|
names->types = XkbRF_SubstituteVars(names->types, &mdefs);
|
2003-11-14 16:54:54 +01:00
|
|
|
if (names->compat)
|
2012-03-21 20:55:09 +01:00
|
|
|
names->compat = XkbRF_SubstituteVars(names->compat, &mdefs);
|
2003-11-14 16:54:54 +01:00
|
|
|
if (names->geometry)
|
2012-03-21 20:55:09 +01:00
|
|
|
names->geometry = XkbRF_SubstituteVars(names->geometry, &mdefs);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
|
|
|
FreeMultiDefs(&mdefs);
|
2003-11-14 16:54:54 +01:00
|
|
|
return (names->keycodes && names->symbols && names->types &&
|
2012-03-21 20:55:09 +01:00
|
|
|
names->compat && names->geometry);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2008-07-18 15:41:29 +02:00
|
|
|
static XkbRF_RulePtr
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_AddRule(XkbRF_RulesPtr rules)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (rules->sz_rules < 1) {
|
|
|
|
rules->sz_rules = 16;
|
|
|
|
rules->num_rules = 0;
|
|
|
|
rules->rules = calloc(rules->sz_rules, sizeof(XkbRF_RuleRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else if (rules->num_rules >= rules->sz_rules) {
|
|
|
|
rules->sz_rules *= 2;
|
|
|
|
rules->rules = realloc(rules->rules,
|
|
|
|
rules->sz_rules * sizeof(XkbRF_RuleRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (!rules->rules) {
|
2012-03-21 20:55:09 +01:00
|
|
|
rules->sz_rules = rules->num_rules = 0;
|
|
|
|
DebugF("Allocation failure in XkbRF_AddRule\n");
|
|
|
|
return NULL;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
memset((char *) &rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
return &rules->rules[rules->num_rules++];
|
|
|
|
}
|
|
|
|
|
2008-07-18 15:41:29 +02:00
|
|
|
static XkbRF_GroupPtr
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_AddGroup(XkbRF_RulesPtr rules)
|
2003-11-14 17:49:22 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (rules->sz_groups < 1) {
|
|
|
|
rules->sz_groups = 16;
|
|
|
|
rules->num_groups = 0;
|
|
|
|
rules->groups = calloc(rules->sz_groups, sizeof(XkbRF_GroupRec));
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
else if (rules->num_groups >= rules->sz_groups) {
|
2012-03-21 20:55:09 +01:00
|
|
|
rules->sz_groups *= 2;
|
|
|
|
rules->groups = realloc(rules->groups,
|
|
|
|
rules->sz_groups * sizeof(XkbRF_GroupRec));
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
if (!rules->groups) {
|
2012-03-21 20:55:09 +01:00
|
|
|
rules->sz_groups = rules->num_groups = 0;
|
|
|
|
return NULL;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
memset((char *) &rules->groups[rules->num_groups], 0,
|
|
|
|
sizeof(XkbRF_GroupRec));
|
2003-11-14 17:49:22 +01:00
|
|
|
return &rules->groups[rules->num_groups++];
|
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_LoadRules(FILE * file, XkbRF_RulesPtr rules)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
InputLine line;
|
|
|
|
RemapSpec remap;
|
|
|
|
XkbRF_RuleRec trule, *rule;
|
|
|
|
XkbRF_GroupRec tgroup, *group;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (!(rules && file))
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
|
|
|
memset((char *) &remap, 0, sizeof(RemapSpec));
|
|
|
|
memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
InitInputLine(&line);
|
2012-03-21 20:55:09 +01:00
|
|
|
while (GetInputLine(file, &line, TRUE)) {
|
|
|
|
if (CheckLine(&line, &remap, &trule, &tgroup)) {
|
2003-11-14 17:49:22 +01:00
|
|
|
if (tgroup.number) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((group = XkbRF_AddGroup(rules)) != NULL) {
|
|
|
|
*group = tgroup;
|
|
|
|
memset((char *) &tgroup, 0, sizeof(XkbRF_GroupRec));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((rule = XkbRF_AddRule(rules)) != NULL) {
|
|
|
|
*rule = trule;
|
|
|
|
memset((char *) &trule, 0, sizeof(XkbRF_RuleRec));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
line.num_line = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
FreeInputLine(&line);
|
2010-01-15 01:07:38 +01:00
|
|
|
return TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_LoadRulesByName(char *base, char *locale, XkbRF_RulesPtr rules)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
FILE *file;
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
Bool ok;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((!base) || (!rules))
|
|
|
|
return FALSE;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (locale) {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (snprintf(buf, PATH_MAX, "%s-%s", base, locale) >= PATH_MAX)
|
|
|
|
return FALSE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
else {
|
2012-03-21 20:55:09 +01:00
|
|
|
if (strlen(base) + 1 > PATH_MAX)
|
|
|
|
return FALSE;
|
|
|
|
strcpy(buf, base);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
file = fopen(buf, "r");
|
|
|
|
if ((!file) && (locale)) { /* fallback if locale was specified */
|
|
|
|
strcpy(buf, base);
|
|
|
|
file = fopen(buf, "r");
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (!file)
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
|
|
|
ok = XkbRF_LoadRules(file, rules);
|
2003-11-14 16:54:54 +01:00
|
|
|
fclose(file);
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
XkbRF_RulesPtr
|
2008-07-18 15:27:57 +02:00
|
|
|
XkbRF_Create(void)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
return calloc(1, sizeof(XkbRF_RulesRec));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
XkbRF_Free(XkbRF_RulesPtr rules, Bool freeRules)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int i;
|
|
|
|
XkbRF_RulePtr rule;
|
|
|
|
XkbRF_GroupPtr group;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (!rules)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (rules->rules) {
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 0, rule = rules->rules; i < rules->num_rules; i++, rule++) {
|
2013-11-15 14:28:47 +01:00
|
|
|
free((void *) rule->model);
|
|
|
|
free((void *) rule->layout);
|
|
|
|
free((void *) rule->variant);
|
|
|
|
free((void *) rule->option);
|
|
|
|
free((void *) rule->keycodes);
|
|
|
|
free((void *) rule->symbols);
|
|
|
|
free((void *) rule->types);
|
|
|
|
free((void *) rule->compat);
|
|
|
|
free((void *) rule->geometry);
|
2012-03-21 20:55:09 +01:00
|
|
|
memset((char *) rule, 0, sizeof(XkbRF_RuleRec));
|
|
|
|
}
|
|
|
|
free(rules->rules);
|
|
|
|
rules->num_rules = rules->sz_rules = 0;
|
|
|
|
rules->rules = NULL;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
|
|
|
|
if (rules->groups) {
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) {
|
2013-11-15 14:28:47 +01:00
|
|
|
free((void *) group->name);
|
2012-03-21 20:55:09 +01:00
|
|
|
free(group->words);
|
|
|
|
}
|
|
|
|
free(rules->groups);
|
|
|
|
rules->num_groups = 0;
|
|
|
|
rules->groups = NULL;
|
2003-11-14 17:49:22 +01:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
if (freeRules)
|
2012-03-21 20:55:09 +01:00
|
|
|
free(rules);
|
2003-11-14 16:54:54 +01:00
|
|
|
return;
|
|
|
|
}
|