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