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 ********************************************************/
35 #include "indicators.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;
284 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
289 if (info->props == pi)
294 for (tmp = pi; tmp != NULL; tmp = next)
300 tmp->name = tmp->value = NULL;
301 next = (PropertyInfo *) tmp->defs.next;
308 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
311 if (key != &row->dfltKey)
314 strcpy(key->name, "unknown");
315 key->defs.defined &= ~_GK_Default;
319 bzero(key, sizeof(KeyInfo));
320 strcpy(key->name, "default");
321 key->defs.defined = _GK_Default;
322 key->defs.fileID = info->fileID;
323 key->defs.merge = info->merge;
324 key->defs.next = NULL;
331 ClearKeyInfo(KeyInfo * key)
333 key->defs.defined &= ~_GK_Default;
334 strcpy(key->name, "default");
342 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
347 if (row->keys == key)
352 for (tmp = key; tmp != NULL; tmp = next)
355 next = (KeyInfo *) tmp->defs.next;
362 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
364 if (row != §ion->dfltRow)
366 *row = section->dfltRow;
367 row->defs.defined &= ~_GR_Default;
371 bzero(row, sizeof(RowInfo *));
372 row->defs.defined = _GR_Default;
373 row->defs.fileID = info->fileID;
374 row->defs.merge = info->merge;
375 row->defs.next = NULL;
376 row->section = section;
379 InitKeyInfo(&row->dfltKey, row, info);
385 ClearRowInfo(RowInfo * row, GeometryInfo * info)
387 row->defs.defined &= ~_GR_Default;
388 row->top = row->left = 0;
389 row->vertical = False;
392 FreeKeys(row->keys, row, info);
393 ClearKeyInfo(&row->dfltKey);
394 row->dfltKey.defs.defined |= _GK_Default;
399 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
404 if (row == section->rows)
407 section->rows = NULL;
409 for (tmp = row; tmp != NULL; tmp = next)
411 ClearRowInfo(tmp, info);
412 next = (RowInfo *) tmp->defs.next;
419 FindDoodadByType(DoodadInfo * di, unsigned type)
423 if (di->type == type)
425 di = (DoodadInfo *) di->defs.next;
431 FindDoodadByName(DoodadInfo * di, uint32_t name)
435 if (di->name == name)
437 di = (DoodadInfo *) di->defs.next;
443 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
449 if (si && si->dfltDoodads)
450 dflt = FindDoodadByType(si->dfltDoodads, type);
451 if ((dflt == NULL) && (info->dfltDoodads))
452 dflt = FindDoodadByType(info->dfltDoodads, type);
456 di->defs.next = NULL;
460 bzero(di, sizeof(DoodadInfo));
461 di->defs.fileID = info->fileID;
467 di->priority = si->nextDoodadPriority++;
468 #if XkbGeomMaxPriority < 255
469 if (si->nextDoodadPriority > XkbGeomMaxPriority)
470 si->nextDoodadPriority = XkbGeomMaxPriority;
475 di->priority = info->nextPriority++;
476 if (info->nextPriority > XkbGeomMaxPriority)
477 info->nextPriority = XkbGeomMaxPriority;
483 ClearDoodadInfo(DoodadInfo * di)
488 bzero(di, sizeof(DoodadInfo));
490 di->defs.defined = 0;
495 ClearOverlayInfo(OverlayInfo * ol)
499 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
506 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
513 if (si->doodads == di)
518 if (si->dfltDoodads == di)
519 si->dfltDoodads = NULL;
521 if (info->doodads == di)
523 info->doodads = NULL;
526 if (info->dfltDoodads == di)
527 info->dfltDoodads = NULL;
528 for (tmp = di; tmp != NULL; tmp = next)
530 next = (DoodadInfo *) tmp->defs.next;
531 ClearDoodadInfo(tmp);
538 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
540 if (si != &info->dfltSection)
542 *si = info->dfltSection;
543 si->defs.defined &= ~_GS_Default;
544 si->name = xkb_intern_atom("unknown");
545 si->priority = info->nextPriority++;
546 if (info->nextPriority > XkbGeomMaxPriority)
547 info->nextPriority = XkbGeomMaxPriority;
551 bzero(si, sizeof(SectionInfo));
552 si->defs.fileID = info->fileID;
553 si->defs.merge = info->merge;
554 si->defs.next = NULL;
556 si->name = xkb_intern_atom("default");
557 InitRowInfo(&si->dfltRow, si, info);
563 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
569 into->defs.fileID = defs.fileID;
570 into->defs.merge = defs.merge;
571 into->defs.next = NULL;
572 into->dfltRow.defs.fileID = defs.fileID;
573 into->dfltRow.defs.merge = defs.merge;
574 into->dfltRow.defs.next = NULL;
575 into->dfltRow.section = into;
576 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
577 into->dfltRow.dfltKey.defs.merge = defs.merge;
578 into->dfltRow.dfltKey.defs.next = NULL;
579 into->dfltRow.dfltKey.row = &into->dfltRow;
584 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
587 si->defs.defined &= ~_GS_Default;
588 si->name = xkb_intern_atom("default");
589 si->top = si->left = 0;
590 si->width = si->height = 0;
594 FreeRows(si->rows, si, info);
597 ClearRowInfo(&si->dfltRow, info);
600 FreeDoodads(si->doodads, si, info);
603 si->dfltRow.defs.defined = _GR_Default;
608 FreeSections(SectionInfo * si, GeometryInfo * info)
613 if (si == info->sections)
616 info->sections = NULL;
618 for (tmp = si; tmp != NULL; tmp = next)
620 ClearSectionInfo(tmp, info);
621 next = (SectionInfo *) tmp->defs.next;
628 FreeShapes(ShapeInfo * si, GeometryInfo * info)
633 if (si == info->shapes)
638 for (tmp = si; tmp != NULL; tmp = next)
643 for (i = 0; i < tmp->nOutlines; i++)
645 if (tmp->outlines[i].points != NULL)
647 free(tmp->outlines[i].points);
648 tmp->outlines[i].num_points = 0;
649 tmp->outlines[i].points = NULL;
655 tmp->outlines = NULL;
656 tmp->primary = tmp->approx = NULL;
658 next = (ShapeInfo *) tmp->defs.next;
664 /***====================================================================***/
667 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
669 bzero(info, sizeof(GeometryInfo));
670 info->fileID = fileID;
672 InitSectionInfo(&info->dfltSection, info);
673 info->dfltSection.defs.defined = _GS_Default;
678 ClearGeometryInfo(GeometryInfo * info)
684 FreeProperties(info->props, info);
686 FreeShapes(info->shapes, info);
688 FreeSections(info->sections, info);
691 info->dfltCornerRadius = 0;
692 ClearSectionInfo(&info->dfltSection, info);
693 info->dfltSection.defs.defined = _GS_Default;
695 ClearAliases(&info->aliases);
699 /***====================================================================***/
701 static PropertyInfo *
702 NextProperty(GeometryInfo * info)
706 pi = uTypedAlloc(PropertyInfo);
709 bzero((char *) pi, sizeof(PropertyInfo));
710 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
717 static PropertyInfo *
718 FindProperty(GeometryInfo * info, char *name)
724 for (old = info->props; old != NULL;
725 old = (PropertyInfo *) old->defs.next)
727 if ((old->name) && (uStringEqual(name, old->name)))
734 AddProperty(GeometryInfo * info, PropertyInfo * new)
738 if ((!new) || (!new->value) || (!new->name))
740 old = FindProperty(info, new->name);
743 if ((new->defs.merge == MergeReplace)
744 || (new->defs.merge == MergeOverride))
746 if (((old->defs.fileID == new->defs.fileID)
747 && (warningLevel > 0)) || (warningLevel > 9))
749 WARN("Multiple definitions for the \"%s\" property\n",
751 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
756 old->value = _XkbDupString(new->value);
759 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
760 || (warningLevel > 9))
762 WARN("Multiple definitions for \"%s\" property\n", new->name);
763 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
769 if ((new = NextProperty(info)) == NULL)
771 new->defs.next = NULL;
772 new->name = _XkbDupString(old->name);
773 new->value = _XkbDupString(old->value);
777 /***====================================================================***/
780 NextShape(GeometryInfo * info)
784 si = uTypedAlloc(ShapeInfo);
787 bzero((char *) si, sizeof(ShapeInfo));
788 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
791 si->dfltCornerRadius = info->dfltCornerRadius;
797 FindShape(GeometryInfo * info, uint32_t name, const char *type, const char *which)
801 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
803 if (name == old->name)
809 WARN("Unknown shape \"%s\" for %s %s\n",
810 XkbcAtomText(name), type, which);
813 ACTION("Using default shape %s instead\n", shText(old));
816 ACTION("No default shape; definition ignored\n");
823 AddShape(GeometryInfo * info, ShapeInfo * new)
827 old = FindShape(info, new->name, NULL, NULL);
830 if ((new->defs.merge == MergeReplace)
831 || (new->defs.merge == MergeOverride))
833 ShapeInfo *next = (ShapeInfo *) old->defs.next;
834 if (((old->defs.fileID == new->defs.fileID)
835 && (warningLevel > 0)) || (warningLevel > 9))
837 WARN("Duplicate shape name \"%s\"\n", shText(old));
838 ACTION("Using last definition\n");
841 old->defs.next = &next->defs;
844 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
845 || (warningLevel > 9))
847 WARN("Multiple shapes named \"%s\"\n", shText(old));
848 ACTION("Using first definition\n");
853 if ((new = NextShape(info)) == NULL)
856 new->defs.next = NULL;
857 old->szOutlines = old->nOutlines = 0;
858 old->outlines = NULL;
864 /***====================================================================***/
867 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
871 next = into->defs.next;
872 ClearDoodadInfo(into);
874 into->defs.next = next;
875 next = from->defs.next;
876 ClearDoodadInfo(from);
877 from->defs.next = next;
882 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
886 di = uTypedCalloc(1, DoodadInfo);
892 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
898 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
905 NextDoodad(SectionInfo * si, GeometryInfo * info)
909 di = uTypedCalloc(1, DoodadInfo);
914 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
921 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
930 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
934 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
937 if ((new->defs.merge == MergeReplace)
938 || (new->defs.merge == MergeOverride))
940 if (((old->defs.fileID == new->defs.fileID)
941 && (warningLevel > 0)) || (warningLevel > 9))
943 WARN("Multiple doodads named \"%s\"\n",
944 XkbcAtomText(old->name));
945 ACTION("Using last definition\n");
947 ReplaceDoodad(old, new);
951 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
952 || (warningLevel > 9))
954 WARN("Multiple doodads named \"%s\"\n",
955 XkbcAtomText(old->name));
956 ACTION("Using first definition\n");
961 if ((new = NextDoodad(si, info)) == NULL)
963 ReplaceDoodad(new, old);
965 new->defs.next = NULL;
970 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
972 DoodadInfo *dflt = NULL;
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;
987 if ((si) && (si->dfltDoodads))
988 dflt = FindDoodadByType(si->dfltDoodads, type);
989 if ((!dflt) && (info->dfltDoodads))
990 dflt = FindDoodadByType(info->dfltDoodads, type);
993 dflt = NextDfltDoodad(si, info);
1003 /***====================================================================***/
1006 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1010 for (old = si->overlays; old != NULL;
1011 old = (OverlayInfo *) old->defs.next)
1013 if (old->name == new->name)
1018 if ((new->defs.merge == MergeReplace)
1019 || (new->defs.merge == MergeOverride))
1021 if (((old->defs.fileID == new->defs.fileID)
1022 && (warningLevel > 0)) || (warningLevel > 9))
1025 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1026 XkbcAtomText(old->name), XkbcAtomText(si->name));
1027 ACTION("Using last definition\n");
1029 ClearOverlayInfo(old);
1030 old->nKeys = new->nKeys;
1031 old->keys = new->keys;
1036 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1037 || (warningLevel > 9))
1039 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1040 XkbcAtomText(old->name), XkbcAtomText(si->name));
1041 ACTION("Using first definition\n");
1046 new = uTypedCalloc(1, OverlayInfo);
1049 if (warningLevel > 0)
1051 WSGO("Couldn't allocate a new OverlayInfo\n");
1053 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1054 XkbcAtomText(old->name), XkbcAtomText(si->name));
1061 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1062 (CommonInfo *) new);
1067 /***====================================================================***/
1069 static SectionInfo *
1070 NextSection(GeometryInfo * info)
1074 si = uTypedAlloc(SectionInfo);
1077 *si = info->dfltSection;
1078 si->defs.defined &= ~_GS_Default;
1079 si->defs.next = NULL;
1083 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1090 static SectionInfo *
1091 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1095 for (old = info->sections; old != NULL;
1096 old = (SectionInfo *) old->defs.next)
1098 if (new->name == old->name)
1105 AddSection(GeometryInfo * info, SectionInfo * new)
1109 old = FindMatchingSection(info, new);
1113 if ((new->defs.merge == MergeReplace)
1114 || (new->defs.merge == MergeOverride))
1116 SectionInfo *next = (SectionInfo *) old->defs.next;
1117 if (((old->defs.fileID == new->defs.fileID)
1118 && (warningLevel > 0)) || (warningLevel > 9))
1120 WARN("Duplicate shape name \"%s\"\n", shText(old));
1121 ACTION("Using last definition\n");
1124 old->defs.next = &next->defs;
1127 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1128 || (warningLevel > 9))
1130 WARN("Multiple shapes named \"%s\"\n", shText(old));
1131 ACTION("Using first definition\n");
1135 WARN("Don't know how to merge sections yet\n");
1139 if ((new = NextSection(info)) == NULL)
1142 new->defs.next = NULL;
1143 old->nRows = old->nDoodads = old->nOverlays = 0;
1145 old->doodads = NULL;
1146 old->overlays = NULL;
1150 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1158 /***====================================================================***/
1161 NextRow(SectionInfo * si)
1165 row = uTypedAlloc(RowInfo);
1169 row->defs.defined &= ~_GR_Default;
1170 row->defs.next = NULL;
1174 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1175 row->index = si->nRows++;
1181 AddRow(SectionInfo * si, RowInfo * new)
1186 if ((new = NextRow(si)) == NULL)
1189 new->defs.next = NULL;
1195 /***====================================================================***/
1198 NextKey(RowInfo * row)
1202 key = uTypedAlloc(KeyInfo);
1205 *key = row->dfltKey;
1206 key->defs.defined &= ~_GK_Default;
1207 key->defs.next = NULL;
1208 key->index = row->nKeys++;
1214 AddKey(RowInfo * row, KeyInfo * new)
1219 if ((new = NextKey(row)) == NULL)
1222 new->defs.next = NULL;
1224 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1228 /***====================================================================***/
1231 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1236 if (from->errorCount > 0)
1238 into->errorCount += from->errorCount;
1241 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1242 if (into->name == NULL)
1244 into->name = from->name;
1247 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1248 into->widthMM = from->widthMM;
1249 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1250 into->heightMM = from->heightMM;
1251 if ((into->font == None) || ((from->font != None) && clobber))
1252 into->font = from->font;
1253 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1254 into->fontSlant = from->fontSlant;
1255 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1256 into->fontWeight = from->fontWeight;
1257 if ((into->fontSetWidth == None)
1258 || ((from->fontSetWidth != None) && clobber))
1259 into->fontSetWidth = from->fontSetWidth;
1260 if ((into->fontVariant == None)
1261 || ((from->fontVariant != None) && clobber))
1262 into->fontVariant = from->fontVariant;
1263 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1264 into->fontSize = from->fontSize;
1265 if ((into->fontEncoding == None)
1266 || ((from->fontEncoding != None) && clobber))
1267 into->fontEncoding = from->fontEncoding;
1268 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1269 into->fontSpec = from->fontSpec;
1270 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1271 into->baseColor = from->baseColor;
1272 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1273 into->labelColor = from->labelColor;
1274 into->nextPriority = from->nextPriority;
1275 if (from->props != NULL)
1278 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1280 if (!AddProperty(into, pi))
1284 if (from->shapes != NULL)
1288 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1290 if (!AddShape(into, si))
1294 if (from->sections != NULL)
1298 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1300 if (!AddSection(into, si))
1304 if (from->doodads != NULL)
1308 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1310 if (!AddDoodad(NULL, into, di))
1314 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1319 typedef void (*FileHandler) (XkbFile * /* file */ ,
1320 struct xkb_desc * /* xkb */ ,
1321 unsigned /* merge */ ,
1322 GeometryInfo * /* info */
1326 HandleIncludeGeometry(IncludeStmt * stmt, struct xkb_desc * xkb, GeometryInfo * info,
1331 GeometryInfo included;
1335 if ((stmt->file == NULL) && (stmt->map == NULL))
1339 bzero(info, sizeof(GeometryInfo));
1341 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1343 InitGeometryInfo(&included, rtrn->id, newMerge);
1344 included.nextPriority = info->nextPriority;
1345 included.dfltCornerRadius = info->dfltCornerRadius;
1346 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1347 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1348 if (stmt->stmt != NULL)
1350 if (included.name != NULL)
1351 free(included.name);
1352 included.name = stmt->stmt;
1358 info->errorCount += 10;
1361 if ((stmt->next != NULL) && (included.errorCount < 1))
1365 GeometryInfo next_incl;
1367 for (next = stmt->next; next != NULL; next = next->next)
1369 if ((next->file == NULL) && (next->map == NULL))
1372 MergeIncludedGeometry(&included, info, next->merge);
1373 ClearGeometryInfo(info);
1375 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1377 InitGeometryInfo(&next_incl, rtrn->id, op);
1378 next_incl.nextPriority = included.nextPriority;
1379 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1380 DupSectionInfo(&next_incl.dfltSection,
1381 &included.dfltSection, &included);
1382 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1383 MergeIncludedGeometry(&included, &next_incl, op);
1384 ClearGeometryInfo(&next_incl);
1388 info->errorCount += 10;
1397 MergeIncludedGeometry(info, &included, newMerge);
1398 ClearGeometryInfo(&included);
1400 return (info->errorCount == 0);
1404 SetShapeField(ShapeInfo * si,
1406 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1410 if ((uStrCaseCmp(field, "radius") == 0)
1411 || (uStrCaseCmp(field, "corner") == 0)
1412 || (uStrCaseCmp(field, "cornerradius") == 0))
1414 if (arrayNdx != NULL)
1417 return ReportNotArray("key shape", field, shText(si));
1419 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1422 return ReportBadType("key shape", field, shText(si), "number");
1425 si->dfltCornerRadius = tmp.ival;
1427 info->dfltCornerRadius = tmp.ival;
1431 return ReportBadField("key shape", field, shText(si));
1435 SetShapeDoodadField(DoodadInfo * di,
1438 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1441 const char *typeName;
1444 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1445 if ((!uStrCaseCmp(field, "corner"))
1446 || (!uStrCaseCmp(field, "cornerradius")))
1448 if (arrayNdx != NULL)
1451 return ReportNotArray(typeName, field, ddText(di));
1453 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1456 return ReportBadType(typeName, field, ddText(di), "number");
1458 di->defs.defined |= _GD_Corner;
1459 di->corner = tmp.ival;
1462 else if (uStrCaseCmp(field, "angle") == 0)
1464 if (arrayNdx != NULL)
1467 return ReportNotArray(typeName, field, ddText(di));
1469 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1472 return ReportBadType(typeName, field, ddText(di), "number");
1474 di->defs.defined |= _GD_Angle;
1475 di->angle = tmp.ival;
1478 else if (uStrCaseCmp(field, "shape") == 0)
1480 if (arrayNdx != NULL)
1483 return ReportNotArray(typeName, field, ddText(di));
1485 if (!ExprResolveString(value, &tmp, NULL, NULL))
1488 return ReportBadType(typeName, field, ddText(di), "string");
1490 di->shape = xkb_intern_atom(tmp.str);
1491 di->defs.defined |= _GD_Shape;
1494 return ReportBadField(typeName, field, ddText(di));
1497 #define FIELD_STRING 0
1498 #define FIELD_SHORT 1
1499 #define FIELD_USHORT 2
1502 SetTextDoodadField(DoodadInfo * di,
1505 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1510 char *typeName = "text doodad";
1515 unsigned short *uval;
1518 if (uStrCaseCmp(field, "angle") == 0)
1520 if (arrayNdx != NULL)
1523 return ReportNotArray(typeName, field, ddText(di));
1525 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1528 return ReportBadType(typeName, field, ddText(di), "number");
1530 di->defs.defined |= _GD_Angle;
1531 di->angle = tmp.ival;
1534 if (uStrCaseCmp(field, "width") == 0)
1536 type = FIELD_USHORT;
1537 pField.uval = &di->width;
1540 else if (uStrCaseCmp(field, "height") == 0)
1542 type = FIELD_USHORT;
1543 pField.uval = &di->height;
1546 else if (uStrCaseCmp(field, "text") == 0)
1548 type = FIELD_STRING;
1549 pField.str = &di->text;
1552 else if (uStrCaseCmp(field, "font") == 0)
1554 type = FIELD_STRING;
1555 pField.str = &di->font;
1558 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1559 (uStrCaseCmp(field, "slant") == 0))
1561 type = FIELD_STRING;
1562 pField.str = &di->fontSlant;
1563 def = _GD_FontSlant;
1565 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1566 (uStrCaseCmp(field, "weight") == 0))
1568 type = FIELD_STRING;
1569 pField.str = &di->fontWeight;
1570 def = _GD_FontWeight;
1572 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1573 (uStrCaseCmp(field, "setwidth") == 0))
1575 type = FIELD_STRING;
1576 pField.str = &di->fontSetWidth;
1577 def = _GD_FontSetWidth;
1579 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1580 (uStrCaseCmp(field, "variant") == 0))
1582 type = FIELD_STRING;
1583 pField.str = &di->fontVariant;
1584 def = _GD_FontVariant;
1586 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1587 (uStrCaseCmp(field, "encoding") == 0))
1589 type = FIELD_STRING;
1590 pField.str = &di->fontEncoding;
1591 def = _GD_FontEncoding;
1593 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1594 (uStrCaseCmp(field, "xfontname") == 0))
1596 type = FIELD_STRING;
1597 pField.str = &di->fontSpec;
1600 else if (uStrCaseCmp(field, "fontsize") == 0)
1602 type = FIELD_USHORT;
1603 pField.uval = &di->fontSize;
1608 return ReportBadField(typeName, field, ddText(di));
1610 if (arrayNdx != NULL)
1613 return ReportNotArray(typeName, field, ddText(di));
1615 if (type == FIELD_STRING)
1617 if (!ExprResolveString(value, &tmp, NULL, NULL))
1620 return ReportBadType(typeName, field, ddText(di), "string");
1622 di->defs.defined |= def;
1623 *pField.str = xkb_intern_atom(tmp.str);
1627 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1630 return ReportBadType(typeName, field, ddText(di), "number");
1632 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1636 ReportBadType(typeName, field, ddText(di), "unsigned");
1638 di->defs.defined |= def;
1639 if (type == FIELD_USHORT)
1640 *pField.uval = tmp.uval;
1642 *pField.ival = tmp.ival;
1648 SetIndicatorDoodadField(DoodadInfo * di,
1652 SectionInfo * si, GeometryInfo * info)
1656 if ((uStrCaseCmp(field, "oncolor") == 0)
1657 || (uStrCaseCmp(field, "offcolor") == 0)
1658 || (uStrCaseCmp(field, "shape") == 0))
1660 if (arrayNdx != NULL)
1663 return ReportNotArray("indicator doodad", field, ddText(di));
1665 if (!ExprResolveString(value, &tmp, NULL, NULL))
1668 return ReportBadType("indicator doodad", field,
1669 ddText(di), "string");
1671 if (uStrCaseCmp(field, "oncolor") == 0)
1673 di->defs.defined |= _GD_Color;
1674 di->color = xkb_intern_atom(tmp.str);
1676 else if (uStrCaseCmp(field, "offcolor") == 0)
1678 di->defs.defined |= _GD_OffColor;
1679 di->offColor = xkb_intern_atom(tmp.str);
1681 else if (uStrCaseCmp(field, "shape") == 0)
1683 di->defs.defined |= _GD_Shape;
1684 di->shape = xkb_intern_atom(tmp.str);
1688 return ReportBadField("indicator doodad", field, ddText(di));
1692 SetLogoDoodadField(DoodadInfo * di,
1695 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1698 char *typeName = "logo doodad";
1700 if ((!uStrCaseCmp(field, "corner"))
1701 || (!uStrCaseCmp(field, "cornerradius")))
1703 if (arrayNdx != NULL)
1706 return ReportNotArray(typeName, field, ddText(di));
1708 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1711 return ReportBadType(typeName, field, ddText(di), "number");
1713 di->defs.defined |= _GD_Corner;
1714 di->corner = tmp.ival;
1717 else if (uStrCaseCmp(field, "angle") == 0)
1719 if (arrayNdx != NULL)
1722 return ReportNotArray(typeName, field, ddText(di));
1724 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1727 return ReportBadType(typeName, field, ddText(di), "number");
1729 di->defs.defined |= _GD_Angle;
1730 di->angle = tmp.ival;
1733 else if (uStrCaseCmp(field, "shape") == 0)
1735 if (arrayNdx != NULL)
1738 return ReportNotArray(typeName, field, ddText(di));
1740 if (!ExprResolveString(value, &tmp, NULL, NULL))
1743 return ReportBadType(typeName, field, ddText(di), "string");
1745 di->shape = xkb_intern_atom(tmp.str);
1746 di->defs.defined |= _GD_Shape;
1749 else if ((!uStrCaseCmp(field, "logoname"))
1750 || (!uStrCaseCmp(field, "name")))
1752 if (arrayNdx != NULL)
1755 return ReportNotArray(typeName, field, ddText(di));
1757 if (!ExprResolveString(value, &tmp, NULL, NULL))
1760 return ReportBadType(typeName, field, ddText(di),
1763 di->logoName = _XkbDupString(tmp.str);
1766 return ReportBadField(typeName, field, ddText(di));
1770 SetDoodadField(DoodadInfo * di,
1773 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1777 if (uStrCaseCmp(field, "priority") == 0)
1779 if (arrayNdx != NULL)
1782 return ReportNotArray("doodad", field, ddText(di));
1784 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1787 return ReportBadType("doodad", field, ddText(di), "integer");
1789 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1792 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1793 tmp.ival, XkbGeomMaxPriority);
1794 ACTION("Priority for doodad %s not changed", ddText(di));
1797 di->defs.defined |= _GD_Priority;
1798 di->priority = tmp.ival;
1801 else if (uStrCaseCmp(field, "left") == 0)
1803 if (arrayNdx != NULL)
1806 return ReportNotArray("doodad", field, ddText(di));
1808 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1811 return ReportBadType("doodad", field, ddText(di), "number");
1813 di->defs.defined |= _GD_Left;
1814 di->left = tmp.ival;
1817 else if (uStrCaseCmp(field, "top") == 0)
1819 if (arrayNdx != NULL)
1822 return ReportNotArray("doodad", field, ddText(di));
1824 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1827 return ReportBadType("doodad", field, ddText(di), "number");
1829 di->defs.defined |= _GD_Top;
1833 else if (uStrCaseCmp(field, "color") == 0)
1835 if (arrayNdx != NULL)
1838 return ReportNotArray("doodad", field, ddText(di));
1840 if (!ExprResolveString(value, &tmp, NULL, NULL))
1843 return ReportBadType("doodad", field, ddText(di), "string");
1845 di->defs.defined |= _GD_Color;
1846 di->color = xkb_intern_atom(tmp.str);
1852 case XkbOutlineDoodad:
1853 case XkbSolidDoodad:
1854 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1856 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1857 case XkbIndicatorDoodad:
1858 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1860 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1862 WSGO("Unknown doodad type %d in SetDoodadField\n",
1863 (unsigned int) di->type);
1864 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1869 SetSectionField(SectionInfo * si,
1871 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1873 unsigned short *pField;
1879 if (uStrCaseCmp(field, "priority") == 0)
1881 if (arrayNdx != NULL)
1884 return ReportNotArray("keyboard section", field, scText(si));
1886 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1889 ReportBadType("keyboard section", field, scText(si), "integer");
1892 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1895 ERROR("Section priority %d out of range (must be 0..%d)\n",
1896 tmp.ival, XkbGeomMaxPriority);
1897 ACTION("Priority for section %s not changed", scText(si));
1900 si->priority = tmp.ival;
1901 si->defs.defined |= _GS_Priority;
1904 else if (uStrCaseCmp(field, "top") == 0)
1909 else if (uStrCaseCmp(field, "left") == 0)
1914 else if (uStrCaseCmp(field, "width") == 0)
1916 pField = &si->width;
1919 else if (uStrCaseCmp(field, "height") == 0)
1921 pField = &si->height;
1924 else if (uStrCaseCmp(field, "angle") == 0)
1926 pField = &si->angle;
1932 return ReportBadField("keyboard section", field, scText(si));
1934 if (arrayNdx != NULL)
1937 return ReportNotArray("keyboard section", field, scText(si));
1939 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1942 ReportBadType("keyboard section", field, scText(si), "number");
1945 si->defs.defined |= def;
1951 SetRowField(RowInfo * row,
1953 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1957 if (uStrCaseCmp(field, "top") == 0)
1959 if (arrayNdx != NULL)
1962 return ReportNotArray("keyboard row", field, rowText(row));
1964 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1967 return ReportBadType("keyboard row", field, rowText(row),
1970 row->defs.defined |= _GR_Top;
1971 row->top = tmp.uval;
1973 else if (uStrCaseCmp(field, "left") == 0)
1975 if (arrayNdx != NULL)
1978 return ReportNotArray("keyboard row", field, rowText(row));
1980 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1983 return ReportBadType("keyboard row", field, rowText(row),
1986 row->defs.defined |= _GR_Left;
1987 row->left = tmp.uval;
1989 else if (uStrCaseCmp(field, "vertical") == 0)
1991 if (arrayNdx != NULL)
1994 return ReportNotArray("keyboard row", field, rowText(row));
1996 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1999 return ReportBadType("keyboard row", field, rowText(row),
2002 row->defs.defined |= _GR_Vertical;
2003 row->vertical = tmp.uval;
2008 return ReportBadField("keyboard row", field, rowText(row));
2014 SetKeyField(KeyInfo * key,
2016 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2020 if (uStrCaseCmp(field, "gap") == 0)
2022 if (arrayNdx != NULL)
2025 return ReportNotArray("key", field, keyText(key));
2027 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2030 return ReportBadType("key", field, keyText(key), "number");
2032 key->defs.defined |= _GK_Gap;
2033 key->gap = tmp.ival;
2035 else if (uStrCaseCmp(field, "shape") == 0)
2037 if (arrayNdx != NULL)
2040 return ReportNotArray("key", field, keyText(key));
2042 if (!ExprResolveString(value, &tmp, NULL, NULL))
2045 return ReportBadType("key", field, keyText(key), "string");
2047 key->defs.defined |= _GK_Shape;
2048 key->shape = xkb_intern_atom(tmp.str);
2051 else if ((uStrCaseCmp(field, "color") == 0) ||
2052 (uStrCaseCmp(field, "keycolor") == 0))
2054 if (arrayNdx != NULL)
2057 return ReportNotArray("key", field, keyText(key));
2059 if (!ExprResolveString(value, &tmp, NULL, NULL))
2062 return ReportBadType("key", field, keyText(key), "string");
2064 key->defs.defined |= _GK_Color;
2065 key->color = xkb_intern_atom(tmp.str);
2068 else if ((uStrCaseCmp(field, "name") == 0)
2069 || (uStrCaseCmp(field, "keyname") == 0))
2071 if (arrayNdx != NULL)
2074 return ReportNotArray("key", field, keyText(key));
2076 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2079 return ReportBadType("key", field, keyText(key), "key name");
2081 key->defs.defined |= _GK_Name;
2082 bzero(key->name, XkbKeyNameLength + 1);
2083 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2088 return ReportBadField("key", field, keyText(key));
2094 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2100 InitPropertyInfo(&pi, info);
2102 if (!ExprResolveString(value, &result, NULL, NULL))
2105 ERROR("Property values must be type string\n");
2106 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2109 pi.value = result.str;
2110 ret = AddProperty(info, &pi);
2116 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2118 ExprResult elem, field, tmp;
2121 uint32_t *pField = NULL;
2122 int ret = True; /* default to no error */
2124 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2125 return 0; /* internal error, already reported */
2128 if (uStrCaseCmp(elem.str, "shape") == 0)
2129 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2130 else if (uStrCaseCmp(elem.str, "key") == 0)
2131 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2132 field.str, ndx, stmt->value, info);
2133 else if (uStrCaseCmp(elem.str, "row") == 0)
2134 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2136 else if (uStrCaseCmp(elem.str, "section") == 0)
2137 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2139 else if (uStrCaseCmp(elem.str, "property") == 0)
2144 ERROR("The %s geometry property is not an array\n", field.str);
2145 ACTION("Ignoring illegal property definition\n");
2149 ret = SetGeometryProperty(info, field.str, stmt->value);
2152 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2153 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2154 else if (uStrCaseCmp(elem.str, "solid") == 0)
2157 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2159 dflt = NextDfltDoodad(NULL, info);
2160 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2162 else if (uStrCaseCmp(elem.str, "outline") == 0)
2165 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2167 dflt = NextDfltDoodad(NULL, info);
2168 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2170 else if (uStrCaseCmp(elem.str, "text") == 0)
2173 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2175 dflt = NextDfltDoodad(NULL, info);
2176 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2178 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2181 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2183 dflt = NextDfltDoodad(NULL, info);
2184 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2186 else if (uStrCaseCmp(elem.str, "logo") == 0)
2189 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2191 dflt = NextDfltDoodad(NULL, info);
2192 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2196 WARN("Assignment to field of unknown element\n");
2197 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2205 if ((uStrCaseCmp(field.str, "width") == 0) ||
2206 (uStrCaseCmp(field.str, "widthmm") == 0))
2211 ret = ReportNotArray("keyboard", field.str, "geometry");
2213 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2216 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2218 else if (tmp.ival < 1)
2220 WARN("Keyboard width must be positive\n");
2221 ACTION("Ignoring illegal keyboard width %s\n",
2222 XkbcGeomFPText(tmp.ival));
2226 if (info->widthMM != 0)
2228 WARN("Keyboard width multiply defined\n");
2229 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2230 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2232 info->widthMM = tmp.ival;
2238 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2239 (uStrCaseCmp(field.str, "heightmm") == 0))
2244 ret = ReportNotArray("keyboard", field.str, "geometry");
2246 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2249 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2253 WARN("Keyboard height must be positive\n");
2254 ACTION("Ignoring illegal keyboard height %s\n",
2255 XkbcGeomFPText(tmp.ival));
2259 if (info->heightMM != 0)
2261 WARN("Keyboard height multiply defined\n");
2262 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2263 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2265 info->heightMM = tmp.ival;
2271 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2276 ret = ReportNotArray("keyboard", field.str, "geometry");
2278 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2281 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2283 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2286 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2287 ACTION("Ignoring font size in keyboard geometry\n");
2291 info->fontSize = tmp.ival;
2297 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2298 (uStrCaseCmp(field.str, "basecolor") == 0))
2303 ret = ReportNotArray("keyboard", field.str, "geometry");
2305 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2308 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2311 info->baseColor = xkb_intern_atom(tmp.str);
2318 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2323 ret = ReportNotArray("keyboard", field.str, "geometry");
2325 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2328 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2331 info->labelColor = xkb_intern_atom(tmp.str);
2338 else if (uStrCaseCmp(field.str, "font") == 0)
2340 pField = &info->font;
2342 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2343 (uStrCaseCmp(field.str, "slant") == 0))
2345 pField = &info->fontSlant;
2347 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2348 (uStrCaseCmp(field.str, "weight") == 0))
2350 pField = &info->fontWeight;
2352 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2353 (uStrCaseCmp(field.str, "setwidth") == 0))
2355 pField = &info->fontWeight;
2357 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2358 (uStrCaseCmp(field.str, "encoding") == 0))
2360 pField = &info->fontEncoding;
2362 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2363 (uStrCaseCmp(field.str, "xfontname") == 0))
2365 pField = &info->fontSpec;
2369 ret = SetGeometryProperty(info, field.str, stmt->value);
2374 /* fallthrough for the cases that set pField */
2378 ret = ReportNotArray("keyboard", field.str, "geometry");
2380 else if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2383 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2386 *pField = xkb_intern_atom(tmp.str);
2393 /***====================================================================***/
2396 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2397 GeometryInfo * info)
2401 struct xkb_outline * outline;
2404 if (def->nOutlines < 1)
2406 WARN("Shape \"%s\" has no outlines\n", shText(si));
2407 ACTION("Definition ignored\n");
2410 si->nOutlines = def->nOutlines;
2411 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2414 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2415 ACTION("Definition ignored\n");
2419 for (nOut = 0, ol = def->outlines; ol != NULL;
2420 ol = (OutlineDef *) ol->common.next)
2422 if (ol->nPoints < 1)
2424 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2428 outline = &si->outlines[nOut++];
2429 outline->num_points = ol->nPoints;
2430 outline->corner_radius = si->dfltCornerRadius;
2431 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2432 if (!outline->points)
2434 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2435 ACTION("Definition ignored\n");
2440 for (nPt = 0, pt = ol->points; pt != NULL;
2441 pt = (ExprDef *) pt->common.next)
2443 outline->points[nPt].x = pt->value.coord.x;
2444 outline->points[nPt].y = pt->value.coord.y;
2447 if (ol->field != None)
2449 const char *str = XkbcAtomText(ol->field);
2450 if ((uStrCaseCmp(str, "approximation") == 0) ||
2451 (uStrCaseCmp(str, "approx") == 0))
2453 if (si->approx == NULL)
2454 si->approx = outline;
2457 WARN("Multiple approximations for \"%s\"\n",
2459 ACTION("Treating all but the first as normal outlines\n");
2462 else if (uStrCaseCmp(str, "primary") == 0)
2464 if (si->primary == NULL)
2465 si->primary = outline;
2468 WARN("Multiple primary outlines for \"%s\"\n",
2470 ACTION("Treating all but the first as normal outlines\n");
2475 WARN("Unknown outline type %s for \"%s\"\n", str,
2477 ACTION("Treated as a normal outline\n");
2481 if (nOut != si->nOutlines)
2483 WSGO("Expected %d outlines, got %d\n",
2484 (unsigned int) si->nOutlines, nOut);
2485 si->nOutlines = nOut;
2491 HandleShapeDef(ShapeDef * def, struct xkb_desc * xkb, unsigned merge,
2492 GeometryInfo * info)
2496 if (def->merge != MergeDefault)
2499 bzero(&si, sizeof(ShapeInfo));
2500 si.defs.merge = merge;
2501 si.name = def->name;
2502 si.dfltCornerRadius = info->dfltCornerRadius;
2503 if (!HandleShapeBody(def, &si, merge, info))
2505 if (!AddShape(info, &si))
2510 /***====================================================================***/
2513 HandleDoodadDef(DoodadDef * def,
2514 unsigned merge, SectionInfo * si, GeometryInfo * info)
2516 ExprResult elem, field;
2521 if (def->common.stmtType == StmtIndicatorMapDef)
2523 def->common.stmtType = StmtDoodadDef;
2524 def->type = XkbIndicatorDoodad;
2526 InitDoodadInfo(&new, def->type, si, info);
2527 new.name = def->name;
2528 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2530 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2531 return 0; /* internal error, already reported */
2532 if (elem.str != NULL)
2534 WARN("Assignment to field of unknown element in doodad %s\n",
2536 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2539 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2545 if (!AddDoodad(si, info, &new))
2547 ClearDoodadInfo(&new);
2551 /***====================================================================***/
2554 HandleOverlayDef(OverlayDef * def,
2555 unsigned merge, SectionInfo * si, GeometryInfo * info)
2557 OverlayKeyDef *keyDef;
2558 OverlayKeyInfo *key;
2561 if ((def->nKeys < 1) && (warningLevel > 3))
2563 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2564 XkbcAtomText(def->name), scText(si));
2565 ACTION("Overlay ignored\n");
2568 bzero(&ol, sizeof(OverlayInfo));
2569 ol.name = def->name;
2570 for (keyDef = def->keys; keyDef;
2571 keyDef = (OverlayKeyDef *) keyDef->common.next)
2573 key = uTypedCalloc(1, OverlayKeyInfo);
2574 if ((!key) && warningLevel > 0)
2576 WSGO("Couldn't allocate OverlayKeyInfo\n");
2577 ACTION("Overlay %s for section %s will be incomplete\n",
2578 XkbcAtomText(ol.name), scText(si));
2581 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2582 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2583 key->sectionRow = _GOK_UnknownRow;
2584 key->overlayRow = _GOK_UnknownRow;
2585 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2586 (CommonInfo *) key);
2589 if (!AddOverlay(si, info, &ol))
2591 ClearOverlayInfo(&ol);
2595 /***====================================================================***/
2598 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2604 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2606 if (expr->op == OpAssign)
2610 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2611 return False; /* internal error, already reported */
2612 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2615 (key, f.str, ndx, expr->value.binary.right, info))
2620 ERROR("Illegal element used in a key definition\n");
2621 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2631 if (!SetKeyField(key, "gap", NULL, expr, info))
2635 if (!SetKeyField(key, "shape", NULL, expr, info))
2639 if (!SetKeyField(key, "name", NULL, expr, info))
2643 ERROR("Cannot determine field for unnamed expression\n");
2644 ACTION("Ignoring key %d in row %d of section %s\n",
2645 row->nKeys + 1, row->section->nRows + 1,
2655 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2656 GeometryInfo * info)
2660 if ((def->nKeys < 1) && (warningLevel > 3))
2662 ERROR("Row in section %s has no keys\n", rowText(row));
2663 ACTION("Section ignored\n");
2666 for (keyDef = def->keys; keyDef != NULL;
2667 keyDef = (KeyDef *) keyDef->common.next)
2669 if (keyDef->common.stmtType == StmtVarDef)
2671 VarDef *var = (VarDef *) keyDef;
2672 ExprResult elem, field;
2674 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2675 return 0; /* internal error, already reported */
2676 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2678 if (!SetRowField(row, field.str, ndx, var->value, info))
2681 else if (uStrCaseCmp(elem.str, "key") == 0)
2684 (&row->dfltKey, field.str, ndx, var->value, info))
2689 WARN("Assignment to field of unknown element in row\n");
2690 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2693 else if (keyDef->common.stmtType == StmtKeyDef)
2696 InitKeyInfo(&key, row, info);
2697 if (keyDef->name != NULL)
2699 int len = strlen(keyDef->name);
2700 if ((len < 1) || (len > XkbKeyNameLength))
2702 ERROR("Illegal name %s for key in section %s\n",
2703 keyDef->name, rowText(row));
2704 ACTION("Section not compiled\n");
2707 bzero(key.name, XkbKeyNameLength + 1);
2708 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2709 key.defs.defined |= _GK_Name;
2711 else if (!HandleComplexKey(keyDef, &key, info))
2713 if (!AddKey(row, &key))
2718 WSGO("Unexpected statement (type %d) in row body\n",
2719 keyDef->common.stmtType);
2727 HandleSectionBody(SectionDef * def,
2728 SectionInfo * si, unsigned merge, GeometryInfo * info)
2733 for (rowDef = def->rows; rowDef != NULL;
2734 rowDef = (RowDef *) rowDef->common.next)
2736 if (rowDef->common.stmtType == StmtVarDef)
2738 VarDef *var = (VarDef *) rowDef;
2739 ExprResult elem, field;
2741 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2742 return 0; /* internal error, already reported */
2743 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2745 if (!SetSectionField(si, field.str, ndx, var->value, info))
2751 else if (uStrCaseCmp(elem.str, "row") == 0)
2754 (&si->dfltRow, field.str, ndx, var->value, info))
2760 else if (uStrCaseCmp(elem.str, "key") == 0)
2762 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2770 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2772 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2780 WARN("Assignment to field of unknown element in section\n");
2781 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2786 else if (rowDef->common.stmtType == StmtRowDef)
2789 InitRowInfo(&row, si, info);
2790 if (!HandleRowBody(rowDef, &row, merge, info))
2792 if (!AddRow(si, &row))
2794 /* ClearRowInfo(&row,info);*/
2796 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2797 (rowDef->common.stmtType == StmtIndicatorMapDef))
2799 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2802 else if (rowDef->common.stmtType == StmtOverlayDef)
2804 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2809 WSGO("Unexpected statement (type %d) in section body\n",
2810 rowDef->common.stmtType);
2814 if (si->nRows != def->nRows)
2816 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2817 (unsigned int) si->nRows);
2818 ACTION("Definition of section %s might be incorrect\n", scText(si));
2824 HandleSectionDef(SectionDef * def,
2825 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2829 if (def->merge != MergeDefault)
2831 InitSectionInfo(&si, info);
2832 si.defs.merge = merge;
2833 si.name = def->name;
2834 if (!HandleSectionBody(def, &si, merge, info))
2836 if (!AddSection(info, &si))
2841 /***====================================================================***/
2844 HandleGeometryFile(XkbFile * file,
2845 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2850 if (merge == MergeDefault)
2851 merge = MergeAugment;
2852 info->name = _XkbDupString(file->name);
2857 switch (stmt->stmtType)
2860 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2861 HandleGeometryFile))
2864 case StmtKeyAliasDef:
2865 if (!HandleAliasDef((KeyAliasDef *) stmt,
2866 merge, info->fileID, &info->aliases))
2872 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2876 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2879 case StmtSectionDef:
2880 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2883 case StmtIndicatorMapDef:
2885 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2890 failWhat = "virtual modfier";
2893 failWhat = "symbol interpretation";
2894 case StmtGroupCompatDef:
2896 failWhat = "group compatibility map";
2897 case StmtKeycodeDef:
2899 failWhat = "key name";
2900 ERROR("Interpretation files may not include other types\n");
2901 ACTION("Ignoring %s definition.\n", failWhat);
2905 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2910 if (info->errorCount > 10)
2913 ERROR("Too many errors\n");
2915 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2922 /***====================================================================***/
2925 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2928 struct xkb_shape * shape;
2929 struct xkb_outline *old_outline, *outline;
2932 si->index = geom->num_shapes;
2934 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2937 WSGO("Couldn't allocate shape in geometry\n");
2938 ACTION("Shape %s not compiled\n", shText(si));
2941 old_outline = si->outlines;
2942 for (i = 0; i < si->nOutlines; i++, old_outline++)
2944 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2947 WSGO("Couldn't allocate outline in shape\n");
2948 ACTION("Shape %s is incomplete\n", shText(si));
2951 n = old_outline->num_points;
2952 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2953 outline->num_points = old_outline->num_points;
2954 outline->corner_radius = old_outline->corner_radius;
2958 n = (si->approx - si->outlines);
2959 shape->approx = &shape->outlines[n];
2963 n = (si->primary - si->outlines);
2964 shape->primary = &shape->outlines[n];
2966 XkbcComputeShapeBounds(shape);
2971 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2973 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2975 if (warningLevel < 9)
2977 ERROR("No position defined for doodad %s\n",
2979 ACTION("Illegal doodad ignored\n");
2983 if ((di->defs.defined & _GD_Priority) == 0)
2985 /* calculate priority -- should be just above previous doodad/row */
2989 case XkbOutlineDoodad:
2990 case XkbSolidDoodad:
2991 if ((di->defs.defined & _GD_Shape) == 0)
2993 ERROR("No shape defined for %s doodad %s\n",
2994 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2996 ACTION("Incomplete definition ignored\n");
3002 si = FindShape(info, di->shape,
3004 XkbOutlineDoodad ? "outline doodad" :
3005 "solid doodad"), ddText(di));
3007 di->shape = si->name;
3010 ERROR("No legal shape for %s\n", ddText(di));
3011 ACTION("Incomplete definition ignored\n");
3015 if ((di->defs.defined & _GD_Color) == 0)
3017 if (warningLevel > 5)
3019 WARN("No color for doodad %s\n", ddText(di));
3020 ACTION("Using black\n");
3022 di->color = xkb_intern_atom("black");
3026 if ((di->defs.defined & _GD_Text) == 0)
3028 ERROR("No text specified for text doodad %s\n", ddText(di));
3029 ACTION("Illegal doodad definition ignored\n");
3032 if ((di->defs.defined & _GD_Angle) == 0)
3034 if ((di->defs.defined & _GD_Color) == 0)
3036 if (warningLevel > 5)
3038 WARN("No color specified for doodad %s\n", ddText(di));
3039 ACTION("Using black\n");
3041 di->color = xkb_intern_atom("black");
3043 if ((di->defs.defined & _GD_FontSpec) != 0)
3045 if ((di->defs.defined & _GD_FontParts) == 0)
3047 if (warningLevel < 9)
3050 ("Text doodad %s has full and partial font definition\n",
3052 ACTION("Full specification ignored\n");
3054 di->defs.defined &= ~_GD_FontSpec;
3055 di->fontSpec = None;
3057 if ((di->defs.defined & _GD_Font) == 0)
3059 if (warningLevel > 5)
3061 WARN("No font specified for doodad %s\n", ddText(di));
3062 ACTION("Using \"%s\"\n", DFLT_FONT);
3064 di->font = xkb_intern_atom(DFLT_FONT);
3066 if ((di->defs.defined & _GD_FontSlant) == 0)
3068 if (warningLevel > 7)
3070 WARN("No font slant for text doodad %s\n", ddText(di));
3071 ACTION("Using \"%s\"\n", DFLT_SLANT);
3073 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3075 if ((di->defs.defined & _GD_FontWeight) == 0)
3077 if (warningLevel > 7)
3079 WARN("No font weight for text doodad %s\n", ddText(di));
3080 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3082 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3084 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3086 if (warningLevel > 9)
3088 WARN("No font set width for text doodad %s\n", ddText(di));
3089 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3091 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3093 if ((di->defs.defined & _GD_FontVariant) == 0)
3095 if (warningLevel > 9)
3097 WARN("No font variant for text doodad %s\n", ddText(di));
3098 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3100 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3102 if ((di->defs.defined & _GD_FontEncoding) == 0)
3104 if (warningLevel > 7)
3106 WARN("No font encoding for doodad %s\n", ddText(di));
3107 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3109 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3111 if ((di->defs.defined & _GD_FontSize) == 0)
3113 if (warningLevel > 7)
3115 WARN("No font size for text doodad %s\n", ddText(di));
3116 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3118 di->fontSize = DFLT_SIZE;
3120 if ((di->defs.defined & _GD_Height) == 0)
3122 unsigned size, nLines;
3124 size = (di->fontSize * 120) / 100;
3125 size = (size * 254) / 720; /* convert to mm/10 */
3126 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3132 if (warningLevel > 5)
3134 WARN("No height for text doodad %s\n", ddText(di));
3135 ACTION("Using calculated height %s millimeters\n",
3136 XkbcGeomFPText(size));
3140 if ((di->defs.defined & _GD_Width) == 0)
3142 unsigned width, tmp;
3145 for (str = XkbcAtomText(di->text); *str; str++)
3158 width *= (di->height * 2) / 3;
3159 if (warningLevel > 5)
3161 WARN("No width for text doodad %s\n", ddText(di));
3162 ACTION("Using calculated width %s millimeters\n",
3163 XkbcGeomFPText(width));
3168 case XkbIndicatorDoodad:
3169 if ((di->defs.defined & _GD_Shape) == 0)
3171 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3172 ACTION("Incomplete definition ignored\n");
3178 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3180 di->shape = si->name;
3183 ERROR("No legal shape for doodad %s\n", ddText(di));
3184 ACTION("Incomplete definition ignored\n");
3188 if ((di->defs.defined & _GD_Color) == 0)
3190 if (warningLevel > 5)
3192 WARN("No \"on\" color for indicator doodad %s\n",
3194 ACTION("Using green\n");
3196 di->color = xkb_intern_atom("green");
3198 if ((di->defs.defined & _GD_OffColor) == 0)
3200 if (warningLevel > 5)
3202 WARN("No \"off\" color for indicator doodad %s\n",
3204 ACTION("Using black\n");
3206 di->offColor = xkb_intern_atom("black");
3210 if (di->logoName == NULL)
3212 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3213 ACTION("Incomplete definition ignored\n");
3216 if ((di->defs.defined & _GD_Shape) == 0)
3218 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3219 ACTION("Incomplete definition ignored\n");
3225 si = FindShape(info, di->shape, "logo doodad",
3228 di->shape = si->name;
3231 ERROR("No legal shape for %s\n", ddText(di));
3232 ACTION("Incomplete definition ignored\n");
3236 if ((di->defs.defined & _GD_Color) == 0)
3238 if (warningLevel > 5)
3240 WARN("No color for doodad %s\n", ddText(di));
3241 ACTION("Using black\n");
3243 di->color = xkb_intern_atom("black");
3247 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3248 (unsigned int) di->type);
3254 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3257 FontFromParts(uint32_t fontTok,
3260 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3263 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3266 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3267 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3268 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3270 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3271 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3273 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3277 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3278 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3279 rtrn = calloc(totalSize, 1);
3281 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3287 CopyDoodadDef(struct xkb_geometry * geom,
3288 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3291 union xkb_doodad * doodad;
3292 struct xkb_color * color;
3293 struct xkb_shape * shape;
3296 if (!VerifyDoodadInfo(di, info))
3299 doodad = XkbcAddGeomDoodad(geom, section, name);
3302 WSGO("Couldn't allocate doodad in %s\n",
3303 (section ? "section" : "geometry"));
3304 ACTION("Cannot copy doodad %s\n", ddText(di));
3307 doodad->any.type = di->type;
3308 doodad->any.priority = di->priority;
3309 doodad->any.top = di->top;
3310 doodad->any.left = di->left;
3313 case XkbOutlineDoodad:
3314 case XkbSolidDoodad:
3315 si = FindShape(info, di->shape, NULL, NULL);
3318 doodad->shape.angle = di->angle;
3319 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3321 shape = &geom->shapes[si->index];
3322 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3323 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3326 doodad->text.angle = di->angle;
3327 doodad->text.width = di->width;
3328 doodad->text.height = di->height;
3329 if (di->fontSpec == None)
3330 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3333 di->fontVariant, di->fontSize,
3336 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3337 doodad->text.text = XkbcAtomGetString(di->text);
3338 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3340 XkbSetTextDoodadColor(geom, &doodad->text, color);
3342 case XkbIndicatorDoodad:
3343 si = FindShape(info, di->shape, NULL, NULL);
3346 shape = &geom->shapes[si->index];
3347 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3349 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3350 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3351 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3353 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3356 si = FindShape(info, di->shape, NULL, NULL);
3359 doodad->logo.angle = di->angle;
3360 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3362 shape = &geom->shapes[si->index];
3363 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3364 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3365 doodad->logo.logo_name = di->logoName;
3366 di->logoName = NULL;
3372 /***====================================================================***/
3375 VerifyOverlayInfo(struct xkb_geometry * geom,
3376 struct xkb_section * section,
3378 GeometryInfo * info, short rowMap[256], short rowSize[256])
3380 register OverlayKeyInfo *ki, *next;
3381 unsigned long oKey, uKey, sKey;
3382 struct xkb_row * row;
3383 struct xkb_key * key;
3386 /* find out which row each key is in */
3387 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3389 oKey = KeyNameToLong(ki->over);
3390 uKey = KeyNameToLong(ki->under);
3391 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3394 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3397 sKey = KeyNameToLong(key->name.name);
3400 if (warningLevel > 0)
3403 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3404 XkbcKeyNameText(key->name.name),
3405 XkbcAtomText(section->name),
3406 XkbcAtomText(oi->name));
3407 ACTION("Overlay definition ignored\n");
3411 else if (sKey == uKey)
3418 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3421 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3422 XkbcKeyNameText(ki->under),
3423 XkbcAtomText(section->name),
3424 XkbcAtomText(oi->name));
3425 ACTION("Definition ignored\n");
3428 /* now prune out keys that aren't in the section */
3429 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3431 next = (OverlayKeyInfo *) oi->keys->defs.next;
3436 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3438 next = (OverlayKeyInfo *) ki->defs.next;
3439 if (next->sectionRow == _GOK_UnknownRow)
3441 ki->defs.next = next->defs.next;
3444 next = (OverlayKeyInfo *) ki->defs.next;
3449 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3450 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3451 ACTION("Overlay definition ignored\n");
3454 /* now figure out how many rows are defined for the overlay */
3455 bzero(rowSize, sizeof(short) * 256);
3456 for (k = 0; k < 256; k++)
3461 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3463 if (rowMap[ki->sectionRow] == -1)
3464 rowMap[ki->sectionRow] = oi->nRows++;
3465 ki->overlayRow = rowMap[ki->sectionRow];
3466 rowSize[ki->overlayRow]++;
3472 CopyOverlayDef(struct xkb_geometry * geom,
3473 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3476 struct xkb_overlay * ol;
3477 struct xkb_overlay_row * row;
3478 struct xkb_overlay_key * key;
3480 short rowMap[256], rowSize[256];
3483 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3486 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3489 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3490 XkbcAtomText(name), XkbcAtomText(section->name));
3493 for (i = 0; i < oi->nRows; i++)
3496 for (tmp = 0, row_under = -1;
3497 (tmp < section->num_rows) && (row_under < 0); tmp++)
3499 if (rowMap[tmp] == i)
3502 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3505 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3506 i, XkbcAtomText(name), XkbcAtomText(section->name));
3510 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3512 row = &ol->rows[ki->overlayRow];
3513 key = &row->keys[row->num_keys++];
3514 bzero(key, sizeof(struct xkb_overlay_key));
3515 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3516 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3521 /***====================================================================***/
3524 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3526 struct xkb_section * section;
3527 struct xkb_row * row;
3528 struct xkb_key * key;
3532 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3534 if (section == NULL)
3536 WSGO("Couldn't allocate section in geometry\n");
3537 ACTION("Section %s not compiled\n", scText(si));
3540 section->top = si->top;
3541 section->left = si->left;
3542 section->width = si->width;
3543 section->height = si->height;
3544 section->angle = si->angle;
3545 section->priority = si->priority;
3546 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3548 row = XkbcAddGeomRow(section, ri->nKeys);
3551 WSGO("Couldn't allocate row in section\n");
3552 ACTION("Section %s is incomplete\n", scText(si));
3556 row->left = ri->left;
3557 row->vertical = ri->vertical;
3558 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3560 struct xkb_color * color;
3561 if ((ki->defs.defined & _GK_Name) == 0)
3563 ERROR("Key %d of row %d in section %s has no name\n",
3564 (int) ki->index, (int) ri->index, scText(si));
3565 ACTION("Section %s ignored\n", scText(si));
3568 key = XkbcAddGeomKey(row);
3571 WSGO("Couldn't allocate key in row\n");
3572 ACTION("Section %s is incomplete\n", scText(si));
3575 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3577 if (ki->shape == None)
3582 si = FindShape(info, ki->shape, "key", keyText(ki));
3585 key->shape_ndx = si->index;
3587 if (ki->color != None)
3589 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3592 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3593 XkbSetKeyColor(geom, key, color);
3596 if (si->doodads != NULL)
3599 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3601 CopyDoodadDef(geom, section, di, info);
3604 if (si->overlays != NULL)
3607 for (oi = si->overlays; oi != NULL;
3608 oi = (OverlayInfo *) oi->defs.next)
3610 CopyOverlayDef(geom, section, oi, info);
3613 if (XkbcComputeSectionBounds(geom, section))
3615 /* 7/6/94 (ef) -- check for negative origin and translate */
3616 if ((si->defs.defined & _GS_Width) == 0)
3617 section->width = section->bounds.x2;
3618 if ((si->defs.defined & _GS_Height) == 0)
3619 section->height = section->bounds.y2;
3624 /***====================================================================***/
3627 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3631 InitGeometryInfo(&info, file->id, merge);
3632 HandleGeometryFile(file, xkb, merge, &info);
3634 if (info.errorCount == 0)
3636 struct xkb_geometry * geom;
3637 struct xkb_geometry_sizes sizes;
3638 bzero(&sizes, sizeof(sizes));
3639 sizes.which = XkbGeomAllMask;
3640 sizes.num_properties = info.nProps;
3641 sizes.num_colors = 8;
3642 sizes.num_shapes = info.nShapes;
3643 sizes.num_sections = info.nSections;
3644 sizes.num_doodads = info.nDoodads;
3645 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3647 WSGO("Couldn't allocate GeometryRec\n");
3648 ACTION("Geometry not compiled\n");
3653 geom->width_mm = info.widthMM;
3654 geom->height_mm = info.heightMM;
3655 if (info.name != NULL)
3657 geom->name = xkb_intern_atom(info.name);
3658 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3659 xkb->names->geometry = geom->name;
3661 if (info.fontSpec != None)
3662 geom->label_font = XkbcAtomGetString(info.fontSpec);
3664 geom->label_font = FontFromParts(info.font, info.fontWeight,
3670 XkbcAddGeomColor(geom, "black", geom->num_colors);
3671 XkbcAddGeomColor(geom, "white", geom->num_colors);
3673 if (info.baseColor == None)
3674 info.baseColor = xkb_intern_atom("white");
3675 if (info.labelColor == None)
3676 info.labelColor = xkb_intern_atom("black");
3678 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3681 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3687 for (pi = info.props; pi != NULL;
3688 pi = (PropertyInfo *) pi->defs.next)
3690 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3697 for (si = info.shapes; si != NULL;
3698 si = (ShapeInfo *) si->defs.next)
3700 if (!CopyShapeDef(geom, si))
3707 for (si = info.sections; si != NULL;
3708 si = (SectionInfo *) si->defs.next)
3710 if (!CopySectionDef(geom, si, &info))
3717 for (di = info.doodads; di != NULL;
3718 di = (DoodadInfo *) di->defs.next)
3720 if (!CopyDoodadDef(geom, NULL, di, &info))
3725 ApplyAliases(xkb, True, &info.aliases);
3726 ClearGeometryInfo(&info);