geometry.c revision bfe6082c
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 snprintf(buf, sizeof(buf), "%s in section %s", 262 XkbAtomText(dpy, di->name, XkbMessage), 263 scText(dpy, 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 WARN("Multiple definitions for the \"%s\" property\n", 748 new->name); 749 ACTION("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 WARN("Multiple definitions for \"%s\" property\n", new->name); 761 ACTION("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 WARN("Unknown shape \"%s\" for %s %s\n", 808 XkbAtomText(info->dpy, name, XkbMessage), type, which); 809 if (old) 810 { 811 ACTION("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 WARN("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 WARN("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 WARN("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 WARN("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(const 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 WARN 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 WARN("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 ACTION 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 WARN("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 WARN("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 const 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 const 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 const char *field, 1514 ExprDef * arrayNdx, 1515 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1516{ 1517 ExprResult tmp; 1518 unsigned def; 1519 unsigned type; 1520 const 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 const 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 const char *field, 1709 ExprDef * arrayNdx, 1710 ExprDef * value, SectionInfo * si, GeometryInfo * info) 1711{ 1712 ExprResult tmp; 1713 const 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 const 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 ERROR("Doodad priority %d out of range (must be 0..%d)\n", 1812 tmp.ival, XkbGeomMaxPriority); 1813 ACTION("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 WSGO("Unknown doodad type %d in SetDoodadField\n", 1885 (unsigned int) di->type); 1886 ACTION("Definition of %s in %s ignored\n", field, ddText(info->dpy, di)); 1887 return False; 1888} 1889 1890static int 1891SetSectionField(SectionInfo * si, 1892 const 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 ERROR("Section priority %d out of range (must be 0..%d)\n", 1920 tmp.ival, XkbGeomMaxPriority); 1921 ACTION("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 const 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 ACTION("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 ERROR("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 ACTION("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 ACTION("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 ACTION("Using last definition (%s),", 2251 XkbGeomFPText(tmp.ival, XkbMessage)); 2252 INFO(" 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 ACTION("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 ACTION("Using last definition (%s),", 2282 XkbGeomFPText(tmp.ival, XkbMessage)); 2283 INFO(" 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 ERROR("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 WARN("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 ERROR("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 = &si->outlines[nOut++]; 2427 outline->num_points = ol->nPoints; 2428 outline->corner_radius = si->dfltCornerRadius; 2429 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec); 2430 if (!outline->points) 2431 { 2432 ERROR("Can't allocate points for \"%s\"\n", 2433 shText(info->dpy, si)); 2434 ACTION("Definition ignored\n"); 2435 info->errorCount++; 2436 return False; 2437 } 2438 for (nPt = 0, pt = ol->points; pt != NULL; 2439 pt = (ExprDef *) pt->common.next) 2440 { 2441 outline->points[nPt].x = pt->value.coord.x; 2442 outline->points[nPt].y = pt->value.coord.y; 2443 nPt++; 2444 } 2445 if (ol->field != None) 2446 { 2447 char *str = XkbAtomText(NULL, ol->field, XkbMessage); 2448 if ((uStrCaseCmp(str, "approximation") == 0) || 2449 (uStrCaseCmp(str, "approx") == 0)) 2450 { 2451 if (si->approx == NULL) 2452 si->approx = outline; 2453 else 2454 { 2455 WARN("Multiple approximations for \"%s\"\n", 2456 shText(info->dpy, si)); 2457 ACTION("Treating all but the first as normal outlines\n"); 2458 } 2459 } 2460 else if (uStrCaseCmp(str, "primary") == 0) 2461 { 2462 if (si->primary == NULL) 2463 si->primary = outline; 2464 else 2465 { 2466 WARN("Multiple primary outlines for \"%s\"\n", 2467 shText(info->dpy, si)); 2468 ACTION("Treating all but the first as normal outlines\n"); 2469 } 2470 } 2471 else 2472 { 2473 WARN("Unknown outline type %s for \"%s\"\n", str, 2474 shText(info->dpy, si)); 2475 ACTION("Treated as a normal outline\n"); 2476 } 2477 } 2478 } 2479 if (nOut != si->nOutlines) 2480 { 2481 WSGO("Expected %d outlines, got %d\n", 2482 (unsigned int) si->nOutlines, nOut); 2483 si->nOutlines = nOut; 2484 } 2485 return True; 2486} 2487 2488static int 2489HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge, 2490 GeometryInfo * info) 2491{ 2492 ShapeInfo si; 2493 2494 if (def->merge != MergeDefault) 2495 merge = def->merge; 2496 2497 bzero(&si, sizeof(ShapeInfo)); 2498 si.defs.merge = merge; 2499 si.name = 2500 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2501 si.dfltCornerRadius = info->dfltCornerRadius; 2502 if (!HandleShapeBody(def, &si, merge, info)) 2503 return False; 2504 if (!AddShape(info, &si)) 2505 return False; 2506 return True; 2507} 2508 2509/***====================================================================***/ 2510 2511static int 2512HandleDoodadDef(DoodadDef * def, 2513 unsigned merge, SectionInfo * si, GeometryInfo * info) 2514{ 2515 ExprResult elem, field; 2516 ExprDef *ndx; 2517 DoodadInfo new; 2518 VarDef *var; 2519 2520 if (def->common.stmtType == StmtIndicatorMapDef) 2521 { 2522 def->common.stmtType = StmtDoodadDef; 2523 def->type = XkbIndicatorDoodad; 2524 } 2525 InitDoodadInfo(&new, def->type, si, info); 2526 new.name = 2527 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2528 for (var = def->body; var != NULL; var = (VarDef *) var->common.next) 2529 { 2530 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) 2531 return 0; /* internal error, already reported */ 2532 if (elem.str != NULL) 2533 { 2534 WARN("Assignment to field of unknown element in doodad %s\n", 2535 ddText(info->dpy, &new)); 2536 ACTION("No value assigned to %s.%s\n", elem.str, field.str); 2537 } 2538 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) 2539 return False; 2540 } 2541 if (!AddDoodad(si, info, &new)) 2542 return False; 2543 ClearDoodadInfo(&new); 2544 return True; 2545} 2546 2547/***====================================================================***/ 2548 2549static int 2550HandleOverlayDef(OverlayDef * def, 2551 unsigned merge, SectionInfo * si, GeometryInfo * info) 2552{ 2553 OverlayKeyDef *keyDef; 2554 OverlayKeyInfo *key; 2555 OverlayInfo ol; 2556 2557 if ((def->nKeys < 1) && (warningLevel > 3)) 2558 { 2559 WARN("Overlay \"%s\" in section \"%s\" has no keys\n", 2560 XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy, 2561 si)); 2562 ACTION("Overlay ignored\n"); 2563 return True; 2564 } 2565 bzero(&ol, sizeof(OverlayInfo)); 2566 ol.name = 2567 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2568 for (keyDef = def->keys; keyDef; 2569 keyDef = (OverlayKeyDef *) keyDef->common.next) 2570 { 2571 key = uTypedCalloc(1, OverlayKeyInfo); 2572 if ((!key) && warningLevel > 0) 2573 { 2574 WSGO("Couldn't allocate OverlayKeyInfo\n"); 2575 ACTION("Overlay %s for section %s will be incomplete\n", 2576 XkbAtomText(info->dpy, ol.name, XkbMessage), 2577 scText(info->dpy, si)); 2578 return False; 2579 } 2580 strncpy(key->over, keyDef->over, XkbKeyNameLength); 2581 strncpy(key->under, keyDef->under, XkbKeyNameLength); 2582 key->sectionRow = _GOK_UnknownRow; 2583 key->overlayRow = _GOK_UnknownRow; 2584 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs, 2585 (CommonInfo *) key); 2586 ol.nKeys++; 2587 } 2588 if (!AddOverlay(si, info, &ol)) 2589 return False; 2590 ClearOverlayInfo(&ol); 2591 return True; 2592} 2593 2594/***====================================================================***/ 2595 2596static Bool 2597HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info) 2598{ 2599 RowInfo *row; 2600 ExprDef *expr; 2601 2602 row = key->row; 2603 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next) 2604 { 2605 if (expr->op == OpAssign) 2606 { 2607 ExprResult elem, f; 2608 ExprDef *ndx; 2609 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0) 2610 return False; /* internal error, already reported */ 2611 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0)) 2612 { 2613 if (!SetKeyField 2614 (key, f.str, ndx, expr->value.binary.right, info)) 2615 return False; 2616 } 2617 else 2618 { 2619 ERROR("Illegal element used in a key definition\n"); 2620 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str); 2621 return False; 2622 } 2623 } 2624 else 2625 { 2626 switch (expr->type) 2627 { 2628 case TypeInt: 2629 case TypeFloat: 2630 if (!SetKeyField(key, "gap", NULL, expr, info)) 2631 return False; 2632 break; 2633 case TypeString: 2634 if (!SetKeyField(key, "shape", NULL, expr, info)) 2635 return False; 2636 break; 2637 case TypeKeyName: 2638 if (!SetKeyField(key, "name", NULL, expr, info)) 2639 return False; 2640 break; 2641 default: 2642 ERROR("Cannot determine field for unnamed expression\n"); 2643 ACTION("Ignoring key %d in row %d of section %s\n", 2644 row->nKeys + 1, row->section->nRows + 1, 2645 rowText(info->dpy, row)); 2646 return False; 2647 } 2648 } 2649 } 2650 return True; 2651} 2652 2653static Bool 2654HandleRowBody(RowDef * def, RowInfo * row, unsigned merge, 2655 GeometryInfo * info) 2656{ 2657 KeyDef *keyDef; 2658 2659 if ((def->nKeys < 1) && (warningLevel > 3)) 2660 { 2661 ERROR("Row in section %s has no keys\n", rowText(info->dpy, row)); 2662 ACTION("Section ignored\n"); 2663 return True; 2664 } 2665 for (keyDef = def->keys; keyDef != NULL; 2666 keyDef = (KeyDef *) keyDef->common.next) 2667 { 2668 if (keyDef->common.stmtType == StmtVarDef) 2669 { 2670 VarDef *var = (VarDef *) keyDef; 2671 ExprResult elem, field; 2672 ExprDef *ndx; 2673 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) 2674 return 0; /* internal error, already reported */ 2675 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0)) 2676 { 2677 if (!SetRowField(row, field.str, ndx, var->value, info)) 2678 return False; 2679 } 2680 else if (uStrCaseCmp(elem.str, "key") == 0) 2681 { 2682 if (!SetKeyField 2683 (&row->dfltKey, field.str, ndx, var->value, info)) 2684 return False; 2685 } 2686 else 2687 { 2688 WARN("Assignment to field of unknown element in row\n"); 2689 ACTION("No value assigned to %s.%s\n", elem.str, field.str); 2690 } 2691 } 2692 else if (keyDef->common.stmtType == StmtKeyDef) 2693 { 2694 KeyInfo key; 2695 InitKeyInfo(&key, row, info); 2696 if (keyDef->name != NULL) 2697 { 2698 int len = strlen(keyDef->name); 2699 if ((len < 1) || (len > XkbKeyNameLength)) 2700 { 2701 ERROR("Illegal name %s for key in section %s\n", 2702 keyDef->name, rowText(info->dpy, row)); 2703 ACTION("Section not compiled\n"); 2704 return False; 2705 } 2706 bzero(key.name, XkbKeyNameLength + 1); 2707 strncpy(key.name, keyDef->name, XkbKeyNameLength); 2708 key.defs.defined |= _GK_Name; 2709 } 2710 else if (!HandleComplexKey(keyDef, &key, info)) 2711 return False; 2712 if (!AddKey(row, &key)) 2713 return False; 2714 } 2715 else 2716 { 2717 WSGO("Unexpected statement (type %d) in row body\n", 2718 keyDef->common.stmtType); 2719 return False; 2720 } 2721 } 2722 return True; 2723} 2724 2725static Bool 2726HandleSectionBody(SectionDef * def, 2727 SectionInfo * si, unsigned merge, GeometryInfo * info) 2728{ 2729 RowDef *rowDef; 2730 DoodadInfo *di; 2731 2732 for (rowDef = def->rows; rowDef != NULL; 2733 rowDef = (RowDef *) rowDef->common.next) 2734 { 2735 if (rowDef->common.stmtType == StmtVarDef) 2736 { 2737 VarDef *var = (VarDef *) rowDef; 2738 ExprResult elem, field; 2739 ExprDef *ndx; 2740 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) 2741 return 0; /* internal error, already reported */ 2742 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0)) 2743 { 2744 if (!SetSectionField(si, field.str, ndx, var->value, info)) 2745 return False; 2746 } 2747 else if (uStrCaseCmp(elem.str, "row") == 0) 2748 { 2749 if (!SetRowField 2750 (&si->dfltRow, field.str, ndx, var->value, info)) 2751 return False; 2752 } 2753 else if (uStrCaseCmp(elem.str, "key") == 0) 2754 { 2755 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx, 2756 var->value, info)) 2757 return False; 2758 } 2759 else if ((di = 2760 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL) 2761 { 2762 if (!SetDoodadField(di, field.str, ndx, var->value, si, info)) 2763 return False; 2764 } 2765 else 2766 { 2767 WARN("Assignment to field of unknown element in section\n"); 2768 ACTION("No value assigned to %s.%s\n", elem.str, field.str); 2769 } 2770 } 2771 else if (rowDef->common.stmtType == StmtRowDef) 2772 { 2773 RowInfo row; 2774 InitRowInfo(&row, si, info); 2775 if (!HandleRowBody(rowDef, &row, merge, info)) 2776 return False; 2777 if (!AddRow(si, &row)) 2778 return False; 2779/* ClearRowInfo(&row,info);*/ 2780 } 2781 else if ((rowDef->common.stmtType == StmtDoodadDef) || 2782 (rowDef->common.stmtType == StmtIndicatorMapDef)) 2783 { 2784 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info)) 2785 return False; 2786 } 2787 else if (rowDef->common.stmtType == StmtOverlayDef) 2788 { 2789 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info)) 2790 return False; 2791 } 2792 else 2793 { 2794 WSGO("Unexpected statement (type %d) in section body\n", 2795 rowDef->common.stmtType); 2796 return False; 2797 } 2798 } 2799 if (si->nRows != def->nRows) 2800 { 2801 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows, 2802 (unsigned int) si->nRows); 2803 ACTION("Definition of section %s might be incorrect\n", 2804 scText(info->dpy, si)); 2805 } 2806 return True; 2807} 2808 2809static int 2810HandleSectionDef(SectionDef * def, 2811 XkbDescPtr xkb, unsigned merge, GeometryInfo * info) 2812{ 2813 SectionInfo si; 2814 char *str; 2815 2816 if (def->merge != MergeDefault) 2817 merge = def->merge; 2818 InitSectionInfo(&si, info); 2819 si.defs.merge = merge; 2820 str = XkbAtomGetString(NULL, def->name); 2821 if ((str == NULL) || (strlen(str) < 1)) 2822 { 2823 ERROR("Section defined without a name\n"); 2824 ACTION("Definition ignored\n"); 2825 return False; 2826 } 2827 si.name = 2828 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); 2829 if (!HandleSectionBody(def, &si, merge, info)) 2830 return False; 2831 if (!AddSection(info, &si)) 2832 return False; 2833 return True; 2834} 2835 2836/***====================================================================***/ 2837 2838static void 2839HandleGeometryFile(XkbFile * file, 2840 XkbDescPtr xkb, unsigned merge, GeometryInfo * info) 2841{ 2842 ParseCommon *stmt; 2843 const char *failWhat; 2844 2845 if (merge == MergeDefault) 2846 merge = MergeAugment; 2847 info->name = uStringDup(file->name); 2848 stmt = file->defs; 2849 while (stmt) 2850 { 2851 failWhat = NULL; 2852 switch (stmt->stmtType) 2853 { 2854 case StmtInclude: 2855 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info, 2856 HandleGeometryFile)) 2857 info->errorCount++; 2858 break; 2859 case StmtKeyAliasDef: 2860 if (!HandleAliasDef((KeyAliasDef *) stmt, 2861 merge, info->fileID, &info->aliases)) 2862 { 2863 info->errorCount++; 2864 } 2865 break; 2866 case StmtVarDef: 2867 if (!HandleGeometryVar((VarDef *) stmt, xkb, info)) 2868 info->errorCount++; 2869 break; 2870 case StmtShapeDef: 2871 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info)) 2872 info->errorCount++; 2873 break; 2874 case StmtSectionDef: 2875 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info)) 2876 info->errorCount++; 2877 break; 2878 case StmtIndicatorMapDef: 2879 case StmtDoodadDef: 2880 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info)) 2881 info->errorCount++; 2882 break; 2883 case StmtVModDef: 2884 if (!failWhat) 2885 failWhat = "virtual modifier"; 2886 case StmtInterpDef: 2887 if (!failWhat) 2888 failWhat = "symbol interpretation"; 2889 case StmtGroupCompatDef: 2890 if (!failWhat) 2891 failWhat = "group compatibility map"; 2892 case StmtKeycodeDef: 2893 if (!failWhat) 2894 failWhat = "key name"; 2895 ERROR("Interpretation files may not include other types\n"); 2896 ACTION("Ignoring %s definition.\n", failWhat); 2897 info->errorCount++; 2898 break; 2899 default: 2900 WSGO("Unexpected statement type %d in HandleGeometryFile\n", 2901 stmt->stmtType); 2902 break; 2903 } 2904 stmt = stmt->next; 2905 if (info->errorCount > 10) 2906 { 2907#ifdef NOISY 2908 ERROR("Too many errors\n"); 2909#endif 2910 ACTION("Abandoning geometry file \"%s\"\n", file->topName); 2911 break; 2912 } 2913 } 2914 return; 2915} 2916 2917/***====================================================================***/ 2918 2919static Bool 2920CopyShapeDef(Display * dpy, XkbGeometryPtr geom, ShapeInfo * si) 2921{ 2922 register int i, n; 2923 XkbShapePtr shape; 2924 XkbOutlinePtr old_outline, outline; 2925 Atom name; 2926 2927 si->index = geom->num_shapes; 2928 name = XkbInternAtom(dpy, XkbAtomGetString(NULL, si->name), False); 2929 shape = XkbAddGeomShape(geom, name, si->nOutlines); 2930 if (!shape) 2931 { 2932 WSGO("Couldn't allocate shape in geometry\n"); 2933 ACTION("Shape %s not compiled\n", shText(dpy, si)); 2934 return False; 2935 } 2936 old_outline = si->outlines; 2937 for (i = 0; i < si->nOutlines; i++, old_outline++) 2938 { 2939 outline = XkbAddGeomOutline(shape, old_outline->num_points); 2940 if (!outline) 2941 { 2942 WSGO("Couldn't allocate outline in shape\n"); 2943 ACTION("Shape %s is incomplete\n", shText(dpy, si)); 2944 return False; 2945 } 2946 n = old_outline->num_points; 2947 memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec)); 2948 outline->num_points = old_outline->num_points; 2949 outline->corner_radius = old_outline->corner_radius; 2950 } 2951 if (si->approx) 2952 { 2953 n = (si->approx - si->outlines); 2954 shape->approx = &shape->outlines[n]; 2955 } 2956 if (si->primary) 2957 { 2958 n = (si->primary - si->outlines); 2959 shape->primary = &shape->outlines[n]; 2960 } 2961 XkbComputeShapeBounds(shape); 2962 return True; 2963} 2964 2965static Bool 2966VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info) 2967{ 2968 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left)) 2969 { 2970 if (warningLevel < 9) 2971 { 2972 ERROR("No position defined for doodad %s\n", 2973 ddText(info->dpy, di)); 2974 ACTION("Illegal doodad ignored\n"); 2975 return False; 2976 } 2977 } 2978 if ((di->defs.defined & _GD_Priority) == 0) 2979 { 2980 /* calculate priority -- should be just above previous doodad/row */ 2981 } 2982 switch (di->type) 2983 { 2984 case XkbOutlineDoodad: 2985 case XkbSolidDoodad: 2986 if ((di->defs.defined & _GD_Shape) == 0) 2987 { 2988 ERROR("No shape defined for %s doodad %s\n", 2989 (di->type == XkbOutlineDoodad ? "outline" : "filled"), 2990 ddText(info->dpy, di)); 2991 ACTION("Incomplete definition ignored\n"); 2992 return False; 2993 } 2994 else 2995 { 2996 ShapeInfo *si; 2997 si = FindShape(info, di->shape, 2998 (di->type == 2999 XkbOutlineDoodad ? "outline doodad" : 3000 "solid doodad"), ddText(info->dpy, di)); 3001 if (si) 3002 di->shape = si->name; 3003 else 3004 { 3005 ERROR("No legal shape for %s\n", ddText(info->dpy, di)); 3006 ACTION("Incomplete definition ignored\n"); 3007 return False; 3008 } 3009 } 3010 if ((di->defs.defined & _GD_Color) == 0) 3011 { 3012 if (warningLevel > 5) 3013 { 3014 WARN("No color for doodad %s\n", ddText(info->dpy, di)); 3015 ACTION("Using black\n"); 3016 } 3017 di->color = XkbInternAtom(NULL, "black", False); 3018 } 3019 break; 3020 case XkbTextDoodad: 3021 if ((di->defs.defined & _GD_Text) == 0) 3022 { 3023 ERROR("No text specified for text doodad %s\n", 3024 ddText(info->dpy, di)); 3025 ACTION("Illegal doodad definition ignored\n"); 3026 return False; 3027 } 3028 if ((di->defs.defined & _GD_Angle) == 0) 3029 di->angle = 0; 3030 if ((di->defs.defined & _GD_Color) == 0) 3031 { 3032 if (warningLevel > 5) 3033 { 3034 WARN("No color specified for doodad %s\n", 3035 ddText(info->dpy, di)); 3036 ACTION("Using black\n"); 3037 } 3038 di->color = XkbInternAtom(NULL, "black", False); 3039 } 3040 if ((di->defs.defined & _GD_FontSpec) != 0) 3041 { 3042 if ((di->defs.defined & _GD_FontParts) == 0) 3043 return True; 3044 if (warningLevel < 9) 3045 { 3046 WARN 3047 ("Text doodad %s has full and partial font definition\n", 3048 ddText(info->dpy, di)); 3049 ACTION("Full specification ignored\n"); 3050 } 3051 di->defs.defined &= ~_GD_FontSpec; 3052 di->fontSpec = None; 3053 } 3054 if ((di->defs.defined & _GD_Font) == 0) 3055 { 3056 if (warningLevel > 5) 3057 { 3058 WARN("No font specified for doodad %s\n", 3059 ddText(info->dpy, di)); 3060 ACTION("Using \"%s\"\n", DFLT_FONT); 3061 } 3062 di->font = XkbInternAtom(NULL, DFLT_FONT, False); 3063 } 3064 if ((di->defs.defined & _GD_FontSlant) == 0) 3065 { 3066 if (warningLevel > 7) 3067 { 3068 WARN("No font slant for text doodad %s\n", 3069 ddText(info->dpy, di)); 3070 ACTION("Using \"%s\"\n", DFLT_SLANT); 3071 } 3072 di->fontSlant = XkbInternAtom(NULL, DFLT_SLANT, False); 3073 } 3074 if ((di->defs.defined & _GD_FontWeight) == 0) 3075 { 3076 if (warningLevel > 7) 3077 { 3078 WARN("No font weight for text doodad %s\n", 3079 ddText(info->dpy, di)); 3080 ACTION("Using \"%s\"\n", DFLT_WEIGHT); 3081 } 3082 di->fontWeight = XkbInternAtom(NULL, DFLT_WEIGHT, False); 3083 } 3084 if ((di->defs.defined & _GD_FontSetWidth) == 0) 3085 { 3086 if (warningLevel > 9) 3087 { 3088 WARN("No font set width for text doodad %s\n", 3089 ddText(info->dpy, di)); 3090 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH); 3091 } 3092 di->fontSetWidth = XkbInternAtom(NULL, DFLT_SET_WIDTH, False); 3093 } 3094 if ((di->defs.defined & _GD_FontVariant) == 0) 3095 { 3096 if (warningLevel > 9) 3097 { 3098 WARN("No font variant for text doodad %s\n", 3099 ddText(info->dpy, di)); 3100 ACTION("Using \"%s\"\n", DFLT_VARIANT); 3101 } 3102 di->fontVariant = XkbInternAtom(NULL, DFLT_VARIANT, False); 3103 } 3104 if ((di->defs.defined & _GD_FontEncoding) == 0) 3105 { 3106 if (warningLevel > 7) 3107 { 3108 WARN("No font encoding for doodad %s\n", 3109 ddText(info->dpy, di)); 3110 ACTION("Using \"%s\"\n", DFLT_ENCODING); 3111 } 3112 di->fontEncoding = XkbInternAtom(NULL, DFLT_ENCODING, False); 3113 } 3114 if ((di->defs.defined & _GD_FontSize) == 0) 3115 { 3116 if (warningLevel > 7) 3117 { 3118 WARN("No font size for text doodad %s\n", 3119 ddText(info->dpy, di)); 3120 ACTION("Using %s point text\n", 3121 XkbGeomFPText(DFLT_SIZE, XkbMessage)); 3122 } 3123 di->fontSize = DFLT_SIZE; 3124 } 3125 if ((di->defs.defined & _GD_Height) == 0) 3126 { 3127 unsigned size, nLines; 3128 char *tmp; 3129 size = (di->fontSize * 120) / 100; 3130 size = (size * 254) / 720; /* convert to mm/10 */ 3131 for (nLines = 1, tmp = XkbAtomGetString(NULL, di->text); *tmp; 3132 tmp++) 3133 { 3134 if (*tmp == '\n') 3135 nLines++; 3136 } 3137 size *= nLines; 3138 if (warningLevel > 5) 3139 { 3140 WARN("No height for text doodad %s\n", 3141 ddText(info->dpy, di)); 3142 ACTION("Using calculated height %s millimeters\n", 3143 XkbGeomFPText(size, XkbMessage)); 3144 } 3145 di->height = size; 3146 } 3147 if ((di->defs.defined & _GD_Width) == 0) 3148 { 3149 unsigned width, tmp; 3150 char *str; 3151 width = tmp = 0; 3152 for (str = XkbAtomGetString(NULL, di->text); *str; str++) 3153 { 3154 if (*str != '\n') 3155 tmp++; 3156 else 3157 { 3158 if (tmp > width) 3159 width = tmp; 3160 tmp = 1; 3161 } 3162 } 3163 if (width == 0) 3164 width = tmp; 3165 width *= (di->height * 2) / 3; 3166 if (warningLevel > 5) 3167 { 3168 WARN("No width for text doodad %s\n", ddText(info->dpy, di)); 3169 ACTION("Using calculated width %s millimeters\n", 3170 XkbGeomFPText(width, XkbMessage)); 3171 } 3172 di->width = width; 3173 } 3174 break; 3175 case XkbIndicatorDoodad: 3176 if ((di->defs.defined & _GD_Shape) == 0) 3177 { 3178 ERROR("No shape defined for indicator doodad %s\n", 3179 ddText(info->dpy, di)); 3180 ACTION("Incomplete definition ignored\n"); 3181 return False; 3182 } 3183 else 3184 { 3185 ShapeInfo *si; 3186 si = FindShape(info, di->shape, "indicator doodad", 3187 ddText(info->dpy, di)); 3188 if (si) 3189 di->shape = si->name; 3190 else 3191 { 3192 ERROR("No legal shape for doodad %s\n", 3193 ddText(info->dpy, di)); 3194 ACTION("Incomplete definition ignored\n"); 3195 return False; 3196 } 3197 } 3198 if ((di->defs.defined & _GD_Color) == 0) 3199 { 3200 if (warningLevel > 5) 3201 { 3202 WARN("No \"on\" color for indicator doodad %s\n", 3203 ddText(info->dpy, di)); 3204 ACTION("Using green\n"); 3205 } 3206 di->color = XkbInternAtom(NULL, "green", False); 3207 } 3208 if ((di->defs.defined & _GD_OffColor) == 0) 3209 { 3210 if (warningLevel > 5) 3211 { 3212 WARN("No \"off\" color for indicator doodad %s\n", 3213 ddText(info->dpy, di)); 3214 ACTION("Using black\n"); 3215 } 3216 di->offColor = XkbInternAtom(NULL, "black", False); 3217 } 3218 break; 3219 case XkbLogoDoodad: 3220 if (di->logoName == NULL) 3221 { 3222 ERROR("No logo name defined for logo doodad %s\n", 3223 ddText(info->dpy, di)); 3224 ACTION("Incomplete definition ignored\n"); 3225 return False; 3226 } 3227 if ((di->defs.defined & _GD_Shape) == 0) 3228 { 3229 ERROR("No shape defined for logo doodad %s\n", 3230 ddText(info->dpy, di)); 3231 ACTION("Incomplete definition ignored\n"); 3232 return False; 3233 } 3234 else 3235 { 3236 ShapeInfo *si; 3237 si = FindShape(info, di->shape, "logo doodad", 3238 ddText(info->dpy, di)); 3239 if (si) 3240 di->shape = si->name; 3241 else 3242 { 3243 ERROR("No legal shape for %s\n", ddText(info->dpy, di)); 3244 ACTION("Incomplete definition ignored\n"); 3245 return False; 3246 } 3247 } 3248 if ((di->defs.defined & _GD_Color) == 0) 3249 { 3250 if (warningLevel > 5) 3251 { 3252 WARN("No color for doodad %s\n", ddText(info->dpy, di)); 3253 ACTION("Using black\n"); 3254 } 3255 di->color = XkbInternAtom(NULL, "black", False); 3256 } 3257 break; 3258 default: 3259 WSGO("Unknown doodad type %d in VerifyDoodad\n", 3260 (unsigned int) di->type); 3261 return False; 3262 } 3263 return True; 3264} 3265 3266#define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s" 3267 3268static char * 3269FontFromParts(Atom fontTok, 3270 Atom weightTok, 3271 Atom slantTok, 3272 Atom setWidthTok, Atom varTok, int size, Atom encodingTok) 3273{ 3274 int totalSize; 3275 const char *font, *weight, *slant, *setWidth, *variant, *encoding; 3276 char *rtrn; 3277 3278 font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT); 3279 weight = 3280 (weightTok != None ? XkbAtomGetString(NULL, weightTok) : DFLT_WEIGHT); 3281 slant = 3282 (slantTok != None ? XkbAtomGetString(NULL, slantTok) : DFLT_SLANT); 3283 setWidth = 3284 (setWidthTok != 3285 None ? XkbAtomGetString(NULL, setWidthTok) : DFLT_SET_WIDTH); 3286 variant = 3287 (varTok != None ? XkbAtomGetString(NULL, varTok) : DFLT_VARIANT); 3288 encoding = 3289 (encodingTok != 3290 None ? XkbAtomGetString(NULL, encodingTok) : DFLT_ENCODING); 3291 if (size == 0) 3292 size = DFLT_SIZE; 3293 totalSize = 3294 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant); 3295 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding); 3296 rtrn = uCalloc(totalSize, 1); 3297 if (rtrn) 3298 { 3299 snprintf(rtrn, totalSize, FONT_TEMPLATE, font, weight, slant, 3300 setWidth, variant, size, encoding); 3301 } 3302 return rtrn; 3303} 3304 3305static Bool 3306CopyDoodadDef(XkbGeometryPtr geom, 3307 XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info) 3308{ 3309 Atom name; 3310 XkbDoodadPtr doodad; 3311 XkbColorPtr color; 3312 XkbShapePtr shape; 3313 ShapeInfo *si; 3314 3315 if (!VerifyDoodadInfo(di, info)) 3316 return False; 3317 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, di->name), False); 3318 doodad = XkbAddGeomDoodad(geom, section, name); 3319 if (!doodad) 3320 { 3321 WSGO("Couldn't allocate doodad in %s\n", 3322 (section ? "section" : "geometry")); 3323 ACTION("Cannot copy doodad %s\n", ddText(info->dpy, di)); 3324 return False; 3325 } 3326 doodad->any.type = di->type; 3327 doodad->any.priority = di->priority; 3328 doodad->any.top = di->top; 3329 doodad->any.left = di->left; 3330 switch (di->type) 3331 { 3332 case XkbOutlineDoodad: 3333 case XkbSolidDoodad: 3334 si = FindShape(info, di->shape, NULL, NULL); 3335 if (!si) 3336 return False; 3337 doodad->shape.angle = di->angle; 3338 color = 3339 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), 3340 geom->num_colors); 3341 shape = &geom->shapes[si->index]; 3342 XkbSetShapeDoodadColor(geom, &doodad->shape, color); 3343 XkbSetShapeDoodadShape(geom, &doodad->shape, shape); 3344 break; 3345 case XkbTextDoodad: 3346 doodad->text.angle = di->angle; 3347 doodad->text.width = di->width; 3348 doodad->text.height = di->height; 3349 if (di->fontSpec == None) 3350 doodad->text.font = FontFromParts(di->font, di->fontWeight, 3351 di->fontSlant, 3352 di->fontSetWidth, 3353 di->fontVariant, di->fontSize, 3354 di->fontEncoding); 3355 else 3356 doodad->text.font = XkbAtomGetString(NULL, di->fontSpec); 3357 doodad->text.text = XkbAtomGetString(NULL, di->text); 3358 color = 3359 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), 3360 geom->num_colors); 3361 XkbSetTextDoodadColor(geom, &doodad->text, color); 3362 break; 3363 case XkbIndicatorDoodad: 3364 si = FindShape(info, di->shape, NULL, NULL); 3365 if (!si) 3366 return False; 3367 shape = &geom->shapes[si->index]; 3368 color = 3369 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), 3370 geom->num_colors); 3371 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape); 3372 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color); 3373 color = 3374 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->offColor), 3375 geom->num_colors); 3376 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color); 3377 break; 3378 case XkbLogoDoodad: 3379 si = FindShape(info, di->shape, NULL, NULL); 3380 if (!si) 3381 return False; 3382 doodad->logo.angle = di->angle; 3383 color = 3384 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), 3385 geom->num_colors); 3386 shape = &geom->shapes[si->index]; 3387 XkbSetLogoDoodadColor(geom, &doodad->logo, color); 3388 XkbSetLogoDoodadShape(geom, &doodad->logo, shape); 3389 doodad->logo.logo_name = di->logoName; 3390 di->logoName = NULL; 3391 break; 3392 } 3393 return True; 3394} 3395 3396/***====================================================================***/ 3397 3398static Bool 3399VerifyOverlayInfo(XkbGeometryPtr geom, 3400 XkbSectionPtr section, 3401 OverlayInfo * oi, 3402 GeometryInfo * info, short rowMap[256], short rowSize[256]) 3403{ 3404 register OverlayKeyInfo *ki, *next; 3405 unsigned long oKey, uKey, sKey; 3406 XkbRowPtr row; 3407 XkbKeyPtr key; 3408 int r, k; 3409 3410 /* find out which row each key is in */ 3411 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) 3412 { 3413 oKey = KeyNameToLong(ki->over); 3414 uKey = KeyNameToLong(ki->under); 3415 for (r = 0, row = section->rows; (r < section->num_rows) && oKey; 3416 r++, row++) 3417 { 3418 for (k = 0, key = row->keys; (k < row->num_keys) && oKey; 3419 k++, key++) 3420 { 3421 sKey = KeyNameToLong(key->name.name); 3422 if (sKey == oKey) 3423 { 3424 if (warningLevel > 0) 3425 { 3426 WARN 3427 ("Key %s in section \"%s\" and overlay \"%s\"\n", 3428 XkbKeyNameText(key->name.name, 3429 XkbMessage), 3430 XkbAtomText(info->dpy, section->name, 3431 XkbMessage), 3432 XkbAtomText(info->dpy, oi->name, XkbMessage)); 3433 ACTION("Overlay definition ignored\n"); 3434 } 3435 oKey = 0; 3436 } 3437 else if (sKey == uKey) 3438 { 3439 ki->sectionRow = r; 3440 oKey = 0; 3441 } 3442 } 3443 } 3444 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0)) 3445 { 3446 WARN 3447 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n", 3448 XkbKeyNameText(ki->under, XkbMessage), 3449 XkbAtomText(info->dpy, section->name, XkbMessage), 3450 XkbAtomText(info->dpy, oi->name, XkbMessage)); 3451 ACTION("Definition ignored\n"); 3452 } 3453 } 3454 /* now prune out keys that aren't in the section */ 3455 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow)) 3456 { 3457 next = (OverlayKeyInfo *) oi->keys->defs.next; 3458 uFree(oi->keys); 3459 oi->keys = next; 3460 oi->nKeys--; 3461 } 3462 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next) 3463 { 3464 next = (OverlayKeyInfo *) ki->defs.next; 3465 if (next->sectionRow == _GOK_UnknownRow) 3466 { 3467 ki->defs.next = next->defs.next; 3468 oi->nKeys--; 3469 uFree(next); 3470 next = (OverlayKeyInfo *) ki->defs.next; 3471 } 3472 } 3473 if (oi->nKeys < 1) 3474 { 3475 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n", 3476 XkbAtomText(info->dpy, oi->name, XkbMessage), 3477 XkbAtomText(info->dpy, section->name, XkbMessage)); 3478 ACTION("Overlay definition ignored\n"); 3479 return False; 3480 } 3481 /* now figure out how many rows are defined for the overlay */ 3482 bzero(rowSize, sizeof(short) * 256); 3483 for (k = 0; k < 256; k++) 3484 { 3485 rowMap[k] = -1; 3486 } 3487 oi->nRows = 0; 3488 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) 3489 { 3490 if (rowMap[ki->sectionRow] == -1) 3491 rowMap[ki->sectionRow] = oi->nRows++; 3492 ki->overlayRow = rowMap[ki->sectionRow]; 3493 rowSize[ki->overlayRow]++; 3494 } 3495 return True; 3496} 3497 3498static Bool 3499CopyOverlayDef(XkbGeometryPtr geom, 3500 XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info) 3501{ 3502 Atom name; 3503 XkbOverlayPtr ol; 3504 XkbOverlayRowPtr row; 3505 XkbOverlayKeyPtr key; 3506 OverlayKeyInfo *ki; 3507 short rowMap[256], rowSize[256]; 3508 int i; 3509 3510 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize)) 3511 return False; 3512 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, oi->name), False); 3513 ol = XkbAddGeomOverlay(section, name, oi->nRows); 3514 if (!ol) 3515 { 3516 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n", 3517 XkbAtomText(info->dpy, name, XkbMessage), 3518 XkbAtomText(info->dpy, section->name, XkbMessage)); 3519 return False; 3520 } 3521 for (i = 0; i < oi->nRows; i++) 3522 { 3523 int tmp, row_under; 3524 for (tmp = 0, row_under = -1; 3525 (tmp < section->num_rows) && (row_under < 0); tmp++) 3526 { 3527 if (rowMap[tmp] == i) 3528 row_under = tmp; 3529 } 3530 if (!XkbAddGeomOverlayRow(ol, row_under, rowSize[i])) 3531 { 3532 WSGO 3533 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n", 3534 i, XkbAtomText(info->dpy, name, XkbMessage), 3535 XkbAtomText(info->dpy, section->name, XkbMessage)); 3536 return False; 3537 } 3538 } 3539 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) 3540 { 3541 row = &ol->rows[ki->overlayRow]; 3542 key = &row->keys[row->num_keys++]; 3543 bzero(key, sizeof(XkbOverlayKeyRec)); 3544 strncpy(key->over.name, ki->over, XkbKeyNameLength); 3545 strncpy(key->under.name, ki->under, XkbKeyNameLength); 3546 } 3547 return True; 3548} 3549 3550/***====================================================================***/ 3551 3552static Bool 3553CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info) 3554{ 3555 XkbSectionPtr section; 3556 XkbRowPtr row; 3557 XkbKeyPtr key; 3558 KeyInfo *ki; 3559 RowInfo *ri; 3560 Atom name; 3561 3562 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, si->name), False); 3563 section = 3564 XkbAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays); 3565 if (section == NULL) 3566 { 3567 WSGO("Couldn't allocate section in geometry\n"); 3568 ACTION("Section %s not compiled\n", scText(info->dpy, si)); 3569 return False; 3570 } 3571 section->top = si->top; 3572 section->left = si->left; 3573 section->width = si->width; 3574 section->height = si->height; 3575 section->angle = si->angle; 3576 section->priority = si->priority; 3577 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next) 3578 { 3579 row = XkbAddGeomRow(section, ri->nKeys); 3580 if (row == NULL) 3581 { 3582 WSGO("Couldn't allocate row in section\n"); 3583 ACTION("Section %s is incomplete\n", scText(info->dpy, si)); 3584 return False; 3585 } 3586 row->top = ri->top; 3587 row->left = ri->left; 3588 row->vertical = ri->vertical; 3589 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next) 3590 { 3591 XkbColorPtr color; 3592 if ((ki->defs.defined & _GK_Name) == 0) 3593 { 3594 ERROR("Key %d of row %d in section %s has no name\n", 3595 (int) ki->index, (int) ri->index, 3596 scText(info->dpy, si)); 3597 ACTION("Section %s ignored\n", scText(info->dpy, si)); 3598 return False; 3599 } 3600 key = XkbAddGeomKey(row); 3601 if (key == NULL) 3602 { 3603 WSGO("Couldn't allocate key in row\n"); 3604 ACTION("Section %s is incomplete\n", scText(info->dpy, si)); 3605 return False; 3606 } 3607 memcpy(key->name.name, ki->name, XkbKeyNameLength); 3608 key->gap = ki->gap; 3609 if (ki->shape == None) 3610 key->shape_ndx = 0; 3611 else 3612 { 3613 ShapeInfo *sinfo; 3614 sinfo = FindShape(info, ki->shape, "key", keyText(ki)); 3615 if (!sinfo) 3616 return False; 3617 key->shape_ndx = sinfo->index; 3618 } 3619 if (ki->color != None) 3620 color = 3621 XkbAddGeomColor(geom, 3622 XkbAtomGetString(NULL, ki->color), 3623 geom->num_colors); 3624 else 3625 color = XkbAddGeomColor(geom, "white", geom->num_colors); 3626 XkbSetKeyColor(geom, key, color); 3627 } 3628 } 3629 if (si->doodads != NULL) 3630 { 3631 DoodadInfo *di; 3632 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next) 3633 { 3634 CopyDoodadDef(geom, section, di, info); 3635 } 3636 } 3637 if (si->overlays != NULL) 3638 { 3639 OverlayInfo *oi; 3640 for (oi = si->overlays; oi != NULL; 3641 oi = (OverlayInfo *) oi->defs.next) 3642 { 3643 CopyOverlayDef(geom, section, oi, info); 3644 } 3645 } 3646 if (XkbComputeSectionBounds(geom, section)) 3647 { 3648 /* 7/6/94 (ef) -- check for negative origin and translate */ 3649 if ((si->defs.defined & _GS_Width) == 0) 3650 section->width = section->bounds.x2; 3651 if ((si->defs.defined & _GS_Height) == 0) 3652 section->height = section->bounds.y2; 3653 } 3654 return True; 3655} 3656 3657/***====================================================================***/ 3658 3659Bool 3660CompileGeometry(XkbFile * file, XkbFileInfo * result, unsigned merge) 3661{ 3662 GeometryInfo info; 3663 XkbDescPtr xkb; 3664 3665 xkb = result->xkb; 3666 InitGeometryInfo(&info, file->id, merge); 3667 info.dpy = xkb->dpy; 3668 HandleGeometryFile(file, xkb, merge, &info); 3669 3670 if (info.errorCount == 0) 3671 { 3672 XkbGeometryPtr geom; 3673 XkbGeometrySizesRec sizes; 3674 bzero(&sizes, sizeof(sizes)); 3675 sizes.which = XkbGeomAllMask; 3676 sizes.num_properties = info.nProps; 3677 sizes.num_colors = 8; 3678 sizes.num_shapes = info.nShapes; 3679 sizes.num_sections = info.nSections; 3680 sizes.num_doodads = info.nDoodads; 3681 if (XkbAllocGeometry(xkb, &sizes) != Success) 3682 { 3683 WSGO("Couldn't allocate GeometryRec\n"); 3684 ACTION("Geometry not compiled\n"); 3685 return False; 3686 } 3687 geom = xkb->geom; 3688 3689 geom->width_mm = info.widthMM; 3690 geom->height_mm = info.heightMM; 3691 if (info.name != NULL) 3692 { 3693 geom->name = XkbInternAtom(xkb->dpy, info.name, False); 3694 if (XkbAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success) 3695 xkb->names->geometry = geom->name; 3696 } 3697 if (info.fontSpec != None) 3698 geom->label_font = 3699 uStringDup(XkbAtomGetString(NULL, info.fontSpec)); 3700 else 3701 geom->label_font = FontFromParts(info.font, info.fontWeight, 3702 info.fontSlant, 3703 info.fontSetWidth, 3704 info.fontVariant, 3705 info.fontSize, 3706 info.fontEncoding); 3707 XkbAddGeomColor(geom, "black", geom->num_colors); 3708 XkbAddGeomColor(geom, "white", geom->num_colors); 3709 3710 if (info.baseColor == None) 3711 info.baseColor = XkbInternAtom(NULL, "white", False); 3712 if (info.labelColor == None) 3713 info.labelColor = XkbInternAtom(NULL, "black", False); 3714 geom->base_color = 3715 XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.baseColor), 3716 geom->num_colors); 3717 geom->label_color = 3718 XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.labelColor), 3719 geom->num_colors); 3720 3721 if (info.props) 3722 { 3723 PropertyInfo *pi; 3724 for (pi = info.props; pi != NULL; 3725 pi = (PropertyInfo *) pi->defs.next) 3726 { 3727 if (!XkbAddGeomProperty(geom, pi->name, pi->value)) 3728 return False; 3729 } 3730 } 3731 if (info.shapes) 3732 { 3733 ShapeInfo *si; 3734 for (si = info.shapes; si != NULL; 3735 si = (ShapeInfo *) si->defs.next) 3736 { 3737 if (!CopyShapeDef(xkb->dpy, geom, si)) 3738 return False; 3739 } 3740 } 3741 if (info.sections) 3742 { 3743 SectionInfo *si; 3744 for (si = info.sections; si != NULL; 3745 si = (SectionInfo *) si->defs.next) 3746 { 3747 if (!CopySectionDef(geom, si, &info)) 3748 return False; 3749 } 3750 } 3751 if (info.doodads) 3752 { 3753 DoodadInfo *di; 3754 for (di = info.doodads; di != NULL; 3755 di = (DoodadInfo *) di->defs.next) 3756 { 3757 if (!CopyDoodadDef(geom, NULL, di, &info)) 3758 return False; 3759 } 3760 } 3761 if (info.aliases) 3762 ApplyAliases(xkb, True, &info.aliases); 3763 ClearGeometryInfo(&info); 3764 return True; 3765 } 3766 return False; 3767} 3768