1 /************************************************************
2 Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
35 #define X_INCLUDE_STRING_H
36 #define XOS_USE_NO_LOCKING
37 #include <X11/Xos_r.h>
40 #include <X11/Xproto.h>
43 #include <X11/Xfuncs.h>
44 #include <X11/Xatom.h>
45 #include <X11/keysym.h>
49 #include <X11/extensions/XKBstr.h>
50 #define XKBSRV_NEED_FILE_FUNCS
54 #define PR_DEBUG(s) fprintf(stderr,s)
55 #define PR_DEBUG1(s,a) fprintf(stderr,s,a)
56 #define PR_DEBUG2(s,a,b) fprintf(stderr,s,a,b)
59 #define PR_DEBUG1(s,a)
60 #define PR_DEBUG2(s,a,b)
63 /***====================================================================***/
65 #define DFLT_LINE_SIZE 128
71 char buf
[DFLT_LINE_SIZE
];
76 InitInputLine(InputLine
*line
)
80 line
->sz_line
= DFLT_LINE_SIZE
;
81 line
->line
= line
->buf
;
86 FreeInputLine(InputLine
*line
)
88 if (line
->line
!=line
->buf
)
92 line
->sz_line
= DFLT_LINE_SIZE
;
93 line
->line
= line
->buf
;
98 InputLineAddChar(InputLine
*line
,int ch
)
100 if (line
->num_line
>=line
->sz_line
) {
101 if (line
->line
==line
->buf
) {
102 line
->line
= (char *)_XkbAlloc(line
->sz_line
*2);
103 memcpy(line
->line
,line
->buf
,line
->sz_line
);
106 line
->line
=(char *)_XkbRealloc((char *)line
->line
,line
->sz_line
*2);
110 line
->line
[line
->num_line
++]= ch
;
114 #define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\
115 (int)((l)->line[(l)->num_line++]= (c)):\
116 InputLineAddChar(l,c))
119 GetInputLine(FILE *file
,InputLine
*line
,Bool checkbang
)
122 Bool endOfFile
,spacePending
,slashPending
,inComment
;
125 while ((!endOfFile
)&&(line
->num_line
==0)) {
126 spacePending
= slashPending
= inComment
= False
;
127 while (((ch
=getc(file
))!='\n')&&(ch
!=EOF
)) {
129 if ((ch
=getc(file
))==EOF
)
149 else if (slashPending
) {
158 while (isspace(ch
)&&(ch
!='\n')&&(ch
!=EOF
)) {
163 if ((ch
!='\n')&&(line
->num_line
>0))
172 if (checkbang
&& ch
=='!') {
173 if (line
->num_line
!=0) {
174 PR_DEBUG("The '!' legal only at start of line\n");
175 PR_DEBUG("Line containing '!' ignored\n");
187 /* else line->num_line++;*/
189 if ((line
->num_line
==0)&&(endOfFile
))
195 /***====================================================================***/
209 #define PART_MASK 0x000F
210 #define COMPONENT_MASK 0x03F0
212 static char * cname
[MAX_WORDS
] = {
213 "model", "layout", "variant", "option",
214 "keycodes", "symbols", "types", "compat", "geometry", "keymap"
217 typedef struct _RemapSpec
{
226 typedef struct _FileSpec
{
227 char * name
[MAX_WORDS
];
228 struct _FileSpec
* pending
;
233 char * layout
[XkbNumKbdGroups
+1];
234 char * variant
[XkbNumKbdGroups
+1];
236 } XkbRF_MultiDefsRec
, *XkbRF_MultiDefsPtr
;
238 #define NDX_BUFF_SIZE 4
240 /***====================================================================***/
243 get_index(char *str
, int *ndx
)
245 char ndx_buf
[NDX_BUFF_SIZE
];
253 end
= strchr(str
, ']');
258 if ( (end
- str
) >= NDX_BUFF_SIZE
) {
262 strncpy(ndx_buf
, str
, end
- str
);
263 ndx_buf
[end
- str
] = '\0';
264 *ndx
= atoi(ndx_buf
);
269 SetUpRemap(InputLine
*line
,RemapSpec
*remap
)
272 unsigned present
, l_ndx_present
, v_ndx_present
;
275 _Xstrtokparams strtok_buf
;
281 l_ndx_present
= v_ndx_present
= present
= 0;
284 bzero((char *)remap
,sizeof(RemapSpec
));
286 while ((tok
=_XStrtok(str
," ",strtok_buf
))!=NULL
) {
291 if (strcmp(tok
,"=")==0)
293 for (i
=0;i
<MAX_WORDS
;i
++) {
294 len
= strlen(cname
[i
]);
295 if (strncmp(cname
[i
],tok
,len
)==0) {
296 if(strlen(tok
) > len
) {
297 char *end
= get_index(tok
+len
, &ndx
);
298 if ((i
!= LAYOUT
&& i
!= VARIANT
) ||
299 *end
!= '\0' || ndx
== -1)
301 if (ndx
< 1 || ndx
> XkbNumKbdGroups
) {
302 PR_DEBUG2("Illegal %s index: %d\n", cname
[i
], ndx
);
303 PR_DEBUG1("Index must be in range 1..%d\n",
313 if (present
&(1<<i
)) {
314 if ((i
== LAYOUT
&& l_ndx_present
&(1<<ndx
)) ||
315 (i
== VARIANT
&& v_ndx_present
&(1<<ndx
)) ) {
316 PR_DEBUG1("Component \"%s\" listed twice\n",tok
);
317 PR_DEBUG("Second definition ignored\n");
323 l_ndx_present
|= 1 << ndx
;
325 v_ndx_present
|= 1 << ndx
;
326 remap
->remap
[remap
->num_remap
].word
= i
;
327 remap
->remap
[remap
->num_remap
++].index
= ndx
;
333 fprintf(stderr
,"Unknown component \"%s\" ignored\n",tok
);
337 if ((present
&PART_MASK
)==0) {
339 unsigned mask
= PART_MASK
;
340 fprintf(stderr
,"Mapping needs at least one of ");
341 for (i
=0; (i
<MAX_WORDS
); i
++) {
344 if (mask
) fprintf(stderr
,"\"%s,\" ",cname
[i
]);
345 else fprintf(stderr
,"or \"%s\"\n",cname
[i
]);
348 fprintf(stderr
,"Illegal mapping ignored\n");
353 if ((present
&COMPONENT_MASK
)==0) {
354 PR_DEBUG("Mapping needs at least one component\n");
355 PR_DEBUG("Illegal mapping ignored\n");
359 if (((present
&COMPONENT_MASK
)&(1<<KEYMAP
))&&
360 ((present
&COMPONENT_MASK
)!=(1<<KEYMAP
))) {
361 PR_DEBUG("Keymap cannot appear with other components\n");
362 PR_DEBUG("Illegal mapping ignored\n");
371 MatchOneOf(char *wanted
,char *vals_defined
)
374 int want_len
= strlen(wanted
);
376 for (str
=vals_defined
,next
=NULL
;str
!=NULL
;str
=next
) {
378 next
= strchr(str
,',');
386 if ((len
==want_len
)&&(strncmp(wanted
,str
,len
)==0))
392 /***====================================================================***/
395 CheckLine( InputLine
* line
,
398 XkbRF_GroupPtr group
)
401 register int nread
, i
;
403 _Xstrtokparams strtok_buf
;
406 if (line
->line
[0]=='!') {
407 if (line
->line
[1] == '$' ||
408 (line
->line
[1] == ' ' && line
->line
[2] == '$')) {
409 char *gname
= strchr(line
->line
, '$');
410 char *words
= strchr(gname
, ' ');
414 for (; *words
; words
++) {
415 if (*words
!= '=' && *words
!= ' ')
420 group
->name
= _XkbDupString(gname
);
421 group
->words
= _XkbDupString(words
);
422 for (i
= 1, words
= group
->words
; *words
; words
++) {
423 if ( *words
== ' ') {
431 SetUpRemap(line
,remap
);
436 if (remap
->num_remap
==0) {
437 PR_DEBUG("Must have a mapping before first line of data\n");
438 PR_DEBUG("Illegal line of data ignored\n");
441 bzero((char *)&tmp
,sizeof(FileSpec
));
443 for (nread
= 0;(tok
=_XStrtok(str
," ",strtok_buf
))!=NULL
;nread
++) {
445 if (strcmp(tok
,"=")==0) {
449 if (nread
>remap
->num_remap
) {
450 PR_DEBUG("Too many words on a line\n");
451 PR_DEBUG1("Extra word \"%s\" ignored\n",tok
);
454 tmp
.name
[remap
->remap
[nread
].word
]= tok
;
455 if (*tok
== '+' || *tok
== '|')
458 if (nread
<remap
->num_remap
) {
459 PR_DEBUG1("Too few words on a line: %s\n", line
->line
);
460 PR_DEBUG("line ignored\n");
465 rule
->number
= remap
->number
;
466 if (tmp
.name
[OPTION
])
467 rule
->flags
|= XkbRF_Option
;
469 rule
->flags
|= XkbRF_Append
;
471 rule
->flags
|= XkbRF_Normal
;
472 rule
->model
= _XkbDupString(tmp
.name
[MODEL
]);
473 rule
->layout
= _XkbDupString(tmp
.name
[LAYOUT
]);
474 rule
->variant
= _XkbDupString(tmp
.name
[VARIANT
]);
475 rule
->option
= _XkbDupString(tmp
.name
[OPTION
]);
477 rule
->keycodes
= _XkbDupString(tmp
.name
[KEYCODES
]);
478 rule
->symbols
= _XkbDupString(tmp
.name
[SYMBOLS
]);
479 rule
->types
= _XkbDupString(tmp
.name
[TYPES
]);
480 rule
->compat
= _XkbDupString(tmp
.name
[COMPAT
]);
481 rule
->geometry
= _XkbDupString(tmp
.name
[GEOMETRY
]);
482 rule
->keymap
= _XkbDupString(tmp
.name
[KEYMAP
]);
484 rule
->layout_num
= rule
->variant_num
= 0;
485 for (i
= 0; i
< nread
; i
++) {
486 if (remap
->remap
[i
].index
) {
487 if (remap
->remap
[i
].word
== LAYOUT
)
488 rule
->layout_num
= remap
->remap
[i
].index
;
489 if (remap
->remap
[i
].word
== VARIANT
)
490 rule
->variant_num
= remap
->remap
[i
].index
;
497 _Concat(char *str1
,char *str2
)
501 if ((!str1
)||(!str2
))
503 len
= strlen(str1
)+strlen(str2
)+1;
504 str1
= _XkbTypedRealloc(str1
,len
,char);
511 squeeze_spaces(char *p1
)
514 for (p2
= p1
; *p2
; p2
++) {
516 if (*p1
!= ' ') p1
++;
522 MakeMultiDefs(XkbRF_MultiDefsPtr mdefs
, XkbRF_VarDefsPtr defs
)
525 bzero((char *)mdefs
,sizeof(XkbRF_MultiDefsRec
));
526 mdefs
->model
= defs
->model
;
527 mdefs
->options
= _XkbDupString(defs
->options
);
528 if (mdefs
->options
) squeeze_spaces(mdefs
->options
);
531 if (!strchr(defs
->layout
, ',')) {
532 mdefs
->layout
[0] = defs
->layout
;
536 mdefs
->layout
[1] = _XkbDupString(defs
->layout
);
537 if (mdefs
->layout
[1] == NULL
)
539 squeeze_spaces(mdefs
->layout
[1]);
540 p
= mdefs
->layout
[1];
541 for (i
= 2; i
<= XkbNumKbdGroups
; i
++) {
542 if ((p
= strchr(p
, ','))) {
544 mdefs
->layout
[i
] = p
;
549 if (p
&& (p
= strchr(p
, ',')))
555 if (!strchr(defs
->variant
, ',')) {
556 mdefs
->variant
[0] = defs
->variant
;
560 mdefs
->variant
[1] = _XkbDupString(defs
->variant
);
561 if (mdefs
->variant
[1] == NULL
)
563 squeeze_spaces(mdefs
->variant
[1]);
564 p
= mdefs
->variant
[1];
565 for (i
= 2; i
<= XkbNumKbdGroups
; i
++) {
566 if ((p
= strchr(p
, ','))) {
568 mdefs
->variant
[i
] = p
;
573 if (p
&& (p
= strchr(p
, ',')))
581 FreeMultiDefs(XkbRF_MultiDefsPtr defs
)
583 if (defs
->options
) _XkbFree(defs
->options
);
584 if (defs
->layout
[1]) _XkbFree(defs
->layout
[1]);
585 if (defs
->variant
[1]) _XkbFree(defs
->variant
[1]);
589 Apply(char *src
, char **dst
)
592 if (*src
== '+' || *src
== '!') {
593 *dst
= _Concat(*dst
, src
);
596 *dst
= _XkbDupString(src
);
602 XkbRF_ApplyRule( XkbRF_RulePtr rule
,
603 XkbComponentNamesPtr names
)
605 rule
->flags
&= ~XkbRF_PendingMatch
; /* clear the flag because it's applied */
607 Apply(rule
->keycodes
, &names
->keycodes
);
608 Apply(rule
->symbols
, &names
->symbols
);
609 Apply(rule
->types
, &names
->types
);
610 Apply(rule
->compat
, &names
->compat
);
611 Apply(rule
->geometry
, &names
->geometry
);
612 Apply(rule
->keymap
, &names
->keymap
);
616 CheckGroup( XkbRF_RulesPtr rules
,
622 XkbRF_GroupPtr group
;
624 for (i
= 0, group
= rules
->groups
; i
< rules
->num_groups
; i
++, group
++) {
625 if (! strcmp(group
->name
, group_name
)) {
629 if (i
== rules
->num_groups
)
631 for (i
= 0, p
= group
->words
; i
< group
->number
; i
++, p
+= strlen(p
)+1) {
632 if (! strcmp(p
, name
)) {
640 XkbRF_CheckApplyRule( XkbRF_RulePtr rule
,
641 XkbRF_MultiDefsPtr mdefs
,
642 XkbComponentNamesPtr names
,
643 XkbRF_RulesPtr rules
)
645 Bool pending
= False
;
647 if (rule
->model
!= NULL
) {
648 if(mdefs
->model
== NULL
)
650 if (strcmp(rule
->model
, "*") == 0) {
653 if (rule
->model
[0] == '$') {
654 if (!CheckGroup(rules
, rule
->model
, mdefs
->model
))
657 if (strcmp(rule
->model
, mdefs
->model
) != 0)
662 if (rule
->option
!= NULL
) {
663 if (mdefs
->options
== NULL
)
665 if ((!MatchOneOf(rule
->option
,mdefs
->options
)))
669 if (rule
->layout
!= NULL
) {
670 if(mdefs
->layout
[rule
->layout_num
] == NULL
||
671 *mdefs
->layout
[rule
->layout_num
] == '\0')
673 if (strcmp(rule
->layout
, "*") == 0) {
676 if (rule
->layout
[0] == '$') {
677 if (!CheckGroup(rules
, rule
->layout
,
678 mdefs
->layout
[rule
->layout_num
]))
681 if (strcmp(rule
->layout
, mdefs
->layout
[rule
->layout_num
]) != 0)
686 if (rule
->variant
!= NULL
) {
687 if (mdefs
->variant
[rule
->variant_num
] == NULL
||
688 *mdefs
->variant
[rule
->variant_num
] == '\0')
690 if (strcmp(rule
->variant
, "*") == 0) {
693 if (rule
->variant
[0] == '$') {
694 if (!CheckGroup(rules
, rule
->variant
,
695 mdefs
->variant
[rule
->variant_num
]))
698 if (strcmp(rule
->variant
,
699 mdefs
->variant
[rule
->variant_num
]) != 0)
705 rule
->flags
|= XkbRF_PendingMatch
;
708 /* exact match, apply it now */
709 XkbRF_ApplyRule(rule
,names
);
714 XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules
)
719 for (i
=0,rule
=rules
->rules
;i
<rules
->num_rules
;i
++,rule
++) {
720 rule
->flags
&= ~XkbRF_PendingMatch
;
725 XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules
,XkbComponentNamesPtr names
)
730 for (rule
= rules
->rules
, i
= 0; i
< rules
->num_rules
; i
++, rule
++) {
731 if ((rule
->flags
&XkbRF_PendingMatch
)==0)
733 XkbRF_ApplyRule(rule
,names
);
738 XkbRF_CheckApplyRules( XkbRF_RulesPtr rules
,
739 XkbRF_MultiDefsPtr mdefs
,
740 XkbComponentNamesPtr names
,
747 for (rule
= rules
->rules
, i
=0; i
< rules
->num_rules
; rule
++, i
++) {
748 if ((rule
->flags
& flags
) != flags
)
750 skip
= XkbRF_CheckApplyRule(rule
, mdefs
, names
, rules
);
751 if (skip
&& !(flags
& XkbRF_Option
)) {
752 for ( ;(i
< rules
->num_rules
) && (rule
->number
== skip
);
759 /***====================================================================***/
762 XkbRF_SubstituteVars(char *name
, XkbRF_MultiDefsPtr mdefs
)
764 char *str
, *outstr
, *orig
, *var
;
768 str
= index(name
,'%');
775 if ((pfx
=='+')||(pfx
=='|')||(pfx
=='_')||(pfx
=='-')) {
784 str
= get_index(var
+ 1, &ndx
);
786 str
= index(str
,'%');
789 if ((*var
=='l') && mdefs
->layout
[ndx
] && *mdefs
->layout
[ndx
])
790 len
+= strlen(mdefs
->layout
[ndx
])+extra_len
;
791 else if ((*var
=='m')&&mdefs
->model
)
792 len
+= strlen(mdefs
->model
)+extra_len
;
793 else if ((*var
=='v') && mdefs
->variant
[ndx
] && *mdefs
->variant
[ndx
])
794 len
+= strlen(mdefs
->variant
[ndx
])+extra_len
;
795 if ((pfx
=='(')&&(*str
==')')) {
798 str
= index(&str
[0],'%');
800 name
= (char *)_XkbAlloc(len
+1);
809 if ((pfx
=='+')||(pfx
=='|')||(pfx
=='_')||(pfx
=='-')) {
819 str
= get_index(var
+ 1, &ndx
);
823 if ((*var
=='l') && mdefs
->layout
[ndx
] && *mdefs
->layout
[ndx
]) {
824 if (pfx
) *outstr
++= pfx
;
825 strcpy(outstr
,mdefs
->layout
[ndx
]);
826 outstr
+= strlen(mdefs
->layout
[ndx
]);
827 if (sfx
) *outstr
++= sfx
;
829 else if ((*var
=='m')&&(mdefs
->model
)) {
830 if (pfx
) *outstr
++= pfx
;
831 strcpy(outstr
,mdefs
->model
);
832 outstr
+= strlen(mdefs
->model
);
833 if (sfx
) *outstr
++= sfx
;
835 else if ((*var
=='v') && mdefs
->variant
[ndx
] && *mdefs
->variant
[ndx
]) {
836 if (pfx
) *outstr
++= pfx
;
837 strcpy(outstr
,mdefs
->variant
[ndx
]);
838 outstr
+= strlen(mdefs
->variant
[ndx
]);
839 if (sfx
) *outstr
++= sfx
;
841 if ((pfx
=='(')&&(*str
==')'))
854 /***====================================================================***/
857 XkbRF_GetComponents( XkbRF_RulesPtr rules
,
858 XkbRF_VarDefsPtr defs
,
859 XkbComponentNamesPtr names
)
861 XkbRF_MultiDefsRec mdefs
;
863 MakeMultiDefs(&mdefs
, defs
);
865 bzero((char *)names
,sizeof(XkbComponentNamesRec
));
866 XkbRF_ClearPartialMatches(rules
);
867 XkbRF_CheckApplyRules(rules
, &mdefs
, names
, XkbRF_Normal
);
868 XkbRF_ApplyPartialMatches(rules
, names
);
869 XkbRF_CheckApplyRules(rules
, &mdefs
, names
, XkbRF_Append
);
870 XkbRF_ApplyPartialMatches(rules
, names
);
871 XkbRF_CheckApplyRules(rules
, &mdefs
, names
, XkbRF_Option
);
874 names
->keycodes
= XkbRF_SubstituteVars(names
->keycodes
, &mdefs
);
876 names
->symbols
= XkbRF_SubstituteVars(names
->symbols
, &mdefs
);
878 names
->types
= XkbRF_SubstituteVars(names
->types
, &mdefs
);
880 names
->compat
= XkbRF_SubstituteVars(names
->compat
, &mdefs
);
882 names
->geometry
= XkbRF_SubstituteVars(names
->geometry
, &mdefs
);
884 names
->keymap
= XkbRF_SubstituteVars(names
->keymap
, &mdefs
);
886 FreeMultiDefs(&mdefs
);
887 return (names
->keycodes
&& names
->symbols
&& names
->types
&&
888 names
->compat
&& names
->geometry
) || names
->keymap
;
892 XkbRF_AddRule(XkbRF_RulesPtr rules
)
894 if (rules
->sz_rules
<1) {
897 rules
->rules
= _XkbTypedCalloc(rules
->sz_rules
,XkbRF_RuleRec
);
899 else if (rules
->num_rules
>=rules
->sz_rules
) {
901 rules
->rules
= _XkbTypedRealloc(rules
->rules
,rules
->sz_rules
,
905 rules
->sz_rules
= rules
->num_rules
= 0;
907 fprintf(stderr
,"Allocation failure in XkbRF_AddRule\n");
911 bzero((char *)&rules
->rules
[rules
->num_rules
],sizeof(XkbRF_RuleRec
));
912 return &rules
->rules
[rules
->num_rules
++];
916 XkbRF_AddGroup(XkbRF_RulesPtr rules
)
918 if (rules
->sz_groups
<1) {
919 rules
->sz_groups
= 16;
920 rules
->num_groups
= 0;
921 rules
->groups
= _XkbTypedCalloc(rules
->sz_groups
,XkbRF_GroupRec
);
923 else if (rules
->num_groups
>= rules
->sz_groups
) {
924 rules
->sz_groups
*= 2;
925 rules
->groups
= _XkbTypedRealloc(rules
->groups
,rules
->sz_groups
,
928 if (!rules
->groups
) {
929 rules
->sz_groups
= rules
->num_groups
= 0;
933 bzero((char *)&rules
->groups
[rules
->num_groups
],sizeof(XkbRF_GroupRec
));
934 return &rules
->groups
[rules
->num_groups
++];
938 XkbRF_LoadRules(FILE *file
, XkbRF_RulesPtr rules
)
942 XkbRF_RuleRec trule
,*rule
;
943 XkbRF_GroupRec tgroup
,*group
;
945 if (!(rules
&& file
))
947 bzero((char *)&remap
,sizeof(RemapSpec
));
948 bzero((char *)&tgroup
,sizeof(XkbRF_GroupRec
));
949 InitInputLine(&line
);
950 while (GetInputLine(file
,&line
,True
)) {
951 if (CheckLine(&line
,&remap
,&trule
,&tgroup
)) {
953 if ((group
= XkbRF_AddGroup(rules
))!=NULL
) {
955 bzero((char *)&tgroup
,sizeof(XkbRF_GroupRec
));
958 if ((rule
= XkbRF_AddRule(rules
))!=NULL
) {
960 bzero((char *)&trule
,sizeof(XkbRF_RuleRec
));
966 FreeInputLine(&line
);
971 XkbRF_LoadRulesByName(char *base
,char *locale
,XkbRF_RulesPtr rules
)
977 if ((!base
)||(!rules
))
980 if (strlen(base
)+strlen(locale
)+2 > PATH_MAX
)
982 sprintf(buf
,"%s-%s", base
, locale
);
985 if (strlen(base
)+1 > PATH_MAX
)
990 file
= fopen(buf
, "r");
991 if ((!file
)&&(locale
)) { /* fallback if locale was specified */
993 file
= fopen(buf
, "r");
997 ok
= XkbRF_LoadRules(file
,rules
);
1002 /***====================================================================***/
1005 #define HEAD_MODEL 1
1006 #define HEAD_LAYOUT 2
1007 #define HEAD_VARIANT 3
1008 #define HEAD_OPTION 4
1009 #define HEAD_EXTRA 5
1012 XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars
)
1014 if (vars
->sz_desc
<1) {
1017 vars
->desc
= _XkbTypedCalloc(vars
->sz_desc
,XkbRF_VarDescRec
);
1019 else if (vars
->num_desc
>=vars
->sz_desc
) {
1021 vars
->desc
= _XkbTypedRealloc(vars
->desc
,vars
->sz_desc
,XkbRF_VarDescRec
);
1024 vars
->sz_desc
= vars
->num_desc
= 0;
1025 PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n");
1028 vars
->desc
[vars
->num_desc
].name
= NULL
;
1029 vars
->desc
[vars
->num_desc
].desc
= NULL
;
1030 return &vars
->desc
[vars
->num_desc
++];
1034 XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars
,XkbRF_VarDescPtr from
)
1036 XkbRF_VarDescPtr nd
;
1038 if ((nd
=XkbRF_AddVarDesc(vars
))!=NULL
) {
1039 nd
->name
= _XkbDupString(from
->name
);
1040 nd
->desc
= _XkbDupString(from
->desc
);
1045 XkbRF_DescribeVarsPtr
1046 XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules
,char *name
)
1048 if (rules
->sz_extra
<1) {
1049 rules
->num_extra
= 0;
1051 rules
->extra_names
= _XkbTypedCalloc(rules
->sz_extra
,char *);
1052 rules
->extra
= _XkbTypedCalloc(rules
->sz_extra
, XkbRF_DescribeVarsRec
);
1054 else if (rules
->num_extra
>=rules
->sz_extra
) {
1055 rules
->sz_extra
*= 2;
1056 rules
->extra_names
= _XkbTypedRealloc(rules
->extra_names
,rules
->sz_extra
,
1058 rules
->extra
=_XkbTypedRealloc(rules
->extra
, rules
->sz_extra
,
1059 XkbRF_DescribeVarsRec
);
1061 if ((!rules
->extra_names
)||(!rules
->extra
)) {
1062 PR_DEBUG("allocation error in extra parts\n");
1063 rules
->sz_extra
= rules
->num_extra
= 0;
1064 rules
->extra_names
= NULL
;
1068 rules
->extra_names
[rules
->num_extra
]= _XkbDupString(name
);
1069 bzero(&rules
->extra
[rules
->num_extra
],sizeof(XkbRF_DescribeVarsRec
));
1070 return &rules
->extra
[rules
->num_extra
++];
1074 XkbRF_LoadDescriptions(FILE *file
,XkbRF_RulesPtr rules
)
1077 XkbRF_VarDescRec tmp
;
1079 int len
,headingtype
,extra_ndx
= 0;
1081 bzero((char *)&tmp
, sizeof(XkbRF_VarDescRec
));
1082 headingtype
= HEAD_NONE
;
1083 InitInputLine(&line
);
1084 for ( ; GetInputLine(file
,&line
,False
); line
.num_line
= 0) {
1085 if (line
.line
[0]=='!') {
1086 tok
= strtok(&(line
.line
[1]), " \t");
1087 if (strcasecmp(tok
,"model") == 0)
1088 headingtype
= HEAD_MODEL
;
1089 else if (strcasecmp(tok
,"layout") == 0)
1090 headingtype
= HEAD_LAYOUT
;
1091 else if (strcasecmp(tok
,"variant") == 0)
1092 headingtype
= HEAD_VARIANT
;
1093 else if (strcasecmp(tok
,"option") == 0)
1094 headingtype
= HEAD_OPTION
;
1097 headingtype
= HEAD_EXTRA
;
1099 for (i
=0;(i
<rules
->num_extra
)&&(extra_ndx
<0);i
++) {
1100 if (!strcasecmp(tok
,rules
->extra_names
[i
]))
1104 XkbRF_DescribeVarsPtr var
;
1105 PR_DEBUG1("Extra heading \"%s\" encountered\n",tok
);
1106 var
= XkbRF_AddVarToDescribe(rules
,tok
);
1108 extra_ndx
= var
-rules
->extra
;
1109 else headingtype
= HEAD_NONE
;
1115 if (headingtype
== HEAD_NONE
) {
1116 PR_DEBUG("Must have a heading before first line of data\n");
1117 PR_DEBUG("Illegal line of data ignored\n");
1121 len
= strlen(line
.line
);
1122 if ((tmp
.name
= strtok(line
.line
, " \t")) == NULL
) {
1123 PR_DEBUG("Huh? No token on line\n");
1124 PR_DEBUG("Illegal line of data ignored\n");
1127 if (strlen(tmp
.name
) == len
) {
1128 PR_DEBUG("No description found\n");
1129 PR_DEBUG("Illegal line of data ignored\n");
1133 tok
= line
.line
+ strlen(tmp
.name
) + 1;
1134 while ((*tok
!='\n')&&isspace(*tok
))
1137 PR_DEBUG("No description found\n");
1138 PR_DEBUG("Illegal line of data ignored\n");
1142 switch (headingtype
) {
1144 XkbRF_AddVarDescCopy(&rules
->models
,&tmp
);
1147 XkbRF_AddVarDescCopy(&rules
->layouts
,&tmp
);
1150 XkbRF_AddVarDescCopy(&rules
->variants
,&tmp
);
1153 XkbRF_AddVarDescCopy(&rules
->options
,&tmp
);
1156 XkbRF_AddVarDescCopy(&rules
->extra
[extra_ndx
],&tmp
);
1160 FreeInputLine(&line
);
1161 if ((rules
->models
.num_desc
==0) && (rules
->layouts
.num_desc
==0) &&
1162 (rules
->variants
.num_desc
==0) && (rules
->options
.num_desc
==0) &&
1163 (rules
->num_extra
==0)) {
1170 XkbRF_LoadDescriptionsByName(char *base
,char *locale
,XkbRF_RulesPtr rules
)
1176 if ((!base
)||(!rules
))
1179 if (strlen(base
)+strlen(locale
)+6 > PATH_MAX
)
1181 sprintf(buf
,"%s-%s.lst", base
, locale
);
1184 if (strlen(base
)+5 > PATH_MAX
)
1186 sprintf(buf
,"%s.lst", base
);
1189 file
= fopen(buf
, "r");
1190 if ((!file
)&&(locale
)) { /* fallback if locale was specified */
1191 sprintf(buf
,"%s.lst", base
);
1193 file
= fopen(buf
, "r");
1197 ok
= XkbRF_LoadDescriptions(file
,rules
);
1202 /***====================================================================***/
1205 XkbRF_Load(char *base
,char *locale
,Bool wantDesc
,Bool wantRules
)
1207 XkbRF_RulesPtr rules
;
1209 if ((!base
)||((!wantDesc
)&&(!wantRules
)))
1211 if ((rules
=_XkbTypedCalloc(1,XkbRF_RulesRec
))==NULL
)
1213 if (wantDesc
&&(!XkbRF_LoadDescriptionsByName(base
,locale
,rules
))) {
1214 XkbRF_Free(rules
,True
);
1217 if (wantRules
&&(!XkbRF_LoadRulesByName(base
,locale
,rules
))) {
1218 XkbRF_Free(rules
,True
);
1225 XkbRF_Create(int szRules
,int szExtra
)
1227 XkbRF_RulesPtr rules
;
1229 if ((rules
=_XkbTypedCalloc(1,XkbRF_RulesRec
))==NULL
)
1232 rules
->sz_rules
= szRules
;
1233 rules
->rules
= _XkbTypedCalloc(rules
->sz_rules
,XkbRF_RuleRec
);
1234 if (!rules
->rules
) {
1240 rules
->sz_extra
= szExtra
;
1241 rules
->extra
= _XkbTypedCalloc(rules
->sz_extra
,XkbRF_DescribeVarsRec
);
1242 if (!rules
->extra
) {
1244 _XkbFree(rules
->rules
);
1252 /***====================================================================***/
1255 XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var
)
1259 for (i
=0;i
<var
->num_desc
;i
++) {
1260 if (var
->desc
[i
].name
)
1261 _XkbFree(var
->desc
[i
].name
);
1262 if (var
->desc
[i
].desc
)
1263 _XkbFree(var
->desc
[i
].desc
);
1264 var
->desc
[i
].name
= var
->desc
[i
].desc
= NULL
;
1267 _XkbFree(var
->desc
);
1273 XkbRF_Free(XkbRF_RulesPtr rules
,Bool freeRules
)
1277 XkbRF_GroupPtr group
;
1281 XkbRF_ClearVarDescriptions(&rules
->models
);
1282 XkbRF_ClearVarDescriptions(&rules
->layouts
);
1283 XkbRF_ClearVarDescriptions(&rules
->variants
);
1284 XkbRF_ClearVarDescriptions(&rules
->options
);
1286 for (i
= 0; i
< rules
->num_extra
; i
++) {
1287 XkbRF_ClearVarDescriptions(&rules
->extra
[i
]);
1289 _XkbFree(rules
->extra
);
1290 rules
->num_extra
= rules
->sz_extra
= 0;
1294 for (i
=0,rule
=rules
->rules
;i
<rules
->num_rules
;i
++,rule
++) {
1295 if (rule
->model
) _XkbFree(rule
->model
);
1296 if (rule
->layout
) _XkbFree(rule
->layout
);
1297 if (rule
->variant
) _XkbFree(rule
->variant
);
1298 if (rule
->option
) _XkbFree(rule
->option
);
1299 if (rule
->keycodes
) _XkbFree(rule
->keycodes
);
1300 if (rule
->symbols
) _XkbFree(rule
->symbols
);
1301 if (rule
->types
) _XkbFree(rule
->types
);
1302 if (rule
->compat
) _XkbFree(rule
->compat
);
1303 if (rule
->geometry
) _XkbFree(rule
->geometry
);
1304 if (rule
->keymap
) _XkbFree(rule
->keymap
);
1305 bzero((char *)rule
,sizeof(XkbRF_RuleRec
));
1307 _XkbFree(rules
->rules
);
1308 rules
->num_rules
= rules
->sz_rules
= 0;
1312 if (rules
->groups
) {
1313 for (i
=0, group
=rules
->groups
;i
<rules
->num_groups
;i
++,group
++) {
1314 if (group
->name
) _XkbFree(group
->name
);
1315 if (group
->words
) _XkbFree(group
->words
);
1317 _XkbFree(rules
->groups
);
1318 rules
->num_groups
= 0;
1319 rules
->groups
= NULL
;