From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libxkbfile/src/maprules.c | 2970 ++++++++++++++++++++++----------------------- 1 file changed, 1485 insertions(+), 1485 deletions(-) (limited to 'libxkbfile/src/maprules.c') diff --git a/libxkbfile/src/maprules.c b/libxkbfile/src/maprules.c index 68b202d98..29f13a447 100644 --- a/libxkbfile/src/maprules.c +++ b/libxkbfile/src/maprules.c @@ -1,1485 +1,1485 @@ -/************************************************************ - 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. - - ********************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#elif defined(HAVE_CONFIG_H) -#include -#endif - -#include -#include -#include - -#define X_INCLUDE_STRING_H -#define XOS_USE_NO_LOCKING -#include - -#ifndef XKB_IN_SERVER - -#include -#include -#include -#include -#include -#include -#include -#include -#include "XKMformat.h" -#include "XKBfileInt.h" -#include "XKBrules.h" - -#else - -#include -#include -#include -#include -#include -#include -#include "misc.h" -#include "inputstr.h" -#include "dix.h" -#include -#define XKBSRV_NEED_FILE_FUNCS -#include - -#endif - -#ifdef DEBUG -#define PR_DEBUG(s) fprintf(stderr,s) -#define PR_DEBUG1(s,a) fprintf(stderr,s,a) -#define PR_DEBUG2(s,a,b) fprintf(stderr,s,a,b) -#else -#define PR_DEBUG(s) -#define PR_DEBUG1(s,a) -#define PR_DEBUG2(s,a,b) -#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 -InitInputLine(InputLine *line) -{ - line->line_num= 1; - line->num_line= 0; - line->sz_line= DFLT_LINE_SIZE; - line->line= line->buf; - return; -} - -static void -FreeInputLine(InputLine *line) -{ - 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 -InputLineAddChar(InputLine *line,int ch) -{ - 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)) - -#ifdef HAVE_UNLOCKED_STDIO -#undef getc -#define getc(x) getc_unlocked(x) -#else -#define flockfile(x) do {} while (0) -#define funlockfile(x) do {} while (0) -#endif - -static Bool -GetInputLine(FILE *file,InputLine *line,Bool checkbang) -{ -int ch; -Bool endOfFile,spacePending,slashPending,inComment; - - endOfFile= False; - flockfile(file); - 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++;*/ - } - funlockfile(file); - 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 number; - int num_remap; - struct { - int word; - int index; - } remap[MAX_WORDS]; -} RemapSpec; - -typedef struct _FileSpec { - char * name[MAX_WORDS]; - struct _FileSpec * pending; -} FileSpec; - -typedef struct { - char * model; - char * layout[XkbNumKbdGroups+1]; - char * variant[XkbNumKbdGroups+1]; - char * options; -} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; - -#define NDX_BUFF_SIZE 4 - -/***====================================================================***/ - -static char* -get_index(char *str, int *ndx) -{ - 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; - } - strncpy(ndx_buf, str, end - str); - ndx_buf[end - str] = '\0'; - *ndx = atoi(ndx_buf); - return end + 1; -} - -static void -SetUpRemap(InputLine *line,RemapSpec *remap) -{ -char * tok,*str; -unsigned present, l_ndx_present, v_ndx_present; -register int i; -int len, ndx; -_Xstrtokparams strtok_buf; -#ifdef DEBUG -Bool found; -#endif - - - l_ndx_present = v_ndx_present = present= 0; - str= &line->line[1]; - len = remap->number; - bzero((char *)remap,sizeof(RemapSpec)); - remap->number = len; - while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { -#ifdef DEBUG - found= False; -#endif - str= NULL; - if (strcmp(tok,"=")==0) - continue; - for (i=0;i len) { - char *end = get_index(tok+len, &ndx); - if ((i != LAYOUT && i != VARIANT) || - *end != '\0' || ndx == -1) - break; - if (ndx < 1 || ndx > XkbNumKbdGroups) { - PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx); - PR_DEBUG1("Index must be in range 1..%d\n", - XkbNumKbdGroups); - break; - } - } else { - ndx = 0; - } -#ifdef DEBUG - found= True; -#endif - if (present&(1<remap[remap->num_remap].word= i; - remap->remap[remap->num_remap++].index= ndx; - 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 least one of "); - for (i=0; (inum_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&COMPONENT_MASK)&(1<num_remap= 0; - return; - } - remap->number++; - return; -} - -static Bool -MatchOneOf(char *wanted,char *vals_defined) -{ -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 -CheckLine( InputLine * line, - RemapSpec * remap, - XkbRF_RulePtr rule, - XkbRF_GroupPtr group) -{ -char * str,*tok; -register int nread, i; -FileSpec tmp; -_Xstrtokparams strtok_buf; -Bool append = False; - - if (line->line[0]=='!') { - if (line->line[1] == '$' || - (line->line[1] == ' ' && line->line[2] == '$')) { - char *gname = strchr(line->line, '$'); - char *words = strchr(gname, ' '); - if(!words) - return False; - *words++ = '\0'; - for (; *words; words++) { - if (*words != '=' && *words != ' ') - break; - } - if (*words == '\0') - return False; - group->name = _XkbDupString(gname); - group->words = _XkbDupString(words); - for (i = 1, words = group->words; *words; words++) { - if ( *words == ' ') { - *words++ = '\0'; - i++; - } - } - group->number = i; - return True; - } else { - 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].word]= tok; - if (*tok == '+' || *tok == '|') - append = True; - } - if (nreadnum_remap) { - PR_DEBUG1("Too few words on a line: %s\n", line->line); - PR_DEBUG("line ignored\n"); - return False; - } - - rule->flags= 0; - rule->number = remap->number; - if (tmp.name[OPTION]) - rule->flags|= XkbRF_Option; - else if (append) - rule->flags|= XkbRF_Append; - else - rule->flags|= XkbRF_Normal; - 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]); - - rule->layout_num = rule->variant_num = 0; - for (i = 0; i < nread; i++) { - if (remap->remap[i].index) { - 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; - } - } - return True; -} - -static char * -_Concat(char *str1,char *str2) -{ -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; -} - -static void -squeeze_spaces(char *p1) -{ - char *p2; - for (p2 = p1; *p2; p2++) { - *p1 = *p2; - if (*p1 != ' ') p1++; - } - *p1 = '\0'; -} - -static Bool -MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) -{ - - bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec)); - mdefs->model = defs->model; - mdefs->options = _XkbDupString(defs->options); - if (mdefs->options) squeeze_spaces(mdefs->options); - - if (defs->layout) { - if (!strchr(defs->layout, ',')) { - mdefs->layout[0] = defs->layout; - } else { - char *p; - int i; - mdefs->layout[1] = _XkbDupString(defs->layout); - if (mdefs->layout[1] == NULL) - return False; - squeeze_spaces(mdefs->layout[1]); - p = mdefs->layout[1]; - 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; - int i; - mdefs->variant[1] = _XkbDupString(defs->variant); - if (mdefs->variant[1] == NULL) - return False; - squeeze_spaces(mdefs->variant[1]); - p = mdefs->variant[1]; - 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; -} - -static void -FreeMultiDefs(XkbRF_MultiDefsPtr defs) -{ - if (defs->options) _XkbFree(defs->options); - if (defs->layout[1]) _XkbFree(defs->layout[1]); - if (defs->variant[1]) _XkbFree(defs->variant[1]); -} - -static void -Apply(char *src, char **dst) -{ - if (src) { - if (*src == '+' || *src == '!') { - *dst= _Concat(*dst, src); - } else { - if (*dst == NULL) - *dst= _XkbDupString(src); - } - } -} - -static void -XkbRF_ApplyRule( XkbRF_RulePtr rule, - XkbComponentNamesPtr names) -{ - rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ - - Apply(rule->keycodes, &names->keycodes); - Apply(rule->symbols, &names->symbols); - Apply(rule->types, &names->types); - Apply(rule->compat, &names->compat); - Apply(rule->geometry, &names->geometry); - Apply(rule->keymap, &names->keymap); -} - -static Bool -CheckGroup( XkbRF_RulesPtr rules, - char * group_name, - char * name) -{ - 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; -} - -static int -XkbRF_CheckApplyRule( XkbRF_RulePtr rule, - XkbRF_MultiDefsPtr mdefs, - XkbComponentNamesPtr names, - XkbRF_RulesPtr rules) -{ - Bool pending = False; - - if (rule->model != NULL) { - if(mdefs->model == NULL) - return 0; - if (strcmp(rule->model, "*") == 0) { - pending = True; - } else { - if (rule->model[0] == '$') { - if (!CheckGroup(rules, rule->model, mdefs->model)) - return 0; - } else { - if (strcmp(rule->model, mdefs->model) != 0) - return 0; - } - } - } - if (rule->option != NULL) { - if (mdefs->options == NULL) - return 0; - if ((!MatchOneOf(rule->option,mdefs->options))) - return 0; - } - - if (rule->layout != NULL) { - if(mdefs->layout[rule->layout_num] == NULL || - *mdefs->layout[rule->layout_num] == '\0') - return 0; - if (strcmp(rule->layout, "*") == 0) { - pending = True; - } else { - if (rule->layout[0] == '$') { - 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; - } - } - } - if (rule->variant != NULL) { - if (mdefs->variant[rule->variant_num] == NULL || - *mdefs->variant[rule->variant_num] == '\0') - return 0; - if (strcmp(rule->variant, "*") == 0) { - pending = True; - } else { - if (rule->variant[0] == '$') { - 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; - } - } - } - if (pending) { - rule->flags|= XkbRF_PendingMatch; - return rule->number; - } - /* exact match, apply it now */ - XkbRF_ApplyRule(rule,names); - return rule->number; -} - -static void -XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) -{ -register int i; -XkbRF_RulePtr rule; - - for (i=0,rule=rules->rules;inum_rules;i++,rule++) { - rule->flags&= ~XkbRF_PendingMatch; - } -} - -static void -XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) -{ -int i; -XkbRF_RulePtr rule; - - for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { - if ((rule->flags&XkbRF_PendingMatch)==0) - continue; - XkbRF_ApplyRule(rule,names); - } -} - -static void -XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, - XkbRF_MultiDefsPtr mdefs, - XkbComponentNamesPtr names, - int flags) -{ -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--; - } - } -} - -/***====================================================================***/ - -static char * -XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) -{ -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= (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'; - - 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) - _XkbFree(orig); - return name; -} - -/***====================================================================***/ - -Bool -XkbRF_GetComponents( XkbRF_RulesPtr rules, - XkbRF_VarDefsPtr defs, - XkbComponentNamesPtr names) -{ - XkbRF_MultiDefsRec mdefs; - - MakeMultiDefs(&mdefs, defs); - - bzero((char *)names,sizeof(XkbComponentNamesRec)); - XkbRF_ClearPartialMatches(rules); - 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); - XkbRF_ApplyPartialMatches(rules, names); - - if (names->keycodes) - names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); - if (names->symbols) - names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); - if (names->types) - names->types= XkbRF_SubstituteVars(names->types, &mdefs); - if (names->compat) - names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); - if (names->geometry) - names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); - if (names->keymap) - names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs); - - FreeMultiDefs(&mdefs); - return (names->keycodes && names->symbols && names->types && - names->compat && names->geometry ) || names->keymap; -} - -XkbRF_RulePtr -XkbRF_AddRule(XkbRF_RulesPtr rules) -{ - 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++]; -} - -XkbRF_GroupPtr -XkbRF_AddGroup(XkbRF_RulesPtr rules) -{ - if (rules->sz_groups<1) { - rules->sz_groups= 16; - rules->num_groups= 0; - rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec); - } - else if (rules->num_groups >= rules->sz_groups) { - rules->sz_groups *= 2; - rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups, - XkbRF_GroupRec); - } - if (!rules->groups) { - rules->sz_groups= rules->num_groups= 0; - return NULL; - } - - bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec)); - return &rules->groups[rules->num_groups++]; -} - -Bool -XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) -{ -InputLine line; -RemapSpec remap; -XkbRF_RuleRec trule,*rule; -XkbRF_GroupRec tgroup,*group; - - if (!(rules && file)) - return False; - bzero((char *)&remap,sizeof(RemapSpec)); - bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); - InitInputLine(&line); - while (GetInputLine(file,&line,True)) { - if (CheckLine(&line,&remap,&trule,&tgroup)) { - if (tgroup.number) { - if ((group= XkbRF_AddGroup(rules))!=NULL) { - *group= tgroup; - bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); - } - } else { - if ((rule= XkbRF_AddRule(rules))!=NULL) { - *rule= trule; - bzero((char *)&trule,sizeof(XkbRF_RuleRec)); - } - } - } - line.num_line= 0; - } - FreeInputLine(&line); - return True; -} - -Bool -XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) -{ -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 -XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) -{ - 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 -XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) -{ -XkbRF_VarDescPtr nd; - - if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { - nd->name= _XkbDupString(from->name); - nd->desc= _XkbDupString(from->desc); - } - return nd; -} - -XkbRF_DescribeVarsPtr -XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) -{ - 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 -XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) -{ -InputLine line; -XkbRF_VarDescRec tmp; -char *tok; -int len,headingtype,extra_ndx = 0; - - 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 (strcmp(tok,"model") == 0) - headingtype = HEAD_MODEL; - else if (_XkbStrCaseCmp(tok,"layout") == 0) - headingtype = HEAD_LAYOUT; - else if (_XkbStrCaseCmp(tok,"variant") == 0) - headingtype = HEAD_VARIANT; - else if (_XkbStrCaseCmp(tok,"option") == 0) - headingtype = HEAD_OPTION; - else { - int i; - headingtype = HEAD_EXTRA; - extra_ndx= -1; - for (i=0;(inum_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 -XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) -{ -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 -XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) -{ -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 -XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) -{ -register int i; - - for (i=0;inum_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 -XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) -{ -int i; -XkbRF_RulePtr rule; -XkbRF_GroupPtr group; - - 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;inum_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 (rules->groups) { - for (i=0, group=rules->groups;inum_groups;i++,group++) { - if (group->name) _XkbFree(group->name); - if (group->words) _XkbFree(group->words); - } - _XkbFree(rules->groups); - rules->num_groups= 0; - rules->groups= NULL; - } - if (freeRules) - _XkbFree(rules); - return; -} - -#ifndef XKB_IN_SERVER - -Bool -XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn) -{ -Atom rules_atom,actual_type; -int fmt; -unsigned long nitems,bytes_after; -unsigned char *data; -char *out, *end; -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=(char*)data; - end=out+nitems; - if (out && (*out) && rf_rtrn) - *rf_rtrn= _XkbDupString(out); - out+=strlen(out)+1; - - if (outmodel= _XkbDupString(out); - out+=strlen(out)+1; - } - - if (outlayout= _XkbDupString(out); - out+=strlen(out)+1; - } - - if (outvariant= _XkbDupString(out); - out+=strlen(out)+1; - } - - if (outoptions= _XkbDupString(out); - out+=strlen(out)+1; - } - - XFree(data); - return True; -} - -Bool -XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs) -{ -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 +/************************************************************ + 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. + + ********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#elif defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include + +#define X_INCLUDE_STRING_H +#define XOS_USE_NO_LOCKING +#include + +#ifndef XKB_IN_SERVER + +#include +#include +#include +#include +#include +#include +#include +#include +#include "XKMformat.h" +#include "XKBfileInt.h" +#include "XKBrules.h" + +#else + +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include +#define XKBSRV_NEED_FILE_FUNCS +#include + +#endif + +#ifdef DEBUG +#define PR_DEBUG(s) fprintf(stderr,s) +#define PR_DEBUG1(s,a) fprintf(stderr,s,a) +#define PR_DEBUG2(s,a,b) fprintf(stderr,s,a,b) +#else +#define PR_DEBUG(s) +#define PR_DEBUG1(s,a) +#define PR_DEBUG2(s,a,b) +#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 +InitInputLine(InputLine *line) +{ + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static void +FreeInputLine(InputLine *line) +{ + 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 +InputLineAddChar(InputLine *line,int ch) +{ + 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)) + +#ifdef HAVE_UNLOCKED_STDIO +#undef getc +#define getc(x) getc_unlocked(x) +#else +#define flockfile(x) do {} while (0) +#define funlockfile(x) do {} while (0) +#endif + +static Bool +GetInputLine(FILE *file,InputLine *line,Bool checkbang) +{ +int ch; +Bool endOfFile,spacePending,slashPending,inComment; + + endOfFile= False; + flockfile(file); + 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++;*/ + } + funlockfile(file); + 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 number; + int num_remap; + struct { + int word; + int index; + } remap[MAX_WORDS]; +} RemapSpec; + +typedef struct _FileSpec { + char * name[MAX_WORDS]; + struct _FileSpec * pending; +} FileSpec; + +typedef struct { + char * model; + char * layout[XkbNumKbdGroups+1]; + char * variant[XkbNumKbdGroups+1]; + char * options; +} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; + +#define NDX_BUFF_SIZE 4 + +/***====================================================================***/ + +static char* +get_index(char *str, int *ndx) +{ + 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; + } + strncpy(ndx_buf, str, end - str); + ndx_buf[end - str] = '\0'; + *ndx = atoi(ndx_buf); + return end + 1; +} + +static void +SetUpRemap(InputLine *line,RemapSpec *remap) +{ +char * tok,*str; +unsigned present, l_ndx_present, v_ndx_present; +register int i; +int len, ndx; +_Xstrtokparams strtok_buf; +#ifdef DEBUG +Bool found; +#endif + + + l_ndx_present = v_ndx_present = present= 0; + str= &line->line[1]; + len = remap->number; + bzero((char *)remap,sizeof(RemapSpec)); + remap->number = len; + while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { +#ifdef DEBUG + found= False; +#endif + str= NULL; + if (strcmp(tok,"=")==0) + continue; + for (i=0;i len) { + char *end = get_index(tok+len, &ndx); + if ((i != LAYOUT && i != VARIANT) || + *end != '\0' || ndx == -1) + break; + if (ndx < 1 || ndx > XkbNumKbdGroups) { + PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx); + PR_DEBUG1("Index must be in range 1..%d\n", + XkbNumKbdGroups); + break; + } + } else { + ndx = 0; + } +#ifdef DEBUG + found= True; +#endif + if (present&(1<remap[remap->num_remap].word= i; + remap->remap[remap->num_remap++].index= ndx; + 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 least one of "); + for (i=0; (inum_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&COMPONENT_MASK)&(1<num_remap= 0; + return; + } + remap->number++; + return; +} + +static Bool +MatchOneOf(char *wanted,char *vals_defined) +{ +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 +CheckLine( InputLine * line, + RemapSpec * remap, + XkbRF_RulePtr rule, + XkbRF_GroupPtr group) +{ +char * str,*tok; +register int nread, i; +FileSpec tmp; +_Xstrtokparams strtok_buf; +Bool append = False; + + if (line->line[0]=='!') { + if (line->line[1] == '$' || + (line->line[1] == ' ' && line->line[2] == '$')) { + char *gname = strchr(line->line, '$'); + char *words = strchr(gname, ' '); + if(!words) + return False; + *words++ = '\0'; + for (; *words; words++) { + if (*words != '=' && *words != ' ') + break; + } + if (*words == '\0') + return False; + group->name = _XkbDupString(gname); + group->words = _XkbDupString(words); + for (i = 1, words = group->words; *words; words++) { + if ( *words == ' ') { + *words++ = '\0'; + i++; + } + } + group->number = i; + return True; + } else { + 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].word]= tok; + if (*tok == '+' || *tok == '|') + append = True; + } + if (nreadnum_remap) { + PR_DEBUG1("Too few words on a line: %s\n", line->line); + PR_DEBUG("line ignored\n"); + return False; + } + + rule->flags= 0; + rule->number = remap->number; + if (tmp.name[OPTION]) + rule->flags|= XkbRF_Option; + else if (append) + rule->flags|= XkbRF_Append; + else + rule->flags|= XkbRF_Normal; + 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]); + + rule->layout_num = rule->variant_num = 0; + for (i = 0; i < nread; i++) { + if (remap->remap[i].index) { + 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; + } + } + return True; +} + +static char * +_Concat(char *str1,char *str2) +{ +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; +} + +static void +squeeze_spaces(char *p1) +{ + char *p2; + for (p2 = p1; *p2; p2++) { + *p1 = *p2; + if (*p1 != ' ') p1++; + } + *p1 = '\0'; +} + +static Bool +MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) +{ + + bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec)); + mdefs->model = defs->model; + mdefs->options = _XkbDupString(defs->options); + if (mdefs->options) squeeze_spaces(mdefs->options); + + if (defs->layout) { + if (!strchr(defs->layout, ',')) { + mdefs->layout[0] = defs->layout; + } else { + char *p; + int i; + mdefs->layout[1] = _XkbDupString(defs->layout); + if (mdefs->layout[1] == NULL) + return False; + squeeze_spaces(mdefs->layout[1]); + p = mdefs->layout[1]; + 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; + int i; + mdefs->variant[1] = _XkbDupString(defs->variant); + if (mdefs->variant[1] == NULL) + return False; + squeeze_spaces(mdefs->variant[1]); + p = mdefs->variant[1]; + 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; +} + +static void +FreeMultiDefs(XkbRF_MultiDefsPtr defs) +{ + if (defs->options) _XkbFree(defs->options); + if (defs->layout[1]) _XkbFree(defs->layout[1]); + if (defs->variant[1]) _XkbFree(defs->variant[1]); +} + +static void +Apply(char *src, char **dst) +{ + if (src) { + if (*src == '+' || *src == '!') { + *dst= _Concat(*dst, src); + } else { + if (*dst == NULL) + *dst= _XkbDupString(src); + } + } +} + +static void +XkbRF_ApplyRule( XkbRF_RulePtr rule, + XkbComponentNamesPtr names) +{ + rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ + + Apply(rule->keycodes, &names->keycodes); + Apply(rule->symbols, &names->symbols); + Apply(rule->types, &names->types); + Apply(rule->compat, &names->compat); + Apply(rule->geometry, &names->geometry); + Apply(rule->keymap, &names->keymap); +} + +static Bool +CheckGroup( XkbRF_RulesPtr rules, + char * group_name, + char * name) +{ + 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; +} + +static int +XkbRF_CheckApplyRule( XkbRF_RulePtr rule, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + XkbRF_RulesPtr rules) +{ + Bool pending = False; + + if (rule->model != NULL) { + if(mdefs->model == NULL) + return 0; + if (strcmp(rule->model, "*") == 0) { + pending = True; + } else { + if (rule->model[0] == '$') { + if (!CheckGroup(rules, rule->model, mdefs->model)) + return 0; + } else { + if (strcmp(rule->model, mdefs->model) != 0) + return 0; + } + } + } + if (rule->option != NULL) { + if (mdefs->options == NULL) + return 0; + if ((!MatchOneOf(rule->option,mdefs->options))) + return 0; + } + + if (rule->layout != NULL) { + if(mdefs->layout[rule->layout_num] == NULL || + *mdefs->layout[rule->layout_num] == '\0') + return 0; + if (strcmp(rule->layout, "*") == 0) { + pending = True; + } else { + if (rule->layout[0] == '$') { + 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; + } + } + } + if (rule->variant != NULL) { + if (mdefs->variant[rule->variant_num] == NULL || + *mdefs->variant[rule->variant_num] == '\0') + return 0; + if (strcmp(rule->variant, "*") == 0) { + pending = True; + } else { + if (rule->variant[0] == '$') { + 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; + } + } + } + if (pending) { + rule->flags|= XkbRF_PendingMatch; + return rule->number; + } + /* exact match, apply it now */ + XkbRF_ApplyRule(rule,names); + return rule->number; +} + +static void +XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) +{ +register int i; +XkbRF_RulePtr rule; + + for (i=0,rule=rules->rules;inum_rules;i++,rule++) { + rule->flags&= ~XkbRF_PendingMatch; + } +} + +static void +XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) +{ +int i; +XkbRF_RulePtr rule; + + for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { + if ((rule->flags&XkbRF_PendingMatch)==0) + continue; + XkbRF_ApplyRule(rule,names); + } +} + +static void +XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + int flags) +{ +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--; + } + } +} + +/***====================================================================***/ + +static char * +XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) +{ +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= (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'; + + 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) + _XkbFree(orig); + return name; +} + +/***====================================================================***/ + +Bool +XkbRF_GetComponents( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +{ + XkbRF_MultiDefsRec mdefs; + + MakeMultiDefs(&mdefs, defs); + + bzero((char *)names,sizeof(XkbComponentNamesRec)); + XkbRF_ClearPartialMatches(rules); + 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); + XkbRF_ApplyPartialMatches(rules, names); + + if (names->keycodes) + names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); + if (names->symbols) + names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); + if (names->types) + names->types= XkbRF_SubstituteVars(names->types, &mdefs); + if (names->compat) + names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); + if (names->geometry) + names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); + if (names->keymap) + names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs); + + FreeMultiDefs(&mdefs); + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry ) || names->keymap; +} + +XkbRF_RulePtr +XkbRF_AddRule(XkbRF_RulesPtr rules) +{ + 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++]; +} + +XkbRF_GroupPtr +XkbRF_AddGroup(XkbRF_RulesPtr rules) +{ + if (rules->sz_groups<1) { + rules->sz_groups= 16; + rules->num_groups= 0; + rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec); + } + else if (rules->num_groups >= rules->sz_groups) { + rules->sz_groups *= 2; + rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups, + XkbRF_GroupRec); + } + if (!rules->groups) { + rules->sz_groups= rules->num_groups= 0; + return NULL; + } + + bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec)); + return &rules->groups[rules->num_groups++]; +} + +Bool +XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) +{ +InputLine line; +RemapSpec remap; +XkbRF_RuleRec trule,*rule; +XkbRF_GroupRec tgroup,*group; + + if (!(rules && file)) + return False; + bzero((char *)&remap,sizeof(RemapSpec)); + bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); + InitInputLine(&line); + while (GetInputLine(file,&line,True)) { + if (CheckLine(&line,&remap,&trule,&tgroup)) { + if (tgroup.number) { + if ((group= XkbRF_AddGroup(rules))!=NULL) { + *group= tgroup; + bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); + } + } else { + if ((rule= XkbRF_AddRule(rules))!=NULL) { + *rule= trule; + bzero((char *)&trule,sizeof(XkbRF_RuleRec)); + } + } + } + line.num_line= 0; + } + FreeInputLine(&line); + return True; +} + +Bool +XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) +{ +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 +XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) +{ + 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 +XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) +{ +XkbRF_VarDescPtr nd; + + if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { + nd->name= _XkbDupString(from->name); + nd->desc= _XkbDupString(from->desc); + } + return nd; +} + +XkbRF_DescribeVarsPtr +XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) +{ + 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 +XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) +{ +InputLine line; +XkbRF_VarDescRec tmp; +char *tok; +int len,headingtype,extra_ndx = 0; + + 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 (strcmp(tok,"model") == 0) + headingtype = HEAD_MODEL; + else if (_XkbStrCaseCmp(tok,"layout") == 0) + headingtype = HEAD_LAYOUT; + else if (_XkbStrCaseCmp(tok,"variant") == 0) + headingtype = HEAD_VARIANT; + else if (_XkbStrCaseCmp(tok,"option") == 0) + headingtype = HEAD_OPTION; + else { + int i; + headingtype = HEAD_EXTRA; + extra_ndx= -1; + for (i=0;(inum_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 +XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) +{ +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 +XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) +{ +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 +XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) +{ +register int i; + + for (i=0;inum_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 +XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) +{ +int i; +XkbRF_RulePtr rule; +XkbRF_GroupPtr group; + + 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;inum_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 (rules->groups) { + for (i=0, group=rules->groups;inum_groups;i++,group++) { + if (group->name) _XkbFree(group->name); + if (group->words) _XkbFree(group->words); + } + _XkbFree(rules->groups); + rules->num_groups= 0; + rules->groups= NULL; + } + if (freeRules) + _XkbFree(rules); + return; +} + +#ifndef XKB_IN_SERVER + +Bool +XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn) +{ +Atom rules_atom,actual_type; +int fmt; +unsigned long nitems,bytes_after; +unsigned char *data; +char *out, *end; +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=(char*)data; + end=out+nitems; + if (out && (*out) && rf_rtrn) + *rf_rtrn= _XkbDupString(out); + out+=strlen(out)+1; + + if (outmodel= _XkbDupString(out); + out+=strlen(out)+1; + } + + if (outlayout= _XkbDupString(out); + out+=strlen(out)+1; + } + + if (outvariant= _XkbDupString(out); + out+=strlen(out)+1; + } + + if (outoptions= _XkbDupString(out); + out+=strlen(out)+1; + } + + XFree(data); + return True; +} + +Bool +XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs) +{ +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 -- cgit v1.2.3