maprules.c revision 8c9fbc29
1/* $Xorg: maprules.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. 4 5 Permission to use, copy, modify, and distribute this 6 software and its documentation for any purpose and without 7 fee is hereby granted, provided that the above copyright 8 notice appear in all copies and that both that copyright 9 notice and this permission notice appear in supporting 10 documentation, and that the name of Silicon Graphics not be 11 used in advertising or publicity pertaining to distribution 12 of the software without specific prior written permission. 13 Silicon Graphics makes no representation about the suitability 14 of this software for any purpose. It is provided "as is" 15 without any express or implied warranty. 16 17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24 THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 26 ********************************************************/ 27/* $XFree86: xc/lib/xkbfile/maprules.c,v 3.17 2002/11/26 01:43:25 dawes Exp $ */ 28 29#ifdef HAVE_DIX_CONFIG_H 30#include <dix-config.h> 31#elif defined(HAVE_CONFIG_H) 32#include <config.h> 33#endif 34 35#include <stdio.h> 36#include <ctype.h> 37#include <stdlib.h> 38 39#define X_INCLUDE_STRING_H 40#define XOS_USE_NO_LOCKING 41#include <X11/Xos_r.h> 42 43#ifndef XKB_IN_SERVER 44 45#include <X11/Xproto.h> 46#include <X11/Xlib.h> 47#include <X11/Xos.h> 48#include <X11/Xfuncs.h> 49#include <X11/Xatom.h> 50#include <X11/keysym.h> 51#include <X11/XKBlib.h> 52#include <X11/extensions/XKBgeom.h> 53#include "XKMformat.h" 54#include "XKBfileInt.h" 55#include "XKBrules.h" 56 57#else 58 59#define NEED_EVENTS 60#include <X11/Xproto.h> 61#include <X11/X.h> 62#include <X11/Xos.h> 63#include <X11/Xfuncs.h> 64#include <X11/Xatom.h> 65#include <X11/keysym.h> 66#include "misc.h" 67#include "inputstr.h" 68#include "dix.h" 69#include <X11/extensions/XKBstr.h> 70#define XKBSRV_NEED_FILE_FUNCS 71#include <X11/extensions/XKBsrv.h> 72 73#endif 74 75#ifdef DEBUG 76#define PR_DEBUG(s) fprintf(stderr,s) 77#define PR_DEBUG1(s,a) fprintf(stderr,s,a) 78#define PR_DEBUG2(s,a,b) fprintf(stderr,s,a,b) 79#else 80#define PR_DEBUG(s) 81#define PR_DEBUG1(s,a) 82#define PR_DEBUG2(s,a,b) 83#endif 84 85/***====================================================================***/ 86 87#define DFLT_LINE_SIZE 128 88 89typedef struct { 90 int line_num; 91 int sz_line; 92 int num_line; 93 char buf[DFLT_LINE_SIZE]; 94 char * line; 95} InputLine; 96 97static void 98InitInputLine(InputLine *line) 99{ 100 line->line_num= 1; 101 line->num_line= 0; 102 line->sz_line= DFLT_LINE_SIZE; 103 line->line= line->buf; 104 return; 105} 106 107static void 108FreeInputLine(InputLine *line) 109{ 110 if (line->line!=line->buf) 111 _XkbFree(line->line); 112 line->line_num= 1; 113 line->num_line= 0; 114 line->sz_line= DFLT_LINE_SIZE; 115 line->line= line->buf; 116 return; 117} 118 119static int 120InputLineAddChar(InputLine *line,int ch) 121{ 122 if (line->num_line>=line->sz_line) { 123 if (line->line==line->buf) { 124 line->line= (char *)_XkbAlloc(line->sz_line*2); 125 memcpy(line->line,line->buf,line->sz_line); 126 } 127 else { 128 line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2); 129 } 130 line->sz_line*= 2; 131 } 132 line->line[line->num_line++]= ch; 133 return ch; 134} 135 136#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ 137 (int)((l)->line[(l)->num_line++]= (c)):\ 138 InputLineAddChar(l,c)) 139 140static Bool 141GetInputLine(FILE *file,InputLine *line,Bool checkbang) 142{ 143int ch; 144Bool endOfFile,spacePending,slashPending,inComment; 145 146 endOfFile= False; 147 while ((!endOfFile)&&(line->num_line==0)) { 148 spacePending= slashPending= inComment= False; 149 while (((ch=getc(file))!='\n')&&(ch!=EOF)) { 150 if (ch=='\\') { 151 if ((ch=getc(file))==EOF) 152 break; 153 if (ch=='\n') { 154 inComment= False; 155 ch= ' '; 156 line->line_num++; 157 } 158 } 159 if (inComment) 160 continue; 161 if (ch=='/') { 162 if (slashPending) { 163 inComment= True; 164 slashPending= False; 165 } 166 else { 167 slashPending= True; 168 } 169 continue; 170 } 171 else if (slashPending) { 172 if (spacePending) { 173 ADD_CHAR(line,' '); 174 spacePending= False; 175 } 176 ADD_CHAR(line,'/'); 177 slashPending= False; 178 } 179 if (isspace(ch)) { 180 while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { 181 ch= getc(file); 182 } 183 if (ch==EOF) 184 break; 185 if ((ch!='\n')&&(line->num_line>0)) 186 spacePending= True; 187 ungetc(ch,file); 188 } 189 else { 190 if (spacePending) { 191 ADD_CHAR(line,' '); 192 spacePending= False; 193 } 194 if (checkbang && ch=='!') { 195 if (line->num_line!=0) { 196 PR_DEBUG("The '!' legal only at start of line\n"); 197 PR_DEBUG("Line containing '!' ignored\n"); 198 line->num_line= 0; 199 inComment= 0; 200 break; 201 } 202 203 } 204 ADD_CHAR(line,ch); 205 } 206 } 207 if (ch==EOF) 208 endOfFile= True; 209/* else line->num_line++;*/ 210 } 211 if ((line->num_line==0)&&(endOfFile)) 212 return False; 213 ADD_CHAR(line,'\0'); 214 return True; 215} 216 217/***====================================================================***/ 218 219#define MODEL 0 220#define LAYOUT 1 221#define VARIANT 2 222#define OPTION 3 223#define KEYCODES 4 224#define SYMBOLS 5 225#define TYPES 6 226#define COMPAT 7 227#define GEOMETRY 8 228#define KEYMAP 9 229#define MAX_WORDS 10 230 231#define PART_MASK 0x000F 232#define COMPONENT_MASK 0x03F0 233 234static char * cname[MAX_WORDS] = { 235 "model", "layout", "variant", "option", 236 "keycodes", "symbols", "types", "compat", "geometry", "keymap" 237}; 238 239typedef struct _RemapSpec { 240 int number; 241 int num_remap; 242 struct { 243 int word; 244 int index; 245 } remap[MAX_WORDS]; 246} RemapSpec; 247 248typedef struct _FileSpec { 249 char * name[MAX_WORDS]; 250 struct _FileSpec * pending; 251} FileSpec; 252 253typedef struct { 254 char * model; 255 char * layout[XkbNumKbdGroups+1]; 256 char * variant[XkbNumKbdGroups+1]; 257 char * options; 258} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; 259 260#define NDX_BUFF_SIZE 4 261 262/***====================================================================***/ 263 264static char* 265get_index(char *str, int *ndx) 266{ 267 char ndx_buf[NDX_BUFF_SIZE]; 268 char *end; 269 270 if (*str != '[') { 271 *ndx = 0; 272 return str; 273 } 274 str++; 275 end = strchr(str, ']'); 276 if (end == NULL) { 277 *ndx = -1; 278 return str - 1; 279 } 280 if ( (end - str) >= NDX_BUFF_SIZE) { 281 *ndx = -1; 282 return end + 1; 283 } 284 strncpy(ndx_buf, str, end - str); 285 ndx_buf[end - str] = '\0'; 286 *ndx = atoi(ndx_buf); 287 return end + 1; 288} 289 290static void 291SetUpRemap(InputLine *line,RemapSpec *remap) 292{ 293char * tok,*str; 294unsigned present, l_ndx_present, v_ndx_present; 295register int i; 296int len, ndx; 297_Xstrtokparams strtok_buf; 298#ifdef DEBUG 299Bool found; 300#endif 301 302 303 l_ndx_present = v_ndx_present = present= 0; 304 str= &line->line[1]; 305 len = remap->number; 306 bzero((char *)remap,sizeof(RemapSpec)); 307 remap->number = len; 308 while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { 309#ifdef DEBUG 310 found= False; 311#endif 312 str= NULL; 313 if (strcmp(tok,"=")==0) 314 continue; 315 for (i=0;i<MAX_WORDS;i++) { 316 len = strlen(cname[i]); 317 if (strncmp(cname[i],tok,len)==0) { 318 if(strlen(tok) > len) { 319 char *end = get_index(tok+len, &ndx); 320 if ((i != LAYOUT && i != VARIANT) || 321 *end != '\0' || ndx == -1) 322 break; 323 if (ndx < 1 || ndx > XkbNumKbdGroups) { 324 PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx); 325 PR_DEBUG1("Index must be in range 1..%d\n", 326 XkbNumKbdGroups); 327 break; 328 } 329 } else { 330 ndx = 0; 331 } 332#ifdef DEBUG 333 found= True; 334#endif 335 if (present&(1<<i)) { 336 if ((i == LAYOUT && l_ndx_present&(1<<ndx)) || 337 (i == VARIANT && v_ndx_present&(1<<ndx)) ) { 338 PR_DEBUG1("Component \"%s\" listed twice\n",tok); 339 PR_DEBUG("Second definition ignored\n"); 340 break; 341 } 342 } 343 present |= (1<<i); 344 if (i == LAYOUT) 345 l_ndx_present |= 1 << ndx; 346 if (i == VARIANT) 347 v_ndx_present |= 1 << ndx; 348 remap->remap[remap->num_remap].word= i; 349 remap->remap[remap->num_remap++].index= ndx; 350 break; 351 } 352 } 353#ifdef DEBUG 354 if (!found) { 355 fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); 356 } 357#endif 358 } 359 if ((present&PART_MASK)==0) { 360#ifdef DEBUG 361 unsigned mask= PART_MASK; 362 fprintf(stderr,"Mapping needs at least one of "); 363 for (i=0; (i<MAX_WORDS); i++) { 364 if ((1L<<i)&mask) { 365 mask&= ~(1L<<i); 366 if (mask) fprintf(stderr,"\"%s,\" ",cname[i]); 367 else fprintf(stderr,"or \"%s\"\n",cname[i]); 368 } 369 } 370 fprintf(stderr,"Illegal mapping ignored\n"); 371#endif 372 remap->num_remap= 0; 373 return; 374 } 375 if ((present&COMPONENT_MASK)==0) { 376 PR_DEBUG("Mapping needs at least one component\n"); 377 PR_DEBUG("Illegal mapping ignored\n"); 378 remap->num_remap= 0; 379 return; 380 } 381 if (((present&COMPONENT_MASK)&(1<<KEYMAP))&& 382 ((present&COMPONENT_MASK)!=(1<<KEYMAP))) { 383 PR_DEBUG("Keymap cannot appear with other components\n"); 384 PR_DEBUG("Illegal mapping ignored\n"); 385 remap->num_remap= 0; 386 return; 387 } 388 remap->number++; 389 return; 390} 391 392static Bool 393MatchOneOf(char *wanted,char *vals_defined) 394{ 395char *str,*next; 396int want_len= strlen(wanted); 397 398 for (str=vals_defined,next=NULL;str!=NULL;str=next) { 399 int len; 400 next= strchr(str,','); 401 if (next) { 402 len= next-str; 403 next++; 404 } 405 else { 406 len= strlen(str); 407 } 408 if ((len==want_len)&&(strncmp(wanted,str,len)==0)) 409 return True; 410 } 411 return False; 412} 413 414/***====================================================================***/ 415 416static Bool 417CheckLine( InputLine * line, 418 RemapSpec * remap, 419 XkbRF_RulePtr rule, 420 XkbRF_GroupPtr group) 421{ 422char * str,*tok; 423register int nread, i; 424FileSpec tmp; 425_Xstrtokparams strtok_buf; 426Bool append = False; 427 428 if (line->line[0]=='!') { 429 if (line->line[1] == '$' || 430 (line->line[1] == ' ' && line->line[2] == '$')) { 431 char *gname = strchr(line->line, '$'); 432 char *words = strchr(gname, ' '); 433 if(!words) 434 return False; 435 *words++ = '\0'; 436 for (; *words; words++) { 437 if (*words != '=' && *words != ' ') 438 break; 439 } 440 if (*words == '\0') 441 return False; 442 group->name = _XkbDupString(gname); 443 group->words = _XkbDupString(words); 444 for (i = 1, words = group->words; *words; words++) { 445 if ( *words == ' ') { 446 *words++ = '\0'; 447 i++; 448 } 449 } 450 group->number = i; 451 return True; 452 } else { 453 SetUpRemap(line,remap); 454 return False; 455 } 456 } 457 458 if (remap->num_remap==0) { 459 PR_DEBUG("Must have a mapping before first line of data\n"); 460 PR_DEBUG("Illegal line of data ignored\n"); 461 return False; 462 } 463 bzero((char *)&tmp,sizeof(FileSpec)); 464 str= line->line; 465 for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { 466 str= NULL; 467 if (strcmp(tok,"=")==0) { 468 nread--; 469 continue; 470 } 471 if (nread>remap->num_remap) { 472 PR_DEBUG("Too many words on a line\n"); 473 PR_DEBUG1("Extra word \"%s\" ignored\n",tok); 474 continue; 475 } 476 tmp.name[remap->remap[nread].word]= tok; 477 if (*tok == '+' || *tok == '|') 478 append = True; 479 } 480 if (nread<remap->num_remap) { 481 PR_DEBUG1("Too few words on a line: %s\n", line->line); 482 PR_DEBUG("line ignored\n"); 483 return False; 484 } 485 486 rule->flags= 0; 487 rule->number = remap->number; 488 if (tmp.name[OPTION]) 489 rule->flags|= XkbRF_Option; 490 else if (append) 491 rule->flags|= XkbRF_Append; 492 else 493 rule->flags|= XkbRF_Normal; 494 rule->model= _XkbDupString(tmp.name[MODEL]); 495 rule->layout= _XkbDupString(tmp.name[LAYOUT]); 496 rule->variant= _XkbDupString(tmp.name[VARIANT]); 497 rule->option= _XkbDupString(tmp.name[OPTION]); 498 499 rule->keycodes= _XkbDupString(tmp.name[KEYCODES]); 500 rule->symbols= _XkbDupString(tmp.name[SYMBOLS]); 501 rule->types= _XkbDupString(tmp.name[TYPES]); 502 rule->compat= _XkbDupString(tmp.name[COMPAT]); 503 rule->geometry= _XkbDupString(tmp.name[GEOMETRY]); 504 rule->keymap= _XkbDupString(tmp.name[KEYMAP]); 505 506 rule->layout_num = rule->variant_num = 0; 507 for (i = 0; i < nread; i++) { 508 if (remap->remap[i].index) { 509 if (remap->remap[i].word == LAYOUT) 510 rule->layout_num = remap->remap[i].index; 511 if (remap->remap[i].word == VARIANT) 512 rule->variant_num = remap->remap[i].index; 513 } 514 } 515 return True; 516} 517 518static char * 519_Concat(char *str1,char *str2) 520{ 521int len; 522 523 if ((!str1)||(!str2)) 524 return str1; 525 len= strlen(str1)+strlen(str2)+1; 526 str1= _XkbTypedRealloc(str1,len,char); 527 if (str1) 528 strcat(str1,str2); 529 return str1; 530} 531 532static void 533squeeze_spaces(char *p1) 534{ 535 char *p2; 536 for (p2 = p1; *p2; p2++) { 537 *p1 = *p2; 538 if (*p1 != ' ') p1++; 539 } 540 *p1 = '\0'; 541} 542 543static Bool 544MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) 545{ 546 547 bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec)); 548 mdefs->model = defs->model; 549 mdefs->options = _XkbDupString(defs->options); 550 if (mdefs->options) squeeze_spaces(mdefs->options); 551 552 if (defs->layout) { 553 if (!strchr(defs->layout, ',')) { 554 mdefs->layout[0] = defs->layout; 555 } else { 556 char *p; 557 int i; 558 mdefs->layout[1] = _XkbDupString(defs->layout); 559 if (mdefs->layout[1] == NULL) 560 return False; 561 squeeze_spaces(mdefs->layout[1]); 562 p = mdefs->layout[1]; 563 for (i = 2; i <= XkbNumKbdGroups; i++) { 564 if ((p = strchr(p, ','))) { 565 *p++ = '\0'; 566 mdefs->layout[i] = p; 567 } else { 568 break; 569 } 570 } 571 if (p && (p = strchr(p, ','))) 572 *p = '\0'; 573 } 574 } 575 576 if (defs->variant) { 577 if (!strchr(defs->variant, ',')) { 578 mdefs->variant[0] = defs->variant; 579 } else { 580 char *p; 581 int i; 582 mdefs->variant[1] = _XkbDupString(defs->variant); 583 if (mdefs->variant[1] == NULL) 584 return False; 585 squeeze_spaces(mdefs->variant[1]); 586 p = mdefs->variant[1]; 587 for (i = 2; i <= XkbNumKbdGroups; i++) { 588 if ((p = strchr(p, ','))) { 589 *p++ = '\0'; 590 mdefs->variant[i] = p; 591 } else { 592 break; 593 } 594 } 595 if (p && (p = strchr(p, ','))) 596 *p = '\0'; 597 } 598 } 599 return True; 600} 601 602static void 603FreeMultiDefs(XkbRF_MultiDefsPtr defs) 604{ 605 if (defs->options) _XkbFree(defs->options); 606 if (defs->layout[1]) _XkbFree(defs->layout[1]); 607 if (defs->variant[1]) _XkbFree(defs->variant[1]); 608} 609 610static void 611Apply(char *src, char **dst) 612{ 613 if (src) { 614 if (*src == '+' || *src == '!') { 615 *dst= _Concat(*dst, src); 616 } else { 617 if (*dst == NULL) 618 *dst= _XkbDupString(src); 619 } 620 } 621} 622 623static void 624XkbRF_ApplyRule( XkbRF_RulePtr rule, 625 XkbComponentNamesPtr names) 626{ 627 rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ 628 629 Apply(rule->keycodes, &names->keycodes); 630 Apply(rule->symbols, &names->symbols); 631 Apply(rule->types, &names->types); 632 Apply(rule->compat, &names->compat); 633 Apply(rule->geometry, &names->geometry); 634 Apply(rule->keymap, &names->keymap); 635} 636 637static Bool 638CheckGroup( XkbRF_RulesPtr rules, 639 char * group_name, 640 char * name) 641{ 642 int i; 643 char *p; 644 XkbRF_GroupPtr group; 645 646 for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { 647 if (! strcmp(group->name, group_name)) { 648 break; 649 } 650 } 651 if (i == rules->num_groups) 652 return False; 653 for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) { 654 if (! strcmp(p, name)) { 655 return True; 656 } 657 } 658 return False; 659} 660 661static int 662XkbRF_CheckApplyRule( XkbRF_RulePtr rule, 663 XkbRF_MultiDefsPtr mdefs, 664 XkbComponentNamesPtr names, 665 XkbRF_RulesPtr rules) 666{ 667 Bool pending = False; 668 669 if (rule->model != NULL) { 670 if(mdefs->model == NULL) 671 return 0; 672 if (strcmp(rule->model, "*") == 0) { 673 pending = True; 674 } else { 675 if (rule->model[0] == '$') { 676 if (!CheckGroup(rules, rule->model, mdefs->model)) 677 return 0; 678 } else { 679 if (strcmp(rule->model, mdefs->model) != 0) 680 return 0; 681 } 682 } 683 } 684 if (rule->option != NULL) { 685 if (mdefs->options == NULL) 686 return 0; 687 if ((!MatchOneOf(rule->option,mdefs->options))) 688 return 0; 689 } 690 691 if (rule->layout != NULL) { 692 if(mdefs->layout[rule->layout_num] == NULL || 693 *mdefs->layout[rule->layout_num] == '\0') 694 return 0; 695 if (strcmp(rule->layout, "*") == 0) { 696 pending = True; 697 } else { 698 if (rule->layout[0] == '$') { 699 if (!CheckGroup(rules, rule->layout, 700 mdefs->layout[rule->layout_num])) 701 return 0; 702 } else { 703 if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) 704 return 0; 705 } 706 } 707 } 708 if (rule->variant != NULL) { 709 if (mdefs->variant[rule->variant_num] == NULL || 710 *mdefs->variant[rule->variant_num] == '\0') 711 return 0; 712 if (strcmp(rule->variant, "*") == 0) { 713 pending = True; 714 } else { 715 if (rule->variant[0] == '$') { 716 if (!CheckGroup(rules, rule->variant, 717 mdefs->variant[rule->variant_num])) 718 return 0; 719 } else { 720 if (strcmp(rule->variant, 721 mdefs->variant[rule->variant_num]) != 0) 722 return 0; 723 } 724 } 725 } 726 if (pending) { 727 rule->flags|= XkbRF_PendingMatch; 728 return rule->number; 729 } 730 /* exact match, apply it now */ 731 XkbRF_ApplyRule(rule,names); 732 return rule->number; 733} 734 735static void 736XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) 737{ 738register int i; 739XkbRF_RulePtr rule; 740 741 for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 742 rule->flags&= ~XkbRF_PendingMatch; 743 } 744} 745 746static void 747XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) 748{ 749int i; 750XkbRF_RulePtr rule; 751 752 for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { 753 if ((rule->flags&XkbRF_PendingMatch)==0) 754 continue; 755 XkbRF_ApplyRule(rule,names); 756 } 757} 758 759static void 760XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, 761 XkbRF_MultiDefsPtr mdefs, 762 XkbComponentNamesPtr names, 763 int flags) 764{ 765int i; 766XkbRF_RulePtr rule; 767int skip; 768 769 for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) { 770 if ((rule->flags & flags) != flags) 771 continue; 772 skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); 773 if (skip && !(flags & XkbRF_Option)) { 774 for ( ;(i < rules->num_rules) && (rule->number == skip); 775 rule++, i++); 776 rule--; i--; 777 } 778 } 779} 780 781/***====================================================================***/ 782 783static char * 784XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) 785{ 786char *str, *outstr, *orig, *var; 787int len, ndx; 788 789 orig= name; 790 str= index(name,'%'); 791 if (str==NULL) 792 return name; 793 len= strlen(name); 794 while (str!=NULL) { 795 char pfx= str[1]; 796 int extra_len= 0; 797 if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 798 extra_len= 1; 799 str++; 800 } 801 else if (pfx=='(') { 802 extra_len= 2; 803 str++; 804 } 805 var = str + 1; 806 str = get_index(var + 1, &ndx); 807 if (ndx == -1) { 808 str = index(str,'%'); 809 continue; 810 } 811 if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) 812 len+= strlen(mdefs->layout[ndx])+extra_len; 813 else if ((*var=='m')&&mdefs->model) 814 len+= strlen(mdefs->model)+extra_len; 815 else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) 816 len+= strlen(mdefs->variant[ndx])+extra_len; 817 if ((pfx=='(')&&(*str==')')) { 818 str++; 819 } 820 str= index(&str[0],'%'); 821 } 822 name= (char *)_XkbAlloc(len+1); 823 str= orig; 824 outstr= name; 825 while (*str!='\0') { 826 if (str[0]=='%') { 827 char pfx,sfx; 828 str++; 829 pfx= str[0]; 830 sfx= '\0'; 831 if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { 832 str++; 833 } 834 else if (pfx=='(') { 835 sfx= ')'; 836 str++; 837 } 838 else pfx= '\0'; 839 840 var = str; 841 str = get_index(var + 1, &ndx); 842 if (ndx == -1) { 843 continue; 844 } 845 if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { 846 if (pfx) *outstr++= pfx; 847 strcpy(outstr,mdefs->layout[ndx]); 848 outstr+= strlen(mdefs->layout[ndx]); 849 if (sfx) *outstr++= sfx; 850 } 851 else if ((*var=='m')&&(mdefs->model)) { 852 if (pfx) *outstr++= pfx; 853 strcpy(outstr,mdefs->model); 854 outstr+= strlen(mdefs->model); 855 if (sfx) *outstr++= sfx; 856 } 857 else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) { 858 if (pfx) *outstr++= pfx; 859 strcpy(outstr,mdefs->variant[ndx]); 860 outstr+= strlen(mdefs->variant[ndx]); 861 if (sfx) *outstr++= sfx; 862 } 863 if ((pfx=='(')&&(*str==')')) 864 str++; 865 } 866 else { 867 *outstr++= *str++; 868 } 869 } 870 *outstr++= '\0'; 871 if (orig!=name) 872 _XkbFree(orig); 873 return name; 874} 875 876/***====================================================================***/ 877 878Bool 879XkbRF_GetComponents( XkbRF_RulesPtr rules, 880 XkbRF_VarDefsPtr defs, 881 XkbComponentNamesPtr names) 882{ 883 XkbRF_MultiDefsRec mdefs; 884 885 MakeMultiDefs(&mdefs, defs); 886 887 bzero((char *)names,sizeof(XkbComponentNamesRec)); 888 XkbRF_ClearPartialMatches(rules); 889 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal); 890 XkbRF_ApplyPartialMatches(rules, names); 891 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); 892 XkbRF_ApplyPartialMatches(rules, names); 893 XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); 894 895 if (names->keycodes) 896 names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); 897 if (names->symbols) 898 names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); 899 if (names->types) 900 names->types= XkbRF_SubstituteVars(names->types, &mdefs); 901 if (names->compat) 902 names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); 903 if (names->geometry) 904 names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); 905 if (names->keymap) 906 names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs); 907 908 FreeMultiDefs(&mdefs); 909 return (names->keycodes && names->symbols && names->types && 910 names->compat && names->geometry ) || names->keymap; 911} 912 913XkbRF_RulePtr 914XkbRF_AddRule(XkbRF_RulesPtr rules) 915{ 916 if (rules->sz_rules<1) { 917 rules->sz_rules= 16; 918 rules->num_rules= 0; 919 rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); 920 } 921 else if (rules->num_rules>=rules->sz_rules) { 922 rules->sz_rules*= 2; 923 rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules, 924 XkbRF_RuleRec); 925 } 926 if (!rules->rules) { 927 rules->sz_rules= rules->num_rules= 0; 928#ifdef DEBUG 929 fprintf(stderr,"Allocation failure in XkbRF_AddRule\n"); 930#endif 931 return NULL; 932 } 933 bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec)); 934 return &rules->rules[rules->num_rules++]; 935} 936 937XkbRF_GroupPtr 938XkbRF_AddGroup(XkbRF_RulesPtr rules) 939{ 940 if (rules->sz_groups<1) { 941 rules->sz_groups= 16; 942 rules->num_groups= 0; 943 rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec); 944 } 945 else if (rules->num_groups >= rules->sz_groups) { 946 rules->sz_groups *= 2; 947 rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups, 948 XkbRF_GroupRec); 949 } 950 if (!rules->groups) { 951 rules->sz_groups= rules->num_groups= 0; 952 return NULL; 953 } 954 955 bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec)); 956 return &rules->groups[rules->num_groups++]; 957} 958 959Bool 960XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) 961{ 962InputLine line; 963RemapSpec remap; 964XkbRF_RuleRec trule,*rule; 965XkbRF_GroupRec tgroup,*group; 966 967 if (!(rules && file)) 968 return False; 969 bzero((char *)&remap,sizeof(RemapSpec)); 970 bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); 971 InitInputLine(&line); 972 while (GetInputLine(file,&line,True)) { 973 if (CheckLine(&line,&remap,&trule,&tgroup)) { 974 if (tgroup.number) { 975 if ((group= XkbRF_AddGroup(rules))!=NULL) { 976 *group= tgroup; 977 bzero((char *)&tgroup,sizeof(XkbRF_GroupRec)); 978 } 979 } else { 980 if ((rule= XkbRF_AddRule(rules))!=NULL) { 981 *rule= trule; 982 bzero((char *)&trule,sizeof(XkbRF_RuleRec)); 983 } 984 } 985 } 986 line.num_line= 0; 987 } 988 FreeInputLine(&line); 989 return True; 990} 991 992Bool 993XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) 994{ 995FILE * file; 996char buf[PATH_MAX]; 997Bool ok; 998 999 if ((!base)||(!rules)) 1000 return False; 1001 if (locale) { 1002 if (strlen(base)+strlen(locale)+2 > PATH_MAX) 1003 return False; 1004 sprintf(buf,"%s-%s", base, locale); 1005 } 1006 else { 1007 if (strlen(base)+1 > PATH_MAX) 1008 return False; 1009 strcpy(buf,base); 1010 } 1011 1012 file= fopen(buf, "r"); 1013 if ((!file)&&(locale)) { /* fallback if locale was specified */ 1014 strcpy(buf,base); 1015 file= fopen(buf, "r"); 1016 } 1017 if (!file) 1018 return False; 1019 ok= XkbRF_LoadRules(file,rules); 1020 fclose(file); 1021 return ok; 1022} 1023 1024/***====================================================================***/ 1025 1026#define HEAD_NONE 0 1027#define HEAD_MODEL 1 1028#define HEAD_LAYOUT 2 1029#define HEAD_VARIANT 3 1030#define HEAD_OPTION 4 1031#define HEAD_EXTRA 5 1032 1033XkbRF_VarDescPtr 1034XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars) 1035{ 1036 if (vars->sz_desc<1) { 1037 vars->sz_desc= 16; 1038 vars->num_desc= 0; 1039 vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec); 1040 } 1041 else if (vars->num_desc>=vars->sz_desc) { 1042 vars->sz_desc*= 2; 1043 vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec); 1044 } 1045 if (!vars->desc) { 1046 vars->sz_desc= vars->num_desc= 0; 1047 PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n"); 1048 return NULL; 1049 } 1050 vars->desc[vars->num_desc].name= NULL; 1051 vars->desc[vars->num_desc].desc= NULL; 1052 return &vars->desc[vars->num_desc++]; 1053} 1054 1055XkbRF_VarDescPtr 1056XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from) 1057{ 1058XkbRF_VarDescPtr nd; 1059 1060 if ((nd=XkbRF_AddVarDesc(vars))!=NULL) { 1061 nd->name= _XkbDupString(from->name); 1062 nd->desc= _XkbDupString(from->desc); 1063 } 1064 return nd; 1065} 1066 1067XkbRF_DescribeVarsPtr 1068XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name) 1069{ 1070 if (rules->sz_extra<1) { 1071 rules->num_extra= 0; 1072 rules->sz_extra= 1; 1073 rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *); 1074 rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec); 1075 } 1076 else if (rules->num_extra>=rules->sz_extra) { 1077 rules->sz_extra*= 2; 1078 rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra, 1079 char *); 1080 rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra, 1081 XkbRF_DescribeVarsRec); 1082 } 1083 if ((!rules->extra_names)||(!rules->extra)) { 1084 PR_DEBUG("allocation error in extra parts\n"); 1085 rules->sz_extra= rules->num_extra= 0; 1086 rules->extra_names= NULL; 1087 rules->extra= NULL; 1088 return NULL; 1089 } 1090 rules->extra_names[rules->num_extra]= _XkbDupString(name); 1091 bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec)); 1092 return &rules->extra[rules->num_extra++]; 1093} 1094 1095Bool 1096XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules) 1097{ 1098InputLine line; 1099XkbRF_VarDescRec tmp; 1100char *tok; 1101int len,headingtype,extra_ndx = 0; 1102 1103 bzero((char *)&tmp, sizeof(XkbRF_VarDescRec)); 1104 headingtype = HEAD_NONE; 1105 InitInputLine(&line); 1106 for ( ; GetInputLine(file,&line,False); line.num_line= 0) { 1107 if (line.line[0]=='!') { 1108 tok = strtok(&(line.line[1]), " \t"); 1109 if (strcmp(tok,"model") == 0) 1110 headingtype = HEAD_MODEL; 1111 else if (_XkbStrCaseCmp(tok,"layout") == 0) 1112 headingtype = HEAD_LAYOUT; 1113 else if (_XkbStrCaseCmp(tok,"variant") == 0) 1114 headingtype = HEAD_VARIANT; 1115 else if (_XkbStrCaseCmp(tok,"option") == 0) 1116 headingtype = HEAD_OPTION; 1117 else { 1118 int i; 1119 headingtype = HEAD_EXTRA; 1120 extra_ndx= -1; 1121 for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) { 1122 if (_XkbStrCaseCmp(tok,rules->extra_names[i])) 1123 extra_ndx= i; 1124 } 1125 if (extra_ndx<0) { 1126 XkbRF_DescribeVarsPtr var; 1127 PR_DEBUG1("Extra heading \"%s\" encountered\n",tok); 1128 var= XkbRF_AddVarToDescribe(rules,tok); 1129 if (var) 1130 extra_ndx= var-rules->extra; 1131 else headingtype= HEAD_NONE; 1132 } 1133 } 1134 continue; 1135 } 1136 1137 if (headingtype == HEAD_NONE) { 1138 PR_DEBUG("Must have a heading before first line of data\n"); 1139 PR_DEBUG("Illegal line of data ignored\n"); 1140 continue; 1141 } 1142 1143 len = strlen(line.line); 1144 if ((tmp.name= strtok(line.line, " \t")) == NULL) { 1145 PR_DEBUG("Huh? No token on line\n"); 1146 PR_DEBUG("Illegal line of data ignored\n"); 1147 continue; 1148 } 1149 if (strlen(tmp.name) == len) { 1150 PR_DEBUG("No description found\n"); 1151 PR_DEBUG("Illegal line of data ignored\n"); 1152 continue; 1153 } 1154 1155 tok = line.line + strlen(tmp.name) + 1; 1156 while ((*tok!='\n')&&isspace(*tok)) 1157 tok++; 1158 if (*tok == '\0') { 1159 PR_DEBUG("No description found\n"); 1160 PR_DEBUG("Illegal line of data ignored\n"); 1161 continue; 1162 } 1163 tmp.desc= tok; 1164 switch (headingtype) { 1165 case HEAD_MODEL: 1166 XkbRF_AddVarDescCopy(&rules->models,&tmp); 1167 break; 1168 case HEAD_LAYOUT: 1169 XkbRF_AddVarDescCopy(&rules->layouts,&tmp); 1170 break; 1171 case HEAD_VARIANT: 1172 XkbRF_AddVarDescCopy(&rules->variants,&tmp); 1173 break; 1174 case HEAD_OPTION: 1175 XkbRF_AddVarDescCopy(&rules->options,&tmp); 1176 break; 1177 case HEAD_EXTRA: 1178 XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp); 1179 break; 1180 } 1181 } 1182 FreeInputLine(&line); 1183 if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) && 1184 (rules->variants.num_desc==0) && (rules->options.num_desc==0) && 1185 (rules->num_extra==0)) { 1186 return False; 1187 } 1188 return True; 1189} 1190 1191Bool 1192XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules) 1193{ 1194FILE * file; 1195char buf[PATH_MAX]; 1196Bool ok; 1197 1198 if ((!base)||(!rules)) 1199 return False; 1200 if (locale) { 1201 if (strlen(base)+strlen(locale)+6 > PATH_MAX) 1202 return False; 1203 sprintf(buf,"%s-%s.lst", base, locale); 1204 } 1205 else { 1206 if (strlen(base)+5 > PATH_MAX) 1207 return False; 1208 sprintf(buf,"%s.lst", base); 1209 } 1210 1211 file= fopen(buf, "r"); 1212 if ((!file)&&(locale)) { /* fallback if locale was specified */ 1213 sprintf(buf,"%s.lst", base); 1214 1215 file= fopen(buf, "r"); 1216 } 1217 if (!file) 1218 return False; 1219 ok= XkbRF_LoadDescriptions(file,rules); 1220 fclose(file); 1221 return ok; 1222} 1223 1224/***====================================================================***/ 1225 1226XkbRF_RulesPtr 1227XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules) 1228{ 1229XkbRF_RulesPtr rules; 1230 1231 if ((!base)||((!wantDesc)&&(!wantRules))) 1232 return NULL; 1233 if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) 1234 return NULL; 1235 if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) { 1236 XkbRF_Free(rules,True); 1237 return NULL; 1238 } 1239 if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) { 1240 XkbRF_Free(rules,True); 1241 return NULL; 1242 } 1243 return rules; 1244} 1245 1246XkbRF_RulesPtr 1247XkbRF_Create(int szRules,int szExtra) 1248{ 1249XkbRF_RulesPtr rules; 1250 1251 if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL) 1252 return NULL; 1253 if (szRules>0) { 1254 rules->sz_rules= szRules; 1255 rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec); 1256 if (!rules->rules) { 1257 _XkbFree(rules); 1258 return NULL; 1259 } 1260 } 1261 if (szExtra>0) { 1262 rules->sz_extra= szExtra; 1263 rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec); 1264 if (!rules->extra) { 1265 if (rules->rules) 1266 _XkbFree(rules->rules); 1267 _XkbFree(rules); 1268 return NULL; 1269 } 1270 } 1271 return rules; 1272} 1273 1274/***====================================================================***/ 1275 1276static void 1277XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var) 1278{ 1279register int i; 1280 1281 for (i=0;i<var->num_desc;i++) { 1282 if (var->desc[i].name) 1283 _XkbFree(var->desc[i].name); 1284 if (var->desc[i].desc) 1285 _XkbFree(var->desc[i].desc); 1286 var->desc[i].name= var->desc[i].desc= NULL; 1287 } 1288 if (var->desc) 1289 _XkbFree(var->desc); 1290 var->desc= NULL; 1291 return; 1292} 1293 1294void 1295XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) 1296{ 1297int i; 1298XkbRF_RulePtr rule; 1299XkbRF_GroupPtr group; 1300 1301 if (!rules) 1302 return; 1303 XkbRF_ClearVarDescriptions(&rules->models); 1304 XkbRF_ClearVarDescriptions(&rules->layouts); 1305 XkbRF_ClearVarDescriptions(&rules->variants); 1306 XkbRF_ClearVarDescriptions(&rules->options); 1307 if (rules->extra) { 1308 for (i = 0; i < rules->num_extra; i++) { 1309 XkbRF_ClearVarDescriptions(&rules->extra[i]); 1310 } 1311 _XkbFree(rules->extra); 1312 rules->num_extra= rules->sz_extra= 0; 1313 rules->extra= NULL; 1314 } 1315 if (rules->rules) { 1316 for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { 1317 if (rule->model) _XkbFree(rule->model); 1318 if (rule->layout) _XkbFree(rule->layout); 1319 if (rule->variant) _XkbFree(rule->variant); 1320 if (rule->option) _XkbFree(rule->option); 1321 if (rule->keycodes) _XkbFree(rule->keycodes); 1322 if (rule->symbols) _XkbFree(rule->symbols); 1323 if (rule->types) _XkbFree(rule->types); 1324 if (rule->compat) _XkbFree(rule->compat); 1325 if (rule->geometry) _XkbFree(rule->geometry); 1326 if (rule->keymap) _XkbFree(rule->keymap); 1327 bzero((char *)rule,sizeof(XkbRF_RuleRec)); 1328 } 1329 _XkbFree(rules->rules); 1330 rules->num_rules= rules->sz_rules= 0; 1331 rules->rules= NULL; 1332 } 1333 1334 if (rules->groups) { 1335 for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) { 1336 if (group->name) _XkbFree(group->name); 1337 if (group->words) _XkbFree(group->words); 1338 } 1339 _XkbFree(rules->groups); 1340 rules->num_groups= 0; 1341 rules->groups= NULL; 1342 } 1343 if (freeRules) 1344 _XkbFree(rules); 1345 return; 1346} 1347 1348#ifndef XKB_IN_SERVER 1349 1350Bool 1351XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn) 1352{ 1353Atom rules_atom,actual_type; 1354int fmt; 1355unsigned long nitems,bytes_after; 1356unsigned char *data; 1357char *out, *end; 1358Status rtrn; 1359 1360 rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,True); 1361 if (rules_atom==None) /* property cannot exist */ 1362 return False; 1363 rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy),rules_atom, 1364 0L,_XKB_RF_NAMES_PROP_MAXLEN,False, 1365 XA_STRING,&actual_type, 1366 &fmt,&nitems,&bytes_after, 1367 (unsigned char **)&data); 1368 if (rtrn!=Success) 1369 return False; 1370 if (rf_rtrn) 1371 *rf_rtrn= NULL; 1372 (void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec)); 1373 if ((bytes_after>0)||(actual_type!=XA_STRING)||(fmt!=8)) { 1374 if (data) XFree(data); 1375 return (fmt==0?True:False); 1376 } 1377 1378 out=(char*)data; 1379 end=out+nitems; 1380 if (out && (*out) && rf_rtrn) 1381 *rf_rtrn= _XkbDupString(out); 1382 out+=strlen(out)+1; 1383 1384 if (out<end) { 1385 if (*out) 1386 vd_rtrn->model= _XkbDupString(out); 1387 out+=strlen(out)+1; 1388 } 1389 1390 if (out<end) { 1391 if (*out) 1392 vd_rtrn->layout= _XkbDupString(out); 1393 out+=strlen(out)+1; 1394 } 1395 1396 if (out<end) { 1397 if (*out) 1398 vd_rtrn->variant= _XkbDupString(out); 1399 out+=strlen(out)+1; 1400 } 1401 1402 if (out<end) { 1403 if (*out) 1404 vd_rtrn->options= _XkbDupString(out); 1405 out+=strlen(out)+1; 1406 } 1407 1408 XFree(data); 1409 return True; 1410} 1411 1412Bool 1413XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs) 1414{ 1415int len,out; 1416Atom name; 1417char * pval; 1418 1419 len= (rules_file?strlen(rules_file):0); 1420 len+= (var_defs->model?strlen(var_defs->model):0); 1421 len+= (var_defs->layout?strlen(var_defs->layout):0); 1422 len+= (var_defs->variant?strlen(var_defs->variant):0); 1423 len+= (var_defs->options?strlen(var_defs->options):0); 1424 if (len<1) 1425 return True; 1426 1427 len+= 5; /* trailing NULs */ 1428 1429 name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,False); 1430 if (name==None) { /* should never happen */ 1431 _XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom); 1432 return False; 1433 } 1434 pval= (char *)_XkbAlloc(len); 1435 if (!pval) { 1436 _XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len); 1437 return False; 1438 } 1439 out= 0; 1440 if (rules_file) { 1441 strcpy(&pval[out],rules_file); 1442 out+= strlen(rules_file); 1443 } 1444 pval[out++]= '\0'; 1445 if (var_defs->model) { 1446 strcpy(&pval[out],var_defs->model); 1447 out+= strlen(var_defs->model); 1448 } 1449 pval[out++]= '\0'; 1450 if (var_defs->layout) { 1451 strcpy(&pval[out],var_defs->layout); 1452 out+= strlen(var_defs->layout); 1453 } 1454 pval[out++]= '\0'; 1455 if (var_defs->variant) { 1456 strcpy(&pval[out],var_defs->variant); 1457 out+= strlen(var_defs->variant); 1458 } 1459 pval[out++]= '\0'; 1460 if (var_defs->options) { 1461 strcpy(&pval[out],var_defs->options); 1462 out+= strlen(var_defs->options); 1463 } 1464 pval[out++]= '\0'; 1465 if (out!=len) { 1466 _XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out); 1467 _XkbFree(pval); 1468 return False; 1469 } 1470 1471 XChangeProperty(dpy,DefaultRootWindow(dpy),name,XA_STRING,8,PropModeReplace, 1472 (unsigned char *)pval,len); 1473 _XkbFree(pval); 1474 return True; 1475} 1476 1477#endif 1478