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 #include <X11/extensions/XKBgeomcommon.h>
42 #define DFLT_FONT "helvetica"
43 #define DFLT_SLANT "r"
44 #define DFLT_WEIGHT "medium"
45 #define DFLT_SET_WIDTH "normal"
46 #define DFLT_VARIANT ""
47 #define DFLT_ENCODING "iso8859-1"
50 typedef struct _PropertyInfo
57 #define _GSh_Outlines (1<<1)
58 #define _GSh_Approx (1<<2)
59 #define _GSh_Primary (1<<3)
60 typedef struct _ShapeInfo
65 unsigned short nOutlines;
66 unsigned short szOutlines;
67 XkbOutlinePtr outlines;
69 XkbOutlinePtr primary;
74 ((s) ? XkbcAtomText((s)->name) : "default shape")
76 #define _GD_Priority (1<<0)
77 #define _GD_Top (1<<1)
78 #define _GD_Left (1<<2)
79 #define _GD_Angle (1<<3)
80 #define _GD_Shape (1<<4)
81 #define _GD_FontVariant (1<<4) /* CHEATING */
82 #define _GD_Corner (1<<5)
83 #define _GD_Width (1<<5) /* CHEATING */
84 #define _GD_Color (1<<6)
85 #define _GD_OffColor (1<<7)
86 #define _GD_Height (1<<7) /* CHEATING */
87 #define _GD_Text (1<<8)
88 #define _GD_Font (1<<9)
89 #define _GD_FontSlant (1<<10)
90 #define _GD_FontWeight (1<<11)
91 #define _GD_FontSetWidth (1<<12)
92 #define _GD_FontSize (1<<13)
93 #define _GD_FontEncoding (1<<14)
94 #define _GD_FontSpec (1<<15)
97 #define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
99 typedef struct _DoodadInfo
104 unsigned char priority;
108 unsigned short corner;
109 unsigned short width;
110 unsigned short height;
120 unsigned short fontSize;
124 struct _SectionInfo *section;
131 #define _GK_Default (1<<0)
132 #define _GK_Name (1<<1)
133 #define _GK_Gap (1<<2)
134 #define _GK_Shape (1<<3)
135 #define _GK_Color (1<<4)
136 typedef struct _KeyInfo
144 struct _RowInfo *row;
146 #define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
148 #define _GR_Default (1<<0)
149 #define _GR_Vertical (1<<1)
150 #define _GR_Top (1<<2)
151 #define _GR_Left (1<<3)
152 typedef struct _RowInfo
159 unsigned short nKeys;
162 struct _SectionInfo *section;
165 ((r) ? XkbcAtomText((r)->section->name) : "default")
167 #define _GOK_UnknownRow -1
168 typedef struct _OverlayKeyInfo
173 char over[XkbKeyNameLength + 1];
174 char under[XkbKeyNameLength + 1];
177 typedef struct _OverlayInfo
181 unsigned short nRows;
182 unsigned short nKeys;
183 OverlayKeyInfo *keys;
186 ((o) ? XkbcAtomText((o)->name) : "default")
189 #define _GS_Default (1<<0)
190 #define _GS_Name (1<<1)
191 #define _GS_Top (1<<2)
192 #define _GS_Left (1<<3)
193 #define _GS_Width (1<<4)
194 #define _GS_Height (1<<5)
195 #define _GS_Angle (1<<6)
196 #define _GS_Priority (1<<7)
197 typedef struct _SectionInfo
203 unsigned short width;
204 unsigned short height;
205 unsigned short angle;
206 unsigned short nRows;
207 unsigned short nDoodads;
208 unsigned short nOverlays;
209 unsigned char priority;
210 unsigned char nextDoodadPriority;
214 DoodadInfo *dfltDoodads;
215 OverlayInfo *overlays;
216 struct _GeometryInfo *geometry;
219 ((s) ? XkbcAtomText((s)->name) : "default")
221 typedef struct _GeometryInfo
227 unsigned nextPriority;
234 SectionInfo *sections;
248 int dfltCornerRadius;
249 SectionInfo dfltSection;
250 DoodadInfo *dfltDoodads;
255 ddText(DoodadInfo * di)
261 strcpy(buf, "default");
266 sprintf(buf, "%s in section %s",
267 XkbcAtomText(di->name), scText(di->section));
270 return XkbcAtomText(di->name);
273 /***====================================================================***/
276 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
278 pi->defs.defined = 0;
279 pi->defs.fileID = info->fileID;
280 pi->defs.merge = info->merge;
281 pi->name = pi->value = NULL;
286 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
291 if (info->props == pi)
296 for (tmp = pi; tmp != NULL; tmp = next)
302 tmp->name = tmp->value = NULL;
303 next = (PropertyInfo *) tmp->defs.next;
310 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
313 if (key != &row->dfltKey)
316 strcpy(key->name, "unknown");
317 key->defs.defined &= ~_GK_Default;
321 bzero(key, sizeof(KeyInfo));
322 strcpy(key->name, "default");
323 key->defs.defined = _GK_Default;
324 key->defs.fileID = info->fileID;
325 key->defs.merge = info->merge;
326 key->defs.next = NULL;
333 ClearKeyInfo(KeyInfo * key)
335 key->defs.defined &= ~_GK_Default;
336 strcpy(key->name, "default");
344 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
349 if (row->keys == key)
354 for (tmp = key; tmp != NULL; tmp = next)
357 next = (KeyInfo *) tmp->defs.next;
364 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
366 if (row != §ion->dfltRow)
368 *row = section->dfltRow;
369 row->defs.defined &= ~_GR_Default;
373 bzero(row, sizeof(RowInfo *));
374 row->defs.defined = _GR_Default;
375 row->defs.fileID = info->fileID;
376 row->defs.merge = info->merge;
377 row->defs.next = NULL;
378 row->section = section;
381 InitKeyInfo(&row->dfltKey, row, info);
387 ClearRowInfo(RowInfo * row, GeometryInfo * info)
389 row->defs.defined &= ~_GR_Default;
390 row->top = row->left = 0;
391 row->vertical = False;
394 FreeKeys(row->keys, row, info);
395 ClearKeyInfo(&row->dfltKey);
396 row->dfltKey.defs.defined |= _GK_Default;
401 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
406 if (row == section->rows)
409 section->rows = NULL;
411 for (tmp = row; tmp != NULL; tmp = next)
413 ClearRowInfo(tmp, info);
414 next = (RowInfo *) tmp->defs.next;
421 FindDoodadByType(DoodadInfo * di, unsigned type)
425 if (di->type == type)
427 di = (DoodadInfo *) di->defs.next;
433 FindDoodadByName(DoodadInfo * di, Atom name)
437 if (di->name == name)
439 di = (DoodadInfo *) di->defs.next;
445 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
451 if (si && si->dfltDoodads)
452 dflt = FindDoodadByType(si->dfltDoodads, type);
453 if ((dflt == NULL) && (info->dfltDoodads))
454 dflt = FindDoodadByType(info->dfltDoodads, type);
458 di->defs.next = NULL;
462 bzero(di, sizeof(DoodadInfo));
463 di->defs.fileID = info->fileID;
469 di->priority = si->nextDoodadPriority++;
470 #if XkbGeomMaxPriority < 255
471 if (si->nextDoodadPriority > XkbGeomMaxPriority)
472 si->nextDoodadPriority = XkbGeomMaxPriority;
477 di->priority = info->nextPriority++;
478 if (info->nextPriority > XkbGeomMaxPriority)
479 info->nextPriority = XkbGeomMaxPriority;
485 ClearDoodadInfo(DoodadInfo * di)
490 bzero(di, sizeof(DoodadInfo));
492 di->defs.defined = 0;
497 ClearOverlayInfo(OverlayInfo * ol)
501 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
508 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
515 if (si->doodads == di)
520 if (si->dfltDoodads == di)
521 si->dfltDoodads = NULL;
523 if (info->doodads == di)
525 info->doodads = NULL;
528 if (info->dfltDoodads == di)
529 info->dfltDoodads = NULL;
530 for (tmp = di; tmp != NULL; tmp = next)
532 next = (DoodadInfo *) tmp->defs.next;
533 ClearDoodadInfo(tmp);
540 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
542 if (si != &info->dfltSection)
544 *si = info->dfltSection;
545 si->defs.defined &= ~_GS_Default;
546 si->name = XkbcInternAtom("unknown", False);
547 si->priority = info->nextPriority++;
548 if (info->nextPriority > XkbGeomMaxPriority)
549 info->nextPriority = XkbGeomMaxPriority;
553 bzero(si, sizeof(SectionInfo));
554 si->defs.fileID = info->fileID;
555 si->defs.merge = info->merge;
556 si->defs.next = NULL;
558 si->name = XkbcInternAtom("default", False);
559 InitRowInfo(&si->dfltRow, si, info);
565 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
571 into->defs.fileID = defs.fileID;
572 into->defs.merge = defs.merge;
573 into->defs.next = NULL;
574 into->dfltRow.defs.fileID = defs.fileID;
575 into->dfltRow.defs.merge = defs.merge;
576 into->dfltRow.defs.next = NULL;
577 into->dfltRow.section = into;
578 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
579 into->dfltRow.dfltKey.defs.merge = defs.merge;
580 into->dfltRow.dfltKey.defs.next = NULL;
581 into->dfltRow.dfltKey.row = &into->dfltRow;
586 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
589 si->defs.defined &= ~_GS_Default;
590 si->name = XkbcInternAtom("default", False);
591 si->top = si->left = 0;
592 si->width = si->height = 0;
596 FreeRows(si->rows, si, info);
599 ClearRowInfo(&si->dfltRow, info);
602 FreeDoodads(si->doodads, si, info);
605 si->dfltRow.defs.defined = _GR_Default;
610 FreeSections(SectionInfo * si, GeometryInfo * info)
615 if (si == info->sections)
618 info->sections = NULL;
620 for (tmp = si; tmp != NULL; tmp = next)
622 ClearSectionInfo(tmp, info);
623 next = (SectionInfo *) tmp->defs.next;
630 FreeShapes(ShapeInfo * si, GeometryInfo * info)
635 if (si == info->shapes)
640 for (tmp = si; tmp != NULL; tmp = next)
645 for (i = 0; i < tmp->nOutlines; i++)
647 if (tmp->outlines[i].points != NULL)
649 uFree(tmp->outlines[i].points);
650 tmp->outlines[i].num_points = 0;
651 tmp->outlines[i].points = NULL;
654 uFree(tmp->outlines);
657 tmp->outlines = NULL;
658 tmp->primary = tmp->approx = NULL;
660 next = (ShapeInfo *) tmp->defs.next;
666 /***====================================================================***/
669 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
671 bzero(info, sizeof(GeometryInfo));
672 info->fileID = fileID;
674 InitSectionInfo(&info->dfltSection, info);
675 info->dfltSection.defs.defined = _GS_Default;
680 ClearGeometryInfo(GeometryInfo * info)
686 FreeProperties(info->props, info);
688 FreeShapes(info->shapes, info);
690 FreeSections(info->sections, info);
693 info->dfltCornerRadius = 0;
694 ClearSectionInfo(&info->dfltSection, info);
695 info->dfltSection.defs.defined = _GS_Default;
697 ClearAliases(&info->aliases);
701 /***====================================================================***/
703 static PropertyInfo *
704 NextProperty(GeometryInfo * info)
708 pi = uTypedAlloc(PropertyInfo);
711 bzero((char *) pi, sizeof(PropertyInfo));
712 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
719 static PropertyInfo *
720 FindProperty(GeometryInfo * info, char *name)
726 for (old = info->props; old != NULL;
727 old = (PropertyInfo *) old->defs.next)
729 if ((old->name) && (uStringEqual(name, old->name)))
736 AddProperty(GeometryInfo * info, PropertyInfo * new)
740 if ((!new) || (!new->value) || (!new->name))
742 old = FindProperty(info, new->name);
745 if ((new->defs.merge == MergeReplace)
746 || (new->defs.merge == MergeOverride))
748 if (((old->defs.fileID == new->defs.fileID)
749 && (warningLevel > 0)) || (warningLevel > 9))
751 WARN("Multiple definitions for the \"%s\" property\n",
753 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
758 old->value = _XkbDupString(new->value);
761 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
762 || (warningLevel > 9))
764 WARN("Multiple definitions for \"%s\" property\n", new->name);
765 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
771 if ((new = NextProperty(info)) == NULL)
773 new->defs.next = NULL;
774 new->name = _XkbDupString(old->name);
775 new->value = _XkbDupString(old->value);
779 /***====================================================================***/
782 NextShape(GeometryInfo * info)
786 si = uTypedAlloc(ShapeInfo);
789 bzero((char *) si, sizeof(ShapeInfo));
790 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
793 si->dfltCornerRadius = info->dfltCornerRadius;
799 FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
803 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
805 if (name == old->name)
811 WARN("Unknown shape \"%s\" for %s %s\n",
812 XkbcAtomText(name), type, which);
815 ACTION("Using default shape %s instead\n", shText(old));
818 ACTION("No default shape; definition ignored\n");
825 AddShape(GeometryInfo * info, ShapeInfo * new)
829 old = FindShape(info, new->name, NULL, NULL);
832 if ((new->defs.merge == MergeReplace)
833 || (new->defs.merge == MergeOverride))
835 ShapeInfo *next = (ShapeInfo *) old->defs.next;
836 if (((old->defs.fileID == new->defs.fileID)
837 && (warningLevel > 0)) || (warningLevel > 9))
839 WARN("Duplicate shape name \"%s\"\n", shText(old));
840 ACTION("Using last definition\n");
843 old->defs.next = &next->defs;
846 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
847 || (warningLevel > 9))
849 WARN("Multiple shapes named \"%s\"\n", shText(old));
850 ACTION("Using first definition\n");
855 if ((new = NextShape(info)) == NULL)
858 new->defs.next = NULL;
859 old->szOutlines = old->nOutlines = 0;
860 old->outlines = NULL;
866 /***====================================================================***/
869 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
873 next = into->defs.next;
874 ClearDoodadInfo(into);
876 into->defs.next = next;
877 next = from->defs.next;
878 ClearDoodadInfo(from);
879 from->defs.next = next;
884 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
888 di = uTypedCalloc(1, DoodadInfo);
894 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
900 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
907 NextDoodad(SectionInfo * si, GeometryInfo * info)
911 di = uTypedCalloc(1, DoodadInfo);
916 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
923 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
932 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
936 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
939 if ((new->defs.merge == MergeReplace)
940 || (new->defs.merge == MergeOverride))
942 if (((old->defs.fileID == new->defs.fileID)
943 && (warningLevel > 0)) || (warningLevel > 9))
945 WARN("Multiple doodads named \"%s\"\n",
946 XkbcAtomText(old->name));
947 ACTION("Using last definition\n");
949 ReplaceDoodad(old, new);
953 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
954 || (warningLevel > 9))
956 WARN("Multiple doodads named \"%s\"\n",
957 XkbcAtomText(old->name));
958 ACTION("Using first definition\n");
963 if ((new = NextDoodad(si, info)) == NULL)
965 ReplaceDoodad(new, old);
967 new->defs.next = NULL;
972 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
974 DoodadInfo *dflt = NULL;
977 if (uStrCaseCmp(name, "outline") == 0)
978 type = XkbOutlineDoodad;
979 else if (uStrCaseCmp(name, "solid") == 0)
980 type = XkbSolidDoodad;
981 else if (uStrCaseCmp(name, "text") == 0)
982 type = XkbTextDoodad;
983 else if (uStrCaseCmp(name, "indicator") == 0)
984 type = XkbIndicatorDoodad;
985 else if (uStrCaseCmp(name, "logo") == 0)
986 type = XkbLogoDoodad;
989 if ((si) && (si->dfltDoodads))
990 dflt = FindDoodadByType(si->dfltDoodads, type);
991 if ((!dflt) && (info->dfltDoodads))
992 dflt = FindDoodadByType(info->dfltDoodads, type);
995 dflt = NextDfltDoodad(si, info);
1005 /***====================================================================***/
1008 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1012 for (old = si->overlays; old != NULL;
1013 old = (OverlayInfo *) old->defs.next)
1015 if (old->name == new->name)
1020 if ((new->defs.merge == MergeReplace)
1021 || (new->defs.merge == MergeOverride))
1023 if (((old->defs.fileID == new->defs.fileID)
1024 && (warningLevel > 0)) || (warningLevel > 9))
1027 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1028 XkbcAtomText(old->name), XkbcAtomText(si->name));
1029 ACTION("Using last definition\n");
1031 ClearOverlayInfo(old);
1032 old->nKeys = new->nKeys;
1033 old->keys = new->keys;
1038 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1039 || (warningLevel > 9))
1041 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1042 XkbcAtomText(old->name), XkbcAtomText(si->name));
1043 ACTION("Using first definition\n");
1048 new = uTypedCalloc(1, OverlayInfo);
1051 if (warningLevel > 0)
1053 WSGO("Couldn't allocate a new OverlayInfo\n");
1055 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1056 XkbcAtomText(old->name), XkbcAtomText(si->name));
1063 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1064 (CommonInfo *) new);
1069 /***====================================================================***/
1071 static SectionInfo *
1072 NextSection(GeometryInfo * info)
1076 si = uTypedAlloc(SectionInfo);
1079 *si = info->dfltSection;
1080 si->defs.defined &= ~_GS_Default;
1081 si->defs.next = NULL;
1085 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1092 static SectionInfo *
1093 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1097 for (old = info->sections; old != NULL;
1098 old = (SectionInfo *) old->defs.next)
1100 if (new->name == old->name)
1107 AddSection(GeometryInfo * info, SectionInfo * new)
1111 old = FindMatchingSection(info, new);
1115 if ((new->defs.merge == MergeReplace)
1116 || (new->defs.merge == MergeOverride))
1118 SectionInfo *next = (SectionInfo *) old->defs.next;
1119 if (((old->defs.fileID == new->defs.fileID)
1120 && (warningLevel > 0)) || (warningLevel > 9))
1122 WARN("Duplicate shape name \"%s\"\n", shText(old));
1123 ACTION("Using last definition\n");
1126 old->defs.next = &next->defs;
1129 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1130 || (warningLevel > 9))
1132 WARN("Multiple shapes named \"%s\"\n", shText(old));
1133 ACTION("Using first definition\n");
1137 WARN("Don't know how to merge sections yet\n");
1141 if ((new = NextSection(info)) == NULL)
1144 new->defs.next = NULL;
1145 old->nRows = old->nDoodads = old->nOverlays = 0;
1147 old->doodads = NULL;
1148 old->overlays = NULL;
1152 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1160 /***====================================================================***/
1163 NextRow(SectionInfo * si)
1167 row = uTypedAlloc(RowInfo);
1171 row->defs.defined &= ~_GR_Default;
1172 row->defs.next = NULL;
1176 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1177 row->index = si->nRows++;
1183 AddRow(SectionInfo * si, RowInfo * new)
1188 if ((new = NextRow(si)) == NULL)
1191 new->defs.next = NULL;
1197 /***====================================================================***/
1200 NextKey(RowInfo * row)
1204 key = uTypedAlloc(KeyInfo);
1207 *key = row->dfltKey;
1208 key->defs.defined &= ~_GK_Default;
1209 key->defs.next = NULL;
1210 key->index = row->nKeys++;
1216 AddKey(RowInfo * row, KeyInfo * new)
1221 if ((new = NextKey(row)) == NULL)
1224 new->defs.next = NULL;
1226 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1230 /***====================================================================***/
1233 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1238 if (from->errorCount > 0)
1240 into->errorCount += from->errorCount;
1243 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1244 if (into->name == NULL)
1246 into->name = from->name;
1249 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1250 into->widthMM = from->widthMM;
1251 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1252 into->heightMM = from->heightMM;
1253 if ((into->font == None) || ((from->font != None) && clobber))
1254 into->font = from->font;
1255 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1256 into->fontSlant = from->fontSlant;
1257 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1258 into->fontWeight = from->fontWeight;
1259 if ((into->fontSetWidth == None)
1260 || ((from->fontSetWidth != None) && clobber))
1261 into->fontSetWidth = from->fontSetWidth;
1262 if ((into->fontVariant == None)
1263 || ((from->fontVariant != None) && clobber))
1264 into->fontVariant = from->fontVariant;
1265 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1266 into->fontSize = from->fontSize;
1267 if ((into->fontEncoding == None)
1268 || ((from->fontEncoding != None) && clobber))
1269 into->fontEncoding = from->fontEncoding;
1270 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1271 into->fontSpec = from->fontSpec;
1272 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1273 into->baseColor = from->baseColor;
1274 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1275 into->labelColor = from->labelColor;
1276 into->nextPriority = from->nextPriority;
1277 if (from->props != NULL)
1280 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1282 if (!AddProperty(into, pi))
1286 if (from->shapes != NULL)
1290 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1292 if (!AddShape(into, si))
1296 if (from->sections != NULL)
1300 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1302 if (!AddSection(into, si))
1306 if (from->doodads != NULL)
1310 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1312 if (!AddDoodad(NULL, into, di))
1316 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1321 typedef void (*FileHandler) (XkbFile * /* file */ ,
1322 XkbcDescPtr /* xkb */ ,
1323 unsigned /* merge */ ,
1324 GeometryInfo * /* info */
1328 HandleIncludeGeometry(IncludeStmt * stmt, XkbcDescPtr xkb, GeometryInfo * info,
1333 GeometryInfo included;
1337 if ((stmt->file == NULL) && (stmt->map == NULL))
1341 bzero(info, sizeof(GeometryInfo));
1343 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1345 InitGeometryInfo(&included, rtrn->id, newMerge);
1346 included.nextPriority = info->nextPriority;
1347 included.dfltCornerRadius = info->dfltCornerRadius;
1348 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1349 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1350 if (stmt->stmt != NULL)
1352 if (included.name != NULL)
1353 uFree(included.name);
1354 included.name = stmt->stmt;
1360 info->errorCount += 10;
1363 if ((stmt->next != NULL) && (included.errorCount < 1))
1367 GeometryInfo next_incl;
1369 for (next = stmt->next; next != NULL; next = next->next)
1371 if ((next->file == NULL) && (next->map == NULL))
1374 MergeIncludedGeometry(&included, info, next->merge);
1375 ClearGeometryInfo(info);
1377 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1379 InitGeometryInfo(&next_incl, rtrn->id, op);
1380 next_incl.nextPriority = included.nextPriority;
1381 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1382 DupSectionInfo(&next_incl.dfltSection,
1383 &included.dfltSection, &included);
1384 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1385 MergeIncludedGeometry(&included, &next_incl, op);
1386 ClearGeometryInfo(&next_incl);
1390 info->errorCount += 10;
1399 MergeIncludedGeometry(info, &included, newMerge);
1400 ClearGeometryInfo(&included);
1402 return (info->errorCount == 0);
1406 SetShapeField(ShapeInfo * si,
1408 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1412 if ((uStrCaseCmp(field, "radius") == 0)
1413 || (uStrCaseCmp(field, "corner") == 0)
1414 || (uStrCaseCmp(field, "cornerradius") == 0))
1416 if (arrayNdx != NULL)
1419 return ReportNotArray("key shape", field, shText(si));
1421 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1424 return ReportBadType("key shape", field, shText(si), "number");
1427 si->dfltCornerRadius = tmp.ival;
1429 info->dfltCornerRadius = tmp.ival;
1433 return ReportBadField("key shape", field, shText(si));
1437 SetShapeDoodadField(DoodadInfo * di,
1440 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1443 const char *typeName;
1446 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1447 if ((!uStrCaseCmp(field, "corner"))
1448 || (!uStrCaseCmp(field, "cornerradius")))
1450 if (arrayNdx != NULL)
1453 return ReportNotArray(typeName, field, ddText(di));
1455 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1458 return ReportBadType(typeName, field, ddText(di), "number");
1460 di->defs.defined |= _GD_Corner;
1461 di->corner = tmp.ival;
1464 else if (uStrCaseCmp(field, "angle") == 0)
1466 if (arrayNdx != NULL)
1469 return ReportNotArray(typeName, field, ddText(di));
1471 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1474 return ReportBadType(typeName, field, ddText(di), "number");
1476 di->defs.defined |= _GD_Angle;
1477 di->angle = tmp.ival;
1480 else if (uStrCaseCmp(field, "shape") == 0)
1482 if (arrayNdx != NULL)
1485 return ReportNotArray(typeName, field, ddText(di));
1487 if (!ExprResolveString(value, &tmp, NULL, NULL))
1490 return ReportBadType(typeName, field, ddText(di), "string");
1492 di->shape = XkbcInternAtom(tmp.str, False);
1493 di->defs.defined |= _GD_Shape;
1496 return ReportBadField(typeName, field, ddText(di));
1499 #define FIELD_STRING 0
1500 #define FIELD_SHORT 1
1501 #define FIELD_USHORT 2
1504 SetTextDoodadField(DoodadInfo * di,
1507 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1512 char *typeName = "text doodad";
1517 unsigned short *uval;
1520 if (uStrCaseCmp(field, "angle") == 0)
1522 if (arrayNdx != NULL)
1525 return ReportNotArray(typeName, field, ddText(di));
1527 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1530 return ReportBadType(typeName, field, ddText(di), "number");
1532 di->defs.defined |= _GD_Angle;
1533 di->angle = tmp.ival;
1536 if (uStrCaseCmp(field, "width") == 0)
1538 type = FIELD_USHORT;
1539 pField.uval = &di->width;
1542 else if (uStrCaseCmp(field, "height") == 0)
1544 type = FIELD_USHORT;
1545 pField.uval = &di->height;
1548 else if (uStrCaseCmp(field, "text") == 0)
1550 type = FIELD_STRING;
1551 pField.str = &di->text;
1554 else if (uStrCaseCmp(field, "font") == 0)
1556 type = FIELD_STRING;
1557 pField.str = &di->font;
1560 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1561 (uStrCaseCmp(field, "slant") == 0))
1563 type = FIELD_STRING;
1564 pField.str = &di->fontSlant;
1565 def = _GD_FontSlant;
1567 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1568 (uStrCaseCmp(field, "weight") == 0))
1570 type = FIELD_STRING;
1571 pField.str = &di->fontWeight;
1572 def = _GD_FontWeight;
1574 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1575 (uStrCaseCmp(field, "setwidth") == 0))
1577 type = FIELD_STRING;
1578 pField.str = &di->fontSetWidth;
1579 def = _GD_FontSetWidth;
1581 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1582 (uStrCaseCmp(field, "variant") == 0))
1584 type = FIELD_STRING;
1585 pField.str = &di->fontVariant;
1586 def = _GD_FontVariant;
1588 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1589 (uStrCaseCmp(field, "encoding") == 0))
1591 type = FIELD_STRING;
1592 pField.str = &di->fontEncoding;
1593 def = _GD_FontEncoding;
1595 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1596 (uStrCaseCmp(field, "xfontname") == 0))
1598 type = FIELD_STRING;
1599 pField.str = &di->fontSpec;
1602 else if (uStrCaseCmp(field, "fontsize") == 0)
1604 type = FIELD_USHORT;
1605 pField.uval = &di->fontSize;
1610 return ReportBadField(typeName, field, ddText(di));
1612 if (arrayNdx != NULL)
1615 return ReportNotArray(typeName, field, ddText(di));
1617 if (type == FIELD_STRING)
1619 if (!ExprResolveString(value, &tmp, NULL, NULL))
1622 return ReportBadType(typeName, field, ddText(di), "string");
1624 di->defs.defined |= def;
1625 *pField.str = XkbcInternAtom(tmp.str, False);
1629 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
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, NULL, NULL))
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 = XkbcInternAtom(tmp.str, False);
1678 else if (uStrCaseCmp(field, "offcolor") == 0)
1680 di->defs.defined |= _GD_OffColor;
1681 di->offColor = XkbcInternAtom(tmp.str, False);
1683 else if (uStrCaseCmp(field, "shape") == 0)
1685 di->defs.defined |= _GD_Shape;
1686 di->shape = XkbcInternAtom(tmp.str, False);
1690 return ReportBadField("indicator doodad", field, ddText(di));
1694 SetLogoDoodadField(DoodadInfo * di,
1697 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1700 char *typeName = "logo doodad";
1702 if ((!uStrCaseCmp(field, "corner"))
1703 || (!uStrCaseCmp(field, "cornerradius")))
1705 if (arrayNdx != NULL)
1708 return ReportNotArray(typeName, field, ddText(di));
1710 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1713 return ReportBadType(typeName, field, ddText(di), "number");
1715 di->defs.defined |= _GD_Corner;
1716 di->corner = tmp.ival;
1719 else if (uStrCaseCmp(field, "angle") == 0)
1721 if (arrayNdx != NULL)
1724 return ReportNotArray(typeName, field, ddText(di));
1726 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1729 return ReportBadType(typeName, field, ddText(di), "number");
1731 di->defs.defined |= _GD_Angle;
1732 di->angle = tmp.ival;
1735 else if (uStrCaseCmp(field, "shape") == 0)
1737 if (arrayNdx != NULL)
1740 return ReportNotArray(typeName, field, ddText(di));
1742 if (!ExprResolveString(value, &tmp, NULL, NULL))
1745 return ReportBadType(typeName, field, ddText(di), "string");
1747 di->shape = XkbcInternAtom(tmp.str, False);
1748 di->defs.defined |= _GD_Shape;
1751 else if ((!uStrCaseCmp(field, "logoname"))
1752 || (!uStrCaseCmp(field, "name")))
1754 if (arrayNdx != NULL)
1757 return ReportNotArray(typeName, field, ddText(di));
1759 if (!ExprResolveString(value, &tmp, NULL, NULL))
1762 return ReportBadType(typeName, field, ddText(di),
1765 di->logoName = _XkbDupString(tmp.str);
1768 return ReportBadField(typeName, field, ddText(di));
1772 SetDoodadField(DoodadInfo * di,
1775 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1779 if (uStrCaseCmp(field, "priority") == 0)
1781 if (arrayNdx != NULL)
1784 return ReportNotArray("doodad", field, ddText(di));
1786 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1789 return ReportBadType("doodad", field, ddText(di), "integer");
1791 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1794 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1795 tmp.ival, XkbGeomMaxPriority);
1796 ACTION("Priority for doodad %s not changed", ddText(di));
1799 di->defs.defined |= _GD_Priority;
1800 di->priority = tmp.ival;
1803 else if (uStrCaseCmp(field, "left") == 0)
1805 if (arrayNdx != NULL)
1808 return ReportNotArray("doodad", field, ddText(di));
1810 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1813 return ReportBadType("doodad", field, ddText(di), "number");
1815 di->defs.defined |= _GD_Left;
1816 di->left = tmp.ival;
1819 else if (uStrCaseCmp(field, "top") == 0)
1821 if (arrayNdx != NULL)
1824 return ReportNotArray("doodad", field, ddText(di));
1826 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1829 return ReportBadType("doodad", field, ddText(di), "number");
1831 di->defs.defined |= _GD_Top;
1835 else if (uStrCaseCmp(field, "color") == 0)
1837 if (arrayNdx != NULL)
1840 return ReportNotArray("doodad", field, ddText(di));
1842 if (!ExprResolveString(value, &tmp, NULL, NULL))
1845 return ReportBadType("doodad", field, ddText(di), "string");
1847 di->defs.defined |= _GD_Color;
1848 di->color = XkbcInternAtom(tmp.str, False);
1854 case XkbOutlineDoodad:
1855 case XkbSolidDoodad:
1856 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1858 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1859 case XkbIndicatorDoodad:
1860 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1862 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1864 WSGO("Unknown doodad type %d in SetDoodadField\n",
1865 (unsigned int) di->type);
1866 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1871 SetSectionField(SectionInfo * si,
1873 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1875 unsigned short *pField;
1881 if (uStrCaseCmp(field, "priority") == 0)
1883 if (arrayNdx != NULL)
1886 return ReportNotArray("keyboard section", field, scText(si));
1888 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1891 ReportBadType("keyboard section", field, scText(si), "integer");
1894 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1897 ERROR("Section priority %d out of range (must be 0..%d)\n",
1898 tmp.ival, XkbGeomMaxPriority);
1899 ACTION("Priority for section %s not changed", scText(si));
1902 si->priority = tmp.ival;
1903 si->defs.defined |= _GS_Priority;
1906 else if (uStrCaseCmp(field, "top") == 0)
1911 else if (uStrCaseCmp(field, "left") == 0)
1916 else if (uStrCaseCmp(field, "width") == 0)
1918 pField = &si->width;
1921 else if (uStrCaseCmp(field, "height") == 0)
1923 pField = &si->height;
1926 else if (uStrCaseCmp(field, "angle") == 0)
1928 pField = &si->angle;
1934 return ReportBadField("keyboard section", field, scText(si));
1936 if (arrayNdx != NULL)
1939 return ReportNotArray("keyboard section", field, scText(si));
1941 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1944 ReportBadType("keyboard section", field, scText(si), "number");
1947 si->defs.defined |= def;
1953 SetRowField(RowInfo * row,
1955 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1959 if (uStrCaseCmp(field, "top") == 0)
1961 if (arrayNdx != NULL)
1964 return ReportNotArray("keyboard row", field, rowText(row));
1966 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1969 return ReportBadType("keyboard row", field, rowText(row),
1972 row->defs.defined |= _GR_Top;
1973 row->top = tmp.uval;
1975 else if (uStrCaseCmp(field, "left") == 0)
1977 if (arrayNdx != NULL)
1980 return ReportNotArray("keyboard row", field, rowText(row));
1982 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1985 return ReportBadType("keyboard row", field, rowText(row),
1988 row->defs.defined |= _GR_Left;
1989 row->left = tmp.uval;
1991 else if (uStrCaseCmp(field, "vertical") == 0)
1993 if (arrayNdx != NULL)
1996 return ReportNotArray("keyboard row", field, rowText(row));
1998 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
2001 return ReportBadType("keyboard row", field, rowText(row),
2004 row->defs.defined |= _GR_Vertical;
2005 row->vertical = tmp.uval;
2010 return ReportBadField("keyboard row", field, rowText(row));
2016 SetKeyField(KeyInfo * key,
2018 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2022 if (uStrCaseCmp(field, "gap") == 0)
2024 if (arrayNdx != NULL)
2027 return ReportNotArray("key", field, keyText(key));
2029 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2032 return ReportBadType("key", field, keyText(key), "number");
2034 key->defs.defined |= _GK_Gap;
2035 key->gap = tmp.ival;
2037 else if (uStrCaseCmp(field, "shape") == 0)
2039 if (arrayNdx != NULL)
2042 return ReportNotArray("key", field, keyText(key));
2044 if (!ExprResolveString(value, &tmp, NULL, NULL))
2047 return ReportBadType("key", field, keyText(key), "string");
2049 key->defs.defined |= _GK_Shape;
2050 key->shape = XkbcInternAtom(tmp.str, False);
2053 else if ((uStrCaseCmp(field, "color") == 0) ||
2054 (uStrCaseCmp(field, "keycolor") == 0))
2056 if (arrayNdx != NULL)
2059 return ReportNotArray("key", field, keyText(key));
2061 if (!ExprResolveString(value, &tmp, NULL, NULL))
2064 return ReportBadType("key", field, keyText(key), "string");
2066 key->defs.defined |= _GK_Color;
2067 key->color = XkbcInternAtom(tmp.str, False);
2070 else if ((uStrCaseCmp(field, "name") == 0)
2071 || (uStrCaseCmp(field, "keyname") == 0))
2073 if (arrayNdx != NULL)
2076 return ReportNotArray("key", field, keyText(key));
2078 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2081 return ReportBadType("key", field, keyText(key), "key name");
2083 key->defs.defined |= _GK_Name;
2084 bzero(key->name, XkbKeyNameLength + 1);
2085 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2090 return ReportBadField("key", field, keyText(key));
2096 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2102 InitPropertyInfo(&pi, info);
2104 if (!ExprResolveString(value, &result, NULL, NULL))
2107 ERROR("Property values must be type string\n");
2108 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2111 pi.value = result.str;
2112 ret = AddProperty(info, &pi);
2118 HandleGeometryVar(VarDef * stmt, XkbcDescPtr xkb, GeometryInfo * info)
2120 ExprResult elem, field, tmp;
2123 Atom *pField = NULL;
2126 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2127 return 0; /* internal error, already reported */
2130 if (uStrCaseCmp(elem.str, "shape") == 0)
2131 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2132 else if (uStrCaseCmp(elem.str, "key") == 0)
2133 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2134 field.str, ndx, stmt->value, info);
2135 else if (uStrCaseCmp(elem.str, "row") == 0)
2136 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2138 else if (uStrCaseCmp(elem.str, "section") == 0)
2139 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2141 else if (uStrCaseCmp(elem.str, "property") == 0)
2146 ERROR("The %s geometry property is not an array\n", field.str);
2147 ACTION("Ignoring illegal property definition\n");
2151 ret = SetGeometryProperty(info, field.str, stmt->value);
2154 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2155 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2156 else if (uStrCaseCmp(elem.str, "solid") == 0)
2159 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2161 dflt = NextDfltDoodad(NULL, info);
2162 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2164 else if (uStrCaseCmp(elem.str, "outline") == 0)
2167 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2169 dflt = NextDfltDoodad(NULL, info);
2170 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2172 else if (uStrCaseCmp(elem.str, "text") == 0)
2175 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2177 dflt = NextDfltDoodad(NULL, info);
2178 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2180 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2183 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2185 dflt = NextDfltDoodad(NULL, info);
2186 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2188 else if (uStrCaseCmp(elem.str, "logo") == 0)
2191 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2193 dflt = NextDfltDoodad(NULL, info);
2194 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2198 WARN("Assignment to field of unknown element\n");
2199 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2207 if ((uStrCaseCmp(field.str, "width") == 0) ||
2208 (uStrCaseCmp(field.str, "widthmm") == 0))
2213 ret = ReportNotArray("keyboard", field.str, "geometry");
2215 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2218 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2220 else if (tmp.ival < 1)
2222 WARN("Keyboard width must be positive\n");
2223 ACTION("Ignoring illegal keyboard width %s\n",
2224 XkbcGeomFPText(tmp.ival));
2228 if (info->widthMM != 0)
2230 WARN("Keyboard width multiply defined\n");
2231 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2232 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2234 info->widthMM = tmp.ival;
2240 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2241 (uStrCaseCmp(field.str, "heightmm") == 0))
2246 ret = ReportNotArray("keyboard", field.str, "geometry");
2248 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2251 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2255 WARN("Keyboard height must be positive\n");
2256 ACTION("Ignoring illegal keyboard height %s\n",
2257 XkbcGeomFPText(tmp.ival));
2261 if (info->heightMM != 0)
2263 WARN("Keyboard height multiply defined\n");
2264 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2265 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2267 info->heightMM = tmp.ival;
2273 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2278 ret = ReportNotArray("keyboard", field.str, "geometry");
2280 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2283 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2285 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2288 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2289 ACTION("Ignoring font size in keyboard geometry\n");
2293 info->fontSize = tmp.ival;
2299 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2300 (uStrCaseCmp(field.str, "basecolor") == 0))
2305 ret = ReportNotArray("keyboard", field.str, "geometry");
2307 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2310 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2313 info->baseColor = XkbcInternAtom(tmp.str, False);
2320 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2325 ret = ReportNotArray("keyboard", field.str, "geometry");
2327 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2330 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2333 info->labelColor = XkbcInternAtom(tmp.str, False);
2340 else if (uStrCaseCmp(field.str, "font") == 0)
2342 pField = &info->font;
2344 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2345 (uStrCaseCmp(field.str, "slant") == 0))
2347 pField = &info->fontSlant;
2349 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2350 (uStrCaseCmp(field.str, "weight") == 0))
2352 pField = &info->fontWeight;
2354 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2355 (uStrCaseCmp(field.str, "setwidth") == 0))
2357 pField = &info->fontWeight;
2359 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2360 (uStrCaseCmp(field.str, "encoding") == 0))
2362 pField = &info->fontEncoding;
2364 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2365 (uStrCaseCmp(field.str, "xfontname") == 0))
2367 pField = &info->fontSpec;
2371 ret = SetGeometryProperty(info, field.str, stmt->value);
2376 /* fallthrough for the cases that set pField */
2380 ret = ReportNotArray("keyboard", field.str, "geometry");
2382 else if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2385 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2388 *pField = XkbcInternAtom(tmp.str, False);
2395 /***====================================================================***/
2398 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2399 GeometryInfo * info)
2403 XkbOutlinePtr outline;
2406 if (def->nOutlines < 1)
2408 WARN("Shape \"%s\" has no outlines\n", shText(si));
2409 ACTION("Definition ignored\n");
2412 si->nOutlines = def->nOutlines;
2413 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
2416 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2417 ACTION("Definition ignored\n");
2421 for (nOut = 0, ol = def->outlines; ol != NULL;
2422 ol = (OutlineDef *) ol->common.next)
2424 if (ol->nPoints < 1)
2426 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2430 outline = &si->outlines[nOut++];
2431 outline->num_points = ol->nPoints;
2432 outline->corner_radius = si->dfltCornerRadius;
2433 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
2434 if (!outline->points)
2436 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2437 ACTION("Definition ignored\n");
2442 for (nPt = 0, pt = ol->points; pt != NULL;
2443 pt = (ExprDef *) pt->common.next)
2445 outline->points[nPt].x = pt->value.coord.x;
2446 outline->points[nPt].y = pt->value.coord.y;
2449 if (ol->field != None)
2451 char *str = XkbcAtomText(ol->field);
2452 if ((uStrCaseCmp(str, "approximation") == 0) ||
2453 (uStrCaseCmp(str, "approx") == 0))
2455 if (si->approx == NULL)
2456 si->approx = outline;
2459 WARN("Multiple approximations for \"%s\"\n",
2461 ACTION("Treating all but the first as normal outlines\n");
2464 else if (uStrCaseCmp(str, "primary") == 0)
2466 if (si->primary == NULL)
2467 si->primary = outline;
2470 WARN("Multiple primary outlines for \"%s\"\n",
2472 ACTION("Treating all but the first as normal outlines\n");
2477 WARN("Unknown outline type %s for \"%s\"\n", str,
2479 ACTION("Treated as a normal outline\n");
2484 if (nOut != si->nOutlines)
2486 WSGO("Expected %d outlines, got %d\n",
2487 (unsigned int) si->nOutlines, nOut);
2488 si->nOutlines = nOut;
2494 HandleShapeDef(ShapeDef * def, XkbcDescPtr xkb, unsigned merge,
2495 GeometryInfo * info)
2499 if (def->merge != MergeDefault)
2502 bzero(&si, sizeof(ShapeInfo));
2503 si.defs.merge = merge;
2504 si.name = def->name;
2505 si.dfltCornerRadius = info->dfltCornerRadius;
2506 if (!HandleShapeBody(def, &si, merge, info))
2508 if (!AddShape(info, &si))
2513 /***====================================================================***/
2516 HandleDoodadDef(DoodadDef * def,
2517 unsigned merge, SectionInfo * si, GeometryInfo * info)
2519 ExprResult elem, field;
2524 if (def->common.stmtType == StmtIndicatorMapDef)
2526 def->common.stmtType = StmtDoodadDef;
2527 def->type = XkbIndicatorDoodad;
2529 InitDoodadInfo(&new, def->type, si, info);
2530 new.name = def->name;
2531 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2533 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2534 return 0; /* internal error, already reported */
2535 if (elem.str != NULL)
2537 WARN("Assignment to field of unknown element in doodad %s\n",
2539 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2542 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2548 if (!AddDoodad(si, info, &new))
2550 ClearDoodadInfo(&new);
2554 /***====================================================================***/
2557 HandleOverlayDef(OverlayDef * def,
2558 unsigned merge, SectionInfo * si, GeometryInfo * info)
2560 OverlayKeyDef *keyDef;
2561 OverlayKeyInfo *key;
2564 if ((def->nKeys < 1) && (warningLevel > 3))
2566 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2567 XkbcAtomText(def->name), scText(si));
2568 ACTION("Overlay ignored\n");
2571 bzero(&ol, sizeof(OverlayInfo));
2572 ol.name = def->name;
2573 for (keyDef = def->keys; keyDef;
2574 keyDef = (OverlayKeyDef *) keyDef->common.next)
2576 key = uTypedCalloc(1, OverlayKeyInfo);
2577 if ((!key) && warningLevel > 0)
2579 WSGO("Couldn't allocate OverlayKeyInfo\n");
2580 ACTION("Overlay %s for section %s will be incomplete\n",
2581 XkbcAtomText(ol.name), scText(si));
2584 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2585 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2586 key->sectionRow = _GOK_UnknownRow;
2587 key->overlayRow = _GOK_UnknownRow;
2588 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2589 (CommonInfo *) key);
2592 if (!AddOverlay(si, info, &ol))
2594 ClearOverlayInfo(&ol);
2598 /***====================================================================***/
2601 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2607 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2609 if (expr->op == OpAssign)
2613 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2614 return False; /* internal error, already reported */
2615 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2618 (key, f.str, ndx, expr->value.binary.right, info))
2623 ERROR("Illegal element used in a key definition\n");
2624 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2634 if (!SetKeyField(key, "gap", NULL, expr, info))
2638 if (!SetKeyField(key, "shape", NULL, expr, info))
2642 if (!SetKeyField(key, "name", NULL, expr, info))
2646 ERROR("Cannot determine field for unnamed expression\n");
2647 ACTION("Ignoring key %d in row %d of section %s\n",
2648 row->nKeys + 1, row->section->nRows + 1,
2658 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2659 GeometryInfo * info)
2663 if ((def->nKeys < 1) && (warningLevel > 3))
2665 ERROR("Row in section %s has no keys\n", rowText(row));
2666 ACTION("Section ignored\n");
2669 for (keyDef = def->keys; keyDef != NULL;
2670 keyDef = (KeyDef *) keyDef->common.next)
2672 if (keyDef->common.stmtType == StmtVarDef)
2674 VarDef *var = (VarDef *) keyDef;
2675 ExprResult elem, field;
2677 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2678 return 0; /* internal error, already reported */
2679 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2681 if (!SetRowField(row, field.str, ndx, var->value, info))
2684 else if (uStrCaseCmp(elem.str, "key") == 0)
2687 (&row->dfltKey, field.str, ndx, var->value, info))
2692 WARN("Assignment to field of unknown element in row\n");
2693 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2696 else if (keyDef->common.stmtType == StmtKeyDef)
2699 InitKeyInfo(&key, row, info);
2700 if (keyDef->name != NULL)
2702 int len = strlen(keyDef->name);
2703 if ((len < 1) || (len > XkbKeyNameLength))
2705 ERROR("Illegal name %s for key in section %s\n",
2706 keyDef->name, rowText(row));
2707 ACTION("Section not compiled\n");
2710 bzero(key.name, XkbKeyNameLength + 1);
2711 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2712 key.defs.defined |= _GK_Name;
2714 else if (!HandleComplexKey(keyDef, &key, info))
2716 if (!AddKey(row, &key))
2721 WSGO("Unexpected statement (type %d) in row body\n",
2722 keyDef->common.stmtType);
2730 HandleSectionBody(SectionDef * def,
2731 SectionInfo * si, unsigned merge, GeometryInfo * info)
2736 for (rowDef = def->rows; rowDef != NULL;
2737 rowDef = (RowDef *) rowDef->common.next)
2739 if (rowDef->common.stmtType == StmtVarDef)
2741 VarDef *var = (VarDef *) rowDef;
2742 ExprResult elem, field;
2744 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2745 return 0; /* internal error, already reported */
2746 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2748 if (!SetSectionField(si, field.str, ndx, var->value, info))
2754 else if (uStrCaseCmp(elem.str, "row") == 0)
2757 (&si->dfltRow, field.str, ndx, var->value, info))
2763 else if (uStrCaseCmp(elem.str, "key") == 0)
2765 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2773 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2775 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2783 WARN("Assignment to field of unknown element in section\n");
2784 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2789 else if (rowDef->common.stmtType == StmtRowDef)
2792 InitRowInfo(&row, si, info);
2793 if (!HandleRowBody(rowDef, &row, merge, info))
2795 if (!AddRow(si, &row))
2797 /* ClearRowInfo(&row,info);*/
2799 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2800 (rowDef->common.stmtType == StmtIndicatorMapDef))
2802 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2805 else if (rowDef->common.stmtType == StmtOverlayDef)
2807 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2812 WSGO("Unexpected statement (type %d) in section body\n",
2813 rowDef->common.stmtType);
2817 if (si->nRows != def->nRows)
2819 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2820 (unsigned int) si->nRows);
2821 ACTION("Definition of section %s might be incorrect\n", scText(si));
2827 HandleSectionDef(SectionDef * def,
2828 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2832 if (def->merge != MergeDefault)
2834 InitSectionInfo(&si, info);
2835 si.defs.merge = merge;
2836 si.name = def->name;
2837 if (!HandleSectionBody(def, &si, merge, info))
2839 if (!AddSection(info, &si))
2844 /***====================================================================***/
2847 HandleGeometryFile(XkbFile * file,
2848 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2853 if (merge == MergeDefault)
2854 merge = MergeAugment;
2855 info->name = _XkbDupString(file->name);
2860 switch (stmt->stmtType)
2863 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2864 HandleGeometryFile))
2867 case StmtKeyAliasDef:
2868 if (!HandleAliasDef((KeyAliasDef *) stmt,
2869 merge, info->fileID, &info->aliases))
2875 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2879 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2882 case StmtSectionDef:
2883 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2886 case StmtIndicatorMapDef:
2888 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2893 failWhat = "virtual modfier";
2896 failWhat = "symbol interpretation";
2897 case StmtGroupCompatDef:
2899 failWhat = "group compatibility map";
2900 case StmtKeycodeDef:
2902 failWhat = "key name";
2903 ERROR("Interpretation files may not include other types\n");
2904 ACTION("Ignoring %s definition.\n", failWhat);
2908 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2913 if (info->errorCount > 10)
2916 ERROR("Too many errors\n");
2918 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2925 /***====================================================================***/
2928 CopyShapeDef(XkbGeometryPtr geom, ShapeInfo * si)
2932 XkbOutlinePtr old_outline, outline;
2935 si->index = geom->num_shapes;
2937 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2940 WSGO("Couldn't allocate shape in geometry\n");
2941 ACTION("Shape %s not compiled\n", shText(si));
2944 old_outline = si->outlines;
2945 for (i = 0; i < si->nOutlines; i++, old_outline++)
2947 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2950 WSGO("Couldn't allocate outline in shape\n");
2951 ACTION("Shape %s is incomplete\n", shText(si));
2954 n = old_outline->num_points;
2955 memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec));
2956 outline->num_points = old_outline->num_points;
2957 outline->corner_radius = old_outline->corner_radius;
2961 n = (si->approx - si->outlines);
2962 shape->approx = &shape->outlines[n];
2966 n = (si->primary - si->outlines);
2967 shape->primary = &shape->outlines[n];
2969 XkbcComputeShapeBounds(shape);
2974 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2976 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2978 if (warningLevel < 9)
2980 ERROR("No position defined for doodad %s\n",
2982 ACTION("Illegal doodad ignored\n");
2986 if ((di->defs.defined & _GD_Priority) == 0)
2988 /* calculate priority -- should be just above previous doodad/row */
2992 case XkbOutlineDoodad:
2993 case XkbSolidDoodad:
2994 if ((di->defs.defined & _GD_Shape) == 0)
2996 ERROR("No shape defined for %s doodad %s\n",
2997 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2999 ACTION("Incomplete definition ignored\n");
3005 si = FindShape(info, di->shape,
3007 XkbOutlineDoodad ? "outline doodad" :
3008 "solid doodad"), ddText(di));
3010 di->shape = si->name;
3013 ERROR("No legal shape for %s\n", ddText(di));
3014 ACTION("Incomplete definition ignored\n");
3018 if ((di->defs.defined & _GD_Color) == 0)
3020 if (warningLevel > 5)
3022 WARN("No color for doodad %s\n", ddText(di));
3023 ACTION("Using black\n");
3025 di->color = XkbcInternAtom("black", False);
3029 if ((di->defs.defined & _GD_Text) == 0)
3031 ERROR("No text specified for text doodad %s\n", ddText(di));
3032 ACTION("Illegal doodad definition ignored\n");
3035 if ((di->defs.defined & _GD_Angle) == 0)
3037 if ((di->defs.defined & _GD_Color) == 0)
3039 if (warningLevel > 5)
3041 WARN("No color specified for doodad %s\n", ddText(di));
3042 ACTION("Using black\n");
3044 di->color = XkbcInternAtom("black", False);
3046 if ((di->defs.defined & _GD_FontSpec) != 0)
3048 if ((di->defs.defined & _GD_FontParts) == 0)
3050 if (warningLevel < 9)
3053 ("Text doodad %s has full and partial font definition\n",
3055 ACTION("Full specification ignored\n");
3057 di->defs.defined &= ~_GD_FontSpec;
3058 di->fontSpec = None;
3060 if ((di->defs.defined & _GD_Font) == 0)
3062 if (warningLevel > 5)
3064 WARN("No font specified for doodad %s\n", ddText(di));
3065 ACTION("Using \"%s\"\n", DFLT_FONT);
3067 di->font = XkbcInternAtom(DFLT_FONT, False);
3069 if ((di->defs.defined & _GD_FontSlant) == 0)
3071 if (warningLevel > 7)
3073 WARN("No font slant for text doodad %s\n", ddText(di));
3074 ACTION("Using \"%s\"\n", DFLT_SLANT);
3076 di->fontSlant = XkbcInternAtom(DFLT_SLANT, False);
3078 if ((di->defs.defined & _GD_FontWeight) == 0)
3080 if (warningLevel > 7)
3082 WARN("No font weight for text doodad %s\n", ddText(di));
3083 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3085 di->fontWeight = XkbcInternAtom(DFLT_WEIGHT, False);
3087 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3089 if (warningLevel > 9)
3091 WARN("No font set width for text doodad %s\n", ddText(di));
3092 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3094 di->fontSetWidth = XkbcInternAtom(DFLT_SET_WIDTH, False);
3096 if ((di->defs.defined & _GD_FontVariant) == 0)
3098 if (warningLevel > 9)
3100 WARN("No font variant for text doodad %s\n", ddText(di));
3101 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3103 di->fontVariant = XkbcInternAtom(DFLT_VARIANT, False);
3105 if ((di->defs.defined & _GD_FontEncoding) == 0)
3107 if (warningLevel > 7)
3109 WARN("No font encoding for doodad %s\n", ddText(di));
3110 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3112 di->fontEncoding = XkbcInternAtom(DFLT_ENCODING, False);
3114 if ((di->defs.defined & _GD_FontSize) == 0)
3116 if (warningLevel > 7)
3118 WARN("No font size for text doodad %s\n", ddText(di));
3119 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3121 di->fontSize = DFLT_SIZE;
3123 if ((di->defs.defined & _GD_Height) == 0)
3125 unsigned size, nLines;
3127 size = (di->fontSize * 120) / 100;
3128 size = (size * 254) / 720; /* convert to mm/10 */
3129 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3135 if (warningLevel > 5)
3137 WARN("No height for text doodad %s\n", ddText(di));
3138 ACTION("Using calculated height %s millimeters\n",
3139 XkbcGeomFPText(size));
3143 if ((di->defs.defined & _GD_Width) == 0)
3145 unsigned width, tmp;
3148 for (str = XkbcAtomText(di->text); *str; str++)
3161 width *= (di->height * 2) / 3;
3162 if (warningLevel > 5)
3164 WARN("No width for text doodad %s\n", ddText(di));
3165 ACTION("Using calculated width %s millimeters\n",
3166 XkbcGeomFPText(width));
3171 case XkbIndicatorDoodad:
3172 if ((di->defs.defined & _GD_Shape) == 0)
3174 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3175 ACTION("Incomplete definition ignored\n");
3181 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3183 di->shape = si->name;
3186 ERROR("No legal shape for doodad %s\n", ddText(di));
3187 ACTION("Incomplete definition ignored\n");
3191 if ((di->defs.defined & _GD_Color) == 0)
3193 if (warningLevel > 5)
3195 WARN("No \"on\" color for indicator doodad %s\n",
3197 ACTION("Using green\n");
3199 di->color = XkbcInternAtom("green", False);
3201 if ((di->defs.defined & _GD_OffColor) == 0)
3203 if (warningLevel > 5)
3205 WARN("No \"off\" color for indicator doodad %s\n",
3207 ACTION("Using black\n");
3209 di->offColor = XkbcInternAtom("black", False);
3213 if (di->logoName == NULL)
3215 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3216 ACTION("Incomplete definition ignored\n");
3219 if ((di->defs.defined & _GD_Shape) == 0)
3221 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3222 ACTION("Incomplete definition ignored\n");
3228 si = FindShape(info, di->shape, "logo doodad",
3231 di->shape = si->name;
3234 ERROR("No legal shape for %s\n", ddText(di));
3235 ACTION("Incomplete definition ignored\n");
3239 if ((di->defs.defined & _GD_Color) == 0)
3241 if (warningLevel > 5)
3243 WARN("No color for doodad %s\n", ddText(di));
3244 ACTION("Using black\n");
3246 di->color = XkbcInternAtom("black", False);
3250 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3251 (unsigned int) di->type);
3257 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3260 FontFromParts(Atom fontTok,
3263 Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
3266 char *font, *weight, *slant, *setWidth, *variant, *encoding;
3269 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3270 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3271 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3273 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3274 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3276 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3280 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3281 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3282 rtrn = uCalloc(totalSize, 1);
3284 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3290 CopyDoodadDef(XkbGeometryPtr geom,
3291 XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info)
3294 XkbDoodadPtr doodad;
3299 if (!VerifyDoodadInfo(di, info))
3302 doodad = XkbcAddGeomDoodad(geom, section, name);
3305 WSGO("Couldn't allocate doodad in %s\n",
3306 (section ? "section" : "geometry"));
3307 ACTION("Cannot copy doodad %s\n", ddText(di));
3310 doodad->any.type = di->type;
3311 doodad->any.priority = di->priority;
3312 doodad->any.top = di->top;
3313 doodad->any.left = di->left;
3316 case XkbOutlineDoodad:
3317 case XkbSolidDoodad:
3318 si = FindShape(info, di->shape, NULL, NULL);
3321 doodad->shape.angle = di->angle;
3322 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3324 shape = &geom->shapes[si->index];
3325 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3326 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3329 doodad->text.angle = di->angle;
3330 doodad->text.width = di->width;
3331 doodad->text.height = di->height;
3332 if (di->fontSpec == None)
3333 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3336 di->fontVariant, di->fontSize,
3339 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3340 doodad->text.text = XkbcAtomGetString(di->text);
3341 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3343 XkbSetTextDoodadColor(geom, &doodad->text, color);
3345 case XkbIndicatorDoodad:
3346 si = FindShape(info, di->shape, NULL, NULL);
3349 shape = &geom->shapes[si->index];
3350 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3352 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3353 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3354 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3356 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3359 si = FindShape(info, di->shape, NULL, NULL);
3362 doodad->logo.angle = di->angle;
3363 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3365 shape = &geom->shapes[si->index];
3366 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3367 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3368 doodad->logo.logo_name = di->logoName;
3369 di->logoName = NULL;
3375 /***====================================================================***/
3378 VerifyOverlayInfo(XkbGeometryPtr geom,
3379 XkbSectionPtr section,
3381 GeometryInfo * info, short rowMap[256], short rowSize[256])
3383 register OverlayKeyInfo *ki, *next;
3384 unsigned long oKey, uKey, sKey;
3389 /* find out which row each key is in */
3390 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3392 oKey = KeyNameToLong(ki->over);
3393 uKey = KeyNameToLong(ki->under);
3394 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3397 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3400 sKey = KeyNameToLong(key->name.name);
3403 if (warningLevel > 0)
3406 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3407 XkbcKeyNameText(key->name.name),
3408 XkbcAtomText(section->name),
3409 XkbcAtomText(oi->name));
3410 ACTION("Overlay definition ignored\n");
3414 else if (sKey == uKey)
3421 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3424 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3425 XkbcKeyNameText(ki->under),
3426 XkbcAtomText(section->name),
3427 XkbcAtomText(oi->name));
3428 ACTION("Definition ignored\n");
3431 /* now prune out keys that aren't in the section */
3432 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3434 next = (OverlayKeyInfo *) oi->keys->defs.next;
3439 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3441 next = (OverlayKeyInfo *) ki->defs.next;
3442 if (next->sectionRow == _GOK_UnknownRow)
3444 ki->defs.next = next->defs.next;
3447 next = (OverlayKeyInfo *) ki->defs.next;
3452 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3453 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3454 ACTION("Overlay definition ignored\n");
3457 /* now figure out how many rows are defined for the overlay */
3458 bzero(rowSize, sizeof(short) * 256);
3459 for (k = 0; k < 256; k++)
3464 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3466 if (rowMap[ki->sectionRow] == -1)
3467 rowMap[ki->sectionRow] = oi->nRows++;
3468 ki->overlayRow = rowMap[ki->sectionRow];
3469 rowSize[ki->overlayRow]++;
3475 CopyOverlayDef(XkbGeometryPtr geom,
3476 XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
3480 XkbOverlayRowPtr row;
3481 XkbOverlayKeyPtr key;
3483 short rowMap[256], rowSize[256];
3486 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3489 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3492 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3493 XkbcAtomText(name), XkbcAtomText(section->name));
3496 for (i = 0; i < oi->nRows; i++)
3499 for (tmp = 0, row_under = -1;
3500 (tmp < section->num_rows) && (row_under < 0); tmp++)
3502 if (rowMap[tmp] == i)
3505 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3508 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3509 i, XkbcAtomText(name), XkbcAtomText(section->name));
3513 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3515 row = &ol->rows[ki->overlayRow];
3516 key = &row->keys[row->num_keys++];
3517 bzero(key, sizeof(XkbOverlayKeyRec));
3518 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3519 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3524 /***====================================================================***/
3527 CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
3529 XkbSectionPtr section;
3535 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3537 if (section == NULL)
3539 WSGO("Couldn't allocate section in geometry\n");
3540 ACTION("Section %s not compiled\n", scText(si));
3543 section->top = si->top;
3544 section->left = si->left;
3545 section->width = si->width;
3546 section->height = si->height;
3547 section->angle = si->angle;
3548 section->priority = si->priority;
3549 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3551 row = XkbcAddGeomRow(section, ri->nKeys);
3554 WSGO("Couldn't allocate row in section\n");
3555 ACTION("Section %s is incomplete\n", scText(si));
3559 row->left = ri->left;
3560 row->vertical = ri->vertical;
3561 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3564 if ((ki->defs.defined & _GK_Name) == 0)
3566 ERROR("Key %d of row %d in section %s has no name\n",
3567 (int) ki->index, (int) ri->index, scText(si));
3568 ACTION("Section %s ignored\n", scText(si));
3571 key = XkbcAddGeomKey(row);
3574 WSGO("Couldn't allocate key in row\n");
3575 ACTION("Section %s is incomplete\n", scText(si));
3578 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3580 if (ki->shape == None)
3585 si = FindShape(info, ki->shape, "key", keyText(ki));
3588 key->shape_ndx = si->index;
3590 if (ki->color != None)
3592 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3595 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3596 XkbSetKeyColor(geom, key, color);
3599 if (si->doodads != NULL)
3602 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3604 CopyDoodadDef(geom, section, di, info);
3607 if (si->overlays != NULL)
3610 for (oi = si->overlays; oi != NULL;
3611 oi = (OverlayInfo *) oi->defs.next)
3613 CopyOverlayDef(geom, section, oi, info);
3616 if (XkbcComputeSectionBounds(geom, section))
3618 /* 7/6/94 (ef) -- check for negative origin and translate */
3619 if ((si->defs.defined & _GS_Width) == 0)
3620 section->width = section->bounds.x2;
3621 if ((si->defs.defined & _GS_Height) == 0)
3622 section->height = section->bounds.y2;
3627 /***====================================================================***/
3630 CompileGeometry(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
3634 InitGeometryInfo(&info, file->id, merge);
3635 HandleGeometryFile(file, xkb, merge, &info);
3637 if (info.errorCount == 0)
3639 XkbGeometryPtr geom;
3640 XkbGeometrySizesRec sizes;
3641 bzero(&sizes, sizeof(sizes));
3642 sizes.which = XkbGeomAllMask;
3643 sizes.num_properties = info.nProps;
3644 sizes.num_colors = 8;
3645 sizes.num_shapes = info.nShapes;
3646 sizes.num_sections = info.nSections;
3647 sizes.num_doodads = info.nDoodads;
3648 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3650 WSGO("Couldn't allocate GeometryRec\n");
3651 ACTION("Geometry not compiled\n");
3656 geom->width_mm = info.widthMM;
3657 geom->height_mm = info.heightMM;
3658 if (info.name != NULL)
3660 geom->name = XkbcInternAtom(info.name, False);
3661 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3662 xkb->names->geometry = geom->name;
3664 if (info.fontSpec != None)
3665 geom->label_font = XkbcAtomGetString(info.fontSpec);
3667 geom->label_font = FontFromParts(info.font, info.fontWeight,
3673 XkbcAddGeomColor(geom, "black", geom->num_colors);
3674 XkbcAddGeomColor(geom, "white", geom->num_colors);
3676 if (info.baseColor == None)
3677 info.baseColor = XkbcInternAtom("white", False);
3678 if (info.labelColor == None)
3679 info.labelColor = XkbcInternAtom("black", False);
3681 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3684 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3690 for (pi = info.props; pi != NULL;
3691 pi = (PropertyInfo *) pi->defs.next)
3693 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3700 for (si = info.shapes; si != NULL;
3701 si = (ShapeInfo *) si->defs.next)
3703 if (!CopyShapeDef(geom, si))
3710 for (si = info.sections; si != NULL;
3711 si = (SectionInfo *) si->defs.next)
3713 if (!CopySectionDef(geom, si, &info))
3720 for (di = info.doodads; di != NULL;
3721 di = (DoodadInfo *) di->defs.next)
3723 if (!CopyDoodadDef(geom, NULL, di, &info))
3728 ApplyAliases(xkb, True, &info.aliases);
3729 ClearGeometryInfo(&info);