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