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))
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))
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))
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))
1488 return ReportBadType(typeName, field, ddText(di), "string");
1490 di->shape = xkb_intern_atom(tmp.str);
1491 di->defs.defined |= _GD_Shape;
1495 return ReportBadField(typeName, field, ddText(di));
1498 #define FIELD_STRING 0
1499 #define FIELD_SHORT 1
1500 #define FIELD_USHORT 2
1503 SetTextDoodadField(DoodadInfo * di,
1506 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1511 char *typeName = "text doodad";
1516 unsigned short *uval;
1519 if (uStrCaseCmp(field, "angle") == 0)
1521 if (arrayNdx != NULL)
1524 return ReportNotArray(typeName, field, ddText(di));
1526 if (!ExprResolveFloat(value, &tmp))
1529 return ReportBadType(typeName, field, ddText(di), "number");
1531 di->defs.defined |= _GD_Angle;
1532 di->angle = tmp.ival;
1535 if (uStrCaseCmp(field, "width") == 0)
1537 type = FIELD_USHORT;
1538 pField.uval = &di->width;
1541 else if (uStrCaseCmp(field, "height") == 0)
1543 type = FIELD_USHORT;
1544 pField.uval = &di->height;
1547 else if (uStrCaseCmp(field, "text") == 0)
1549 type = FIELD_STRING;
1550 pField.str = &di->text;
1553 else if (uStrCaseCmp(field, "font") == 0)
1555 type = FIELD_STRING;
1556 pField.str = &di->font;
1559 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1560 (uStrCaseCmp(field, "slant") == 0))
1562 type = FIELD_STRING;
1563 pField.str = &di->fontSlant;
1564 def = _GD_FontSlant;
1566 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1567 (uStrCaseCmp(field, "weight") == 0))
1569 type = FIELD_STRING;
1570 pField.str = &di->fontWeight;
1571 def = _GD_FontWeight;
1573 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1574 (uStrCaseCmp(field, "setwidth") == 0))
1576 type = FIELD_STRING;
1577 pField.str = &di->fontSetWidth;
1578 def = _GD_FontSetWidth;
1580 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1581 (uStrCaseCmp(field, "variant") == 0))
1583 type = FIELD_STRING;
1584 pField.str = &di->fontVariant;
1585 def = _GD_FontVariant;
1587 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1588 (uStrCaseCmp(field, "encoding") == 0))
1590 type = FIELD_STRING;
1591 pField.str = &di->fontEncoding;
1592 def = _GD_FontEncoding;
1594 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1595 (uStrCaseCmp(field, "xfontname") == 0))
1597 type = FIELD_STRING;
1598 pField.str = &di->fontSpec;
1601 else if (uStrCaseCmp(field, "fontsize") == 0)
1603 type = FIELD_USHORT;
1604 pField.uval = &di->fontSize;
1609 return ReportBadField(typeName, field, ddText(di));
1611 if (arrayNdx != NULL)
1614 return ReportNotArray(typeName, field, ddText(di));
1616 if (type == FIELD_STRING)
1618 if (!ExprResolveString(value, &tmp))
1621 return ReportBadType(typeName, field, ddText(di), "string");
1623 di->defs.defined |= def;
1624 *pField.str = xkb_intern_atom(tmp.str);
1629 if (!ExprResolveFloat(value, &tmp))
1632 return ReportBadType(typeName, field, ddText(di), "number");
1634 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1638 ReportBadType(typeName, field, ddText(di), "unsigned");
1640 di->defs.defined |= def;
1641 if (type == FIELD_USHORT)
1642 *pField.uval = tmp.uval;
1644 *pField.ival = tmp.ival;
1650 SetIndicatorDoodadField(DoodadInfo * di,
1654 SectionInfo * si, GeometryInfo * info)
1658 if ((uStrCaseCmp(field, "oncolor") == 0)
1659 || (uStrCaseCmp(field, "offcolor") == 0)
1660 || (uStrCaseCmp(field, "shape") == 0))
1662 if (arrayNdx != NULL)
1665 return ReportNotArray("indicator doodad", field, ddText(di));
1667 if (!ExprResolveString(value, &tmp))
1670 return ReportBadType("indicator doodad", field,
1671 ddText(di), "string");
1673 if (uStrCaseCmp(field, "oncolor") == 0)
1675 di->defs.defined |= _GD_Color;
1676 di->color = xkb_intern_atom(tmp.str);
1678 else if (uStrCaseCmp(field, "offcolor") == 0)
1680 di->defs.defined |= _GD_OffColor;
1681 di->offColor = xkb_intern_atom(tmp.str);
1683 else if (uStrCaseCmp(field, "shape") == 0)
1685 di->defs.defined |= _GD_Shape;
1686 di->shape = xkb_intern_atom(tmp.str);
1691 return ReportBadField("indicator doodad", field, ddText(di));
1695 SetLogoDoodadField(DoodadInfo * di,
1698 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1701 char *typeName = "logo doodad";
1703 if ((!uStrCaseCmp(field, "corner"))
1704 || (!uStrCaseCmp(field, "cornerradius")))
1706 if (arrayNdx != NULL)
1709 return ReportNotArray(typeName, field, ddText(di));
1711 if (!ExprResolveFloat(value, &tmp))
1714 return ReportBadType(typeName, field, ddText(di), "number");
1716 di->defs.defined |= _GD_Corner;
1717 di->corner = tmp.ival;
1720 else if (uStrCaseCmp(field, "angle") == 0)
1722 if (arrayNdx != NULL)
1725 return ReportNotArray(typeName, field, ddText(di));
1727 if (!ExprResolveFloat(value, &tmp))
1730 return ReportBadType(typeName, field, ddText(di), "number");
1732 di->defs.defined |= _GD_Angle;
1733 di->angle = tmp.ival;
1736 else if (uStrCaseCmp(field, "shape") == 0)
1738 if (arrayNdx != NULL)
1741 return ReportNotArray(typeName, field, ddText(di));
1743 if (!ExprResolveString(value, &tmp))
1746 return ReportBadType(typeName, field, ddText(di), "string");
1748 di->shape = xkb_intern_atom(tmp.str);
1750 di->defs.defined |= _GD_Shape;
1753 else if ((!uStrCaseCmp(field, "logoname"))
1754 || (!uStrCaseCmp(field, "name")))
1756 if (arrayNdx != NULL)
1759 return ReportNotArray(typeName, field, ddText(di));
1761 if (!ExprResolveString(value, &tmp))
1764 return ReportBadType(typeName, field, ddText(di),
1767 di->logoName = _XkbDupString(tmp.str);
1771 return ReportBadField(typeName, field, ddText(di));
1775 SetDoodadField(DoodadInfo * di,
1778 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1782 if (uStrCaseCmp(field, "priority") == 0)
1784 if (arrayNdx != NULL)
1787 return ReportNotArray("doodad", field, ddText(di));
1789 if (!ExprResolveInteger(value, &tmp))
1792 return ReportBadType("doodad", field, ddText(di), "integer");
1794 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1797 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1798 tmp.ival, XkbGeomMaxPriority);
1799 ACTION("Priority for doodad %s not changed", ddText(di));
1802 di->defs.defined |= _GD_Priority;
1803 di->priority = tmp.ival;
1806 else if (uStrCaseCmp(field, "left") == 0)
1808 if (arrayNdx != NULL)
1811 return ReportNotArray("doodad", field, ddText(di));
1813 if (!ExprResolveFloat(value, &tmp))
1816 return ReportBadType("doodad", field, ddText(di), "number");
1818 di->defs.defined |= _GD_Left;
1819 di->left = tmp.ival;
1822 else if (uStrCaseCmp(field, "top") == 0)
1824 if (arrayNdx != NULL)
1827 return ReportNotArray("doodad", field, ddText(di));
1829 if (!ExprResolveFloat(value, &tmp))
1832 return ReportBadType("doodad", field, ddText(di), "number");
1834 di->defs.defined |= _GD_Top;
1838 else if (uStrCaseCmp(field, "color") == 0)
1840 if (arrayNdx != NULL)
1843 return ReportNotArray("doodad", field, ddText(di));
1845 if (!ExprResolveString(value, &tmp))
1848 return ReportBadType("doodad", field, ddText(di), "string");
1850 di->defs.defined |= _GD_Color;
1851 di->color = xkb_intern_atom(tmp.str);
1857 case XkbOutlineDoodad:
1858 case XkbSolidDoodad:
1859 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1861 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1862 case XkbIndicatorDoodad:
1863 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1865 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1867 WSGO("Unknown doodad type %d in SetDoodadField\n",
1868 (unsigned int) di->type);
1869 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1874 SetSectionField(SectionInfo * si,
1876 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1878 unsigned short *pField;
1884 if (uStrCaseCmp(field, "priority") == 0)
1886 if (arrayNdx != NULL)
1889 return ReportNotArray("keyboard section", field, scText(si));
1891 if (!ExprResolveInteger(value, &tmp))
1894 ReportBadType("keyboard section", field, scText(si), "integer");
1897 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1900 ERROR("Section priority %d out of range (must be 0..%d)\n",
1901 tmp.ival, XkbGeomMaxPriority);
1902 ACTION("Priority for section %s not changed", scText(si));
1905 si->priority = tmp.ival;
1906 si->defs.defined |= _GS_Priority;
1909 else if (uStrCaseCmp(field, "top") == 0)
1914 else if (uStrCaseCmp(field, "left") == 0)
1919 else if (uStrCaseCmp(field, "width") == 0)
1921 pField = &si->width;
1924 else if (uStrCaseCmp(field, "height") == 0)
1926 pField = &si->height;
1929 else if (uStrCaseCmp(field, "angle") == 0)
1931 pField = &si->angle;
1937 return ReportBadField("keyboard section", field, scText(si));
1939 if (arrayNdx != NULL)
1942 return ReportNotArray("keyboard section", field, scText(si));
1944 if (!ExprResolveFloat(value, &tmp))
1947 ReportBadType("keyboard section", field, scText(si), "number");
1950 si->defs.defined |= def;
1956 SetRowField(RowInfo * row,
1958 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1962 if (uStrCaseCmp(field, "top") == 0)
1964 if (arrayNdx != NULL)
1967 return ReportNotArray("keyboard row", field, rowText(row));
1969 if (!ExprResolveFloat(value, &tmp))
1972 return ReportBadType("keyboard row", field, rowText(row),
1975 row->defs.defined |= _GR_Top;
1976 row->top = tmp.uval;
1978 else if (uStrCaseCmp(field, "left") == 0)
1980 if (arrayNdx != NULL)
1983 return ReportNotArray("keyboard row", field, rowText(row));
1985 if (!ExprResolveFloat(value, &tmp))
1988 return ReportBadType("keyboard row", field, rowText(row),
1991 row->defs.defined |= _GR_Left;
1992 row->left = tmp.uval;
1994 else if (uStrCaseCmp(field, "vertical") == 0)
1996 if (arrayNdx != NULL)
1999 return ReportNotArray("keyboard row", field, rowText(row));
2001 if (!ExprResolveBoolean(value, &tmp))
2004 return ReportBadType("keyboard row", field, rowText(row),
2007 row->defs.defined |= _GR_Vertical;
2008 row->vertical = tmp.uval;
2013 return ReportBadField("keyboard row", field, rowText(row));
2019 SetKeyField(KeyInfo * key,
2021 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2025 if (uStrCaseCmp(field, "gap") == 0)
2027 if (arrayNdx != NULL)
2030 return ReportNotArray("key", field, keyText(key));
2032 if (!ExprResolveFloat(value, &tmp))
2035 return ReportBadType("key", field, keyText(key), "number");
2037 key->defs.defined |= _GK_Gap;
2038 key->gap = tmp.ival;
2040 else if (uStrCaseCmp(field, "shape") == 0)
2042 if (arrayNdx != NULL)
2045 return ReportNotArray("key", field, keyText(key));
2047 if (!ExprResolveString(value, &tmp))
2050 return ReportBadType("key", field, keyText(key), "string");
2052 key->defs.defined |= _GK_Shape;
2053 key->shape = xkb_intern_atom(tmp.str);
2056 else if ((uStrCaseCmp(field, "color") == 0) ||
2057 (uStrCaseCmp(field, "keycolor") == 0))
2059 if (arrayNdx != NULL)
2062 return ReportNotArray("key", field, keyText(key));
2064 if (!ExprResolveString(value, &tmp))
2067 return ReportBadType("key", field, keyText(key), "string");
2069 key->defs.defined |= _GK_Color;
2070 key->color = xkb_intern_atom(tmp.str);
2073 else if ((uStrCaseCmp(field, "name") == 0)
2074 || (uStrCaseCmp(field, "keyname") == 0))
2076 if (arrayNdx != NULL)
2079 return ReportNotArray("key", field, keyText(key));
2081 if (!ExprResolveKeyName(value, &tmp))
2084 return ReportBadType("key", field, keyText(key), "key name");
2086 key->defs.defined |= _GK_Name;
2087 bzero(key->name, XkbKeyNameLength + 1);
2088 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2093 return ReportBadField("key", field, keyText(key));
2099 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2105 InitPropertyInfo(&pi, info);
2107 if (!ExprResolveString(value, &result))
2110 ERROR("Property values must be type string\n");
2111 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2114 pi.value = result.str;
2115 ret = AddProperty(info, &pi);
2121 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2123 ExprResult elem, field, tmp;
2126 uint32_t *pField = NULL;
2127 int ret = True; /* default to no error */
2129 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2130 return 0; /* internal error, already reported */
2133 if (uStrCaseCmp(elem.str, "shape") == 0)
2134 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2135 else if (uStrCaseCmp(elem.str, "key") == 0)
2136 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2137 field.str, ndx, stmt->value, info);
2138 else if (uStrCaseCmp(elem.str, "row") == 0)
2139 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2141 else if (uStrCaseCmp(elem.str, "section") == 0)
2142 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2144 else if (uStrCaseCmp(elem.str, "property") == 0)
2149 ERROR("The %s geometry property is not an array\n", field.str);
2150 ACTION("Ignoring illegal property definition\n");
2154 ret = SetGeometryProperty(info, field.str, stmt->value);
2157 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2158 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2159 else if (uStrCaseCmp(elem.str, "solid") == 0)
2162 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2164 dflt = NextDfltDoodad(NULL, info);
2165 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2167 else if (uStrCaseCmp(elem.str, "outline") == 0)
2170 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2172 dflt = NextDfltDoodad(NULL, info);
2173 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2175 else if (uStrCaseCmp(elem.str, "text") == 0)
2178 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2180 dflt = NextDfltDoodad(NULL, info);
2181 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2183 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2186 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2188 dflt = NextDfltDoodad(NULL, info);
2189 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2191 else if (uStrCaseCmp(elem.str, "logo") == 0)
2194 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2196 dflt = NextDfltDoodad(NULL, info);
2197 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2201 WARN("Assignment to field of unknown element\n");
2202 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2210 if ((uStrCaseCmp(field.str, "width") == 0) ||
2211 (uStrCaseCmp(field.str, "widthmm") == 0))
2216 ret = ReportNotArray("keyboard", field.str, "geometry");
2218 else if (!ExprResolveFloat(stmt->value, &tmp))
2221 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2223 else if (tmp.ival < 1)
2225 WARN("Keyboard width must be positive\n");
2226 ACTION("Ignoring illegal keyboard width %s\n",
2227 XkbcGeomFPText(tmp.ival));
2231 if (info->widthMM != 0)
2233 WARN("Keyboard width multiply defined\n");
2234 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2235 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2237 info->widthMM = tmp.ival;
2243 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2244 (uStrCaseCmp(field.str, "heightmm") == 0))
2249 ret = ReportNotArray("keyboard", field.str, "geometry");
2251 if (!ExprResolveFloat(stmt->value, &tmp))
2254 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2258 WARN("Keyboard height must be positive\n");
2259 ACTION("Ignoring illegal keyboard height %s\n",
2260 XkbcGeomFPText(tmp.ival));
2264 if (info->heightMM != 0)
2266 WARN("Keyboard height multiply defined\n");
2267 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2268 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2270 info->heightMM = tmp.ival;
2276 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2281 ret = ReportNotArray("keyboard", field.str, "geometry");
2283 else if (!ExprResolveFloat(stmt->value, &tmp))
2286 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2288 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2291 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2292 ACTION("Ignoring font size in keyboard geometry\n");
2296 info->fontSize = tmp.ival;
2302 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2303 (uStrCaseCmp(field.str, "basecolor") == 0))
2308 ret = ReportNotArray("keyboard", field.str, "geometry");
2310 if (!ExprResolveString(stmt->value, &tmp))
2313 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2316 info->baseColor = xkb_intern_atom(tmp.str);
2323 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2328 ret = ReportNotArray("keyboard", field.str, "geometry");
2330 if (!ExprResolveString(stmt->value, &tmp))
2333 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2336 info->labelColor = xkb_intern_atom(tmp.str);
2343 else if (uStrCaseCmp(field.str, "font") == 0)
2345 pField = &info->font;
2347 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2348 (uStrCaseCmp(field.str, "slant") == 0))
2350 pField = &info->fontSlant;
2352 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2353 (uStrCaseCmp(field.str, "weight") == 0))
2355 pField = &info->fontWeight;
2357 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2358 (uStrCaseCmp(field.str, "setwidth") == 0))
2360 pField = &info->fontWeight;
2362 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2363 (uStrCaseCmp(field.str, "encoding") == 0))
2365 pField = &info->fontEncoding;
2367 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2368 (uStrCaseCmp(field.str, "xfontname") == 0))
2370 pField = &info->fontSpec;
2374 ret = SetGeometryProperty(info, field.str, stmt->value);
2379 /* fallthrough for the cases that set pField */
2383 ret = ReportNotArray("keyboard", field.str, "geometry");
2385 else if (!ExprResolveString(stmt->value, &tmp))
2388 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2391 *pField = xkb_intern_atom(tmp.str);
2398 /***====================================================================***/
2401 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2402 GeometryInfo * info)
2406 struct xkb_outline * outline;
2409 if (def->nOutlines < 1)
2411 WARN("Shape \"%s\" has no outlines\n", shText(si));
2412 ACTION("Definition ignored\n");
2415 si->nOutlines = def->nOutlines;
2416 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2419 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2420 ACTION("Definition ignored\n");
2424 for (nOut = 0, ol = def->outlines; ol != NULL;
2425 ol = (OutlineDef *) ol->common.next)
2427 if (ol->nPoints < 1)
2429 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2433 outline = &si->outlines[nOut++];
2434 outline->num_points = ol->nPoints;
2435 outline->corner_radius = si->dfltCornerRadius;
2436 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2437 if (!outline->points)
2439 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2440 ACTION("Definition ignored\n");
2445 for (nPt = 0, pt = ol->points; pt != NULL;
2446 pt = (ExprDef *) pt->common.next)
2448 outline->points[nPt].x = pt->value.coord.x;
2449 outline->points[nPt].y = pt->value.coord.y;
2452 if (ol->field != None)
2454 const char *str = XkbcAtomText(ol->field);
2455 if ((uStrCaseCmp(str, "approximation") == 0) ||
2456 (uStrCaseCmp(str, "approx") == 0))
2458 if (si->approx == NULL)
2459 si->approx = outline;
2462 WARN("Multiple approximations for \"%s\"\n",
2464 ACTION("Treating all but the first as normal outlines\n");
2467 else if (uStrCaseCmp(str, "primary") == 0)
2469 if (si->primary == NULL)
2470 si->primary = outline;
2473 WARN("Multiple primary outlines for \"%s\"\n",
2475 ACTION("Treating all but the first as normal outlines\n");
2480 WARN("Unknown outline type %s for \"%s\"\n", str,
2482 ACTION("Treated as a normal outline\n");
2486 if (nOut != si->nOutlines)
2488 WSGO("Expected %d outlines, got %d\n",
2489 (unsigned int) si->nOutlines, nOut);
2490 si->nOutlines = nOut;
2496 HandleShapeDef(ShapeDef * def, struct xkb_desc * xkb, unsigned merge,
2497 GeometryInfo * info)
2501 if (def->merge != MergeDefault)
2504 bzero(&si, sizeof(ShapeInfo));
2505 si.defs.merge = merge;
2506 si.name = def->name;
2507 si.dfltCornerRadius = info->dfltCornerRadius;
2508 if (!HandleShapeBody(def, &si, merge, info))
2510 if (!AddShape(info, &si))
2515 /***====================================================================***/
2518 HandleDoodadDef(DoodadDef * def,
2519 unsigned merge, SectionInfo * si, GeometryInfo * info)
2521 ExprResult elem, field;
2526 if (def->common.stmtType == StmtIndicatorMapDef)
2528 def->common.stmtType = StmtDoodadDef;
2529 def->type = XkbIndicatorDoodad;
2531 InitDoodadInfo(&new, def->type, si, info);
2532 new.name = def->name;
2533 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2535 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2536 return 0; /* internal error, already reported */
2537 if (elem.str != NULL)
2539 WARN("Assignment to field of unknown element in doodad %s\n",
2541 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2544 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2550 if (!AddDoodad(si, info, &new))
2552 ClearDoodadInfo(&new);
2556 /***====================================================================***/
2559 HandleOverlayDef(OverlayDef * def,
2560 unsigned merge, SectionInfo * si, GeometryInfo * info)
2562 OverlayKeyDef *keyDef;
2563 OverlayKeyInfo *key;
2566 if ((def->nKeys < 1) && (warningLevel > 3))
2568 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2569 XkbcAtomText(def->name), scText(si));
2570 ACTION("Overlay ignored\n");
2573 bzero(&ol, sizeof(OverlayInfo));
2574 ol.name = def->name;
2575 for (keyDef = def->keys; keyDef;
2576 keyDef = (OverlayKeyDef *) keyDef->common.next)
2578 key = uTypedCalloc(1, OverlayKeyInfo);
2579 if ((!key) && warningLevel > 0)
2581 WSGO("Couldn't allocate OverlayKeyInfo\n");
2582 ACTION("Overlay %s for section %s will be incomplete\n",
2583 XkbcAtomText(ol.name), scText(si));
2586 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2587 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2588 key->sectionRow = _GOK_UnknownRow;
2589 key->overlayRow = _GOK_UnknownRow;
2590 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2591 (CommonInfo *) key);
2594 if (!AddOverlay(si, info, &ol))
2596 ClearOverlayInfo(&ol);
2600 /***====================================================================***/
2603 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2609 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2611 if (expr->op == OpAssign)
2615 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2616 return False; /* internal error, already reported */
2617 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2620 (key, f.str, ndx, expr->value.binary.right, info))
2631 ERROR("Illegal element used in a key definition\n");
2632 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2644 if (!SetKeyField(key, "gap", NULL, expr, info))
2648 if (!SetKeyField(key, "shape", NULL, expr, info))
2652 if (!SetKeyField(key, "name", NULL, expr, info))
2656 ERROR("Cannot determine field for unnamed expression\n");
2657 ACTION("Ignoring key %d in row %d of section %s\n",
2658 row->nKeys + 1, row->section->nRows + 1,
2668 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2669 GeometryInfo * info)
2673 if ((def->nKeys < 1) && (warningLevel > 3))
2675 ERROR("Row in section %s has no keys\n", rowText(row));
2676 ACTION("Section ignored\n");
2679 for (keyDef = def->keys; keyDef != NULL;
2680 keyDef = (KeyDef *) keyDef->common.next)
2682 if (keyDef->common.stmtType == StmtVarDef)
2684 VarDef *var = (VarDef *) keyDef;
2685 ExprResult elem, field;
2687 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2688 return 0; /* internal error, already reported */
2689 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2691 if (!SetRowField(row, field.str, ndx, var->value, info))
2694 else if (uStrCaseCmp(elem.str, "key") == 0)
2697 (&row->dfltKey, field.str, ndx, var->value, info))
2702 WARN("Assignment to field of unknown element in row\n");
2703 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2708 else if (keyDef->common.stmtType == StmtKeyDef)
2711 InitKeyInfo(&key, row, info);
2712 if (keyDef->name != NULL)
2714 int len = strlen(keyDef->name);
2715 if ((len < 1) || (len > XkbKeyNameLength))
2717 ERROR("Illegal name %s for key in section %s\n",
2718 keyDef->name, rowText(row));
2719 ACTION("Section not compiled\n");
2722 bzero(key.name, XkbKeyNameLength + 1);
2723 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2724 key.defs.defined |= _GK_Name;
2726 else if (!HandleComplexKey(keyDef, &key, info))
2728 if (!AddKey(row, &key))
2733 WSGO("Unexpected statement (type %d) in row body\n",
2734 keyDef->common.stmtType);
2742 HandleSectionBody(SectionDef * def,
2743 SectionInfo * si, unsigned merge, GeometryInfo * info)
2748 for (rowDef = def->rows; rowDef != NULL;
2749 rowDef = (RowDef *) rowDef->common.next)
2751 if (rowDef->common.stmtType == StmtVarDef)
2753 VarDef *var = (VarDef *) rowDef;
2754 ExprResult elem, field;
2756 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2757 return 0; /* internal error, already reported */
2758 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2760 if (!SetSectionField(si, field.str, ndx, var->value, info))
2766 else if (uStrCaseCmp(elem.str, "row") == 0)
2769 (&si->dfltRow, field.str, ndx, var->value, info))
2775 else if (uStrCaseCmp(elem.str, "key") == 0)
2777 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2785 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2787 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2795 WARN("Assignment to field of unknown element in section\n");
2796 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2801 else if (rowDef->common.stmtType == StmtRowDef)
2804 InitRowInfo(&row, si, info);
2805 if (!HandleRowBody(rowDef, &row, merge, info))
2807 if (!AddRow(si, &row))
2809 /* ClearRowInfo(&row,info);*/
2811 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2812 (rowDef->common.stmtType == StmtIndicatorMapDef))
2814 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2817 else if (rowDef->common.stmtType == StmtOverlayDef)
2819 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2824 WSGO("Unexpected statement (type %d) in section body\n",
2825 rowDef->common.stmtType);
2829 if (si->nRows != def->nRows)
2831 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2832 (unsigned int) si->nRows);
2833 ACTION("Definition of section %s might be incorrect\n", scText(si));
2839 HandleSectionDef(SectionDef * def,
2840 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2844 if (def->merge != MergeDefault)
2846 InitSectionInfo(&si, info);
2847 si.defs.merge = merge;
2848 si.name = def->name;
2849 if (!HandleSectionBody(def, &si, merge, info))
2851 if (!AddSection(info, &si))
2856 /***====================================================================***/
2859 HandleGeometryFile(XkbFile * file,
2860 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2865 if (merge == MergeDefault)
2866 merge = MergeAugment;
2867 info->name = _XkbDupString(file->name);
2872 switch (stmt->stmtType)
2875 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2876 HandleGeometryFile))
2879 case StmtKeyAliasDef:
2880 if (!HandleAliasDef((KeyAliasDef *) stmt,
2881 merge, info->fileID, &info->aliases))
2887 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2891 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2894 case StmtSectionDef:
2895 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2898 case StmtIndicatorMapDef:
2900 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2905 failWhat = "virtual modfier";
2908 failWhat = "symbol interpretation";
2909 case StmtGroupCompatDef:
2911 failWhat = "group compatibility map";
2912 case StmtKeycodeDef:
2914 failWhat = "key name";
2915 ERROR("Interpretation files may not include other types\n");
2916 ACTION("Ignoring %s definition.\n", failWhat);
2920 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2925 if (info->errorCount > 10)
2928 ERROR("Too many errors\n");
2930 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2937 /***====================================================================***/
2940 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2943 struct xkb_shape * shape;
2944 struct xkb_outline *old_outline, *outline;
2947 si->index = geom->num_shapes;
2949 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2952 WSGO("Couldn't allocate shape in geometry\n");
2953 ACTION("Shape %s not compiled\n", shText(si));
2956 old_outline = si->outlines;
2957 for (i = 0; i < si->nOutlines; i++, old_outline++)
2959 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2962 WSGO("Couldn't allocate outline in shape\n");
2963 ACTION("Shape %s is incomplete\n", shText(si));
2966 n = old_outline->num_points;
2967 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2968 outline->num_points = old_outline->num_points;
2969 outline->corner_radius = old_outline->corner_radius;
2973 n = (si->approx - si->outlines);
2974 shape->approx = &shape->outlines[n];
2978 n = (si->primary - si->outlines);
2979 shape->primary = &shape->outlines[n];
2981 XkbcComputeShapeBounds(shape);
2986 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2988 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2990 if (warningLevel < 9)
2992 ERROR("No position defined for doodad %s\n",
2994 ACTION("Illegal doodad ignored\n");
2998 if ((di->defs.defined & _GD_Priority) == 0)
3000 /* calculate priority -- should be just above previous doodad/row */
3004 case XkbOutlineDoodad:
3005 case XkbSolidDoodad:
3006 if ((di->defs.defined & _GD_Shape) == 0)
3008 ERROR("No shape defined for %s doodad %s\n",
3009 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
3011 ACTION("Incomplete definition ignored\n");
3017 si = FindShape(info, di->shape,
3019 XkbOutlineDoodad ? "outline doodad" :
3020 "solid doodad"), ddText(di));
3022 di->shape = si->name;
3025 ERROR("No legal shape for %s\n", ddText(di));
3026 ACTION("Incomplete definition ignored\n");
3030 if ((di->defs.defined & _GD_Color) == 0)
3032 if (warningLevel > 5)
3034 WARN("No color for doodad %s\n", ddText(di));
3035 ACTION("Using black\n");
3037 di->color = xkb_intern_atom("black");
3041 if ((di->defs.defined & _GD_Text) == 0)
3043 ERROR("No text specified for text doodad %s\n", ddText(di));
3044 ACTION("Illegal doodad definition ignored\n");
3047 if ((di->defs.defined & _GD_Angle) == 0)
3049 if ((di->defs.defined & _GD_Color) == 0)
3051 if (warningLevel > 5)
3053 WARN("No color specified for doodad %s\n", ddText(di));
3054 ACTION("Using black\n");
3056 di->color = xkb_intern_atom("black");
3058 if ((di->defs.defined & _GD_FontSpec) != 0)
3060 if ((di->defs.defined & _GD_FontParts) == 0)
3062 if (warningLevel < 9)
3065 ("Text doodad %s has full and partial font definition\n",
3067 ACTION("Full specification ignored\n");
3069 di->defs.defined &= ~_GD_FontSpec;
3070 di->fontSpec = None;
3072 if ((di->defs.defined & _GD_Font) == 0)
3074 if (warningLevel > 5)
3076 WARN("No font specified for doodad %s\n", ddText(di));
3077 ACTION("Using \"%s\"\n", DFLT_FONT);
3079 di->font = xkb_intern_atom(DFLT_FONT);
3081 if ((di->defs.defined & _GD_FontSlant) == 0)
3083 if (warningLevel > 7)
3085 WARN("No font slant for text doodad %s\n", ddText(di));
3086 ACTION("Using \"%s\"\n", DFLT_SLANT);
3088 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3090 if ((di->defs.defined & _GD_FontWeight) == 0)
3092 if (warningLevel > 7)
3094 WARN("No font weight for text doodad %s\n", ddText(di));
3095 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3097 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3099 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3101 if (warningLevel > 9)
3103 WARN("No font set width for text doodad %s\n", ddText(di));
3104 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3106 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3108 if ((di->defs.defined & _GD_FontVariant) == 0)
3110 if (warningLevel > 9)
3112 WARN("No font variant for text doodad %s\n", ddText(di));
3113 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3115 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3117 if ((di->defs.defined & _GD_FontEncoding) == 0)
3119 if (warningLevel > 7)
3121 WARN("No font encoding for doodad %s\n", ddText(di));
3122 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3124 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3126 if ((di->defs.defined & _GD_FontSize) == 0)
3128 if (warningLevel > 7)
3130 WARN("No font size for text doodad %s\n", ddText(di));
3131 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3133 di->fontSize = DFLT_SIZE;
3135 if ((di->defs.defined & _GD_Height) == 0)
3137 unsigned size, nLines;
3139 size = (di->fontSize * 120) / 100;
3140 size = (size * 254) / 720; /* convert to mm/10 */
3141 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3147 if (warningLevel > 5)
3149 WARN("No height for text doodad %s\n", ddText(di));
3150 ACTION("Using calculated height %s millimeters\n",
3151 XkbcGeomFPText(size));
3155 if ((di->defs.defined & _GD_Width) == 0)
3157 unsigned width, tmp;
3160 for (str = XkbcAtomText(di->text); *str; str++)
3173 width *= (di->height * 2) / 3;
3174 if (warningLevel > 5)
3176 WARN("No width for text doodad %s\n", ddText(di));
3177 ACTION("Using calculated width %s millimeters\n",
3178 XkbcGeomFPText(width));
3183 case XkbIndicatorDoodad:
3184 if ((di->defs.defined & _GD_Shape) == 0)
3186 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3187 ACTION("Incomplete definition ignored\n");
3193 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3195 di->shape = si->name;
3198 ERROR("No legal shape for doodad %s\n", ddText(di));
3199 ACTION("Incomplete definition ignored\n");
3203 if ((di->defs.defined & _GD_Color) == 0)
3205 if (warningLevel > 5)
3207 WARN("No \"on\" color for indicator doodad %s\n",
3209 ACTION("Using green\n");
3211 di->color = xkb_intern_atom("green");
3213 if ((di->defs.defined & _GD_OffColor) == 0)
3215 if (warningLevel > 5)
3217 WARN("No \"off\" color for indicator doodad %s\n",
3219 ACTION("Using black\n");
3221 di->offColor = xkb_intern_atom("black");
3225 if (di->logoName == NULL)
3227 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3228 ACTION("Incomplete definition ignored\n");
3231 if ((di->defs.defined & _GD_Shape) == 0)
3233 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3234 ACTION("Incomplete definition ignored\n");
3240 si = FindShape(info, di->shape, "logo doodad",
3243 di->shape = si->name;
3246 ERROR("No legal shape for %s\n", ddText(di));
3247 ACTION("Incomplete definition ignored\n");
3251 if ((di->defs.defined & _GD_Color) == 0)
3253 if (warningLevel > 5)
3255 WARN("No color for doodad %s\n", ddText(di));
3256 ACTION("Using black\n");
3258 di->color = xkb_intern_atom("black");
3262 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3263 (unsigned int) di->type);
3269 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3272 FontFromParts(uint32_t fontTok,
3275 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3278 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3281 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3282 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3283 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3285 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3286 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3288 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3292 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3293 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3294 rtrn = calloc(totalSize, 1);
3296 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3302 CopyDoodadDef(struct xkb_geometry * geom,
3303 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3306 union xkb_doodad * doodad;
3307 struct xkb_color * color;
3308 struct xkb_shape * shape;
3311 if (!VerifyDoodadInfo(di, info))
3314 doodad = XkbcAddGeomDoodad(geom, section, name);
3317 WSGO("Couldn't allocate doodad in %s\n",
3318 (section ? "section" : "geometry"));
3319 ACTION("Cannot copy doodad %s\n", ddText(di));
3322 doodad->any.type = di->type;
3323 doodad->any.priority = di->priority;
3324 doodad->any.top = di->top;
3325 doodad->any.left = di->left;
3328 case XkbOutlineDoodad:
3329 case XkbSolidDoodad:
3330 si = FindShape(info, di->shape, NULL, NULL);
3333 doodad->shape.angle = di->angle;
3334 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3336 shape = &geom->shapes[si->index];
3337 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3338 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3341 doodad->text.angle = di->angle;
3342 doodad->text.width = di->width;
3343 doodad->text.height = di->height;
3344 if (di->fontSpec == None)
3345 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3348 di->fontVariant, di->fontSize,
3351 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3352 doodad->text.text = XkbcAtomGetString(di->text);
3353 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3355 XkbSetTextDoodadColor(geom, &doodad->text, color);
3357 case XkbIndicatorDoodad:
3358 si = FindShape(info, di->shape, NULL, NULL);
3361 shape = &geom->shapes[si->index];
3362 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3364 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3365 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3366 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3368 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3371 si = FindShape(info, di->shape, NULL, NULL);
3374 doodad->logo.angle = di->angle;
3375 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3377 shape = &geom->shapes[si->index];
3378 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3379 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3380 doodad->logo.logo_name = di->logoName;
3381 di->logoName = NULL;
3387 /***====================================================================***/
3390 VerifyOverlayInfo(struct xkb_geometry * geom,
3391 struct xkb_section * section,
3393 GeometryInfo * info, short rowMap[256], short rowSize[256])
3395 register OverlayKeyInfo *ki, *next;
3396 unsigned long oKey, uKey, sKey;
3397 struct xkb_row * row;
3398 struct xkb_key * key;
3401 /* find out which row each key is in */
3402 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3404 oKey = KeyNameToLong(ki->over);
3405 uKey = KeyNameToLong(ki->under);
3406 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3409 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3412 sKey = KeyNameToLong(key->name.name);
3415 if (warningLevel > 0)
3418 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3419 XkbcKeyNameText(key->name.name),
3420 XkbcAtomText(section->name),
3421 XkbcAtomText(oi->name));
3422 ACTION("Overlay definition ignored\n");
3426 else if (sKey == uKey)
3433 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3436 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3437 XkbcKeyNameText(ki->under),
3438 XkbcAtomText(section->name),
3439 XkbcAtomText(oi->name));
3440 ACTION("Definition ignored\n");
3443 /* now prune out keys that aren't in the section */
3444 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3446 next = (OverlayKeyInfo *) oi->keys->defs.next;
3451 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3453 next = (OverlayKeyInfo *) ki->defs.next;
3454 if (next->sectionRow == _GOK_UnknownRow)
3456 ki->defs.next = next->defs.next;
3459 next = (OverlayKeyInfo *) ki->defs.next;
3464 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3465 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3466 ACTION("Overlay definition ignored\n");
3469 /* now figure out how many rows are defined for the overlay */
3470 bzero(rowSize, sizeof(short) * 256);
3471 for (k = 0; k < 256; k++)
3476 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3478 if (rowMap[ki->sectionRow] == -1)
3479 rowMap[ki->sectionRow] = oi->nRows++;
3480 ki->overlayRow = rowMap[ki->sectionRow];
3481 rowSize[ki->overlayRow]++;
3487 CopyOverlayDef(struct xkb_geometry * geom,
3488 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3491 struct xkb_overlay * ol;
3492 struct xkb_overlay_row * row;
3493 struct xkb_overlay_key * key;
3495 short rowMap[256], rowSize[256];
3498 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3501 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3504 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3505 XkbcAtomText(name), XkbcAtomText(section->name));
3508 for (i = 0; i < oi->nRows; i++)
3511 for (tmp = 0, row_under = -1;
3512 (tmp < section->num_rows) && (row_under < 0); tmp++)
3514 if (rowMap[tmp] == i)
3517 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3520 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3521 i, XkbcAtomText(name), XkbcAtomText(section->name));
3525 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3527 row = &ol->rows[ki->overlayRow];
3528 key = &row->keys[row->num_keys++];
3529 bzero(key, sizeof(struct xkb_overlay_key));
3530 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3531 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3536 /***====================================================================***/
3539 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3541 struct xkb_section * section;
3542 struct xkb_row * row;
3543 struct xkb_key * key;
3547 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3549 if (section == NULL)
3551 WSGO("Couldn't allocate section in geometry\n");
3552 ACTION("Section %s not compiled\n", scText(si));
3555 section->top = si->top;
3556 section->left = si->left;
3557 section->width = si->width;
3558 section->height = si->height;
3559 section->angle = si->angle;
3560 section->priority = si->priority;
3561 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3563 row = XkbcAddGeomRow(section, ri->nKeys);
3566 WSGO("Couldn't allocate row in section\n");
3567 ACTION("Section %s is incomplete\n", scText(si));
3571 row->left = ri->left;
3572 row->vertical = ri->vertical;
3573 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3575 struct xkb_color * color;
3576 if ((ki->defs.defined & _GK_Name) == 0)
3578 ERROR("Key %d of row %d in section %s has no name\n",
3579 (int) ki->index, (int) ri->index, scText(si));
3580 ACTION("Section %s ignored\n", scText(si));
3583 key = XkbcAddGeomKey(row);
3586 WSGO("Couldn't allocate key in row\n");
3587 ACTION("Section %s is incomplete\n", scText(si));
3590 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3592 if (ki->shape == None)
3597 si = FindShape(info, ki->shape, "key", keyText(ki));
3600 key->shape_ndx = si->index;
3602 if (ki->color != None)
3604 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3607 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3608 XkbSetKeyColor(geom, key, color);
3611 if (si->doodads != NULL)
3614 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3616 CopyDoodadDef(geom, section, di, info);
3619 if (si->overlays != NULL)
3622 for (oi = si->overlays; oi != NULL;
3623 oi = (OverlayInfo *) oi->defs.next)
3625 CopyOverlayDef(geom, section, oi, info);
3628 if (XkbcComputeSectionBounds(geom, section))
3630 /* 7/6/94 (ef) -- check for negative origin and translate */
3631 if ((si->defs.defined & _GS_Width) == 0)
3632 section->width = section->bounds.x2;
3633 if ((si->defs.defined & _GS_Height) == 0)
3634 section->height = section->bounds.y2;
3639 /***====================================================================***/
3642 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3646 InitGeometryInfo(&info, file->id, merge);
3647 HandleGeometryFile(file, xkb, merge, &info);
3649 if (info.errorCount == 0)
3651 struct xkb_geometry * geom;
3652 struct xkb_geometry_sizes sizes;
3653 bzero(&sizes, sizeof(sizes));
3654 sizes.which = XkbGeomAllMask;
3655 sizes.num_properties = info.nProps;
3656 sizes.num_colors = 8;
3657 sizes.num_shapes = info.nShapes;
3658 sizes.num_sections = info.nSections;
3659 sizes.num_doodads = info.nDoodads;
3660 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3662 WSGO("Couldn't allocate GeometryRec\n");
3663 ACTION("Geometry not compiled\n");
3668 geom->width_mm = info.widthMM;
3669 geom->height_mm = info.heightMM;
3670 if (info.name != NULL)
3672 geom->name = xkb_intern_atom(info.name);
3673 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3674 xkb->names->geometry = geom->name;
3676 if (info.fontSpec != None)
3677 geom->label_font = XkbcAtomGetString(info.fontSpec);
3679 geom->label_font = FontFromParts(info.font, info.fontWeight,
3685 XkbcAddGeomColor(geom, "black", geom->num_colors);
3686 XkbcAddGeomColor(geom, "white", geom->num_colors);
3688 if (info.baseColor == None)
3689 info.baseColor = xkb_intern_atom("white");
3690 if (info.labelColor == None)
3691 info.labelColor = xkb_intern_atom("black");
3693 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3696 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3702 for (pi = info.props; pi != NULL;
3703 pi = (PropertyInfo *) pi->defs.next)
3705 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3712 for (si = info.shapes; si != NULL;
3713 si = (ShapeInfo *) si->defs.next)
3715 if (!CopyShapeDef(geom, si))
3722 for (si = info.sections; si != NULL;
3723 si = (SectionInfo *) si->defs.next)
3725 if (!CopySectionDef(geom, si, &info))
3732 for (di = info.doodads; di != NULL;
3733 di = (DoodadInfo *) di->defs.next)
3735 if (!CopyDoodadDef(geom, NULL, di, &info))
3740 ApplyAliases(xkb, True, &info.aliases);
3741 ClearGeometryInfo(&info);