1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
34 #include "indicators.h"
39 #define DFLT_FONT "helvetica"
40 #define DFLT_SLANT "r"
41 #define DFLT_WEIGHT "medium"
42 #define DFLT_SET_WIDTH "normal"
43 #define DFLT_VARIANT ""
44 #define DFLT_ENCODING "iso8859-1"
47 typedef struct _PropertyInfo
54 #define _GSh_Outlines (1<<1)
55 #define _GSh_Approx (1<<2)
56 #define _GSh_Primary (1<<3)
57 typedef struct _ShapeInfo
62 unsigned short nOutlines;
63 unsigned short szOutlines;
64 struct xkb_outline * outlines;
65 struct xkb_outline * approx;
66 struct xkb_outline * primary;
71 ((s) ? XkbcAtomText((s)->name) : "default shape")
73 #define _GD_Priority (1<<0)
74 #define _GD_Top (1<<1)
75 #define _GD_Left (1<<2)
76 #define _GD_Angle (1<<3)
77 #define _GD_Shape (1<<4)
78 #define _GD_FontVariant (1<<4) /* CHEATING */
79 #define _GD_Corner (1<<5)
80 #define _GD_Width (1<<5) /* CHEATING */
81 #define _GD_Color (1<<6)
82 #define _GD_OffColor (1<<7)
83 #define _GD_Height (1<<7) /* CHEATING */
84 #define _GD_Text (1<<8)
85 #define _GD_Font (1<<9)
86 #define _GD_FontSlant (1<<10)
87 #define _GD_FontWeight (1<<11)
88 #define _GD_FontSetWidth (1<<12)
89 #define _GD_FontSize (1<<13)
90 #define _GD_FontEncoding (1<<14)
91 #define _GD_FontSpec (1<<15)
94 #define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
96 typedef struct _DoodadInfo
101 unsigned char priority;
105 unsigned short corner;
106 unsigned short width;
107 unsigned short height;
115 uint32_t fontSetWidth;
116 uint32_t fontVariant;
117 unsigned short fontSize;
118 uint32_t fontEncoding;
121 struct _SectionInfo *section;
128 #define _GK_Default (1<<0)
129 #define _GK_Name (1<<1)
130 #define _GK_Gap (1<<2)
131 #define _GK_Shape (1<<3)
132 #define _GK_Color (1<<4)
133 typedef struct _KeyInfo
141 struct _RowInfo *row;
143 #define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
145 #define _GR_Default (1<<0)
146 #define _GR_Vertical (1<<1)
147 #define _GR_Top (1<<2)
148 #define _GR_Left (1<<3)
149 typedef struct _RowInfo
156 unsigned short nKeys;
159 struct _SectionInfo *section;
162 ((r) ? XkbcAtomText((r)->section->name) : "default")
164 #define _GOK_UnknownRow -1
165 typedef struct _OverlayKeyInfo
170 char over[XkbKeyNameLength + 1];
171 char under[XkbKeyNameLength + 1];
174 typedef struct _OverlayInfo
178 unsigned short nRows;
179 unsigned short nKeys;
180 OverlayKeyInfo *keys;
183 ((o) ? XkbcAtomText((o)->name) : "default")
186 #define _GS_Default (1<<0)
187 #define _GS_Name (1<<1)
188 #define _GS_Top (1<<2)
189 #define _GS_Left (1<<3)
190 #define _GS_Width (1<<4)
191 #define _GS_Height (1<<5)
192 #define _GS_Angle (1<<6)
193 #define _GS_Priority (1<<7)
194 typedef struct _SectionInfo
200 unsigned short width;
201 unsigned short height;
202 unsigned short angle;
203 unsigned short nRows;
204 unsigned short nDoodads;
205 unsigned short nOverlays;
206 unsigned char priority;
207 unsigned char nextDoodadPriority;
211 DoodadInfo *dfltDoodads;
212 OverlayInfo *overlays;
213 struct _GeometryInfo *geometry;
216 ((s) ? XkbcAtomText((s)->name) : "default")
218 typedef struct _GeometryInfo
224 unsigned nextPriority;
231 SectionInfo *sections;
238 uint32_t fontSetWidth;
239 uint32_t fontVariant;
241 uint32_t fontEncoding;
245 int dfltCornerRadius;
246 SectionInfo dfltSection;
247 DoodadInfo *dfltDoodads;
252 ddText(DoodadInfo * di)
258 strcpy(buf, "default");
263 sprintf(buf, "%s in section %s",
264 XkbcAtomText(di->name), scText(di->section));
267 return XkbcAtomText(di->name);
270 /***====================================================================***/
273 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
275 pi->defs.defined = 0;
276 pi->defs.fileID = info->fileID;
277 pi->defs.merge = info->merge;
278 pi->name = pi->value = NULL;
283 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
288 if (info->props == pi)
293 for (tmp = pi; tmp != NULL; tmp = next)
297 tmp->name = tmp->value = NULL;
298 next = (PropertyInfo *) tmp->defs.next;
305 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
308 if (key != &row->dfltKey)
311 strcpy(key->name, "unknown");
312 key->defs.defined &= ~_GK_Default;
316 bzero(key, sizeof(KeyInfo));
317 strcpy(key->name, "default");
318 key->defs.defined = _GK_Default;
319 key->defs.fileID = info->fileID;
320 key->defs.merge = info->merge;
321 key->defs.next = NULL;
328 ClearKeyInfo(KeyInfo * key)
330 key->defs.defined &= ~_GK_Default;
331 strcpy(key->name, "default");
339 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
344 if (row->keys == key)
349 for (tmp = key; tmp != NULL; tmp = next)
352 next = (KeyInfo *) tmp->defs.next;
359 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
361 if (row != §ion->dfltRow)
363 *row = section->dfltRow;
364 row->defs.defined &= ~_GR_Default;
368 bzero(row, sizeof(RowInfo));
369 row->defs.defined = _GR_Default;
370 row->defs.fileID = info->fileID;
371 row->defs.merge = info->merge;
372 row->defs.next = NULL;
373 row->section = section;
376 InitKeyInfo(&row->dfltKey, row, info);
382 ClearRowInfo(RowInfo * row, GeometryInfo * info)
384 row->defs.defined &= ~_GR_Default;
385 row->top = row->left = 0;
386 row->vertical = False;
389 FreeKeys(row->keys, row, info);
390 ClearKeyInfo(&row->dfltKey);
391 row->dfltKey.defs.defined |= _GK_Default;
396 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
401 if (row == section->rows)
404 section->rows = NULL;
406 for (tmp = row; tmp != NULL; tmp = next)
408 ClearRowInfo(tmp, info);
409 next = (RowInfo *) tmp->defs.next;
416 FindDoodadByType(DoodadInfo * di, unsigned type)
420 if (di->type == type)
422 di = (DoodadInfo *) di->defs.next;
428 FindDoodadByName(DoodadInfo * di, uint32_t name)
432 if (di->name == name)
434 di = (DoodadInfo *) di->defs.next;
440 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
446 if (si && si->dfltDoodads)
447 dflt = FindDoodadByType(si->dfltDoodads, type);
448 if ((dflt == NULL) && (info->dfltDoodads))
449 dflt = FindDoodadByType(info->dfltDoodads, type);
453 di->defs.next = NULL;
457 bzero(di, sizeof(DoodadInfo));
458 di->defs.fileID = info->fileID;
464 di->priority = si->nextDoodadPriority++;
465 #if XkbGeomMaxPriority < 255
466 if (si->nextDoodadPriority > XkbGeomMaxPriority)
467 si->nextDoodadPriority = XkbGeomMaxPriority;
472 di->priority = info->nextPriority++;
473 if (info->nextPriority > XkbGeomMaxPriority)
474 info->nextPriority = XkbGeomMaxPriority;
480 ClearDoodadInfo(DoodadInfo * di)
485 bzero(di, sizeof(DoodadInfo));
487 di->defs.defined = 0;
492 ClearOverlayInfo(OverlayInfo * ol)
496 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
503 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
510 if (si->doodads == di)
515 if (si->dfltDoodads == di)
516 si->dfltDoodads = NULL;
518 if (info->doodads == di)
520 info->doodads = NULL;
523 if (info->dfltDoodads == di)
524 info->dfltDoodads = NULL;
525 for (tmp = di; tmp != NULL; tmp = next)
527 next = (DoodadInfo *) tmp->defs.next;
528 ClearDoodadInfo(tmp);
535 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
537 if (si != &info->dfltSection)
539 *si = info->dfltSection;
540 si->defs.defined &= ~_GS_Default;
541 si->name = xkb_intern_atom("unknown");
542 si->priority = info->nextPriority++;
543 if (info->nextPriority > XkbGeomMaxPriority)
544 info->nextPriority = XkbGeomMaxPriority;
548 bzero(si, sizeof(SectionInfo));
549 si->defs.fileID = info->fileID;
550 si->defs.merge = info->merge;
551 si->defs.next = NULL;
553 si->name = xkb_intern_atom("default");
554 InitRowInfo(&si->dfltRow, si, info);
560 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
566 into->defs.next = NULL;
567 into->dfltRow.defs.fileID = defs.fileID;
568 into->dfltRow.defs.merge = defs.merge;
569 into->dfltRow.defs.next = NULL;
570 into->dfltRow.section = into;
571 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
572 into->dfltRow.dfltKey.defs.merge = defs.merge;
573 into->dfltRow.dfltKey.defs.next = NULL;
574 into->dfltRow.dfltKey.row = &into->dfltRow;
579 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
582 si->defs.defined &= ~_GS_Default;
583 si->name = xkb_intern_atom("default");
584 si->top = si->left = 0;
585 si->width = si->height = 0;
589 FreeRows(si->rows, si, info);
592 ClearRowInfo(&si->dfltRow, info);
595 FreeDoodads(si->doodads, si, info);
598 si->dfltRow.defs.defined = _GR_Default;
603 FreeSections(SectionInfo * si, GeometryInfo * info)
608 if (si == info->sections)
611 info->sections = NULL;
613 for (tmp = si; tmp != NULL; tmp = next)
615 ClearSectionInfo(tmp, info);
616 next = (SectionInfo *) tmp->defs.next;
623 FreeShapes(ShapeInfo * si, GeometryInfo * info)
628 if (si == info->shapes)
633 for (tmp = si; tmp != NULL; tmp = next)
638 for (i = 0; i < tmp->nOutlines; i++)
640 if (tmp->outlines[i].points != NULL)
642 free(tmp->outlines[i].points);
643 tmp->outlines[i].num_points = 0;
644 tmp->outlines[i].points = NULL;
650 tmp->outlines = NULL;
651 tmp->primary = tmp->approx = NULL;
653 next = (ShapeInfo *) tmp->defs.next;
659 /***====================================================================***/
662 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
664 bzero(info, sizeof(GeometryInfo));
665 info->fileID = fileID;
667 InitSectionInfo(&info->dfltSection, info);
668 info->dfltSection.defs.defined = _GS_Default;
673 ClearGeometryInfo(GeometryInfo * info)
678 FreeProperties(info->props, info);
680 FreeShapes(info->shapes, info);
682 FreeSections(info->sections, info);
685 info->dfltCornerRadius = 0;
686 ClearSectionInfo(&info->dfltSection, info);
687 info->dfltSection.defs.defined = _GS_Default;
689 ClearAliases(&info->aliases);
693 /***====================================================================***/
695 static PropertyInfo *
696 NextProperty(GeometryInfo * info)
700 pi = uTypedAlloc(PropertyInfo);
703 bzero((char *) pi, sizeof(PropertyInfo));
704 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
711 static PropertyInfo *
712 FindProperty(GeometryInfo * info, char *name)
718 for (old = info->props; old != NULL;
719 old = (PropertyInfo *) old->defs.next)
721 if ((old->name) && (uStringEqual(name, old->name)))
728 AddProperty(GeometryInfo * info, PropertyInfo * new)
732 if ((!new) || (!new->value) || (!new->name))
734 old = FindProperty(info, new->name);
737 if ((new->defs.merge == MergeReplace)
738 || (new->defs.merge == MergeOverride))
740 if (((old->defs.fileID == new->defs.fileID)
741 && (warningLevel > 0)) || (warningLevel > 9))
743 WARN("Multiple definitions for the \"%s\" property\n",
745 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
749 old->value = _XkbDupString(new->value);
752 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
753 || (warningLevel > 9))
755 WARN("Multiple definitions for \"%s\" property\n", new->name);
756 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
762 if ((new = NextProperty(info)) == NULL)
764 new->defs.next = NULL;
765 new->name = _XkbDupString(old->name);
766 new->value = _XkbDupString(old->value);
770 /***====================================================================***/
773 NextShape(GeometryInfo * info)
777 si = uTypedAlloc(ShapeInfo);
780 bzero((char *) si, sizeof(ShapeInfo));
781 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
784 si->dfltCornerRadius = info->dfltCornerRadius;
790 FindShape(GeometryInfo * info, uint32_t name, const char *type, const char *which)
794 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
796 if (name == old->name)
802 WARN("Unknown shape \"%s\" for %s %s\n",
803 XkbcAtomText(name), type, which);
806 ACTION("Using default shape %s instead\n", shText(old));
809 ACTION("No default shape; definition ignored\n");
816 AddShape(GeometryInfo * info, ShapeInfo * new)
820 old = FindShape(info, new->name, NULL, NULL);
823 if ((new->defs.merge == MergeReplace)
824 || (new->defs.merge == MergeOverride))
826 ShapeInfo *next = (ShapeInfo *) old->defs.next;
827 if (((old->defs.fileID == new->defs.fileID)
828 && (warningLevel > 0)) || (warningLevel > 9))
830 WARN("Duplicate shape name \"%s\"\n", shText(old));
831 ACTION("Using last definition\n");
834 old->defs.next = &next->defs;
837 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
838 || (warningLevel > 9))
840 WARN("Multiple shapes named \"%s\"\n", shText(old));
841 ACTION("Using first definition\n");
846 if ((new = NextShape(info)) == NULL)
849 new->defs.next = NULL;
850 old->szOutlines = old->nOutlines = 0;
851 old->outlines = NULL;
857 /***====================================================================***/
860 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
864 next = into->defs.next;
865 ClearDoodadInfo(into);
867 into->defs.next = next;
868 next = from->defs.next;
869 ClearDoodadInfo(from);
870 from->defs.next = next;
875 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
879 di = uTypedCalloc(1, DoodadInfo);
885 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
891 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
898 NextDoodad(SectionInfo * si, GeometryInfo * info)
902 di = uTypedCalloc(1, DoodadInfo);
907 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
914 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
923 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
927 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
930 if ((new->defs.merge == MergeReplace)
931 || (new->defs.merge == MergeOverride))
933 if (((old->defs.fileID == new->defs.fileID)
934 && (warningLevel > 0)) || (warningLevel > 9))
936 WARN("Multiple doodads named \"%s\"\n",
937 XkbcAtomText(old->name));
938 ACTION("Using last definition\n");
940 ReplaceDoodad(old, new);
944 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
945 || (warningLevel > 9))
947 WARN("Multiple doodads named \"%s\"\n",
948 XkbcAtomText(old->name));
949 ACTION("Using first definition\n");
954 if ((new = NextDoodad(si, info)) == NULL)
956 ReplaceDoodad(new, old);
958 new->defs.next = NULL;
963 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
965 DoodadInfo *dflt = NULL;
968 if (uStrCaseCmp(name, "outline") == 0)
969 type = XkbOutlineDoodad;
970 else if (uStrCaseCmp(name, "solid") == 0)
971 type = XkbSolidDoodad;
972 else if (uStrCaseCmp(name, "text") == 0)
973 type = XkbTextDoodad;
974 else if (uStrCaseCmp(name, "indicator") == 0)
975 type = XkbIndicatorDoodad;
976 else if (uStrCaseCmp(name, "logo") == 0)
977 type = XkbLogoDoodad;
980 if ((si) && (si->dfltDoodads))
981 dflt = FindDoodadByType(si->dfltDoodads, type);
982 if ((!dflt) && (info->dfltDoodads))
983 dflt = FindDoodadByType(info->dfltDoodads, type);
986 dflt = NextDfltDoodad(si, info);
996 /***====================================================================***/
999 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1003 for (old = si->overlays; old != NULL;
1004 old = (OverlayInfo *) old->defs.next)
1006 if (old->name == new->name)
1011 if ((new->defs.merge == MergeReplace)
1012 || (new->defs.merge == MergeOverride))
1014 if (((old->defs.fileID == new->defs.fileID)
1015 && (warningLevel > 0)) || (warningLevel > 9))
1018 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1019 XkbcAtomText(old->name), XkbcAtomText(si->name));
1020 ACTION("Using last definition\n");
1022 ClearOverlayInfo(old);
1023 old->nKeys = new->nKeys;
1024 old->keys = new->keys;
1029 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1030 || (warningLevel > 9))
1032 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1033 XkbcAtomText(old->name), XkbcAtomText(si->name));
1034 ACTION("Using first definition\n");
1039 new = uTypedCalloc(1, OverlayInfo);
1042 if (warningLevel > 0)
1044 WSGO("Couldn't allocate a new OverlayInfo\n");
1046 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1047 XkbcAtomText(old->name), XkbcAtomText(si->name));
1054 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1055 (CommonInfo *) new);
1060 /***====================================================================***/
1062 static SectionInfo *
1063 NextSection(GeometryInfo * info)
1067 si = uTypedAlloc(SectionInfo);
1070 *si = info->dfltSection;
1071 si->defs.defined &= ~_GS_Default;
1072 si->defs.next = NULL;
1076 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1083 static SectionInfo *
1084 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1088 for (old = info->sections; old != NULL;
1089 old = (SectionInfo *) old->defs.next)
1091 if (new->name == old->name)
1098 AddSection(GeometryInfo * info, SectionInfo * new)
1102 old = FindMatchingSection(info, new);
1106 if ((new->defs.merge == MergeReplace)
1107 || (new->defs.merge == MergeOverride))
1109 SectionInfo *next = (SectionInfo *) old->defs.next;
1110 if (((old->defs.fileID == new->defs.fileID)
1111 && (warningLevel > 0)) || (warningLevel > 9))
1113 WARN("Duplicate shape name \"%s\"\n", shText(old));
1114 ACTION("Using last definition\n");
1117 old->defs.next = &next->defs;
1120 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1121 || (warningLevel > 9))
1123 WARN("Multiple shapes named \"%s\"\n", shText(old));
1124 ACTION("Using first definition\n");
1128 WARN("Don't know how to merge sections yet\n");
1132 if ((new = NextSection(info)) == NULL)
1135 new->defs.next = NULL;
1136 old->nRows = old->nDoodads = old->nOverlays = 0;
1138 old->doodads = NULL;
1139 old->overlays = NULL;
1143 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1151 /***====================================================================***/
1154 NextRow(SectionInfo * si)
1158 row = uTypedAlloc(RowInfo);
1162 row->defs.defined &= ~_GR_Default;
1163 row->defs.next = NULL;
1167 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1168 row->index = si->nRows++;
1174 AddRow(SectionInfo * si, RowInfo * new)
1179 if ((new = NextRow(si)) == NULL)
1182 new->defs.next = NULL;
1188 /***====================================================================***/
1191 NextKey(RowInfo * row)
1195 key = uTypedAlloc(KeyInfo);
1198 *key = row->dfltKey;
1199 key->defs.defined &= ~_GK_Default;
1200 key->defs.next = NULL;
1201 key->index = row->nKeys++;
1207 AddKey(RowInfo * row, KeyInfo * new)
1212 if ((new = NextKey(row)) == NULL)
1215 new->defs.next = NULL;
1217 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1221 /***====================================================================***/
1224 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1229 if (from->errorCount > 0)
1231 into->errorCount += from->errorCount;
1234 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1235 if (into->name == NULL)
1237 into->name = from->name;
1240 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1241 into->widthMM = from->widthMM;
1242 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1243 into->heightMM = from->heightMM;
1244 if ((into->font == None) || ((from->font != None) && clobber))
1245 into->font = from->font;
1246 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1247 into->fontSlant = from->fontSlant;
1248 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1249 into->fontWeight = from->fontWeight;
1250 if ((into->fontSetWidth == None)
1251 || ((from->fontSetWidth != None) && clobber))
1252 into->fontSetWidth = from->fontSetWidth;
1253 if ((into->fontVariant == None)
1254 || ((from->fontVariant != None) && clobber))
1255 into->fontVariant = from->fontVariant;
1256 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1257 into->fontSize = from->fontSize;
1258 if ((into->fontEncoding == None)
1259 || ((from->fontEncoding != None) && clobber))
1260 into->fontEncoding = from->fontEncoding;
1261 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1262 into->fontSpec = from->fontSpec;
1263 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1264 into->baseColor = from->baseColor;
1265 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1266 into->labelColor = from->labelColor;
1267 into->nextPriority = from->nextPriority;
1268 if (from->props != NULL)
1271 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1273 if (!AddProperty(into, pi))
1277 if (from->shapes != NULL)
1281 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1283 if (!AddShape(into, si))
1287 if (from->sections != NULL)
1291 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1293 if (!AddSection(into, si))
1297 if (from->doodads != NULL)
1301 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1303 if (!AddDoodad(NULL, into, di))
1307 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1312 typedef void (*FileHandler) (XkbFile * /* file */ ,
1313 struct xkb_desc * /* xkb */ ,
1314 unsigned /* merge */ ,
1315 GeometryInfo * /* info */
1319 HandleIncludeGeometry(IncludeStmt * stmt, struct xkb_desc * xkb, GeometryInfo * info,
1324 GeometryInfo included;
1328 if ((stmt->file == NULL) && (stmt->map == NULL))
1332 bzero(info, sizeof(GeometryInfo));
1334 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1336 InitGeometryInfo(&included, rtrn->id, newMerge);
1337 included.nextPriority = info->nextPriority;
1338 included.dfltCornerRadius = info->dfltCornerRadius;
1339 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1340 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1341 if (stmt->stmt != NULL)
1343 free(included.name);
1344 included.name = stmt->stmt;
1350 info->errorCount += 10;
1353 if ((stmt->next != NULL) && (included.errorCount < 1))
1357 GeometryInfo next_incl;
1359 for (next = stmt->next; next != NULL; next = next->next)
1361 if ((next->file == NULL) && (next->map == NULL))
1364 MergeIncludedGeometry(&included, info, next->merge);
1365 ClearGeometryInfo(info);
1367 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1369 InitGeometryInfo(&next_incl, rtrn->id, op);
1370 next_incl.nextPriority = included.nextPriority;
1371 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1372 DupSectionInfo(&next_incl.dfltSection,
1373 &included.dfltSection, &included);
1374 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1375 MergeIncludedGeometry(&included, &next_incl, op);
1376 ClearGeometryInfo(&next_incl);
1380 info->errorCount += 10;
1389 MergeIncludedGeometry(info, &included, newMerge);
1390 ClearGeometryInfo(&included);
1392 return (info->errorCount == 0);
1396 SetShapeField(ShapeInfo * si,
1398 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1402 if ((uStrCaseCmp(field, "radius") == 0)
1403 || (uStrCaseCmp(field, "corner") == 0)
1404 || (uStrCaseCmp(field, "cornerradius") == 0))
1406 if (arrayNdx != NULL)
1409 return ReportNotArray("key shape", field, shText(si));
1411 if (!ExprResolveFloat(value, &tmp))
1414 return ReportBadType("key shape", field, shText(si), "number");
1417 si->dfltCornerRadius = tmp.ival;
1419 info->dfltCornerRadius = tmp.ival;
1423 return ReportBadField("key shape", field, shText(si));
1427 SetShapeDoodadField(DoodadInfo * di,
1430 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1433 const char *typeName;
1436 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1437 if ((!uStrCaseCmp(field, "corner"))
1438 || (!uStrCaseCmp(field, "cornerradius")))
1440 if (arrayNdx != NULL)
1443 return ReportNotArray(typeName, field, ddText(di));
1445 if (!ExprResolveFloat(value, &tmp))
1448 return ReportBadType(typeName, field, ddText(di), "number");
1450 di->defs.defined |= _GD_Corner;
1451 di->corner = tmp.ival;
1454 else if (uStrCaseCmp(field, "angle") == 0)
1456 if (arrayNdx != NULL)
1459 return ReportNotArray(typeName, field, ddText(di));
1461 if (!ExprResolveFloat(value, &tmp))
1464 return ReportBadType(typeName, field, ddText(di), "number");
1466 di->defs.defined |= _GD_Angle;
1467 di->angle = tmp.ival;
1470 else if (uStrCaseCmp(field, "shape") == 0)
1472 if (arrayNdx != NULL)
1475 return ReportNotArray(typeName, field, ddText(di));
1477 if (!ExprResolveString(value, &tmp))
1480 return ReportBadType(typeName, field, ddText(di), "string");
1482 di->shape = xkb_intern_atom(tmp.str);
1483 di->defs.defined |= _GD_Shape;
1487 return ReportBadField(typeName, field, ddText(di));
1490 #define FIELD_STRING 0
1491 #define FIELD_SHORT 1
1492 #define FIELD_USHORT 2
1495 SetTextDoodadField(DoodadInfo * di,
1498 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1503 const char *typeName = "text doodad";
1508 unsigned short *uval;
1511 if (uStrCaseCmp(field, "angle") == 0)
1513 if (arrayNdx != NULL)
1516 return ReportNotArray(typeName, field, ddText(di));
1518 if (!ExprResolveFloat(value, &tmp))
1521 return ReportBadType(typeName, field, ddText(di), "number");
1523 di->defs.defined |= _GD_Angle;
1524 di->angle = tmp.ival;
1527 if (uStrCaseCmp(field, "width") == 0)
1529 type = FIELD_USHORT;
1530 pField.uval = &di->width;
1533 else if (uStrCaseCmp(field, "height") == 0)
1535 type = FIELD_USHORT;
1536 pField.uval = &di->height;
1539 else if (uStrCaseCmp(field, "text") == 0)
1541 type = FIELD_STRING;
1542 pField.str = &di->text;
1545 else if (uStrCaseCmp(field, "font") == 0)
1547 type = FIELD_STRING;
1548 pField.str = &di->font;
1551 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1552 (uStrCaseCmp(field, "slant") == 0))
1554 type = FIELD_STRING;
1555 pField.str = &di->fontSlant;
1556 def = _GD_FontSlant;
1558 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1559 (uStrCaseCmp(field, "weight") == 0))
1561 type = FIELD_STRING;
1562 pField.str = &di->fontWeight;
1563 def = _GD_FontWeight;
1565 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1566 (uStrCaseCmp(field, "setwidth") == 0))
1568 type = FIELD_STRING;
1569 pField.str = &di->fontSetWidth;
1570 def = _GD_FontSetWidth;
1572 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1573 (uStrCaseCmp(field, "variant") == 0))
1575 type = FIELD_STRING;
1576 pField.str = &di->fontVariant;
1577 def = _GD_FontVariant;
1579 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1580 (uStrCaseCmp(field, "encoding") == 0))
1582 type = FIELD_STRING;
1583 pField.str = &di->fontEncoding;
1584 def = _GD_FontEncoding;
1586 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1587 (uStrCaseCmp(field, "xfontname") == 0))
1589 type = FIELD_STRING;
1590 pField.str = &di->fontSpec;
1593 else if (uStrCaseCmp(field, "fontsize") == 0)
1595 type = FIELD_USHORT;
1596 pField.uval = &di->fontSize;
1601 return ReportBadField(typeName, field, ddText(di));
1603 if (arrayNdx != NULL)
1606 return ReportNotArray(typeName, field, ddText(di));
1608 if (type == FIELD_STRING)
1610 if (!ExprResolveString(value, &tmp))
1613 return ReportBadType(typeName, field, ddText(di), "string");
1615 di->defs.defined |= def;
1616 *pField.str = xkb_intern_atom(tmp.str);
1621 if (!ExprResolveFloat(value, &tmp))
1624 return ReportBadType(typeName, field, ddText(di), "number");
1626 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1630 ReportBadType(typeName, field, ddText(di), "unsigned");
1632 di->defs.defined |= def;
1633 if (type == FIELD_USHORT)
1634 *pField.uval = tmp.uval;
1636 *pField.ival = tmp.ival;
1642 SetIndicatorDoodadField(DoodadInfo * di,
1646 SectionInfo * si, GeometryInfo * info)
1650 if ((uStrCaseCmp(field, "oncolor") == 0)
1651 || (uStrCaseCmp(field, "offcolor") == 0)
1652 || (uStrCaseCmp(field, "shape") == 0))
1654 if (arrayNdx != NULL)
1657 return ReportNotArray("indicator doodad", field, ddText(di));
1659 if (!ExprResolveString(value, &tmp))
1662 return ReportBadType("indicator doodad", field,
1663 ddText(di), "string");
1665 if (uStrCaseCmp(field, "oncolor") == 0)
1667 di->defs.defined |= _GD_Color;
1668 di->color = xkb_intern_atom(tmp.str);
1670 else if (uStrCaseCmp(field, "offcolor") == 0)
1672 di->defs.defined |= _GD_OffColor;
1673 di->offColor = xkb_intern_atom(tmp.str);
1675 else if (uStrCaseCmp(field, "shape") == 0)
1677 di->defs.defined |= _GD_Shape;
1678 di->shape = xkb_intern_atom(tmp.str);
1683 return ReportBadField("indicator doodad", field, ddText(di));
1687 SetLogoDoodadField(DoodadInfo * di,
1690 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1693 const char *typeName = "logo doodad";
1695 if ((!uStrCaseCmp(field, "corner"))
1696 || (!uStrCaseCmp(field, "cornerradius")))
1698 if (arrayNdx != NULL)
1701 return ReportNotArray(typeName, field, ddText(di));
1703 if (!ExprResolveFloat(value, &tmp))
1706 return ReportBadType(typeName, field, ddText(di), "number");
1708 di->defs.defined |= _GD_Corner;
1709 di->corner = tmp.ival;
1712 else if (uStrCaseCmp(field, "angle") == 0)
1714 if (arrayNdx != NULL)
1717 return ReportNotArray(typeName, field, ddText(di));
1719 if (!ExprResolveFloat(value, &tmp))
1722 return ReportBadType(typeName, field, ddText(di), "number");
1724 di->defs.defined |= _GD_Angle;
1725 di->angle = tmp.ival;
1728 else if (uStrCaseCmp(field, "shape") == 0)
1730 if (arrayNdx != NULL)
1733 return ReportNotArray(typeName, field, ddText(di));
1735 if (!ExprResolveString(value, &tmp))
1738 return ReportBadType(typeName, field, ddText(di), "string");
1740 di->shape = xkb_intern_atom(tmp.str);
1742 di->defs.defined |= _GD_Shape;
1745 else if ((!uStrCaseCmp(field, "logoname"))
1746 || (!uStrCaseCmp(field, "name")))
1748 if (arrayNdx != NULL)
1751 return ReportNotArray(typeName, field, ddText(di));
1753 if (!ExprResolveString(value, &tmp))
1756 return ReportBadType(typeName, field, ddText(di),
1759 di->logoName = _XkbDupString(tmp.str);
1763 return ReportBadField(typeName, field, ddText(di));
1767 SetDoodadField(DoodadInfo * di,
1770 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1774 if (uStrCaseCmp(field, "priority") == 0)
1776 if (arrayNdx != NULL)
1779 return ReportNotArray("doodad", field, ddText(di));
1781 if (!ExprResolveInteger(value, &tmp))
1784 return ReportBadType("doodad", field, ddText(di), "integer");
1786 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1789 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1790 tmp.ival, XkbGeomMaxPriority);
1791 ACTION("Priority for doodad %s not changed", ddText(di));
1794 di->defs.defined |= _GD_Priority;
1795 di->priority = tmp.ival;
1798 else if (uStrCaseCmp(field, "left") == 0)
1800 if (arrayNdx != NULL)
1803 return ReportNotArray("doodad", field, ddText(di));
1805 if (!ExprResolveFloat(value, &tmp))
1808 return ReportBadType("doodad", field, ddText(di), "number");
1810 di->defs.defined |= _GD_Left;
1811 di->left = tmp.ival;
1814 else if (uStrCaseCmp(field, "top") == 0)
1816 if (arrayNdx != NULL)
1819 return ReportNotArray("doodad", field, ddText(di));
1821 if (!ExprResolveFloat(value, &tmp))
1824 return ReportBadType("doodad", field, ddText(di), "number");
1826 di->defs.defined |= _GD_Top;
1830 else if (uStrCaseCmp(field, "color") == 0)
1832 if (arrayNdx != NULL)
1835 return ReportNotArray("doodad", field, ddText(di));
1837 if (!ExprResolveString(value, &tmp))
1840 return ReportBadType("doodad", field, ddText(di), "string");
1842 di->defs.defined |= _GD_Color;
1843 di->color = xkb_intern_atom(tmp.str);
1849 case XkbOutlineDoodad:
1850 case XkbSolidDoodad:
1851 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1853 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1854 case XkbIndicatorDoodad:
1855 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1857 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1859 WSGO("Unknown doodad type %d in SetDoodadField\n",
1860 (unsigned int) di->type);
1861 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1866 SetSectionField(SectionInfo * si,
1868 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1870 unsigned short *pField;
1875 if (uStrCaseCmp(field, "priority") == 0)
1877 if (arrayNdx != NULL)
1880 return ReportNotArray("keyboard section", field, scText(si));
1882 if (!ExprResolveInteger(value, &tmp))
1885 ReportBadType("keyboard section", field, scText(si), "integer");
1888 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1891 ERROR("Section priority %d out of range (must be 0..%d)\n",
1892 tmp.ival, XkbGeomMaxPriority);
1893 ACTION("Priority for section %s not changed", scText(si));
1896 si->priority = tmp.ival;
1897 si->defs.defined |= _GS_Priority;
1900 else if (uStrCaseCmp(field, "top") == 0)
1905 else if (uStrCaseCmp(field, "left") == 0)
1910 else if (uStrCaseCmp(field, "width") == 0)
1912 pField = &si->width;
1915 else if (uStrCaseCmp(field, "height") == 0)
1917 pField = &si->height;
1920 else if (uStrCaseCmp(field, "angle") == 0)
1922 pField = &si->angle;
1928 return ReportBadField("keyboard section", field, scText(si));
1930 if (arrayNdx != NULL)
1933 return ReportNotArray("keyboard section", field, scText(si));
1935 if (!ExprResolveFloat(value, &tmp))
1938 ReportBadType("keyboard section", field, scText(si), "number");
1941 si->defs.defined |= def;
1947 SetRowField(RowInfo * row,
1949 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1953 if (uStrCaseCmp(field, "top") == 0)
1955 if (arrayNdx != NULL)
1958 return ReportNotArray("keyboard row", field, rowText(row));
1960 if (!ExprResolveFloat(value, &tmp))
1963 return ReportBadType("keyboard row", field, rowText(row),
1966 row->defs.defined |= _GR_Top;
1967 row->top = tmp.uval;
1969 else if (uStrCaseCmp(field, "left") == 0)
1971 if (arrayNdx != NULL)
1974 return ReportNotArray("keyboard row", field, rowText(row));
1976 if (!ExprResolveFloat(value, &tmp))
1979 return ReportBadType("keyboard row", field, rowText(row),
1982 row->defs.defined |= _GR_Left;
1983 row->left = tmp.uval;
1985 else if (uStrCaseCmp(field, "vertical") == 0)
1987 if (arrayNdx != NULL)
1990 return ReportNotArray("keyboard row", field, rowText(row));
1992 if (!ExprResolveBoolean(value, &tmp))
1995 return ReportBadType("keyboard row", field, rowText(row),
1998 row->defs.defined |= _GR_Vertical;
1999 row->vertical = tmp.uval;
2004 return ReportBadField("keyboard row", field, rowText(row));
2010 SetKeyField(KeyInfo * key,
2012 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2016 if (uStrCaseCmp(field, "gap") == 0)
2018 if (arrayNdx != NULL)
2021 return ReportNotArray("key", field, keyText(key));
2023 if (!ExprResolveFloat(value, &tmp))
2026 return ReportBadType("key", field, keyText(key), "number");
2028 key->defs.defined |= _GK_Gap;
2029 key->gap = tmp.ival;
2031 else if (uStrCaseCmp(field, "shape") == 0)
2033 if (arrayNdx != NULL)
2036 return ReportNotArray("key", field, keyText(key));
2038 if (!ExprResolveString(value, &tmp))
2041 return ReportBadType("key", field, keyText(key), "string");
2043 key->defs.defined |= _GK_Shape;
2044 key->shape = xkb_intern_atom(tmp.str);
2047 else if ((uStrCaseCmp(field, "color") == 0) ||
2048 (uStrCaseCmp(field, "keycolor") == 0))
2050 if (arrayNdx != NULL)
2053 return ReportNotArray("key", field, keyText(key));
2055 if (!ExprResolveString(value, &tmp))
2058 return ReportBadType("key", field, keyText(key), "string");
2060 key->defs.defined |= _GK_Color;
2061 key->color = xkb_intern_atom(tmp.str);
2064 else if ((uStrCaseCmp(field, "name") == 0)
2065 || (uStrCaseCmp(field, "keyname") == 0))
2067 if (arrayNdx != NULL)
2070 return ReportNotArray("key", field, keyText(key));
2072 if (!ExprResolveKeyName(value, &tmp))
2075 return ReportBadType("key", field, keyText(key), "key name");
2077 key->defs.defined |= _GK_Name;
2078 bzero(key->name, XkbKeyNameLength + 1);
2079 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2084 return ReportBadField("key", field, keyText(key));
2090 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2096 InitPropertyInfo(&pi, info);
2098 if (!ExprResolveString(value, &result))
2101 ERROR("Property values must be type string\n");
2102 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2105 pi.value = result.str;
2106 ret = AddProperty(info, &pi);
2112 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2114 ExprResult elem, field, tmp;
2117 uint32_t *pField = NULL;
2118 int ret = True; /* default to no error */
2120 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2121 return 0; /* internal error, already reported */
2124 if (uStrCaseCmp(elem.str, "shape") == 0)
2125 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2126 else if (uStrCaseCmp(elem.str, "key") == 0)
2127 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2128 field.str, ndx, stmt->value, info);
2129 else if (uStrCaseCmp(elem.str, "row") == 0)
2130 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2132 else if (uStrCaseCmp(elem.str, "section") == 0)
2133 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2135 else if (uStrCaseCmp(elem.str, "property") == 0)
2140 ERROR("The %s geometry property is not an array\n", field.str);
2141 ACTION("Ignoring illegal property definition\n");
2145 ret = SetGeometryProperty(info, field.str, stmt->value);
2148 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2149 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2150 else if (uStrCaseCmp(elem.str, "solid") == 0)
2153 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2155 dflt = NextDfltDoodad(NULL, info);
2156 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2158 else if (uStrCaseCmp(elem.str, "outline") == 0)
2161 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2163 dflt = NextDfltDoodad(NULL, info);
2164 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2166 else if (uStrCaseCmp(elem.str, "text") == 0)
2169 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2171 dflt = NextDfltDoodad(NULL, info);
2172 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2174 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2177 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2179 dflt = NextDfltDoodad(NULL, info);
2180 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2182 else if (uStrCaseCmp(elem.str, "logo") == 0)
2185 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2187 dflt = NextDfltDoodad(NULL, info);
2188 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2192 WARN("Assignment to field of unknown element\n");
2193 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2201 if ((uStrCaseCmp(field.str, "width") == 0) ||
2202 (uStrCaseCmp(field.str, "widthmm") == 0))
2207 ret = ReportNotArray("keyboard", field.str, "geometry");
2209 else if (!ExprResolveFloat(stmt->value, &tmp))
2212 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2214 else if (tmp.ival < 1)
2216 WARN("Keyboard width must be positive\n");
2217 ACTION("Ignoring illegal keyboard width %s\n",
2218 XkbcGeomFPText(tmp.ival));
2222 if (info->widthMM != 0)
2224 WARN("Keyboard width multiply defined\n");
2225 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2226 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2228 info->widthMM = tmp.ival;
2234 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2235 (uStrCaseCmp(field.str, "heightmm") == 0))
2240 ret = ReportNotArray("keyboard", field.str, "geometry");
2242 else if (!ExprResolveFloat(stmt->value, &tmp))
2245 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2247 else if (tmp.ival < 1)
2249 WARN("Keyboard height must be positive\n");
2250 ACTION("Ignoring illegal keyboard height %s\n",
2251 XkbcGeomFPText(tmp.ival));
2255 if (info->heightMM != 0)
2257 WARN("Keyboard height multiply defined\n");
2258 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2259 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2261 info->heightMM = tmp.ival;
2267 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2272 ret = ReportNotArray("keyboard", field.str, "geometry");
2274 else if (!ExprResolveFloat(stmt->value, &tmp))
2277 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2279 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2282 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2283 ACTION("Ignoring font size in keyboard geometry\n");
2287 info->fontSize = tmp.ival;
2293 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2294 (uStrCaseCmp(field.str, "basecolor") == 0))
2299 ret = ReportNotArray("keyboard", field.str, "geometry");
2301 else if (!ExprResolveString(stmt->value, &tmp))
2304 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2307 info->baseColor = xkb_intern_atom(tmp.str);
2314 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2319 ret = ReportNotArray("keyboard", field.str, "geometry");
2321 else if (!ExprResolveString(stmt->value, &tmp))
2324 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2327 info->labelColor = xkb_intern_atom(tmp.str);
2334 else if (uStrCaseCmp(field.str, "font") == 0)
2336 pField = &info->font;
2338 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2339 (uStrCaseCmp(field.str, "slant") == 0))
2341 pField = &info->fontSlant;
2343 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2344 (uStrCaseCmp(field.str, "weight") == 0))
2346 pField = &info->fontWeight;
2348 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2349 (uStrCaseCmp(field.str, "setwidth") == 0))
2351 pField = &info->fontWeight;
2353 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2354 (uStrCaseCmp(field.str, "encoding") == 0))
2356 pField = &info->fontEncoding;
2358 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2359 (uStrCaseCmp(field.str, "xfontname") == 0))
2361 pField = &info->fontSpec;
2365 ret = SetGeometryProperty(info, field.str, stmt->value);
2370 /* fallthrough for the cases that set pField */
2374 ret = ReportNotArray("keyboard", field.str, "geometry");
2376 else if (!ExprResolveString(stmt->value, &tmp))
2379 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2382 *pField = xkb_intern_atom(tmp.str);
2389 /***====================================================================***/
2392 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2393 GeometryInfo * info)
2397 struct xkb_outline * outline;
2400 if (def->nOutlines < 1)
2402 WARN("Shape \"%s\" has no outlines\n", shText(si));
2403 ACTION("Definition ignored\n");
2406 si->nOutlines = def->nOutlines;
2407 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2410 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2411 ACTION("Definition ignored\n");
2415 for (nOut = 0, ol = def->outlines; ol != NULL;
2416 ol = (OutlineDef *) ol->common.next)
2418 if (ol->nPoints < 1)
2420 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2424 outline = &si->outlines[nOut++];
2425 outline->num_points = ol->nPoints;
2426 outline->corner_radius = si->dfltCornerRadius;
2427 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2428 if (!outline->points)
2430 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2431 ACTION("Definition ignored\n");
2436 for (nPt = 0, pt = ol->points; pt != NULL;
2437 pt = (ExprDef *) pt->common.next)
2439 outline->points[nPt].x = pt->value.coord.x;
2440 outline->points[nPt].y = pt->value.coord.y;
2443 if (ol->field != None)
2445 const char *str = XkbcAtomText(ol->field);
2446 if ((uStrCaseCmp(str, "approximation") == 0) ||
2447 (uStrCaseCmp(str, "approx") == 0))
2449 if (si->approx == NULL)
2450 si->approx = outline;
2453 WARN("Multiple approximations for \"%s\"\n",
2455 ACTION("Treating all but the first as normal outlines\n");
2458 else if (uStrCaseCmp(str, "primary") == 0)
2460 if (si->primary == NULL)
2461 si->primary = outline;
2464 WARN("Multiple primary outlines for \"%s\"\n",
2466 ACTION("Treating all but the first as normal outlines\n");
2471 WARN("Unknown outline type %s for \"%s\"\n", str,
2473 ACTION("Treated as a normal outline\n");
2477 if (nOut != si->nOutlines)
2479 WSGO("Expected %d outlines, got %d\n",
2480 (unsigned int) si->nOutlines, nOut);
2481 si->nOutlines = nOut;
2487 HandleShapeDef(ShapeDef * def, struct xkb_desc * xkb, unsigned merge,
2488 GeometryInfo * info)
2492 if (def->merge != MergeDefault)
2495 bzero(&si, sizeof(ShapeInfo));
2496 si.defs.merge = merge;
2497 si.name = def->name;
2498 si.dfltCornerRadius = info->dfltCornerRadius;
2499 if (!HandleShapeBody(def, &si, merge, info))
2501 if (!AddShape(info, &si))
2506 /***====================================================================***/
2509 HandleDoodadDef(DoodadDef * def,
2510 unsigned merge, SectionInfo * si, GeometryInfo * info)
2512 ExprResult elem, field;
2517 if (def->common.stmtType == StmtIndicatorMapDef)
2519 def->common.stmtType = StmtDoodadDef;
2520 def->type = XkbIndicatorDoodad;
2522 InitDoodadInfo(&new, def->type, si, info);
2523 new.name = def->name;
2524 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2526 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2527 return 0; /* internal error, already reported */
2528 if (elem.str != NULL)
2530 WARN("Assignment to field of unknown element in doodad %s\n",
2532 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2535 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2541 if (!AddDoodad(si, info, &new))
2543 ClearDoodadInfo(&new);
2547 /***====================================================================***/
2550 HandleOverlayDef(OverlayDef * def,
2551 unsigned merge, SectionInfo * si, GeometryInfo * info)
2553 OverlayKeyDef *keyDef;
2554 OverlayKeyInfo *key;
2557 if ((def->nKeys < 1) && (warningLevel > 3))
2559 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2560 XkbcAtomText(def->name), scText(si));
2561 ACTION("Overlay ignored\n");
2564 bzero(&ol, sizeof(OverlayInfo));
2565 ol.name = def->name;
2566 for (keyDef = def->keys; keyDef;
2567 keyDef = (OverlayKeyDef *) keyDef->common.next)
2569 key = uTypedCalloc(1, OverlayKeyInfo);
2572 if (warningLevel > 0)
2574 WSGO("Couldn't allocate OverlayKeyInfo\n");
2575 ACTION("Overlay %s for section %s will be incomplete\n",
2576 XkbcAtomText(ol.name), scText(si));
2580 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2581 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2582 key->sectionRow = _GOK_UnknownRow;
2583 key->overlayRow = _GOK_UnknownRow;
2584 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2585 (CommonInfo *) key);
2588 if (!AddOverlay(si, info, &ol))
2590 ClearOverlayInfo(&ol);
2594 /***====================================================================***/
2597 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2601 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2603 if (expr->op == OpAssign)
2607 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2608 return False; /* internal error, already reported */
2609 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2612 (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);
2632 RowInfo *row = key->row;
2637 if (!SetKeyField(key, "gap", NULL, expr, info))
2641 if (!SetKeyField(key, "shape", NULL, expr, info))
2645 if (!SetKeyField(key, "name", NULL, expr, info))
2649 ERROR("Cannot determine field for unnamed expression\n");
2651 ACTION("Ignoring key %d in row %d of section %s\n",
2652 row->nKeys + 1, row->section->nRows + 1,
2662 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2663 GeometryInfo * info)
2667 if ((def->nKeys < 1) && (warningLevel > 3))
2669 ERROR("Row in section %s has no keys\n", rowText(row));
2670 ACTION("Section ignored\n");
2673 for (keyDef = def->keys; keyDef != NULL;
2674 keyDef = (KeyDef *) keyDef->common.next)
2676 if (keyDef->common.stmtType == StmtVarDef)
2678 VarDef *var = (VarDef *) keyDef;
2679 ExprResult elem, field;
2681 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2682 return 0; /* internal error, already reported */
2683 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2685 if (!SetRowField(row, field.str, ndx, var->value, info))
2688 else if (uStrCaseCmp(elem.str, "key") == 0)
2691 (&row->dfltKey, field.str, ndx, var->value, info))
2696 WARN("Assignment to field of unknown element in row\n");
2697 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2702 else if (keyDef->common.stmtType == StmtKeyDef)
2705 InitKeyInfo(&key, row, info);
2706 if (keyDef->name != NULL)
2708 int len = strlen(keyDef->name);
2709 if ((len < 1) || (len > XkbKeyNameLength))
2711 ERROR("Illegal name %s for key in section %s\n",
2712 keyDef->name, rowText(row));
2713 ACTION("Section not compiled\n");
2716 bzero(key.name, XkbKeyNameLength + 1);
2717 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2718 key.defs.defined |= _GK_Name;
2720 else if (!HandleComplexKey(keyDef, &key, info))
2722 if (!AddKey(row, &key))
2727 WSGO("Unexpected statement (type %d) in row body\n",
2728 keyDef->common.stmtType);
2736 HandleSectionBody(SectionDef * def,
2737 SectionInfo * si, unsigned merge, GeometryInfo * info)
2742 for (rowDef = def->rows; rowDef != NULL;
2743 rowDef = (RowDef *) rowDef->common.next)
2745 if (rowDef->common.stmtType == StmtVarDef)
2747 VarDef *var = (VarDef *) rowDef;
2748 ExprResult elem, field;
2750 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2751 return 0; /* internal error, already reported */
2752 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2754 if (!SetSectionField(si, field.str, ndx, var->value, info))
2760 else if (uStrCaseCmp(elem.str, "row") == 0)
2763 (&si->dfltRow, field.str, ndx, var->value, info))
2769 else if (uStrCaseCmp(elem.str, "key") == 0)
2771 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2779 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2781 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2789 WARN("Assignment to field of unknown element in section\n");
2790 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2795 else if (rowDef->common.stmtType == StmtRowDef)
2798 InitRowInfo(&row, si, info);
2799 if (!HandleRowBody(rowDef, &row, merge, info))
2801 if (!AddRow(si, &row))
2803 /* ClearRowInfo(&row,info);*/
2805 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2806 (rowDef->common.stmtType == StmtIndicatorMapDef))
2808 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2811 else if (rowDef->common.stmtType == StmtOverlayDef)
2813 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2818 WSGO("Unexpected statement (type %d) in section body\n",
2819 rowDef->common.stmtType);
2823 if (si->nRows != def->nRows)
2825 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2826 (unsigned int) si->nRows);
2827 ACTION("Definition of section %s might be incorrect\n", scText(si));
2833 HandleSectionDef(SectionDef * def,
2834 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2838 if (def->merge != MergeDefault)
2840 InitSectionInfo(&si, info);
2841 si.defs.merge = merge;
2842 si.name = def->name;
2843 if (!HandleSectionBody(def, &si, merge, info))
2845 if (!AddSection(info, &si))
2850 /***====================================================================***/
2853 HandleGeometryFile(XkbFile * file,
2854 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2857 const char *failWhat;
2859 if (merge == MergeDefault)
2860 merge = MergeAugment;
2861 info->name = _XkbDupString(file->name);
2866 switch (stmt->stmtType)
2869 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2870 HandleGeometryFile))
2873 case StmtKeyAliasDef:
2874 if (!HandleAliasDef((KeyAliasDef *) stmt,
2875 merge, info->fileID, &info->aliases))
2881 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2885 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2888 case StmtSectionDef:
2889 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2892 case StmtIndicatorMapDef:
2894 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2899 failWhat = "virtual modfier";
2902 failWhat = "symbol interpretation";
2903 case StmtGroupCompatDef:
2905 failWhat = "group compatibility map";
2906 case StmtKeycodeDef:
2908 failWhat = "key name";
2909 ERROR("Interpretation files may not include other types\n");
2910 ACTION("Ignoring %s definition.\n", failWhat);
2914 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2919 if (info->errorCount > 10)
2922 ERROR("Too many errors\n");
2924 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2931 /***====================================================================***/
2934 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2937 struct xkb_shape * shape;
2938 struct xkb_outline *old_outline, *outline;
2941 si->index = geom->num_shapes;
2943 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2946 WSGO("Couldn't allocate shape in geometry\n");
2947 ACTION("Shape %s not compiled\n", shText(si));
2950 old_outline = si->outlines;
2951 for (i = 0; i < si->nOutlines; i++, old_outline++)
2953 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2956 WSGO("Couldn't allocate outline in shape\n");
2957 ACTION("Shape %s is incomplete\n", shText(si));
2960 n = old_outline->num_points;
2961 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2962 outline->num_points = old_outline->num_points;
2963 outline->corner_radius = old_outline->corner_radius;
2967 n = (si->approx - si->outlines);
2968 shape->approx = &shape->outlines[n];
2972 n = (si->primary - si->outlines);
2973 shape->primary = &shape->outlines[n];
2975 XkbcComputeShapeBounds(shape);
2980 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2982 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2984 if (warningLevel < 9)
2986 ERROR("No position defined for doodad %s\n",
2988 ACTION("Illegal doodad ignored\n");
2992 if ((di->defs.defined & _GD_Priority) == 0)
2994 /* calculate priority -- should be just above previous doodad/row */
2998 case XkbOutlineDoodad:
2999 case XkbSolidDoodad:
3000 if ((di->defs.defined & _GD_Shape) == 0)
3002 ERROR("No shape defined for %s doodad %s\n",
3003 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
3005 ACTION("Incomplete definition ignored\n");
3011 si = FindShape(info, di->shape,
3013 XkbOutlineDoodad ? "outline doodad" :
3014 "solid doodad"), ddText(di));
3016 di->shape = si->name;
3019 ERROR("No legal shape for %s\n", ddText(di));
3020 ACTION("Incomplete definition ignored\n");
3024 if ((di->defs.defined & _GD_Color) == 0)
3026 if (warningLevel > 5)
3028 WARN("No color for doodad %s\n", ddText(di));
3029 ACTION("Using black\n");
3031 di->color = xkb_intern_atom("black");
3035 if ((di->defs.defined & _GD_Text) == 0)
3037 ERROR("No text specified for text doodad %s\n", ddText(di));
3038 ACTION("Illegal doodad definition ignored\n");
3041 if ((di->defs.defined & _GD_Angle) == 0)
3043 if ((di->defs.defined & _GD_Color) == 0)
3045 if (warningLevel > 5)
3047 WARN("No color specified for doodad %s\n", ddText(di));
3048 ACTION("Using black\n");
3050 di->color = xkb_intern_atom("black");
3052 if ((di->defs.defined & _GD_FontSpec) != 0)
3054 if ((di->defs.defined & _GD_FontParts) == 0)
3056 if (warningLevel < 9)
3059 ("Text doodad %s has full and partial font definition\n",
3061 ACTION("Full specification ignored\n");
3063 di->defs.defined &= ~_GD_FontSpec;
3064 di->fontSpec = None;
3066 if ((di->defs.defined & _GD_Font) == 0)
3068 if (warningLevel > 5)
3070 WARN("No font specified for doodad %s\n", ddText(di));
3071 ACTION("Using \"%s\"\n", DFLT_FONT);
3073 di->font = xkb_intern_atom(DFLT_FONT);
3075 if ((di->defs.defined & _GD_FontSlant) == 0)
3077 if (warningLevel > 7)
3079 WARN("No font slant for text doodad %s\n", ddText(di));
3080 ACTION("Using \"%s\"\n", DFLT_SLANT);
3082 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3084 if ((di->defs.defined & _GD_FontWeight) == 0)
3086 if (warningLevel > 7)
3088 WARN("No font weight for text doodad %s\n", ddText(di));
3089 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3091 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3093 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3095 if (warningLevel > 9)
3097 WARN("No font set width for text doodad %s\n", ddText(di));
3098 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3100 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3102 if ((di->defs.defined & _GD_FontVariant) == 0)
3104 if (warningLevel > 9)
3106 WARN("No font variant for text doodad %s\n", ddText(di));
3107 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3109 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3111 if ((di->defs.defined & _GD_FontEncoding) == 0)
3113 if (warningLevel > 7)
3115 WARN("No font encoding for doodad %s\n", ddText(di));
3116 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3118 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3120 if ((di->defs.defined & _GD_FontSize) == 0)
3122 if (warningLevel > 7)
3124 WARN("No font size for text doodad %s\n", ddText(di));
3125 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3127 di->fontSize = DFLT_SIZE;
3129 if ((di->defs.defined & _GD_Height) == 0)
3131 unsigned size, nLines;
3133 size = (di->fontSize * 120) / 100;
3134 size = (size * 254) / 720; /* convert to mm/10 */
3135 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3141 if (warningLevel > 5)
3143 WARN("No height for text doodad %s\n", ddText(di));
3144 ACTION("Using calculated height %s millimeters\n",
3145 XkbcGeomFPText(size));
3149 if ((di->defs.defined & _GD_Width) == 0)
3151 unsigned width, tmp;
3154 for (str = XkbcAtomText(di->text); *str; str++)
3167 width *= (di->height * 2) / 3;
3168 if (warningLevel > 5)
3170 WARN("No width for text doodad %s\n", ddText(di));
3171 ACTION("Using calculated width %s millimeters\n",
3172 XkbcGeomFPText(width));
3177 case XkbIndicatorDoodad:
3178 if ((di->defs.defined & _GD_Shape) == 0)
3180 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3181 ACTION("Incomplete definition ignored\n");
3187 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3189 di->shape = si->name;
3192 ERROR("No legal shape for doodad %s\n", ddText(di));
3193 ACTION("Incomplete definition ignored\n");
3197 if ((di->defs.defined & _GD_Color) == 0)
3199 if (warningLevel > 5)
3201 WARN("No \"on\" color for indicator doodad %s\n",
3203 ACTION("Using green\n");
3205 di->color = xkb_intern_atom("green");
3207 if ((di->defs.defined & _GD_OffColor) == 0)
3209 if (warningLevel > 5)
3211 WARN("No \"off\" color for indicator doodad %s\n",
3213 ACTION("Using black\n");
3215 di->offColor = xkb_intern_atom("black");
3219 if (di->logoName == NULL)
3221 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3222 ACTION("Incomplete definition ignored\n");
3225 if ((di->defs.defined & _GD_Shape) == 0)
3227 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3228 ACTION("Incomplete definition ignored\n");
3234 si = FindShape(info, di->shape, "logo doodad",
3237 di->shape = si->name;
3240 ERROR("No legal shape for %s\n", ddText(di));
3241 ACTION("Incomplete definition ignored\n");
3245 if ((di->defs.defined & _GD_Color) == 0)
3247 if (warningLevel > 5)
3249 WARN("No color for doodad %s\n", ddText(di));
3250 ACTION("Using black\n");
3252 di->color = xkb_intern_atom("black");
3256 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3257 (unsigned int) di->type);
3263 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3266 FontFromParts(uint32_t fontTok,
3269 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3272 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3275 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3276 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3277 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3279 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3280 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3282 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3286 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3287 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3288 rtrn = calloc(totalSize, 1);
3290 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3296 CopyDoodadDef(struct xkb_geometry * geom,
3297 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3300 union xkb_doodad * doodad;
3301 struct xkb_color * color;
3302 struct xkb_shape * shape;
3305 if (!VerifyDoodadInfo(di, info))
3308 doodad = XkbcAddGeomDoodad(geom, section, name);
3311 WSGO("Couldn't allocate doodad in %s\n",
3312 (section ? "section" : "geometry"));
3313 ACTION("Cannot copy doodad %s\n", ddText(di));
3316 doodad->any.type = di->type;
3317 doodad->any.priority = di->priority;
3318 doodad->any.top = di->top;
3319 doodad->any.left = di->left;
3322 case XkbOutlineDoodad:
3323 case XkbSolidDoodad:
3324 si = FindShape(info, di->shape, NULL, NULL);
3327 doodad->shape.angle = di->angle;
3328 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3330 shape = &geom->shapes[si->index];
3331 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3332 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3335 doodad->text.angle = di->angle;
3336 doodad->text.width = di->width;
3337 doodad->text.height = di->height;
3338 if (di->fontSpec == None)
3339 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3342 di->fontVariant, di->fontSize,
3345 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3346 doodad->text.text = XkbcAtomGetString(di->text);
3347 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3349 XkbSetTextDoodadColor(geom, &doodad->text, color);
3351 case XkbIndicatorDoodad:
3352 si = FindShape(info, di->shape, NULL, NULL);
3355 shape = &geom->shapes[si->index];
3356 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3358 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3359 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3360 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3362 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3365 si = FindShape(info, di->shape, NULL, NULL);
3368 doodad->logo.angle = di->angle;
3369 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3371 shape = &geom->shapes[si->index];
3372 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3373 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3374 doodad->logo.logo_name = di->logoName;
3375 di->logoName = NULL;
3381 /***====================================================================***/
3384 VerifyOverlayInfo(struct xkb_geometry * geom,
3385 struct xkb_section * section,
3387 GeometryInfo * info, short rowMap[256], short rowSize[256])
3389 OverlayKeyInfo *ki, *next;
3390 unsigned long oKey, uKey, sKey;
3391 struct xkb_row * row;
3392 struct xkb_key * key;
3395 /* find out which row each key is in */
3396 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3398 oKey = KeyNameToLong(ki->over);
3399 uKey = KeyNameToLong(ki->under);
3400 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3403 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3406 sKey = KeyNameToLong(key->name.name);
3409 if (warningLevel > 0)
3412 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3413 XkbcKeyNameText(key->name.name),
3414 XkbcAtomText(section->name),
3415 XkbcAtomText(oi->name));
3416 ACTION("Overlay definition ignored\n");
3420 else if (sKey == uKey)
3427 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3430 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3431 XkbcKeyNameText(ki->under),
3432 XkbcAtomText(section->name),
3433 XkbcAtomText(oi->name));
3434 ACTION("Definition ignored\n");
3437 /* now prune out keys that aren't in the section */
3438 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3440 next = (OverlayKeyInfo *) oi->keys->defs.next;
3445 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3447 next = (OverlayKeyInfo *) ki->defs.next;
3448 if (next->sectionRow == _GOK_UnknownRow)
3450 ki->defs.next = next->defs.next;
3453 next = (OverlayKeyInfo *) ki->defs.next;
3458 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3459 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3460 ACTION("Overlay definition ignored\n");
3463 /* now figure out how many rows are defined for the overlay */
3464 bzero(rowSize, sizeof(short) * 256);
3465 for (k = 0; k < 256; k++)
3470 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3472 if (rowMap[ki->sectionRow] == -1)
3473 rowMap[ki->sectionRow] = oi->nRows++;
3474 ki->overlayRow = rowMap[ki->sectionRow];
3475 rowSize[ki->overlayRow]++;
3481 CopyOverlayDef(struct xkb_geometry * geom,
3482 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3485 struct xkb_overlay * ol;
3486 struct xkb_overlay_row * row;
3487 struct xkb_overlay_key * key;
3489 short rowMap[256], rowSize[256];
3492 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3495 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3498 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3499 XkbcAtomText(name), XkbcAtomText(section->name));
3502 for (i = 0; i < oi->nRows; i++)
3505 for (tmp = 0, row_under = -1;
3506 (tmp < section->num_rows) && (row_under < 0); tmp++)
3508 if (rowMap[tmp] == i)
3511 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3514 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3515 i, XkbcAtomText(name), XkbcAtomText(section->name));
3519 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3521 row = &ol->rows[ki->overlayRow];
3522 key = &row->keys[row->num_keys++];
3523 bzero(key, sizeof(struct xkb_overlay_key));
3524 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3525 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3530 /***====================================================================***/
3533 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3535 struct xkb_section * section;
3536 struct xkb_row * row;
3537 struct xkb_key * key;
3541 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3543 if (section == NULL)
3545 WSGO("Couldn't allocate section in geometry\n");
3546 ACTION("Section %s not compiled\n", scText(si));
3549 section->top = si->top;
3550 section->left = si->left;
3551 section->width = si->width;
3552 section->height = si->height;
3553 section->angle = si->angle;
3554 section->priority = si->priority;
3555 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3557 row = XkbcAddGeomRow(section, ri->nKeys);
3560 WSGO("Couldn't allocate row in section\n");
3561 ACTION("Section %s is incomplete\n", scText(si));
3565 row->left = ri->left;
3566 row->vertical = ri->vertical;
3567 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3569 struct xkb_color * color;
3570 if ((ki->defs.defined & _GK_Name) == 0)
3572 ERROR("Key %d of row %d in section %s has no name\n",
3573 (int) ki->index, (int) ri->index, scText(si));
3574 ACTION("Section %s ignored\n", scText(si));
3577 key = XkbcAddGeomKey(row);
3580 WSGO("Couldn't allocate key in row\n");
3581 ACTION("Section %s is incomplete\n", scText(si));
3584 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3586 if (ki->shape == None)
3591 shapei = FindShape(info, ki->shape, "key", keyText(ki));
3594 key->shape_ndx = shapei->index;
3596 if (ki->color != None)
3598 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3601 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3602 XkbSetKeyColor(geom, key, color);
3605 if (si->doodads != NULL)
3608 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3610 CopyDoodadDef(geom, section, di, info);
3613 if (si->overlays != NULL)
3616 for (oi = si->overlays; oi != NULL;
3617 oi = (OverlayInfo *) oi->defs.next)
3619 CopyOverlayDef(geom, section, oi, info);
3622 if (XkbcComputeSectionBounds(geom, section))
3624 /* 7/6/94 (ef) -- check for negative origin and translate */
3625 if ((si->defs.defined & _GS_Width) == 0)
3626 section->width = section->bounds.x2;
3627 if ((si->defs.defined & _GS_Height) == 0)
3628 section->height = section->bounds.y2;
3633 /***====================================================================***/
3636 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3640 InitGeometryInfo(&info, file->id, merge);
3641 HandleGeometryFile(file, xkb, merge, &info);
3643 if (info.errorCount == 0)
3645 struct xkb_geometry * geom;
3646 struct xkb_geometry_sizes sizes;
3647 bzero(&sizes, sizeof(sizes));
3648 sizes.which = XkbGeomAllMask;
3649 sizes.num_properties = info.nProps;
3650 sizes.num_colors = 8;
3651 sizes.num_shapes = info.nShapes;
3652 sizes.num_sections = info.nSections;
3653 sizes.num_doodads = info.nDoodads;
3654 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3656 WSGO("Couldn't allocate GeometryRec\n");
3657 ACTION("Geometry not compiled\n");
3662 geom->width_mm = info.widthMM;
3663 geom->height_mm = info.heightMM;
3664 if (info.name != NULL)
3666 geom->name = xkb_intern_atom(info.name);
3667 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3668 xkb->names->geometry = geom->name;
3670 if (info.fontSpec != None)
3671 geom->label_font = XkbcAtomGetString(info.fontSpec);
3673 geom->label_font = FontFromParts(info.font, info.fontWeight,
3679 XkbcAddGeomColor(geom, "black", geom->num_colors);
3680 XkbcAddGeomColor(geom, "white", geom->num_colors);
3682 if (info.baseColor == None)
3683 info.baseColor = xkb_intern_atom("white");
3684 if (info.labelColor == None)
3685 info.labelColor = xkb_intern_atom("black");
3687 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3690 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3696 for (pi = info.props; pi != NULL;
3697 pi = (PropertyInfo *) pi->defs.next)
3699 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3706 for (si = info.shapes; si != NULL;
3707 si = (ShapeInfo *) si->defs.next)
3709 if (!CopyShapeDef(geom, si))
3716 for (si = info.sections; si != NULL;
3717 si = (SectionInfo *) si->defs.next)
3719 if (!CopySectionDef(geom, si, &info))
3726 for (di = info.doodads; di != NULL;
3727 di = (DoodadInfo *) di->defs.next)
3729 if (!CopyDoodadDef(geom, NULL, di, &info))
3734 ApplyAliases(xkb, True, &info.aliases);
3735 ClearGeometryInfo(&info);