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;
282 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
287 if (info->props == pi)
292 for (tmp = pi; tmp != NULL; tmp = next)
296 tmp->name = tmp->value = NULL;
297 next = (PropertyInfo *) tmp->defs.next;
303 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
306 if (key != &row->dfltKey)
309 strcpy(key->name, "unknown");
310 key->defs.defined &= ~_GK_Default;
314 memset(key, 0, sizeof(KeyInfo));
315 strcpy(key->name, "default");
316 key->defs.defined = _GK_Default;
317 key->defs.fileID = info->fileID;
318 key->defs.merge = info->merge;
319 key->defs.next = NULL;
325 ClearKeyInfo(KeyInfo * key)
327 key->defs.defined &= ~_GK_Default;
328 strcpy(key->name, "default");
335 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
340 if (row->keys == key)
345 for (tmp = key; tmp != NULL; tmp = next)
348 next = (KeyInfo *) tmp->defs.next;
354 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
356 if (row != §ion->dfltRow)
358 *row = section->dfltRow;
359 row->defs.defined &= ~_GR_Default;
363 memset(row, 0, sizeof(RowInfo));
364 row->defs.defined = _GR_Default;
365 row->defs.fileID = info->fileID;
366 row->defs.merge = info->merge;
367 row->defs.next = NULL;
368 row->section = section;
371 InitKeyInfo(&row->dfltKey, row, info);
376 ClearRowInfo(RowInfo * row, GeometryInfo * info)
378 row->defs.defined &= ~_GR_Default;
379 row->top = row->left = 0;
380 row->vertical = False;
383 FreeKeys(row->keys, row, info);
384 ClearKeyInfo(&row->dfltKey);
385 row->dfltKey.defs.defined |= _GK_Default;
389 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
394 if (row == section->rows)
397 section->rows = NULL;
399 for (tmp = row; tmp != NULL; tmp = next)
401 ClearRowInfo(tmp, info);
402 next = (RowInfo *) tmp->defs.next;
408 FindDoodadByType(DoodadInfo * di, unsigned type)
412 if (di->type == type)
414 di = (DoodadInfo *) di->defs.next;
420 FindDoodadByName(DoodadInfo * di, uint32_t name)
424 if (di->name == name)
426 di = (DoodadInfo *) di->defs.next;
432 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
438 if (si && si->dfltDoodads)
439 dflt = FindDoodadByType(si->dfltDoodads, type);
440 if ((dflt == NULL) && (info->dfltDoodads))
441 dflt = FindDoodadByType(info->dfltDoodads, type);
445 di->defs.next = NULL;
449 memset(di, 0, sizeof(DoodadInfo));
450 di->defs.fileID = info->fileID;
456 di->priority = si->nextDoodadPriority++;
457 #if XkbGeomMaxPriority < 255
458 if (si->nextDoodadPriority > XkbGeomMaxPriority)
459 si->nextDoodadPriority = XkbGeomMaxPriority;
464 di->priority = info->nextPriority++;
465 if (info->nextPriority > XkbGeomMaxPriority)
466 info->nextPriority = XkbGeomMaxPriority;
471 ClearDoodadInfo(DoodadInfo * di)
476 memset(di, 0, sizeof(DoodadInfo));
478 di->defs.defined = 0;
482 ClearOverlayInfo(OverlayInfo * ol)
486 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
492 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
499 if (si->doodads == di)
504 if (si->dfltDoodads == di)
505 si->dfltDoodads = NULL;
507 if (info->doodads == di)
509 info->doodads = NULL;
512 if (info->dfltDoodads == di)
513 info->dfltDoodads = NULL;
514 for (tmp = di; tmp != NULL; tmp = next)
516 next = (DoodadInfo *) tmp->defs.next;
517 ClearDoodadInfo(tmp);
523 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
525 if (si != &info->dfltSection)
527 *si = info->dfltSection;
528 si->defs.defined &= ~_GS_Default;
529 si->name = xkb_intern_atom("unknown");
530 si->priority = info->nextPriority++;
531 if (info->nextPriority > XkbGeomMaxPriority)
532 info->nextPriority = XkbGeomMaxPriority;
536 memset(si, 0, sizeof(SectionInfo));
537 si->defs.fileID = info->fileID;
538 si->defs.merge = info->merge;
539 si->defs.next = NULL;
541 si->name = xkb_intern_atom("default");
542 InitRowInfo(&si->dfltRow, si, info);
547 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
553 into->defs.next = NULL;
554 into->dfltRow.defs.fileID = defs.fileID;
555 into->dfltRow.defs.merge = defs.merge;
556 into->dfltRow.defs.next = NULL;
557 into->dfltRow.section = into;
558 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
559 into->dfltRow.dfltKey.defs.merge = defs.merge;
560 into->dfltRow.dfltKey.defs.next = NULL;
561 into->dfltRow.dfltKey.row = &into->dfltRow;
565 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
568 si->defs.defined &= ~_GS_Default;
569 si->name = xkb_intern_atom("default");
570 si->top = si->left = 0;
571 si->width = si->height = 0;
575 FreeRows(si->rows, si, info);
578 ClearRowInfo(&si->dfltRow, info);
581 FreeDoodads(si->doodads, si, info);
584 si->dfltRow.defs.defined = _GR_Default;
588 FreeSections(SectionInfo * si, GeometryInfo * info)
593 if (si == info->sections)
596 info->sections = NULL;
598 for (tmp = si; tmp != NULL; tmp = next)
600 ClearSectionInfo(tmp, info);
601 next = (SectionInfo *) tmp->defs.next;
607 FreeShapes(ShapeInfo * si, GeometryInfo * info)
612 if (si == info->shapes)
617 for (tmp = si; tmp != NULL; tmp = next)
622 for (i = 0; i < tmp->nOutlines; i++)
624 if (tmp->outlines[i].points != NULL)
626 free(tmp->outlines[i].points);
627 tmp->outlines[i].num_points = 0;
628 tmp->outlines[i].points = NULL;
634 tmp->outlines = NULL;
635 tmp->primary = tmp->approx = NULL;
637 next = (ShapeInfo *) tmp->defs.next;
642 /***====================================================================***/
645 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
647 memset(info, 0, sizeof(GeometryInfo));
648 info->fileID = fileID;
650 InitSectionInfo(&info->dfltSection, info);
651 info->dfltSection.defs.defined = _GS_Default;
655 ClearGeometryInfo(GeometryInfo * info)
660 FreeProperties(info->props, info);
662 FreeShapes(info->shapes, info);
664 FreeSections(info->sections, info);
667 info->dfltCornerRadius = 0;
668 ClearSectionInfo(&info->dfltSection, info);
669 info->dfltSection.defs.defined = _GS_Default;
671 ClearAliases(&info->aliases);
674 /***====================================================================***/
676 static PropertyInfo *
677 NextProperty(GeometryInfo * info)
681 pi = uTypedAlloc(PropertyInfo);
684 memset(pi, 0, sizeof(PropertyInfo));
685 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
692 static PropertyInfo *
693 FindProperty(GeometryInfo * info, char *name)
699 for (old = info->props; old != NULL;
700 old = (PropertyInfo *) old->defs.next)
702 if ((old->name) && (uStringEqual(name, old->name)))
709 AddProperty(GeometryInfo * info, PropertyInfo * new)
713 if ((!new) || (!new->value) || (!new->name))
715 old = FindProperty(info, new->name);
718 if ((new->defs.merge == MergeReplace)
719 || (new->defs.merge == MergeOverride))
721 if (((old->defs.fileID == new->defs.fileID)
722 && (warningLevel > 0)) || (warningLevel > 9))
724 WARN("Multiple definitions for the \"%s\" property\n",
726 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
730 old->value = _XkbDupString(new->value);
733 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
734 || (warningLevel > 9))
736 WARN("Multiple definitions for \"%s\" property\n", new->name);
737 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
743 if ((new = NextProperty(info)) == NULL)
745 new->defs.next = NULL;
746 new->name = _XkbDupString(old->name);
747 new->value = _XkbDupString(old->value);
751 /***====================================================================***/
754 NextShape(GeometryInfo * info)
758 si = uTypedAlloc(ShapeInfo);
761 memset(si, 0, sizeof(ShapeInfo));
762 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
765 si->dfltCornerRadius = info->dfltCornerRadius;
771 FindShape(GeometryInfo * info, uint32_t name, const char *type, const char *which)
775 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
777 if (name == old->name)
783 WARN("Unknown shape \"%s\" for %s %s\n",
784 XkbcAtomText(name), type, which);
787 ACTION("Using default shape %s instead\n", shText(old));
790 ACTION("No default shape; definition ignored\n");
797 AddShape(GeometryInfo * info, ShapeInfo * new)
801 old = FindShape(info, new->name, NULL, NULL);
804 if ((new->defs.merge == MergeReplace)
805 || (new->defs.merge == MergeOverride))
807 ShapeInfo *next = (ShapeInfo *) old->defs.next;
808 if (((old->defs.fileID == new->defs.fileID)
809 && (warningLevel > 0)) || (warningLevel > 9))
811 WARN("Duplicate shape name \"%s\"\n", shText(old));
812 ACTION("Using last definition\n");
815 old->defs.next = &next->defs;
818 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
819 || (warningLevel > 9))
821 WARN("Multiple shapes named \"%s\"\n", shText(old));
822 ACTION("Using first definition\n");
827 if ((new = NextShape(info)) == NULL)
830 new->defs.next = NULL;
831 old->szOutlines = old->nOutlines = 0;
832 old->outlines = NULL;
838 /***====================================================================***/
841 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
845 next = into->defs.next;
846 ClearDoodadInfo(into);
848 into->defs.next = next;
849 next = from->defs.next;
850 ClearDoodadInfo(from);
851 from->defs.next = next;
855 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
859 di = uTypedCalloc(1, DoodadInfo);
865 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
871 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
878 NextDoodad(SectionInfo * si, GeometryInfo * info)
882 di = uTypedCalloc(1, DoodadInfo);
887 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
894 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
903 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
907 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
910 if ((new->defs.merge == MergeReplace)
911 || (new->defs.merge == MergeOverride))
913 if (((old->defs.fileID == new->defs.fileID)
914 && (warningLevel > 0)) || (warningLevel > 9))
916 WARN("Multiple doodads named \"%s\"\n",
917 XkbcAtomText(old->name));
918 ACTION("Using last definition\n");
920 ReplaceDoodad(old, new);
924 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
925 || (warningLevel > 9))
927 WARN("Multiple doodads named \"%s\"\n",
928 XkbcAtomText(old->name));
929 ACTION("Using first definition\n");
934 if ((new = NextDoodad(si, info)) == NULL)
936 ReplaceDoodad(new, old);
938 new->defs.next = NULL;
943 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
945 DoodadInfo *dflt = NULL;
948 if (uStrCaseCmp(name, "outline") == 0)
949 type = XkbOutlineDoodad;
950 else if (uStrCaseCmp(name, "solid") == 0)
951 type = XkbSolidDoodad;
952 else if (uStrCaseCmp(name, "text") == 0)
953 type = XkbTextDoodad;
954 else if (uStrCaseCmp(name, "indicator") == 0)
955 type = XkbIndicatorDoodad;
956 else if (uStrCaseCmp(name, "logo") == 0)
957 type = XkbLogoDoodad;
960 if ((si) && (si->dfltDoodads))
961 dflt = FindDoodadByType(si->dfltDoodads, type);
962 if ((!dflt) && (info->dfltDoodads))
963 dflt = FindDoodadByType(info->dfltDoodads, type);
966 dflt = NextDfltDoodad(si, info);
976 /***====================================================================***/
979 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
983 for (old = si->overlays; old != NULL;
984 old = (OverlayInfo *) old->defs.next)
986 if (old->name == new->name)
991 if ((new->defs.merge == MergeReplace)
992 || (new->defs.merge == MergeOverride))
994 if (((old->defs.fileID == new->defs.fileID)
995 && (warningLevel > 0)) || (warningLevel > 9))
998 ("Multiple overlays named \"%s\" for section \"%s\"\n",
999 XkbcAtomText(old->name), XkbcAtomText(si->name));
1000 ACTION("Using last definition\n");
1002 ClearOverlayInfo(old);
1003 old->nKeys = new->nKeys;
1004 old->keys = new->keys;
1009 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1010 || (warningLevel > 9))
1012 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1013 XkbcAtomText(old->name), XkbcAtomText(si->name));
1014 ACTION("Using first definition\n");
1019 new = uTypedCalloc(1, OverlayInfo);
1022 if (warningLevel > 0)
1024 WSGO("Couldn't allocate a new OverlayInfo\n");
1026 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1027 XkbcAtomText(old->name), XkbcAtomText(si->name));
1034 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1035 (CommonInfo *) new);
1040 /***====================================================================***/
1042 static SectionInfo *
1043 NextSection(GeometryInfo * info)
1047 si = uTypedAlloc(SectionInfo);
1050 *si = info->dfltSection;
1051 si->defs.defined &= ~_GS_Default;
1052 si->defs.next = NULL;
1056 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1063 static SectionInfo *
1064 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1068 for (old = info->sections; old != NULL;
1069 old = (SectionInfo *) old->defs.next)
1071 if (new->name == old->name)
1078 AddSection(GeometryInfo * info, SectionInfo * new)
1082 old = FindMatchingSection(info, new);
1086 if ((new->defs.merge == MergeReplace)
1087 || (new->defs.merge == MergeOverride))
1089 SectionInfo *next = (SectionInfo *) old->defs.next;
1090 if (((old->defs.fileID == new->defs.fileID)
1091 && (warningLevel > 0)) || (warningLevel > 9))
1093 WARN("Duplicate shape name \"%s\"\n", shText(old));
1094 ACTION("Using last definition\n");
1097 old->defs.next = &next->defs;
1100 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1101 || (warningLevel > 9))
1103 WARN("Multiple shapes named \"%s\"\n", shText(old));
1104 ACTION("Using first definition\n");
1108 WARN("Don't know how to merge sections yet\n");
1112 if ((new = NextSection(info)) == NULL)
1115 new->defs.next = NULL;
1116 old->nRows = old->nDoodads = old->nOverlays = 0;
1118 old->doodads = NULL;
1119 old->overlays = NULL;
1123 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1131 /***====================================================================***/
1134 NextRow(SectionInfo * si)
1138 row = uTypedAlloc(RowInfo);
1142 row->defs.defined &= ~_GR_Default;
1143 row->defs.next = NULL;
1147 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1148 row->index = si->nRows++;
1154 AddRow(SectionInfo * si, RowInfo * new)
1159 if ((new = NextRow(si)) == NULL)
1162 new->defs.next = NULL;
1168 /***====================================================================***/
1171 NextKey(RowInfo * row)
1175 key = uTypedAlloc(KeyInfo);
1178 *key = row->dfltKey;
1179 key->defs.defined &= ~_GK_Default;
1180 key->defs.next = NULL;
1181 key->index = row->nKeys++;
1187 AddKey(RowInfo * row, KeyInfo * new)
1192 if ((new = NextKey(row)) == NULL)
1195 new->defs.next = NULL;
1197 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1201 /***====================================================================***/
1204 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1209 if (from->errorCount > 0)
1211 into->errorCount += from->errorCount;
1214 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1215 if (into->name == NULL)
1217 into->name = from->name;
1220 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1221 into->widthMM = from->widthMM;
1222 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1223 into->heightMM = from->heightMM;
1224 if ((into->font == None) || ((from->font != None) && clobber))
1225 into->font = from->font;
1226 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1227 into->fontSlant = from->fontSlant;
1228 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1229 into->fontWeight = from->fontWeight;
1230 if ((into->fontSetWidth == None)
1231 || ((from->fontSetWidth != None) && clobber))
1232 into->fontSetWidth = from->fontSetWidth;
1233 if ((into->fontVariant == None)
1234 || ((from->fontVariant != None) && clobber))
1235 into->fontVariant = from->fontVariant;
1236 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1237 into->fontSize = from->fontSize;
1238 if ((into->fontEncoding == None)
1239 || ((from->fontEncoding != None) && clobber))
1240 into->fontEncoding = from->fontEncoding;
1241 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1242 into->fontSpec = from->fontSpec;
1243 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1244 into->baseColor = from->baseColor;
1245 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1246 into->labelColor = from->labelColor;
1247 into->nextPriority = from->nextPriority;
1248 if (from->props != NULL)
1251 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1253 if (!AddProperty(into, pi))
1257 if (from->shapes != NULL)
1261 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1263 if (!AddShape(into, si))
1267 if (from->sections != NULL)
1271 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1273 if (!AddSection(into, si))
1277 if (from->doodads != NULL)
1281 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1283 if (!AddDoodad(NULL, into, di))
1287 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1291 typedef void (*FileHandler) (XkbFile * /* file */ ,
1292 struct xkb_desc * /* xkb */ ,
1293 unsigned /* merge */ ,
1294 GeometryInfo * /* info */
1298 HandleIncludeGeometry(IncludeStmt * stmt, struct xkb_desc * xkb, GeometryInfo * info,
1303 GeometryInfo included;
1307 if ((stmt->file == NULL) && (stmt->map == NULL))
1311 memset(info, 0, sizeof(GeometryInfo));
1313 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1315 InitGeometryInfo(&included, rtrn->id, newMerge);
1316 included.nextPriority = info->nextPriority;
1317 included.dfltCornerRadius = info->dfltCornerRadius;
1318 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1319 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1320 if (stmt->stmt != NULL)
1322 free(included.name);
1323 included.name = stmt->stmt;
1329 info->errorCount += 10;
1332 if ((stmt->next != NULL) && (included.errorCount < 1))
1336 GeometryInfo next_incl;
1338 for (next = stmt->next; next != NULL; next = next->next)
1340 if ((next->file == NULL) && (next->map == NULL))
1343 MergeIncludedGeometry(&included, info, next->merge);
1344 ClearGeometryInfo(info);
1346 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1348 InitGeometryInfo(&next_incl, rtrn->id, op);
1349 next_incl.nextPriority = included.nextPriority;
1350 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1351 DupSectionInfo(&next_incl.dfltSection,
1352 &included.dfltSection, &included);
1353 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1354 MergeIncludedGeometry(&included, &next_incl, op);
1355 ClearGeometryInfo(&next_incl);
1359 info->errorCount += 10;
1368 MergeIncludedGeometry(info, &included, newMerge);
1369 ClearGeometryInfo(&included);
1371 return (info->errorCount == 0);
1375 SetShapeField(ShapeInfo * si,
1377 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1381 if ((uStrCaseCmp(field, "radius") == 0)
1382 || (uStrCaseCmp(field, "corner") == 0)
1383 || (uStrCaseCmp(field, "cornerradius") == 0))
1385 if (arrayNdx != NULL)
1388 return ReportNotArray("key shape", field, shText(si));
1390 if (!ExprResolveFloat(value, &tmp))
1393 return ReportBadType("key shape", field, shText(si), "number");
1396 si->dfltCornerRadius = tmp.ival;
1398 info->dfltCornerRadius = tmp.ival;
1402 return ReportBadField("key shape", field, shText(si));
1406 SetShapeDoodadField(DoodadInfo * di,
1409 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1412 const char *typeName;
1415 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1416 if ((!uStrCaseCmp(field, "corner"))
1417 || (!uStrCaseCmp(field, "cornerradius")))
1419 if (arrayNdx != NULL)
1422 return ReportNotArray(typeName, field, ddText(di));
1424 if (!ExprResolveFloat(value, &tmp))
1427 return ReportBadType(typeName, field, ddText(di), "number");
1429 di->defs.defined |= _GD_Corner;
1430 di->corner = tmp.ival;
1433 else if (uStrCaseCmp(field, "angle") == 0)
1435 if (arrayNdx != NULL)
1438 return ReportNotArray(typeName, field, ddText(di));
1440 if (!ExprResolveFloat(value, &tmp))
1443 return ReportBadType(typeName, field, ddText(di), "number");
1445 di->defs.defined |= _GD_Angle;
1446 di->angle = tmp.ival;
1449 else if (uStrCaseCmp(field, "shape") == 0)
1451 if (arrayNdx != NULL)
1454 return ReportNotArray(typeName, field, ddText(di));
1456 if (!ExprResolveString(value, &tmp))
1459 return ReportBadType(typeName, field, ddText(di), "string");
1461 di->shape = xkb_intern_atom(tmp.str);
1462 di->defs.defined |= _GD_Shape;
1466 return ReportBadField(typeName, field, ddText(di));
1469 #define FIELD_STRING 0
1470 #define FIELD_SHORT 1
1471 #define FIELD_USHORT 2
1474 SetTextDoodadField(DoodadInfo * di,
1477 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1482 const char *typeName = "text doodad";
1487 unsigned short *uval;
1490 if (uStrCaseCmp(field, "angle") == 0)
1492 if (arrayNdx != NULL)
1495 return ReportNotArray(typeName, field, ddText(di));
1497 if (!ExprResolveFloat(value, &tmp))
1500 return ReportBadType(typeName, field, ddText(di), "number");
1502 di->defs.defined |= _GD_Angle;
1503 di->angle = tmp.ival;
1506 if (uStrCaseCmp(field, "width") == 0)
1508 type = FIELD_USHORT;
1509 pField.uval = &di->width;
1512 else if (uStrCaseCmp(field, "height") == 0)
1514 type = FIELD_USHORT;
1515 pField.uval = &di->height;
1518 else if (uStrCaseCmp(field, "text") == 0)
1520 type = FIELD_STRING;
1521 pField.str = &di->text;
1524 else if (uStrCaseCmp(field, "font") == 0)
1526 type = FIELD_STRING;
1527 pField.str = &di->font;
1530 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1531 (uStrCaseCmp(field, "slant") == 0))
1533 type = FIELD_STRING;
1534 pField.str = &di->fontSlant;
1535 def = _GD_FontSlant;
1537 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1538 (uStrCaseCmp(field, "weight") == 0))
1540 type = FIELD_STRING;
1541 pField.str = &di->fontWeight;
1542 def = _GD_FontWeight;
1544 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1545 (uStrCaseCmp(field, "setwidth") == 0))
1547 type = FIELD_STRING;
1548 pField.str = &di->fontSetWidth;
1549 def = _GD_FontSetWidth;
1551 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1552 (uStrCaseCmp(field, "variant") == 0))
1554 type = FIELD_STRING;
1555 pField.str = &di->fontVariant;
1556 def = _GD_FontVariant;
1558 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1559 (uStrCaseCmp(field, "encoding") == 0))
1561 type = FIELD_STRING;
1562 pField.str = &di->fontEncoding;
1563 def = _GD_FontEncoding;
1565 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1566 (uStrCaseCmp(field, "xfontname") == 0))
1568 type = FIELD_STRING;
1569 pField.str = &di->fontSpec;
1572 else if (uStrCaseCmp(field, "fontsize") == 0)
1574 type = FIELD_USHORT;
1575 pField.uval = &di->fontSize;
1580 return ReportBadField(typeName, field, ddText(di));
1582 if (arrayNdx != NULL)
1585 return ReportNotArray(typeName, field, ddText(di));
1587 if (type == FIELD_STRING)
1589 if (!ExprResolveString(value, &tmp))
1592 return ReportBadType(typeName, field, ddText(di), "string");
1594 di->defs.defined |= def;
1595 *pField.str = xkb_intern_atom(tmp.str);
1600 if (!ExprResolveFloat(value, &tmp))
1603 return ReportBadType(typeName, field, ddText(di), "number");
1605 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1609 ReportBadType(typeName, field, ddText(di), "unsigned");
1611 di->defs.defined |= def;
1612 if (type == FIELD_USHORT)
1613 *pField.uval = tmp.uval;
1615 *pField.ival = tmp.ival;
1621 SetIndicatorDoodadField(DoodadInfo * di,
1625 SectionInfo * si, GeometryInfo * info)
1629 if ((uStrCaseCmp(field, "oncolor") == 0)
1630 || (uStrCaseCmp(field, "offcolor") == 0)
1631 || (uStrCaseCmp(field, "shape") == 0))
1633 if (arrayNdx != NULL)
1636 return ReportNotArray("indicator doodad", field, ddText(di));
1638 if (!ExprResolveString(value, &tmp))
1641 return ReportBadType("indicator doodad", field,
1642 ddText(di), "string");
1644 if (uStrCaseCmp(field, "oncolor") == 0)
1646 di->defs.defined |= _GD_Color;
1647 di->color = xkb_intern_atom(tmp.str);
1649 else if (uStrCaseCmp(field, "offcolor") == 0)
1651 di->defs.defined |= _GD_OffColor;
1652 di->offColor = xkb_intern_atom(tmp.str);
1654 else if (uStrCaseCmp(field, "shape") == 0)
1656 di->defs.defined |= _GD_Shape;
1657 di->shape = xkb_intern_atom(tmp.str);
1662 return ReportBadField("indicator doodad", field, ddText(di));
1666 SetLogoDoodadField(DoodadInfo * di,
1669 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1672 const char *typeName = "logo doodad";
1674 if ((!uStrCaseCmp(field, "corner"))
1675 || (!uStrCaseCmp(field, "cornerradius")))
1677 if (arrayNdx != NULL)
1680 return ReportNotArray(typeName, field, ddText(di));
1682 if (!ExprResolveFloat(value, &tmp))
1685 return ReportBadType(typeName, field, ddText(di), "number");
1687 di->defs.defined |= _GD_Corner;
1688 di->corner = tmp.ival;
1691 else if (uStrCaseCmp(field, "angle") == 0)
1693 if (arrayNdx != NULL)
1696 return ReportNotArray(typeName, field, ddText(di));
1698 if (!ExprResolveFloat(value, &tmp))
1701 return ReportBadType(typeName, field, ddText(di), "number");
1703 di->defs.defined |= _GD_Angle;
1704 di->angle = tmp.ival;
1707 else if (uStrCaseCmp(field, "shape") == 0)
1709 if (arrayNdx != NULL)
1712 return ReportNotArray(typeName, field, ddText(di));
1714 if (!ExprResolveString(value, &tmp))
1717 return ReportBadType(typeName, field, ddText(di), "string");
1719 di->shape = xkb_intern_atom(tmp.str);
1721 di->defs.defined |= _GD_Shape;
1724 else if ((!uStrCaseCmp(field, "logoname"))
1725 || (!uStrCaseCmp(field, "name")))
1727 if (arrayNdx != NULL)
1730 return ReportNotArray(typeName, field, ddText(di));
1732 if (!ExprResolveString(value, &tmp))
1735 return ReportBadType(typeName, field, ddText(di),
1738 di->logoName = _XkbDupString(tmp.str);
1742 return ReportBadField(typeName, field, ddText(di));
1746 SetDoodadField(DoodadInfo * di,
1749 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1753 if (uStrCaseCmp(field, "priority") == 0)
1755 if (arrayNdx != NULL)
1758 return ReportNotArray("doodad", field, ddText(di));
1760 if (!ExprResolveInteger(value, &tmp))
1763 return ReportBadType("doodad", field, ddText(di), "integer");
1765 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1768 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1769 tmp.ival, XkbGeomMaxPriority);
1770 ACTION("Priority for doodad %s not changed", ddText(di));
1773 di->defs.defined |= _GD_Priority;
1774 di->priority = tmp.ival;
1777 else if (uStrCaseCmp(field, "left") == 0)
1779 if (arrayNdx != NULL)
1782 return ReportNotArray("doodad", field, ddText(di));
1784 if (!ExprResolveFloat(value, &tmp))
1787 return ReportBadType("doodad", field, ddText(di), "number");
1789 di->defs.defined |= _GD_Left;
1790 di->left = tmp.ival;
1793 else if (uStrCaseCmp(field, "top") == 0)
1795 if (arrayNdx != NULL)
1798 return ReportNotArray("doodad", field, ddText(di));
1800 if (!ExprResolveFloat(value, &tmp))
1803 return ReportBadType("doodad", field, ddText(di), "number");
1805 di->defs.defined |= _GD_Top;
1809 else if (uStrCaseCmp(field, "color") == 0)
1811 if (arrayNdx != NULL)
1814 return ReportNotArray("doodad", field, ddText(di));
1816 if (!ExprResolveString(value, &tmp))
1819 return ReportBadType("doodad", field, ddText(di), "string");
1821 di->defs.defined |= _GD_Color;
1822 di->color = xkb_intern_atom(tmp.str);
1828 case XkbOutlineDoodad:
1829 case XkbSolidDoodad:
1830 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1832 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1833 case XkbIndicatorDoodad:
1834 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1836 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1838 WSGO("Unknown doodad type %d in SetDoodadField\n",
1839 (unsigned int) di->type);
1840 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1845 SetSectionField(SectionInfo * si,
1847 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1849 unsigned short *pField;
1854 if (uStrCaseCmp(field, "priority") == 0)
1856 if (arrayNdx != NULL)
1859 return ReportNotArray("keyboard section", field, scText(si));
1861 if (!ExprResolveInteger(value, &tmp))
1864 ReportBadType("keyboard section", field, scText(si), "integer");
1867 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1870 ERROR("Section priority %d out of range (must be 0..%d)\n",
1871 tmp.ival, XkbGeomMaxPriority);
1872 ACTION("Priority for section %s not changed", scText(si));
1875 si->priority = tmp.ival;
1876 si->defs.defined |= _GS_Priority;
1879 else if (uStrCaseCmp(field, "top") == 0)
1884 else if (uStrCaseCmp(field, "left") == 0)
1889 else if (uStrCaseCmp(field, "width") == 0)
1891 pField = &si->width;
1894 else if (uStrCaseCmp(field, "height") == 0)
1896 pField = &si->height;
1899 else if (uStrCaseCmp(field, "angle") == 0)
1901 pField = &si->angle;
1907 return ReportBadField("keyboard section", field, scText(si));
1909 if (arrayNdx != NULL)
1912 return ReportNotArray("keyboard section", field, scText(si));
1914 if (!ExprResolveFloat(value, &tmp))
1917 ReportBadType("keyboard section", field, scText(si), "number");
1920 si->defs.defined |= def;
1926 SetRowField(RowInfo * row,
1928 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1932 if (uStrCaseCmp(field, "top") == 0)
1934 if (arrayNdx != NULL)
1937 return ReportNotArray("keyboard row", field, rowText(row));
1939 if (!ExprResolveFloat(value, &tmp))
1942 return ReportBadType("keyboard row", field, rowText(row),
1945 row->defs.defined |= _GR_Top;
1946 row->top = tmp.uval;
1948 else if (uStrCaseCmp(field, "left") == 0)
1950 if (arrayNdx != NULL)
1953 return ReportNotArray("keyboard row", field, rowText(row));
1955 if (!ExprResolveFloat(value, &tmp))
1958 return ReportBadType("keyboard row", field, rowText(row),
1961 row->defs.defined |= _GR_Left;
1962 row->left = tmp.uval;
1964 else if (uStrCaseCmp(field, "vertical") == 0)
1966 if (arrayNdx != NULL)
1969 return ReportNotArray("keyboard row", field, rowText(row));
1971 if (!ExprResolveBoolean(value, &tmp))
1974 return ReportBadType("keyboard row", field, rowText(row),
1977 row->defs.defined |= _GR_Vertical;
1978 row->vertical = tmp.uval;
1983 return ReportBadField("keyboard row", field, rowText(row));
1989 SetKeyField(KeyInfo * key,
1991 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1995 if (uStrCaseCmp(field, "gap") == 0)
1997 if (arrayNdx != NULL)
2000 return ReportNotArray("key", field, keyText(key));
2002 if (!ExprResolveFloat(value, &tmp))
2005 return ReportBadType("key", field, keyText(key), "number");
2007 key->defs.defined |= _GK_Gap;
2008 key->gap = tmp.ival;
2010 else if (uStrCaseCmp(field, "shape") == 0)
2012 if (arrayNdx != NULL)
2015 return ReportNotArray("key", field, keyText(key));
2017 if (!ExprResolveString(value, &tmp))
2020 return ReportBadType("key", field, keyText(key), "string");
2022 key->defs.defined |= _GK_Shape;
2023 key->shape = xkb_intern_atom(tmp.str);
2026 else if ((uStrCaseCmp(field, "color") == 0) ||
2027 (uStrCaseCmp(field, "keycolor") == 0))
2029 if (arrayNdx != NULL)
2032 return ReportNotArray("key", field, keyText(key));
2034 if (!ExprResolveString(value, &tmp))
2037 return ReportBadType("key", field, keyText(key), "string");
2039 key->defs.defined |= _GK_Color;
2040 key->color = xkb_intern_atom(tmp.str);
2043 else if ((uStrCaseCmp(field, "name") == 0)
2044 || (uStrCaseCmp(field, "keyname") == 0))
2046 if (arrayNdx != NULL)
2049 return ReportNotArray("key", field, keyText(key));
2051 if (!ExprResolveKeyName(value, &tmp))
2054 return ReportBadType("key", field, keyText(key), "key name");
2056 key->defs.defined |= _GK_Name;
2057 memset(key->name, 0, XkbKeyNameLength + 1);
2058 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2063 return ReportBadField("key", field, keyText(key));
2069 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2075 InitPropertyInfo(&pi, info);
2077 if (!ExprResolveString(value, &result))
2080 ERROR("Property values must be type string\n");
2081 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2084 pi.value = result.str;
2085 ret = AddProperty(info, &pi);
2091 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2093 ExprResult elem, field, tmp;
2096 uint32_t *pField = NULL;
2097 int ret = True; /* default to no error */
2099 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2100 return 0; /* internal error, already reported */
2103 if (uStrCaseCmp(elem.str, "shape") == 0)
2104 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2105 else if (uStrCaseCmp(elem.str, "key") == 0)
2106 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2107 field.str, ndx, stmt->value, info);
2108 else if (uStrCaseCmp(elem.str, "row") == 0)
2109 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2111 else if (uStrCaseCmp(elem.str, "section") == 0)
2112 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2114 else if (uStrCaseCmp(elem.str, "property") == 0)
2119 ERROR("The %s geometry property is not an array\n", field.str);
2120 ACTION("Ignoring illegal property definition\n");
2124 ret = SetGeometryProperty(info, field.str, stmt->value);
2127 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2128 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2129 else if (uStrCaseCmp(elem.str, "solid") == 0)
2132 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2134 dflt = NextDfltDoodad(NULL, info);
2135 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2137 else if (uStrCaseCmp(elem.str, "outline") == 0)
2140 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2142 dflt = NextDfltDoodad(NULL, info);
2143 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2145 else if (uStrCaseCmp(elem.str, "text") == 0)
2148 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2150 dflt = NextDfltDoodad(NULL, info);
2151 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2153 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2156 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2158 dflt = NextDfltDoodad(NULL, info);
2159 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2161 else if (uStrCaseCmp(elem.str, "logo") == 0)
2164 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2166 dflt = NextDfltDoodad(NULL, info);
2167 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2171 WARN("Assignment to field of unknown element\n");
2172 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2180 if ((uStrCaseCmp(field.str, "width") == 0) ||
2181 (uStrCaseCmp(field.str, "widthmm") == 0))
2186 ret = ReportNotArray("keyboard", field.str, "geometry");
2188 else if (!ExprResolveFloat(stmt->value, &tmp))
2191 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2193 else if (tmp.ival < 1)
2195 WARN("Keyboard width must be positive\n");
2196 ACTION("Ignoring illegal keyboard width %s\n",
2197 XkbcGeomFPText(tmp.ival));
2201 if (info->widthMM != 0)
2203 WARN("Keyboard width multiply defined\n");
2204 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2205 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2207 info->widthMM = tmp.ival;
2213 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2214 (uStrCaseCmp(field.str, "heightmm") == 0))
2219 ret = ReportNotArray("keyboard", field.str, "geometry");
2221 else if (!ExprResolveFloat(stmt->value, &tmp))
2224 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2226 else if (tmp.ival < 1)
2228 WARN("Keyboard height must be positive\n");
2229 ACTION("Ignoring illegal keyboard height %s\n",
2230 XkbcGeomFPText(tmp.ival));
2234 if (info->heightMM != 0)
2236 WARN("Keyboard height multiply defined\n");
2237 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2238 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2240 info->heightMM = tmp.ival;
2246 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2251 ret = ReportNotArray("keyboard", field.str, "geometry");
2253 else if (!ExprResolveFloat(stmt->value, &tmp))
2256 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2258 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2261 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2262 ACTION("Ignoring font size in keyboard geometry\n");
2266 info->fontSize = tmp.ival;
2272 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2273 (uStrCaseCmp(field.str, "basecolor") == 0))
2278 ret = ReportNotArray("keyboard", field.str, "geometry");
2280 else if (!ExprResolveString(stmt->value, &tmp))
2283 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2286 info->baseColor = xkb_intern_atom(tmp.str);
2293 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2298 ret = ReportNotArray("keyboard", field.str, "geometry");
2300 else if (!ExprResolveString(stmt->value, &tmp))
2303 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2306 info->labelColor = xkb_intern_atom(tmp.str);
2313 else if (uStrCaseCmp(field.str, "font") == 0)
2315 pField = &info->font;
2317 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2318 (uStrCaseCmp(field.str, "slant") == 0))
2320 pField = &info->fontSlant;
2322 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2323 (uStrCaseCmp(field.str, "weight") == 0))
2325 pField = &info->fontWeight;
2327 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2328 (uStrCaseCmp(field.str, "setwidth") == 0))
2330 pField = &info->fontWeight;
2332 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2333 (uStrCaseCmp(field.str, "encoding") == 0))
2335 pField = &info->fontEncoding;
2337 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2338 (uStrCaseCmp(field.str, "xfontname") == 0))
2340 pField = &info->fontSpec;
2344 ret = SetGeometryProperty(info, field.str, stmt->value);
2349 /* fallthrough for the cases that set pField */
2353 ret = ReportNotArray("keyboard", field.str, "geometry");
2355 else if (!ExprResolveString(stmt->value, &tmp))
2358 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2361 *pField = xkb_intern_atom(tmp.str);
2368 /***====================================================================***/
2371 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2372 GeometryInfo * info)
2376 struct xkb_outline * outline;
2379 if (def->nOutlines < 1)
2381 WARN("Shape \"%s\" has no outlines\n", shText(si));
2382 ACTION("Definition ignored\n");
2385 si->nOutlines = def->nOutlines;
2386 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2389 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2390 ACTION("Definition ignored\n");
2394 for (nOut = 0, ol = def->outlines; ol != NULL;
2395 ol = (OutlineDef *) ol->common.next)
2397 if (ol->nPoints < 1)
2399 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2403 outline = &si->outlines[nOut++];
2404 outline->num_points = ol->nPoints;
2405 outline->corner_radius = si->dfltCornerRadius;
2406 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2407 if (!outline->points)
2409 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2410 ACTION("Definition ignored\n");
2415 for (nPt = 0, pt = ol->points; pt != NULL;
2416 pt = (ExprDef *) pt->common.next)
2418 outline->points[nPt].x = pt->value.coord.x;
2419 outline->points[nPt].y = pt->value.coord.y;
2422 if (ol->field != None)
2424 const char *str = XkbcAtomText(ol->field);
2425 if ((uStrCaseCmp(str, "approximation") == 0) ||
2426 (uStrCaseCmp(str, "approx") == 0))
2428 if (si->approx == NULL)
2429 si->approx = outline;
2432 WARN("Multiple approximations for \"%s\"\n",
2434 ACTION("Treating all but the first as normal outlines\n");
2437 else if (uStrCaseCmp(str, "primary") == 0)
2439 if (si->primary == NULL)
2440 si->primary = outline;
2443 WARN("Multiple primary outlines for \"%s\"\n",
2445 ACTION("Treating all but the first as normal outlines\n");
2450 WARN("Unknown outline type %s for \"%s\"\n", str,
2452 ACTION("Treated as a normal outline\n");
2456 if (nOut != si->nOutlines)
2458 WSGO("Expected %d outlines, got %d\n",
2459 (unsigned int) si->nOutlines, nOut);
2460 si->nOutlines = nOut;
2466 HandleShapeDef(ShapeDef * def, struct xkb_desc * xkb, unsigned merge,
2467 GeometryInfo * info)
2471 if (def->merge != MergeDefault)
2474 memset(&si, 0, sizeof(ShapeInfo));
2475 si.defs.merge = merge;
2476 si.name = def->name;
2477 si.dfltCornerRadius = info->dfltCornerRadius;
2478 if (!HandleShapeBody(def, &si, merge, info))
2480 if (!AddShape(info, &si))
2485 /***====================================================================***/
2488 HandleDoodadDef(DoodadDef * def,
2489 unsigned merge, SectionInfo * si, GeometryInfo * info)
2491 ExprResult elem, field;
2496 if (def->common.stmtType == StmtIndicatorMapDef)
2498 def->common.stmtType = StmtDoodadDef;
2499 def->type = XkbIndicatorDoodad;
2501 InitDoodadInfo(&new, def->type, si, info);
2502 new.name = def->name;
2503 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2505 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2506 return 0; /* internal error, already reported */
2507 if (elem.str != NULL)
2509 WARN("Assignment to field of unknown element in doodad %s\n",
2511 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2514 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2520 if (!AddDoodad(si, info, &new))
2522 ClearDoodadInfo(&new);
2526 /***====================================================================***/
2529 HandleOverlayDef(OverlayDef * def,
2530 unsigned merge, SectionInfo * si, GeometryInfo * info)
2532 OverlayKeyDef *keyDef;
2533 OverlayKeyInfo *key;
2536 if ((def->nKeys < 1) && (warningLevel > 3))
2538 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2539 XkbcAtomText(def->name), scText(si));
2540 ACTION("Overlay ignored\n");
2543 memset(&ol, 0, sizeof(OverlayInfo));
2544 ol.name = def->name;
2545 for (keyDef = def->keys; keyDef;
2546 keyDef = (OverlayKeyDef *) keyDef->common.next)
2548 key = uTypedCalloc(1, OverlayKeyInfo);
2551 if (warningLevel > 0)
2553 WSGO("Couldn't allocate OverlayKeyInfo\n");
2554 ACTION("Overlay %s for section %s will be incomplete\n",
2555 XkbcAtomText(ol.name), scText(si));
2559 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2560 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2561 key->sectionRow = _GOK_UnknownRow;
2562 key->overlayRow = _GOK_UnknownRow;
2563 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2564 (CommonInfo *) key);
2567 if (!AddOverlay(si, info, &ol))
2569 ClearOverlayInfo(&ol);
2573 /***====================================================================***/
2576 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2580 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2582 if (expr->op == OpAssign)
2586 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2587 return False; /* internal error, already reported */
2588 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2591 (key, f.str, ndx, expr->value.binary.right, info))
2602 ERROR("Illegal element used in a key definition\n");
2603 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2611 RowInfo *row = key->row;
2616 if (!SetKeyField(key, "gap", NULL, expr, info))
2620 if (!SetKeyField(key, "shape", NULL, expr, info))
2624 if (!SetKeyField(key, "name", NULL, expr, info))
2628 ERROR("Cannot determine field for unnamed expression\n");
2630 ACTION("Ignoring key %d in row %d of section %s\n",
2631 row->nKeys + 1, row->section->nRows + 1,
2641 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2642 GeometryInfo * info)
2646 if ((def->nKeys < 1) && (warningLevel > 3))
2648 ERROR("Row in section %s has no keys\n", rowText(row));
2649 ACTION("Section ignored\n");
2652 for (keyDef = def->keys; keyDef != NULL;
2653 keyDef = (KeyDef *) keyDef->common.next)
2655 if (keyDef->common.stmtType == StmtVarDef)
2657 VarDef *var = (VarDef *) keyDef;
2658 ExprResult elem, field;
2660 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2661 return 0; /* internal error, already reported */
2662 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2664 if (!SetRowField(row, field.str, ndx, var->value, info))
2667 else if (uStrCaseCmp(elem.str, "key") == 0)
2670 (&row->dfltKey, field.str, ndx, var->value, info))
2675 WARN("Assignment to field of unknown element in row\n");
2676 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2681 else if (keyDef->common.stmtType == StmtKeyDef)
2684 InitKeyInfo(&key, row, info);
2685 if (keyDef->name != NULL)
2687 int len = strlen(keyDef->name);
2688 if ((len < 1) || (len > XkbKeyNameLength))
2690 ERROR("Illegal name %s for key in section %s\n",
2691 keyDef->name, rowText(row));
2692 ACTION("Section not compiled\n");
2695 memset(key.name, 0, XkbKeyNameLength + 1);
2696 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2697 key.defs.defined |= _GK_Name;
2699 else if (!HandleComplexKey(keyDef, &key, info))
2701 if (!AddKey(row, &key))
2706 WSGO("Unexpected statement (type %d) in row body\n",
2707 keyDef->common.stmtType);
2715 HandleSectionBody(SectionDef * def,
2716 SectionInfo * si, unsigned merge, GeometryInfo * info)
2721 for (rowDef = def->rows; rowDef != NULL;
2722 rowDef = (RowDef *) rowDef->common.next)
2724 if (rowDef->common.stmtType == StmtVarDef)
2726 VarDef *var = (VarDef *) rowDef;
2727 ExprResult elem, field;
2729 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2730 return 0; /* internal error, already reported */
2731 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2733 if (!SetSectionField(si, field.str, ndx, var->value, info))
2739 else if (uStrCaseCmp(elem.str, "row") == 0)
2742 (&si->dfltRow, field.str, ndx, var->value, info))
2748 else if (uStrCaseCmp(elem.str, "key") == 0)
2750 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2758 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2760 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2768 WARN("Assignment to field of unknown element in section\n");
2769 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2774 else if (rowDef->common.stmtType == StmtRowDef)
2777 InitRowInfo(&row, si, info);
2778 if (!HandleRowBody(rowDef, &row, merge, info))
2780 if (!AddRow(si, &row))
2782 /* ClearRowInfo(&row,info);*/
2784 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2785 (rowDef->common.stmtType == StmtIndicatorMapDef))
2787 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2790 else if (rowDef->common.stmtType == StmtOverlayDef)
2792 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2797 WSGO("Unexpected statement (type %d) in section body\n",
2798 rowDef->common.stmtType);
2802 if (si->nRows != def->nRows)
2804 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2805 (unsigned int) si->nRows);
2806 ACTION("Definition of section %s might be incorrect\n", scText(si));
2812 HandleSectionDef(SectionDef * def,
2813 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2817 if (def->merge != MergeDefault)
2819 InitSectionInfo(&si, info);
2820 si.defs.merge = merge;
2821 si.name = def->name;
2822 if (!HandleSectionBody(def, &si, merge, info))
2824 if (!AddSection(info, &si))
2829 /***====================================================================***/
2832 HandleGeometryFile(XkbFile * file,
2833 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2836 const char *failWhat;
2838 if (merge == MergeDefault)
2839 merge = MergeAugment;
2840 info->name = _XkbDupString(file->name);
2845 switch (stmt->stmtType)
2848 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2849 HandleGeometryFile))
2852 case StmtKeyAliasDef:
2853 if (!HandleAliasDef((KeyAliasDef *) stmt,
2854 merge, info->fileID, &info->aliases))
2860 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2864 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2867 case StmtSectionDef:
2868 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2871 case StmtIndicatorMapDef:
2873 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2878 failWhat = "virtual modfier";
2881 failWhat = "symbol interpretation";
2882 case StmtGroupCompatDef:
2884 failWhat = "group compatibility map";
2885 case StmtKeycodeDef:
2887 failWhat = "key name";
2888 ERROR("Interpretation files may not include other types\n");
2889 ACTION("Ignoring %s definition.\n", failWhat);
2893 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2898 if (info->errorCount > 10)
2901 ERROR("Too many errors\n");
2903 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2909 /***====================================================================***/
2912 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2915 struct xkb_shape * shape;
2916 struct xkb_outline *old_outline, *outline;
2919 si->index = geom->num_shapes;
2921 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2924 WSGO("Couldn't allocate shape in geometry\n");
2925 ACTION("Shape %s not compiled\n", shText(si));
2928 old_outline = si->outlines;
2929 for (i = 0; i < si->nOutlines; i++, old_outline++)
2931 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2934 WSGO("Couldn't allocate outline in shape\n");
2935 ACTION("Shape %s is incomplete\n", shText(si));
2938 n = old_outline->num_points;
2939 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2940 outline->num_points = old_outline->num_points;
2941 outline->corner_radius = old_outline->corner_radius;
2945 n = (si->approx - si->outlines);
2946 shape->approx = &shape->outlines[n];
2950 n = (si->primary - si->outlines);
2951 shape->primary = &shape->outlines[n];
2953 XkbcComputeShapeBounds(shape);
2958 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2960 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2962 if (warningLevel < 9)
2964 ERROR("No position defined for doodad %s\n",
2966 ACTION("Illegal doodad ignored\n");
2970 if ((di->defs.defined & _GD_Priority) == 0)
2972 /* calculate priority -- should be just above previous doodad/row */
2976 case XkbOutlineDoodad:
2977 case XkbSolidDoodad:
2978 if ((di->defs.defined & _GD_Shape) == 0)
2980 ERROR("No shape defined for %s doodad %s\n",
2981 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2983 ACTION("Incomplete definition ignored\n");
2989 si = FindShape(info, di->shape,
2991 XkbOutlineDoodad ? "outline doodad" :
2992 "solid doodad"), ddText(di));
2994 di->shape = si->name;
2997 ERROR("No legal shape for %s\n", ddText(di));
2998 ACTION("Incomplete definition ignored\n");
3002 if ((di->defs.defined & _GD_Color) == 0)
3004 if (warningLevel > 5)
3006 WARN("No color for doodad %s\n", ddText(di));
3007 ACTION("Using black\n");
3009 di->color = xkb_intern_atom("black");
3013 if ((di->defs.defined & _GD_Text) == 0)
3015 ERROR("No text specified for text doodad %s\n", ddText(di));
3016 ACTION("Illegal doodad definition ignored\n");
3019 if ((di->defs.defined & _GD_Angle) == 0)
3021 if ((di->defs.defined & _GD_Color) == 0)
3023 if (warningLevel > 5)
3025 WARN("No color specified for doodad %s\n", ddText(di));
3026 ACTION("Using black\n");
3028 di->color = xkb_intern_atom("black");
3030 if ((di->defs.defined & _GD_FontSpec) != 0)
3032 if ((di->defs.defined & _GD_FontParts) == 0)
3034 if (warningLevel < 9)
3037 ("Text doodad %s has full and partial font definition\n",
3039 ACTION("Full specification ignored\n");
3041 di->defs.defined &= ~_GD_FontSpec;
3042 di->fontSpec = None;
3044 if ((di->defs.defined & _GD_Font) == 0)
3046 if (warningLevel > 5)
3048 WARN("No font specified for doodad %s\n", ddText(di));
3049 ACTION("Using \"%s\"\n", DFLT_FONT);
3051 di->font = xkb_intern_atom(DFLT_FONT);
3053 if ((di->defs.defined & _GD_FontSlant) == 0)
3055 if (warningLevel > 7)
3057 WARN("No font slant for text doodad %s\n", ddText(di));
3058 ACTION("Using \"%s\"\n", DFLT_SLANT);
3060 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3062 if ((di->defs.defined & _GD_FontWeight) == 0)
3064 if (warningLevel > 7)
3066 WARN("No font weight for text doodad %s\n", ddText(di));
3067 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3069 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3071 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3073 if (warningLevel > 9)
3075 WARN("No font set width for text doodad %s\n", ddText(di));
3076 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3078 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3080 if ((di->defs.defined & _GD_FontVariant) == 0)
3082 if (warningLevel > 9)
3084 WARN("No font variant for text doodad %s\n", ddText(di));
3085 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3087 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3089 if ((di->defs.defined & _GD_FontEncoding) == 0)
3091 if (warningLevel > 7)
3093 WARN("No font encoding for doodad %s\n", ddText(di));
3094 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3096 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3098 if ((di->defs.defined & _GD_FontSize) == 0)
3100 if (warningLevel > 7)
3102 WARN("No font size for text doodad %s\n", ddText(di));
3103 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3105 di->fontSize = DFLT_SIZE;
3107 if ((di->defs.defined & _GD_Height) == 0)
3109 unsigned size, nLines;
3111 size = (di->fontSize * 120) / 100;
3112 size = (size * 254) / 720; /* convert to mm/10 */
3113 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3119 if (warningLevel > 5)
3121 WARN("No height for text doodad %s\n", ddText(di));
3122 ACTION("Using calculated height %s millimeters\n",
3123 XkbcGeomFPText(size));
3127 if ((di->defs.defined & _GD_Width) == 0)
3129 unsigned width, tmp;
3132 for (str = XkbcAtomText(di->text); *str; str++)
3145 width *= (di->height * 2) / 3;
3146 if (warningLevel > 5)
3148 WARN("No width for text doodad %s\n", ddText(di));
3149 ACTION("Using calculated width %s millimeters\n",
3150 XkbcGeomFPText(width));
3155 case XkbIndicatorDoodad:
3156 if ((di->defs.defined & _GD_Shape) == 0)
3158 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3159 ACTION("Incomplete definition ignored\n");
3165 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3167 di->shape = si->name;
3170 ERROR("No legal shape for doodad %s\n", ddText(di));
3171 ACTION("Incomplete definition ignored\n");
3175 if ((di->defs.defined & _GD_Color) == 0)
3177 if (warningLevel > 5)
3179 WARN("No \"on\" color for indicator doodad %s\n",
3181 ACTION("Using green\n");
3183 di->color = xkb_intern_atom("green");
3185 if ((di->defs.defined & _GD_OffColor) == 0)
3187 if (warningLevel > 5)
3189 WARN("No \"off\" color for indicator doodad %s\n",
3191 ACTION("Using black\n");
3193 di->offColor = xkb_intern_atom("black");
3197 if (di->logoName == NULL)
3199 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3200 ACTION("Incomplete definition ignored\n");
3203 if ((di->defs.defined & _GD_Shape) == 0)
3205 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3206 ACTION("Incomplete definition ignored\n");
3212 si = FindShape(info, di->shape, "logo doodad",
3215 di->shape = si->name;
3218 ERROR("No legal shape for %s\n", ddText(di));
3219 ACTION("Incomplete definition ignored\n");
3223 if ((di->defs.defined & _GD_Color) == 0)
3225 if (warningLevel > 5)
3227 WARN("No color for doodad %s\n", ddText(di));
3228 ACTION("Using black\n");
3230 di->color = xkb_intern_atom("black");
3234 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3235 (unsigned int) di->type);
3241 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3244 FontFromParts(uint32_t fontTok,
3247 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3250 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3253 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3254 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3255 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3257 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3258 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3260 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3264 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3265 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3266 rtrn = calloc(totalSize, 1);
3268 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3274 CopyDoodadDef(struct xkb_geometry * geom,
3275 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3278 union xkb_doodad * doodad;
3279 struct xkb_color * color;
3280 struct xkb_shape * shape;
3283 if (!VerifyDoodadInfo(di, info))
3286 doodad = XkbcAddGeomDoodad(geom, section, name);
3289 WSGO("Couldn't allocate doodad in %s\n",
3290 (section ? "section" : "geometry"));
3291 ACTION("Cannot copy doodad %s\n", ddText(di));
3294 doodad->any.type = di->type;
3295 doodad->any.priority = di->priority;
3296 doodad->any.top = di->top;
3297 doodad->any.left = di->left;
3300 case XkbOutlineDoodad:
3301 case XkbSolidDoodad:
3302 si = FindShape(info, di->shape, NULL, NULL);
3305 doodad->shape.angle = di->angle;
3306 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3308 shape = &geom->shapes[si->index];
3309 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3310 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3313 doodad->text.angle = di->angle;
3314 doodad->text.width = di->width;
3315 doodad->text.height = di->height;
3316 if (di->fontSpec == None)
3317 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3320 di->fontVariant, di->fontSize,
3323 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3324 doodad->text.text = XkbcAtomGetString(di->text);
3325 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3327 XkbSetTextDoodadColor(geom, &doodad->text, color);
3329 case XkbIndicatorDoodad:
3330 si = FindShape(info, di->shape, NULL, NULL);
3333 shape = &geom->shapes[si->index];
3334 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3336 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3337 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3338 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3340 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3343 si = FindShape(info, di->shape, NULL, NULL);
3346 doodad->logo.angle = di->angle;
3347 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3349 shape = &geom->shapes[si->index];
3350 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3351 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3352 doodad->logo.logo_name = di->logoName;
3353 di->logoName = NULL;
3359 /***====================================================================***/
3362 VerifyOverlayInfo(struct xkb_geometry * geom,
3363 struct xkb_section * section,
3365 GeometryInfo * info, short rowMap[256], short rowSize[256])
3367 OverlayKeyInfo *ki, *next;
3368 unsigned long oKey, uKey, sKey;
3369 struct xkb_row * row;
3370 struct xkb_key * key;
3373 /* find out which row each key is in */
3374 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3376 oKey = KeyNameToLong(ki->over);
3377 uKey = KeyNameToLong(ki->under);
3378 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3381 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3384 sKey = KeyNameToLong(key->name.name);
3387 if (warningLevel > 0)
3390 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3391 XkbcKeyNameText(key->name.name),
3392 XkbcAtomText(section->name),
3393 XkbcAtomText(oi->name));
3394 ACTION("Overlay definition ignored\n");
3398 else if (sKey == uKey)
3405 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3408 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3409 XkbcKeyNameText(ki->under),
3410 XkbcAtomText(section->name),
3411 XkbcAtomText(oi->name));
3412 ACTION("Definition ignored\n");
3415 /* now prune out keys that aren't in the section */
3416 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3418 next = (OverlayKeyInfo *) oi->keys->defs.next;
3423 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3425 next = (OverlayKeyInfo *) ki->defs.next;
3426 if (next->sectionRow == _GOK_UnknownRow)
3428 ki->defs.next = next->defs.next;
3431 next = (OverlayKeyInfo *) ki->defs.next;
3436 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3437 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3438 ACTION("Overlay definition ignored\n");
3441 /* now figure out how many rows are defined for the overlay */
3442 memset(rowSize, 0, sizeof(short) * 256);
3443 for (k = 0; k < 256; k++)
3448 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3450 if (rowMap[ki->sectionRow] == -1)
3451 rowMap[ki->sectionRow] = oi->nRows++;
3452 ki->overlayRow = rowMap[ki->sectionRow];
3453 rowSize[ki->overlayRow]++;
3459 CopyOverlayDef(struct xkb_geometry * geom,
3460 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3463 struct xkb_overlay * ol;
3464 struct xkb_overlay_row * row;
3465 struct xkb_overlay_key * key;
3467 short rowMap[256], rowSize[256];
3470 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3473 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3476 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3477 XkbcAtomText(name), XkbcAtomText(section->name));
3480 for (i = 0; i < oi->nRows; i++)
3483 for (tmp = 0, row_under = -1;
3484 (tmp < section->num_rows) && (row_under < 0); tmp++)
3486 if (rowMap[tmp] == i)
3489 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3492 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3493 i, XkbcAtomText(name), XkbcAtomText(section->name));
3497 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3499 row = &ol->rows[ki->overlayRow];
3500 key = &row->keys[row->num_keys++];
3501 memset(key, 0, sizeof(struct xkb_overlay_key));
3502 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3503 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3508 /***====================================================================***/
3511 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3513 struct xkb_section * section;
3514 struct xkb_row * row;
3515 struct xkb_key * key;
3519 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3521 if (section == NULL)
3523 WSGO("Couldn't allocate section in geometry\n");
3524 ACTION("Section %s not compiled\n", scText(si));
3527 section->top = si->top;
3528 section->left = si->left;
3529 section->width = si->width;
3530 section->height = si->height;
3531 section->angle = si->angle;
3532 section->priority = si->priority;
3533 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3535 row = XkbcAddGeomRow(section, ri->nKeys);
3538 WSGO("Couldn't allocate row in section\n");
3539 ACTION("Section %s is incomplete\n", scText(si));
3543 row->left = ri->left;
3544 row->vertical = ri->vertical;
3545 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3547 struct xkb_color * color;
3548 if ((ki->defs.defined & _GK_Name) == 0)
3550 ERROR("Key %d of row %d in section %s has no name\n",
3551 (int) ki->index, (int) ri->index, scText(si));
3552 ACTION("Section %s ignored\n", scText(si));
3555 key = XkbcAddGeomKey(row);
3558 WSGO("Couldn't allocate key in row\n");
3559 ACTION("Section %s is incomplete\n", scText(si));
3562 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3564 if (ki->shape == None)
3569 shapei = FindShape(info, ki->shape, "key", keyText(ki));
3572 key->shape_ndx = shapei->index;
3574 if (ki->color != None)
3576 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3579 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3580 XkbSetKeyColor(geom, key, color);
3583 if (si->doodads != NULL)
3586 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3588 CopyDoodadDef(geom, section, di, info);
3591 if (si->overlays != NULL)
3594 for (oi = si->overlays; oi != NULL;
3595 oi = (OverlayInfo *) oi->defs.next)
3597 CopyOverlayDef(geom, section, oi, info);
3600 if (XkbcComputeSectionBounds(geom, section))
3602 /* 7/6/94 (ef) -- check for negative origin and translate */
3603 if ((si->defs.defined & _GS_Width) == 0)
3604 section->width = section->bounds.x2;
3605 if ((si->defs.defined & _GS_Height) == 0)
3606 section->height = section->bounds.y2;
3611 /***====================================================================***/
3614 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3618 InitGeometryInfo(&info, file->id, merge);
3619 HandleGeometryFile(file, xkb, merge, &info);
3621 if (info.errorCount == 0)
3623 struct xkb_geometry * geom;
3624 struct xkb_geometry_sizes sizes;
3625 memset(&sizes, 0, sizeof(sizes));
3626 sizes.which = XkbGeomAllMask;
3627 sizes.num_properties = info.nProps;
3628 sizes.num_colors = 8;
3629 sizes.num_shapes = info.nShapes;
3630 sizes.num_sections = info.nSections;
3631 sizes.num_doodads = info.nDoodads;
3632 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3634 WSGO("Couldn't allocate GeometryRec\n");
3635 ACTION("Geometry not compiled\n");
3640 geom->width_mm = info.widthMM;
3641 geom->height_mm = info.heightMM;
3642 if (info.name != NULL)
3644 geom->name = xkb_intern_atom(info.name);
3645 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3646 xkb->names->geometry = geom->name;
3648 if (info.fontSpec != None)
3649 geom->label_font = XkbcAtomGetString(info.fontSpec);
3651 geom->label_font = FontFromParts(info.font, info.fontWeight,
3657 XkbcAddGeomColor(geom, "black", geom->num_colors);
3658 XkbcAddGeomColor(geom, "white", geom->num_colors);
3660 if (info.baseColor == None)
3661 info.baseColor = xkb_intern_atom("white");
3662 if (info.labelColor == None)
3663 info.labelColor = xkb_intern_atom("black");
3665 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3668 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3674 for (pi = info.props; pi != NULL;
3675 pi = (PropertyInfo *) pi->defs.next)
3677 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3684 for (si = info.shapes; si != NULL;
3685 si = (ShapeInfo *) si->defs.next)
3687 if (!CopyShapeDef(geom, si))
3694 for (si = info.sections; si != NULL;
3695 si = (SectionInfo *) si->defs.next)
3697 if (!CopySectionDef(geom, si, &info))
3704 for (di = info.doodads; di != NULL;
3705 di = (DoodadInfo *) di->defs.next)
3707 if (!CopyDoodadDef(geom, NULL, di, &info))
3712 ApplyAliases(xkb, True, &info.aliases);
3713 ClearGeometryInfo(&info);