geometry.c revision f46a6179
1/* $Xorg: geometry.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1994 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/programs/xkbcomp/geometry.c,v 1.5tsi Exp $ */ 28 29#include "xkbcomp.h" 30#include "tokens.h" 31#include "expr.h" 32#include "vmod.h" 33#include "misc.h" 34#include "indicators.h" 35#include "action.h" 36#include "keycodes.h" 37#include "alias.h" 38 39#include "X11/extensions/XKBgeom.h" 40 41#define DFLT_FONT "helvetica" 42#define DFLT_SLANT "r" 43#define DFLT_WEIGHT "medium" 44#define DFLT_SET_WIDTH "normal" 45#define DFLT_VARIANT "" 46#define DFLT_ENCODING "iso8859-1" 47#define DFLT_SIZE 120 48 49typedef struct _PropertyInfo { 50 CommonInfo defs; 51 char * name; 52 char * value; 53} PropertyInfo; 54 55#define _GSh_Outlines (1<<1) 56#define _GSh_Approx (1<<2) 57#define _GSh_Primary (1<<3) 58typedef struct _ShapeInfo { 59 CommonInfo defs; 60 Atom name; 61 short index; 62 unsigned short nOutlines; 63 unsigned short szOutlines; 64 XkbOutlinePtr outlines; 65 XkbOutlinePtr approx; 66 XkbOutlinePtr primary; 67 int dfltCornerRadius; 68} ShapeInfo; 69 70#define shText(d,s) \ 71 ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default shape") 72 73#define _GD_Priority (1<<0) 74#define _GD_Top (1<<1) 75#define _GD_Left (1<<2) 76#define _GD_Angle (1<<3) 77#define _GD_Shape (1<<4) 78#define _GD_FontVariant (1<<4) /* CHEATING */ 79#define _GD_Corner (1<<5) 80#define _GD_Width (1<<5) /* CHEATING */ 81#define _GD_Color (1<<6) 82#define _GD_OffColor (1<<7) 83#define _GD_Height (1<<7) /* CHEATING */ 84#define _GD_Text (1<<8) 85#define _GD_Font (1<<9) 86#define _GD_FontSlant (1<<10) 87#define _GD_FontWeight (1<<11) 88#define _GD_FontSetWidth (1<<12) 89#define _GD_FontSize (1<<13) 90#define _GD_FontEncoding (1<<14) 91#define _GD_FontSpec (1<<15) 92 93 94#define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant) 95 96typedef struct _DoodadInfo { 97 CommonInfo defs; 98 Atom name; 99 unsigned char type; 100 unsigned char priority; 101 short top; 102 short left; 103 short angle; 104 unsigned short corner; 105 unsigned short width; 106 unsigned short height; 107 Atom shape; 108 Atom color; 109 Atom offColor; 110 Atom text; 111 Atom font; 112 Atom fontSlant; 113 Atom fontWeight; 114 Atom fontSetWidth; 115 Atom fontVariant; 116 unsigned short fontSize; 117 Atom fontEncoding; 118 Atom fontSpec; 119 char * logoName; 120 struct _SectionInfo *section; 121} DoodadInfo; 122 123#define Yes 1 124#define No 0 125#define Undefined -1 126 127#define _GK_Default (1<<0) 128#define _GK_Name (1<<1) 129#define _GK_Gap (1<<2) 130#define _GK_Shape (1<<3) 131#define _GK_Color (1<<4) 132typedef struct _KeyInfo { 133 CommonInfo defs; 134 char name[8]; 135 short gap; 136 short index; 137 Atom shape; 138 Atom color; 139 struct _RowInfo * row; 140} KeyInfo; 141#define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default") 142 143#define _GR_Default (1<<0) 144#define _GR_Vertical (1<<1) 145#define _GR_Top (1<<2) 146#define _GR_Left (1<<3) 147typedef struct _RowInfo { 148 CommonInfo defs; 149 unsigned short top; 150 unsigned short left; 151 short index; 152 Bool vertical; 153 unsigned short nKeys; 154 KeyInfo * keys; 155 KeyInfo dfltKey; 156 struct _SectionInfo *section; 157} RowInfo; 158#define rowText(d,r) \ 159 ((r)?XkbAtomText((d),(r)->section->name,XkbMessage):"default") 160 161#define _GOK_UnknownRow -1 162typedef struct _OverlayKeyInfo { 163 CommonInfo defs; 164 short sectionRow; 165 short overlayRow; 166 char over[XkbKeyNameLength+1]; 167 char under[XkbKeyNameLength+1]; 168} OverlayKeyInfo; 169 170typedef struct _OverlayInfo { 171 CommonInfo defs; 172 Atom name; 173 unsigned short nRows; 174 unsigned short nKeys; 175 OverlayKeyInfo *keys; 176} OverlayInfo; 177#define oiText(d,o) ((o)?XkbAtomText((d),(o)->name,XkbMessage):"default") 178 179 180#define _GS_Default (1<<0) 181#define _GS_Name (1<<1) 182#define _GS_Top (1<<2) 183#define _GS_Left (1<<3) 184#define _GS_Width (1<<4) 185#define _GS_Height (1<<5) 186#define _GS_Angle (1<<6) 187#define _GS_Priority (1<<7) 188typedef struct _SectionInfo { 189 CommonInfo defs; 190 Atom name; 191 unsigned short top; 192 unsigned short left; 193 unsigned short width; 194 unsigned short height; 195 unsigned short angle; 196 unsigned short nRows; 197 unsigned short nDoodads; 198 unsigned short nOverlays; 199 unsigned char priority; 200 unsigned char nextDoodadPriority; 201 RowInfo * rows; 202 DoodadInfo * doodads; 203 RowInfo dfltRow; 204 DoodadInfo * dfltDoodads; 205 OverlayInfo * overlays; 206 struct _GeometryInfo *geometry; 207} SectionInfo; 208#define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default") 209 210typedef struct _GeometryInfo { 211 char * name; 212 Display * dpy; 213 unsigned fileID; 214 unsigned merge; 215 int errorCount; 216 unsigned nextPriority; 217 int nProps; 218 int nShapes; 219 int nSections; 220 int nDoodads; 221 PropertyInfo * props; 222 ShapeInfo * shapes; 223 SectionInfo * sections; 224 DoodadInfo * doodads; 225 int widthMM; 226 int heightMM; 227 Atom font; 228 Atom fontSlant; 229 Atom fontWeight; 230 Atom fontSetWidth; 231 Atom fontVariant; 232 unsigned fontSize; 233 Atom fontEncoding; 234 Atom fontSpec; 235 Atom baseColor; 236 Atom labelColor; 237 int dfltCornerRadius; 238 SectionInfo dfltSection; 239 DoodadInfo * dfltDoodads; 240 AliasInfo * aliases; 241} GeometryInfo; 242 243static char * 244ddText(Display *dpy,DoodadInfo *di) 245{ 246static char buf[64]; 247 248 if (di==NULL) { 249 strcpy(buf,"default"); 250 return buf; 251 } 252 if (di->section) { 253 sprintf(buf,"%s in section %s",XkbAtomText(dpy,di->name,XkbMessage), 254 scText(dpy,di->section)); 255 return buf; 256 } 257 return XkbAtomText(dpy,di->name,XkbMessage); 258} 259 260/***====================================================================***/ 261 262static void 263InitPropertyInfo(PropertyInfo *pi,GeometryInfo *info) 264{ 265 pi->defs.defined= 0; 266 pi->defs.fileID= info->fileID; 267 pi->defs.merge= info->merge; 268 pi->name= pi->value= NULL; 269 return; 270} 271 272static void 273FreeProperties(PropertyInfo *pi,GeometryInfo *info) 274{ 275PropertyInfo * tmp; 276PropertyInfo * next; 277 278 if (info->props==pi) { 279 info->props= NULL; 280 info->nProps= 0; 281 } 282 for (tmp=pi;tmp!=NULL;tmp=next) { 283 if (tmp->name) 284 uFree(tmp->name); 285 if (tmp->value) 286 uFree(tmp->value); 287 tmp->name= tmp->value=NULL; 288 next= (PropertyInfo *)tmp->defs.next; 289 uFree(tmp); 290 } 291 return; 292} 293 294static void 295InitKeyInfo(KeyInfo *key,RowInfo *row,GeometryInfo *info) 296{ 297 298 if (key!=&row->dfltKey) { 299 *key= row->dfltKey; 300 strcpy(key->name,"unknown"); 301 key->defs.defined&= ~_GK_Default; 302 } 303 else { 304 bzero(key,sizeof(KeyInfo)); 305 strcpy(key->name,"default"); 306 key->defs.defined= _GK_Default; 307 key->defs.fileID= info->fileID; 308 key->defs.merge= info->merge; 309 key->defs.next= NULL; 310 key->row= row; 311 } 312 return; 313} 314 315static void 316ClearKeyInfo(KeyInfo *key) 317{ 318 key->defs.defined&= ~_GK_Default; 319 strcpy(key->name,"default"); 320 key->gap= 0; 321 key->shape= None; 322 key->color= None; 323 return; 324} 325 326static void 327FreeKeys(KeyInfo *key,RowInfo *row,GeometryInfo *info) 328{ 329KeyInfo * tmp; 330KeyInfo * next; 331 332 if (row->keys==key) { 333 row->nKeys= 0; 334 row->keys= NULL; 335 } 336 for (tmp=key;tmp!=NULL;tmp=next) { 337 ClearKeyInfo(tmp); 338 next= (KeyInfo *)tmp->defs.next; 339 uFree(tmp); 340 } 341 return; 342} 343 344static void 345InitRowInfo(RowInfo *row,SectionInfo *section,GeometryInfo *info) 346{ 347 if (row!= §ion->dfltRow) { 348 *row= section->dfltRow; 349 row->defs.defined&= ~_GR_Default; 350 } 351 else { 352 bzero(row,sizeof(RowInfo *)); 353 row->defs.defined= _GR_Default; 354 row->defs.fileID= info->fileID; 355 row->defs.merge= info->merge; 356 row->defs.next= NULL; 357 row->section= section; 358 row->nKeys= 0; 359 row->keys= NULL; 360 InitKeyInfo(&row->dfltKey,row,info); 361 } 362 return; 363} 364 365static void 366ClearRowInfo(RowInfo *row,GeometryInfo *info) 367{ 368 row->defs.defined&= ~_GR_Default; 369 row->top= row->left= 0; 370 row->vertical= False; 371 row->nKeys= 0; 372 if (row->keys) 373 FreeKeys(row->keys,row,info); 374 ClearKeyInfo(&row->dfltKey); 375 row->dfltKey.defs.defined|= _GK_Default; 376 return; 377} 378 379static void 380FreeRows(RowInfo *row,SectionInfo *section,GeometryInfo *info) 381{ 382RowInfo * next; 383RowInfo * tmp; 384 385 if (row==section->rows) { 386 section->nRows= 0; 387 section->rows= NULL; 388 } 389 for (tmp=row;tmp!=NULL;tmp=next) { 390 ClearRowInfo(tmp,info); 391 next= (RowInfo *)tmp->defs.next; 392 uFree(tmp); 393 } 394 return; 395} 396 397static DoodadInfo * 398FindDoodadByType(DoodadInfo *di,unsigned type) 399{ 400 while (di) { 401 if (di->type==type) 402 return di; 403 di= (DoodadInfo *)di->defs.next; 404 } 405 return NULL; 406} 407 408static DoodadInfo * 409FindDoodadByName(DoodadInfo *di,Atom name) 410{ 411 while (di) { 412 if (di->name==name) 413 return di; 414 di= (DoodadInfo *)di->defs.next; 415 } 416 return NULL; 417} 418 419static void 420InitDoodadInfo(DoodadInfo *di,unsigned type,SectionInfo *si,GeometryInfo *info) 421{ 422DoodadInfo * dflt; 423 424 dflt= NULL; 425 if (si && si->dfltDoodads) 426 dflt= FindDoodadByType(si->dfltDoodads,type); 427 if ((dflt==NULL)&&(info->dfltDoodads)) 428 dflt= FindDoodadByType(info->dfltDoodads,type); 429 if (dflt!=NULL) { 430 *di= *dflt; 431 di->defs.next= NULL; 432 } 433 else { 434 bzero(di,sizeof(DoodadInfo)); 435 di->defs.fileID= info->fileID; 436 di->type= type; 437 } 438 di->section= si; 439 if (si!=NULL) { 440 di->priority= si->nextDoodadPriority++; 441#if XkbGeomMaxPriority < 255 442 if (si->nextDoodadPriority>XkbGeomMaxPriority) 443 si->nextDoodadPriority= XkbGeomMaxPriority; 444#endif 445 } 446 else { 447 di->priority= info->nextPriority++; 448 if (info->nextPriority>XkbGeomMaxPriority) 449 info->nextPriority= XkbGeomMaxPriority; 450 } 451 return; 452} 453 454static void 455ClearDoodadInfo(DoodadInfo *di) 456{ 457CommonInfo defs; 458 459 defs= di->defs; 460 bzero(di,sizeof(DoodadInfo)); 461 di->defs= defs; 462 di->defs.defined= 0; 463 return; 464} 465 466static void 467ClearOverlayInfo(OverlayInfo *ol) 468{ 469 if (ol && ol->keys) { 470 ol->keys= (OverlayKeyInfo *)ClearCommonInfo(&ol->keys->defs); 471 ol->nKeys= 0; 472 } 473 return; 474} 475 476static void 477FreeDoodads(DoodadInfo *di,SectionInfo *si,GeometryInfo *info) 478{ 479DoodadInfo * tmp; 480DoodadInfo * next; 481 482 if (si) { 483 if (si->doodads==di) { 484 si->doodads= NULL; 485 si->nDoodads= 0; 486 } 487 if (si->dfltDoodads==di) 488 si->dfltDoodads= NULL; 489 } 490 if (info->doodads==di) { 491 info->doodads= NULL; 492 info->nDoodads= 0; 493 } 494 if (info->dfltDoodads==di) 495 info->dfltDoodads= NULL; 496 for (tmp=di;tmp!=NULL;tmp=next) { 497 next= (DoodadInfo *)tmp->defs.next; 498 ClearDoodadInfo(tmp); 499 uFree(tmp); 500 } 501 return; 502} 503 504static void 505InitSectionInfo(SectionInfo *si,GeometryInfo *info) 506{ 507 if (si!=&info->dfltSection) { 508 *si= info->dfltSection; 509 si->defs.defined&= ~_GS_Default; 510 si->name= XkbInternAtom(info->dpy,"unknown",False); 511 si->priority= info->nextPriority++; 512 if (info->nextPriority>XkbGeomMaxPriority) 513 info->nextPriority= XkbGeomMaxPriority; 514 } 515 else { 516 bzero(si,sizeof(SectionInfo)); 517 si->defs.fileID= info->fileID; 518 si->defs.merge= info->merge; 519 si->defs.next= NULL; 520 si->geometry= info; 521 si->name= XkbInternAtom(info->dpy,"default",False); 522 InitRowInfo(&si->dfltRow,si,info); 523 } 524 return; 525} 526 527static void 528DupSectionInfo(SectionInfo *into,SectionInfo *from,GeometryInfo *info) 529{ 530CommonInfo defs; 531 532 defs= into->defs; 533 *into= *from; 534 into->defs.fileID= defs.fileID; 535 into->defs.merge= defs.merge; 536 into->defs.next= NULL; 537 into->dfltRow.defs.fileID= defs.fileID; 538 into->dfltRow.defs.merge= defs.merge; 539 into->dfltRow.defs.next= NULL; 540 into->dfltRow.section= into; 541 into->dfltRow.dfltKey.defs.fileID= defs.fileID; 542 into->dfltRow.dfltKey.defs.merge= defs.merge; 543 into->dfltRow.dfltKey.defs.next= NULL; 544 into->dfltRow.dfltKey.row= &into->dfltRow; 545 return; 546} 547 548static void 549ClearSectionInfo(SectionInfo *si,GeometryInfo *info) 550{ 551 552 si->defs.defined&= ~_GS_Default; 553 si->name= XkbInternAtom(info->dpy,"default",False); 554 si->top= si->left= 0; 555 si->width= si->height= 0; 556 si->angle= 0; 557 if (si->rows) { 558 FreeRows(si->rows,si,info); 559 si->rows= NULL; 560 } 561 ClearRowInfo(&si->dfltRow,info); 562 if (si->doodads) { 563 FreeDoodads(si->doodads,si,info); 564 si->doodads= NULL; 565 } 566 si->dfltRow.defs.defined= _GR_Default; 567 return; 568} 569 570static void 571FreeSections(SectionInfo *si,GeometryInfo *info) 572{ 573SectionInfo * tmp; 574SectionInfo * next; 575 576 if (si==info->sections) { 577 info->nSections= 0; 578 info->sections= NULL; 579 } 580 for (tmp=si;tmp!=NULL;tmp=next) { 581 ClearSectionInfo(tmp,info); 582 next= (SectionInfo *)tmp->defs.next; 583 uFree(tmp); 584 } 585 return; 586} 587 588static void 589FreeShapes(ShapeInfo *si,GeometryInfo *info) 590{ 591ShapeInfo * tmp; 592ShapeInfo * next; 593 594 if (si==info->shapes) { 595 info->nShapes= 0; 596 info->shapes= NULL; 597 } 598 for (tmp=si;tmp!=NULL;tmp=next) { 599 if (tmp->outlines) { 600 register int i; 601 for (i=0;i<tmp->nOutlines;i++) { 602 if (tmp->outlines[i].points!=NULL) { 603 uFree(tmp->outlines[i].points); 604 tmp->outlines[i].num_points= 0; 605 tmp->outlines[i].points= NULL; 606 } 607 } 608 uFree(tmp->outlines); 609 tmp->szOutlines= 0; 610 tmp->nOutlines= 0; 611 tmp->outlines= NULL; 612 tmp->primary= tmp->approx=NULL; 613 } 614 next= (ShapeInfo *)tmp->defs.next; 615 uFree(tmp); 616 } 617 return; 618} 619 620/***====================================================================***/ 621 622static void 623InitGeometryInfo(GeometryInfo *info,unsigned fileID,unsigned merge) 624{ 625 bzero(info,sizeof(GeometryInfo)); 626 info->fileID= fileID; 627 info->merge= merge; 628 InitSectionInfo(&info->dfltSection,info); 629 info->dfltSection.defs.defined= _GS_Default; 630 return; 631} 632 633static void 634ClearGeometryInfo(GeometryInfo *info) 635{ 636 if (info->name) 637 uFree(info->name); 638 info->name= NULL; 639 if (info->props) 640 FreeProperties(info->props,info); 641 if (info->shapes) 642 FreeShapes(info->shapes,info); 643 if (info->sections) 644 FreeSections(info->sections,info); 645 info->widthMM= 0; 646 info->heightMM= 0; 647 info->dfltCornerRadius= 0; 648 ClearSectionInfo(&info->dfltSection,info); 649 info->dfltSection.defs.defined= _GS_Default; 650 if (info->aliases) 651 ClearAliases(&info->aliases); 652 return; 653} 654 655/***====================================================================***/ 656 657static PropertyInfo * 658NextProperty(GeometryInfo *info) 659{ 660PropertyInfo * pi; 661 662 pi= uTypedAlloc(PropertyInfo); 663 if (pi) { 664 bzero((char *)pi,sizeof(PropertyInfo)); 665 info->props= (PropertyInfo *)AddCommonInfo(&info->props->defs, 666 (CommonInfo *)pi); 667 info->nProps++; 668 } 669 return pi; 670} 671 672static PropertyInfo * 673FindProperty(GeometryInfo *info,char *name) 674{ 675PropertyInfo * old; 676 677 if (!name) 678 return NULL; 679 for (old= info->props;old!=NULL;old=(PropertyInfo *)old->defs.next) { 680 if ((old->name)&&(uStringEqual(name,old->name))) 681 return old; 682 } 683 return NULL; 684} 685 686static Bool 687AddProperty(GeometryInfo *info,PropertyInfo *new) 688{ 689PropertyInfo * old; 690 691 if ((!new)||(!new->value)||(!new->name)) 692 return False; 693 old= FindProperty(info,new->name); 694 if (old!=NULL) { 695 if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) { 696 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 697 (warningLevel>9)) { 698 WARN1("Multiple definitions for the \"%s\" property\n", 699 new->name); 700 ACTION2("Ignoring \"%s\", using \"%s\"\n",old->value, 701 new->value); 702 } 703 if (old->value) 704 uFree(old->value); 705 old->value= uStringDup(new->value); 706 return True; 707 } 708 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 709 (warningLevel>9)) { 710 WARN1("Multiple definitions for \"%s\" property\n",new->name); 711 ACTION2("Using \"%s\", ignoring \"%s\" \n",old->value,new->value); 712 } 713 return True; 714 } 715 old= new; 716 if ((new= NextProperty(info))==NULL) 717 return False; 718 new->defs.next= NULL; 719 new->name= uStringDup(old->name); 720 new->value= uStringDup(old->value); 721 return True; 722} 723 724/***====================================================================***/ 725 726static ShapeInfo * 727NextShape(GeometryInfo *info) 728{ 729ShapeInfo * si; 730 731 si= uTypedAlloc(ShapeInfo); 732 if (si) { 733 bzero((char *)si,sizeof(ShapeInfo)); 734 info->shapes= (ShapeInfo *)AddCommonInfo(&info->shapes->defs, 735 (CommonInfo *)si); 736 info->nShapes++; 737 si->dfltCornerRadius= info->dfltCornerRadius; 738 } 739 return si; 740} 741 742static ShapeInfo * 743FindShape(GeometryInfo *info, Atom name, const char *type, const char *which) 744{ 745ShapeInfo * old; 746 747 for (old= info->shapes;old!=NULL;old=(ShapeInfo *)old->defs.next) { 748 if (name==old->name) 749 return old; 750 } 751 if (type!=NULL) { 752 old= info->shapes; 753 WARN3("Unknown shape \"%s\" for %s %s\n", 754 XkbAtomText(info->dpy,name,XkbMessage),type,which); 755 if (old) { 756 ACTION1("Using default shape %s instead\n",shText(info->dpy,old)); 757 return old; 758 } 759 ACTION("No default shape; definition ignored\n"); 760 return NULL; 761 } 762 return NULL; 763} 764 765static Bool 766AddShape(GeometryInfo *info,ShapeInfo *new) 767{ 768ShapeInfo * old; 769 770 old= FindShape(info,new->name,NULL,NULL); 771 if (old!=NULL) { 772 if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) { 773 ShapeInfo *next= (ShapeInfo *)old->defs.next; 774 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 775 (warningLevel>9)) { 776 WARN1("Duplicate shape name \"%s\"\n",shText(info->dpy,old)); 777 ACTION("Using last definition\n"); 778 } 779 *old= *new; 780 old->defs.next= &next->defs; 781 return True; 782 } 783 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 784 (warningLevel>9)) { 785 WARN1("Multiple shapes named \"%s\"\n",shText(info->dpy,old)); 786 ACTION("Using first definition\n"); 787 } 788 return True; 789 } 790 old= new; 791 if ((new= NextShape(info))==NULL) 792 return False; 793 *new= *old; 794 new->defs.next= NULL; 795 old->szOutlines= old->nOutlines= 0; 796 old->outlines= NULL; 797 old->approx= NULL; 798 old->primary= NULL; 799 return True; 800} 801 802/***====================================================================***/ 803 804static void 805ReplaceDoodad(DoodadInfo *into,DoodadInfo *from) 806{ 807CommonInfo * next; 808 809 next= into->defs.next; 810 ClearDoodadInfo(into); 811 *into= *from; 812 into->defs.next= next; 813 next= from->defs.next; 814 ClearDoodadInfo(from); 815 from->defs.next= next; 816 return; 817} 818 819static DoodadInfo * 820NextDfltDoodad(SectionInfo *si,GeometryInfo *info) 821{ 822DoodadInfo * di; 823 824 di= uTypedCalloc(1,DoodadInfo); 825 if (!di) 826 return NULL; 827 if (si) { 828 si->dfltDoodads= (DoodadInfo *)AddCommonInfo(&si->dfltDoodads->defs, 829 (CommonInfo *)di); 830 } 831 else { 832 info->dfltDoodads= (DoodadInfo *)AddCommonInfo(&info->dfltDoodads->defs, 833 (CommonInfo *)di); 834 } 835 return di; 836} 837 838static DoodadInfo * 839NextDoodad(SectionInfo *si,GeometryInfo *info) 840{ 841DoodadInfo * di; 842 843 di= uTypedCalloc(1,DoodadInfo); 844 if (di) { 845 if (si) { 846 si->doodads= (DoodadInfo *)AddCommonInfo(&si->doodads->defs, 847 (CommonInfo *)di); 848 si->nDoodads++; 849 } 850 else { 851 info->doodads= (DoodadInfo *)AddCommonInfo(&info->doodads->defs, 852 (CommonInfo *)di); 853 info->nDoodads++; 854 } 855 } 856 return di; 857} 858 859static Bool 860AddDoodad(SectionInfo *si,GeometryInfo *info,DoodadInfo *new) 861{ 862DoodadInfo * old; 863 864 old= FindDoodadByName((si?si->doodads:info->doodads),new->name); 865 if (old!=NULL) { 866 if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) { 867 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 868 (warningLevel>9)) { 869 WARN1("Multiple doodads named \"%s\"\n", 870 XkbAtomText(info->dpy,old->name,XkbMessage)); 871 ACTION("Using last definition\n"); 872 } 873 ReplaceDoodad(old,new); 874 old->section= si; 875 return True; 876 } 877 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 878 (warningLevel>9)) { 879 WARN1("Multiple doodads named \"%s\"\n", 880 XkbAtomText(info->dpy,old->name,XkbMessage)); 881 ACTION("Using first definition\n"); 882 } 883 return True; 884 } 885 old= new; 886 if ((new= NextDoodad(si,info))==NULL) 887 return False; 888 ReplaceDoodad(new,old); 889 new->section= si; 890 new->defs.next= NULL; 891 return True; 892} 893 894static DoodadInfo * 895FindDfltDoodadByTypeName(char *name,SectionInfo *si,GeometryInfo *info) 896{ 897DoodadInfo * dflt; 898unsigned type; 899 900 if (uStrCaseCmp(name,"outline")==0) type= XkbOutlineDoodad; 901 else if (uStrCaseCmp(name,"solid")==0) type= XkbSolidDoodad; 902 else if (uStrCaseCmp(name,"text")==0) type= XkbTextDoodad; 903 else if (uStrCaseCmp(name,"indicator")==0) type= XkbIndicatorDoodad; 904 else if (uStrCaseCmp(name,"logo")==0) type= XkbLogoDoodad; 905 else return NULL; 906 if ((si)&&(si->dfltDoodads)) 907 dflt= FindDoodadByType(si->dfltDoodads,type); 908 else dflt= NULL; 909 if ((!dflt)&&(info->dfltDoodads)) 910 dflt= FindDoodadByType(info->dfltDoodads,type); 911 if (dflt==NULL) { 912 dflt= NextDfltDoodad(si,info); 913 if (dflt!=NULL) { 914 dflt->name= None; 915 dflt->type= type; 916 } 917 } 918 return dflt; 919} 920 921/***====================================================================***/ 922 923static Bool 924AddOverlay(SectionInfo *si,GeometryInfo *info,OverlayInfo *new) 925{ 926OverlayInfo * old; 927 928 for (old=si->overlays;old!=NULL;old=(OverlayInfo *)old->defs.next) { 929 if (old->name==new->name) 930 break; 931 } 932 if (old!=NULL) { 933 if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) { 934 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 935 (warningLevel>9)) { 936 WARN2("Multiple overlays named \"%s\" for section \"%s\"\n", 937 XkbAtomText(info->dpy,old->name,XkbMessage), 938 XkbAtomText(info->dpy,si->name,XkbMessage)); 939 ACTION("Using last definition\n"); 940 } 941 ClearOverlayInfo(old); 942 old->nKeys= new->nKeys; 943 old->keys= new->keys; 944 new->nKeys= 0; 945 new->keys= NULL; 946 return True; 947 } 948 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 949 (warningLevel>9)) { 950 WARN2("Multiple doodads named \"%s\" in section \"%s\"\n", 951 XkbAtomText(info->dpy,old->name,XkbMessage), 952 XkbAtomText(info->dpy,si->name,XkbMessage)); 953 ACTION("Using first definition\n"); 954 } 955 return True; 956 } 957 old= new; 958 new= uTypedCalloc(1,OverlayInfo); 959 if (!new) { 960 if (warningLevel>0) { 961 WSGO("Couldn't allocate a new OverlayInfo\n"); 962 ACTION2("Overlay \"%s\" in section \"%s\" will be incomplete\n", 963 XkbAtomText(info->dpy,old->name,XkbMessage), 964 XkbAtomText(info->dpy,si->name,XkbMessage)); 965 } 966 return False; 967 } 968 *new= *old; 969 old->nKeys= 0; 970 old->keys= NULL; 971 si->overlays= (OverlayInfo *)AddCommonInfo(&si->overlays->defs, 972 (CommonInfo *)new); 973 si->nOverlays++; 974 return True; 975} 976 977/***====================================================================***/ 978 979static SectionInfo * 980NextSection(GeometryInfo *info) 981{ 982SectionInfo * si; 983 984 si= uTypedAlloc(SectionInfo); 985 if (si) { 986 *si= info->dfltSection; 987 si->defs.defined&= ~_GS_Default; 988 si->defs.next= NULL; 989 si->nRows= 0; 990 si->rows= NULL; 991 info->sections= (SectionInfo *)AddCommonInfo(&info->sections->defs, 992 (CommonInfo *)si); 993 info->nSections++; 994 } 995 return si; 996} 997 998static SectionInfo * 999FindMatchingSection(GeometryInfo *info,SectionInfo *new) 1000{ 1001SectionInfo * old; 1002 1003 for (old=info->sections;old!=NULL;old=(SectionInfo *)old->defs.next) { 1004 if (new->name==old->name) 1005 return old; 1006 } 1007 return NULL; 1008} 1009 1010static Bool 1011AddSection(GeometryInfo *info,SectionInfo *new) 1012{ 1013SectionInfo * old; 1014 1015 old= FindMatchingSection(info,new); 1016 if (old!=NULL) { 1017#ifdef NOTDEF 1018 if ((new->defs.merge==MergeReplace)||(new->defs.merge==MergeOverride)) { 1019 SectionInfo *next= (SectionInfo *)old->defs.next; 1020 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 1021 (warningLevel>9)) { 1022 WARN1("Duplicate shape name \"%s\"\n",shText(info->dpy,old)); 1023 ACTION("Using last definition\n"); 1024 } 1025 *old= *new; 1026 old->defs.next= &next->defs; 1027 return True; 1028 } 1029 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 1030 (warningLevel>9)) { 1031 WARN1("Multiple shapes named \"%s\"\n",shText(info->dpy,old)); 1032 ACTION("Using first definition\n"); 1033 } 1034 return True; 1035#else 1036 WARN("Don't know how to merge sections yet\n"); 1037#endif 1038 } 1039 old= new; 1040 if ((new= NextSection(info))==NULL) 1041 return False; 1042 *new= *old; 1043 new->defs.next= NULL; 1044 old->nRows= old->nDoodads= old->nOverlays= 0; 1045 old->rows= NULL; 1046 old->doodads= NULL; 1047 old->overlays= NULL; 1048 if (new->doodads) { 1049 DoodadInfo *di; 1050 for (di=new->doodads;di;di=(DoodadInfo *)di->defs.next) { 1051 di->section= new; 1052 } 1053 } 1054 return True; 1055} 1056 1057/***====================================================================***/ 1058 1059static RowInfo * 1060NextRow(SectionInfo *si) 1061{ 1062RowInfo * row; 1063 1064 row= uTypedAlloc(RowInfo); 1065 if (row) { 1066 *row= si->dfltRow; 1067 row->defs.defined&= ~_GR_Default; 1068 row->defs.next= NULL; 1069 row->nKeys= 0; 1070 row->keys= NULL; 1071 si->rows= (RowInfo *)AddCommonInfo(&si->rows->defs,(CommonInfo *)row); 1072 row->index= si->nRows++; 1073 } 1074 return row; 1075} 1076 1077static Bool 1078AddRow(SectionInfo *si,RowInfo *new) 1079{ 1080RowInfo * old; 1081 1082 old= new; 1083 if ((new= NextRow(si))==NULL) 1084 return False; 1085 *new= *old; 1086 new->defs.next= NULL; 1087 old->nKeys= 0; 1088 old->keys= NULL; 1089 return True; 1090} 1091 1092/***====================================================================***/ 1093 1094static KeyInfo * 1095NextKey(RowInfo *row) 1096{ 1097KeyInfo * key; 1098 1099 key= uTypedAlloc(KeyInfo); 1100 if (key) { 1101 *key= row->dfltKey; 1102 key->defs.defined&= ~_GK_Default; 1103 key->defs.next= NULL; 1104 key->index= row->nKeys++; 1105 } 1106 return key; 1107} 1108 1109static Bool 1110AddKey(RowInfo *row,KeyInfo *new) 1111{ 1112KeyInfo * old; 1113 1114 old= new; 1115 if ((new= NextKey(row))==NULL) 1116 return False; 1117 *new= *old; 1118 new->defs.next= NULL; 1119 row->keys= (KeyInfo *)AddCommonInfo(&row->keys->defs,(CommonInfo *)new); 1120 return True; 1121} 1122 1123/***====================================================================***/ 1124 1125static void 1126MergeIncludedGeometry(GeometryInfo *into,GeometryInfo *from,unsigned merge) 1127{ 1128Bool clobber; 1129 1130 if (from->errorCount>0) { 1131 into->errorCount+= from->errorCount; 1132 return; 1133 } 1134 clobber= (merge==MergeOverride)||(merge==MergeReplace); 1135 if (into->name==NULL) { 1136 into->name= from->name; 1137 from->name= NULL; 1138 } 1139 if ((into->widthMM==0)||((from->widthMM!=0)&&clobber)) 1140 into->widthMM= from->widthMM; 1141 if ((into->heightMM==0)||((from->heightMM!=0)&&clobber)) 1142 into->heightMM= from->heightMM; 1143 if ((into->font==None)||((from->font!=None)&&clobber)) 1144 into->font= from->font; 1145 if ((into->fontSlant==None)||((from->fontSlant!=None)&&clobber)) 1146 into->fontSlant= from->fontSlant; 1147 if ((into->fontWeight==None)||((from->fontWeight!=None)&&clobber)) 1148 into->fontWeight= from->fontWeight; 1149 if ((into->fontSetWidth==None)||((from->fontSetWidth!=None)&&clobber)) 1150 into->fontSetWidth= from->fontSetWidth; 1151 if ((into->fontVariant==None)||((from->fontVariant!=None)&&clobber)) 1152 into->fontVariant= from->fontVariant; 1153 if ((into->fontSize==0)||((from->fontSize!=0)&&clobber)) 1154 into->fontSize= from->fontSize; 1155 if ((into->fontEncoding==None)||((from->fontEncoding!=None)&&clobber)) 1156 into->fontEncoding= from->fontEncoding; 1157 if ((into->fontSpec==None)||((from->fontSpec!=None)&&clobber)) 1158 into->fontSpec= from->fontSpec; 1159 if ((into->baseColor==None)||((from->baseColor!=None)&&clobber)) 1160 into->baseColor= from->baseColor; 1161 if ((into->labelColor==None)||((from->labelColor!=None)&&clobber)) 1162 into->labelColor= from->labelColor; 1163 into->nextPriority= from->nextPriority; 1164 if (from->props!=NULL) { 1165 PropertyInfo *pi; 1166 for (pi=from->props;pi;pi=(PropertyInfo *)pi->defs.next) { 1167 if (!AddProperty(into,pi)) 1168 into->errorCount++; 1169 } 1170 } 1171 if (from->shapes!=NULL) { 1172 ShapeInfo * si; 1173 1174 for (si=from->shapes;si;si=(ShapeInfo *)si->defs.next) { 1175 if (!AddShape(into,si)) 1176 into->errorCount++; 1177 } 1178 } 1179 if (from->sections!=NULL) { 1180 SectionInfo * si; 1181 1182 for (si=from->sections;si;si=(SectionInfo *)si->defs.next) { 1183 if (!AddSection(into,si)) 1184 into->errorCount++; 1185 } 1186 } 1187 if (from->doodads!=NULL) { 1188 DoodadInfo * di; 1189 1190 for (di=from->doodads;di;di=(DoodadInfo *)di->defs.next) { 1191 if (!AddDoodad(NULL,into,di)) 1192 into->errorCount++; 1193 } 1194 } 1195 if (!MergeAliases(&into->aliases,&from->aliases,merge)) 1196 into->errorCount++; 1197 return; 1198} 1199 1200typedef void (*FileHandler)( 1201 XkbFile * /* file */, 1202 XkbDescPtr /* xkb */, 1203 unsigned /* merge */, 1204 GeometryInfo * /* info */ 1205); 1206 1207static Bool 1208HandleIncludeGeometry(IncludeStmt *stmt,XkbDescPtr xkb,GeometryInfo *info, 1209 FileHandler hndlr) 1210{ 1211unsigned newMerge; 1212XkbFile * rtrn; 1213GeometryInfo included; 1214Bool haveSelf; 1215 1216 haveSelf= False; 1217 if ((stmt->file==NULL)&&(stmt->map==NULL)) { 1218 haveSelf= True; 1219 included= *info; 1220 bzero(info,sizeof(GeometryInfo)); 1221 } 1222 else if (ProcessIncludeFile(stmt,XkmGeometryIndex,&rtrn,&newMerge)) { 1223 InitGeometryInfo(&included,rtrn->id,newMerge); 1224 included.nextPriority= info->nextPriority; 1225 included.dfltCornerRadius= info->dfltCornerRadius; 1226 DupSectionInfo(&included.dfltSection,&info->dfltSection,info); 1227 (*hndlr)(rtrn,xkb,MergeOverride,&included); 1228 if (stmt->stmt!=NULL) { 1229 if (included.name!=NULL) 1230 uFree(included.name); 1231 included.name= stmt->stmt; 1232 stmt->stmt= NULL; 1233 } 1234 } 1235 else { 1236 info->errorCount+= 10; 1237 return False; 1238 } 1239 if ((stmt->next!=NULL)&&(included.errorCount<1)) { 1240 IncludeStmt * next; 1241 unsigned op; 1242 GeometryInfo next_incl; 1243 1244 for (next=stmt->next;next!=NULL;next=next->next) { 1245 if ((next->file==NULL)&&(next->map==NULL)) { 1246 haveSelf= True; 1247 MergeIncludedGeometry(&included,info,next->merge); 1248 ClearGeometryInfo(info); 1249 } 1250 else if (ProcessIncludeFile(next,XkmGeometryIndex,&rtrn,&op)) { 1251 InitGeometryInfo(&next_incl,rtrn->id,op); 1252 next_incl.nextPriority= included.nextPriority; 1253 next_incl.dfltCornerRadius= included.dfltCornerRadius; 1254 DupSectionInfo(&next_incl.dfltSection,&included.dfltSection, 1255 &included); 1256 (*hndlr)(rtrn,xkb,MergeOverride,&next_incl); 1257 MergeIncludedGeometry(&included,&next_incl,op); 1258 ClearGeometryInfo(&next_incl); 1259 } 1260 else { 1261 info->errorCount+= 10; 1262 return False; 1263 } 1264 } 1265 } 1266 if (haveSelf) 1267 *info= included; 1268 else { 1269 MergeIncludedGeometry(info,&included,newMerge); 1270 ClearGeometryInfo(&included); 1271 } 1272 return (info->errorCount==0); 1273} 1274 1275static int 1276SetShapeField( ShapeInfo * si, 1277 char * field, 1278 ExprDef * arrayNdx, 1279 ExprDef * value, 1280 GeometryInfo * info) 1281{ 1282ExprResult tmp; 1283 1284 if ((uStrCaseCmp(field,"radius")==0)||(uStrCaseCmp(field,"corner")==0)|| 1285 (uStrCaseCmp(field,"cornerradius")==0)) { 1286 if (arrayNdx!=NULL) { 1287 info->errorCount++; 1288 return ReportNotArray("key shape",field,shText(info->dpy,si)); 1289 } 1290 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1291 info->errorCount++; 1292 return ReportBadType("key shape",field, 1293 shText(info->dpy,si),"number"); 1294 } 1295 if (si) 1296 si->dfltCornerRadius= tmp.ival; 1297 else info->dfltCornerRadius= tmp.ival; 1298 return True; 1299 } 1300 info->errorCount++; 1301 return ReportBadField("key shape",field,shText(info->dpy,si)); 1302} 1303 1304static int 1305SetShapeDoodadField( DoodadInfo * di, 1306 char * field, 1307 ExprDef * arrayNdx, 1308 ExprDef * value, 1309 SectionInfo * si, 1310 GeometryInfo * info) 1311{ 1312ExprResult tmp; 1313const char *typeName; 1314 1315 typeName= (di->type==XkbSolidDoodad?"solid doodad":"outline doodad"); 1316 if ((!uStrCaseCmp(field,"corner"))||(!uStrCaseCmp(field,"cornerradius"))) { 1317 if (arrayNdx!=NULL) { 1318 info->errorCount++; 1319 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1320 } 1321 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1322 info->errorCount++; 1323 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1324 } 1325 di->defs.defined|= _GD_Corner; 1326 di->corner= tmp.ival; 1327 return True; 1328 } 1329 else if (uStrCaseCmp(field,"angle")==0) { 1330 if (arrayNdx!=NULL) { 1331 info->errorCount++; 1332 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1333 } 1334 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1335 info->errorCount++; 1336 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1337 } 1338 di->defs.defined|= _GD_Angle; 1339 di->angle= tmp.ival; 1340 return True; 1341 } 1342 else if (uStrCaseCmp(field,"shape")==0) { 1343 if (arrayNdx!=NULL) { 1344 info->errorCount++; 1345 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1346 } 1347 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1348 info->errorCount++; 1349 return ReportBadType(typeName,field,ddText(info->dpy,di),"string"); 1350 } 1351 di->shape= XkbInternAtom(info->dpy,tmp.str,False); 1352 di->defs.defined|= _GD_Shape; 1353 return True; 1354 } 1355 return ReportBadField(typeName,field,ddText(info->dpy,di)); 1356} 1357 1358#define FIELD_STRING 0 1359#define FIELD_SHORT 1 1360#define FIELD_USHORT 2 1361 1362static int 1363SetTextDoodadField( DoodadInfo * di, 1364 char * field, 1365 ExprDef * arrayNdx, 1366 ExprDef * value, 1367 SectionInfo * si, 1368 GeometryInfo * info) 1369{ 1370ExprResult tmp; 1371unsigned def; 1372unsigned type; 1373char * typeName= "text doodad"; 1374union { 1375 Atom * str; 1376 short * ival; 1377 unsigned short * uval; 1378} pField; 1379 1380 if (uStrCaseCmp(field,"angle")==0) { 1381 if (arrayNdx!=NULL) { 1382 info->errorCount++; 1383 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1384 } 1385 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1386 info->errorCount++; 1387 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1388 } 1389 di->defs.defined|= _GD_Angle; 1390 di->angle= tmp.ival; 1391 return True; 1392 } 1393 if (uStrCaseCmp(field,"width")==0) { 1394 type= FIELD_USHORT; 1395 pField.uval= &di->width; 1396 def= _GD_Width; 1397 } 1398 else if (uStrCaseCmp(field,"height")==0) { 1399 type= FIELD_USHORT; 1400 pField.uval= &di->height; 1401 def= _GD_Height; 1402 } 1403 else if (uStrCaseCmp(field,"text")==0) { 1404 type= FIELD_STRING; 1405 pField.str= &di->text; 1406 def= _GD_Text; 1407 } 1408 else if (uStrCaseCmp(field,"font")==0) { 1409 type= FIELD_STRING; 1410 pField.str= &di->font; 1411 def= _GD_Font; 1412 } 1413 else if ((uStrCaseCmp(field,"fontslant")==0)|| 1414 (uStrCaseCmp(field,"slant")==0)) { 1415 type= FIELD_STRING; 1416 pField.str= &di->fontSlant; 1417 def= _GD_FontSlant; 1418 } 1419 else if ((uStrCaseCmp(field,"fontweight")==0)|| 1420 (uStrCaseCmp(field,"weight")==0)) { 1421 type= FIELD_STRING; 1422 pField.str= &di->fontWeight; 1423 def= _GD_FontWeight; 1424 } 1425 else if ((uStrCaseCmp(field,"fontwidth")==0)|| 1426 (uStrCaseCmp(field,"setwidth")==0)) { 1427 type= FIELD_STRING; 1428 pField.str= &di->fontSetWidth; 1429 def= _GD_FontSetWidth; 1430 } 1431 else if ((uStrCaseCmp(field,"fontvariant")==0)|| 1432 (uStrCaseCmp(field,"variant")==0)) { 1433 type= FIELD_STRING; 1434 pField.str= &di->fontVariant; 1435 def= _GD_FontVariant; 1436 } 1437 else if ((uStrCaseCmp(field,"fontencoding")==0)|| 1438 (uStrCaseCmp(field,"encoding")==0)) { 1439 type= FIELD_STRING; 1440 pField.str= &di->fontEncoding; 1441 def= _GD_FontEncoding; 1442 } 1443 else if ((uStrCaseCmp(field,"xfont")==0)|| 1444 (uStrCaseCmp(field,"xfontname")==0)) { 1445 type= FIELD_STRING; 1446 pField.str= &di->fontSpec; 1447 def= _GD_FontSpec; 1448 } 1449 else if (uStrCaseCmp(field,"fontsize")==0) { 1450 type= FIELD_USHORT; 1451 pField.uval= &di->fontSize; 1452 def= _GD_FontSize; 1453 } 1454 else { 1455 return ReportBadField(typeName,field,ddText(info->dpy,di)); 1456 } 1457 if (arrayNdx!=NULL) { 1458 info->errorCount++; 1459 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1460 } 1461 if (type==FIELD_STRING) { 1462 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1463 info->errorCount++; 1464 return ReportBadType(typeName,field,ddText(info->dpy,di), 1465 "string"); 1466 } 1467 di->defs.defined|= def; 1468 *pField.str= XkbInternAtom(NULL,tmp.str,False); 1469 } 1470 else { 1471 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1472 info->errorCount++; 1473 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1474 } 1475 if ((type==FIELD_USHORT)&&(tmp.ival<0)) { 1476 info->errorCount++; 1477 return 1478 ReportBadType(typeName,field,ddText(info->dpy,di),"unsigned"); 1479 } 1480 di->defs.defined|= def; 1481 if (type==FIELD_USHORT) 1482 *pField.uval= tmp.uval; 1483 else *pField.ival= tmp.ival; 1484 } 1485 return True; 1486} 1487 1488static int 1489SetIndicatorDoodadField( DoodadInfo * di, 1490 char * field, 1491 ExprDef * arrayNdx, 1492 ExprDef * value, 1493 SectionInfo * si, 1494 GeometryInfo * info) 1495{ 1496ExprResult tmp; 1497 1498 if ((uStrCaseCmp(field,"oncolor")==0)||(uStrCaseCmp(field,"offcolor")==0) 1499 ||(uStrCaseCmp(field,"shape")==0)) { 1500 if (arrayNdx!=NULL) { 1501 info->errorCount++; 1502 return ReportNotArray("indicator doodad",field, 1503 ddText(info->dpy,di)); 1504 } 1505 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1506 info->errorCount++; 1507 return ReportBadType("indicator doodad",field,ddText(info->dpy,di), 1508 "string"); 1509 } 1510 if (uStrCaseCmp(field,"oncolor")==0) { 1511 di->defs.defined|= _GD_Color; 1512 di->color= XkbInternAtom(NULL,tmp.str,False); 1513 } 1514 else if (uStrCaseCmp(field,"offcolor")==0) { 1515 di->defs.defined|= _GD_OffColor; 1516 di->offColor= XkbInternAtom(NULL,tmp.str,False); 1517 } 1518 else if (uStrCaseCmp(field,"shape")==0) { 1519 di->defs.defined|= _GD_Shape; 1520 di->shape= XkbInternAtom(info->dpy,tmp.str,False); 1521 } 1522 return True; 1523 } 1524 return ReportBadField("indicator doodad",field,ddText(info->dpy,di)); 1525} 1526 1527static int 1528SetLogoDoodadField( DoodadInfo * di, 1529 char * field, 1530 ExprDef * arrayNdx, 1531 ExprDef * value, 1532 SectionInfo * si, 1533 GeometryInfo * info) 1534{ 1535ExprResult tmp; 1536char * typeName= "logo doodad"; 1537 1538 if ((!uStrCaseCmp(field,"corner"))||(!uStrCaseCmp(field,"cornerradius"))) { 1539 if (arrayNdx!=NULL) { 1540 info->errorCount++; 1541 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1542 } 1543 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1544 info->errorCount++; 1545 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1546 } 1547 di->defs.defined|= _GD_Corner; 1548 di->corner= tmp.ival; 1549 return True; 1550 } 1551 else if (uStrCaseCmp(field,"angle")==0) { 1552 if (arrayNdx!=NULL) { 1553 info->errorCount++; 1554 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1555 } 1556 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1557 info->errorCount++; 1558 return ReportBadType(typeName,field,ddText(info->dpy,di),"number"); 1559 } 1560 di->defs.defined|= _GD_Angle; 1561 di->angle= tmp.ival; 1562 return True; 1563 } 1564 else if (uStrCaseCmp(field,"shape")==0) { 1565 if (arrayNdx!=NULL) { 1566 info->errorCount++; 1567 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1568 } 1569 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1570 info->errorCount++; 1571 return ReportBadType(typeName,field,ddText(info->dpy,di),"string"); 1572 } 1573 di->shape= XkbInternAtom(info->dpy,tmp.str,False); 1574 di->defs.defined|= _GD_Shape; 1575 return True; 1576 } 1577 else if ((!uStrCaseCmp(field,"logoname"))||(!uStrCaseCmp(field,"name"))) { 1578 if (arrayNdx!=NULL) { 1579 info->errorCount++; 1580 return ReportNotArray(typeName,field,ddText(info->dpy,di)); 1581 } 1582 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1583 info->errorCount++; 1584 return ReportBadType(typeName,field,ddText(info->dpy,di),"string"); 1585 } 1586 di->logoName= uStringDup(tmp.str); 1587 return True; 1588 } 1589 return ReportBadField(typeName,field,ddText(info->dpy,di)); 1590} 1591 1592static int 1593SetDoodadField( DoodadInfo * di, 1594 char * field, 1595 ExprDef * arrayNdx, 1596 ExprDef * value, 1597 SectionInfo * si, 1598 GeometryInfo * info) 1599{ 1600ExprResult tmp; 1601 1602 if (uStrCaseCmp(field,"priority")==0) { 1603 if (arrayNdx!=NULL) { 1604 info->errorCount++; 1605 return ReportNotArray("doodad",field,ddText(info->dpy,di)); 1606 } 1607 if (!ExprResolveInteger(value,&tmp,NULL,NULL)) { 1608 info->errorCount++; 1609 return ReportBadType("doodad",field,ddText(info->dpy,di),"integer"); 1610 } 1611 if ((tmp.ival<0)||(tmp.ival>XkbGeomMaxPriority)) { 1612 info->errorCount++; 1613 ERROR2("Doodad priority %d out of range (must be 0..%d)\n", 1614 tmp.ival,XkbGeomMaxPriority); 1615 ACTION1("Priority for doodad %s not changed",ddText(info->dpy,di)); 1616 return False; 1617 } 1618 di->defs.defined|= _GD_Priority; 1619 di->priority= tmp.ival; 1620 return True; 1621 } 1622 else if (uStrCaseCmp(field,"left")==0) { 1623 if (arrayNdx!=NULL) { 1624 info->errorCount++; 1625 return ReportNotArray("doodad",field,ddText(info->dpy,di)); 1626 } 1627 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1628 info->errorCount++; 1629 return ReportBadType("doodad",field,ddText(info->dpy,di),"number"); 1630 } 1631 di->defs.defined|= _GD_Left; 1632 di->left= tmp.ival; 1633 return True; 1634 } 1635 else if (uStrCaseCmp(field,"top")==0) { 1636 if (arrayNdx!=NULL) { 1637 info->errorCount++; 1638 return ReportNotArray("doodad",field,ddText(info->dpy,di)); 1639 } 1640 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1641 info->errorCount++; 1642 return ReportBadType("doodad",field,ddText(info->dpy,di),"number"); 1643 } 1644 di->defs.defined|= _GD_Top; 1645 di->top= tmp.ival; 1646 return True; 1647 } 1648 else if (uStrCaseCmp(field,"color")==0) { 1649 if (arrayNdx!=NULL) { 1650 info->errorCount++; 1651 return ReportNotArray("doodad",field,ddText(info->dpy,di)); 1652 } 1653 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1654 info->errorCount++; 1655 return ReportBadType("doodad",field,ddText(info->dpy,di),"string"); 1656 } 1657 di->defs.defined|= _GD_Color; 1658 di->color= XkbInternAtom(NULL,tmp.str,False); 1659 return True; 1660 } 1661 switch (di->type) { 1662 case XkbOutlineDoodad: 1663 case XkbSolidDoodad: 1664 return SetShapeDoodadField(di,field,arrayNdx,value,si,info); 1665 case XkbTextDoodad: 1666 return SetTextDoodadField(di,field,arrayNdx,value,si,info); 1667 case XkbIndicatorDoodad: 1668 return SetIndicatorDoodadField(di,field,arrayNdx,value,si,info); 1669 case XkbLogoDoodad: 1670 return SetLogoDoodadField(di,field,arrayNdx,value,si,info); 1671 } 1672 WSGO1("Unknown doodad type %d in SetDoodadField\n",(unsigned int)di->type); 1673 ACTION2("Definition of %s in %s ignored\n",field,ddText(info->dpy,di)); 1674 return False; 1675} 1676 1677static int 1678SetSectionField( SectionInfo * si, 1679 char * field, 1680 ExprDef * arrayNdx, 1681 ExprDef * value, 1682 GeometryInfo * info) 1683{ 1684unsigned short * pField; 1685unsigned def; 1686ExprResult tmp; 1687 1688 pField= NULL; 1689 def= 0; 1690 if (uStrCaseCmp(field,"priority")==0) { 1691 if (arrayNdx!=NULL) { 1692 info->errorCount++; 1693 return ReportNotArray("keyboard section",field,scText(info->dpy,si)); 1694 } 1695 if (!ExprResolveInteger(value,&tmp,NULL,NULL)) { 1696 info->errorCount++; 1697 ReportBadType("keyboard section",field,scText(info->dpy,si), 1698 "integer"); 1699 return False; 1700 } 1701 if ((tmp.ival<0)||(tmp.ival>XkbGeomMaxPriority)) { 1702 info->errorCount++; 1703 ERROR2("Section priority %d out of range (must be 0..%d)\n", 1704 tmp.ival,XkbGeomMaxPriority); 1705 ACTION1("Priority for section %s not changed",scText(info->dpy,si)); 1706 return False; 1707 } 1708 si->priority= tmp.ival; 1709 si->defs.defined|= _GS_Priority; 1710 return True; 1711 } 1712 else if (uStrCaseCmp(field,"top")==0) { 1713 pField= &si->top; 1714 def= _GS_Top; 1715 } 1716 else if (uStrCaseCmp(field,"left")==0) { 1717 pField= &si->left; 1718 def= _GS_Left; 1719 } 1720 else if (uStrCaseCmp(field,"width")==0) { 1721 pField= &si->width; 1722 def= _GS_Width; 1723 } 1724 else if (uStrCaseCmp(field,"height")==0) { 1725 pField= &si->height; 1726 def= _GS_Height; 1727 } 1728 else if (uStrCaseCmp(field,"angle")==0) { 1729 pField= &si->angle; 1730 def= _GS_Angle; 1731 } 1732 else { 1733 info->errorCount++; 1734 return ReportBadField("keyboard section",field,scText(info->dpy,si)); 1735 } 1736 if (arrayNdx!=NULL) { 1737 info->errorCount++; 1738 return ReportNotArray("keyboard section",field,scText(info->dpy,si)); 1739 } 1740 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1741 info->errorCount++; 1742 ReportBadType("keyboard section",field,scText(info->dpy,si),"number"); 1743 return False; 1744 } 1745 si->defs.defined|= def; 1746 *pField= tmp.uval; 1747 return True; 1748} 1749 1750static int 1751SetRowField( RowInfo * row, 1752 char * field, 1753 ExprDef * arrayNdx, 1754 ExprDef * value, 1755 GeometryInfo * info) 1756{ 1757ExprResult tmp; 1758 1759 if (uStrCaseCmp(field,"top")==0) { 1760 if (arrayNdx!=NULL) { 1761 info->errorCount++; 1762 return ReportNotArray("keyboard row",field,rowText(info->dpy,row)); 1763 } 1764 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1765 info->errorCount++; 1766 return ReportBadType("keyboard row",field,rowText(info->dpy,row), 1767 "number"); 1768 } 1769 row->defs.defined|= _GR_Top; 1770 row->top= tmp.uval; 1771 } 1772 else if (uStrCaseCmp(field,"left")==0) { 1773 if (arrayNdx!=NULL) { 1774 info->errorCount++; 1775 return ReportNotArray("keyboard row",field,rowText(info->dpy,row)); 1776 } 1777 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1778 info->errorCount++; 1779 return ReportBadType("keyboard row",field,rowText(info->dpy,row), 1780 "number"); 1781 } 1782 row->defs.defined|= _GR_Left; 1783 row->left= tmp.uval; 1784 } 1785 else if (uStrCaseCmp(field,"vertical")==0) { 1786 if (arrayNdx!=NULL) { 1787 info->errorCount++; 1788 return ReportNotArray("keyboard row",field,rowText(info->dpy,row)); 1789 } 1790 if (!ExprResolveBoolean(value,&tmp,NULL,NULL)) { 1791 info->errorCount++; 1792 return ReportBadType("keyboard row",field,rowText(info->dpy,row), 1793 "boolean"); 1794 } 1795 row->defs.defined|= _GR_Vertical; 1796 row->vertical= tmp.uval; 1797 } 1798 else { 1799 info->errorCount++; 1800 return ReportBadField("keyboard row",field,rowText(info->dpy,row)); 1801 } 1802 return True; 1803} 1804 1805static int 1806SetKeyField( KeyInfo *key, 1807 const char *field, 1808 ExprDef *arrayNdx, 1809 ExprDef *value, 1810 GeometryInfo *info) 1811{ 1812ExprResult tmp; 1813 1814 if (uStrCaseCmp(field,"gap")==0) { 1815 if (arrayNdx!=NULL) { 1816 info->errorCount++; 1817 return ReportNotArray("key",field,keyText(key)); 1818 } 1819 if (!ExprResolveFloat(value,&tmp,NULL,NULL)) { 1820 info->errorCount++; 1821 return ReportBadType("key",field,keyText(key),"number"); 1822 } 1823 key->defs.defined|= _GK_Gap; 1824 key->gap= tmp.ival; 1825 } 1826 else if (uStrCaseCmp(field,"shape")==0) { 1827 if (arrayNdx!=NULL) { 1828 info->errorCount++; 1829 return ReportNotArray("key",field,keyText(key)); 1830 } 1831 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1832 info->errorCount++; 1833 return ReportBadType("key",field,keyText(key),"string"); 1834 } 1835 key->defs.defined|= _GK_Shape; 1836 key->shape= XkbInternAtom(info->dpy,tmp.str,False); 1837 } 1838 else if ((uStrCaseCmp(field,"color")==0)|| 1839 (uStrCaseCmp(field,"keycolor")==0)) { 1840 if (arrayNdx!=NULL) { 1841 info->errorCount++; 1842 return ReportNotArray("key",field,keyText(key)); 1843 } 1844 if (!ExprResolveString(value,&tmp,NULL,NULL)) { 1845 info->errorCount++; 1846 return ReportBadType("key",field,keyText(key),"string"); 1847 } 1848 key->defs.defined|= _GK_Color; 1849 key->color= XkbInternAtom(NULL,tmp.str,False); 1850 } 1851 else if ((uStrCaseCmp(field,"name")==0)||(uStrCaseCmp(field,"keyname")==0)){ 1852 if (arrayNdx!=NULL) { 1853 info->errorCount++; 1854 return ReportNotArray("key",field,keyText(key)); 1855 } 1856 if (!ExprResolveKeyName(value,&tmp,NULL,NULL)) { 1857 info->errorCount++; 1858 return ReportBadType("key",field,keyText(key),"key name"); 1859 } 1860 key->defs.defined|= _GK_Name; 1861 bzero(key->name,XkbKeyNameLength+1); 1862 strncpy(key->name,tmp.keyName.name,XkbKeyNameLength); 1863 } 1864 else { 1865 info->errorCount++; 1866 return ReportBadField("key",field,keyText(key)); 1867 } 1868 return True; 1869} 1870 1871static int 1872SetGeometryProperty(GeometryInfo *info,char *property,ExprDef *value) 1873{ 1874PropertyInfo pi; 1875ExprResult result; 1876 1877 InitPropertyInfo(&pi,info); 1878 pi.name= property; 1879 if (!ExprResolveString(value,&result,NULL,NULL)) { 1880 info->errorCount++; 1881 ERROR("Property values must be type string\n"); 1882 ACTION1("Ignoring illegal definition of \"%s\" property\n",property); 1883 return False; 1884 } 1885 pi.value= result.str; 1886 return AddProperty(info,&pi); 1887} 1888 1889static int 1890HandleGeometryVar(VarDef *stmt,XkbDescPtr xkb,GeometryInfo *info) 1891{ 1892ExprResult elem,field,tmp; 1893ExprDef * ndx; 1894DoodadInfo * di; 1895Atom * pField; 1896 1897 if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0) 1898 return 0; /* internal error, already reported */ 1899 if (elem.str&&(uStrCaseCmp(elem.str,"shape")==0)) 1900 return SetShapeField(NULL,field.str,ndx,stmt->value,info); 1901 if (elem.str&&(uStrCaseCmp(elem.str,"key")==0)) 1902 return SetKeyField(&info->dfltSection.dfltRow.dfltKey, 1903 field.str,ndx,stmt->value,info); 1904 if (elem.str&&(uStrCaseCmp(elem.str,"row")==0)) 1905 return SetRowField(&info->dfltSection.dfltRow,field.str,ndx, 1906 stmt->value,info); 1907 if (elem.str&&(uStrCaseCmp(elem.str,"section")==0)) { 1908 return SetSectionField(&info->dfltSection,field.str,ndx,stmt->value, 1909 info); 1910 } 1911 if (elem.str&&(uStrCaseCmp(elem.str,"property")==0)) { 1912 if (ndx!=NULL) { 1913 info->errorCount++; 1914 ERROR1("The %s geometry property is not an array\n",field.str); 1915 ACTION("Ignoring illegal property definition\n"); 1916 return False; 1917 } 1918 return SetGeometryProperty(info,field.str,stmt->value); 1919 } 1920 if (elem.str&&((di=FindDfltDoodadByTypeName(elem.str,NULL,info))!=NULL)) { 1921 return SetDoodadField(di,field.str,ndx,stmt->value,NULL,info); 1922 } 1923 if (elem.str&&(uStrCaseCmp(elem.str,"solid")==0)) { 1924 DoodadInfo *dflt; 1925 dflt= FindDoodadByType(info->dfltDoodads,XkbSolidDoodad); 1926 if (dflt==NULL) 1927 dflt= NextDfltDoodad(NULL,info); 1928 return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info); 1929 } 1930 if (elem.str&&(uStrCaseCmp(elem.str,"outline")==0)) { 1931 DoodadInfo *dflt; 1932 dflt= FindDoodadByType(info->dfltDoodads,XkbOutlineDoodad); 1933 if (dflt==NULL) 1934 dflt= NextDfltDoodad(NULL,info); 1935 return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info); 1936 } 1937 if (elem.str&&(uStrCaseCmp(elem.str,"text")==0)) { 1938 DoodadInfo *dflt; 1939 dflt= FindDoodadByType(info->dfltDoodads,XkbTextDoodad); 1940 if (dflt==NULL) 1941 dflt= NextDfltDoodad(NULL,info); 1942 return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info); 1943 } 1944 if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) { 1945 DoodadInfo *dflt; 1946 dflt= FindDoodadByType(info->dfltDoodads,XkbIndicatorDoodad); 1947 if (dflt==NULL) 1948 dflt= NextDfltDoodad(NULL,info); 1949 return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info); 1950 } 1951 if (elem.str&&(uStrCaseCmp(elem.str,"logo")==0)) { 1952 DoodadInfo *dflt; 1953 dflt= FindDoodadByType(info->dfltDoodads,XkbLogoDoodad); 1954 if (dflt==NULL) 1955 dflt= NextDfltDoodad(NULL,info); 1956 return SetDoodadField(dflt,field.str,ndx,stmt->value,NULL,info); 1957 } 1958 if (elem.str) { 1959 WARN("Assignment to field of unknown element\n"); 1960 ACTION2("No value assigned to %s.%s\n",elem.str,field.str); 1961 return False; 1962 } 1963 1964 if ((uStrCaseCmp(field.str,"width")==0)|| 1965 (uStrCaseCmp(field.str,"widthmm")==0)) { 1966 if (ndx!=NULL) { 1967 info->errorCount++; 1968 return ReportNotArray("keyboard",field.str,"geometry"); 1969 } 1970 if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) { 1971 info->errorCount++; 1972 return ReportBadType("keyboard",field.str,"geometry","number"); 1973 } 1974 if (tmp.ival<1) { 1975 WARN("Keyboard width must be positive\n"); 1976 ACTION1("Ignoring illegal keyboard width %s\n", 1977 XkbGeomFPText(tmp.ival,XkbMessage)); 1978 return True; 1979 } 1980 if (info->widthMM!=0) { 1981 WARN("Keyboard width multiply defined\n"); 1982 ACTION1("Using last definition (%s),", 1983 XkbGeomFPText(tmp.ival,XkbMessage)); 1984 INFO1(" ignoring first (%s)\n", 1985 XkbGeomFPText(info->widthMM,XkbMessage)); 1986 } 1987 info->widthMM= tmp.ival; 1988 return True; 1989 } 1990 else if ((uStrCaseCmp(field.str,"height")==0)|| 1991 (uStrCaseCmp(field.str,"heightmm")==0)) { 1992 if (ndx!=NULL) { 1993 info->errorCount++; 1994 return ReportNotArray("keyboard",field.str,"geometry"); 1995 } 1996 if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) { 1997 info->errorCount++; 1998 return ReportBadType("keyboard",field.str,"geometry","number"); 1999 } 2000 if (tmp.ival<1) { 2001 WARN("Keyboard height must be positive\n"); 2002 ACTION1("Ignoring illegal keyboard height %s\n", 2003 XkbGeomFPText(tmp.ival,XkbMessage)); 2004 return True; 2005 } 2006 if (info->heightMM!=0) { 2007 WARN("Keyboard height multiply defined\n"); 2008 ACTION1("Using last definition (%s),", 2009 XkbGeomFPText(tmp.ival,XkbMessage)); 2010 INFO1(" ignoring first (%s)\n", 2011 XkbGeomFPText(info->heightMM,XkbMessage)); 2012 } 2013 info->heightMM= tmp.ival; 2014 return True; 2015 } 2016 else if (uStrCaseCmp(field.str,"font")==0) { 2017 pField= &info->font; 2018 } 2019 else if ((uStrCaseCmp(field.str,"fontslant")==0)|| 2020 (uStrCaseCmp(field.str,"slant")==0)) { 2021 pField= &info->fontSlant; 2022 } 2023 else if ((uStrCaseCmp(field.str,"fontweight")==0)|| 2024 (uStrCaseCmp(field.str,"weight")==0)) { 2025 pField= &info->fontWeight; 2026 } 2027 else if ((uStrCaseCmp(field.str,"fontwidth")==0)|| 2028 (uStrCaseCmp(field.str,"setwidth")==0)) { 2029 pField= &info->fontWeight; 2030 } 2031 else if ((uStrCaseCmp(field.str,"fontencoding")==0)|| 2032 (uStrCaseCmp(field.str,"encoding")==0)) { 2033 pField= &info->fontEncoding; 2034 } 2035 else if ((uStrCaseCmp(field.str,"xfont")==0)|| 2036 (uStrCaseCmp(field.str,"xfontname")==0)) { 2037 pField= &info->fontSpec; 2038 } 2039 else if (uStrCaseCmp(field.str,"fontsize")==0) { 2040 if (ndx!=NULL) { 2041 info->errorCount++; 2042 return ReportNotArray("keyboard",field.str,"geometry"); 2043 } 2044 if (!ExprResolveFloat(stmt->value,&tmp,NULL,NULL)) { 2045 info->errorCount++; 2046 return ReportBadType("keyboard",field.str,"geometry","number"); 2047 } 2048 if ((tmp.ival<40)||(tmp.ival>2550)) { 2049 info->errorCount++; 2050 ERROR1("Illegal font size %d (must be 4..255)\n",tmp.ival); 2051 ACTION("Ignoring font size in keyboard geometry\n"); 2052 return False; 2053 } 2054 info->fontSize= tmp.ival; 2055 return True; 2056 } 2057 else if ((uStrCaseCmp(field.str,"color")==0)|| 2058 (uStrCaseCmp(field.str,"basecolor")==0)){ 2059 if (ndx!=NULL) { 2060 info->errorCount++; 2061 return ReportNotArray("keyboard",field.str,"geometry"); 2062 } 2063 if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) { 2064 info->errorCount++; 2065 return ReportBadType("keyboard",field.str,"geometry","string"); 2066 } 2067 info->baseColor= XkbInternAtom(NULL,tmp.str,False); 2068 return True; 2069 } 2070 else if (uStrCaseCmp(field.str,"labelcolor")==0){ 2071 if (ndx!=NULL) { 2072 info->errorCount++; 2073 return ReportNotArray("keyboard",field.str,"geometry"); 2074 } 2075 if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) { 2076 info->errorCount++; 2077 return ReportBadType("keyboard",field.str,"geometry","string"); 2078 } 2079 info->labelColor= XkbInternAtom(NULL,tmp.str,False); 2080 return True; 2081 } 2082 else { 2083 return SetGeometryProperty(info,field.str,stmt->value); 2084 } 2085 2086 if (ndx!=NULL) { 2087 info->errorCount++; 2088 return ReportNotArray("keyboard",field.str,"geometry"); 2089 } 2090 if (!ExprResolveString(stmt->value,&tmp,NULL,NULL)) { 2091 info->errorCount++; 2092 return ReportBadType("keyboard",field.str,"geometry","string"); 2093 } 2094 *pField= XkbInternAtom(NULL,tmp.str,False); 2095 return True; 2096} 2097 2098/***====================================================================***/ 2099 2100static Bool 2101HandleShapeBody(ShapeDef *def,ShapeInfo *si,unsigned merge,GeometryInfo *info) 2102{ 2103OutlineDef * ol; 2104int nOut,nPt; 2105XkbOutlinePtr outline; 2106ExprDef * pt; 2107 2108 if (def->nOutlines<1) { 2109 WARN1("Shape \"%s\" has no outlines\n",shText(info->dpy,si)); 2110 ACTION("Definition ignored\n"); 2111 return True; 2112 } 2113 si->nOutlines= def->nOutlines; 2114 si->outlines= uTypedCalloc(def->nOutlines,XkbOutlineRec); 2115 if (!si->outlines) { 2116 ERROR1("Couldn't allocate outlines for \"%s\"\n",shText(info->dpy,si)); 2117 ACTION("Definition ignored\n"); 2118 info->errorCount++; 2119 return False; 2120 } 2121 for (nOut=0,ol=def->outlines;ol!=NULL;ol=(OutlineDef *)ol->common.next) { 2122 if (ol->nPoints<1) { 2123 SetShapeField(si,XkbAtomGetString(NULL,ol->field),NULL, 2124 ol->points,info); 2125 continue; 2126 } 2127 outline= NULL; 2128 outline= &si->outlines[nOut++]; 2129 outline->num_points= ol->nPoints; 2130 outline->corner_radius= si->dfltCornerRadius; 2131 outline->points= uTypedCalloc(ol->nPoints,XkbPointRec); 2132 if (!outline->points) { 2133 ERROR1("Can't allocate points for \"%s\"\n",shText(info->dpy,si)); 2134 ACTION("Definition ignored\n"); 2135 info->errorCount++; 2136 return False; 2137 } 2138 for (nPt=0,pt=ol->points;pt!=NULL;pt=(ExprDef *)pt->common.next) { 2139 outline->points[nPt].x= pt->value.coord.x; 2140 outline->points[nPt].y= pt->value.coord.y; 2141 nPt++; 2142 } 2143 if (ol->field!=None) { 2144 char *str= XkbAtomText(NULL,ol->field,XkbMessage); 2145 if ((uStrCaseCmp(str,"approximation")==0)|| 2146 (uStrCaseCmp(str,"approx")==0)) { 2147 if (si->approx==NULL) 2148 si->approx= outline; 2149 else { 2150 WARN1("Multiple approximations for \"%s\"\n", 2151 shText(info->dpy,si)); 2152 ACTION("Treating all but the first as normal outlines\n"); 2153 } 2154 } 2155 else if (uStrCaseCmp(str,"primary")==0) { 2156 if (si->primary==NULL) 2157 si->primary= outline; 2158 else { 2159 WARN1("Multiple primary outlines for \"%s\"\n", 2160 shText(info->dpy,si)); 2161 ACTION("Treating all but the first as normal outlines\n"); 2162 } 2163 } 2164 else { 2165 WARN2("Unknown outline type %s for \"%s\"\n",str, 2166 shText(info->dpy,si)); 2167 ACTION("Treated as a normal outline\n"); 2168 } 2169 } 2170 } 2171 if (nOut!=si->nOutlines) { 2172 WSGO2("Expected %d outlines, got %d\n",(unsigned int)si->nOutlines, 2173 nOut); 2174 si->nOutlines= nOut; 2175 } 2176 return True; 2177} 2178 2179static int 2180HandleShapeDef(ShapeDef *def,XkbDescPtr xkb,unsigned merge,GeometryInfo *info) 2181{ 2182ShapeInfo si; 2183 2184 if (def->merge!=MergeDefault) 2185 merge= def->merge; 2186 2187 bzero(&si,sizeof(ShapeInfo)); 2188 si.defs.merge= merge; 2189 si.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False); 2190 si.dfltCornerRadius= info->dfltCornerRadius; 2191 if (!HandleShapeBody(def,&si,merge,info)) 2192 return False; 2193 if (!AddShape(info,&si)) 2194 return False; 2195 return True; 2196} 2197 2198/***====================================================================***/ 2199 2200static int 2201HandleDoodadDef( DoodadDef *def, 2202 unsigned merge, 2203 SectionInfo *si, 2204 GeometryInfo *info) 2205{ 2206ExprResult elem,field; 2207ExprDef * ndx; 2208DoodadInfo new; 2209VarDef * var; 2210 2211 if (def->common.stmtType==StmtIndicatorMapDef) { 2212 def->common.stmtType= StmtDoodadDef; 2213 def->type= XkbIndicatorDoodad; 2214 } 2215 InitDoodadInfo(&new,def->type,si,info); 2216 new.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False); 2217 for (var=def->body;var!=NULL;var= (VarDef *)var->common.next) { 2218 if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0) 2219 return 0; /* internal error, already reported */ 2220 if (elem.str!=NULL) { 2221 WARN1("Assignment to field of unknown element in doodad %s\n", 2222 ddText(info->dpy,&new)); 2223 ACTION2("No value assigned to %s.%s\n",elem.str,field.str); 2224 } 2225 else if (!SetDoodadField(&new,field.str,ndx,var->value,si,info)) 2226 return False; 2227 } 2228 if (!AddDoodad(si,info,&new)) 2229 return False; 2230 ClearDoodadInfo(&new); 2231 return True; 2232} 2233 2234/***====================================================================***/ 2235 2236static int 2237HandleOverlayDef( OverlayDef * def, 2238 unsigned merge, 2239 SectionInfo * si, 2240 GeometryInfo * info) 2241{ 2242OverlayKeyDef * keyDef; 2243OverlayKeyInfo *key; 2244OverlayInfo ol; 2245 2246 if ((def->nKeys<1)&&(warningLevel>3)) { 2247 WARN2("Overlay \"%s\" in section \"%s\" has no keys\n", 2248 XkbAtomText(NULL,def->name,XkbMessage), 2249 scText(info->dpy,si)); 2250 ACTION("Overlay ignored\n"); 2251 return True; 2252 } 2253 bzero(&ol,sizeof(OverlayInfo)); 2254 ol.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False); 2255 for (keyDef= def->keys;keyDef;keyDef=(OverlayKeyDef *)keyDef->common.next) { 2256 key= uTypedCalloc(1,OverlayKeyInfo); 2257 if ((!key)&&warningLevel>0) { 2258 WSGO("Couldn't allocate OverlayKeyInfo\n"); 2259 ACTION2("Overlay %s for section %s will be incomplete\n", 2260 oiText(info->dpy,&ol), 2261 scText(info->dpy,si)); 2262 return False; 2263 } 2264 strncpy(key->over,keyDef->over,XkbKeyNameLength); 2265 strncpy(key->under,keyDef->under,XkbKeyNameLength); 2266 key->sectionRow= _GOK_UnknownRow; 2267 key->overlayRow= _GOK_UnknownRow; 2268 ol.keys= (OverlayKeyInfo *)AddCommonInfo(&ol.keys->defs, 2269 (CommonInfo *)key); 2270 ol.nKeys++; 2271 } 2272 if (!AddOverlay(si,info,&ol)) 2273 return False; 2274 ClearOverlayInfo(&ol); 2275 return True; 2276} 2277 2278/***====================================================================***/ 2279 2280static Bool 2281HandleComplexKey(KeyDef *def,KeyInfo *key,GeometryInfo *info) 2282{ 2283RowInfo * row; 2284ExprDef * expr; 2285 2286 row= key->row; 2287 for (expr=def->expr;expr!=NULL;expr=(ExprDef *)expr->common.next) { 2288 if (expr->op==OpAssign) { 2289 ExprResult elem,f; 2290 ExprDef *ndx; 2291 if (ExprResolveLhs(expr->value.binary.left,&elem,&f,&ndx)==0) 2292 return False; /* internal error, already reported */ 2293 if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"key")==0)) { 2294 if (!SetKeyField(key,f.str,ndx,expr->value.binary.right,info)) 2295 return False; 2296 } 2297 else { 2298 ERROR("Illegal element used in a key definition\n"); 2299 ACTION2("Assignment to %s.%s ignored\n",elem.str,f.str); 2300 return False; 2301 } 2302 } 2303 else { 2304 switch (expr->type) { 2305 case TypeInt: case TypeFloat: 2306 if (!SetKeyField(key,"gap",NULL,expr,info)) 2307 return False; 2308 break; 2309 case TypeString: 2310 if (!SetKeyField(key,"shape",NULL,expr,info)) 2311 return False; 2312 break; 2313 case TypeKeyName: 2314 if (!SetKeyField(key,"name",NULL,expr,info)) 2315 return False; 2316 break; 2317 default: 2318 ERROR("Cannot determine field for unnamed expression\n"); 2319 ACTION3("Ignoring key %d in row %d of section %s\n", 2320 row->nKeys+1,row->section->nRows+1, 2321 rowText(info->dpy,row)); 2322 return False; 2323 } 2324 } 2325 } 2326 return True; 2327} 2328 2329static Bool 2330HandleRowBody(RowDef *def,RowInfo *row,unsigned merge,GeometryInfo *info) 2331{ 2332KeyDef * keyDef; 2333 2334 if ((def->nKeys<1)&&(warningLevel>3)) { 2335 ERROR1("Row in section %s has no keys\n",rowText(info->dpy,row)); 2336 ACTION("Section ignored\n"); 2337 return True; 2338 } 2339 for (keyDef= def->keys; keyDef!=NULL;keyDef=(KeyDef *)keyDef->common.next) { 2340 if (keyDef->common.stmtType==StmtVarDef) { 2341 VarDef *var= (VarDef *)keyDef; 2342 ExprResult elem,field; 2343 ExprDef *ndx; 2344 if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0) 2345 return 0; /* internal error, already reported */ 2346 if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"row")==0)) { 2347 if (!SetRowField(row,field.str,ndx,var->value,info)) 2348 return False; 2349 } 2350 else if (uStrCaseCmp(elem.str,"key")==0) { 2351 if (!SetKeyField(&row->dfltKey,field.str,ndx,var->value,info)) 2352 return False; 2353 } 2354 else { 2355 WARN("Assignment to field of unknown element in row\n"); 2356 ACTION2("No value assigned to %s.%s\n",elem.str,field.str); 2357 } 2358 } 2359 else if (keyDef->common.stmtType==StmtKeyDef) { 2360 KeyInfo key; 2361 InitKeyInfo(&key,row,info); 2362 if (keyDef->name!=NULL) { 2363 int len= strlen(keyDef->name); 2364 if ((len<1)||(len>XkbKeyNameLength)) { 2365 ERROR2("Illegal name %s for key in section %s\n", 2366 keyDef->name, 2367 rowText(info->dpy,row)); 2368 ACTION("Section not compiled\n"); 2369 return False; 2370 } 2371 bzero(key.name,XkbKeyNameLength+1); 2372 strncpy(key.name,keyDef->name,XkbKeyNameLength); 2373 key.defs.defined|= _GK_Name; 2374 } 2375 else if (!HandleComplexKey(keyDef,&key,info)) 2376 return False; 2377 if (!AddKey(row,&key)) 2378 return False; 2379 } 2380 else { 2381 WSGO1("Unexpected statement (type %d) in row body\n", 2382 keyDef->common.stmtType); 2383 return False; 2384 } 2385 } 2386 return True; 2387} 2388 2389static Bool 2390HandleSectionBody( SectionDef * def, 2391 SectionInfo * si, 2392 unsigned merge, 2393 GeometryInfo * info) 2394{ 2395RowDef * rowDef; 2396DoodadInfo * di; 2397 2398 for (rowDef= def->rows;rowDef!=NULL;rowDef=(RowDef *)rowDef->common.next) { 2399 if (rowDef->common.stmtType==StmtVarDef) { 2400 VarDef *var= (VarDef *)rowDef; 2401 ExprResult elem,field; 2402 ExprDef *ndx; 2403 if (ExprResolveLhs(var->name,&elem,&field,&ndx)==0) 2404 return 0; /* internal error, already reported */ 2405 if ((elem.str==NULL)||(uStrCaseCmp(elem.str,"section")==0)) { 2406 if (!SetSectionField(si,field.str,ndx,var->value,info)) 2407 return False; 2408 } 2409 else if (uStrCaseCmp(elem.str,"row")==0) { 2410 if (!SetRowField(&si->dfltRow,field.str,ndx,var->value,info)) 2411 return False; 2412 } 2413 else if (uStrCaseCmp(elem.str,"key")==0) { 2414 if(!SetKeyField(&si->dfltRow.dfltKey,field.str,ndx, 2415 var->value,info)) 2416 return False; 2417 } 2418 else if ((di=FindDfltDoodadByTypeName(elem.str,si,info))!=NULL) { 2419 if (!SetDoodadField(di,field.str,ndx,var->value,si,info)) 2420 return False; 2421 } 2422 else { 2423 WARN("Assignment to field of unknown element in section\n"); 2424 ACTION2("No value assigned to %s.%s\n",elem.str,field.str); 2425 } 2426 } 2427 else if (rowDef->common.stmtType==StmtRowDef) { 2428 RowInfo row; 2429 InitRowInfo(&row,si,info); 2430 if (!HandleRowBody(rowDef,&row,merge,info)) 2431 return False; 2432 if (!AddRow(si,&row)) 2433 return False; 2434/* ClearRowInfo(&row,info);*/ 2435 } 2436 else if ((rowDef->common.stmtType==StmtDoodadDef)|| 2437 (rowDef->common.stmtType==StmtIndicatorMapDef)) { 2438 if (!HandleDoodadDef((DoodadDef *)rowDef,merge,si,info)) 2439 return False; 2440 } 2441 else if (rowDef->common.stmtType==StmtOverlayDef) { 2442 if (!HandleOverlayDef((OverlayDef *)rowDef,merge,si,info)) 2443 return False; 2444 } 2445 else { 2446 WSGO1("Unexpected statement (type %d) in section body\n", 2447 rowDef->common.stmtType); 2448 return False; 2449 } 2450 } 2451 if (si->nRows!=def->nRows) { 2452 WSGO2("Expected %d rows, found %d\n",(unsigned int)def->nRows, 2453 (unsigned int)si->nRows); 2454 ACTION1("Definition of section %s might be incorrect\n", 2455 scText(info->dpy,si)); 2456 } 2457 return True; 2458} 2459 2460static int 2461HandleSectionDef( SectionDef * def, 2462 XkbDescPtr xkb, 2463 unsigned merge, 2464 GeometryInfo * info) 2465{ 2466SectionInfo si; 2467char * str; 2468 2469 if (def->merge!=MergeDefault) 2470 merge= def->merge; 2471 InitSectionInfo(&si,info); 2472 si.defs.merge= merge; 2473 str= XkbAtomGetString(NULL,def->name); 2474 if ((str==NULL)||(strlen(str)<1)) { 2475 ERROR("Section defined without a name\n"); 2476 ACTION("Definition ignored\n"); 2477 return False; 2478 } 2479 si.name= XkbInternAtom(info->dpy,XkbAtomGetString(NULL,def->name),False); 2480 if (!HandleSectionBody(def,&si,merge,info)) 2481 return False; 2482 if (!AddSection(info,&si)) 2483 return False; 2484 return True; 2485} 2486 2487/***====================================================================***/ 2488 2489static void 2490HandleGeometryFile( XkbFile * file, 2491 XkbDescPtr xkb, 2492 unsigned merge, 2493 GeometryInfo * info) 2494{ 2495ParseCommon * stmt; 2496char * failWhat; 2497 2498 if (merge==MergeDefault) 2499 merge= MergeAugment; 2500 info->name= uStringDup(file->name); 2501 stmt= file->defs; 2502 while (stmt) { 2503 failWhat= NULL; 2504 switch (stmt->stmtType) { 2505 case StmtInclude: 2506 if (!HandleIncludeGeometry((IncludeStmt *)stmt,xkb,info, 2507 HandleGeometryFile)) 2508 info->errorCount++; 2509 break; 2510 case StmtKeyAliasDef: 2511 if (!HandleAliasDef((KeyAliasDef *)stmt, 2512 merge,info->fileID,&info->aliases)) { 2513 info->errorCount++; 2514 } 2515 break; 2516 case StmtVarDef: 2517 if (!HandleGeometryVar((VarDef *)stmt,xkb,info)) 2518 info->errorCount++; 2519 break; 2520 case StmtShapeDef: 2521 if (!HandleShapeDef((ShapeDef *)stmt,xkb,merge,info)) 2522 info->errorCount++; 2523 break; 2524 case StmtSectionDef: 2525 if (!HandleSectionDef((SectionDef *)stmt,xkb,merge,info)) 2526 info->errorCount++; 2527 break; 2528 case StmtIndicatorMapDef: 2529 case StmtDoodadDef: 2530 if (!HandleDoodadDef((DoodadDef *)stmt,merge,NULL,info)) 2531 info->errorCount++; 2532 break; 2533 case StmtVModDef: 2534 if (!failWhat) failWhat= "virtual modfier"; 2535 case StmtInterpDef: 2536 if (!failWhat) failWhat= "symbol interpretation"; 2537 case StmtGroupCompatDef: 2538 if (!failWhat) failWhat= "group compatibility map"; 2539 case StmtKeycodeDef: 2540 if (!failWhat) failWhat= "key name"; 2541 ERROR("Interpretation files may not include other types\n"); 2542 ACTION1("Ignoring %s definition.\n",failWhat); 2543 info->errorCount++; 2544 break; 2545 default: 2546 WSGO1("Unexpected statement type %d in HandleGeometryFile\n", 2547 stmt->stmtType); 2548 break; 2549 } 2550 stmt= stmt->next; 2551 if (info->errorCount>10) { 2552#ifdef NOISY 2553 ERROR("Too many errors\n"); 2554#endif 2555 ACTION1("Abandoning geometry file \"%s\"\n",file->topName); 2556 break; 2557 } 2558 } 2559 return; 2560} 2561 2562/***====================================================================***/ 2563 2564static Bool 2565CopyShapeDef(Display *dpy,XkbGeometryPtr geom,ShapeInfo *si) 2566{ 2567register int i,n; 2568XkbShapePtr shape; 2569XkbOutlinePtr old_outline,outline; 2570Atom name; 2571 2572 si->index= geom->num_shapes; 2573 name= XkbInternAtom(dpy,XkbAtomGetString(NULL,si->name),False); 2574 shape= XkbAddGeomShape(geom,name,si->nOutlines); 2575 if (!shape) { 2576 WSGO("Couldn't allocate shape in geometry\n"); 2577 ACTION1("Shape %s not compiled\n",shText(dpy,si)); 2578 return False; 2579 } 2580 old_outline= si->outlines; 2581 for (i=0;i<si->nOutlines;i++,old_outline++) { 2582 outline= XkbAddGeomOutline(shape,old_outline->num_points); 2583 if (!outline) { 2584 WSGO("Couldn't allocate outline in shape\n"); 2585 ACTION1("Shape %s is incomplete\n",shText(dpy,si)); 2586 return False; 2587 } 2588 n= old_outline->num_points; 2589 memcpy(outline->points,old_outline->points,n*sizeof(XkbPointRec)); 2590 outline->num_points= old_outline->num_points; 2591 outline->corner_radius= old_outline->corner_radius; 2592 } 2593 if (si->approx) { 2594 n= (si->approx-si->outlines); 2595 shape->approx= &shape->outlines[n]; 2596 } 2597 if (si->primary) { 2598 n= (si->primary-si->outlines); 2599 shape->primary= &shape->outlines[n]; 2600 } 2601 XkbComputeShapeBounds(shape); 2602 return True; 2603} 2604 2605static Bool 2606VerifyDoodadInfo(DoodadInfo *di,GeometryInfo *info) 2607{ 2608 if ((di->defs.defined&(_GD_Top|_GD_Left))!=(_GD_Top|_GD_Left)) { 2609 if (warningLevel<9) { 2610 ERROR1("No position defined for doodad %s\n",ddText(info->dpy,di)); 2611 ACTION("Illegal doodad ignored\n"); 2612 return False; 2613 } 2614 } 2615 if ((di->defs.defined & _GD_Priority) == 0) { 2616 /* calculate priority -- should be just above previous doodad/row */ 2617 } 2618 switch (di->type) { 2619 case XkbOutlineDoodad: 2620 case XkbSolidDoodad: 2621 if ((di->defs.defined&_GD_Shape)==0) { 2622 ERROR2("No shape defined for %s doodad %s\n", 2623 (di->type==XkbOutlineDoodad?"outline":"filled"), 2624 ddText(info->dpy,di)); 2625 ACTION("Incomplete definition ignored\n"); 2626 return False; 2627 } 2628 else { 2629 ShapeInfo *si; 2630 si= FindShape(info,di->shape, (di->type==XkbOutlineDoodad? 2631 "outline doodad": 2632 "solid doodad"), 2633 ddText(info->dpy,di)); 2634 if (si) 2635 di->shape= si->name; 2636 else { 2637 ERROR1("No legal shape for %s\n",ddText(info->dpy,di)); 2638 ACTION("Incomplete definition ignored\n"); 2639 return False; 2640 } 2641 } 2642 if ((di->defs.defined&_GD_Color)==0) { 2643 if (warningLevel>5) { 2644 WARN1("No color for doodad %s\n",ddText(info->dpy,di)); 2645 ACTION("Using black\n"); 2646 } 2647 di->color= XkbInternAtom(NULL,"black",False); 2648 } 2649 break; 2650 case XkbTextDoodad: 2651 if ((di->defs.defined&_GD_Text)==0) { 2652 ERROR1("No text specified for text doodad %s\n", 2653 ddText(info->dpy,di)); 2654 ACTION("Illegal doodad definition ignored\n"); 2655 return False; 2656 } 2657 if ((di->defs.defined&_GD_Angle)==0) 2658 di->angle= 0; 2659 if ((di->defs.defined&_GD_Color)==0) { 2660 if (warningLevel>5) { 2661 WARN1("No color specified for doodad %s\n", 2662 ddText(info->dpy,di)); 2663 ACTION("Using black\n"); 2664 } 2665 di->color= XkbInternAtom(NULL,"black",False); 2666 } 2667 if ((di->defs.defined&_GD_FontSpec)!=0) { 2668 if ((di->defs.defined&_GD_FontParts)==0) 2669 return True; 2670 if (warningLevel<9) { 2671 WARN1("Text doodad %s has full and partial font definition\n", 2672 ddText(info->dpy,di)); 2673 ACTION("Full specification ignored\n"); 2674 } 2675 di->defs.defined&= ~_GD_FontSpec; 2676 di->fontSpec= None; 2677 } 2678 if ((di->defs.defined&_GD_Font)==0) { 2679 if (warningLevel>5) { 2680 WARN1("No font specified for doodad %s\n", 2681 ddText(info->dpy,di)); 2682 ACTION1("Using \"%s\"\n",DFLT_FONT); 2683 } 2684 di->font= XkbInternAtom(NULL,DFLT_FONT,False); 2685 } 2686 if ((di->defs.defined&_GD_FontSlant)==0) { 2687 if (warningLevel>7) { 2688 WARN1("No font slant for text doodad %s\n", 2689 ddText(info->dpy,di)); 2690 ACTION1("Using \"%s\"\n",DFLT_SLANT); 2691 } 2692 di->fontSlant= XkbInternAtom(NULL,DFLT_SLANT,False); 2693 } 2694 if ((di->defs.defined&_GD_FontWeight)==0) { 2695 if (warningLevel>7) { 2696 WARN1("No font weight for text doodad %s\n", 2697 ddText(info->dpy,di)); 2698 ACTION1("Using \"%s\"\n",DFLT_WEIGHT); 2699 } 2700 di->fontWeight= XkbInternAtom(NULL,DFLT_WEIGHT,False); 2701 } 2702 if ((di->defs.defined&_GD_FontSetWidth)==0) { 2703 if (warningLevel>9) { 2704 WARN1("No font set width for text doodad %s\n", 2705 ddText(info->dpy,di)); 2706 ACTION1("Using \"%s\"\n",DFLT_SET_WIDTH); 2707 } 2708 di->fontSetWidth= XkbInternAtom(NULL,DFLT_SET_WIDTH,False); 2709 } 2710 if ((di->defs.defined&_GD_FontVariant)==0) { 2711 if (warningLevel>9) { 2712 WARN1("No font variant for text doodad %s\n", 2713 ddText(info->dpy,di)); 2714 ACTION1("Using \"%s\"\n",DFLT_VARIANT); 2715 } 2716 di->fontVariant= XkbInternAtom(NULL,DFLT_VARIANT,False); 2717 } 2718 if ((di->defs.defined&_GD_FontEncoding)==0) { 2719 if (warningLevel>7) { 2720 WARN1("No font encoding for doodad %s\n", 2721 ddText(info->dpy,di)); 2722 ACTION1("Using \"%s\"\n",DFLT_ENCODING); 2723 } 2724 di->fontEncoding= XkbInternAtom(NULL,DFLT_ENCODING,False); 2725 } 2726 if ((di->defs.defined&_GD_FontSize)==0) { 2727 if (warningLevel>7) { 2728 WARN1("No font size for text doodad %s\n", 2729 ddText(info->dpy,di)); 2730 ACTION1("Using %s point text\n", 2731 XkbGeomFPText(DFLT_SIZE,XkbMessage)); 2732 } 2733 di->fontSize= DFLT_SIZE; 2734 } 2735 if ((di->defs.defined&_GD_Height)==0) { 2736 unsigned size,nLines; 2737 char *tmp; 2738 size= (di->fontSize*120)/100; 2739 size= (size*254)/720; /* convert to mm/10 */ 2740 for (nLines=1,tmp=XkbAtomGetString(NULL,di->text);*tmp;tmp++) { 2741 if (*tmp=='\n') nLines++; 2742 } 2743 size*= nLines; 2744 if (warningLevel>5) { 2745 WARN1("No height for text doodad %s\n", 2746 ddText(info->dpy,di)); 2747 ACTION1("Using calculated height %s millimeters\n", 2748 XkbGeomFPText(size,XkbMessage)); 2749 } 2750 di->height= size; 2751 } 2752 if ((di->defs.defined&_GD_Width)==0) { 2753 unsigned width,tmp; 2754 char *str; 2755 width= tmp= 0; 2756 for (str=XkbAtomGetString(NULL,di->text);*str;str++) { 2757 if (*str!='\n') 2758 tmp++; 2759 else { 2760 if (tmp>width) 2761 width= tmp; 2762 tmp= 1; 2763 } 2764 } 2765 if (width==0) 2766 width= tmp; 2767 width*= (di->height*2)/3; 2768 if (warningLevel>5) { 2769 WARN1("No width for text doodad %s\n",ddText(info->dpy,di)); 2770 ACTION1("Using calculated width %s millimeters\n", 2771 XkbGeomFPText(width,XkbMessage)); 2772 } 2773 di->width= width; 2774 } 2775 break; 2776 case XkbIndicatorDoodad: 2777 if ((di->defs.defined&_GD_Shape)==0) { 2778 ERROR1("No shape defined for indicator doodad %s\n", 2779 ddText(info->dpy,di)); 2780 ACTION("Incomplete definition ignored\n"); 2781 return False; 2782 } 2783 else { 2784 ShapeInfo *si; 2785 si= FindShape(info,di->shape,"indicator doodad", 2786 ddText(info->dpy,di)); 2787 if (si) 2788 di->shape= si->name; 2789 else { 2790 ERROR1("No legal shape for doodad %s\n", 2791 ddText(info->dpy,di)); 2792 ACTION("Incomplete definition ignored\n"); 2793 return False; 2794 } 2795 } 2796 if ((di->defs.defined&_GD_Color)==0) { 2797 if (warningLevel>5) { 2798 WARN1("No \"on\" color for indicator doodad %s\n", 2799 ddText(info->dpy,di)); 2800 ACTION("Using green\n"); 2801 } 2802 di->color= XkbInternAtom(NULL,"green",False); 2803 } 2804 if ((di->defs.defined&_GD_OffColor)==0) { 2805 if (warningLevel>5) { 2806 WARN1("No \"off\" color for indicator doodad %s\n", 2807 ddText(info->dpy,di)); 2808 ACTION("Using black\n"); 2809 } 2810 di->offColor= XkbInternAtom(NULL,"black",False); 2811 } 2812 break; 2813 case XkbLogoDoodad: 2814 if (di->logoName==NULL) { 2815 ERROR1("No logo name defined for logo doodad %s\n", 2816 ddText(info->dpy,di)); 2817 ACTION("Incomplete definition ignored\n"); 2818 return False; 2819 } 2820 if ((di->defs.defined&_GD_Shape)==0) { 2821 ERROR1("No shape defined for logo doodad %s\n", 2822 ddText(info->dpy,di)); 2823 ACTION("Incomplete definition ignored\n"); 2824 return False; 2825 } 2826 else { 2827 ShapeInfo *si; 2828 si= FindShape(info,di->shape,"logo doodad", 2829 ddText(info->dpy,di)); 2830 if (si) 2831 di->shape= si->name; 2832 else { 2833 ERROR1("No legal shape for %s\n",ddText(info->dpy,di)); 2834 ACTION("Incomplete definition ignored\n"); 2835 return False; 2836 } 2837 } 2838 if ((di->defs.defined&_GD_Color)==0) { 2839 if (warningLevel>5) { 2840 WARN1("No color for doodad %s\n",ddText(info->dpy,di)); 2841 ACTION("Using black\n"); 2842 } 2843 di->color= XkbInternAtom(NULL,"black",False); 2844 } 2845 break; 2846 default: 2847 WSGO1("Uknown doodad type %d in VerifyDoodad\n",(unsigned int)di->type); 2848 return False; 2849 } 2850 return True; 2851} 2852 2853#define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s" 2854 2855static char * 2856FontFromParts( Atom fontTok, 2857 Atom weightTok, 2858 Atom slantTok, 2859 Atom setWidthTok, 2860 Atom varTok, 2861 int size, 2862 Atom encodingTok) 2863{ 2864int totalSize; 2865char *font,*weight,*slant,*setWidth,*variant,*encoding; 2866char * rtrn; 2867 2868 font= (fontTok!=None?XkbAtomGetString(NULL,fontTok):DFLT_FONT); 2869 weight= (weightTok!=None?XkbAtomGetString(NULL,weightTok):DFLT_WEIGHT); 2870 slant= (slantTok!=None?XkbAtomGetString(NULL,slantTok):DFLT_SLANT); 2871 setWidth= (setWidthTok!=None?XkbAtomGetString(NULL,setWidthTok): 2872 DFLT_SET_WIDTH); 2873 variant= (varTok!=None?XkbAtomGetString(NULL,varTok):DFLT_VARIANT); 2874 encoding= (encodingTok!=None?XkbAtomGetString(NULL,encodingTok): 2875 DFLT_ENCODING); 2876 if (size==0) 2877 size= DFLT_SIZE; 2878 totalSize= strlen(FONT_TEMPLATE)+strlen(font)+strlen(weight)+strlen(slant); 2879 totalSize+= strlen(setWidth)+strlen(variant)+strlen(encoding); 2880 rtrn= uCalloc(totalSize,1); 2881 if (rtrn) { 2882 sprintf(rtrn,FONT_TEMPLATE,font,weight,slant,setWidth,variant, 2883 size,encoding); 2884 } 2885 return rtrn; 2886} 2887 2888static Bool 2889CopyDoodadDef( XkbGeometryPtr geom, 2890 XkbSectionPtr section, 2891 DoodadInfo * di, 2892 GeometryInfo * info) 2893{ 2894Atom name; 2895XkbDoodadPtr doodad; 2896XkbColorPtr color; 2897XkbShapePtr shape; 2898ShapeInfo * si; 2899 2900 if (!VerifyDoodadInfo(di,info)) 2901 return False; 2902 name= XkbInternAtom(NULL,XkbAtomGetString(NULL,di->name),False); 2903 doodad= XkbAddGeomDoodad(geom,section,name); 2904 if (!doodad) { 2905 WSGO1("Couldn't allocate doodad in %s\n", 2906 (section?"section":"geometry")); 2907 ACTION1("Cannot copy doodad %s\n",ddText(info->dpy,di)); 2908 return False; 2909 } 2910 doodad->any.type= di->type; 2911 doodad->any.priority= di->priority; 2912 doodad->any.top= di->top; 2913 doodad->any.left= di->left; 2914 switch (di->type) { 2915 case XkbOutlineDoodad: 2916 case XkbSolidDoodad: 2917 si= FindShape(info,di->shape,NULL,NULL); 2918 if (!si) 2919 return False; 2920 doodad->shape.angle= di->angle; 2921 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors); 2922 shape= &geom->shapes[si->index]; 2923 XkbSetShapeDoodadColor(geom,&doodad->shape,color); 2924 XkbSetShapeDoodadShape(geom,&doodad->shape,shape); 2925 break; 2926 case XkbTextDoodad: 2927 doodad->text.angle= di->angle; 2928 doodad->text.width= di->width; 2929 doodad->text.height= di->height; 2930 if (di->fontSpec==None) 2931 doodad->text.font= FontFromParts(di->font,di->fontWeight, 2932 di->fontSlant,di->fontSetWidth, 2933 di->fontVariant, 2934 di->fontSize,di->fontEncoding); 2935 else doodad->text.font= XkbAtomGetString(NULL,di->fontSpec); 2936 doodad->text.text= XkbAtomGetString(NULL,di->text); 2937 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors); 2938 XkbSetTextDoodadColor(geom,&doodad->text,color); 2939 break; 2940 case XkbIndicatorDoodad: 2941 si= FindShape(info,di->shape,NULL,NULL); 2942 if (!si) 2943 return False; 2944 shape= &geom->shapes[si->index]; 2945 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors); 2946 XkbSetIndicatorDoodadShape(geom,&doodad->indicator,shape); 2947 XkbSetIndicatorDoodadOnColor(geom,&doodad->indicator,color); 2948 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->offColor),geom->num_colors); 2949 XkbSetIndicatorDoodadOffColor(geom,&doodad->indicator,color); 2950 break; 2951 case XkbLogoDoodad: 2952 si= FindShape(info,di->shape,NULL,NULL); 2953 if (!si) 2954 return False; 2955 doodad->logo.angle= di->angle; 2956 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,di->color),geom->num_colors); 2957 shape= &geom->shapes[si->index]; 2958 XkbSetLogoDoodadColor(geom,&doodad->logo,color); 2959 XkbSetLogoDoodadShape(geom,&doodad->logo,shape); 2960 doodad->logo.logo_name= di->logoName; 2961 di->logoName= NULL; 2962 break; 2963 } 2964 return True; 2965} 2966 2967/***====================================================================***/ 2968 2969static Bool 2970VerifyOverlayInfo( XkbGeometryPtr geom, 2971 XkbSectionPtr section, 2972 OverlayInfo * oi, 2973 GeometryInfo * info, 2974 short rowMap[256], 2975 short rowSize[256]) 2976{ 2977register OverlayKeyInfo * ki,*next; 2978unsigned long oKey,uKey,sKey; 2979XkbRowPtr row; 2980XkbKeyPtr key; 2981int r,k; 2982 2983 /* find out which row each key is in */ 2984 for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) { 2985 oKey= KeyNameToLong(ki->over); 2986 uKey= KeyNameToLong(ki->under); 2987 for (r=0,row=section->rows;(r<section->num_rows)&&oKey;r++,row++) { 2988 for (k=0,key=row->keys;(k<row->num_keys)&&oKey;k++,key++) { 2989 sKey= KeyNameToLong(key->name.name); 2990 if (sKey==oKey) { 2991 if (warningLevel>0) { 2992 WARN3("Key %s in section \"%s\" and overlay \"%s\"\n", 2993 XkbKeyNameText(key->name.name,XkbMessage), 2994 XkbAtomText(info->dpy,section->name,XkbMessage), 2995 XkbAtomText(info->dpy,oi->name,XkbMessage)); 2996 ACTION("Overlay definition ignored\n"); 2997 } 2998 oKey= 0; 2999 } 3000 else if (sKey==uKey) { 3001 ki->sectionRow= r; 3002 oKey= 0; 3003 } 3004 } 3005 } 3006 if ((ki->sectionRow==_GOK_UnknownRow)&&(warningLevel>0)) { 3007 WARN3("Key %s not in \"%s\", but has an overlay key in \"%s\"\n", 3008 XkbKeyNameText(ki->under,XkbMessage), 3009 XkbAtomText(info->dpy,section->name,XkbMessage), 3010 XkbAtomText(info->dpy,oi->name,XkbMessage)); 3011 ACTION("Definition ignored\n"); 3012 } 3013 } 3014 /* now prune out keys that aren't in the section */ 3015 while ((oi->keys!=NULL)&&(oi->keys->sectionRow==_GOK_UnknownRow)) { 3016 next= (OverlayKeyInfo *)oi->keys->defs.next; 3017 uFree(oi->keys); 3018 oi->keys= next; 3019 oi->nKeys--; 3020 } 3021 for (ki=oi->keys;(ki!=NULL)&&(ki->defs.next!=NULL);ki=next) { 3022 next= (OverlayKeyInfo *)ki->defs.next; 3023 if (next->sectionRow==_GOK_UnknownRow) { 3024 ki->defs.next= next->defs.next; 3025 oi->nKeys--; 3026 uFree(next); 3027 next= (OverlayKeyInfo *)ki->defs.next; 3028 } 3029 } 3030 if (oi->nKeys<1) { 3031 ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n", 3032 XkbAtomText(info->dpy,oi->name,XkbMessage), 3033 XkbAtomText(info->dpy,section->name,XkbMessage)); 3034 ACTION("Overlay definition ignored\n"); 3035 return False; 3036 } 3037 /* now figure out how many rows are defined for the overlay */ 3038 bzero(rowSize,sizeof(short)*256); 3039 for (k=0;k<256;k++) { 3040 rowMap[k]= -1; 3041 } 3042 oi->nRows= 0; 3043 for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) { 3044 if (rowMap[ki->sectionRow]==-1) 3045 rowMap[ki->sectionRow]= oi->nRows++; 3046 ki->overlayRow= rowMap[ki->sectionRow]; 3047 rowSize[ki->overlayRow]++; 3048 } 3049 return True; 3050} 3051 3052static Bool 3053CopyOverlayDef( XkbGeometryPtr geom, 3054 XkbSectionPtr section, 3055 OverlayInfo * oi, 3056 GeometryInfo * info) 3057{ 3058Atom name; 3059XkbOverlayPtr ol; 3060XkbOverlayRowPtr row; 3061XkbOverlayKeyPtr key; 3062OverlayKeyInfo * ki; 3063short rowMap[256],rowSize[256]; 3064int i; 3065 3066 if (!VerifyOverlayInfo(geom,section,oi,info,rowMap,rowSize)) 3067 return False; 3068 name= XkbInternAtom(NULL,XkbAtomGetString(NULL,oi->name),False); 3069 ol= XkbAddGeomOverlay(section,name,oi->nRows); 3070 if (!ol) { 3071 WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n", 3072 XkbAtomText(info->dpy,name,XkbMessage), 3073 XkbAtomText(info->dpy,section->name,XkbMessage)); 3074 return False; 3075 } 3076 for (i=0;i<oi->nRows;i++) { 3077 int tmp,row_under; 3078 for (tmp=0,row_under=-1;(tmp<section->num_rows)&&(row_under<0);tmp++) { 3079 if (rowMap[tmp]==i) 3080 row_under= tmp; 3081 } 3082 if (!XkbAddGeomOverlayRow(ol,row_under,rowSize[i])) { 3083 WSGO3("Can't add row %d to overlay \"%s\" of section \"%s\"\n", 3084 i,XkbAtomText(info->dpy,name,XkbMessage), 3085 XkbAtomText(info->dpy,section->name,XkbMessage)); 3086 return False; 3087 } 3088 } 3089 for (ki=oi->keys;ki!=NULL;ki=(OverlayKeyInfo *)ki->defs.next) { 3090 row= &ol->rows[ki->overlayRow]; 3091 key= &row->keys[row->num_keys++]; 3092 bzero(key,sizeof(XkbOverlayKeyRec)); 3093 strncpy(key->over.name,ki->over,XkbKeyNameLength); 3094 strncpy(key->under.name,ki->under,XkbKeyNameLength); 3095 } 3096 return True; 3097} 3098 3099/***====================================================================***/ 3100 3101static Bool 3102CopySectionDef(XkbGeometryPtr geom,SectionInfo *si,GeometryInfo *info) 3103{ 3104XkbSectionPtr section; 3105XkbRowPtr row; 3106XkbKeyPtr key; 3107KeyInfo * ki; 3108RowInfo * ri; 3109Atom name; 3110 3111 name= XkbInternAtom(NULL,XkbAtomGetString(NULL,si->name),False); 3112 section= XkbAddGeomSection(geom,name,si->nRows,si->nDoodads,si->nOverlays); 3113 if (section==NULL) { 3114 WSGO("Couldn't allocate section in geometry\n"); 3115 ACTION1("Section %s not compiled\n",scText(info->dpy,si)); 3116 return False; 3117 } 3118 section->top= si->top; 3119 section->left= si->left; 3120 section->width= si->width; 3121 section->height= si->height; 3122 section->angle= si->angle; 3123 section->priority= si->priority; 3124 for (ri=si->rows;ri!=NULL;ri=(RowInfo *)ri->defs.next) { 3125 row= XkbAddGeomRow(section,ri->nKeys); 3126 if (row==NULL) { 3127 WSGO("Couldn't allocate row in section\n"); 3128 ACTION1("Section %s is incomplete\n",scText(info->dpy,si)); 3129 return False; 3130 } 3131 row->top= ri->top; 3132 row->left= ri->left; 3133 row->vertical= ri->vertical; 3134 for (ki=ri->keys;ki!=NULL;ki=(KeyInfo *)ki->defs.next) { 3135 XkbColorPtr color; 3136 if ((ki->defs.defined&_GK_Name)==0) { 3137 ERROR3("Key %d of row %d in section %s has no name\n", 3138 (int)ki->index,(int)ri->index, 3139 scText(info->dpy,si)); 3140 ACTION1("Section %s ignored\n",scText(info->dpy,si)); 3141 return False; 3142 } 3143 key= XkbAddGeomKey(row); 3144 if (key==NULL) { 3145 WSGO("Couldn't allocate key in row\n"); 3146 ACTION1("Section %s is incomplete\n",scText(info->dpy,si)); 3147 return False; 3148 } 3149 memcpy(key->name.name,ki->name,XkbKeyNameLength); 3150 key->gap= ki->gap; 3151 if (ki->shape==None) 3152 key->shape_ndx= 0; 3153 else { 3154 ShapeInfo *si; 3155 si= FindShape(info,ki->shape,"key",keyText(ki)); 3156 if (!si) 3157 return False; 3158 key->shape_ndx= si->index; 3159 } 3160 if (ki->color!=None) 3161 color= XkbAddGeomColor(geom,XkbAtomGetString(NULL,ki->color),geom->num_colors); 3162 else color= XkbAddGeomColor(geom,"white",geom->num_colors); 3163 XkbSetKeyColor(geom,key,color); 3164 } 3165 } 3166 if (si->doodads!=NULL) { 3167 DoodadInfo *di; 3168 for (di=si->doodads;di!=NULL;di=(DoodadInfo *)di->defs.next) { 3169 CopyDoodadDef(geom,section,di,info); 3170 } 3171 } 3172 if (si->overlays!=NULL) { 3173 OverlayInfo *oi; 3174 for (oi=si->overlays;oi!=NULL;oi=(OverlayInfo *)oi->defs.next) { 3175 CopyOverlayDef(geom,section,oi,info); 3176 } 3177 } 3178 if (XkbComputeSectionBounds(geom,section)) { 3179 /* 7/6/94 (ef) -- check for negative origin and translate */ 3180 if ((si->defs.defined&_GS_Width)==0) 3181 section->width= section->bounds.x2; 3182 if ((si->defs.defined&_GS_Height)==0) 3183 section->height= section->bounds.y2; 3184 } 3185 return True; 3186} 3187 3188/***====================================================================***/ 3189 3190Bool 3191CompileGeometry(XkbFile *file,XkbFileInfo *result,unsigned merge) 3192{ 3193GeometryInfo info; 3194XkbDescPtr xkb; 3195 3196 xkb= result->xkb; 3197 InitGeometryInfo(&info,file->id,merge); 3198 info.dpy= xkb->dpy; 3199 HandleGeometryFile(file,xkb,merge,&info); 3200 3201 if (info.errorCount==0) { 3202 XkbGeometryPtr geom; 3203 XkbGeometrySizesRec sizes; 3204 bzero(&sizes,sizeof(sizes)); 3205 sizes.which= XkbGeomAllMask; 3206 sizes.num_properties= info.nProps; 3207 sizes.num_colors= 8; 3208 sizes.num_shapes= info.nShapes; 3209 sizes.num_sections= info.nSections; 3210 sizes.num_doodads= info.nDoodads; 3211 if (XkbAllocGeometry(xkb,&sizes)!=Success) { 3212 WSGO("Couldn't allocate GeometryRec\n"); 3213 ACTION("Geometry not compiled\n"); 3214 return False; 3215 } 3216 geom= xkb->geom; 3217 3218 geom->width_mm= info.widthMM; 3219 geom->height_mm= info.heightMM; 3220 if (info.name!=NULL) { 3221 geom->name= XkbInternAtom(xkb->dpy,info.name,False); 3222 if (XkbAllocNames(xkb,XkbGeometryNameMask,0,0)==Success) 3223 xkb->names->geometry= geom->name; 3224 } 3225 if (info.fontSpec!=None) 3226 geom->label_font= uStringDup(XkbAtomGetString(NULL,info.fontSpec)); 3227 else geom->label_font= FontFromParts(info.font,info.fontWeight, 3228 info.fontSlant,info.fontSetWidth, 3229 info.fontVariant, 3230 info.fontSize,info.fontEncoding); 3231 XkbAddGeomColor(geom,"black",geom->num_colors); 3232 XkbAddGeomColor(geom,"white",geom->num_colors); 3233 3234 if (info.baseColor==None) 3235 info.baseColor= XkbInternAtom(NULL,"white",False); 3236 if (info.labelColor==None) 3237 info.labelColor= XkbInternAtom(NULL,"black",False); 3238 geom->base_color= 3239 XkbAddGeomColor(geom,XkbAtomGetString(NULL,info.baseColor),geom->num_colors); 3240 geom->label_color= 3241 XkbAddGeomColor(geom,XkbAtomGetString(NULL,info.labelColor),geom->num_colors); 3242 3243 if (info.props) { 3244 PropertyInfo *pi; 3245 for (pi= info.props;pi!=NULL;pi=(PropertyInfo *)pi->defs.next) { 3246 if (!XkbAddGeomProperty(geom,pi->name,pi->value)) 3247 return False; 3248 } 3249 } 3250 if (info.shapes) { 3251 ShapeInfo *si; 3252 for (si= info.shapes;si!=NULL;si=(ShapeInfo *)si->defs.next) { 3253 if (!CopyShapeDef(xkb->dpy,geom,si)) 3254 return False; 3255 } 3256 } 3257 if (info.sections) { 3258 SectionInfo *si; 3259 for (si= info.sections;si!=NULL;si=(SectionInfo *)si->defs.next) { 3260 if (!CopySectionDef(geom,si,&info)) 3261 return False; 3262 } 3263 } 3264 if (info.doodads) { 3265 DoodadInfo *di; 3266 for (di= info.doodads;di!=NULL;di=(DoodadInfo *)di->defs.next) { 3267 if (!CopyDoodadDef(geom,NULL,di,&info)) 3268 return False; 3269 } 3270 } 3271 if (info.aliases) 3272 ApplyAliases(xkb,True,&info.aliases); 3273 ClearGeometryInfo(&info); 3274 return True; 3275 } 3276 return False; 3277} 3278