1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
34 #include "indicators.h"
38 #include "parseutils.h"
40 #define DFLT_FONT "helvetica"
41 #define DFLT_SLANT "r"
42 #define DFLT_WEIGHT "medium"
43 #define DFLT_SET_WIDTH "normal"
44 #define DFLT_VARIANT ""
45 #define DFLT_ENCODING "iso8859-1"
48 typedef struct _PropertyInfo
55 #define _GSh_Outlines (1<<1)
56 #define _GSh_Approx (1<<2)
57 #define _GSh_Primary (1<<3)
58 typedef struct _ShapeInfo
63 unsigned short nOutlines;
64 unsigned short szOutlines;
65 struct xkb_outline * outlines;
66 struct xkb_outline * approx;
67 struct xkb_outline * primary;
72 ((s) ? XkbcAtomText((s)->name) : "default shape")
74 #define _GD_Priority (1<<0)
75 #define _GD_Top (1<<1)
76 #define _GD_Left (1<<2)
77 #define _GD_Angle (1<<3)
78 #define _GD_Shape (1<<4)
79 #define _GD_FontVariant (1<<4) /* CHEATING */
80 #define _GD_Corner (1<<5)
81 #define _GD_Width (1<<5) /* CHEATING */
82 #define _GD_Color (1<<6)
83 #define _GD_OffColor (1<<7)
84 #define _GD_Height (1<<7) /* CHEATING */
85 #define _GD_Text (1<<8)
86 #define _GD_Font (1<<9)
87 #define _GD_FontSlant (1<<10)
88 #define _GD_FontWeight (1<<11)
89 #define _GD_FontSetWidth (1<<12)
90 #define _GD_FontSize (1<<13)
91 #define _GD_FontEncoding (1<<14)
92 #define _GD_FontSpec (1<<15)
95 #define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
97 typedef struct _DoodadInfo
102 unsigned char priority;
106 unsigned short corner;
107 unsigned short width;
108 unsigned short height;
116 uint32_t fontSetWidth;
117 uint32_t fontVariant;
118 unsigned short fontSize;
119 uint32_t fontEncoding;
122 struct _SectionInfo *section;
129 #define _GK_Default (1<<0)
130 #define _GK_Name (1<<1)
131 #define _GK_Gap (1<<2)
132 #define _GK_Shape (1<<3)
133 #define _GK_Color (1<<4)
134 typedef struct _KeyInfo
142 struct _RowInfo *row;
144 #define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
146 #define _GR_Default (1<<0)
147 #define _GR_Vertical (1<<1)
148 #define _GR_Top (1<<2)
149 #define _GR_Left (1<<3)
150 typedef struct _RowInfo
157 unsigned short nKeys;
160 struct _SectionInfo *section;
163 ((r) ? XkbcAtomText((r)->section->name) : "default")
165 #define _GOK_UnknownRow -1
166 typedef struct _OverlayKeyInfo
171 char over[XkbKeyNameLength + 1];
172 char under[XkbKeyNameLength + 1];
175 typedef struct _OverlayInfo
179 unsigned short nRows;
180 unsigned short nKeys;
181 OverlayKeyInfo *keys;
184 ((o) ? XkbcAtomText((o)->name) : "default")
187 #define _GS_Default (1<<0)
188 #define _GS_Name (1<<1)
189 #define _GS_Top (1<<2)
190 #define _GS_Left (1<<3)
191 #define _GS_Width (1<<4)
192 #define _GS_Height (1<<5)
193 #define _GS_Angle (1<<6)
194 #define _GS_Priority (1<<7)
195 typedef struct _SectionInfo
201 unsigned short width;
202 unsigned short height;
203 unsigned short angle;
204 unsigned short nRows;
205 unsigned short nDoodads;
206 unsigned short nOverlays;
207 unsigned char priority;
208 unsigned char nextDoodadPriority;
212 DoodadInfo *dfltDoodads;
213 OverlayInfo *overlays;
214 struct _GeometryInfo *geometry;
217 ((s) ? XkbcAtomText((s)->name) : "default")
219 typedef struct _GeometryInfo
225 unsigned nextPriority;
232 SectionInfo *sections;
239 uint32_t fontSetWidth;
240 uint32_t fontVariant;
242 uint32_t fontEncoding;
246 int dfltCornerRadius;
247 SectionInfo dfltSection;
248 DoodadInfo *dfltDoodads;
253 ddText(DoodadInfo * di)
259 strcpy(buf, "default");
264 sprintf(buf, "%s in section %s",
265 XkbcAtomText(di->name), scText(di->section));
268 return XkbcAtomText(di->name);
271 /***====================================================================***/
274 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
276 pi->defs.defined = 0;
277 pi->defs.fileID = info->fileID;
278 pi->defs.merge = info->merge;
279 pi->name = pi->value = NULL;
283 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
288 if (info->props == pi)
293 for (tmp = pi; tmp != NULL; tmp = next)
297 tmp->name = tmp->value = NULL;
298 next = (PropertyInfo *) tmp->defs.next;
304 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
307 if (key != &row->dfltKey)
310 strcpy(key->name, "unknown");
311 key->defs.defined &= ~_GK_Default;
315 memset(key, 0, sizeof(KeyInfo));
316 strcpy(key->name, "default");
317 key->defs.defined = _GK_Default;
318 key->defs.fileID = info->fileID;
319 key->defs.merge = info->merge;
320 key->defs.next = NULL;
326 ClearKeyInfo(KeyInfo * key)
328 key->defs.defined &= ~_GK_Default;
329 strcpy(key->name, "default");
336 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
341 if (row->keys == key)
346 for (tmp = key; tmp != NULL; tmp = next)
349 next = (KeyInfo *) tmp->defs.next;
355 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
357 if (row != §ion->dfltRow)
359 *row = section->dfltRow;
360 row->defs.defined &= ~_GR_Default;
364 memset(row, 0, sizeof(RowInfo));
365 row->defs.defined = _GR_Default;
366 row->defs.fileID = info->fileID;
367 row->defs.merge = info->merge;
368 row->defs.next = NULL;
369 row->section = section;
372 InitKeyInfo(&row->dfltKey, row, info);
377 ClearRowInfo(RowInfo * row, GeometryInfo * info)
379 row->defs.defined &= ~_GR_Default;
380 row->top = row->left = 0;
381 row->vertical = False;
384 FreeKeys(row->keys, row, info);
385 ClearKeyInfo(&row->dfltKey);
386 row->dfltKey.defs.defined |= _GK_Default;
390 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
395 if (row == section->rows)
398 section->rows = NULL;
400 for (tmp = row; tmp != NULL; tmp = next)
402 ClearRowInfo(tmp, info);
403 next = (RowInfo *) tmp->defs.next;
409 FindDoodadByType(DoodadInfo * di, unsigned type)
413 if (di->type == type)
415 di = (DoodadInfo *) di->defs.next;
421 FindDoodadByName(DoodadInfo * di, uint32_t name)
425 if (di->name == name)
427 di = (DoodadInfo *) di->defs.next;
433 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
439 if (si && si->dfltDoodads)
440 dflt = FindDoodadByType(si->dfltDoodads, type);
441 if ((dflt == NULL) && (info->dfltDoodads))
442 dflt = FindDoodadByType(info->dfltDoodads, type);
446 di->defs.next = NULL;
450 memset(di, 0, sizeof(DoodadInfo));
451 di->defs.fileID = info->fileID;
457 di->priority = si->nextDoodadPriority++;
458 #if XkbGeomMaxPriority < 255
459 if (si->nextDoodadPriority > XkbGeomMaxPriority)
460 si->nextDoodadPriority = XkbGeomMaxPriority;
465 di->priority = info->nextPriority++;
466 if (info->nextPriority > XkbGeomMaxPriority)
467 info->nextPriority = XkbGeomMaxPriority;
472 ClearDoodadInfo(DoodadInfo * di)
477 memset(di, 0, sizeof(DoodadInfo));
479 di->defs.defined = 0;
483 ClearOverlayInfo(OverlayInfo * ol)
487 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
493 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
500 if (si->doodads == di)
505 if (si->dfltDoodads == di)
506 si->dfltDoodads = NULL;
508 if (info->doodads == di)
510 info->doodads = NULL;
513 if (info->dfltDoodads == di)
514 info->dfltDoodads = NULL;
515 for (tmp = di; tmp != NULL; tmp = next)
517 next = (DoodadInfo *) tmp->defs.next;
518 ClearDoodadInfo(tmp);
524 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
526 if (si != &info->dfltSection)
528 *si = info->dfltSection;
529 si->defs.defined &= ~_GS_Default;
530 si->name = xkb_intern_atom("unknown");
531 si->priority = info->nextPriority++;
532 if (info->nextPriority > XkbGeomMaxPriority)
533 info->nextPriority = XkbGeomMaxPriority;
537 memset(si, 0, sizeof(SectionInfo));
538 si->defs.fileID = info->fileID;
539 si->defs.merge = info->merge;
540 si->defs.next = NULL;
542 si->name = xkb_intern_atom("default");
543 InitRowInfo(&si->dfltRow, si, info);
548 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
554 into->defs.next = NULL;
555 into->dfltRow.defs.fileID = defs.fileID;
556 into->dfltRow.defs.merge = defs.merge;
557 into->dfltRow.defs.next = NULL;
558 into->dfltRow.section = into;
559 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
560 into->dfltRow.dfltKey.defs.merge = defs.merge;
561 into->dfltRow.dfltKey.defs.next = NULL;
562 into->dfltRow.dfltKey.row = &into->dfltRow;
566 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
569 si->defs.defined &= ~_GS_Default;
570 si->name = xkb_intern_atom("default");
571 si->top = si->left = 0;
572 si->width = si->height = 0;
576 FreeRows(si->rows, si, info);
579 ClearRowInfo(&si->dfltRow, info);
582 FreeDoodads(si->doodads, si, info);
585 si->dfltRow.defs.defined = _GR_Default;
589 FreeSections(SectionInfo * si, GeometryInfo * info)
594 if (si == info->sections)
597 info->sections = NULL;
599 for (tmp = si; tmp != NULL; tmp = next)
601 ClearSectionInfo(tmp, info);
602 next = (SectionInfo *) tmp->defs.next;
608 FreeShapes(ShapeInfo * si, GeometryInfo * info)
613 if (si == info->shapes)
618 for (tmp = si; tmp != NULL; tmp = next)
623 for (i = 0; i < tmp->nOutlines; i++)
625 if (tmp->outlines[i].points != NULL)
627 free(tmp->outlines[i].points);
628 tmp->outlines[i].num_points = 0;
629 tmp->outlines[i].points = NULL;
635 tmp->outlines = NULL;
636 tmp->primary = tmp->approx = NULL;
638 next = (ShapeInfo *) tmp->defs.next;
643 /***====================================================================***/
646 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
648 memset(info, 0, sizeof(GeometryInfo));
649 info->fileID = fileID;
651 InitSectionInfo(&info->dfltSection, info);
652 info->dfltSection.defs.defined = _GS_Default;
656 ClearGeometryInfo(GeometryInfo * info)
661 FreeProperties(info->props, info);
663 FreeShapes(info->shapes, info);
665 FreeSections(info->sections, info);
668 info->dfltCornerRadius = 0;
669 ClearSectionInfo(&info->dfltSection, info);
670 info->dfltSection.defs.defined = _GS_Default;
672 ClearAliases(&info->aliases);
675 /***====================================================================***/
677 static PropertyInfo *
678 NextProperty(GeometryInfo * info)
682 pi = uTypedAlloc(PropertyInfo);
685 memset(pi, 0, sizeof(PropertyInfo));
686 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
693 static PropertyInfo *
694 FindProperty(GeometryInfo * info, char *name)
700 for (old = info->props; old != NULL;
701 old = (PropertyInfo *) old->defs.next)
703 if ((old->name) && (uStringEqual(name, old->name)))
710 AddProperty(GeometryInfo * info, PropertyInfo * new)
714 if ((!new) || (!new->value) || (!new->name))
716 old = FindProperty(info, new->name);
719 if ((new->defs.merge == MergeReplace)
720 || (new->defs.merge == MergeOverride))
722 if (((old->defs.fileID == new->defs.fileID)
723 && (warningLevel > 0)) || (warningLevel > 9))
725 WARN("Multiple definitions for the \"%s\" property\n",
727 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
731 old->value = _XkbDupString(new->value);
734 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
735 || (warningLevel > 9))
737 WARN("Multiple definitions for \"%s\" property\n", new->name);
738 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
744 if ((new = NextProperty(info)) == NULL)
746 new->defs.next = NULL;
747 new->name = _XkbDupString(old->name);
748 new->value = _XkbDupString(old->value);
752 /***====================================================================***/
755 NextShape(GeometryInfo * info)
759 si = uTypedAlloc(ShapeInfo);
762 memset(si, 0, sizeof(ShapeInfo));
763 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
766 si->dfltCornerRadius = info->dfltCornerRadius;
772 FindShape(GeometryInfo * info, uint32_t name, const char *type, const char *which)
776 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
778 if (name == old->name)
784 WARN("Unknown shape \"%s\" for %s %s\n",
785 XkbcAtomText(name), type, which);
788 ACTION("Using default shape %s instead\n", shText(old));
791 ACTION("No default shape; definition ignored\n");
798 AddShape(GeometryInfo * info, ShapeInfo * new)
802 old = FindShape(info, new->name, NULL, NULL);
805 if ((new->defs.merge == MergeReplace)
806 || (new->defs.merge == MergeOverride))
808 ShapeInfo *next = (ShapeInfo *) old->defs.next;
809 if (((old->defs.fileID == new->defs.fileID)
810 && (warningLevel > 0)) || (warningLevel > 9))
812 WARN("Duplicate shape name \"%s\"\n", shText(old));
813 ACTION("Using last definition\n");
816 old->defs.next = &next->defs;
819 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
820 || (warningLevel > 9))
822 WARN("Multiple shapes named \"%s\"\n", shText(old));
823 ACTION("Using first definition\n");
828 if ((new = NextShape(info)) == NULL)
831 new->defs.next = NULL;
832 old->szOutlines = old->nOutlines = 0;
833 old->outlines = NULL;
839 /***====================================================================***/
842 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
846 next = into->defs.next;
847 ClearDoodadInfo(into);
849 into->defs.next = next;
850 next = from->defs.next;
851 ClearDoodadInfo(from);
852 from->defs.next = next;
856 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
860 di = uTypedCalloc(1, DoodadInfo);
866 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
872 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
879 NextDoodad(SectionInfo * si, GeometryInfo * info)
883 di = uTypedCalloc(1, DoodadInfo);
888 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
895 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
904 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
908 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
911 if ((new->defs.merge == MergeReplace)
912 || (new->defs.merge == MergeOverride))
914 if (((old->defs.fileID == new->defs.fileID)
915 && (warningLevel > 0)) || (warningLevel > 9))
917 WARN("Multiple doodads named \"%s\"\n",
918 XkbcAtomText(old->name));
919 ACTION("Using last definition\n");
921 ReplaceDoodad(old, new);
925 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
926 || (warningLevel > 9))
928 WARN("Multiple doodads named \"%s\"\n",
929 XkbcAtomText(old->name));
930 ACTION("Using first definition\n");
935 if ((new = NextDoodad(si, info)) == NULL)
937 ReplaceDoodad(new, old);
939 new->defs.next = NULL;
944 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
946 DoodadInfo *dflt = NULL;
949 if (uStrCaseCmp(name, "outline") == 0)
950 type = XkbOutlineDoodad;
951 else if (uStrCaseCmp(name, "solid") == 0)
952 type = XkbSolidDoodad;
953 else if (uStrCaseCmp(name, "text") == 0)
954 type = XkbTextDoodad;
955 else if (uStrCaseCmp(name, "indicator") == 0)
956 type = XkbIndicatorDoodad;
957 else if (uStrCaseCmp(name, "logo") == 0)
958 type = XkbLogoDoodad;
961 if ((si) && (si->dfltDoodads))
962 dflt = FindDoodadByType(si->dfltDoodads, type);
963 if ((!dflt) && (info->dfltDoodads))
964 dflt = FindDoodadByType(info->dfltDoodads, type);
967 dflt = NextDfltDoodad(si, info);
977 /***====================================================================***/
980 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
984 for (old = si->overlays; old != NULL;
985 old = (OverlayInfo *) old->defs.next)
987 if (old->name == new->name)
992 if ((new->defs.merge == MergeReplace)
993 || (new->defs.merge == MergeOverride))
995 if (((old->defs.fileID == new->defs.fileID)
996 && (warningLevel > 0)) || (warningLevel > 9))
999 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1000 XkbcAtomText(old->name), XkbcAtomText(si->name));
1001 ACTION("Using last definition\n");
1003 ClearOverlayInfo(old);
1004 old->nKeys = new->nKeys;
1005 old->keys = new->keys;
1010 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1011 || (warningLevel > 9))
1013 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1014 XkbcAtomText(old->name), XkbcAtomText(si->name));
1015 ACTION("Using first definition\n");
1020 new = uTypedCalloc(1, OverlayInfo);
1023 if (warningLevel > 0)
1025 WSGO("Couldn't allocate a new OverlayInfo\n");
1027 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1028 XkbcAtomText(old->name), XkbcAtomText(si->name));
1035 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1036 (CommonInfo *) new);
1041 /***====================================================================***/
1043 static SectionInfo *
1044 NextSection(GeometryInfo * info)
1048 si = uTypedAlloc(SectionInfo);
1051 *si = info->dfltSection;
1052 si->defs.defined &= ~_GS_Default;
1053 si->defs.next = NULL;
1057 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1064 static SectionInfo *
1065 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1069 for (old = info->sections; old != NULL;
1070 old = (SectionInfo *) old->defs.next)
1072 if (new->name == old->name)
1079 AddSection(GeometryInfo * info, SectionInfo * new)
1083 old = FindMatchingSection(info, new);
1087 if ((new->defs.merge == MergeReplace)
1088 || (new->defs.merge == MergeOverride))
1090 SectionInfo *next = (SectionInfo *) old->defs.next;
1091 if (((old->defs.fileID == new->defs.fileID)
1092 && (warningLevel > 0)) || (warningLevel > 9))
1094 WARN("Duplicate shape name \"%s\"\n", shText(old));
1095 ACTION("Using last definition\n");
1098 old->defs.next = &next->defs;
1101 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1102 || (warningLevel > 9))
1104 WARN("Multiple shapes named \"%s\"\n", shText(old));
1105 ACTION("Using first definition\n");
1109 WARN("Don't know how to merge sections yet\n");
1113 if ((new = NextSection(info)) == NULL)
1116 new->defs.next = NULL;
1117 old->nRows = old->nDoodads = old->nOverlays = 0;
1119 old->doodads = NULL;
1120 old->overlays = NULL;
1124 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1132 /***====================================================================***/
1135 NextRow(SectionInfo * si)
1139 row = uTypedAlloc(RowInfo);
1143 row->defs.defined &= ~_GR_Default;
1144 row->defs.next = NULL;
1148 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1149 row->index = si->nRows++;
1155 AddRow(SectionInfo * si, RowInfo * new)
1160 if ((new = NextRow(si)) == NULL)
1163 new->defs.next = NULL;
1169 /***====================================================================***/
1172 NextKey(RowInfo * row)
1176 key = uTypedAlloc(KeyInfo);
1179 *key = row->dfltKey;
1180 key->defs.defined &= ~_GK_Default;
1181 key->defs.next = NULL;
1182 key->index = row->nKeys++;
1188 AddKey(RowInfo * row, KeyInfo * new)
1193 if ((new = NextKey(row)) == NULL)
1196 new->defs.next = NULL;
1198 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1202 /***====================================================================***/
1205 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1210 if (from->errorCount > 0)
1212 into->errorCount += from->errorCount;
1215 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1216 if (into->name == NULL)
1218 into->name = from->name;
1221 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1222 into->widthMM = from->widthMM;
1223 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1224 into->heightMM = from->heightMM;
1225 if ((into->font == None) || ((from->font != None) && clobber))
1226 into->font = from->font;
1227 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1228 into->fontSlant = from->fontSlant;
1229 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1230 into->fontWeight = from->fontWeight;
1231 if ((into->fontSetWidth == None)
1232 || ((from->fontSetWidth != None) && clobber))
1233 into->fontSetWidth = from->fontSetWidth;
1234 if ((into->fontVariant == None)
1235 || ((from->fontVariant != None) && clobber))
1236 into->fontVariant = from->fontVariant;
1237 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1238 into->fontSize = from->fontSize;
1239 if ((into->fontEncoding == None)
1240 || ((from->fontEncoding != None) && clobber))
1241 into->fontEncoding = from->fontEncoding;
1242 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1243 into->fontSpec = from->fontSpec;
1244 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1245 into->baseColor = from->baseColor;
1246 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1247 into->labelColor = from->labelColor;
1248 into->nextPriority = from->nextPriority;
1249 if (from->props != NULL)
1252 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1254 if (!AddProperty(into, pi))
1258 if (from->shapes != NULL)
1262 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1264 if (!AddShape(into, si))
1268 if (from->sections != NULL)
1272 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1274 if (!AddSection(into, si))
1278 if (from->doodads != NULL)
1282 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1284 if (!AddDoodad(NULL, into, di))
1288 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1292 typedef void (*FileHandler) (XkbFile * /* file */ ,
1293 struct xkb_desc * /* xkb */ ,
1294 unsigned /* merge */ ,
1295 GeometryInfo * /* info */
1299 HandleIncludeGeometry(IncludeStmt * stmt, struct xkb_desc * xkb, GeometryInfo * info,
1304 GeometryInfo included;
1308 if ((stmt->file == NULL) && (stmt->map == NULL))
1312 memset(info, 0, sizeof(GeometryInfo));
1314 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1316 InitGeometryInfo(&included, rtrn->id, newMerge);
1317 included.nextPriority = info->nextPriority;
1318 included.dfltCornerRadius = info->dfltCornerRadius;
1319 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1320 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1321 if (stmt->stmt != NULL)
1323 free(included.name);
1324 included.name = stmt->stmt;
1331 info->errorCount += 10;
1334 if ((stmt->next != NULL) && (included.errorCount < 1))
1338 GeometryInfo next_incl;
1340 for (next = stmt->next; next != NULL; next = next->next)
1342 if ((next->file == NULL) && (next->map == NULL))
1345 MergeIncludedGeometry(&included, info, next->merge);
1346 ClearGeometryInfo(info);
1348 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1350 InitGeometryInfo(&next_incl, rtrn->id, op);
1351 next_incl.nextPriority = included.nextPriority;
1352 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1353 DupSectionInfo(&next_incl.dfltSection,
1354 &included.dfltSection, &included);
1355 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1356 MergeIncludedGeometry(&included, &next_incl, op);
1357 ClearGeometryInfo(&next_incl);
1362 info->errorCount += 10;
1371 MergeIncludedGeometry(info, &included, newMerge);
1372 ClearGeometryInfo(&included);
1374 return (info->errorCount == 0);
1378 SetShapeField(ShapeInfo * si,
1380 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1384 if ((uStrCaseCmp(field, "radius") == 0)
1385 || (uStrCaseCmp(field, "corner") == 0)
1386 || (uStrCaseCmp(field, "cornerradius") == 0))
1388 if (arrayNdx != NULL)
1391 return ReportNotArray("key shape", field, shText(si));
1393 if (!ExprResolveFloat(value, &tmp))
1396 return ReportBadType("key shape", field, shText(si), "number");
1399 si->dfltCornerRadius = tmp.ival;
1401 info->dfltCornerRadius = tmp.ival;
1405 return ReportBadField("key shape", field, shText(si));
1409 SetShapeDoodadField(DoodadInfo * di,
1412 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1415 const char *typeName;
1418 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1419 if ((!uStrCaseCmp(field, "corner"))
1420 || (!uStrCaseCmp(field, "cornerradius")))
1422 if (arrayNdx != NULL)
1425 return ReportNotArray(typeName, field, ddText(di));
1427 if (!ExprResolveFloat(value, &tmp))
1430 return ReportBadType(typeName, field, ddText(di), "number");
1432 di->defs.defined |= _GD_Corner;
1433 di->corner = tmp.ival;
1436 else if (uStrCaseCmp(field, "angle") == 0)
1438 if (arrayNdx != NULL)
1441 return ReportNotArray(typeName, field, ddText(di));
1443 if (!ExprResolveFloat(value, &tmp))
1446 return ReportBadType(typeName, field, ddText(di), "number");
1448 di->defs.defined |= _GD_Angle;
1449 di->angle = tmp.ival;
1452 else if (uStrCaseCmp(field, "shape") == 0)
1454 if (arrayNdx != NULL)
1457 return ReportNotArray(typeName, field, ddText(di));
1459 if (!ExprResolveString(value, &tmp))
1462 return ReportBadType(typeName, field, ddText(di), "string");
1464 di->shape = xkb_intern_atom(tmp.str);
1465 di->defs.defined |= _GD_Shape;
1469 return ReportBadField(typeName, field, ddText(di));
1472 #define FIELD_STRING 0
1473 #define FIELD_SHORT 1
1474 #define FIELD_USHORT 2
1477 SetTextDoodadField(DoodadInfo * di,
1480 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1485 const char *typeName = "text doodad";
1490 unsigned short *uval;
1493 if (uStrCaseCmp(field, "angle") == 0)
1495 if (arrayNdx != NULL)
1498 return ReportNotArray(typeName, field, ddText(di));
1500 if (!ExprResolveFloat(value, &tmp))
1503 return ReportBadType(typeName, field, ddText(di), "number");
1505 di->defs.defined |= _GD_Angle;
1506 di->angle = tmp.ival;
1509 if (uStrCaseCmp(field, "width") == 0)
1511 type = FIELD_USHORT;
1512 pField.uval = &di->width;
1515 else if (uStrCaseCmp(field, "height") == 0)
1517 type = FIELD_USHORT;
1518 pField.uval = &di->height;
1521 else if (uStrCaseCmp(field, "text") == 0)
1523 type = FIELD_STRING;
1524 pField.str = &di->text;
1527 else if (uStrCaseCmp(field, "font") == 0)
1529 type = FIELD_STRING;
1530 pField.str = &di->font;
1533 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1534 (uStrCaseCmp(field, "slant") == 0))
1536 type = FIELD_STRING;
1537 pField.str = &di->fontSlant;
1538 def = _GD_FontSlant;
1540 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1541 (uStrCaseCmp(field, "weight") == 0))
1543 type = FIELD_STRING;
1544 pField.str = &di->fontWeight;
1545 def = _GD_FontWeight;
1547 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1548 (uStrCaseCmp(field, "setwidth") == 0))
1550 type = FIELD_STRING;
1551 pField.str = &di->fontSetWidth;
1552 def = _GD_FontSetWidth;
1554 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1555 (uStrCaseCmp(field, "variant") == 0))
1557 type = FIELD_STRING;
1558 pField.str = &di->fontVariant;
1559 def = _GD_FontVariant;
1561 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1562 (uStrCaseCmp(field, "encoding") == 0))
1564 type = FIELD_STRING;
1565 pField.str = &di->fontEncoding;
1566 def = _GD_FontEncoding;
1568 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1569 (uStrCaseCmp(field, "xfontname") == 0))
1571 type = FIELD_STRING;
1572 pField.str = &di->fontSpec;
1575 else if (uStrCaseCmp(field, "fontsize") == 0)
1577 type = FIELD_USHORT;
1578 pField.uval = &di->fontSize;
1583 return ReportBadField(typeName, field, ddText(di));
1585 if (arrayNdx != NULL)
1588 return ReportNotArray(typeName, field, ddText(di));
1590 if (type == FIELD_STRING)
1592 if (!ExprResolveString(value, &tmp))
1595 return ReportBadType(typeName, field, ddText(di), "string");
1597 di->defs.defined |= def;
1598 *pField.str = xkb_intern_atom(tmp.str);
1603 if (!ExprResolveFloat(value, &tmp))
1606 return ReportBadType(typeName, field, ddText(di), "number");
1608 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1612 ReportBadType(typeName, field, ddText(di), "unsigned");
1614 di->defs.defined |= def;
1615 if (type == FIELD_USHORT)
1616 *pField.uval = tmp.uval;
1618 *pField.ival = tmp.ival;
1624 SetIndicatorDoodadField(DoodadInfo * di,
1628 SectionInfo * si, GeometryInfo * info)
1632 if ((uStrCaseCmp(field, "oncolor") == 0)
1633 || (uStrCaseCmp(field, "offcolor") == 0)
1634 || (uStrCaseCmp(field, "shape") == 0))
1636 if (arrayNdx != NULL)
1639 return ReportNotArray("indicator doodad", field, ddText(di));
1641 if (!ExprResolveString(value, &tmp))
1644 return ReportBadType("indicator doodad", field,
1645 ddText(di), "string");
1647 if (uStrCaseCmp(field, "oncolor") == 0)
1649 di->defs.defined |= _GD_Color;
1650 di->color = xkb_intern_atom(tmp.str);
1652 else if (uStrCaseCmp(field, "offcolor") == 0)
1654 di->defs.defined |= _GD_OffColor;
1655 di->offColor = xkb_intern_atom(tmp.str);
1657 else if (uStrCaseCmp(field, "shape") == 0)
1659 di->defs.defined |= _GD_Shape;
1660 di->shape = xkb_intern_atom(tmp.str);
1665 return ReportBadField("indicator doodad", field, ddText(di));
1669 SetLogoDoodadField(DoodadInfo * di,
1672 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1675 const char *typeName = "logo doodad";
1677 if ((!uStrCaseCmp(field, "corner"))
1678 || (!uStrCaseCmp(field, "cornerradius")))
1680 if (arrayNdx != NULL)
1683 return ReportNotArray(typeName, field, ddText(di));
1685 if (!ExprResolveFloat(value, &tmp))
1688 return ReportBadType(typeName, field, ddText(di), "number");
1690 di->defs.defined |= _GD_Corner;
1691 di->corner = tmp.ival;
1694 else if (uStrCaseCmp(field, "angle") == 0)
1696 if (arrayNdx != NULL)
1699 return ReportNotArray(typeName, field, ddText(di));
1701 if (!ExprResolveFloat(value, &tmp))
1704 return ReportBadType(typeName, field, ddText(di), "number");
1706 di->defs.defined |= _GD_Angle;
1707 di->angle = tmp.ival;
1710 else if (uStrCaseCmp(field, "shape") == 0)
1712 if (arrayNdx != NULL)
1715 return ReportNotArray(typeName, field, ddText(di));
1717 if (!ExprResolveString(value, &tmp))
1720 return ReportBadType(typeName, field, ddText(di), "string");
1722 di->shape = xkb_intern_atom(tmp.str);
1724 di->defs.defined |= _GD_Shape;
1727 else if ((!uStrCaseCmp(field, "logoname"))
1728 || (!uStrCaseCmp(field, "name")))
1730 if (arrayNdx != NULL)
1733 return ReportNotArray(typeName, field, ddText(di));
1735 if (!ExprResolveString(value, &tmp))
1738 return ReportBadType(typeName, field, ddText(di),
1741 di->logoName = _XkbDupString(tmp.str);
1745 return ReportBadField(typeName, field, ddText(di));
1749 SetDoodadField(DoodadInfo * di,
1752 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1756 if (uStrCaseCmp(field, "priority") == 0)
1758 if (arrayNdx != NULL)
1761 return ReportNotArray("doodad", field, ddText(di));
1763 if (!ExprResolveInteger(value, &tmp))
1766 return ReportBadType("doodad", field, ddText(di), "integer");
1768 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1771 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1772 tmp.ival, XkbGeomMaxPriority);
1773 ACTION("Priority for doodad %s not changed", ddText(di));
1776 di->defs.defined |= _GD_Priority;
1777 di->priority = tmp.ival;
1780 else if (uStrCaseCmp(field, "left") == 0)
1782 if (arrayNdx != NULL)
1785 return ReportNotArray("doodad", field, ddText(di));
1787 if (!ExprResolveFloat(value, &tmp))
1790 return ReportBadType("doodad", field, ddText(di), "number");
1792 di->defs.defined |= _GD_Left;
1793 di->left = tmp.ival;
1796 else if (uStrCaseCmp(field, "top") == 0)
1798 if (arrayNdx != NULL)
1801 return ReportNotArray("doodad", field, ddText(di));
1803 if (!ExprResolveFloat(value, &tmp))
1806 return ReportBadType("doodad", field, ddText(di), "number");
1808 di->defs.defined |= _GD_Top;
1812 else if (uStrCaseCmp(field, "color") == 0)
1814 if (arrayNdx != NULL)
1817 return ReportNotArray("doodad", field, ddText(di));
1819 if (!ExprResolveString(value, &tmp))
1822 return ReportBadType("doodad", field, ddText(di), "string");
1824 di->defs.defined |= _GD_Color;
1825 di->color = xkb_intern_atom(tmp.str);
1831 case XkbOutlineDoodad:
1832 case XkbSolidDoodad:
1833 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1835 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1836 case XkbIndicatorDoodad:
1837 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1839 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1841 WSGO("Unknown doodad type %d in SetDoodadField\n",
1842 (unsigned int) di->type);
1843 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1848 SetSectionField(SectionInfo * si,
1850 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1852 unsigned short *pField;
1857 if (uStrCaseCmp(field, "priority") == 0)
1859 if (arrayNdx != NULL)
1862 return ReportNotArray("keyboard section", field, scText(si));
1864 if (!ExprResolveInteger(value, &tmp))
1867 ReportBadType("keyboard section", field, scText(si), "integer");
1870 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1873 ERROR("Section priority %d out of range (must be 0..%d)\n",
1874 tmp.ival, XkbGeomMaxPriority);
1875 ACTION("Priority for section %s not changed", scText(si));
1878 si->priority = tmp.ival;
1879 si->defs.defined |= _GS_Priority;
1882 else if (uStrCaseCmp(field, "top") == 0)
1887 else if (uStrCaseCmp(field, "left") == 0)
1892 else if (uStrCaseCmp(field, "width") == 0)
1894 pField = &si->width;
1897 else if (uStrCaseCmp(field, "height") == 0)
1899 pField = &si->height;
1902 else if (uStrCaseCmp(field, "angle") == 0)
1904 pField = &si->angle;
1910 return ReportBadField("keyboard section", field, scText(si));
1912 if (arrayNdx != NULL)
1915 return ReportNotArray("keyboard section", field, scText(si));
1917 if (!ExprResolveFloat(value, &tmp))
1920 ReportBadType("keyboard section", field, scText(si), "number");
1923 si->defs.defined |= def;
1929 SetRowField(RowInfo * row,
1931 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1935 if (uStrCaseCmp(field, "top") == 0)
1937 if (arrayNdx != NULL)
1940 return ReportNotArray("keyboard row", field, rowText(row));
1942 if (!ExprResolveFloat(value, &tmp))
1945 return ReportBadType("keyboard row", field, rowText(row),
1948 row->defs.defined |= _GR_Top;
1949 row->top = tmp.uval;
1951 else if (uStrCaseCmp(field, "left") == 0)
1953 if (arrayNdx != NULL)
1956 return ReportNotArray("keyboard row", field, rowText(row));
1958 if (!ExprResolveFloat(value, &tmp))
1961 return ReportBadType("keyboard row", field, rowText(row),
1964 row->defs.defined |= _GR_Left;
1965 row->left = tmp.uval;
1967 else if (uStrCaseCmp(field, "vertical") == 0)
1969 if (arrayNdx != NULL)
1972 return ReportNotArray("keyboard row", field, rowText(row));
1974 if (!ExprResolveBoolean(value, &tmp))
1977 return ReportBadType("keyboard row", field, rowText(row),
1980 row->defs.defined |= _GR_Vertical;
1981 row->vertical = tmp.uval;
1986 return ReportBadField("keyboard row", field, rowText(row));
1992 SetKeyField(KeyInfo * key,
1994 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1998 if (uStrCaseCmp(field, "gap") == 0)
2000 if (arrayNdx != NULL)
2003 return ReportNotArray("key", field, keyText(key));
2005 if (!ExprResolveFloat(value, &tmp))
2008 return ReportBadType("key", field, keyText(key), "number");
2010 key->defs.defined |= _GK_Gap;
2011 key->gap = tmp.ival;
2013 else if (uStrCaseCmp(field, "shape") == 0)
2015 if (arrayNdx != NULL)
2018 return ReportNotArray("key", field, keyText(key));
2020 if (!ExprResolveString(value, &tmp))
2023 return ReportBadType("key", field, keyText(key), "string");
2025 key->defs.defined |= _GK_Shape;
2026 key->shape = xkb_intern_atom(tmp.str);
2029 else if ((uStrCaseCmp(field, "color") == 0) ||
2030 (uStrCaseCmp(field, "keycolor") == 0))
2032 if (arrayNdx != NULL)
2035 return ReportNotArray("key", field, keyText(key));
2037 if (!ExprResolveString(value, &tmp))
2040 return ReportBadType("key", field, keyText(key), "string");
2042 key->defs.defined |= _GK_Color;
2043 key->color = xkb_intern_atom(tmp.str);
2046 else if ((uStrCaseCmp(field, "name") == 0)
2047 || (uStrCaseCmp(field, "keyname") == 0))
2049 if (arrayNdx != NULL)
2052 return ReportNotArray("key", field, keyText(key));
2054 if (!ExprResolveKeyName(value, &tmp))
2057 return ReportBadType("key", field, keyText(key), "key name");
2059 key->defs.defined |= _GK_Name;
2060 memset(key->name, 0, XkbKeyNameLength + 1);
2061 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2066 return ReportBadField("key", field, keyText(key));
2072 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2078 InitPropertyInfo(&pi, info);
2080 if (!ExprResolveString(value, &result))
2083 ERROR("Property values must be type string\n");
2084 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2087 pi.value = result.str;
2088 ret = AddProperty(info, &pi);
2094 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2096 ExprResult elem, field, tmp;
2099 uint32_t *pField = NULL;
2100 int ret = True; /* default to no error */
2102 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2103 return 0; /* internal error, already reported */
2106 if (uStrCaseCmp(elem.str, "shape") == 0)
2107 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2108 else if (uStrCaseCmp(elem.str, "key") == 0)
2109 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2110 field.str, ndx, stmt->value, info);
2111 else if (uStrCaseCmp(elem.str, "row") == 0)
2112 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2114 else if (uStrCaseCmp(elem.str, "section") == 0)
2115 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2117 else if (uStrCaseCmp(elem.str, "property") == 0)
2122 ERROR("The %s geometry property is not an array\n", field.str);
2123 ACTION("Ignoring illegal property definition\n");
2127 ret = SetGeometryProperty(info, field.str, stmt->value);
2130 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2131 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2132 else if (uStrCaseCmp(elem.str, "solid") == 0)
2135 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2137 dflt = NextDfltDoodad(NULL, info);
2138 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2140 else if (uStrCaseCmp(elem.str, "outline") == 0)
2143 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2145 dflt = NextDfltDoodad(NULL, info);
2146 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2148 else if (uStrCaseCmp(elem.str, "text") == 0)
2151 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2153 dflt = NextDfltDoodad(NULL, info);
2154 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2156 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2159 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2161 dflt = NextDfltDoodad(NULL, info);
2162 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2164 else if (uStrCaseCmp(elem.str, "logo") == 0)
2167 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2169 dflt = NextDfltDoodad(NULL, info);
2170 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2174 WARN("Assignment to field of unknown element\n");
2175 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2183 if ((uStrCaseCmp(field.str, "width") == 0) ||
2184 (uStrCaseCmp(field.str, "widthmm") == 0))
2189 ret = ReportNotArray("keyboard", field.str, "geometry");
2191 else if (!ExprResolveFloat(stmt->value, &tmp))
2194 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2196 else if (tmp.ival < 1)
2198 WARN("Keyboard width must be positive\n");
2199 ACTION("Ignoring illegal keyboard width %s\n",
2200 XkbcGeomFPText(tmp.ival));
2204 if (info->widthMM != 0)
2206 WARN("Keyboard width multiply defined\n");
2207 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2208 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2210 info->widthMM = tmp.ival;
2216 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2217 (uStrCaseCmp(field.str, "heightmm") == 0))
2222 ret = ReportNotArray("keyboard", field.str, "geometry");
2224 else if (!ExprResolveFloat(stmt->value, &tmp))
2227 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2229 else if (tmp.ival < 1)
2231 WARN("Keyboard height must be positive\n");
2232 ACTION("Ignoring illegal keyboard height %s\n",
2233 XkbcGeomFPText(tmp.ival));
2237 if (info->heightMM != 0)
2239 WARN("Keyboard height multiply defined\n");
2240 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2241 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2243 info->heightMM = tmp.ival;
2249 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2254 ret = ReportNotArray("keyboard", field.str, "geometry");
2256 else if (!ExprResolveFloat(stmt->value, &tmp))
2259 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2261 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2264 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2265 ACTION("Ignoring font size in keyboard geometry\n");
2269 info->fontSize = tmp.ival;
2275 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2276 (uStrCaseCmp(field.str, "basecolor") == 0))
2281 ret = ReportNotArray("keyboard", field.str, "geometry");
2283 else if (!ExprResolveString(stmt->value, &tmp))
2286 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2289 info->baseColor = xkb_intern_atom(tmp.str);
2296 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2301 ret = ReportNotArray("keyboard", field.str, "geometry");
2303 else if (!ExprResolveString(stmt->value, &tmp))
2306 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2309 info->labelColor = xkb_intern_atom(tmp.str);
2316 else if (uStrCaseCmp(field.str, "font") == 0)
2318 pField = &info->font;
2320 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2321 (uStrCaseCmp(field.str, "slant") == 0))
2323 pField = &info->fontSlant;
2325 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2326 (uStrCaseCmp(field.str, "weight") == 0))
2328 pField = &info->fontWeight;
2330 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2331 (uStrCaseCmp(field.str, "setwidth") == 0))
2333 pField = &info->fontWeight;
2335 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2336 (uStrCaseCmp(field.str, "encoding") == 0))
2338 pField = &info->fontEncoding;
2340 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2341 (uStrCaseCmp(field.str, "xfontname") == 0))
2343 pField = &info->fontSpec;
2347 ret = SetGeometryProperty(info, field.str, stmt->value);
2352 /* fallthrough for the cases that set pField */
2356 ret = ReportNotArray("keyboard", field.str, "geometry");
2358 else if (!ExprResolveString(stmt->value, &tmp))
2361 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2364 *pField = xkb_intern_atom(tmp.str);
2371 /***====================================================================***/
2374 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2375 GeometryInfo * info)
2379 struct xkb_outline * outline;
2382 if (def->nOutlines < 1)
2384 WARN("Shape \"%s\" has no outlines\n", shText(si));
2385 ACTION("Definition ignored\n");
2388 si->nOutlines = def->nOutlines;
2389 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2392 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2393 ACTION("Definition ignored\n");
2397 for (nOut = 0, ol = def->outlines; ol != NULL;
2398 ol = (OutlineDef *) ol->common.next)
2400 if (ol->nPoints < 1)
2402 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2406 outline = &si->outlines[nOut++];
2407 outline->num_points = ol->nPoints;
2408 outline->corner_radius = si->dfltCornerRadius;
2409 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2410 if (!outline->points)
2412 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2413 ACTION("Definition ignored\n");
2418 for (nPt = 0, pt = ol->points; pt != NULL;
2419 pt = (ExprDef *) pt->common.next)
2421 outline->points[nPt].x = pt->value.coord.x;
2422 outline->points[nPt].y = pt->value.coord.y;
2425 if (ol->field != None)
2427 const char *str = XkbcAtomText(ol->field);
2428 if ((uStrCaseCmp(str, "approximation") == 0) ||
2429 (uStrCaseCmp(str, "approx") == 0))
2431 if (si->approx == NULL)
2432 si->approx = outline;
2435 WARN("Multiple approximations for \"%s\"\n",
2437 ACTION("Treating all but the first as normal outlines\n");
2440 else if (uStrCaseCmp(str, "primary") == 0)
2442 if (si->primary == NULL)
2443 si->primary = outline;
2446 WARN("Multiple primary outlines for \"%s\"\n",
2448 ACTION("Treating all but the first as normal outlines\n");
2453 WARN("Unknown outline type %s for \"%s\"\n", str,
2455 ACTION("Treated as a normal outline\n");
2459 if (nOut != si->nOutlines)
2461 WSGO("Expected %d outlines, got %d\n",
2462 (unsigned int) si->nOutlines, nOut);
2463 si->nOutlines = nOut;
2469 HandleShapeDef(ShapeDef * def, struct xkb_desc * xkb, unsigned merge,
2470 GeometryInfo * info)
2474 if (def->merge != MergeDefault)
2477 memset(&si, 0, sizeof(ShapeInfo));
2478 si.defs.merge = merge;
2479 si.name = def->name;
2480 si.dfltCornerRadius = info->dfltCornerRadius;
2481 if (!HandleShapeBody(def, &si, merge, info))
2483 if (!AddShape(info, &si))
2488 /***====================================================================***/
2491 HandleDoodadDef(DoodadDef * def,
2492 unsigned merge, SectionInfo * si, GeometryInfo * info)
2494 ExprResult elem, field;
2499 if (def->common.stmtType == StmtIndicatorMapDef)
2501 def->common.stmtType = StmtDoodadDef;
2502 def->type = XkbIndicatorDoodad;
2504 InitDoodadInfo(&new, def->type, si, info);
2505 new.name = def->name;
2506 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2508 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2509 return 0; /* internal error, already reported */
2510 if (elem.str != NULL)
2512 WARN("Assignment to field of unknown element in doodad %s\n",
2514 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2517 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2523 if (!AddDoodad(si, info, &new))
2525 ClearDoodadInfo(&new);
2529 /***====================================================================***/
2532 HandleOverlayDef(OverlayDef * def,
2533 unsigned merge, SectionInfo * si, GeometryInfo * info)
2535 OverlayKeyDef *keyDef;
2536 OverlayKeyInfo *key;
2539 if ((def->nKeys < 1) && (warningLevel > 3))
2541 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2542 XkbcAtomText(def->name), scText(si));
2543 ACTION("Overlay ignored\n");
2546 memset(&ol, 0, sizeof(OverlayInfo));
2547 ol.name = def->name;
2548 for (keyDef = def->keys; keyDef;
2549 keyDef = (OverlayKeyDef *) keyDef->common.next)
2551 key = uTypedCalloc(1, OverlayKeyInfo);
2554 if (warningLevel > 0)
2556 WSGO("Couldn't allocate OverlayKeyInfo\n");
2557 ACTION("Overlay %s for section %s will be incomplete\n",
2558 XkbcAtomText(ol.name), scText(si));
2562 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2563 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2564 key->sectionRow = _GOK_UnknownRow;
2565 key->overlayRow = _GOK_UnknownRow;
2566 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2567 (CommonInfo *) key);
2570 if (!AddOverlay(si, info, &ol))
2572 ClearOverlayInfo(&ol);
2576 /***====================================================================***/
2579 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2583 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2585 if (expr->op == OpAssign)
2589 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2590 return False; /* internal error, already reported */
2591 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2594 (key, f.str, ndx, expr->value.binary.right, info))
2605 ERROR("Illegal element used in a key definition\n");
2606 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2614 RowInfo *row = key->row;
2619 if (!SetKeyField(key, "gap", NULL, expr, info))
2623 if (!SetKeyField(key, "shape", NULL, expr, info))
2627 if (!SetKeyField(key, "name", NULL, expr, info))
2631 ERROR("Cannot determine field for unnamed expression\n");
2633 ACTION("Ignoring key %d in row %d of section %s\n",
2634 row->nKeys + 1, row->section->nRows + 1,
2644 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2645 GeometryInfo * info)
2649 if ((def->nKeys < 1) && (warningLevel > 3))
2651 ERROR("Row in section %s has no keys\n", rowText(row));
2652 ACTION("Section ignored\n");
2655 for (keyDef = def->keys; keyDef != NULL;
2656 keyDef = (KeyDef *) keyDef->common.next)
2658 if (keyDef->common.stmtType == StmtVarDef)
2660 VarDef *var = (VarDef *) keyDef;
2661 ExprResult elem, field;
2663 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2664 return 0; /* internal error, already reported */
2665 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2667 if (!SetRowField(row, field.str, ndx, var->value, info))
2670 else if (uStrCaseCmp(elem.str, "key") == 0)
2673 (&row->dfltKey, field.str, ndx, var->value, info))
2678 WARN("Assignment to field of unknown element in row\n");
2679 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2684 else if (keyDef->common.stmtType == StmtKeyDef)
2687 InitKeyInfo(&key, row, info);
2688 if (keyDef->name != NULL)
2690 int len = strlen(keyDef->name);
2691 if ((len < 1) || (len > XkbKeyNameLength))
2693 ERROR("Illegal name %s for key in section %s\n",
2694 keyDef->name, rowText(row));
2695 ACTION("Section not compiled\n");
2698 memset(key.name, 0, XkbKeyNameLength + 1);
2699 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2700 key.defs.defined |= _GK_Name;
2702 else if (!HandleComplexKey(keyDef, &key, info))
2704 if (!AddKey(row, &key))
2709 WSGO("Unexpected statement (type %d) in row body\n",
2710 keyDef->common.stmtType);
2718 HandleSectionBody(SectionDef * def,
2719 SectionInfo * si, unsigned merge, GeometryInfo * info)
2724 for (rowDef = def->rows; rowDef != NULL;
2725 rowDef = (RowDef *) rowDef->common.next)
2727 if (rowDef->common.stmtType == StmtVarDef)
2729 VarDef *var = (VarDef *) rowDef;
2730 ExprResult elem, field;
2732 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2733 return 0; /* internal error, already reported */
2734 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2736 if (!SetSectionField(si, field.str, ndx, var->value, info))
2742 else if (uStrCaseCmp(elem.str, "row") == 0)
2745 (&si->dfltRow, field.str, ndx, var->value, info))
2751 else if (uStrCaseCmp(elem.str, "key") == 0)
2753 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2761 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2763 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2771 WARN("Assignment to field of unknown element in section\n");
2772 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2777 else if (rowDef->common.stmtType == StmtRowDef)
2780 InitRowInfo(&row, si, info);
2781 if (!HandleRowBody(rowDef, &row, merge, info))
2783 if (!AddRow(si, &row))
2785 /* ClearRowInfo(&row,info);*/
2787 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2788 (rowDef->common.stmtType == StmtIndicatorMapDef))
2790 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2793 else if (rowDef->common.stmtType == StmtOverlayDef)
2795 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2800 WSGO("Unexpected statement (type %d) in section body\n",
2801 rowDef->common.stmtType);
2805 if (si->nRows != def->nRows)
2807 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2808 (unsigned int) si->nRows);
2809 ACTION("Definition of section %s might be incorrect\n", scText(si));
2815 HandleSectionDef(SectionDef * def,
2816 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2820 if (def->merge != MergeDefault)
2822 InitSectionInfo(&si, info);
2823 si.defs.merge = merge;
2824 si.name = def->name;
2825 if (!HandleSectionBody(def, &si, merge, info))
2827 if (!AddSection(info, &si))
2832 /***====================================================================***/
2835 HandleGeometryFile(XkbFile * file,
2836 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2839 const char *failWhat;
2841 if (merge == MergeDefault)
2842 merge = MergeAugment;
2843 info->name = _XkbDupString(file->name);
2848 switch (stmt->stmtType)
2851 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2852 HandleGeometryFile))
2855 case StmtKeyAliasDef:
2856 if (!HandleAliasDef((KeyAliasDef *) stmt,
2857 merge, info->fileID, &info->aliases))
2863 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2867 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2870 case StmtSectionDef:
2871 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2874 case StmtIndicatorMapDef:
2876 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2881 failWhat = "virtual modfier";
2884 failWhat = "symbol interpretation";
2885 case StmtGroupCompatDef:
2887 failWhat = "group compatibility map";
2888 case StmtKeycodeDef:
2890 failWhat = "key name";
2891 ERROR("Interpretation files may not include other types\n");
2892 ACTION("Ignoring %s definition.\n", failWhat);
2896 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2901 if (info->errorCount > 10)
2904 ERROR("Too many errors\n");
2906 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2912 /***====================================================================***/
2915 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2918 struct xkb_shape * shape;
2919 struct xkb_outline *old_outline, *outline;
2922 si->index = geom->num_shapes;
2924 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2927 WSGO("Couldn't allocate shape in geometry\n");
2928 ACTION("Shape %s not compiled\n", shText(si));
2931 old_outline = si->outlines;
2932 for (i = 0; i < si->nOutlines; i++, old_outline++)
2934 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2937 WSGO("Couldn't allocate outline in shape\n");
2938 ACTION("Shape %s is incomplete\n", shText(si));
2941 n = old_outline->num_points;
2942 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2943 outline->num_points = old_outline->num_points;
2944 outline->corner_radius = old_outline->corner_radius;
2948 n = (si->approx - si->outlines);
2949 shape->approx = &shape->outlines[n];
2953 n = (si->primary - si->outlines);
2954 shape->primary = &shape->outlines[n];
2956 XkbcComputeShapeBounds(shape);
2961 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2963 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2965 if (warningLevel < 9)
2967 ERROR("No position defined for doodad %s\n",
2969 ACTION("Illegal doodad ignored\n");
2973 if ((di->defs.defined & _GD_Priority) == 0)
2975 /* calculate priority -- should be just above previous doodad/row */
2979 case XkbOutlineDoodad:
2980 case XkbSolidDoodad:
2981 if ((di->defs.defined & _GD_Shape) == 0)
2983 ERROR("No shape defined for %s doodad %s\n",
2984 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2986 ACTION("Incomplete definition ignored\n");
2992 si = FindShape(info, di->shape,
2994 XkbOutlineDoodad ? "outline doodad" :
2995 "solid doodad"), ddText(di));
2997 di->shape = si->name;
3000 ERROR("No legal shape for %s\n", ddText(di));
3001 ACTION("Incomplete definition ignored\n");
3005 if ((di->defs.defined & _GD_Color) == 0)
3007 if (warningLevel > 5)
3009 WARN("No color for doodad %s\n", ddText(di));
3010 ACTION("Using black\n");
3012 di->color = xkb_intern_atom("black");
3016 if ((di->defs.defined & _GD_Text) == 0)
3018 ERROR("No text specified for text doodad %s\n", ddText(di));
3019 ACTION("Illegal doodad definition ignored\n");
3022 if ((di->defs.defined & _GD_Angle) == 0)
3024 if ((di->defs.defined & _GD_Color) == 0)
3026 if (warningLevel > 5)
3028 WARN("No color specified for doodad %s\n", ddText(di));
3029 ACTION("Using black\n");
3031 di->color = xkb_intern_atom("black");
3033 if ((di->defs.defined & _GD_FontSpec) != 0)
3035 if ((di->defs.defined & _GD_FontParts) == 0)
3037 if (warningLevel < 9)
3040 ("Text doodad %s has full and partial font definition\n",
3042 ACTION("Full specification ignored\n");
3044 di->defs.defined &= ~_GD_FontSpec;
3045 di->fontSpec = None;
3047 if ((di->defs.defined & _GD_Font) == 0)
3049 if (warningLevel > 5)
3051 WARN("No font specified for doodad %s\n", ddText(di));
3052 ACTION("Using \"%s\"\n", DFLT_FONT);
3054 di->font = xkb_intern_atom(DFLT_FONT);
3056 if ((di->defs.defined & _GD_FontSlant) == 0)
3058 if (warningLevel > 7)
3060 WARN("No font slant for text doodad %s\n", ddText(di));
3061 ACTION("Using \"%s\"\n", DFLT_SLANT);
3063 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3065 if ((di->defs.defined & _GD_FontWeight) == 0)
3067 if (warningLevel > 7)
3069 WARN("No font weight for text doodad %s\n", ddText(di));
3070 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3072 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3074 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3076 if (warningLevel > 9)
3078 WARN("No font set width for text doodad %s\n", ddText(di));
3079 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3081 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3083 if ((di->defs.defined & _GD_FontVariant) == 0)
3085 if (warningLevel > 9)
3087 WARN("No font variant for text doodad %s\n", ddText(di));
3088 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3090 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3092 if ((di->defs.defined & _GD_FontEncoding) == 0)
3094 if (warningLevel > 7)
3096 WARN("No font encoding for doodad %s\n", ddText(di));
3097 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3099 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3101 if ((di->defs.defined & _GD_FontSize) == 0)
3103 if (warningLevel > 7)
3105 WARN("No font size for text doodad %s\n", ddText(di));
3106 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3108 di->fontSize = DFLT_SIZE;
3110 if ((di->defs.defined & _GD_Height) == 0)
3112 unsigned size, nLines;
3114 size = (di->fontSize * 120) / 100;
3115 size = (size * 254) / 720; /* convert to mm/10 */
3116 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3122 if (warningLevel > 5)
3124 WARN("No height for text doodad %s\n", ddText(di));
3125 ACTION("Using calculated height %s millimeters\n",
3126 XkbcGeomFPText(size));
3130 if ((di->defs.defined & _GD_Width) == 0)
3132 unsigned width, tmp;
3135 for (str = XkbcAtomText(di->text); *str; str++)
3148 width *= (di->height * 2) / 3;
3149 if (warningLevel > 5)
3151 WARN("No width for text doodad %s\n", ddText(di));
3152 ACTION("Using calculated width %s millimeters\n",
3153 XkbcGeomFPText(width));
3158 case XkbIndicatorDoodad:
3159 if ((di->defs.defined & _GD_Shape) == 0)
3161 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3162 ACTION("Incomplete definition ignored\n");
3168 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3170 di->shape = si->name;
3173 ERROR("No legal shape for doodad %s\n", ddText(di));
3174 ACTION("Incomplete definition ignored\n");
3178 if ((di->defs.defined & _GD_Color) == 0)
3180 if (warningLevel > 5)
3182 WARN("No \"on\" color for indicator doodad %s\n",
3184 ACTION("Using green\n");
3186 di->color = xkb_intern_atom("green");
3188 if ((di->defs.defined & _GD_OffColor) == 0)
3190 if (warningLevel > 5)
3192 WARN("No \"off\" color for indicator doodad %s\n",
3194 ACTION("Using black\n");
3196 di->offColor = xkb_intern_atom("black");
3200 if (di->logoName == NULL)
3202 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3203 ACTION("Incomplete definition ignored\n");
3206 if ((di->defs.defined & _GD_Shape) == 0)
3208 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3209 ACTION("Incomplete definition ignored\n");
3215 si = FindShape(info, di->shape, "logo doodad",
3218 di->shape = si->name;
3221 ERROR("No legal shape for %s\n", ddText(di));
3222 ACTION("Incomplete definition ignored\n");
3226 if ((di->defs.defined & _GD_Color) == 0)
3228 if (warningLevel > 5)
3230 WARN("No color for doodad %s\n", ddText(di));
3231 ACTION("Using black\n");
3233 di->color = xkb_intern_atom("black");
3237 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3238 (unsigned int) di->type);
3244 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3247 FontFromParts(uint32_t fontTok,
3250 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3253 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3256 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3257 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3258 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3260 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3261 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3263 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3267 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3268 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3269 rtrn = calloc(totalSize, 1);
3271 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3277 CopyDoodadDef(struct xkb_geometry * geom,
3278 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3281 union xkb_doodad * doodad;
3282 struct xkb_color * color;
3283 struct xkb_shape * shape;
3286 if (!VerifyDoodadInfo(di, info))
3289 doodad = XkbcAddGeomDoodad(geom, section, name);
3292 WSGO("Couldn't allocate doodad in %s\n",
3293 (section ? "section" : "geometry"));
3294 ACTION("Cannot copy doodad %s\n", ddText(di));
3297 doodad->any.type = di->type;
3298 doodad->any.priority = di->priority;
3299 doodad->any.top = di->top;
3300 doodad->any.left = di->left;
3303 case XkbOutlineDoodad:
3304 case XkbSolidDoodad:
3305 si = FindShape(info, di->shape, NULL, NULL);
3308 doodad->shape.angle = di->angle;
3309 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3311 shape = &geom->shapes[si->index];
3312 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3313 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3316 doodad->text.angle = di->angle;
3317 doodad->text.width = di->width;
3318 doodad->text.height = di->height;
3319 if (di->fontSpec == None)
3320 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3323 di->fontVariant, di->fontSize,
3326 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3327 doodad->text.text = XkbcAtomGetString(di->text);
3328 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3330 XkbSetTextDoodadColor(geom, &doodad->text, color);
3332 case XkbIndicatorDoodad:
3333 si = FindShape(info, di->shape, NULL, NULL);
3336 shape = &geom->shapes[si->index];
3337 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3339 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3340 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3341 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3343 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3346 si = FindShape(info, di->shape, NULL, NULL);
3349 doodad->logo.angle = di->angle;
3350 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3352 shape = &geom->shapes[si->index];
3353 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3354 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3355 doodad->logo.logo_name = di->logoName;
3356 di->logoName = NULL;
3362 /***====================================================================***/
3365 VerifyOverlayInfo(struct xkb_geometry * geom,
3366 struct xkb_section * section,
3368 GeometryInfo * info, short rowMap[256], short rowSize[256])
3370 OverlayKeyInfo *ki, *next;
3371 unsigned long oKey, uKey, sKey;
3372 struct xkb_row * row;
3373 struct xkb_key * key;
3376 /* find out which row each key is in */
3377 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3379 oKey = KeyNameToLong(ki->over);
3380 uKey = KeyNameToLong(ki->under);
3381 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3384 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3387 sKey = KeyNameToLong(key->name.name);
3390 if (warningLevel > 0)
3393 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3394 XkbcKeyNameText(key->name.name),
3395 XkbcAtomText(section->name),
3396 XkbcAtomText(oi->name));
3397 ACTION("Overlay definition ignored\n");
3401 else if (sKey == uKey)
3408 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3411 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3412 XkbcKeyNameText(ki->under),
3413 XkbcAtomText(section->name),
3414 XkbcAtomText(oi->name));
3415 ACTION("Definition ignored\n");
3418 /* now prune out keys that aren't in the section */
3419 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3421 next = (OverlayKeyInfo *) oi->keys->defs.next;
3426 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3428 next = (OverlayKeyInfo *) ki->defs.next;
3429 if (next->sectionRow == _GOK_UnknownRow)
3431 ki->defs.next = next->defs.next;
3434 next = (OverlayKeyInfo *) ki->defs.next;
3439 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3440 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3441 ACTION("Overlay definition ignored\n");
3444 /* now figure out how many rows are defined for the overlay */
3445 memset(rowSize, 0, sizeof(short) * 256);
3446 for (k = 0; k < 256; k++)
3451 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3453 if (rowMap[ki->sectionRow] == -1)
3454 rowMap[ki->sectionRow] = oi->nRows++;
3455 ki->overlayRow = rowMap[ki->sectionRow];
3456 rowSize[ki->overlayRow]++;
3462 CopyOverlayDef(struct xkb_geometry * geom,
3463 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3466 struct xkb_overlay * ol;
3467 struct xkb_overlay_row * row;
3468 struct xkb_overlay_key * key;
3470 short rowMap[256], rowSize[256];
3473 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3476 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3479 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3480 XkbcAtomText(name), XkbcAtomText(section->name));
3483 for (i = 0; i < oi->nRows; i++)
3486 for (tmp = 0, row_under = -1;
3487 (tmp < section->num_rows) && (row_under < 0); tmp++)
3489 if (rowMap[tmp] == i)
3492 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3495 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3496 i, XkbcAtomText(name), XkbcAtomText(section->name));
3500 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3502 row = &ol->rows[ki->overlayRow];
3503 key = &row->keys[row->num_keys++];
3504 memset(key, 0, sizeof(struct xkb_overlay_key));
3505 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3506 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3511 /***====================================================================***/
3514 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3516 struct xkb_section * section;
3517 struct xkb_row * row;
3518 struct xkb_key * key;
3522 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3524 if (section == NULL)
3526 WSGO("Couldn't allocate section in geometry\n");
3527 ACTION("Section %s not compiled\n", scText(si));
3530 section->top = si->top;
3531 section->left = si->left;
3532 section->width = si->width;
3533 section->height = si->height;
3534 section->angle = si->angle;
3535 section->priority = si->priority;
3536 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3538 row = XkbcAddGeomRow(section, ri->nKeys);
3541 WSGO("Couldn't allocate row in section\n");
3542 ACTION("Section %s is incomplete\n", scText(si));
3546 row->left = ri->left;
3547 row->vertical = ri->vertical;
3548 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3550 struct xkb_color * color;
3551 if ((ki->defs.defined & _GK_Name) == 0)
3553 ERROR("Key %d of row %d in section %s has no name\n",
3554 (int) ki->index, (int) ri->index, scText(si));
3555 ACTION("Section %s ignored\n", scText(si));
3558 key = XkbcAddGeomKey(row);
3561 WSGO("Couldn't allocate key in row\n");
3562 ACTION("Section %s is incomplete\n", scText(si));
3565 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3567 if (ki->shape == None)
3572 shapei = FindShape(info, ki->shape, "key", keyText(ki));
3575 key->shape_ndx = shapei->index;
3577 if (ki->color != None)
3579 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3582 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3583 XkbSetKeyColor(geom, key, color);
3586 if (si->doodads != NULL)
3589 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3591 CopyDoodadDef(geom, section, di, info);
3594 if (si->overlays != NULL)
3597 for (oi = si->overlays; oi != NULL;
3598 oi = (OverlayInfo *) oi->defs.next)
3600 CopyOverlayDef(geom, section, oi, info);
3603 if (XkbcComputeSectionBounds(geom, section))
3605 /* 7/6/94 (ef) -- check for negative origin and translate */
3606 if ((si->defs.defined & _GS_Width) == 0)
3607 section->width = section->bounds.x2;
3608 if ((si->defs.defined & _GS_Height) == 0)
3609 section->height = section->bounds.y2;
3614 /***====================================================================***/
3617 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3621 InitGeometryInfo(&info, file->id, merge);
3622 HandleGeometryFile(file, xkb, merge, &info);
3624 if (info.errorCount == 0)
3626 struct xkb_geometry * geom;
3627 struct xkb_geometry_sizes sizes;
3628 memset(&sizes, 0, sizeof(sizes));
3629 sizes.which = XkbGeomAllMask;
3630 sizes.num_properties = info.nProps;
3631 sizes.num_colors = 8;
3632 sizes.num_shapes = info.nShapes;
3633 sizes.num_sections = info.nSections;
3634 sizes.num_doodads = info.nDoodads;
3635 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3637 WSGO("Couldn't allocate GeometryRec\n");
3638 ACTION("Geometry not compiled\n");
3643 geom->width_mm = info.widthMM;
3644 geom->height_mm = info.heightMM;
3645 if (info.name != NULL)
3647 geom->name = xkb_intern_atom(info.name);
3648 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3649 xkb->names->geometry = geom->name;
3651 if (info.fontSpec != None)
3652 geom->label_font = XkbcAtomGetString(info.fontSpec);
3654 geom->label_font = FontFromParts(info.font, info.fontWeight,
3660 XkbcAddGeomColor(geom, "black", geom->num_colors);
3661 XkbcAddGeomColor(geom, "white", geom->num_colors);
3663 if (info.baseColor == None)
3664 info.baseColor = xkb_intern_atom("white");
3665 if (info.labelColor == None)
3666 info.labelColor = xkb_intern_atom("black");
3668 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3671 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3677 for (pi = info.props; pi != NULL;
3678 pi = (PropertyInfo *) pi->defs.next)
3680 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3687 for (si = info.shapes; si != NULL;
3688 si = (ShapeInfo *) si->defs.next)
3690 if (!CopyShapeDef(geom, si))
3697 for (si = info.sections; si != NULL;
3698 si = (SectionInfo *) si->defs.next)
3700 if (!CopySectionDef(geom, si, &info))
3707 for (di = info.doodads; di != NULL;
3708 di = (DoodadInfo *) di->defs.next)
3710 if (!CopyDoodadDef(geom, NULL, di, &info))
3715 ApplyAliases(xkb, True, &info.aliases);
3716 ClearGeometryInfo(&info);