1383 lines
33 KiB
C
1383 lines
33 KiB
C
|
/* $Xorg: maprules.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */
|
||
|
/************************************************************
|
||
|
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
|
||
|
documentation, and that the name of Silicon Graphics not be
|
||
|
used in advertising or publicity pertaining to distribution
|
||
|
of the software without specific prior written permission.
|
||
|
Silicon Graphics makes no representation about the suitability
|
||
|
of this software for any purpose. It is provided "as is"
|
||
|
without any express or implied warranty.
|
||
|
|
||
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||
|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||
|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
||
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
|
||
|
********************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <ctype.h>
|
||
|
#ifndef X_NOT_STDC_ENV
|
||
|
#include <stdlib.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define X_INCLUDE_STRING_H
|
||
|
#define XOS_USE_NO_LOCKING
|
||
|
#include <X11/Xos_r.h>
|
||
|
|
||
|
#ifndef XKB_IN_SERVER
|
||
|
|
||
|
#include <X11/Xproto.h>
|
||
|
#include <X11/Xlib.h>
|
||
|
#include <X11/Xos.h>
|
||
|
#include <X11/Xfuncs.h>
|
||
|
#include <X11/Xatom.h>
|
||
|
#include <X11/keysym.h>
|
||
|
#include <X11/XKBlib.h>
|
||
|
#include <X11/extensions/XKBgeom.h>
|
||
|
#include "XKMformat.h"
|
||
|
#include "XKBfileInt.h"
|
||
|
#include "XKBrules.h"
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define NEED_EVENTS
|
||
|
#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"
|
||
|
#include "XKBstr.h"
|
||
|
#define XKBSRV_NEED_FILE_FUNCS
|
||
|
#include "XKBsrv.h"
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#define PR_DEBUG(s) fprintf(stderr,s)
|
||
|
#define PR_DEBUG1(s,a) fprintf(stderr,s,a)
|
||
|
#else
|
||
|
#define PR_DEBUG(s)
|
||
|
#define PR_DEBUG1(s,a)
|
||
|
#endif
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
#define DFLT_LINE_SIZE 128
|
||
|
|
||
|
typedef struct {
|
||
|
int line_num;
|
||
|
int sz_line;
|
||
|
int num_line;
|
||
|
char buf[DFLT_LINE_SIZE];
|
||
|
char * line;
|
||
|
} InputLine;
|
||
|
|
||
|
static void
|
||
|
#if NeedFunctionPrototypes
|
||
|
InitInputLine(InputLine *line)
|
||
|
#else
|
||
|
InitInputLine(line)
|
||
|
InputLine * line;
|
||
|
#endif
|
||
|
{
|
||
|
line->line_num= 1;
|
||
|
line->num_line= 0;
|
||
|
line->sz_line= DFLT_LINE_SIZE;
|
||
|
line->line= line->buf;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
#if NeedFunctionPrototypes
|
||
|
FreeInputLine(InputLine *line)
|
||
|
#else
|
||
|
FreeInputLine(line)
|
||
|
InputLine *line;
|
||
|
#endif
|
||
|
{
|
||
|
if (line->line!=line->buf)
|
||
|
_XkbFree(line->line);
|
||
|
line->line_num= 1;
|
||
|
line->num_line= 0;
|
||
|
line->sz_line= DFLT_LINE_SIZE;
|
||
|
line->line= line->buf;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
#if NeedFunctionPrototypes
|
||
|
InputLineAddChar(InputLine *line,int ch)
|
||
|
#else
|
||
|
InputLineAddChar(line,ch)
|
||
|
InputLine * line;
|
||
|
int ch;
|
||
|
#endif
|
||
|
{
|
||
|
if (line->num_line>=line->sz_line) {
|
||
|
if (line->line==line->buf) {
|
||
|
line->line= (char *)_XkbAlloc(line->sz_line*2);
|
||
|
memcpy(line->line,line->buf,line->sz_line);
|
||
|
}
|
||
|
else {
|
||
|
line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2);
|
||
|
}
|
||
|
line->sz_line*= 2;
|
||
|
}
|
||
|
line->line[line->num_line++]= ch;
|
||
|
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
|
||
|
#if NeedFunctionPrototypes
|
||
|
GetInputLine(FILE *file,InputLine *line,Bool checkbang)
|
||
|
#else
|
||
|
GetInputLine(file,line,checkbang)
|
||
|
FILE * file;
|
||
|
InputLine * line;
|
||
|
Bool checkbang;
|
||
|
#endif
|
||
|
{
|
||
|
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) {
|
||
|
PR_DEBUG("The '!' legal only at start of line\n");
|
||
|
PR_DEBUG("Line containing '!' ignored\n");
|
||
|
line->num_line= 0;
|
||
|
inComment= 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
ADD_CHAR(line,ch);
|
||
|
}
|
||
|
}
|
||
|
if (ch==EOF)
|
||
|
endOfFile= True;
|
||
|
/* else line->num_line++;*/
|
||
|
}
|
||
|
if ((line->num_line==0)&&(endOfFile))
|
||
|
return False;
|
||
|
ADD_CHAR(line,'\0');
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
#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
|
||
|
#define KEYMAP 9
|
||
|
#define MAX_WORDS 10
|
||
|
|
||
|
#define PART_MASK 0x000F
|
||
|
#define COMPONENT_MASK 0x03F0
|
||
|
|
||
|
static char * cname[MAX_WORDS] = {
|
||
|
"model", "layout", "variant", "option",
|
||
|
"keycodes", "symbols", "types", "compat", "geometry", "keymap"
|
||
|
};
|
||
|
|
||
|
typedef struct _RemapSpec {
|
||
|
int num_remap;
|
||
|
int remap[MAX_WORDS];
|
||
|
} RemapSpec;
|
||
|
|
||
|
typedef struct _FileSpec {
|
||
|
char * name[MAX_WORDS];
|
||
|
struct _FileSpec * pending;
|
||
|
} FileSpec;
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
static void
|
||
|
#if NeedFunctionPrototypes
|
||
|
SetUpRemap(InputLine *line,RemapSpec *remap)
|
||
|
#else
|
||
|
SetUpRemap(line,remap)
|
||
|
InputLine * line;
|
||
|
RemapSpec * remap;
|
||
|
#endif
|
||
|
{
|
||
|
char * tok,*str;
|
||
|
unsigned present;
|
||
|
register int i;
|
||
|
#ifdef DEBUG
|
||
|
Bool found;
|
||
|
#endif
|
||
|
_Xstrtokparams strtok_buf;
|
||
|
|
||
|
present= 0;
|
||
|
str= &line->line[1];
|
||
|
bzero((char *)remap,sizeof(RemapSpec));
|
||
|
while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) {
|
||
|
#ifdef DEBUG
|
||
|
found= False;
|
||
|
#endif
|
||
|
str= NULL;
|
||
|
if (strcmp(tok,"=")==0)
|
||
|
continue;
|
||
|
for (i=0;i<MAX_WORDS;i++) {
|
||
|
if (strcmp(cname[i],tok)==0) {
|
||
|
#ifdef DEBUG
|
||
|
found= True;
|
||
|
#endif
|
||
|
if (present&(1<<i)) {
|
||
|
PR_DEBUG1("Component \"%s\" listed twice\n",tok);
|
||
|
PR_DEBUG("Second definition ignored\n");
|
||
|
break;
|
||
|
}
|
||
|
present|= (1<<i);
|
||
|
remap->remap[remap->num_remap++]= i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#ifdef DEBUG
|
||
|
if (!found) {
|
||
|
fprintf(stderr,"Unknown component \"%s\" ignored\n",tok);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
if ((present&PART_MASK)==0) {
|
||
|
#ifdef DEBUG
|
||
|
unsigned mask= PART_MASK;
|
||
|
fprintf(stderr,"Mapping needs at one of ");
|
||
|
for (i=0;(i<MAX_WORDS)&mask;i++) {
|
||
|
if ((1L<<i)&mask) {
|
||
|
mask&= ~(1L<<i);
|
||
|
if (mask) fprintf(stderr,"\"%s,\" ",cname[i]);
|
||
|
else fprintf(stderr,"or \"%s\"\n",cname[i]);
|
||
|
}
|
||
|
}
|
||
|
fprintf(stderr,"Illegal mapping ignored\n");
|
||
|
#endif
|
||
|
remap->num_remap= 0;
|
||
|
return;
|
||
|
}
|
||
|
if ((present&COMPONENT_MASK)==0) {
|
||
|
PR_DEBUG("Mapping needs at least one component\n");
|
||
|
PR_DEBUG("Illegal mapping ignored\n");
|
||
|
remap->num_remap= 0;
|
||
|
return;
|
||
|
}
|
||
|
if (((present&PART_MASK)&(1<<OPTION))&&
|
||
|
((present&PART_MASK)!=(1<<OPTION))) {
|
||
|
PR_DEBUG("Options cannot appear with other parts\n");
|
||
|
PR_DEBUG("Illegal mapping ignored\n");
|
||
|
remap->num_remap= 0;
|
||
|
return;
|
||
|
}
|
||
|
if (((present&COMPONENT_MASK)&(1<<KEYMAP))&&
|
||
|
((present&COMPONENT_MASK)!=(1<<KEYMAP))) {
|
||
|
PR_DEBUG("Keymap cannot appear with other components\n");
|
||
|
PR_DEBUG("Illegal mapping ignored\n");
|
||
|
remap->num_remap= 0;
|
||
|
return;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
MatchOneOf(char *wanted,char *vals_defined)
|
||
|
#else
|
||
|
MatchOneOf(wanted,vals_defined)
|
||
|
char * wanted;
|
||
|
char * vals_defined;
|
||
|
#endif
|
||
|
{
|
||
|
char *str,*next;
|
||
|
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;
|
||
|
}
|
||
|
return False;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
static Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
CheckLine( InputLine * line,
|
||
|
RemapSpec * remap,
|
||
|
XkbRF_RulePtr rule)
|
||
|
#else
|
||
|
CheckLine(line,remap,rule)
|
||
|
InputLine * line;
|
||
|
RemapSpec * remap;
|
||
|
XkbRF_RulePtr rule;
|
||
|
#endif
|
||
|
{
|
||
|
char * str,*tok;
|
||
|
register int nread;
|
||
|
FileSpec tmp;
|
||
|
_Xstrtokparams strtok_buf;
|
||
|
|
||
|
if (line->line[0]=='!') {
|
||
|
SetUpRemap(line,remap);
|
||
|
return False;
|
||
|
}
|
||
|
if (remap->num_remap==0) {
|
||
|
PR_DEBUG("Must have a mapping before first line of data\n");
|
||
|
PR_DEBUG("Illegal line of data ignored\n");
|
||
|
return False;
|
||
|
}
|
||
|
bzero((char *)&tmp,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) {
|
||
|
PR_DEBUG("Too many words on a line\n");
|
||
|
PR_DEBUG1("Extra word \"%s\" ignored\n",tok);
|
||
|
continue;
|
||
|
}
|
||
|
tmp.name[remap->remap[nread]]= tok;
|
||
|
}
|
||
|
if (nread<remap->num_remap) {
|
||
|
PR_DEBUG("Too few words on a line\n");
|
||
|
PR_DEBUG("line ignored\n");
|
||
|
return False;
|
||
|
}
|
||
|
if ((tmp.name[MODEL]!=NULL)&&(strcmp(tmp.name[MODEL],"*")==0))
|
||
|
tmp.name[MODEL]= NULL;
|
||
|
if ((tmp.name[LAYOUT]!=NULL)&&(strcmp(tmp.name[LAYOUT],"*")==0))
|
||
|
tmp.name[LAYOUT]= NULL;
|
||
|
if ((tmp.name[VARIANT]!=NULL)&&(strcmp(tmp.name[VARIANT],"*")==0))
|
||
|
tmp.name[VARIANT]= NULL;
|
||
|
|
||
|
rule->flags= 0;
|
||
|
if (tmp.name[OPTION])
|
||
|
rule->flags|= XkbRF_Delayed|XkbRF_Append;
|
||
|
rule->model= _XkbDupString(tmp.name[MODEL]);
|
||
|
rule->layout= _XkbDupString(tmp.name[LAYOUT]);
|
||
|
rule->variant= _XkbDupString(tmp.name[VARIANT]);
|
||
|
rule->option= _XkbDupString(tmp.name[OPTION]);
|
||
|
|
||
|
rule->keycodes= _XkbDupString(tmp.name[KEYCODES]);
|
||
|
rule->symbols= _XkbDupString(tmp.name[SYMBOLS]);
|
||
|
rule->types= _XkbDupString(tmp.name[TYPES]);
|
||
|
rule->compat= _XkbDupString(tmp.name[COMPAT]);
|
||
|
rule->geometry= _XkbDupString(tmp.name[GEOMETRY]);
|
||
|
rule->keymap= _XkbDupString(tmp.name[KEYMAP]);
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
#if NeedFunctionPrototypes
|
||
|
_Concat(char *str1,char *str2)
|
||
|
#else
|
||
|
_Concat(str1,str2)
|
||
|
char * str1;
|
||
|
char * str2;
|
||
|
#endif
|
||
|
{
|
||
|
int len;
|
||
|
|
||
|
if ((!str1)||(!str2))
|
||
|
return str1;
|
||
|
len= strlen(str1)+strlen(str2)+1;
|
||
|
str1= _XkbTypedRealloc(str1,len,char);
|
||
|
if (str1)
|
||
|
strcat(str1,str2);
|
||
|
return str1;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_ApplyRule( XkbRF_RulePtr rule,
|
||
|
XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_ApplyRule(rule,names)
|
||
|
XkbRF_RulePtr rule;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */
|
||
|
if ((rule->flags&XkbRF_Append)==0) {
|
||
|
if ((names->keycodes==NULL)&&(rule->keycodes!=NULL))
|
||
|
names->keycodes= _XkbDupString(rule->keycodes);
|
||
|
|
||
|
if ((names->symbols==NULL)&&(rule->symbols!=NULL))
|
||
|
names->symbols= _XkbDupString(rule->symbols);
|
||
|
|
||
|
if ((names->types==NULL)&&(rule->types!=NULL))
|
||
|
names->types= _XkbDupString(rule->types);
|
||
|
|
||
|
if ((names->compat==NULL)&&(rule->compat!=NULL))
|
||
|
names->compat= _XkbDupString(rule->compat);
|
||
|
|
||
|
if ((names->geometry==NULL)&&(rule->geometry!=NULL))
|
||
|
names->geometry= _XkbDupString(rule->geometry);
|
||
|
|
||
|
if ((names->keymap==NULL)&&(rule->keymap!=NULL))
|
||
|
names->keymap= _XkbDupString(rule->keymap);
|
||
|
}
|
||
|
else {
|
||
|
if (rule->keycodes)
|
||
|
names->keycodes= _Concat(names->keycodes,rule->keycodes);
|
||
|
if (rule->symbols)
|
||
|
names->symbols= _Concat(names->symbols,rule->symbols);
|
||
|
if (rule->types)
|
||
|
names->types= _Concat(names->types,rule->types);
|
||
|
if (rule->compat)
|
||
|
names->compat= _Concat(names->compat,rule->compat);
|
||
|
if (rule->geometry)
|
||
|
names->geometry= _Concat(names->geometry,rule->geometry);
|
||
|
if (rule->keymap)
|
||
|
names->keymap= _Concat(names->keymap,rule->keymap);
|
||
|
}
|
||
|
return (names->keycodes && names->symbols && names->types &&
|
||
|
names->compat && names->geometry ) || names->keymap;
|
||
|
}
|
||
|
|
||
|
#define CHECK_MATCH(r,d) ((((r)[0]=='?')&&((r)[1]=='\0'))||(strcmp(r,d)==0))
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_CheckApplyRule( XkbRF_RulePtr rule,
|
||
|
XkbRF_VarDefsPtr defs,
|
||
|
XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_CheckApplyRule(rule,defs,names)
|
||
|
XkbRF_RulePtr rule;
|
||
|
XkbRF_VarDefsPtr defs;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
if (rule->model!=NULL) {
|
||
|
if ((!defs->model)||(!CHECK_MATCH(rule->model,defs->model)))
|
||
|
return False;
|
||
|
}
|
||
|
if (rule->layout!=NULL) {
|
||
|
if ((!defs->layout)||(!CHECK_MATCH(rule->layout,defs->layout)))
|
||
|
return False;
|
||
|
}
|
||
|
if (rule->variant!=NULL) {
|
||
|
if ((!defs->variant)||(!CHECK_MATCH(rule->variant,defs->variant)))
|
||
|
return False;
|
||
|
}
|
||
|
if (rule->option!=NULL) {
|
||
|
if ((!defs->options)||(!MatchOneOf(rule->option,defs->options)))
|
||
|
return False;
|
||
|
}
|
||
|
|
||
|
if ((!rule->option)&&
|
||
|
((!rule->model)||(!rule->layout)||(!rule->variant))) {
|
||
|
/* partial map -- partial maps are applied in the order they */
|
||
|
/* appear, but all partial maps come before any options. */
|
||
|
rule->flags|= XkbRF_PendingMatch;
|
||
|
return False;
|
||
|
}
|
||
|
/* exact match, apply it now */
|
||
|
return XkbRF_ApplyRule(rule,names);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_ClearPartialMatches(rules)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
register int i;
|
||
|
XkbRF_RulePtr rule;
|
||
|
|
||
|
for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
|
||
|
rule->flags&= ~XkbRF_PendingMatch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_ApplyPartialMatches(rules,names)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
int i;
|
||
|
XkbRF_RulePtr rule;
|
||
|
Bool complete;
|
||
|
|
||
|
complete= False;
|
||
|
for (rule=rules->rules,i=0;(i<rules->num_rules)&&(!complete);i++,rule++) {
|
||
|
if ((rule->flags&XkbRF_PendingMatch)==0)
|
||
|
continue;
|
||
|
complete= XkbRF_ApplyRule(rule,names);
|
||
|
}
|
||
|
return complete;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_CheckApplyDelayedRules( XkbRF_RulesPtr rules,
|
||
|
XkbRF_VarDefsPtr defs,
|
||
|
XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_CheckApplyDelayedRules(rules,defs,names)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
XkbRF_VarDefsPtr defs;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
int i;
|
||
|
XkbRF_RulePtr rule;
|
||
|
|
||
|
for (rule=rules->rules,i=0;(i<rules->num_rules);i++,rule++) {
|
||
|
if ((rule->flags&XkbRF_Delayed)==0)
|
||
|
continue;
|
||
|
XkbRF_CheckApplyRule(rule,defs,names);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_CheckApplyRules( XkbRF_RulesPtr rules,
|
||
|
XkbRF_VarDefsPtr defs,
|
||
|
XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_CheckApplyRules(rules,defs,names)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
XkbRF_VarDefsPtr defs;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
int i;
|
||
|
XkbRF_RulePtr rule;
|
||
|
Bool complete;
|
||
|
|
||
|
complete= False;
|
||
|
for (rule=rules->rules,i=0;(i<rules->num_rules)&&(!complete);i++,rule++) {
|
||
|
if ((rule->flags&XkbRF_Delayed)!=0)
|
||
|
continue;
|
||
|
complete= XkbRF_CheckApplyRule(rule,defs,names);
|
||
|
}
|
||
|
return complete;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
char *
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_SubstituteVars(char *name,XkbRF_VarDefsPtr defs)
|
||
|
#else
|
||
|
XkbRF_SubstituteVars(name,defs)
|
||
|
char * name;
|
||
|
XkbRF_VarDefsPtr defs;
|
||
|
#endif
|
||
|
{
|
||
|
char *str,*outstr,*orig;
|
||
|
int len;
|
||
|
|
||
|
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++;
|
||
|
}
|
||
|
|
||
|
if ((str[1]=='l')&&defs->layout)
|
||
|
len+= strlen(defs->layout)+extra_len;
|
||
|
else if ((str[1]=='m')&&defs->model)
|
||
|
len+= strlen(defs->model)+extra_len;
|
||
|
else if ((str[1]=='v')&&defs->variant)
|
||
|
len+= strlen(defs->variant)+extra_len;
|
||
|
if ((pfx=='(')&&(str[2]==')')) {
|
||
|
str++;
|
||
|
}
|
||
|
str= index(&str[1],'%');
|
||
|
}
|
||
|
name= (char *)_XkbAlloc(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++;
|
||
|
}
|
||
|
else pfx= '\0';
|
||
|
|
||
|
if ((str[0]=='l')&&(defs->layout)) {
|
||
|
if (pfx) *outstr++= pfx;
|
||
|
strcpy(outstr,defs->layout);
|
||
|
outstr+= strlen(defs->layout);
|
||
|
if (sfx) *outstr++= sfx;
|
||
|
}
|
||
|
else if ((str[0]=='m')&&(defs->model)) {
|
||
|
if (pfx) *outstr++= pfx;
|
||
|
strcpy(outstr,defs->model);
|
||
|
outstr+= strlen(defs->model);
|
||
|
if (sfx) *outstr++= sfx;
|
||
|
}
|
||
|
else if ((str[0]=='v')&&(defs->variant)) {
|
||
|
if (pfx) *outstr++= pfx;
|
||
|
strcpy(outstr,defs->variant);
|
||
|
outstr+= strlen(defs->variant);
|
||
|
if (sfx) *outstr++= sfx;
|
||
|
}
|
||
|
str++;
|
||
|
if ((pfx=='(')&&(str[0]==')'))
|
||
|
str++;
|
||
|
}
|
||
|
else {
|
||
|
*outstr++= *str++;
|
||
|
}
|
||
|
}
|
||
|
*outstr++= '\0';
|
||
|
if (orig!=name)
|
||
|
_XkbFree(orig);
|
||
|
return name;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_GetComponents( XkbRF_RulesPtr rules,
|
||
|
XkbRF_VarDefsPtr defs,
|
||
|
XkbComponentNamesPtr names)
|
||
|
#else
|
||
|
XkbRF_GetComponents(rules,defs,names)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
XkbRF_VarDefsPtr defs;
|
||
|
XkbComponentNamesPtr names;
|
||
|
#endif
|
||
|
{
|
||
|
Bool complete;
|
||
|
|
||
|
bzero((char *)names,sizeof(XkbComponentNamesRec));
|
||
|
XkbRF_ClearPartialMatches(rules);
|
||
|
complete= XkbRF_CheckApplyRules(rules,defs,names);
|
||
|
if (!complete)
|
||
|
complete= XkbRF_ApplyPartialMatches(rules,names);
|
||
|
XkbRF_CheckApplyDelayedRules(rules,defs,names);
|
||
|
if (names->keycodes)
|
||
|
names->keycodes= XkbRF_SubstituteVars(names->keycodes,defs);
|
||
|
if (names->symbols)
|
||
|
names->symbols= XkbRF_SubstituteVars(names->symbols,defs);
|
||
|
if (names->types)
|
||
|
names->types= XkbRF_SubstituteVars(names->types,defs);
|
||
|
if (names->compat)
|
||
|
names->compat= XkbRF_SubstituteVars(names->compat,defs);
|
||
|
if (names->geometry)
|
||
|
names->geometry= XkbRF_SubstituteVars(names->geometry,defs);
|
||
|
if (names->keymap)
|
||
|
names->keymap= XkbRF_SubstituteVars(names->keymap,defs);
|
||
|
return (names->keycodes && names->symbols && names->types &&
|
||
|
names->compat && names->geometry ) || names->keymap;
|
||
|
}
|
||
|
|
||
|
XkbRF_RulePtr
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_AddRule(XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_AddRule(rules)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
if (rules->sz_rules<1) {
|
||
|
rules->sz_rules= 16;
|
||
|
rules->num_rules= 0;
|
||
|
rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec);
|
||
|
}
|
||
|
else if (rules->num_rules>=rules->sz_rules) {
|
||
|
rules->sz_rules*= 2;
|
||
|
rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules,
|
||
|
XkbRF_RuleRec);
|
||
|
}
|
||
|
if (!rules->rules) {
|
||
|
rules->sz_rules= rules->num_rules= 0;
|
||
|
#ifdef DEBUG
|
||
|
fprintf(stderr,"Allocation failure in XkbRF_AddRule\n");
|
||
|
#endif
|
||
|
return NULL;
|
||
|
}
|
||
|
bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec));
|
||
|
return &rules->rules[rules->num_rules++];
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_LoadRules(file,rules)
|
||
|
FILE * file;
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
InputLine line;
|
||
|
RemapSpec remap;
|
||
|
XkbRF_RuleRec trule,*rule;
|
||
|
|
||
|
if (!(rules && file))
|
||
|
return False;
|
||
|
bzero((char *)&remap,sizeof(RemapSpec));
|
||
|
InitInputLine(&line);
|
||
|
while (GetInputLine(file,&line,True)) {
|
||
|
if (CheckLine(&line,&remap,&trule)) {
|
||
|
if ((rule= XkbRF_AddRule(rules))!=NULL) {
|
||
|
*rule= trule;
|
||
|
bzero((char *)&trule,sizeof(XkbRF_RuleRec));
|
||
|
}
|
||
|
}
|
||
|
line.num_line= 0;
|
||
|
}
|
||
|
FreeInputLine(&line);
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_LoadRulesByName(base,locale,rules)
|
||
|
char * base;
|
||
|
char * locale;
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
FILE * file;
|
||
|
char buf[PATH_MAX];
|
||
|
Bool ok;
|
||
|
|
||
|
if ((!base)||(!rules))
|
||
|
return False;
|
||
|
if (locale) {
|
||
|
if (strlen(base)+strlen(locale)+2 > PATH_MAX)
|
||
|
return False;
|
||
|
sprintf(buf,"%s-%s", base, locale);
|
||
|
}
|
||
|
else {
|
||
|
if (strlen(base)+1 > PATH_MAX)
|
||
|
return False;
|
||
|
strcpy(buf,base);
|
||
|
}
|
||
|
|
||
|
file= fopen(buf, "r");
|
||
|
if ((!file)&&(locale)) { /* fallback if locale was specified */
|
||
|
strcpy(buf,base);
|
||
|
file= fopen(buf, "r");
|
||
|
}
|
||
|
if (!file)
|
||
|
return False;
|
||
|
ok= XkbRF_LoadRules(file,rules);
|
||
|
fclose(file);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
#define HEAD_NONE 0
|
||
|
#define HEAD_MODEL 1
|
||
|
#define HEAD_LAYOUT 2
|
||
|
#define HEAD_VARIANT 3
|
||
|
#define HEAD_OPTION 4
|
||
|
#define HEAD_EXTRA 5
|
||
|
|
||
|
XkbRF_VarDescPtr
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars)
|
||
|
#else
|
||
|
XkbRF_AddVarDesc(vars)
|
||
|
XkbRF_DescribeVarsPtr vars;
|
||
|
#endif
|
||
|
{
|
||
|
if (vars->sz_desc<1) {
|
||
|
vars->sz_desc= 16;
|
||
|
vars->num_desc= 0;
|
||
|
vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec);
|
||
|
}
|
||
|
else if (vars->num_desc>=vars->sz_desc) {
|
||
|
vars->sz_desc*= 2;
|
||
|
vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec);
|
||
|
}
|
||
|
if (!vars->desc) {
|
||
|
vars->sz_desc= vars->num_desc= 0;
|
||
|
PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
vars->desc[vars->num_desc].name= NULL;
|
||
|
vars->desc[vars->num_desc].desc= NULL;
|
||
|
return &vars->desc[vars->num_desc++];
|
||
|
}
|
||
|
|
||
|
XkbRF_VarDescPtr
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from)
|
||
|
#else
|
||
|
XkbRF_AddVarDescCopy(vars,from)
|
||
|
XkbRF_DescribeVarsPtr vars;
|
||
|
XkbRF_VarDescPtr from;
|
||
|
#endif
|
||
|
{
|
||
|
XkbRF_VarDescPtr nd;
|
||
|
|
||
|
if ((nd=XkbRF_AddVarDesc(vars))!=NULL) {
|
||
|
nd->name= _XkbDupString(from->name);
|
||
|
nd->desc= _XkbDupString(from->desc);
|
||
|
}
|
||
|
return nd;
|
||
|
}
|
||
|
|
||
|
XkbRF_DescribeVarsPtr
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name)
|
||
|
#else
|
||
|
XkbRF_AddVarToDescribe(rules,name)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
char * name;
|
||
|
#endif
|
||
|
{
|
||
|
if (rules->sz_extra<1) {
|
||
|
rules->num_extra= 0;
|
||
|
rules->sz_extra= 1;
|
||
|
rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *);
|
||
|
rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec);
|
||
|
}
|
||
|
else if (rules->num_extra>=rules->sz_extra) {
|
||
|
rules->sz_extra*= 2;
|
||
|
rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra,
|
||
|
char *);
|
||
|
rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra,
|
||
|
XkbRF_DescribeVarsRec);
|
||
|
}
|
||
|
if ((!rules->extra_names)||(!rules->extra)) {
|
||
|
PR_DEBUG("allocation error in extra parts\n");
|
||
|
rules->sz_extra= rules->num_extra= 0;
|
||
|
rules->extra_names= NULL;
|
||
|
rules->extra= NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
rules->extra_names[rules->num_extra]= _XkbDupString(name);
|
||
|
bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec));
|
||
|
return &rules->extra[rules->num_extra++];
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_LoadDescriptions(file,rules)
|
||
|
FILE * file;
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
InputLine line;
|
||
|
XkbRF_VarDescRec tmp;
|
||
|
char *tok;
|
||
|
int len,headingtype,extra_ndx;
|
||
|
|
||
|
bzero((char *)&tmp, sizeof(XkbRF_VarDescRec));
|
||
|
headingtype = HEAD_NONE;
|
||
|
InitInputLine(&line);
|
||
|
for ( ; GetInputLine(file,&line,False); line.num_line= 0) {
|
||
|
if (line.line[0]=='!') {
|
||
|
tok = strtok(&(line.line[1]), " \t");
|
||
|
if (!_XkbStrCaseCmp(tok,"model"))
|
||
|
headingtype = HEAD_MODEL;
|
||
|
else if (!_XkbStrCaseCmp(tok,"layout"))
|
||
|
headingtype = HEAD_LAYOUT;
|
||
|
else if (!_XkbStrCaseCmp(tok,"variant"))
|
||
|
headingtype = HEAD_VARIANT;
|
||
|
else if (!_XkbStrCaseCmp(tok,"option"))
|
||
|
headingtype = HEAD_OPTION;
|
||
|
else {
|
||
|
int i;
|
||
|
headingtype = HEAD_EXTRA;
|
||
|
extra_ndx= -1;
|
||
|
for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) {
|
||
|
if (!_XkbStrCaseCmp(tok,rules->extra_names[i]))
|
||
|
extra_ndx= i;
|
||
|
}
|
||
|
if (extra_ndx<0) {
|
||
|
XkbRF_DescribeVarsPtr var;
|
||
|
PR_DEBUG1("Extra heading \"%s\" encountered\n",tok);
|
||
|
var= XkbRF_AddVarToDescribe(rules,tok);
|
||
|
if (var)
|
||
|
extra_ndx= var-rules->extra;
|
||
|
else headingtype= HEAD_NONE;
|
||
|
}
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (headingtype == HEAD_NONE) {
|
||
|
PR_DEBUG("Must have a heading before first line of data\n");
|
||
|
PR_DEBUG("Illegal line of data ignored\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
len = strlen(line.line);
|
||
|
if ((tmp.name= strtok(line.line, " \t")) == NULL) {
|
||
|
PR_DEBUG("Huh? No token on line\n");
|
||
|
PR_DEBUG("Illegal line of data ignored\n");
|
||
|
continue;
|
||
|
}
|
||
|
if (strlen(tmp.name) == len) {
|
||
|
PR_DEBUG("No description found\n");
|
||
|
PR_DEBUG("Illegal line of data ignored\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
tok = line.line + strlen(tmp.name) + 1;
|
||
|
while ((*tok!='\n')&&isspace(*tok))
|
||
|
tok++;
|
||
|
if (*tok == '\0') {
|
||
|
PR_DEBUG("No description found\n");
|
||
|
PR_DEBUG("Illegal line of data ignored\n");
|
||
|
continue;
|
||
|
}
|
||
|
tmp.desc= tok;
|
||
|
switch (headingtype) {
|
||
|
case HEAD_MODEL:
|
||
|
XkbRF_AddVarDescCopy(&rules->models,&tmp);
|
||
|
break;
|
||
|
case HEAD_LAYOUT:
|
||
|
XkbRF_AddVarDescCopy(&rules->layouts,&tmp);
|
||
|
break;
|
||
|
case HEAD_VARIANT:
|
||
|
XkbRF_AddVarDescCopy(&rules->variants,&tmp);
|
||
|
break;
|
||
|
case HEAD_OPTION:
|
||
|
XkbRF_AddVarDescCopy(&rules->options,&tmp);
|
||
|
break;
|
||
|
case HEAD_EXTRA:
|
||
|
XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
FreeInputLine(&line);
|
||
|
if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) &&
|
||
|
(rules->variants.num_desc==0) && (rules->options.num_desc==0) &&
|
||
|
(rules->num_extra==0)) {
|
||
|
return False;
|
||
|
}
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules)
|
||
|
#else
|
||
|
XkbRF_LoadDescriptionsByName(base,locale,rules)
|
||
|
char * base;
|
||
|
char * locale;
|
||
|
XkbRF_RulesPtr rules;
|
||
|
#endif
|
||
|
{
|
||
|
FILE * file;
|
||
|
char buf[PATH_MAX];
|
||
|
Bool ok;
|
||
|
|
||
|
if ((!base)||(!rules))
|
||
|
return False;
|
||
|
if (locale) {
|
||
|
if (strlen(base)+strlen(locale)+6 > PATH_MAX)
|
||
|
return False;
|
||
|
sprintf(buf,"%s-%s.lst", base, locale);
|
||
|
}
|
||
|
else {
|
||
|
if (strlen(base)+5 > PATH_MAX)
|
||
|
return False;
|
||
|
sprintf(buf,"%s.lst", base);
|
||
|
}
|
||
|
|
||
|
file= fopen(buf, "r");
|
||
|
if ((!file)&&(locale)) { /* fallback if locale was specified */
|
||
|
sprintf(buf,"%s.lst", base);
|
||
|
|
||
|
file= fopen(buf, "r");
|
||
|
}
|
||
|
if (!file)
|
||
|
return False;
|
||
|
ok= XkbRF_LoadDescriptions(file,rules);
|
||
|
fclose(file);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
XkbRF_RulesPtr
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules)
|
||
|
#else
|
||
|
XkbRF_Load(base,locale,wantDesc,wantRules)
|
||
|
char *base;
|
||
|
char *locale;
|
||
|
Bool wantDesc;
|
||
|
Bool wantRules;
|
||
|
#endif
|
||
|
{
|
||
|
XkbRF_RulesPtr rules;
|
||
|
|
||
|
if ((!base)||((!wantDesc)&&(!wantRules)))
|
||
|
return NULL;
|
||
|
if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL)
|
||
|
return NULL;
|
||
|
if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) {
|
||
|
XkbRF_Free(rules,True);
|
||
|
return NULL;
|
||
|
}
|
||
|
if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) {
|
||
|
XkbRF_Free(rules,True);
|
||
|
return NULL;
|
||
|
}
|
||
|
return rules;
|
||
|
}
|
||
|
|
||
|
XkbRF_RulesPtr
|
||
|
XkbRF_Create(int szRules,int szExtra)
|
||
|
{
|
||
|
XkbRF_RulesPtr rules;
|
||
|
|
||
|
if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL)
|
||
|
return NULL;
|
||
|
if (szRules>0) {
|
||
|
rules->sz_rules= szRules;
|
||
|
rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec);
|
||
|
if (!rules->rules) {
|
||
|
_XkbFree(rules);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
if (szExtra>0) {
|
||
|
rules->sz_extra= szExtra;
|
||
|
rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec);
|
||
|
if (!rules->extra) {
|
||
|
if (rules->rules)
|
||
|
_XkbFree(rules->rules);
|
||
|
_XkbFree(rules);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
return rules;
|
||
|
}
|
||
|
|
||
|
/***====================================================================***/
|
||
|
|
||
|
static void
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var)
|
||
|
#else
|
||
|
XkbRF_ClearVarDescriptions(var)
|
||
|
XkbRF_DescribeVarsPtr var;
|
||
|
#endif
|
||
|
{
|
||
|
register int i;
|
||
|
|
||
|
for (i=0;i<var->num_desc;i++) {
|
||
|
if (var->desc[i].name)
|
||
|
_XkbFree(var->desc[i].name);
|
||
|
if (var->desc[i].desc)
|
||
|
_XkbFree(var->desc[i].desc);
|
||
|
var->desc[i].name= var->desc[i].desc= NULL;
|
||
|
}
|
||
|
if (var->desc)
|
||
|
_XkbFree(var->desc);
|
||
|
var->desc= NULL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules)
|
||
|
#else
|
||
|
XkbRF_Free(rules,freeRules)
|
||
|
XkbRF_RulesPtr rules;
|
||
|
Bool freeRules;
|
||
|
#endif
|
||
|
{
|
||
|
int i;
|
||
|
XkbRF_RulePtr rule;
|
||
|
|
||
|
if (!rules)
|
||
|
return;
|
||
|
XkbRF_ClearVarDescriptions(&rules->models);
|
||
|
XkbRF_ClearVarDescriptions(&rules->layouts);
|
||
|
XkbRF_ClearVarDescriptions(&rules->variants);
|
||
|
XkbRF_ClearVarDescriptions(&rules->options);
|
||
|
if (rules->extra) {
|
||
|
for (i = 0; i < rules->num_extra; i++) {
|
||
|
XkbRF_ClearVarDescriptions(&rules->extra[i]);
|
||
|
}
|
||
|
_XkbFree(rules->extra);
|
||
|
rules->num_extra= rules->sz_extra= 0;
|
||
|
rules->extra= NULL;
|
||
|
}
|
||
|
if (rules->rules) {
|
||
|
for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
|
||
|
if (rule->model) _XkbFree(rule->model);
|
||
|
if (rule->layout) _XkbFree(rule->layout);
|
||
|
if (rule->variant) _XkbFree(rule->variant);
|
||
|
if (rule->option) _XkbFree(rule->option);
|
||
|
if (rule->keycodes) _XkbFree(rule->keycodes);
|
||
|
if (rule->symbols) _XkbFree(rule->symbols);
|
||
|
if (rule->types) _XkbFree(rule->types);
|
||
|
if (rule->compat) _XkbFree(rule->compat);
|
||
|
if (rule->geometry) _XkbFree(rule->geometry);
|
||
|
if (rule->keymap) _XkbFree(rule->keymap);
|
||
|
bzero((char *)rule,sizeof(XkbRF_RuleRec));
|
||
|
}
|
||
|
_XkbFree(rules->rules);
|
||
|
rules->num_rules= rules->sz_rules= 0;
|
||
|
rules->rules= NULL;
|
||
|
}
|
||
|
if (freeRules)
|
||
|
_XkbFree(rules);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#ifndef XKB_IN_SERVER
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn)
|
||
|
#else
|
||
|
XkbRF_GetNamesProp(dpy,rf_rtrn,vd_rtrn)
|
||
|
Display * dpy;
|
||
|
char ** rf_rtrn;
|
||
|
XkbRF_VarDefsPtr vd_rtrn;
|
||
|
#endif
|
||
|
{
|
||
|
Atom rules_atom,actual_type;
|
||
|
int fmt;
|
||
|
unsigned long nitems,bytes_after;
|
||
|
char *data,*out;
|
||
|
Status rtrn;
|
||
|
|
||
|
rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,True);
|
||
|
if (rules_atom==None) /* property cannot exist */
|
||
|
return False;
|
||
|
rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy),rules_atom,
|
||
|
0L,_XKB_RF_NAMES_PROP_MAXLEN,False,
|
||
|
XA_STRING,&actual_type,
|
||
|
&fmt,&nitems,&bytes_after,
|
||
|
(unsigned char **)&data);
|
||
|
if (rtrn!=Success)
|
||
|
return False;
|
||
|
if (rf_rtrn)
|
||
|
*rf_rtrn= NULL;
|
||
|
(void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec));
|
||
|
if ((bytes_after>0)||(actual_type!=XA_STRING)||(fmt!=8)) {
|
||
|
if (data) XFree(data);
|
||
|
return (fmt==0?True:False);
|
||
|
}
|
||
|
|
||
|
out= data;
|
||
|
if (out && (*out) && rf_rtrn)
|
||
|
*rf_rtrn= _XkbDupString(out);
|
||
|
out+=strlen(out)+1;
|
||
|
|
||
|
if ((out-data)<nitems) {
|
||
|
if (*out)
|
||
|
vd_rtrn->model= _XkbDupString(out);
|
||
|
out+=strlen(out)+1;
|
||
|
}
|
||
|
|
||
|
if ((out-data)<nitems) {
|
||
|
if (*out)
|
||
|
vd_rtrn->layout= _XkbDupString(out);
|
||
|
out+=strlen(out)+1;
|
||
|
}
|
||
|
|
||
|
if ((out-data)<nitems) {
|
||
|
if (*out)
|
||
|
vd_rtrn->variant= _XkbDupString(out);
|
||
|
out+=strlen(out)+1;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((out-data)<nitems) {
|
||
|
if (*out)
|
||
|
vd_rtrn->options= _XkbDupString(out);
|
||
|
out+=strlen(out)+1;
|
||
|
}
|
||
|
XFree(data);
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
#if NeedFunctionPrototypes
|
||
|
XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs)
|
||
|
#else
|
||
|
XkbRF_SetNamesProp(dpy,rules_file,var_defs)
|
||
|
Display * dpy;
|
||
|
char * rules_file;
|
||
|
XkbRF_VarDefsPtr var_defs;
|
||
|
#endif
|
||
|
{
|
||
|
int len,out;
|
||
|
Atom name;
|
||
|
char * pval;
|
||
|
|
||
|
len= (rules_file?strlen(rules_file):0);
|
||
|
len+= (var_defs->model?strlen(var_defs->model):0);
|
||
|
len+= (var_defs->layout?strlen(var_defs->layout):0);
|
||
|
len+= (var_defs->variant?strlen(var_defs->variant):0);
|
||
|
len+= (var_defs->options?strlen(var_defs->options):0);
|
||
|
if (len<1)
|
||
|
return True;
|
||
|
|
||
|
len+= 5; /* trailing NULs */
|
||
|
|
||
|
name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,False);
|
||
|
if (name==None) { /* should never happen */
|
||
|
_XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom);
|
||
|
return False;
|
||
|
}
|
||
|
pval= (char *)_XkbAlloc(len);
|
||
|
if (!pval) {
|
||
|
_XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len);
|
||
|
return False;
|
||
|
}
|
||
|
out= 0;
|
||
|
if (rules_file) {
|
||
|
strcpy(&pval[out],rules_file);
|
||
|
out+= strlen(rules_file);
|
||
|
}
|
||
|
pval[out++]= '\0';
|
||
|
if (var_defs->model) {
|
||
|
strcpy(&pval[out],var_defs->model);
|
||
|
out+= strlen(var_defs->model);
|
||
|
}
|
||
|
pval[out++]= '\0';
|
||
|
if (var_defs->layout) {
|
||
|
strcpy(&pval[out],var_defs->layout);
|
||
|
out+= strlen(var_defs->layout);
|
||
|
}
|
||
|
pval[out++]= '\0';
|
||
|
if (var_defs->variant) {
|
||
|
strcpy(&pval[out],var_defs->variant);
|
||
|
out+= strlen(var_defs->variant);
|
||
|
}
|
||
|
pval[out++]= '\0';
|
||
|
if (var_defs->options) {
|
||
|
strcpy(&pval[out],var_defs->options);
|
||
|
out+= strlen(var_defs->options);
|
||
|
}
|
||
|
pval[out++]= '\0';
|
||
|
if (out!=len) {
|
||
|
_XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out);
|
||
|
_XkbFree(pval);
|
||
|
return False;
|
||
|
}
|
||
|
|
||
|
XChangeProperty(dpy,DefaultRootWindow(dpy),name,XA_STRING,8,PropModeReplace,
|
||
|
(unsigned char *)pval,len);
|
||
|
_XkbFree(pval);
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
#endif
|