geometry.c revision 1d8c7986
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 183 184#define _GS_Default (1<<0) 185#define _GS_Name (1<<1) 186#define _GS_Top (1<<2) 187#define _GS_Left (1<<3) 188#define _GS_Width (1<<4) 189#define _GS_Height (1<<5) 190#define _GS_Angle (1<<6) 191#define _GS_Priority (1<<7) 192typedef struct _SectionInfo 193{ 194 CommonInfo defs; 195 Atom name; 196 unsigned short top; 197 unsigned short left; 198 unsigned short width; 199 unsigned short height; 200 unsigned short angle; 201 unsigned short nRows; 202 unsigned short nDoodads; 203 unsigned short nOverlays; 204 unsigned char priority; 205 unsigned char nextDoodadPriority; 206 RowInfo *rows; 207 DoodadInfo *doodads; 208 RowInfo dfltRow; 209 DoodadInfo *dfltDoodads; 210 OverlayInfo *overlays; 211 struct _GeometryInfo *geometry; 212} SectionInfo; 213#define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default") 214 215typedef struct _GeometryInfo 216{ 217 char *name; 218 Display *dpy; 219 unsigned fileID; 220 unsigned merge; 221 int errorCount; 222 unsigned nextPriority; 223 int nProps; 224 int nShapes; 225 int nSections; 226 int nDoodads; 227 PropertyInfo *props; 228 ShapeInfo *shapes; 229 SectionInfo *sections; 230 DoodadInfo *doodads; 231 int widthMM; 232 int heightMM; 233 Atom font; 234 Atom fontSlant; 235 Atom fontWeight; 236 Atom fontSetWidth; 237 Atom fontVariant; 238 unsigned fontSize; 239 Atom fontEncoding; 240 Atom fontSpec; 241 Atom baseColor; 242 Atom labelColor; 243 int dfltCornerRadius; 244 SectionInfo dfltSection; 245 DoodadInfo *dfltDoodads; 246 AliasInfo *aliases; 247} GeometryInfo; 248 249static char * 250ddText(Display * dpy, DoodadInfo * di) 251{ 252 static char buf[64]; 253 254 if (di == NULL) 255 { 256 strcpy(buf, "default"); 257 return buf; 258 } 259 if (di->section) 260 { 261 sprintf(buf, "%s in section %s", 262 XkbAtomText(dpy, di->name, XkbMessage), scText(dpy, 263 di->section)); 264 return buf; 265 } 266 return XkbAtomText(dpy, di->name, XkbMessage); 267} 268 269/***====================================================================***/ 270 271static void 272InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info) 273{ 274 pi->defs.defined = 0; 275 pi->defs.fileID = info->fileID; 276 pi->defs.merge = info->merge; 277 pi->name = pi->value = NULL; 278 return; 279} 280 281static void 282FreeProperties(PropertyInfo * pi, GeometryInfo * info) 283{ 284 PropertyInfo *tmp; 285 PropertyInfo *next; 286 287 if (info->props == pi) 288 { 289 info->props = NULL; 290 info->nProps = 0; 291 } 292 for (tmp = pi; tmp != NULL; tmp = next) 293 { 294 if (tmp->name) 295 uFree(tmp->name); 296 if (tmp->value) 297 uFree(tmp->value); 298 tmp->name = tmp->value = NULL; 299 next = (PropertyInfo *) tmp->defs.next; 300 uFree(tmp); 301 } 302 return; 303} 304 305static void 306InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info) 307{ 308 309 if (key != &row->dfltKey) 310 { 311 *key = row->dfltKey; 312 strcpy(key->name, "unknown"); 313 key->defs.defined &= ~_GK_Default; 314 } 315 else 316 { 317 bzero(key, sizeof(KeyInfo)); 318 strcpy(key->name, "default"); 319 key->defs.defined = _GK_Default; 320 key->defs.fileID = info->fileID; 321 key->defs.merge = info->merge; 322 key->defs.next = NULL; 323 key->row = row; 324 } 325 return; 326} 327 328static void 329ClearKeyInfo(KeyInfo * key) 330{ 331 key->defs.defined &= ~_GK_Default; 332 strcpy(key->name, "default"); 333 key->gap = 0; 334 key->shape = None; 335 key->color = None; 336 return; 337} 338 339static void 340FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info) 341{ 342 KeyInfo *tmp; 343 KeyInfo *next; 344 345 if (row->keys == key) 346 { 347 row->nKeys = 0; 348 row->keys = NULL; 349 } 350 for (tmp = key; tmp != NULL; tmp = next) 351 { 352 ClearKeyInfo(tmp); 353 next = (KeyInfo *) tmp->defs.next; 354 uFree(tmp); 355 } 356 return; 357} 358 359static void 360InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info) 361{ 362 if (row != §ion->dfltRow) 363 { 364 *row = section->dfltRow; 365 row->defs.defined &= ~_GR_Default; 366 } 367 else 368 { 369 bzero(row, sizeof(*row)); 370 row->defs.defined = _GR_Default; 371 row->defs.fileID = info->fileID; 372 row->defs.merge = info->merge; 373 row->defs.next = NULL; 374 row->section = section; 375 row->nKeys = 0; 376 row->keys = NULL; 377 InitKeyInfo(&row->dfltKey, row, info); 378 } 379 return; 380} 381 382static void 383ClearRowInfo(RowInfo * row, GeometryInfo * info) 384{ 385 row->defs.defined &= ~_GR_Default; 386 row->top = row->left = 0; 387 row->vertical = False; 388 row->nKeys = 0; 389 if (row->keys) 390 FreeKeys(row->keys, row, info); 391 ClearKeyInfo(&row->dfltKey); 392 row->dfltKey.defs.defined |= _GK_Default; 393 return; 394} 395 396static void 397FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info) 398{ 399 RowInfo *next; 400 RowInfo *tmp; 401 402 if (row == section->rows) 403 { 404 section->nRows = 0; 405 section->rows = NULL; 406 } 407 for (tmp = row; tmp != NULL; tmp = next) 408 { 409 ClearRowInfo(tmp, info); 410 next = (RowInfo *) tmp->defs.next; 411 uFree(tmp); 412 } 413 return; 414} 415 416static DoodadInfo * 417FindDoodadByType(DoodadInfo * di, unsigned type) 418{ 419 while (di) 420 { 421 if (di->type == type) 422 return di; 423 di = (DoodadInfo *) di->defs.next; 424 } 425 return NULL; 426} 427 428static DoodadInfo * 429FindDoodadByName(DoodadInfo * di, Atom name) 430{ 431 while (di) 432 { 433 if (di->name == name) 434 return di; 435 di = (DoodadInfo *) di->defs.next; 436 } 437 return NULL; 438} 439 440static void 441InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si, 442 GeometryInfo * info) 443{ 444 DoodadInfo *dflt; 445 446 dflt = NULL; 447 if (si && si->dfltDoodads) 448 dflt = FindDoodadByType(si->dfltDoodads, type); 449 if ((dflt == NULL) && (info->dfltDoodads)) 450 dflt = FindDoodadByType(info->dfltDoodads, type); 451 if (dflt != NULL) 452 { 453 *di = *dflt; 454 di->defs.next = NULL; 455 } 456 else 457 { 458 bzero(di, sizeof(DoodadInfo)); 459 di->defs.fileID = info->fileID; 460 di->type = type; 461 } 462 di->section = si; 463 if (si != NULL) 464 { 465 di->priority = si->nextDoodadPriority++; 466#if XkbGeomMaxPriority < 255 467 if (si->nextDoodadPriority > XkbGeomMaxPriority) 468 si->nextDoodadPriority = XkbGeomMaxPriority; 469#endif 470 } 471 else 472 { 473 di->priority = info->nextPriority++; 474 if (info->nextPriority > XkbGeomMaxPriority) 475 info->nextPriority = XkbGeomMaxPriority; 476 } 477 return; 478} 479 480static void 481ClearDoodadInfo(DoodadInfo * di) 482{ 483 CommonInfo defs; 484 485 defs = di->defs; 486 bzero(di, sizeof(DoodadInfo)); 487 di->defs = defs; 488 di->defs.defined = 0; 489 return; 490} 491 492static void 493ClearOverlayInfo(OverlayInfo * ol) 494{ 495 if (ol && ol->keys) 496 { 497 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs); 498 ol->nKeys = 0; 499 } 500 return; 501} 502 503static void 504FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info) 505{ 506 DoodadInfo *tmp; 507 DoodadInfo *next; 508 509 if (si) 510 { 511 if (si->doodads == di) 512 { 513 si->doodads = NULL; 514 si->nDoodads = 0; 515 } 516 if (si->dfltDoodads == di) 517 si->dfltDoodads = NULL; 518 } 519 if (info->doodads == di) 520 { 521 info->doodads = NULL; 522 info->nDoodads = 0; 523 } 524 if (info->dfltDoodads == di) 525 info->dfltDoodads = NULL; 526 for (tmp = di; tmp != NULL; tmp = next) 527 { 528 next = (DoodadInfo *) tmp->defs.next; 529 ClearDoodadInfo(tmp); 530 uFree(tmp); 531 } 532 return; 533} 534 535static void 536InitSectionInfo(SectionInfo * si, GeometryInfo * info) 537{ 538 if (si != &info->dfltSection) 539 { 540 *si = info->dfltSection; 541 si->defs.defined &= ~_GS_Default; 542 si->name = XkbInternAtom(info->dpy, "unknown", False); 543 si->priority = info->nextPriority++; 544 if (info->nextPriority > XkbGeomMaxPriority) 545 info->nextPriority = XkbGeomMaxPriority; 546 } 547 else 548 { 549 bzero(si, sizeof(SectionInfo)); 550 si->defs.fileID = info->fileID; 551 si->defs.merge = info->merge; 552 si->defs.next = NULL; 553 si->geometry = info; 554 si->name = XkbInternAtom(info->dpy, "default", False); 555 InitRowInfo(&si->dfltRow, si, info); 556 } 557 return; 558} 559 560static void 561DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info) 562{ 563 CommonInfo defs; 564 565 defs = into->defs; 566 *into = *from; 567 into->defs.fileID = defs.fileID; 568 into->defs.merge = defs.merge; 569 into->defs.next = NULL; 570 into->dfltRow.defs.fileID = defs.fileID; 571 into->dfltRow.defs.merge = defs.merge; 572 into->dfltRow.defs.next = NULL; 573 into->dfltRow.section = into; 574 into->dfltRow.dfltKey.defs.fileID = defs.fileID; 575 into->dfltRow.dfltKey.defs.merge = defs.merge; 576 into->dfltRow.dfltKey.defs.next = NULL; 577 into->dfltRow.dfltKey.row = &into->dfltRow; 578 return; 579} 580 581static void 582ClearSectionInfo(SectionInfo * si, GeometryInfo * info) 583{ 584 585 si->defs.defined &= ~_GS_Default; 586 si->name = XkbInternAtom(info->dpy, "default", False); 587 si->top = si->left = 0; 588 si->width = si->height = 0; 589 si->angle = 0; 590 if (si->rows) 591 { 592 FreeRows(si->rows, si, info); 593 si->rows = NULL; 594 } 595 ClearRowInfo(&si->dfltRow, info); 596 if (si->doodads) 597 { 598 FreeDoodads(si->doodads, si, info); 599 si->doodads = NULL; 600 } 601 si->dfltRow.defs.defined = _GR_Default; 602 return; 603} 604 605static void 606FreeSections(SectionInfo * si, GeometryInfo * info) 607{ 608 SectionInfo *tmp; 609 SectionInfo *next; 610 611 if (si == info->sections) 612 { 613 info->nSections = 0; 614 info->sections = NULL; 615 } 616 for (tmp = si; tmp != NULL; tmp = next) 617 { 618 ClearSectionInfo(tmp, info); 619 next = (SectionInfo *) tmp->defs.next; 620 uFree(tmp); 621 } 622 return; 623} 624 625static void 626FreeShapes(ShapeInfo * si, GeometryInfo * info) 627{ 628 ShapeInfo *tmp; 629 ShapeInfo *next; 630 631 if (si == info->shapes) 632 { 633 info->nShapes = 0; 634 info->shapes = NULL; 635 } 636 for (tmp = si; tmp != NULL; tmp = next) 637 { 638 if (tmp->outlines) 639 { 640 register int i; 641 for (i = 0; i < tmp->nOutlines; i++) 642 { 643 if (tmp->outlines[i].points != NULL) 644 { 645 uFree(tmp->outlines[i].points); 646 tmp->outlines[i].num_points = 0; 647 tmp->outlines[i].points = NULL; 648 } 649 } 650 uFree(tmp->outlines); 651 tmp->szOutlines = 0; 652 tmp->nOutlines = 0; 653 tmp->outlines = NULL; 654 tmp->primary = tmp->approx = NULL; 655 } 656 next = (ShapeInfo *) tmp->defs.next; 657 uFree(tmp); 658 } 659 return; 660} 661 662/***====================================================================***/ 663 664static void 665InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge) 666{ 667 bzero(info, sizeof(GeometryInfo)); 668 info->fileID = fileID; 669 info->merge = merge; 670 InitSectionInfo(&info->dfltSection, info); 671 info->dfltSection.defs.defined = _GS_Default; 672 return; 673} 674 675static void 676ClearGeometryInfo(GeometryInfo * info) 677{ 678 if (info->name) 679 uFree(info->name); 680 info->name = NULL; 681 if (info->props) 682 FreeProperties(info->props, info); 683 if (info->shapes) 684 FreeShapes(info->shapes, info); 685 if (info->sections) 686 FreeSections(info->sections, info); 687 info->widthMM = 0; 688 info->heightMM = 0; 689 info->dfltCornerRadius = 0; 690 ClearSectionInfo(&info->dfltSection, info); 691 info->dfltSection.defs.defined = _GS_Default; 692 if (info->aliases) 693 ClearAliases(&info->aliases); 694 return; 695} 696 697/***====================================================================***/ 698 699static PropertyInfo * 700NextProperty(GeometryInfo * info) 701{ 702 PropertyInfo *pi; 703 704 pi = uTypedAlloc(PropertyInfo); 705 if (pi) 706 { 707 bzero((char *) pi, sizeof(PropertyInfo)); 708 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs, 709 (CommonInfo *) pi); 710 info->nProps++; 711 } 712 return pi; 713} 714 715static PropertyInfo * 716FindProperty(GeometryInfo * info, char *name) 717{ 718 PropertyInfo *old; 719 720 if (!name) 721 return NULL; 722 for (old = info->props; old != NULL; 723 old = (PropertyInfo *) old->defs.next) 724 { 725 if ((old->name) && (uStringEqual(name, old->name))) 726 return old; 727 } 728 return NULL; 729} 730 731static Bool 732AddProperty(GeometryInfo * info, PropertyInfo * new) 733{ 734 PropertyInfo *old; 735 736 if ((!new) || (!new->value) || (!new->name)) 737 return False; 738 old = FindProperty(info, new->name); 739 if (old != NULL) 740 { 741 if ((new->defs.merge == MergeReplace) 742 || (new->defs.merge == MergeOverride)) 743 { 744 if (((old->defs.fileID == new->defs.fileID) 745 && (warningLevel > 0)) || (warningLevel > 9)) 746 { 747 WARN1("Multiple definitions for the \"%s\" property\n", 748 new->name); 749 ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value, 750 new->value); 751 } 752 if (old->value) 753 uFree(old->value); 754 old->value = uStringDup(new->value); 755 return True; 756 } 757 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 758 || (warningLevel > 9)) 759 { 760 WARN1("Multiple definitions for \"%s\" property\n", new->name); 761 ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value, 762 new->value); 763 } 764 return True; 765 } 766 old = new; 767 if ((new = NextProperty(info)) == NULL) 768 return False; 769 new->defs.next = NULL; 770 new->name = uStringDup(old->name); 771 new->value = uStringDup(old->value); 772 return True; 773} 774 775/***====================================================================***/ 776 777static ShapeInfo * 778NextShape(GeometryInfo * info) 779{ 780 ShapeInfo *si; 781 782 si = uTypedAlloc(ShapeInfo); 783 if (si) 784 { 785 bzero((char *) si, sizeof(ShapeInfo)); 786 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs, 787 (CommonInfo *) si); 788 info->nShapes++; 789 si->dfltCornerRadius = info->dfltCornerRadius; 790 } 791 return si; 792} 793 794static ShapeInfo * 795FindShape(GeometryInfo * info, Atom name, const char *type, const char *which) 796{ 797 ShapeInfo *old; 798 799 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next) 800 { 801 if (name == old->name) 802 return old; 803 } 804 if (type != NULL) 805 { 806 old = info->shapes; 807 WARN3("Unknown shape \"%s\" for %s %s\n", 808 XkbAtomText(info->dpy, name, XkbMessage), type, which); 809 if (old) 810 { 811 ACTION1("Using default shape %s instead\n", 812 shText(info->dpy, old)); 813 return old; 814 } 815 ACTION("No default shape; definition ignored\n"); 816 return NULL; 817 } 818 return NULL; 819} 820 821static Bool 822AddShape(GeometryInfo * info, ShapeInfo * new) 823{ 824 ShapeInfo *old; 825 826 old = FindShape(info, new->name, NULL, NULL); 827 if (old != NULL) 828 { 829 if ((new->defs.merge == MergeReplace) 830 || (new->defs.merge == MergeOverride)) 831 { 832 ShapeInfo *next = (ShapeInfo *) old->defs.next; 833 if (((old->defs.fileID == new->defs.fileID) 834 && (warningLevel > 0)) || (warningLevel > 9)) 835 { 836 WARN1("Duplicate shape name \"%s\"\n", 837 shText(info->dpy, old)); 838 ACTION("Using last definition\n"); 839 } 840 *old = *new; 841 old->defs.next = &next->defs; 842 return True; 843 } 844 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 845 || (warningLevel > 9)) 846 { 847 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old)); 848 ACTION("Using first definition\n"); 849 } 850 return True; 851 } 852 old = new; 853 if ((new = NextShape(info)) == NULL) 854 return False; 855 *new = *old; 856 new->defs.next = NULL; 857 old->szOutlines = old->nOutlines = 0; 858 old->outlines = NULL; 859 old->approx = NULL; 860 old->primary = NULL; 861 return True; 862} 863 864/***====================================================================***/ 865 866static void 867ReplaceDoodad(DoodadInfo * into, DoodadInfo * from) 868{ 869 CommonInfo *next; 870 871 next = into->defs.next; 872 ClearDoodadInfo(into); 873 *into = *from; 874 into->defs.next = next; 875 next = from->defs.next; 876 ClearDoodadInfo(from); 877 from->defs.next = next; 878 return; 879} 880 881static DoodadInfo * 882NextDfltDoodad(SectionInfo * si, GeometryInfo * info) 883{ 884 DoodadInfo *di; 885 886 di = uTypedCalloc(1, DoodadInfo); 887 if (!di) 888 return NULL; 889 if (si) 890 { 891 si->dfltDoodads = 892 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs, 893 (CommonInfo *) di); 894 } 895 else 896 { 897 info->dfltDoodads = 898 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs, 899 (CommonInfo *) di); 900 } 901 return di; 902} 903 904static DoodadInfo * 905NextDoodad(SectionInfo * si, GeometryInfo * info) 906{ 907 DoodadInfo *di; 908 909 di = uTypedCalloc(1, DoodadInfo); 910 if (di) 911 { 912 if (si) 913 { 914 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs, 915 (CommonInfo *) di); 916 si->nDoodads++; 917 } 918 else 919 { 920 info->doodads = 921 (DoodadInfo *) AddCommonInfo(&info->doodads->defs, 922 (CommonInfo *) di); 923 info->nDoodads++; 924 } 925 } 926 return di; 927} 928 929static Bool 930AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new) 931{ 932 DoodadInfo *old; 933 934 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name); 935 if (old != NULL) 936 { 937 if ((new->defs.merge == MergeReplace) 938 || (new->defs.merge == MergeOverride)) 939 { 940 if (((old->defs.fileID == new->defs.fileID) 941 && (warningLevel > 0)) || (warningLevel > 9)) 942 { 943 WARN1("Multiple doodads named \"%s\"\n", 944 XkbAtomText(info->dpy, old->name, XkbMessage)); 945 ACTION("Using last definition\n"); 946 } 947 ReplaceDoodad(old, new); 948 old->section = si; 949 return True; 950 } 951 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 952 || (warningLevel > 9)) 953 { 954 WARN1("Multiple doodads named \"%s\"\n", 955 XkbAtomText(info->dpy, old->name, XkbMessage)); 956 ACTION("Using first definition\n"); 957 } 958 return True; 959 } 960 old = new; 961 if ((new = NextDoodad(si, info)) == NULL) 962 return False; 963 ReplaceDoodad(new, old); 964 new->section = si; 965 new->defs.next = NULL; 966 return True; 967} 968 969static DoodadInfo * 970FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info) 971{ 972 DoodadInfo *dflt; 973 unsigned type; 974 975 if (uStrCaseCmp(name, "outline") == 0) 976 type = XkbOutlineDoodad; 977 else if (uStrCaseCmp(name, "solid") == 0) 978 type = XkbSolidDoodad; 979 else if (uStrCaseCmp(name, "text") == 0) 980 type = XkbTextDoodad; 981 else if (uStrCaseCmp(name, "indicator") == 0) 982 type = XkbIndicatorDoodad; 983 else if (uStrCaseCmp(name, "logo") == 0) 984 type = XkbLogoDoodad; 985 else 986 return NULL; 987 if ((si) && (si->dfltDoodads)) 988 dflt = FindDoodadByType(si->dfltDoodads, type); 989 else 990 dflt = NULL; 991 if ((!dflt) && (info->dfltDoodads)) 992 dflt = FindDoodadByType(info->dfltDoodads, type); 993 if (dflt == NULL) 994 { 995 dflt = NextDfltDoodad(si, info); 996 if (dflt != NULL) 997 { 998 dflt->name = None; 999 dflt->type = type; 1000 } 1001 } 1002 return dflt; 1003} 1004 1005/***====================================================================***/ 1006 1007static Bool 1008AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new) 1009{ 1010 OverlayInfo *old; 1011 1012 for (old = si->overlays; old != NULL; 1013 old = (OverlayInfo *) old->defs.next) 1014 { 1015 if (old->name == new->name) 1016 break; 1017 } 1018 if (old != NULL) 1019 { 1020 if ((new->defs.merge == MergeReplace) 1021 || (new->defs.merge == MergeOverride)) 1022 { 1023 if (((old->defs.fileID == new->defs.fileID) 1024 && (warningLevel > 0)) || (warningLevel > 9)) 1025 { 1026 WARN2 1027 ("Multiple overlays named \"%s\" for section \"%s\"\n", 1028 XkbAtomText(info->dpy, old->name, XkbMessage), 1029 XkbAtomText(info->dpy, si->name, XkbMessage)); 1030 ACTION("Using last definition\n"); 1031 } 1032 ClearOverlayInfo(old); 1033 old->nKeys = new->nKeys; 1034 old->keys = new->keys; 1035 new->nKeys = 0; 1036 new->keys = NULL; 1037 return True; 1038 } 1039 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 1040 || (warningLevel > 9)) 1041 { 1042 WARN2("Multiple doodads named \"%s\" in section \"%s\"\n", 1043 XkbAtomText(info->dpy, old->name, XkbMessage), 1044 XkbAtomText(info->dpy, si->name, XkbMessage)); 1045 ACTION("Using first definition\n"); 1046 } 1047 return True; 1048 } 1049 old = new; 1050 new = uTypedCalloc(1, OverlayInfo); 1051 if (!new) 1052 { 1053 if (warningLevel > 0) 1054 { 1055 WSGO("Couldn't allocate a new OverlayInfo\n"); 1056 ACTION2 1057 ("Overlay \"%s\" in section \"%s\" will be incomplete\n", 1058 XkbAtomText(info->dpy, old->name, XkbMessage), 1059 XkbAtomText(info->dpy, si->name, XkbMessage)); 1060 } 1061 return False; 1062 } 1063 *new = *old; 1064 old->nKeys = 0; 1065 old->keys = NULL; 1066 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs, 1067 (CommonInfo *) new); 1068 si->nOverlays++; 1069 return True; 1070} 1071 1072/***====================================================================***/ 1073 1074static SectionInfo * 1075NextSection(GeometryInfo * info) 1076{ 1077 SectionInfo *si; 1078 1079 si = uTypedAlloc(SectionInfo); 1080 if (si) 1081 { 1082 *si = info->dfltSection; 1083 si->defs.defined &= ~_GS_Default; 1084 si->defs.next = NULL; 1085 si->nRows = 0; 1086 si->rows = NULL; 1087 info->sections = 1088 (SectionInfo *) AddCommonInfo(&info->sections->defs, 1089 (CommonInfo *) si); 1090 info->nSections++; 1091 } 1092 return si; 1093} 1094 1095static SectionInfo * 1096FindMatchingSection(GeometryInfo * info, SectionInfo * new) 1097{ 1098 SectionInfo *old; 1099 1100 for (old = info->sections; old != NULL; 1101 old = (SectionInfo *) old->defs.next) 1102 { 1103 if (new->name == old->name) 1104 return old; 1105 } 1106 return NULL; 1107} 1108 1109static Bool 1110AddSection(GeometryInfo * info, SectionInfo * new) 1111{ 1112 SectionInfo *old; 1113 1114 old = FindMatchingSection(info, new); 1115 if (old != NULL) 1116 { 1117#ifdef NOTDEF 1118 if ((new->defs.merge == MergeReplace) 1119 || (new->defs.merge == MergeOverride)) 1120 { 1121 SectionInfo *next = (SectionInfo *) old->defs.next; 1122 if (((old->defs.fileID == new->defs.fileID) 1123 && (warningLevel > 0)) || (warningLevel > 9)) 1124 { 1125 WARN1("Duplicate shape name \"%s\"\n", 1126 shText(info->dpy, old)); 1127 ACTION("Using last definition\n"); 1128 } 1129 *old = *new; 1130 old->defs.next = &next->defs; 1131 return True; 1132 } 1133 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) 1134 || (warningLevel > 9)) 1135 { 1136 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old)); 1137 ACTION("Using first definition\n"); 1138 } 1139 return True; 1140#else 1141 WARN("Don't know how to merge sections yet\n"); 1142#endif 1143 } 1144 old = new; 1145 if ((new = NextSection(info)) == NULL) 1146 return False; 1147 *new = *old; 1148 new->defs.next = NULL; 1149 old->nRows = old->nDoodads = old->nOverlays = 0; 1150 old->rows = NULL; 1151 old->doodads = NULL; 1152 old->overlays = NULL; 1153 if (new->doodads) 1154 { 1155 DoodadInfo *di; 1156 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next) 1157 { 1158 di->section = new; 1159 } 1160 } 1161 return True; 1162} 1163 1164/***====================================================================***/ 1165 1166static RowInfo * 1167NextRow(SectionInfo * si) 1168{ 1169 RowInfo *row; 1170 1171 row = uTypedAlloc(RowInfo); 1172 if (row) 1173 { 1174 *row = si->dfltRow; 1175 row->defs.defined &= ~_GR_Default; 1176 row->defs.next = NULL; 1177 row->nKeys = 0; 1178 row->keys = NULL; 1179 si->rows = 1180 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row); 1181 row->index = si->nRows++; 1182 } 1183 return row; 1184} 1185 1186static Bool 1187AddRow(SectionInfo * si, RowInfo * new) 1188{ 1189 RowInfo *old; 1190 1191 old = new; 1192 if ((new = NextRow(si)) == NULL) 1193 return False; 1194 *new = *old; 1195 new->defs.next = NULL; 1196 old->nKeys = 0; 1197 old->keys = NULL; 1198 return True; 1199} 1200 1201/***====================================================================***/ 1202 1203static KeyInfo * 1204NextKey(RowInfo * row) 1205{ 1206 KeyInfo *key; 1207 1208 key = uTypedAlloc(KeyInfo); 1209 if (key) 1210 { 1211 *key = row->dfltKey; 1212 key->defs.defined &= ~_GK_Default; 1213 key->defs.next = NULL; 1214 key->index = row->nKeys++; 1215 } 1216 return key; 1217} 1218 1219static Bool 1220AddKey(RowInfo * row, KeyInfo * new) 1221{ 1222 KeyInfo *old; 1223 1224 old = new; 1225 if ((new = NextKey(row)) == NULL) 1226 return False; 1227 *new = *old; 1228 new->defs.next = NULL; 1229 row->keys = 1230 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new); 1231 return True; 1232} 1233 1234/***====================================================================***/ 1235 1236static void 1237MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from, 1238 unsigned merge) 1239{ 1240 Bool clobber; 1241 1242 if (from->errorCount > 0) 1243 { 1244 into->errorCount += from->errorCount; 1245 return; 1246 } 1247 clobber = (merge == MergeOverride) || (merge == MergeReplace); 1248 if (into->name == NULL) 1249 { 1250 into->name = from->name; 1251 from->name = NULL; 1252 } 1253 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber)) 1254 into->widthMM = from->widthMM; 1255 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber)) 1256 into->heightMM = from->heightMM; 1257 if ((into->font == None) || ((from->font != None) && clobber)) 1258 into->font = from->font; 1259 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber)) 1260 into->fontSlant = from->fontSlant; 1261 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber)) 1262 into->fontWeight = from->fontWeight; 1263 if ((into->fontSetWidth == None) 1264 || ((from->fontSetWidth != None) && clobber)) 1265 into->fontSetWidth = from->fontSetWidth; 1266 if ((into->fontVariant == None) 1267 || ((from->fontVariant != None) && clobber)) 1268 into->fontVariant = from->fontVariant; 1269 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber)) 1270 into->fontSize = from->fontSize; 1271 if ((into->fontEncoding == None) 1272 || ((from->fontEncoding != None) && clobber)) 1273 into->fontEncoding = from->fontEncoding; 1274 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber)) 1275 into->fontSpec = from->fontSpec; 1276 if ((into->baseColor == None) || ((from->baseColor != None) && clobber)) 1277 into->baseColor = from->baseColor; 1278 if ((into->labelColor == None) || ((from->labelColor != None) && clobber)) 1279 into->labelColor = from->labelColor; 1280 into->nextPriority = from->nextPriority; 1281 if (from->props != NULL) 1282 { 1283 PropertyInfo *pi; 1284 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next) 1285 { 1286 if (!AddProperty(into, pi)) 1287 into->errorCount++; 1288 } 1289 } 1290 if (from->shapes != NULL) 1291 { 1292 ShapeInfo *si; 1293 1294 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next) 1295 { 1296 if (!AddShape(into, si)) 1297 into->errorCount++; 1298 } 1299 } 1300 if (from->sections != NULL) 1301 { 1302 SectionInfo *si; 1303 1304 for (si = from->sections; si; si = (SectionInfo *) si->defs.next) 1305 { 1306 if (!AddSection(into, si)) 1307 into->errorCount++; 1308 } 1309 } 1310 if (from->doodads != NULL) 1311 { 1312 DoodadInfo *di; 1313 1314 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next) 1315 { 1316 if (!AddDoodad(NULL, into, di)) 1317 into->errorCount++; 1318 } 1319 } 1320 if (!MergeAliases(&into->aliases, &from->aliases, merge)) 1321 into->errorCount++; 1322 return; 1323} 1324 1325typedef void (*FileHandler) (XkbFile * /* file */ , 1326 XkbDescPtr /* xkb */ , 1327 unsigned /* merge */ , 1328 GeometryInfo * /* info */ 1329 ); 1330 1331static Bool 1332HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info, 1333 FileHandler hndlr) 1334{ 1335 unsigned newMerge; 1336 XkbFile *rtrn; 1337 GeometryInfo included; 1338 Bool haveSelf; 1339 1340 haveSelf = False; 1341 if ((stmt->file == NULL) && (stmt->map == NULL)) 1342 { 1343 haveSelf = True; 1344 included = *info; 1345 bzero(info, sizeof(GeometryInfo)); 1346 } 1347 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge)) 1348 { 1349 InitGeometryInfo(&included, rtrn->id, newMerge); 1350 included.nextPriority = info->nextPriority; 1351 included.dfltCornerRadius = info->dfltCornerRadius; 1352 DupSectionInfo(&included.dfltSection, &info->dfltSection, info); 1353 (*hndlr) (rtrn, xkb, MergeOverride, &included); 1354 if (stmt->stmt != NULL) 1355 { 1356 if (included.name != NULL) 1357 uFree(included.name); 1358 included.name = stmt->stmt; 1359 stmt->stmt = NULL; 1360 } 1361 } 1362 else 1363 { 1364 info->errorCount += 10; 1365 return False; 1366 } 1367 if ((stmt->next != NULL) && (included.errorCount < 1)) 1368 { 1369 IncludeStmt *next; 1370 unsigned op; 1371 GeometryInfo next_incl; 1372 1373 for (next = stmt->next; next != NULL; next = next->next) 1374 { 1375 if ((next->file == NULL) && (next->map == NULL)) 1376 { 1377 haveSelf = True; 1378 MergeIncludedGeometry(&included, info, next->merge); 1379 ClearGeometryInfo(info); 1380 } 1381 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op)) 1382 { 1383 InitGeometryInfo(&next_incl, rtrn->id, op); 1384 next_incl.nextPriority = included.nextPriority; 1385 next_incl.dfltCornerRadius = included.dfltCornerRadius; 1386 DupSectionInfo(&next_incl.dfltSection, 1387 &included.dfltSection, &included); 1388 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); 1389 MergeIncludedGeometry(&included, &next_incl, op); 1390 ClearGeometryInfo(&next_incl); 1391 } 1392 else 1393 { 1394 info->errorCount += 10; 1395 return False; 1396 } 1397 } 1398 } 1399 if (haveSelf) 1400 *info = included; 1401 else 1402 { 1403 MergeIncludedGeometry(info, &included, newMerge); 1404 ClearGeometryInfo(&included); 1405 } 1406 return (info->errorCount == 0); 1407} 1408 1409static int 1410SetShapeField(ShapeInfo * si, 1411 char *field, 1412 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) 1413{ 1414 ExprResult tmp; 1415 1416 if ((uStrCaseCmp(field, "radius") == 0) 1417 || (uStrCaseCmp(field, "corner") == 0) 1418 || (uStrCaseCmp(field, "cornerradius") == 0)) 1419 { 1420 if (arrayNdx != NULL) 1421 { 1422 info->errorCount++; 1423 return ReportNotArray("key shape", field, shText(info->dpy, si)); 1424 } 1425 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1426 { 1427 info->errorCount++; 1428 return ReportBadType("key shape", field, 1429 shText(info->dpy, si), "number"); 1430 } 1431 if (si) 1432 si->dfltCornerRadius = tmp.ival; 1433 else 1434 info->dfltCornerRadius = tmp.ival; 1435 return True; 1436 } 1437 info->errorCount++; 1438 return ReportBadField("key shape", field, shText(info->dpy, si)); 1439} 1440 1441static int 1442SetShapeDoodadField(DoodadInfo * di, 1443 char *field, 1444 ExprDef * arrayNdx, 1445 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1446{ 1447 ExprResult tmp; 1448 const char *typeName; 1449 1450 typeName = 1451 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad"); 1452 if ((!uStrCaseCmp(field, "corner")) 1453 || (!uStrCaseCmp(field, "cornerradius"))) 1454 { 1455 if (arrayNdx != NULL) 1456 { 1457 info->errorCount++; 1458 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1459 } 1460 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1461 { 1462 info->errorCount++; 1463 return ReportBadType(typeName, field, ddText(info->dpy, di), 1464 "number"); 1465 } 1466 di->defs.defined |= _GD_Corner; 1467 di->corner = tmp.ival; 1468 return True; 1469 } 1470 else if (uStrCaseCmp(field, "angle") == 0) 1471 { 1472 if (arrayNdx != NULL) 1473 { 1474 info->errorCount++; 1475 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1476 } 1477 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1478 { 1479 info->errorCount++; 1480 return ReportBadType(typeName, field, ddText(info->dpy, di), 1481 "number"); 1482 } 1483 di->defs.defined |= _GD_Angle; 1484 di->angle = tmp.ival; 1485 return True; 1486 } 1487 else if (uStrCaseCmp(field, "shape") == 0) 1488 { 1489 if (arrayNdx != NULL) 1490 { 1491 info->errorCount++; 1492 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1493 } 1494 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1495 { 1496 info->errorCount++; 1497 return ReportBadType(typeName, field, ddText(info->dpy, di), 1498 "string"); 1499 } 1500 di->shape = XkbInternAtom(info->dpy, tmp.str, False); 1501 di->defs.defined |= _GD_Shape; 1502 return True; 1503 } 1504 return ReportBadField(typeName, field, ddText(info->dpy, di)); 1505} 1506 1507#define FIELD_STRING 0 1508#define FIELD_SHORT 1 1509#define FIELD_USHORT 2 1510 1511static int 1512SetTextDoodadField(DoodadInfo * di, 1513 char *field, 1514 ExprDef * arrayNdx, 1515 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1516{ 1517 ExprResult tmp; 1518 unsigned def; 1519 unsigned type; 1520 char *typeName = "text doodad"; 1521 union 1522 { 1523 Atom *str; 1524 short *ival; 1525 unsigned short *uval; 1526 } pField; 1527 1528 if (uStrCaseCmp(field, "angle") == 0) 1529 { 1530 if (arrayNdx != NULL) 1531 { 1532 info->errorCount++; 1533 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1534 } 1535 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1536 { 1537 info->errorCount++; 1538 return ReportBadType(typeName, field, ddText(info->dpy, di), 1539 "number"); 1540 } 1541 di->defs.defined |= _GD_Angle; 1542 di->angle = tmp.ival; 1543 return True; 1544 } 1545 if (uStrCaseCmp(field, "width") == 0) 1546 { 1547 type = FIELD_USHORT; 1548 pField.uval = &di->width; 1549 def = _GD_Width; 1550 } 1551 else if (uStrCaseCmp(field, "height") == 0) 1552 { 1553 type = FIELD_USHORT; 1554 pField.uval = &di->height; 1555 def = _GD_Height; 1556 } 1557 else if (uStrCaseCmp(field, "text") == 0) 1558 { 1559 type = FIELD_STRING; 1560 pField.str = &di->text; 1561 def = _GD_Text; 1562 } 1563 else if (uStrCaseCmp(field, "font") == 0) 1564 { 1565 type = FIELD_STRING; 1566 pField.str = &di->font; 1567 def = _GD_Font; 1568 } 1569 else if ((uStrCaseCmp(field, "fontslant") == 0) || 1570 (uStrCaseCmp(field, "slant") == 0)) 1571 { 1572 type = FIELD_STRING; 1573 pField.str = &di->fontSlant; 1574 def = _GD_FontSlant; 1575 } 1576 else if ((uStrCaseCmp(field, "fontweight") == 0) || 1577 (uStrCaseCmp(field, "weight") == 0)) 1578 { 1579 type = FIELD_STRING; 1580 pField.str = &di->fontWeight; 1581 def = _GD_FontWeight; 1582 } 1583 else if ((uStrCaseCmp(field, "fontwidth") == 0) || 1584 (uStrCaseCmp(field, "setwidth") == 0)) 1585 { 1586 type = FIELD_STRING; 1587 pField.str = &di->fontSetWidth; 1588 def = _GD_FontSetWidth; 1589 } 1590 else if ((uStrCaseCmp(field, "fontvariant") == 0) || 1591 (uStrCaseCmp(field, "variant") == 0)) 1592 { 1593 type = FIELD_STRING; 1594 pField.str = &di->fontVariant; 1595 def = _GD_FontVariant; 1596 } 1597 else if ((uStrCaseCmp(field, "fontencoding") == 0) || 1598 (uStrCaseCmp(field, "encoding") == 0)) 1599 { 1600 type = FIELD_STRING; 1601 pField.str = &di->fontEncoding; 1602 def = _GD_FontEncoding; 1603 } 1604 else if ((uStrCaseCmp(field, "xfont") == 0) || 1605 (uStrCaseCmp(field, "xfontname") == 0)) 1606 { 1607 type = FIELD_STRING; 1608 pField.str = &di->fontSpec; 1609 def = _GD_FontSpec; 1610 } 1611 else if (uStrCaseCmp(field, "fontsize") == 0) 1612 { 1613 type = FIELD_USHORT; 1614 pField.uval = &di->fontSize; 1615 def = _GD_FontSize; 1616 } 1617 else 1618 { 1619 return ReportBadField(typeName, field, ddText(info->dpy, di)); 1620 } 1621 if (arrayNdx != NULL) 1622 { 1623 info->errorCount++; 1624 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1625 } 1626 if (type == FIELD_STRING) 1627 { 1628 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1629 { 1630 info->errorCount++; 1631 return ReportBadType(typeName, field, ddText(info->dpy, di), 1632 "string"); 1633 } 1634 di->defs.defined |= def; 1635 *pField.str = XkbInternAtom(NULL, tmp.str, False); 1636 } 1637 else 1638 { 1639 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1640 { 1641 info->errorCount++; 1642 return ReportBadType(typeName, field, ddText(info->dpy, di), 1643 "number"); 1644 } 1645 if ((type == FIELD_USHORT) && (tmp.ival < 0)) 1646 { 1647 info->errorCount++; 1648 return 1649 ReportBadType(typeName, field, ddText(info->dpy, di), 1650 "unsigned"); 1651 } 1652 di->defs.defined |= def; 1653 if (type == FIELD_USHORT) 1654 *pField.uval = tmp.uval; 1655 else 1656 *pField.ival = tmp.ival; 1657 } 1658 return True; 1659} 1660 1661static int 1662SetIndicatorDoodadField(DoodadInfo * di, 1663 char *field, 1664 ExprDef * arrayNdx, 1665 ExprDef * value, 1666 SectionInfo * si, GeometryInfo * info) 1667{ 1668 ExprResult tmp; 1669 1670 if ((uStrCaseCmp(field, "oncolor") == 0) 1671 || (uStrCaseCmp(field, "offcolor") == 0) 1672 || (uStrCaseCmp(field, "shape") == 0)) 1673 { 1674 if (arrayNdx != NULL) 1675 { 1676 info->errorCount++; 1677 return ReportNotArray("indicator doodad", field, 1678 ddText(info->dpy, di)); 1679 } 1680 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1681 { 1682 info->errorCount++; 1683 return ReportBadType("indicator doodad", field, 1684 ddText(info->dpy, di), "string"); 1685 } 1686 if (uStrCaseCmp(field, "oncolor") == 0) 1687 { 1688 di->defs.defined |= _GD_Color; 1689 di->color = XkbInternAtom(NULL, tmp.str, False); 1690 } 1691 else if (uStrCaseCmp(field, "offcolor") == 0) 1692 { 1693 di->defs.defined |= _GD_OffColor; 1694 di->offColor = XkbInternAtom(NULL, tmp.str, False); 1695 } 1696 else if (uStrCaseCmp(field, "shape") == 0) 1697 { 1698 di->defs.defined |= _GD_Shape; 1699 di->shape = XkbInternAtom(info->dpy, tmp.str, False); 1700 } 1701 return True; 1702 } 1703 return ReportBadField("indicator doodad", field, ddText(info->dpy, di)); 1704} 1705 1706static int 1707SetLogoDoodadField(DoodadInfo * di, 1708 char *field, 1709 ExprDef * arrayNdx, 1710 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1711{ 1712 ExprResult tmp; 1713 char *typeName = "logo doodad"; 1714 1715 if ((!uStrCaseCmp(field, "corner")) 1716 || (!uStrCaseCmp(field, "cornerradius"))) 1717 { 1718 if (arrayNdx != NULL) 1719 { 1720 info->errorCount++; 1721 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1722 } 1723 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1724 { 1725 info->errorCount++; 1726 return ReportBadType(typeName, field, ddText(info->dpy, di), 1727 "number"); 1728 } 1729 di->defs.defined |= _GD_Corner; 1730 di->corner = tmp.ival; 1731 return True; 1732 } 1733 else if (uStrCaseCmp(field, "angle") == 0) 1734 { 1735 if (arrayNdx != NULL) 1736 { 1737 info->errorCount++; 1738 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1739 } 1740 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1741 { 1742 info->errorCount++; 1743 return ReportBadType(typeName, field, ddText(info->dpy, di), 1744 "number"); 1745 } 1746 di->defs.defined |= _GD_Angle; 1747 di->angle = tmp.ival; 1748 return True; 1749 } 1750 else if (uStrCaseCmp(field, "shape") == 0) 1751 { 1752 if (arrayNdx != NULL) 1753 { 1754 info->errorCount++; 1755 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1756 } 1757 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1758 { 1759 info->errorCount++; 1760 return ReportBadType(typeName, field, ddText(info->dpy, di), 1761 "string"); 1762 } 1763 di->shape = XkbInternAtom(info->dpy, tmp.str, False); 1764 di->defs.defined |= _GD_Shape; 1765 return True; 1766 } 1767 else if ((!uStrCaseCmp(field, "logoname")) 1768 || (!uStrCaseCmp(field, "name"))) 1769 { 1770 if (arrayNdx != NULL) 1771 { 1772 info->errorCount++; 1773 return ReportNotArray(typeName, field, ddText(info->dpy, di)); 1774 } 1775 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1776 { 1777 info->errorCount++; 1778 return ReportBadType(typeName, field, ddText(info->dpy, di), 1779 "string"); 1780 } 1781 di->logoName = uStringDup(tmp.str); 1782 return True; 1783 } 1784 return ReportBadField(typeName, field, ddText(info->dpy, di)); 1785} 1786 1787static int 1788SetDoodadField(DoodadInfo * di, 1789 char *field, 1790 ExprDef * arrayNdx, 1791 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1792{ 1793 ExprResult tmp; 1794 1795 if (uStrCaseCmp(field, "priority") == 0) 1796 { 1797 if (arrayNdx != NULL) 1798 { 1799 info->errorCount++; 1800 return ReportNotArray("doodad", field, ddText(info->dpy, di)); 1801 } 1802 if (!ExprResolveInteger(value, &tmp, NULL, NULL)) 1803 { 1804 info->errorCount++; 1805 return ReportBadType("doodad", field, ddText(info->dpy, di), 1806 "integer"); 1807 } 1808 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority)) 1809 { 1810 info->errorCount++; 1811 ERROR2("Doodad priority %d out of range (must be 0..%d)\n", 1812 tmp.ival, XkbGeomMaxPriority); 1813 ACTION1("Priority for doodad %s not changed", 1814 ddText(info->dpy, di)); 1815 return False; 1816 } 1817 di->defs.defined |= _GD_Priority; 1818 di->priority = tmp.ival; 1819 return True; 1820 } 1821 else if (uStrCaseCmp(field, "left") == 0) 1822 { 1823 if (arrayNdx != NULL) 1824 { 1825 info->errorCount++; 1826 return ReportNotArray("doodad", field, ddText(info->dpy, di)); 1827 } 1828 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1829 { 1830 info->errorCount++; 1831 return ReportBadType("doodad", field, ddText(info->dpy, di), 1832 "number"); 1833 } 1834 di->defs.defined |= _GD_Left; 1835 di->left = tmp.ival; 1836 return True; 1837 } 1838 else if (uStrCaseCmp(field, "top") == 0) 1839 { 1840 if (arrayNdx != NULL) 1841 { 1842 info->errorCount++; 1843 return ReportNotArray("doodad", field, ddText(info->dpy, di)); 1844 } 1845 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1846 { 1847 info->errorCount++; 1848 return ReportBadType("doodad", field, ddText(info->dpy, di), 1849 "number"); 1850 } 1851 di->defs.defined |= _GD_Top; 1852 di->top = tmp.ival; 1853 return True; 1854 } 1855 else if (uStrCaseCmp(field, "color") == 0) 1856 { 1857 if (arrayNdx != NULL) 1858 { 1859 info->errorCount++; 1860 return ReportNotArray("doodad", field, ddText(info->dpy, di)); 1861 } 1862 if (!ExprResolveString(value, &tmp, NULL, NULL)) 1863 { 1864 info->errorCount++; 1865 return ReportBadType("doodad", field, ddText(info->dpy, di), 1866 "string"); 1867 } 1868 di->defs.defined |= _GD_Color; 1869 di->color = XkbInternAtom(NULL, tmp.str, False); 1870 return True; 1871 } 1872 switch (di->type) 1873 { 1874 case XkbOutlineDoodad: 1875 case XkbSolidDoodad: 1876 return SetShapeDoodadField(di, field, arrayNdx, value, si, info); 1877 case XkbTextDoodad: 1878 return SetTextDoodadField(di, field, arrayNdx, value, si, info); 1879 case XkbIndicatorDoodad: 1880 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info); 1881 case XkbLogoDoodad: 1882 return SetLogoDoodadField(di, field, arrayNdx, value, si, info); 1883 } 1884 WSGO1("Unknown doodad type %d in SetDoodadField\n", 1885 (unsigned int) di->type); 1886 ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di)); 1887 return False; 1888} 1889 1890static int 1891SetSectionField(SectionInfo * si, 1892 char *field, 1893 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) 1894{ 1895 unsigned short *pField; 1896 unsigned def; 1897 ExprResult tmp; 1898 1899 pField = NULL; 1900 def = 0; 1901 if (uStrCaseCmp(field, "priority") == 0) 1902 { 1903 if (arrayNdx != NULL) 1904 { 1905 info->errorCount++; 1906 return ReportNotArray("keyboard section", field, 1907 scText(info->dpy, si)); 1908 } 1909 if (!ExprResolveInteger(value, &tmp, NULL, NULL)) 1910 { 1911 info->errorCount++; 1912 ReportBadType("keyboard section", field, 1913 scText(info->dpy, si), "integer"); 1914 return False; 1915 } 1916 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority)) 1917 { 1918 info->errorCount++; 1919 ERROR2("Section priority %d out of range (must be 0..%d)\n", 1920 tmp.ival, XkbGeomMaxPriority); 1921 ACTION1("Priority for section %s not changed", 1922 scText(info->dpy, si)); 1923 return False; 1924 } 1925 si->priority = tmp.ival; 1926 si->defs.defined |= _GS_Priority; 1927 return True; 1928 } 1929 else if (uStrCaseCmp(field, "top") == 0) 1930 { 1931 pField = &si->top; 1932 def = _GS_Top; 1933 } 1934 else if (uStrCaseCmp(field, "left") == 0) 1935 { 1936 pField = &si->left; 1937 def = _GS_Left; 1938 } 1939 else if (uStrCaseCmp(field, "width") == 0) 1940 { 1941 pField = &si->width; 1942 def = _GS_Width; 1943 } 1944 else if (uStrCaseCmp(field, "height") == 0) 1945 { 1946 pField = &si->height; 1947 def = _GS_Height; 1948 } 1949 else if (uStrCaseCmp(field, "angle") == 0) 1950 { 1951 pField = &si->angle; 1952 def = _GS_Angle; 1953 } 1954 else 1955 { 1956 info->errorCount++; 1957 return ReportBadField("keyboard section", field, 1958 scText(info->dpy, si)); 1959 } 1960 if (arrayNdx != NULL) 1961 { 1962 info->errorCount++; 1963 return ReportNotArray("keyboard section", field, 1964 scText(info->dpy, si)); 1965 } 1966 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1967 { 1968 info->errorCount++; 1969 ReportBadType("keyboard section", field, scText(info->dpy, si), 1970 "number"); 1971 return False; 1972 } 1973 si->defs.defined |= def; 1974 *pField = tmp.uval; 1975 return True; 1976} 1977 1978static int 1979SetRowField(RowInfo * row, 1980 char *field, 1981 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) 1982{ 1983 ExprResult tmp; 1984 1985 if (uStrCaseCmp(field, "top") == 0) 1986 { 1987 if (arrayNdx != NULL) 1988 { 1989 info->errorCount++; 1990 return ReportNotArray("keyboard row", field, 1991 rowText(info->dpy, row)); 1992 } 1993 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 1994 { 1995 info->errorCount++; 1996 return ReportBadType("keyboard row", field, 1997 rowText(info->dpy, row), "number"); 1998 } 1999 row->defs.defined |= _GR_Top; 2000 row->top = tmp.uval; 2001 } 2002 else if (uStrCaseCmp(field, "left") == 0) 2003 { 2004 if (arrayNdx != NULL) 2005 { 2006 info->errorCount++; 2007 return ReportNotArray("keyboard row", field, 2008 rowText(info->dpy, row)); 2009 } 2010 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 2011 { 2012 info->errorCount++; 2013 return ReportBadType("keyboard row", field, 2014 rowText(info->dpy, row), "number"); 2015 } 2016 row->defs.defined |= _GR_Left; 2017 row->left = tmp.uval; 2018 } 2019 else if (uStrCaseCmp(field, "vertical") == 0) 2020 { 2021 if (arrayNdx != NULL) 2022 { 2023 info->errorCount++; 2024 return ReportNotArray("keyboard row", field, 2025 rowText(info->dpy, row)); 2026 } 2027 if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) 2028 { 2029 info->errorCount++; 2030 return ReportBadType("keyboard row", field, 2031 rowText(info->dpy, row), "boolean"); 2032 } 2033 row->defs.defined |= _GR_Vertical; 2034 row->vertical = tmp.uval; 2035 } 2036 else 2037 { 2038 info->errorCount++; 2039 return ReportBadField("keyboard row", field, rowText(info->dpy, row)); 2040 } 2041 return True; 2042} 2043 2044static int 2045SetKeyField(KeyInfo * key, 2046 const char *field, 2047 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) 2048{ 2049 ExprResult tmp; 2050 2051 if (uStrCaseCmp(field, "gap") == 0) 2052 { 2053 if (arrayNdx != NULL) 2054 { 2055 info->errorCount++; 2056 return ReportNotArray("key", field, keyText(key)); 2057 } 2058 if (!ExprResolveFloat(value, &tmp, NULL, NULL)) 2059 { 2060 info->errorCount++; 2061 return ReportBadType("key", field, keyText(key), "number"); 2062 } 2063 key->defs.defined |= _GK_Gap; 2064 key->gap = tmp.ival; 2065 } 2066 else if (uStrCaseCmp(field, "shape") == 0) 2067 { 2068 if (arrayNdx != NULL) 2069 { 2070 info->errorCount++; 2071 return ReportNotArray("key", field, keyText(key)); 2072 } 2073 if (!ExprResolveString(value, &tmp, NULL, NULL)) 2074 { 2075 info->errorCount++; 2076 return ReportBadType("key", field, keyText(key), "string"); 2077 } 2078 key->defs.defined |= _GK_Shape; 2079 key->shape = XkbInternAtom(info->dpy, tmp.str, False); 2080 } 2081 else if ((uStrCaseCmp(field, "color") == 0) || 2082 (uStrCaseCmp(field, "keycolor") == 0)) 2083 { 2084 if (arrayNdx != NULL) 2085 { 2086 info->errorCount++; 2087 return ReportNotArray("key", field, keyText(key)); 2088 } 2089 if (!ExprResolveString(value, &tmp, NULL, NULL)) 2090 { 2091 info->errorCount++; 2092 return ReportBadType("key", field, keyText(key), "string"); 2093 } 2094 key->defs.defined |= _GK_Color; 2095 key->color = XkbInternAtom(NULL, tmp.str, False); 2096 } 2097 else if ((uStrCaseCmp(field, "name") == 0) 2098 || (uStrCaseCmp(field, "keyname") == 0)) 2099 { 2100 if (arrayNdx != NULL) 2101 { 2102 info->errorCount++; 2103 return ReportNotArray("key", field, keyText(key)); 2104 } 2105 if (!ExprResolveKeyName(value, &tmp, NULL, NULL)) 2106 { 2107 info->errorCount++; 2108 return ReportBadType("key", field, keyText(key), "key name"); 2109 } 2110 key->defs.defined |= _GK_Name; 2111 bzero(key->name, XkbKeyNameLength + 1); 2112 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength); 2113 } 2114 else 2115 { 2116 info->errorCount++; 2117 return ReportBadField("key", field, keyText(key)); 2118 } 2119 return True; 2120} 2121 2122static int 2123SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value) 2124{ 2125 PropertyInfo pi; 2126 ExprResult result; 2127 2128 InitPropertyInfo(&pi, info); 2129 pi.name = property; 2130 if (!ExprResolveString(value, &result, NULL, NULL)) 2131 { 2132 info->errorCount++; 2133 ERROR("Property values must be type string\n"); 2134 ACTION1("Ignoring illegal definition of \"%s\" property\n", property); 2135 return False; 2136 } 2137 pi.value = result.str; 2138 return AddProperty(info, &pi); 2139} 2140 2141static int 2142HandleGeometryVar(VarDef * stmt, XkbDescPtr xkb, GeometryInfo * info) 2143{ 2144 ExprResult elem, field, tmp; 2145 ExprDef *ndx; 2146 DoodadInfo *di; 2147 Atom *pField; 2148 2149 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0) 2150 return 0; /* internal error, already reported */ 2151 if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0)) 2152 return SetShapeField(NULL, field.str, ndx, stmt->value, info); 2153 if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) 2154 return SetKeyField(&info->dfltSection.dfltRow.dfltKey, 2155 field.str, ndx, stmt->value, info); 2156 if (elem.str && (uStrCaseCmp(elem.str, "row") == 0)) 2157 return SetRowField(&info->dfltSection.dfltRow, field.str, ndx, 2158 stmt->value, info); 2159 if (elem.str && (uStrCaseCmp(elem.str, "section") == 0)) 2160 { 2161 return SetSectionField(&info->dfltSection, field.str, ndx, 2162 stmt->value, info); 2163 } 2164 if (elem.str && (uStrCaseCmp(elem.str, "property") == 0)) 2165 { 2166 if (ndx != NULL) 2167 { 2168 info->errorCount++; 2169 ERROR1("The %s geometry property is not an array\n", field.str); 2170 ACTION("Ignoring illegal property definition\n"); 2171 return False; 2172 } 2173 return SetGeometryProperty(info, field.str, stmt->value); 2174 } 2175 if (elem.str 2176 && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)) 2177 { 2178 return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info); 2179 } 2180 if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0)) 2181 { 2182 DoodadInfo *dflt; 2183 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad); 2184 if (dflt == NULL) 2185 dflt = NextDfltDoodad(NULL, info); 2186 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); 2187 } 2188 if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0)) 2189 { 2190 DoodadInfo *dflt; 2191 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad); 2192 if (dflt == NULL) 2193 dflt = NextDfltDoodad(NULL, info); 2194 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); 2195 } 2196 if (elem.str && (uStrCaseCmp(elem.str, "text") == 0)) 2197 { 2198 DoodadInfo *dflt; 2199 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad); 2200 if (dflt == NULL) 2201 dflt = NextDfltDoodad(NULL, info); 2202 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); 2203 } 2204 if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0)) 2205 { 2206 DoodadInfo *dflt; 2207 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad); 2208 if (dflt == NULL) 2209 dflt = NextDfltDoodad(NULL, info); 2210 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); 2211 } 2212 if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0)) 2213 { 2214 DoodadInfo *dflt; 2215 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad); 2216 if (dflt == NULL) 2217 dflt = NextDfltDoodad(NULL, info); 2218 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); 2219 } 2220 if (elem.str) 2221 { 2222 WARN("Assignment to field of unknown element\n"); 2223 ACTION2("No value assigned to %s.%s\n", elem.str, field.str); 2224 return False; 2225 } 2226 2227 if ((uStrCaseCmp(field.str, "width") == 0) || 2228 (uStrCaseCmp(field.str, "widthmm") == 0)) 2229 { 2230 if (ndx != NULL) 2231 { 2232 info->errorCount++; 2233 return ReportNotArray("keyboard", field.str, "geometry"); 2234 } 2235 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) 2236 { 2237 info->errorCount++; 2238 return ReportBadType("keyboard", field.str, "geometry", "number"); 2239 } 2240 if (tmp.ival < 1) 2241 { 2242 WARN("Keyboard width must be positive\n"); 2243 ACTION1("Ignoring illegal keyboard width %s\n", 2244 XkbGeomFPText(tmp.ival, XkbMessage)); 2245 return True; 2246 } 2247 if (info->widthMM != 0) 2248 { 2249 WARN("Keyboard width multiply defined\n"); 2250 ACTION1("Using last definition (%s),", 2251 XkbGeomFPText(tmp.ival, XkbMessage)); 2252 INFO1(" ignoring first (%s)\n", 2253 XkbGeomFPText(info->widthMM, XkbMessage)); 2254 } 2255 info->widthMM = tmp.ival; 2256 return True; 2257 } 2258 else if ((uStrCaseCmp(field.str, "height") == 0) || 2259 (uStrCaseCmp(field.str, "heightmm") == 0)) 2260 { 2261 if (ndx != NULL) 2262 { 2263 info->errorCount++; 2264 return ReportNotArray("keyboard", field.str, "geometry"); 2265 } 2266 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) 2267 { 2268 info->errorCount++; 2269 return ReportBadType("keyboard", field.str, "geometry", "number"); 2270 } 2271 if (tmp.ival < 1) 2272 { 2273 WARN("Keyboard height must be positive\n"); 2274 ACTION1("Ignoring illegal keyboard height %s\n", 2275 XkbGeomFPText(tmp.ival, XkbMessage)); 2276 return True; 2277 } 2278 if (info->heightMM != 0) 2279 { 2280 WARN("Keyboard height multiply defined\n"); 2281 ACTION1("Using last definition (%s),", 2282 XkbGeomFPText(tmp.ival, XkbMessage)); 2283 INFO1(" ignoring first (%s)\n", 2284 XkbGeomFPText(info->heightMM, XkbMessage)); 2285 } 2286 info->heightMM = tmp.ival; 2287 return True; 2288 } 2289 else if (uStrCaseCmp(field.str, "font") == 0) 2290 { 2291 pField = &info->font; 2292 } 2293 else if ((uStrCaseCmp(field.str, "fontslant") == 0) || 2294 (uStrCaseCmp(field.str, "slant") == 0)) 2295 { 2296 pField = &info->fontSlant; 2297 } 2298 else if ((uStrCaseCmp(field.str, "fontweight") == 0) || 2299 (uStrCaseCmp(field.str, "weight") == 0)) 2300 { 2301 pField = &info->fontWeight; 2302 } 2303 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) || 2304 (uStrCaseCmp(field.str, "setwidth") == 0)) 2305 { 2306 pField = &info->fontWeight; 2307 } 2308 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) || 2309 (uStrCaseCmp(field.str, "encoding") == 0)) 2310 { 2311 pField = &info->fontEncoding; 2312 } 2313 else if ((uStrCaseCmp(field.str, "xfont") == 0) || 2314 (uStrCaseCmp(field.str, "xfontname") == 0)) 2315 { 2316 pField = &info->fontSpec; 2317 } 2318 else if (uStrCaseCmp(field.str, "fontsize") == 0) 2319 { 2320 if (ndx != NULL) 2321 { 2322 info->errorCount++; 2323 return ReportNotArray("keyboard", field.str, "geometry"); 2324 } 2325 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) 2326 { 2327 info->errorCount++; 2328 return ReportBadType("keyboard", field.str, "geometry", "number"); 2329 } 2330 if ((tmp.ival < 40) || (tmp.ival > 2550)) 2331 { 2332 info->errorCount++; 2333 ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival); 2334 ACTION("Ignoring font size in keyboard geometry\n"); 2335 return False; 2336 } 2337 info->fontSize = tmp.ival; 2338 return True; 2339 } 2340 else if ((uStrCaseCmp(field.str, "color") == 0) || 2341 (uStrCaseCmp(field.str, "basecolor") == 0)) 2342 { 2343 if (ndx != NULL) 2344 { 2345 info->errorCount++; 2346 return ReportNotArray("keyboard", field.str, "geometry"); 2347 } 2348 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) 2349 { 2350 info->errorCount++; 2351 return ReportBadType("keyboard", field.str, "geometry", "string"); 2352 } 2353 info->baseColor = XkbInternAtom(NULL, tmp.str, False); 2354 return True; 2355 } 2356 else if (uStrCaseCmp(field.str, "labelcolor") == 0) 2357 { 2358 if (ndx != NULL) 2359 { 2360 info->errorCount++; 2361 return ReportNotArray("keyboard", field.str, "geometry"); 2362 } 2363 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) 2364 { 2365 info->errorCount++; 2366 return ReportBadType("keyboard", field.str, "geometry", "string"); 2367 } 2368 info->labelColor = XkbInternAtom(NULL, tmp.str, False); 2369 return True; 2370 } 2371 else 2372 { 2373 return SetGeometryProperty(info, field.str, stmt->value); 2374 } 2375 2376 if (ndx != NULL) 2377 { 2378 info->errorCount++; 2379 return ReportNotArray("keyboard", field.str, "geometry"); 2380 } 2381 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) 2382 { 2383 info->errorCount++; 2384 return ReportBadType("keyboard", field.str, "geometry", "string"); 2385 } 2386 *pField = XkbInternAtom(NULL, tmp.str, False); 2387 return True; 2388} 2389 2390/***====================================================================***/ 2391 2392static Bool 2393HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge, 2394 GeometryInfo * info) 2395{ 2396 OutlineDef *ol; 2397 int nOut, nPt; 2398 XkbOutlinePtr outline; 2399 ExprDef *pt; 2400 2401 if (def->nOutlines < 1) 2402 { 2403 WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si)); 2404 ACTION("Definition ignored\n"); 2405 return True; 2406 } 2407 si->nOutlines = def->nOutlines; 2408 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec); 2409 if (!si->outlines) 2410 { 2411 ERROR1("Couldn't allocate outlines for \"%s\"\n", 2412 shText(info->dpy, si)); 2413 ACTION("Definition ignored\n"); 2414 info->errorCount++; 2415 return False; 2416 } 2417 for (nOut = 0, ol = def->outlines; ol != NULL; 2418 ol = (OutlineDef *) ol->common.next) 2419 { 2420 if (ol->nPoints < 1) 2421 { 2422 SetShapeField(si, XkbAtomGetString(NULL, ol->field), NULL, 2423 ol->points, info); 2424 continue; 2425 } 2426 outline = NULL; 2427 outline = &si->outlines[nOut++]; 2428 outline->num_points = ol->nPoints; 2429 outline->corner_radius = si->dfltCornerRadius; 2430 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec); 2431 if (!outline->points) 2432 { 2433 ERROR1("Can't allocate points for \"%s\"\n", 2434 shText(info->dpy, si)); 2435 ACTION("Definition ignored\n"); 2436 info->errorCount++; 2437 return False; 2438 } 2439 for (nPt = 0, pt = ol->points; pt != NULL; 2440 pt = (ExprDef *) pt->common.next) 2441 { 2442 outline->points[nPt].x = pt->value.coord.x; 2443 outline->points[nPt].y = pt->value.coord.y; 2444 nPt++; 2445 } 2446 if (ol->field != None) 2447 { 2448 char *str = XkbAtomText(NULL, ol->field, XkbMessage); 2449 if ((uStrCaseCmp(str, "approximation") == 0) || 2450 (uStrCaseCmp(str, "approx") == 0)) 2451 { 2452 if (si->approx == NULL) 2453 si->approx = outline; 2454 else 2455 { 2456 WARN1("Multiple approximations for \"%s\"\n", 2457 shText(info->dpy, si)); 2458 ACTION("Treating all but the first as normal outlines\n"); 2459 } 2460 } 2461 else if (uStrCaseCmp(str, "primary") == 0) 2462 { 2463 if (si->primary == NULL) 2464 si->primary = outline; 2465 else 2466 { 2467 WARN1("Multiple primary outlines for \"%s\"\n", 2468 shText(info->dpy, si)); 2469 ACTION("Treating all but the first as normal outlines\n"); 2470 } 2471 } 2472 else 2473 { 2474 WARN2("Unknown outline type %s for \"%s\"\n", str, 2475 shText(info->dpy, si)); 2476 ACTION("Treated as a normal outline\n"); 2477 } 2478 } 2479 } 2480 if (nOut != si->nOutlines) 2481 { 2482 WSGO2("Expected %d outlines, got %d\n", 2483 (unsigned int) si->nOutlines, nOut); 2484 si->nOutlines = nOut; 2485 } 2486 return True; 2487} 2488 2489static int 2490HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge, 2491 GeometryInfo * info) 2492{ 2493 ShapeInfo si; 2494 2495 if (def->merge != MergeDefault) 2496 merge = def->merge; 2497 2498 bzero(&si, sizeof(ShapeInfo)); 2499 si.defs.merge = merge; 2500 si.name = 2501 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2502 si.dfltCornerRadius = info->dfltCornerRadius; 2503 if (!HandleShapeBody(def, &si, merge, info)) 2504 return False; 2505 if (!AddShape(info, &si)) 2506 return False; 2507 return True; 2508} 2509 2510/***====================================================================***/ 2511 2512static int 2513HandleDoodadDef(DoodadDef * def, 2514 unsigned merge, SectionInfo * si, GeometryInfo * info) 2515{ 2516 ExprResult elem, field; 2517 ExprDef *ndx; 2518 DoodadInfo new; 2519 VarDef *var; 2520 2521 if (def->common.stmtType == StmtIndicatorMapDef) 2522 { 2523 def->common.stmtType = StmtDoodadDef; 2524 def->type = XkbIndicatorDoodad; 2525 } 2526 InitDoodadInfo(&new, def->type, si, info); 2527 new.name = 2528 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2529 for (var = def->body; var != NULL; var = (VarDef *) var->common.next) 2530 { 2531 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) 2532 return 0; /* internal error, already reported */ 2533 if (elem.str != NULL) 2534 { 2535 WARN1("Assignment to field of unknown element in doodad %s\n", 2536 ddText(info->dpy, &new)); 2537 ACTION2("No value assigned to %s.%s\n", elem.str, field.str); 2538 } 2539 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) 2540 return False; 2541 } 2542 if (!AddDoodad(si, info, &new)) 2543 return False; 2544 ClearDoodadInfo(&new); 2545 return True; 2546} 2547 2548/***====================================================================***/ 2549 2550static int 2551HandleOverlayDef(OverlayDef * def, 2552 unsigned merge, SectionInfo * si, GeometryInfo * info) 2553{ 2554 OverlayKeyDef *keyDef; 2555 OverlayKeyInfo *key; 2556 OverlayInfo ol; 2557 2558 if ((def->nKeys < 1) && (warningLevel > 3)) 2559 { 2560 WARN2("Overlay \"%s\" in section \"%s\" has no keys\n", 2561 XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy, 2562 si)); 2563 ACTION("Overlay ignored\n"); 2564 return True; 2565 } 2566 bzero(&ol, sizeof(OverlayInfo)); 2567 ol.name = 2568 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2569 for (keyDef = def->keys; keyDef; 2570 keyDef = (OverlayKeyDef *) keyDef->common.next) 2571 { 2572 key = uTypedCalloc(1, OverlayKeyInfo); 2573 if ((!key) && warningLevel > 0) 2574 { 2575 WSGO("Couldn't allocate OverlayKeyInfo\n"); 2576 ACTION2("Overlay %s for section %s will be incomplete\n", 2577 XkbAtomText(info->dpy, ol.name, XkbMessage), 2578 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 *sinfo; 3615 sinfo = FindShape(info, ki->shape, "key", keyText(ki)); 3616 if (!sinfo) 3617 return False; 3618 key->shape_ndx = sinfo->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