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 ********************************************************/
32 #include "indicators.h"
37 #include "X11/extensions/XKBgeom.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 XkbOutlinePtr outlines;
66 XkbOutlinePtr primary;
71 ((s)?XkbAtomText((d),(s)->name,XkbMessage):"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;
117 unsigned short fontSize;
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;
161 #define rowText(d,r) \
162 ((r)?XkbAtomText((d),(r)->section->name,XkbMessage):"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;
184 #define _GS_Default (1<<0)
185 #define _GS_Name (1<<1)
186 #define _GS_Top (1<<2)
187 #define _GS_Left (1<<3)
188 #define _GS_Width (1<<4)
189 #define _GS_Height (1<<5)
190 #define _GS_Angle (1<<6)
191 #define _GS_Priority (1<<7)
192 typedef struct _SectionInfo
198 unsigned short width;
199 unsigned short height;
200 unsigned short angle;
201 unsigned short nRows;
202 unsigned short nDoodads;
203 unsigned short nOverlays;
204 unsigned char priority;
205 unsigned char nextDoodadPriority;
209 DoodadInfo *dfltDoodads;
210 OverlayInfo *overlays;
211 struct _GeometryInfo *geometry;
213 #define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default")
215 typedef struct _GeometryInfo
222 unsigned nextPriority;
229 SectionInfo *sections;
243 int dfltCornerRadius;
244 SectionInfo dfltSection;
245 DoodadInfo *dfltDoodads;
250 ddText(Display * dpy, DoodadInfo * di)
256 strcpy(buf, "default");
261 sprintf(buf, "%s in section %s",
262 XkbAtomText(dpy, di->name, XkbMessage), scText(dpy,
266 return XkbAtomText(dpy, di->name, XkbMessage);
269 /***====================================================================***/
272 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
274 pi->defs.defined = 0;
275 pi->defs.fileID = info->fileID;
276 pi->defs.merge = info->merge;
277 pi->name = pi->value = NULL;
282 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
287 if (info->props == pi)
292 for (tmp = pi; tmp != NULL; tmp = next)
298 tmp->name = tmp->value = NULL;
299 next = (PropertyInfo *) tmp->defs.next;
306 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
309 if (key != &row->dfltKey)
312 strcpy(key->name, "unknown");
313 key->defs.defined &= ~_GK_Default;
317 bzero(key, sizeof(KeyInfo));
318 strcpy(key->name, "default");
319 key->defs.defined = _GK_Default;
320 key->defs.fileID = info->fileID;
321 key->defs.merge = info->merge;
322 key->defs.next = NULL;
329 ClearKeyInfo(KeyInfo * key)
331 key->defs.defined &= ~_GK_Default;
332 strcpy(key->name, "default");
340 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
345 if (row->keys == key)
350 for (tmp = key; tmp != NULL; tmp = next)
353 next = (KeyInfo *) tmp->defs.next;
360 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
362 if (row != §ion->dfltRow)
364 *row = section->dfltRow;
365 row->defs.defined &= ~_GR_Default;
369 bzero(row, sizeof(*row));
370 row->defs.defined = _GR_Default;
371 row->defs.fileID = info->fileID;
372 row->defs.merge = info->merge;
373 row->defs.next = NULL;
374 row->section = section;
377 InitKeyInfo(&row->dfltKey, row, info);
383 ClearRowInfo(RowInfo * row, GeometryInfo * info)
385 row->defs.defined &= ~_GR_Default;
386 row->top = row->left = 0;
387 row->vertical = False;
390 FreeKeys(row->keys, row, info);
391 ClearKeyInfo(&row->dfltKey);
392 row->dfltKey.defs.defined |= _GK_Default;
397 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
402 if (row == section->rows)
405 section->rows = NULL;
407 for (tmp = row; tmp != NULL; tmp = next)
409 ClearRowInfo(tmp, info);
410 next = (RowInfo *) tmp->defs.next;
417 FindDoodadByType(DoodadInfo * di, unsigned type)
421 if (di->type == type)
423 di = (DoodadInfo *) di->defs.next;
429 FindDoodadByName(DoodadInfo * di, Atom name)
433 if (di->name == name)
435 di = (DoodadInfo *) di->defs.next;
441 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
447 if (si && si->dfltDoodads)
448 dflt = FindDoodadByType(si->dfltDoodads, type);
449 if ((dflt == NULL) && (info->dfltDoodads))
450 dflt = FindDoodadByType(info->dfltDoodads, type);
454 di->defs.next = NULL;
458 bzero(di, sizeof(DoodadInfo));
459 di->defs.fileID = info->fileID;
465 di->priority = si->nextDoodadPriority++;
466 #if XkbGeomMaxPriority < 255
467 if (si->nextDoodadPriority > XkbGeomMaxPriority)
468 si->nextDoodadPriority = XkbGeomMaxPriority;
473 di->priority = info->nextPriority++;
474 if (info->nextPriority > XkbGeomMaxPriority)
475 info->nextPriority = XkbGeomMaxPriority;
481 ClearDoodadInfo(DoodadInfo * di)
486 bzero(di, sizeof(DoodadInfo));
488 di->defs.defined = 0;
493 ClearOverlayInfo(OverlayInfo * ol)
497 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
504 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
511 if (si->doodads == di)
516 if (si->dfltDoodads == di)
517 si->dfltDoodads = NULL;
519 if (info->doodads == di)
521 info->doodads = NULL;
524 if (info->dfltDoodads == di)
525 info->dfltDoodads = NULL;
526 for (tmp = di; tmp != NULL; tmp = next)
528 next = (DoodadInfo *) tmp->defs.next;
529 ClearDoodadInfo(tmp);
536 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
538 if (si != &info->dfltSection)
540 *si = info->dfltSection;
541 si->defs.defined &= ~_GS_Default;
542 si->name = XkbInternAtom(info->dpy, "unknown", False);
543 si->priority = info->nextPriority++;
544 if (info->nextPriority > XkbGeomMaxPriority)
545 info->nextPriority = XkbGeomMaxPriority;
549 bzero(si, sizeof(SectionInfo));
550 si->defs.fileID = info->fileID;
551 si->defs.merge = info->merge;
552 si->defs.next = NULL;
554 si->name = XkbInternAtom(info->dpy, "default", False);
555 InitRowInfo(&si->dfltRow, si, info);
561 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
567 into->defs.fileID = defs.fileID;
568 into->defs.merge = defs.merge;
569 into->defs.next = NULL;
570 into->dfltRow.defs.fileID = defs.fileID;
571 into->dfltRow.defs.merge = defs.merge;
572 into->dfltRow.defs.next = NULL;
573 into->dfltRow.section = into;
574 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
575 into->dfltRow.dfltKey.defs.merge = defs.merge;
576 into->dfltRow.dfltKey.defs.next = NULL;
577 into->dfltRow.dfltKey.row = &into->dfltRow;
582 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
585 si->defs.defined &= ~_GS_Default;
586 si->name = XkbInternAtom(info->dpy, "default", False);
587 si->top = si->left = 0;
588 si->width = si->height = 0;
592 FreeRows(si->rows, si, info);
595 ClearRowInfo(&si->dfltRow, info);
598 FreeDoodads(si->doodads, si, info);
601 si->dfltRow.defs.defined = _GR_Default;
606 FreeSections(SectionInfo * si, GeometryInfo * info)
611 if (si == info->sections)
614 info->sections = NULL;
616 for (tmp = si; tmp != NULL; tmp = next)
618 ClearSectionInfo(tmp, info);
619 next = (SectionInfo *) tmp->defs.next;
626 FreeShapes(ShapeInfo * si, GeometryInfo * info)
631 if (si == info->shapes)
636 for (tmp = si; tmp != NULL; tmp = next)
641 for (i = 0; i < tmp->nOutlines; i++)
643 if (tmp->outlines[i].points != NULL)
645 uFree(tmp->outlines[i].points);
646 tmp->outlines[i].num_points = 0;
647 tmp->outlines[i].points = NULL;
650 uFree(tmp->outlines);
653 tmp->outlines = NULL;
654 tmp->primary = tmp->approx = NULL;
656 next = (ShapeInfo *) tmp->defs.next;
662 /***====================================================================***/
665 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
667 bzero(info, sizeof(GeometryInfo));
668 info->fileID = fileID;
670 InitSectionInfo(&info->dfltSection, info);
671 info->dfltSection.defs.defined = _GS_Default;
676 ClearGeometryInfo(GeometryInfo * info)
682 FreeProperties(info->props, info);
684 FreeShapes(info->shapes, info);
686 FreeSections(info->sections, info);
689 info->dfltCornerRadius = 0;
690 ClearSectionInfo(&info->dfltSection, info);
691 info->dfltSection.defs.defined = _GS_Default;
693 ClearAliases(&info->aliases);
697 /***====================================================================***/
699 static PropertyInfo *
700 NextProperty(GeometryInfo * info)
704 pi = uTypedAlloc(PropertyInfo);
707 bzero((char *) pi, sizeof(PropertyInfo));
708 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
715 static PropertyInfo *
716 FindProperty(GeometryInfo * info, char *name)
722 for (old = info->props; old != NULL;
723 old = (PropertyInfo *) old->defs.next)
725 if ((old->name) && (uStringEqual(name, old->name)))
732 AddProperty(GeometryInfo * info, PropertyInfo * new)
736 if ((!new) || (!new->value) || (!new->name))
738 old = FindProperty(info, new->name);
741 if ((new->defs.merge == MergeReplace)
742 || (new->defs.merge == MergeOverride))
744 if (((old->defs.fileID == new->defs.fileID)
745 && (warningLevel > 0)) || (warningLevel > 9))
747 WARN1("Multiple definitions for the \"%s\" property\n",
749 ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value,
754 old->value = uStringDup(new->value);
757 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
758 || (warningLevel > 9))
760 WARN1("Multiple definitions for \"%s\" property\n", new->name);
761 ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value,
767 if ((new = NextProperty(info)) == NULL)
769 new->defs.next = NULL;
770 new->name = uStringDup(old->name);
771 new->value = uStringDup(old->value);
775 /***====================================================================***/
778 NextShape(GeometryInfo * info)
782 si = uTypedAlloc(ShapeInfo);
785 bzero((char *) si, sizeof(ShapeInfo));
786 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
789 si->dfltCornerRadius = info->dfltCornerRadius;
795 FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
799 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
801 if (name == old->name)
807 WARN3("Unknown shape \"%s\" for %s %s\n",
808 XkbAtomText(info->dpy, name, XkbMessage), type, which);
811 ACTION1("Using default shape %s instead\n",
812 shText(info->dpy, old));
815 ACTION("No default shape; definition ignored\n");
822 AddShape(GeometryInfo * info, ShapeInfo * new)
826 old = FindShape(info, new->name, NULL, NULL);
829 if ((new->defs.merge == MergeReplace)
830 || (new->defs.merge == MergeOverride))
832 ShapeInfo *next = (ShapeInfo *) old->defs.next;
833 if (((old->defs.fileID == new->defs.fileID)
834 && (warningLevel > 0)) || (warningLevel > 9))
836 WARN1("Duplicate shape name \"%s\"\n",
837 shText(info->dpy, old));
838 ACTION("Using last definition\n");
841 old->defs.next = &next->defs;
844 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
845 || (warningLevel > 9))
847 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
848 ACTION("Using first definition\n");
853 if ((new = NextShape(info)) == NULL)
856 new->defs.next = NULL;
857 old->szOutlines = old->nOutlines = 0;
858 old->outlines = NULL;
864 /***====================================================================***/
867 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
871 next = into->defs.next;
872 ClearDoodadInfo(into);
874 into->defs.next = next;
875 next = from->defs.next;
876 ClearDoodadInfo(from);
877 from->defs.next = next;
882 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
886 di = uTypedCalloc(1, DoodadInfo);
892 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
898 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
905 NextDoodad(SectionInfo * si, GeometryInfo * info)
909 di = uTypedCalloc(1, DoodadInfo);
914 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
921 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
930 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
934 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
937 if ((new->defs.merge == MergeReplace)
938 || (new->defs.merge == MergeOverride))
940 if (((old->defs.fileID == new->defs.fileID)
941 && (warningLevel > 0)) || (warningLevel > 9))
943 WARN1("Multiple doodads named \"%s\"\n",
944 XkbAtomText(info->dpy, old->name, XkbMessage));
945 ACTION("Using last definition\n");
947 ReplaceDoodad(old, new);
951 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
952 || (warningLevel > 9))
954 WARN1("Multiple doodads named \"%s\"\n",
955 XkbAtomText(info->dpy, old->name, XkbMessage));
956 ACTION("Using first definition\n");
961 if ((new = NextDoodad(si, info)) == NULL)
963 ReplaceDoodad(new, old);
965 new->defs.next = NULL;
970 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
975 if (uStrCaseCmp(name, "outline") == 0)
976 type = XkbOutlineDoodad;
977 else if (uStrCaseCmp(name, "solid") == 0)
978 type = XkbSolidDoodad;
979 else if (uStrCaseCmp(name, "text") == 0)
980 type = XkbTextDoodad;
981 else if (uStrCaseCmp(name, "indicator") == 0)
982 type = XkbIndicatorDoodad;
983 else if (uStrCaseCmp(name, "logo") == 0)
984 type = XkbLogoDoodad;
987 if ((si) && (si->dfltDoodads))
988 dflt = FindDoodadByType(si->dfltDoodads, type);
991 if ((!dflt) && (info->dfltDoodads))
992 dflt = FindDoodadByType(info->dfltDoodads, type);
995 dflt = NextDfltDoodad(si, info);
1005 /***====================================================================***/
1008 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1012 for (old = si->overlays; old != NULL;
1013 old = (OverlayInfo *) old->defs.next)
1015 if (old->name == new->name)
1020 if ((new->defs.merge == MergeReplace)
1021 || (new->defs.merge == MergeOverride))
1023 if (((old->defs.fileID == new->defs.fileID)
1024 && (warningLevel > 0)) || (warningLevel > 9))
1027 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1028 XkbAtomText(info->dpy, old->name, XkbMessage),
1029 XkbAtomText(info->dpy, si->name, XkbMessage));
1030 ACTION("Using last definition\n");
1032 ClearOverlayInfo(old);
1033 old->nKeys = new->nKeys;
1034 old->keys = new->keys;
1039 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1040 || (warningLevel > 9))
1042 WARN2("Multiple doodads named \"%s\" in section \"%s\"\n",
1043 XkbAtomText(info->dpy, old->name, XkbMessage),
1044 XkbAtomText(info->dpy, si->name, XkbMessage));
1045 ACTION("Using first definition\n");
1050 new = uTypedCalloc(1, OverlayInfo);
1053 if (warningLevel > 0)
1055 WSGO("Couldn't allocate a new OverlayInfo\n");
1057 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1058 XkbAtomText(info->dpy, old->name, XkbMessage),
1059 XkbAtomText(info->dpy, si->name, XkbMessage));
1066 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1067 (CommonInfo *) new);
1072 /***====================================================================***/
1074 static SectionInfo *
1075 NextSection(GeometryInfo * info)
1079 si = uTypedAlloc(SectionInfo);
1082 *si = info->dfltSection;
1083 si->defs.defined &= ~_GS_Default;
1084 si->defs.next = NULL;
1088 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1095 static SectionInfo *
1096 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1100 for (old = info->sections; old != NULL;
1101 old = (SectionInfo *) old->defs.next)
1103 if (new->name == old->name)
1110 AddSection(GeometryInfo * info, SectionInfo * new)
1114 old = FindMatchingSection(info, new);
1118 if ((new->defs.merge == MergeReplace)
1119 || (new->defs.merge == MergeOverride))
1121 SectionInfo *next = (SectionInfo *) old->defs.next;
1122 if (((old->defs.fileID == new->defs.fileID)
1123 && (warningLevel > 0)) || (warningLevel > 9))
1125 WARN1("Duplicate shape name \"%s\"\n",
1126 shText(info->dpy, old));
1127 ACTION("Using last definition\n");
1130 old->defs.next = &next->defs;
1133 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1134 || (warningLevel > 9))
1136 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
1137 ACTION("Using first definition\n");
1141 WARN("Don't know how to merge sections yet\n");
1145 if ((new = NextSection(info)) == NULL)
1148 new->defs.next = NULL;
1149 old->nRows = old->nDoodads = old->nOverlays = 0;
1151 old->doodads = NULL;
1152 old->overlays = NULL;
1156 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1164 /***====================================================================***/
1167 NextRow(SectionInfo * si)
1171 row = uTypedAlloc(RowInfo);
1175 row->defs.defined &= ~_GR_Default;
1176 row->defs.next = NULL;
1180 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1181 row->index = si->nRows++;
1187 AddRow(SectionInfo * si, RowInfo * new)
1192 if ((new = NextRow(si)) == NULL)
1195 new->defs.next = NULL;
1201 /***====================================================================***/
1204 NextKey(RowInfo * row)
1208 key = uTypedAlloc(KeyInfo);
1211 *key = row->dfltKey;
1212 key->defs.defined &= ~_GK_Default;
1213 key->defs.next = NULL;
1214 key->index = row->nKeys++;
1220 AddKey(RowInfo * row, KeyInfo * new)
1225 if ((new = NextKey(row)) == NULL)
1228 new->defs.next = NULL;
1230 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1234 /***====================================================================***/
1237 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1242 if (from->errorCount > 0)
1244 into->errorCount += from->errorCount;
1247 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1248 if (into->name == NULL)
1250 into->name = from->name;
1253 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1254 into->widthMM = from->widthMM;
1255 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1256 into->heightMM = from->heightMM;
1257 if ((into->font == None) || ((from->font != None) && clobber))
1258 into->font = from->font;
1259 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1260 into->fontSlant = from->fontSlant;
1261 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1262 into->fontWeight = from->fontWeight;
1263 if ((into->fontSetWidth == None)
1264 || ((from->fontSetWidth != None) && clobber))
1265 into->fontSetWidth = from->fontSetWidth;
1266 if ((into->fontVariant == None)
1267 || ((from->fontVariant != None) && clobber))
1268 into->fontVariant = from->fontVariant;
1269 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1270 into->fontSize = from->fontSize;
1271 if ((into->fontEncoding == None)
1272 || ((from->fontEncoding != None) && clobber))
1273 into->fontEncoding = from->fontEncoding;
1274 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1275 into->fontSpec = from->fontSpec;
1276 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1277 into->baseColor = from->baseColor;
1278 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1279 into->labelColor = from->labelColor;
1280 into->nextPriority = from->nextPriority;
1281 if (from->props != NULL)
1284 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1286 if (!AddProperty(into, pi))
1290 if (from->shapes != NULL)
1294 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1296 if (!AddShape(into, si))
1300 if (from->sections != NULL)
1304 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1306 if (!AddSection(into, si))
1310 if (from->doodads != NULL)
1314 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1316 if (!AddDoodad(NULL, into, di))
1320 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1325 typedef void (*FileHandler) (XkbFile * /* file */ ,
1326 XkbDescPtr /* xkb */ ,
1327 unsigned /* merge */ ,
1328 GeometryInfo * /* info */
1332 HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info,
1337 GeometryInfo included;
1341 if ((stmt->file == NULL) && (stmt->map == NULL))
1345 bzero(info, sizeof(GeometryInfo));
1347 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1349 InitGeometryInfo(&included, rtrn->id, newMerge);
1350 included.nextPriority = info->nextPriority;
1351 included.dfltCornerRadius = info->dfltCornerRadius;
1352 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1353 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1354 if (stmt->stmt != NULL)
1356 if (included.name != NULL)
1357 uFree(included.name);
1358 included.name = stmt->stmt;
1364 info->errorCount += 10;
1367 if ((stmt->next != NULL) && (included.errorCount < 1))
1371 GeometryInfo next_incl;
1373 for (next = stmt->next; next != NULL; next = next->next)
1375 if ((next->file == NULL) && (next->map == NULL))
1378 MergeIncludedGeometry(&included, info, next->merge);
1379 ClearGeometryInfo(info);
1381 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1383 InitGeometryInfo(&next_incl, rtrn->id, op);
1384 next_incl.nextPriority = included.nextPriority;
1385 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1386 DupSectionInfo(&next_incl.dfltSection,
1387 &included.dfltSection, &included);
1388 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1389 MergeIncludedGeometry(&included, &next_incl, op);
1390 ClearGeometryInfo(&next_incl);
1394 info->errorCount += 10;
1403 MergeIncludedGeometry(info, &included, newMerge);
1404 ClearGeometryInfo(&included);
1406 return (info->errorCount == 0);
1410 SetShapeField(ShapeInfo * si,
1412 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1416 if ((uStrCaseCmp(field, "radius") == 0)
1417 || (uStrCaseCmp(field, "corner") == 0)
1418 || (uStrCaseCmp(field, "cornerradius") == 0))
1420 if (arrayNdx != NULL)
1423 return ReportNotArray("key shape", field, shText(info->dpy, si));
1425 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1428 return ReportBadType("key shape", field,
1429 shText(info->dpy, si), "number");
1432 si->dfltCornerRadius = tmp.ival;
1434 info->dfltCornerRadius = tmp.ival;
1438 return ReportBadField("key shape", field, shText(info->dpy, si));
1442 SetShapeDoodadField(DoodadInfo * di,
1445 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1448 const char *typeName;
1451 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1452 if ((!uStrCaseCmp(field, "corner"))
1453 || (!uStrCaseCmp(field, "cornerradius")))
1455 if (arrayNdx != NULL)
1458 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1460 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1463 return ReportBadType(typeName, field, ddText(info->dpy, di),
1466 di->defs.defined |= _GD_Corner;
1467 di->corner = tmp.ival;
1470 else if (uStrCaseCmp(field, "angle") == 0)
1472 if (arrayNdx != NULL)
1475 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1477 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1480 return ReportBadType(typeName, field, ddText(info->dpy, di),
1483 di->defs.defined |= _GD_Angle;
1484 di->angle = tmp.ival;
1487 else if (uStrCaseCmp(field, "shape") == 0)
1489 if (arrayNdx != NULL)
1492 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1494 if (!ExprResolveString(value, &tmp, NULL, NULL))
1497 return ReportBadType(typeName, field, ddText(info->dpy, di),
1500 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1501 di->defs.defined |= _GD_Shape;
1504 return ReportBadField(typeName, field, ddText(info->dpy, di));
1507 #define FIELD_STRING 0
1508 #define FIELD_SHORT 1
1509 #define FIELD_USHORT 2
1512 SetTextDoodadField(DoodadInfo * di,
1515 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1520 char *typeName = "text doodad";
1525 unsigned short *uval;
1528 if (uStrCaseCmp(field, "angle") == 0)
1530 if (arrayNdx != NULL)
1533 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1535 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1538 return ReportBadType(typeName, field, ddText(info->dpy, di),
1541 di->defs.defined |= _GD_Angle;
1542 di->angle = tmp.ival;
1545 if (uStrCaseCmp(field, "width") == 0)
1547 type = FIELD_USHORT;
1548 pField.uval = &di->width;
1551 else if (uStrCaseCmp(field, "height") == 0)
1553 type = FIELD_USHORT;
1554 pField.uval = &di->height;
1557 else if (uStrCaseCmp(field, "text") == 0)
1559 type = FIELD_STRING;
1560 pField.str = &di->text;
1563 else if (uStrCaseCmp(field, "font") == 0)
1565 type = FIELD_STRING;
1566 pField.str = &di->font;
1569 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1570 (uStrCaseCmp(field, "slant") == 0))
1572 type = FIELD_STRING;
1573 pField.str = &di->fontSlant;
1574 def = _GD_FontSlant;
1576 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1577 (uStrCaseCmp(field, "weight") == 0))
1579 type = FIELD_STRING;
1580 pField.str = &di->fontWeight;
1581 def = _GD_FontWeight;
1583 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1584 (uStrCaseCmp(field, "setwidth") == 0))
1586 type = FIELD_STRING;
1587 pField.str = &di->fontSetWidth;
1588 def = _GD_FontSetWidth;
1590 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1591 (uStrCaseCmp(field, "variant") == 0))
1593 type = FIELD_STRING;
1594 pField.str = &di->fontVariant;
1595 def = _GD_FontVariant;
1597 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1598 (uStrCaseCmp(field, "encoding") == 0))
1600 type = FIELD_STRING;
1601 pField.str = &di->fontEncoding;
1602 def = _GD_FontEncoding;
1604 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1605 (uStrCaseCmp(field, "xfontname") == 0))
1607 type = FIELD_STRING;
1608 pField.str = &di->fontSpec;
1611 else if (uStrCaseCmp(field, "fontsize") == 0)
1613 type = FIELD_USHORT;
1614 pField.uval = &di->fontSize;
1619 return ReportBadField(typeName, field, ddText(info->dpy, di));
1621 if (arrayNdx != NULL)
1624 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1626 if (type == FIELD_STRING)
1628 if (!ExprResolveString(value, &tmp, NULL, NULL))
1631 return ReportBadType(typeName, field, ddText(info->dpy, di),
1634 di->defs.defined |= def;
1635 *pField.str = XkbInternAtom(NULL, tmp.str, False);
1639 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1642 return ReportBadType(typeName, field, ddText(info->dpy, di),
1645 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1649 ReportBadType(typeName, field, ddText(info->dpy, di),
1652 di->defs.defined |= def;
1653 if (type == FIELD_USHORT)
1654 *pField.uval = tmp.uval;
1656 *pField.ival = tmp.ival;
1662 SetIndicatorDoodadField(DoodadInfo * di,
1666 SectionInfo * si, GeometryInfo * info)
1670 if ((uStrCaseCmp(field, "oncolor") == 0)
1671 || (uStrCaseCmp(field, "offcolor") == 0)
1672 || (uStrCaseCmp(field, "shape") == 0))
1674 if (arrayNdx != NULL)
1677 return ReportNotArray("indicator doodad", field,
1678 ddText(info->dpy, di));
1680 if (!ExprResolveString(value, &tmp, NULL, NULL))
1683 return ReportBadType("indicator doodad", field,
1684 ddText(info->dpy, di), "string");
1686 if (uStrCaseCmp(field, "oncolor") == 0)
1688 di->defs.defined |= _GD_Color;
1689 di->color = XkbInternAtom(NULL, tmp.str, False);
1691 else if (uStrCaseCmp(field, "offcolor") == 0)
1693 di->defs.defined |= _GD_OffColor;
1694 di->offColor = XkbInternAtom(NULL, tmp.str, False);
1696 else if (uStrCaseCmp(field, "shape") == 0)
1698 di->defs.defined |= _GD_Shape;
1699 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1703 return ReportBadField("indicator doodad", field, ddText(info->dpy, di));
1707 SetLogoDoodadField(DoodadInfo * di,
1710 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1713 char *typeName = "logo doodad";
1715 if ((!uStrCaseCmp(field, "corner"))
1716 || (!uStrCaseCmp(field, "cornerradius")))
1718 if (arrayNdx != NULL)
1721 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1723 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1726 return ReportBadType(typeName, field, ddText(info->dpy, di),
1729 di->defs.defined |= _GD_Corner;
1730 di->corner = tmp.ival;
1733 else if (uStrCaseCmp(field, "angle") == 0)
1735 if (arrayNdx != NULL)
1738 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1740 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1743 return ReportBadType(typeName, field, ddText(info->dpy, di),
1746 di->defs.defined |= _GD_Angle;
1747 di->angle = tmp.ival;
1750 else if (uStrCaseCmp(field, "shape") == 0)
1752 if (arrayNdx != NULL)
1755 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1757 if (!ExprResolveString(value, &tmp, NULL, NULL))
1760 return ReportBadType(typeName, field, ddText(info->dpy, di),
1763 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1764 di->defs.defined |= _GD_Shape;
1767 else if ((!uStrCaseCmp(field, "logoname"))
1768 || (!uStrCaseCmp(field, "name")))
1770 if (arrayNdx != NULL)
1773 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1775 if (!ExprResolveString(value, &tmp, NULL, NULL))
1778 return ReportBadType(typeName, field, ddText(info->dpy, di),
1781 di->logoName = uStringDup(tmp.str);
1784 return ReportBadField(typeName, field, ddText(info->dpy, di));
1788 SetDoodadField(DoodadInfo * di,
1791 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1795 if (uStrCaseCmp(field, "priority") == 0)
1797 if (arrayNdx != NULL)
1800 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1802 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1805 return ReportBadType("doodad", field, ddText(info->dpy, di),
1808 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1811 ERROR2("Doodad priority %d out of range (must be 0..%d)\n",
1812 tmp.ival, XkbGeomMaxPriority);
1813 ACTION1("Priority for doodad %s not changed",
1814 ddText(info->dpy, di));
1817 di->defs.defined |= _GD_Priority;
1818 di->priority = tmp.ival;
1821 else if (uStrCaseCmp(field, "left") == 0)
1823 if (arrayNdx != NULL)
1826 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1828 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1831 return ReportBadType("doodad", field, ddText(info->dpy, di),
1834 di->defs.defined |= _GD_Left;
1835 di->left = tmp.ival;
1838 else if (uStrCaseCmp(field, "top") == 0)
1840 if (arrayNdx != NULL)
1843 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1845 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1848 return ReportBadType("doodad", field, ddText(info->dpy, di),
1851 di->defs.defined |= _GD_Top;
1855 else if (uStrCaseCmp(field, "color") == 0)
1857 if (arrayNdx != NULL)
1860 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1862 if (!ExprResolveString(value, &tmp, NULL, NULL))
1865 return ReportBadType("doodad", field, ddText(info->dpy, di),
1868 di->defs.defined |= _GD_Color;
1869 di->color = XkbInternAtom(NULL, tmp.str, False);
1874 case XkbOutlineDoodad:
1875 case XkbSolidDoodad:
1876 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1878 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1879 case XkbIndicatorDoodad:
1880 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1882 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1884 WSGO1("Unknown doodad type %d in SetDoodadField\n",
1885 (unsigned int) di->type);
1886 ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di));
1891 SetSectionField(SectionInfo * si,
1893 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1895 unsigned short *pField;
1901 if (uStrCaseCmp(field, "priority") == 0)
1903 if (arrayNdx != NULL)
1906 return ReportNotArray("keyboard section", field,
1907 scText(info->dpy, si));
1909 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1912 ReportBadType("keyboard section", field,
1913 scText(info->dpy, si), "integer");
1916 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1919 ERROR2("Section priority %d out of range (must be 0..%d)\n",
1920 tmp.ival, XkbGeomMaxPriority);
1921 ACTION1("Priority for section %s not changed",
1922 scText(info->dpy, si));
1925 si->priority = tmp.ival;
1926 si->defs.defined |= _GS_Priority;
1929 else if (uStrCaseCmp(field, "top") == 0)
1934 else if (uStrCaseCmp(field, "left") == 0)
1939 else if (uStrCaseCmp(field, "width") == 0)
1941 pField = &si->width;
1944 else if (uStrCaseCmp(field, "height") == 0)
1946 pField = &si->height;
1949 else if (uStrCaseCmp(field, "angle") == 0)
1951 pField = &si->angle;
1957 return ReportBadField("keyboard section", field,
1958 scText(info->dpy, si));
1960 if (arrayNdx != NULL)
1963 return ReportNotArray("keyboard section", field,
1964 scText(info->dpy, si));
1966 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1969 ReportBadType("keyboard section", field, scText(info->dpy, si),
1973 si->defs.defined |= def;
1979 SetRowField(RowInfo * row,
1981 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1985 if (uStrCaseCmp(field, "top") == 0)
1987 if (arrayNdx != NULL)
1990 return ReportNotArray("keyboard row", field,
1991 rowText(info->dpy, row));
1993 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1996 return ReportBadType("keyboard row", field,
1997 rowText(info->dpy, row), "number");
1999 row->defs.defined |= _GR_Top;
2000 row->top = tmp.uval;
2002 else if (uStrCaseCmp(field, "left") == 0)
2004 if (arrayNdx != NULL)
2007 return ReportNotArray("keyboard row", field,
2008 rowText(info->dpy, row));
2010 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2013 return ReportBadType("keyboard row", field,
2014 rowText(info->dpy, row), "number");
2016 row->defs.defined |= _GR_Left;
2017 row->left = tmp.uval;
2019 else if (uStrCaseCmp(field, "vertical") == 0)
2021 if (arrayNdx != NULL)
2024 return ReportNotArray("keyboard row", field,
2025 rowText(info->dpy, row));
2027 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
2030 return ReportBadType("keyboard row", field,
2031 rowText(info->dpy, row), "boolean");
2033 row->defs.defined |= _GR_Vertical;
2034 row->vertical = tmp.uval;
2039 return ReportBadField("keyboard row", field, rowText(info->dpy, row));
2045 SetKeyField(KeyInfo * key,
2047 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2051 if (uStrCaseCmp(field, "gap") == 0)
2053 if (arrayNdx != NULL)
2056 return ReportNotArray("key", field, keyText(key));
2058 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2061 return ReportBadType("key", field, keyText(key), "number");
2063 key->defs.defined |= _GK_Gap;
2064 key->gap = tmp.ival;
2066 else if (uStrCaseCmp(field, "shape") == 0)
2068 if (arrayNdx != NULL)
2071 return ReportNotArray("key", field, keyText(key));
2073 if (!ExprResolveString(value, &tmp, NULL, NULL))
2076 return ReportBadType("key", field, keyText(key), "string");
2078 key->defs.defined |= _GK_Shape;
2079 key->shape = XkbInternAtom(info->dpy, tmp.str, False);
2081 else if ((uStrCaseCmp(field, "color") == 0) ||
2082 (uStrCaseCmp(field, "keycolor") == 0))
2084 if (arrayNdx != NULL)
2087 return ReportNotArray("key", field, keyText(key));
2089 if (!ExprResolveString(value, &tmp, NULL, NULL))
2092 return ReportBadType("key", field, keyText(key), "string");
2094 key->defs.defined |= _GK_Color;
2095 key->color = XkbInternAtom(NULL, tmp.str, False);
2097 else if ((uStrCaseCmp(field, "name") == 0)
2098 || (uStrCaseCmp(field, "keyname") == 0))
2100 if (arrayNdx != NULL)
2103 return ReportNotArray("key", field, keyText(key));
2105 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2108 return ReportBadType("key", field, keyText(key), "key name");
2110 key->defs.defined |= _GK_Name;
2111 bzero(key->name, XkbKeyNameLength + 1);
2112 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2117 return ReportBadField("key", field, keyText(key));
2123 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2128 InitPropertyInfo(&pi, info);
2130 if (!ExprResolveString(value, &result, NULL, NULL))
2133 ERROR("Property values must be type string\n");
2134 ACTION1("Ignoring illegal definition of \"%s\" property\n", property);
2137 pi.value = result.str;
2138 return AddProperty(info, &pi);
2142 HandleGeometryVar(VarDef * stmt, XkbDescPtr xkb, GeometryInfo * info)
2144 ExprResult elem, field, tmp;
2149 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2150 return 0; /* internal error, already reported */
2151 if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0))
2152 return SetShapeField(NULL, field.str, ndx, stmt->value, info);
2153 if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
2154 return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2155 field.str, ndx, stmt->value, info);
2156 if (elem.str && (uStrCaseCmp(elem.str, "row") == 0))
2157 return SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2159 if (elem.str && (uStrCaseCmp(elem.str, "section") == 0))
2161 return SetSectionField(&info->dfltSection, field.str, ndx,
2164 if (elem.str && (uStrCaseCmp(elem.str, "property") == 0))
2169 ERROR1("The %s geometry property is not an array\n", field.str);
2170 ACTION("Ignoring illegal property definition\n");
2173 return SetGeometryProperty(info, field.str, stmt->value);
2176 && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL))
2178 return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2180 if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0))
2183 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2185 dflt = NextDfltDoodad(NULL, info);
2186 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2188 if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0))
2191 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2193 dflt = NextDfltDoodad(NULL, info);
2194 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2196 if (elem.str && (uStrCaseCmp(elem.str, "text") == 0))
2199 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2201 dflt = NextDfltDoodad(NULL, info);
2202 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2204 if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
2207 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2209 dflt = NextDfltDoodad(NULL, info);
2210 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2212 if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0))
2215 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2217 dflt = NextDfltDoodad(NULL, info);
2218 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2222 WARN("Assignment to field of unknown element\n");
2223 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2227 if ((uStrCaseCmp(field.str, "width") == 0) ||
2228 (uStrCaseCmp(field.str, "widthmm") == 0))
2233 return ReportNotArray("keyboard", field.str, "geometry");
2235 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2238 return ReportBadType("keyboard", field.str, "geometry", "number");
2242 WARN("Keyboard width must be positive\n");
2243 ACTION1("Ignoring illegal keyboard width %s\n",
2244 XkbGeomFPText(tmp.ival, XkbMessage));
2247 if (info->widthMM != 0)
2249 WARN("Keyboard width multiply defined\n");
2250 ACTION1("Using last definition (%s),",
2251 XkbGeomFPText(tmp.ival, XkbMessage));
2252 INFO1(" ignoring first (%s)\n",
2253 XkbGeomFPText(info->widthMM, XkbMessage));
2255 info->widthMM = tmp.ival;
2258 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2259 (uStrCaseCmp(field.str, "heightmm") == 0))
2264 return ReportNotArray("keyboard", field.str, "geometry");
2266 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2269 return ReportBadType("keyboard", field.str, "geometry", "number");
2273 WARN("Keyboard height must be positive\n");
2274 ACTION1("Ignoring illegal keyboard height %s\n",
2275 XkbGeomFPText(tmp.ival, XkbMessage));
2278 if (info->heightMM != 0)
2280 WARN("Keyboard height multiply defined\n");
2281 ACTION1("Using last definition (%s),",
2282 XkbGeomFPText(tmp.ival, XkbMessage));
2283 INFO1(" ignoring first (%s)\n",
2284 XkbGeomFPText(info->heightMM, XkbMessage));
2286 info->heightMM = tmp.ival;
2289 else if (uStrCaseCmp(field.str, "font") == 0)
2291 pField = &info->font;
2293 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2294 (uStrCaseCmp(field.str, "slant") == 0))
2296 pField = &info->fontSlant;
2298 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2299 (uStrCaseCmp(field.str, "weight") == 0))
2301 pField = &info->fontWeight;
2303 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2304 (uStrCaseCmp(field.str, "setwidth") == 0))
2306 pField = &info->fontWeight;
2308 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2309 (uStrCaseCmp(field.str, "encoding") == 0))
2311 pField = &info->fontEncoding;
2313 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2314 (uStrCaseCmp(field.str, "xfontname") == 0))
2316 pField = &info->fontSpec;
2318 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2323 return ReportNotArray("keyboard", field.str, "geometry");
2325 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2328 return ReportBadType("keyboard", field.str, "geometry", "number");
2330 if ((tmp.ival < 40) || (tmp.ival > 2550))
2333 ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival);
2334 ACTION("Ignoring font size in keyboard geometry\n");
2337 info->fontSize = tmp.ival;
2340 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2341 (uStrCaseCmp(field.str, "basecolor") == 0))
2346 return ReportNotArray("keyboard", field.str, "geometry");
2348 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2351 return ReportBadType("keyboard", field.str, "geometry", "string");
2353 info->baseColor = XkbInternAtom(NULL, tmp.str, False);
2356 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2361 return ReportNotArray("keyboard", field.str, "geometry");
2363 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2366 return ReportBadType("keyboard", field.str, "geometry", "string");
2368 info->labelColor = XkbInternAtom(NULL, tmp.str, False);
2373 return SetGeometryProperty(info, field.str, stmt->value);
2379 return ReportNotArray("keyboard", field.str, "geometry");
2381 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2384 return ReportBadType("keyboard", field.str, "geometry", "string");
2386 *pField = XkbInternAtom(NULL, tmp.str, False);
2390 /***====================================================================***/
2393 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2394 GeometryInfo * info)
2398 XkbOutlinePtr outline;
2401 if (def->nOutlines < 1)
2403 WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si));
2404 ACTION("Definition ignored\n");
2407 si->nOutlines = def->nOutlines;
2408 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
2411 ERROR1("Couldn't allocate outlines for \"%s\"\n",
2412 shText(info->dpy, si));
2413 ACTION("Definition ignored\n");
2417 for (nOut = 0, ol = def->outlines; ol != NULL;
2418 ol = (OutlineDef *) ol->common.next)
2420 if (ol->nPoints < 1)
2422 SetShapeField(si, XkbAtomGetString(NULL, ol->field), NULL,
2427 outline = &si->outlines[nOut++];
2428 outline->num_points = ol->nPoints;
2429 outline->corner_radius = si->dfltCornerRadius;
2430 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
2431 if (!outline->points)
2433 ERROR1("Can't allocate points for \"%s\"\n",
2434 shText(info->dpy, si));
2435 ACTION("Definition ignored\n");
2439 for (nPt = 0, pt = ol->points; pt != NULL;
2440 pt = (ExprDef *) pt->common.next)
2442 outline->points[nPt].x = pt->value.coord.x;
2443 outline->points[nPt].y = pt->value.coord.y;
2446 if (ol->field != None)
2448 char *str = XkbAtomText(NULL, ol->field, XkbMessage);
2449 if ((uStrCaseCmp(str, "approximation") == 0) ||
2450 (uStrCaseCmp(str, "approx") == 0))
2452 if (si->approx == NULL)
2453 si->approx = outline;
2456 WARN1("Multiple approximations for \"%s\"\n",
2457 shText(info->dpy, si));
2458 ACTION("Treating all but the first as normal outlines\n");
2461 else if (uStrCaseCmp(str, "primary") == 0)
2463 if (si->primary == NULL)
2464 si->primary = outline;
2467 WARN1("Multiple primary outlines for \"%s\"\n",
2468 shText(info->dpy, si));
2469 ACTION("Treating all but the first as normal outlines\n");
2474 WARN2("Unknown outline type %s for \"%s\"\n", str,
2475 shText(info->dpy, si));
2476 ACTION("Treated as a normal outline\n");
2480 if (nOut != si->nOutlines)
2482 WSGO2("Expected %d outlines, got %d\n",
2483 (unsigned int) si->nOutlines, nOut);
2484 si->nOutlines = nOut;
2490 HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge,
2491 GeometryInfo * info)
2495 if (def->merge != MergeDefault)
2498 bzero(&si, sizeof(ShapeInfo));
2499 si.defs.merge = merge;
2501 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2502 si.dfltCornerRadius = info->dfltCornerRadius;
2503 if (!HandleShapeBody(def, &si, merge, info))
2505 if (!AddShape(info, &si))
2510 /***====================================================================***/
2513 HandleDoodadDef(DoodadDef * def,
2514 unsigned merge, SectionInfo * si, GeometryInfo * info)
2516 ExprResult elem, field;
2521 if (def->common.stmtType == StmtIndicatorMapDef)
2523 def->common.stmtType = StmtDoodadDef;
2524 def->type = XkbIndicatorDoodad;
2526 InitDoodadInfo(&new, def->type, si, info);
2528 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2529 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2531 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2532 return 0; /* internal error, already reported */
2533 if (elem.str != NULL)
2535 WARN1("Assignment to field of unknown element in doodad %s\n",
2536 ddText(info->dpy, &new));
2537 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2539 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info))
2542 if (!AddDoodad(si, info, &new))
2544 ClearDoodadInfo(&new);
2548 /***====================================================================***/
2551 HandleOverlayDef(OverlayDef * def,
2552 unsigned merge, SectionInfo * si, GeometryInfo * info)
2554 OverlayKeyDef *keyDef;
2555 OverlayKeyInfo *key;
2558 if ((def->nKeys < 1) && (warningLevel > 3))
2560 WARN2("Overlay \"%s\" in section \"%s\" has no keys\n",
2561 XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy,
2563 ACTION("Overlay ignored\n");
2566 bzero(&ol, sizeof(OverlayInfo));
2568 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2569 for (keyDef = def->keys; keyDef;
2570 keyDef = (OverlayKeyDef *) keyDef->common.next)
2572 key = uTypedCalloc(1, OverlayKeyInfo);
2573 if ((!key) && warningLevel > 0)
2575 WSGO("Couldn't allocate OverlayKeyInfo\n");
2576 ACTION2("Overlay %s for section %s will be incomplete\n",
2577 XkbAtomText(info->dpy, ol.name, XkbMessage),
2578 scText(info->dpy, si));
2581 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2582 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2583 key->sectionRow = _GOK_UnknownRow;
2584 key->overlayRow = _GOK_UnknownRow;
2585 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2586 (CommonInfo *) key);
2589 if (!AddOverlay(si, info, &ol))
2591 ClearOverlayInfo(&ol);
2595 /***====================================================================***/
2598 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2604 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2606 if (expr->op == OpAssign)
2610 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2611 return False; /* internal error, already reported */
2612 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2615 (key, f.str, ndx, expr->value.binary.right, info))
2620 ERROR("Illegal element used in a key definition\n");
2621 ACTION2("Assignment to %s.%s ignored\n", elem.str, f.str);
2631 if (!SetKeyField(key, "gap", NULL, expr, info))
2635 if (!SetKeyField(key, "shape", NULL, expr, info))
2639 if (!SetKeyField(key, "name", NULL, expr, info))
2643 ERROR("Cannot determine field for unnamed expression\n");
2644 ACTION3("Ignoring key %d in row %d of section %s\n",
2645 row->nKeys + 1, row->section->nRows + 1,
2646 rowText(info->dpy, row));
2655 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2656 GeometryInfo * info)
2660 if ((def->nKeys < 1) && (warningLevel > 3))
2662 ERROR1("Row in section %s has no keys\n", rowText(info->dpy, row));
2663 ACTION("Section ignored\n");
2666 for (keyDef = def->keys; keyDef != NULL;
2667 keyDef = (KeyDef *) keyDef->common.next)
2669 if (keyDef->common.stmtType == StmtVarDef)
2671 VarDef *var = (VarDef *) keyDef;
2672 ExprResult elem, field;
2674 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2675 return 0; /* internal error, already reported */
2676 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2678 if (!SetRowField(row, field.str, ndx, var->value, info))
2681 else if (uStrCaseCmp(elem.str, "key") == 0)
2684 (&row->dfltKey, field.str, ndx, var->value, info))
2689 WARN("Assignment to field of unknown element in row\n");
2690 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2693 else if (keyDef->common.stmtType == StmtKeyDef)
2696 InitKeyInfo(&key, row, info);
2697 if (keyDef->name != NULL)
2699 int len = strlen(keyDef->name);
2700 if ((len < 1) || (len > XkbKeyNameLength))
2702 ERROR2("Illegal name %s for key in section %s\n",
2703 keyDef->name, rowText(info->dpy, row));
2704 ACTION("Section not compiled\n");
2707 bzero(key.name, XkbKeyNameLength + 1);
2708 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2709 key.defs.defined |= _GK_Name;
2711 else if (!HandleComplexKey(keyDef, &key, info))
2713 if (!AddKey(row, &key))
2718 WSGO1("Unexpected statement (type %d) in row body\n",
2719 keyDef->common.stmtType);
2727 HandleSectionBody(SectionDef * def,
2728 SectionInfo * si, unsigned merge, GeometryInfo * info)
2733 for (rowDef = def->rows; rowDef != NULL;
2734 rowDef = (RowDef *) rowDef->common.next)
2736 if (rowDef->common.stmtType == StmtVarDef)
2738 VarDef *var = (VarDef *) rowDef;
2739 ExprResult elem, field;
2741 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2742 return 0; /* internal error, already reported */
2743 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2745 if (!SetSectionField(si, field.str, ndx, var->value, info))
2748 else if (uStrCaseCmp(elem.str, "row") == 0)
2751 (&si->dfltRow, field.str, ndx, var->value, info))
2754 else if (uStrCaseCmp(elem.str, "key") == 0)
2756 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2761 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2763 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2768 WARN("Assignment to field of unknown element in section\n");
2769 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2772 else if (rowDef->common.stmtType == StmtRowDef)
2775 InitRowInfo(&row, si, info);
2776 if (!HandleRowBody(rowDef, &row, merge, info))
2778 if (!AddRow(si, &row))
2780 /* ClearRowInfo(&row,info);*/
2782 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2783 (rowDef->common.stmtType == StmtIndicatorMapDef))
2785 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2788 else if (rowDef->common.stmtType == StmtOverlayDef)
2790 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2795 WSGO1("Unexpected statement (type %d) in section body\n",
2796 rowDef->common.stmtType);
2800 if (si->nRows != def->nRows)
2802 WSGO2("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2803 (unsigned int) si->nRows);
2804 ACTION1("Definition of section %s might be incorrect\n",
2805 scText(info->dpy, si));
2811 HandleSectionDef(SectionDef * def,
2812 XkbDescPtr xkb, unsigned merge, GeometryInfo * info)
2817 if (def->merge != MergeDefault)
2819 InitSectionInfo(&si, info);
2820 si.defs.merge = merge;
2821 str = XkbAtomGetString(NULL, def->name);
2822 if ((str == NULL) || (strlen(str) < 1))
2824 ERROR("Section defined without a name\n");
2825 ACTION("Definition ignored\n");
2829 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2830 if (!HandleSectionBody(def, &si, merge, info))
2832 if (!AddSection(info, &si))
2837 /***====================================================================***/
2840 HandleGeometryFile(XkbFile * file,
2841 XkbDescPtr xkb, unsigned merge, GeometryInfo * info)
2846 if (merge == MergeDefault)
2847 merge = MergeAugment;
2848 info->name = uStringDup(file->name);
2853 switch (stmt->stmtType)
2856 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2857 HandleGeometryFile))
2860 case StmtKeyAliasDef:
2861 if (!HandleAliasDef((KeyAliasDef *) stmt,
2862 merge, info->fileID, &info->aliases))
2868 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2872 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2875 case StmtSectionDef:
2876 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2879 case StmtIndicatorMapDef:
2881 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2886 failWhat = "virtual modfier";
2889 failWhat = "symbol interpretation";
2890 case StmtGroupCompatDef:
2892 failWhat = "group compatibility map";
2893 case StmtKeycodeDef:
2895 failWhat = "key name";
2896 ERROR("Interpretation files may not include other types\n");
2897 ACTION1("Ignoring %s definition.\n", failWhat);
2901 WSGO1("Unexpected statement type %d in HandleGeometryFile\n",
2906 if (info->errorCount > 10)
2909 ERROR("Too many errors\n");
2911 ACTION1("Abandoning geometry file \"%s\"\n", file->topName);
2918 /***====================================================================***/
2921 CopyShapeDef(Display * dpy, XkbGeometryPtr geom, ShapeInfo * si)
2925 XkbOutlinePtr old_outline, outline;
2928 si->index = geom->num_shapes;
2929 name = XkbInternAtom(dpy, XkbAtomGetString(NULL, si->name), False);
2930 shape = XkbAddGeomShape(geom, name, si->nOutlines);
2933 WSGO("Couldn't allocate shape in geometry\n");
2934 ACTION1("Shape %s not compiled\n", shText(dpy, si));
2937 old_outline = si->outlines;
2938 for (i = 0; i < si->nOutlines; i++, old_outline++)
2940 outline = XkbAddGeomOutline(shape, old_outline->num_points);
2943 WSGO("Couldn't allocate outline in shape\n");
2944 ACTION1("Shape %s is incomplete\n", shText(dpy, si));
2947 n = old_outline->num_points;
2948 memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec));
2949 outline->num_points = old_outline->num_points;
2950 outline->corner_radius = old_outline->corner_radius;
2954 n = (si->approx - si->outlines);
2955 shape->approx = &shape->outlines[n];
2959 n = (si->primary - si->outlines);
2960 shape->primary = &shape->outlines[n];
2962 XkbComputeShapeBounds(shape);
2967 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2969 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2971 if (warningLevel < 9)
2973 ERROR1("No position defined for doodad %s\n",
2974 ddText(info->dpy, di));
2975 ACTION("Illegal doodad ignored\n");
2979 if ((di->defs.defined & _GD_Priority) == 0)
2981 /* calculate priority -- should be just above previous doodad/row */
2985 case XkbOutlineDoodad:
2986 case XkbSolidDoodad:
2987 if ((di->defs.defined & _GD_Shape) == 0)
2989 ERROR2("No shape defined for %s doodad %s\n",
2990 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2991 ddText(info->dpy, di));
2992 ACTION("Incomplete definition ignored\n");
2998 si = FindShape(info, di->shape,
3000 XkbOutlineDoodad ? "outline doodad" :
3001 "solid doodad"), ddText(info->dpy, di));
3003 di->shape = si->name;
3006 ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
3007 ACTION("Incomplete definition ignored\n");
3011 if ((di->defs.defined & _GD_Color) == 0)
3013 if (warningLevel > 5)
3015 WARN1("No color for doodad %s\n", ddText(info->dpy, di));
3016 ACTION("Using black\n");
3018 di->color = XkbInternAtom(NULL, "black", False);
3022 if ((di->defs.defined & _GD_Text) == 0)
3024 ERROR1("No text specified for text doodad %s\n",
3025 ddText(info->dpy, di));
3026 ACTION("Illegal doodad definition ignored\n");
3029 if ((di->defs.defined & _GD_Angle) == 0)
3031 if ((di->defs.defined & _GD_Color) == 0)
3033 if (warningLevel > 5)
3035 WARN1("No color specified for doodad %s\n",
3036 ddText(info->dpy, di));
3037 ACTION("Using black\n");
3039 di->color = XkbInternAtom(NULL, "black", False);
3041 if ((di->defs.defined & _GD_FontSpec) != 0)
3043 if ((di->defs.defined & _GD_FontParts) == 0)
3045 if (warningLevel < 9)
3048 ("Text doodad %s has full and partial font definition\n",
3049 ddText(info->dpy, di));
3050 ACTION("Full specification ignored\n");
3052 di->defs.defined &= ~_GD_FontSpec;
3053 di->fontSpec = None;
3055 if ((di->defs.defined & _GD_Font) == 0)
3057 if (warningLevel > 5)
3059 WARN1("No font specified for doodad %s\n",
3060 ddText(info->dpy, di));
3061 ACTION1("Using \"%s\"\n", DFLT_FONT);
3063 di->font = XkbInternAtom(NULL, DFLT_FONT, False);
3065 if ((di->defs.defined & _GD_FontSlant) == 0)
3067 if (warningLevel > 7)
3069 WARN1("No font slant for text doodad %s\n",
3070 ddText(info->dpy, di));
3071 ACTION1("Using \"%s\"\n", DFLT_SLANT);
3073 di->fontSlant = XkbInternAtom(NULL, DFLT_SLANT, False);
3075 if ((di->defs.defined & _GD_FontWeight) == 0)
3077 if (warningLevel > 7)
3079 WARN1("No font weight for text doodad %s\n",
3080 ddText(info->dpy, di));
3081 ACTION1("Using \"%s\"\n", DFLT_WEIGHT);
3083 di->fontWeight = XkbInternAtom(NULL, DFLT_WEIGHT, False);
3085 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3087 if (warningLevel > 9)
3089 WARN1("No font set width for text doodad %s\n",
3090 ddText(info->dpy, di));
3091 ACTION1("Using \"%s\"\n", DFLT_SET_WIDTH);
3093 di->fontSetWidth = XkbInternAtom(NULL, DFLT_SET_WIDTH, False);
3095 if ((di->defs.defined & _GD_FontVariant) == 0)
3097 if (warningLevel > 9)
3099 WARN1("No font variant for text doodad %s\n",
3100 ddText(info->dpy, di));
3101 ACTION1("Using \"%s\"\n", DFLT_VARIANT);
3103 di->fontVariant = XkbInternAtom(NULL, DFLT_VARIANT, False);
3105 if ((di->defs.defined & _GD_FontEncoding) == 0)
3107 if (warningLevel > 7)
3109 WARN1("No font encoding for doodad %s\n",
3110 ddText(info->dpy, di));
3111 ACTION1("Using \"%s\"\n", DFLT_ENCODING);
3113 di->fontEncoding = XkbInternAtom(NULL, DFLT_ENCODING, False);
3115 if ((di->defs.defined & _GD_FontSize) == 0)
3117 if (warningLevel > 7)
3119 WARN1("No font size for text doodad %s\n",
3120 ddText(info->dpy, di));
3121 ACTION1("Using %s point text\n",
3122 XkbGeomFPText(DFLT_SIZE, XkbMessage));
3124 di->fontSize = DFLT_SIZE;
3126 if ((di->defs.defined & _GD_Height) == 0)
3128 unsigned size, nLines;
3130 size = (di->fontSize * 120) / 100;
3131 size = (size * 254) / 720; /* convert to mm/10 */
3132 for (nLines = 1, tmp = XkbAtomGetString(NULL, di->text); *tmp;
3139 if (warningLevel > 5)
3141 WARN1("No height for text doodad %s\n",
3142 ddText(info->dpy, di));
3143 ACTION1("Using calculated height %s millimeters\n",
3144 XkbGeomFPText(size, XkbMessage));
3148 if ((di->defs.defined & _GD_Width) == 0)
3150 unsigned width, tmp;
3153 for (str = XkbAtomGetString(NULL, di->text); *str; str++)
3166 width *= (di->height * 2) / 3;
3167 if (warningLevel > 5)
3169 WARN1("No width for text doodad %s\n", ddText(info->dpy, di));
3170 ACTION1("Using calculated width %s millimeters\n",
3171 XkbGeomFPText(width, XkbMessage));
3176 case XkbIndicatorDoodad:
3177 if ((di->defs.defined & _GD_Shape) == 0)
3179 ERROR1("No shape defined for indicator doodad %s\n",
3180 ddText(info->dpy, di));
3181 ACTION("Incomplete definition ignored\n");
3187 si = FindShape(info, di->shape, "indicator doodad",
3188 ddText(info->dpy, di));
3190 di->shape = si->name;
3193 ERROR1("No legal shape for doodad %s\n",
3194 ddText(info->dpy, di));
3195 ACTION("Incomplete definition ignored\n");
3199 if ((di->defs.defined & _GD_Color) == 0)
3201 if (warningLevel > 5)
3203 WARN1("No \"on\" color for indicator doodad %s\n",
3204 ddText(info->dpy, di));
3205 ACTION("Using green\n");
3207 di->color = XkbInternAtom(NULL, "green", False);
3209 if ((di->defs.defined & _GD_OffColor) == 0)
3211 if (warningLevel > 5)
3213 WARN1("No \"off\" color for indicator doodad %s\n",
3214 ddText(info->dpy, di));
3215 ACTION("Using black\n");
3217 di->offColor = XkbInternAtom(NULL, "black", False);
3221 if (di->logoName == NULL)
3223 ERROR1("No logo name defined for logo doodad %s\n",
3224 ddText(info->dpy, di));
3225 ACTION("Incomplete definition ignored\n");
3228 if ((di->defs.defined & _GD_Shape) == 0)
3230 ERROR1("No shape defined for logo doodad %s\n",
3231 ddText(info->dpy, di));
3232 ACTION("Incomplete definition ignored\n");
3238 si = FindShape(info, di->shape, "logo doodad",
3239 ddText(info->dpy, di));
3241 di->shape = si->name;
3244 ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
3245 ACTION("Incomplete definition ignored\n");
3249 if ((di->defs.defined & _GD_Color) == 0)
3251 if (warningLevel > 5)
3253 WARN1("No color for doodad %s\n", ddText(info->dpy, di));
3254 ACTION("Using black\n");
3256 di->color = XkbInternAtom(NULL, "black", False);
3260 WSGO1("Uknown doodad type %d in VerifyDoodad\n",
3261 (unsigned int) di->type);
3267 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3270 FontFromParts(Atom fontTok,
3273 Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
3276 char *font, *weight, *slant, *setWidth, *variant, *encoding;
3279 font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT);
3281 (weightTok != None ? XkbAtomGetString(NULL, weightTok) : DFLT_WEIGHT);
3283 (slantTok != None ? XkbAtomGetString(NULL, slantTok) : DFLT_SLANT);
3286 None ? XkbAtomGetString(NULL, setWidthTok) : DFLT_SET_WIDTH);
3288 (varTok != None ? XkbAtomGetString(NULL, varTok) : DFLT_VARIANT);
3291 None ? XkbAtomGetString(NULL, encodingTok) : DFLT_ENCODING);
3295 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3296 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3297 rtrn = uCalloc(totalSize, 1);
3300 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3307 CopyDoodadDef(XkbGeometryPtr geom,
3308 XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info)
3311 XkbDoodadPtr doodad;
3316 if (!VerifyDoodadInfo(di, info))
3318 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, di->name), False);
3319 doodad = XkbAddGeomDoodad(geom, section, name);
3322 WSGO1("Couldn't allocate doodad in %s\n",
3323 (section ? "section" : "geometry"));
3324 ACTION1("Cannot copy doodad %s\n", ddText(info->dpy, di));
3327 doodad->any.type = di->type;
3328 doodad->any.priority = di->priority;
3329 doodad->any.top = di->top;
3330 doodad->any.left = di->left;
3333 case XkbOutlineDoodad:
3334 case XkbSolidDoodad:
3335 si = FindShape(info, di->shape, NULL, NULL);
3338 doodad->shape.angle = di->angle;
3340 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
3342 shape = &geom->shapes[si->index];
3343 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3344 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3347 doodad->text.angle = di->angle;
3348 doodad->text.width = di->width;
3349 doodad->text.height = di->height;
3350 if (di->fontSpec == None)
3351 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3354 di->fontVariant, di->fontSize,
3357 doodad->text.font = XkbAtomGetString(NULL, di->fontSpec);
3358 doodad->text.text = XkbAtomGetString(NULL, di->text);
3360 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
3362 XkbSetTextDoodadColor(geom, &doodad->text, color);
3364 case XkbIndicatorDoodad:
3365 si = FindShape(info, di->shape, NULL, NULL);
3368 shape = &geom->shapes[si->index];
3370 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
3372 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3373 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3375 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->offColor),
3377 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3380 si = FindShape(info, di->shape, NULL, NULL);
3383 doodad->logo.angle = di->angle;
3385 XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
3387 shape = &geom->shapes[si->index];
3388 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3389 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3390 doodad->logo.logo_name = di->logoName;
3391 di->logoName = NULL;
3397 /***====================================================================***/
3400 VerifyOverlayInfo(XkbGeometryPtr geom,
3401 XkbSectionPtr section,
3403 GeometryInfo * info, short rowMap[256], short rowSize[256])
3405 register OverlayKeyInfo *ki, *next;
3406 unsigned long oKey, uKey, sKey;
3411 /* find out which row each key is in */
3412 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3414 oKey = KeyNameToLong(ki->over);
3415 uKey = KeyNameToLong(ki->under);
3416 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3419 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3422 sKey = KeyNameToLong(key->name.name);
3425 if (warningLevel > 0)
3428 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3429 XkbKeyNameText(key->name.name,
3431 XkbAtomText(info->dpy, section->name,
3433 XkbAtomText(info->dpy, oi->name, XkbMessage));
3434 ACTION("Overlay definition ignored\n");
3438 else if (sKey == uKey)
3445 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3448 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3449 XkbKeyNameText(ki->under, XkbMessage),
3450 XkbAtomText(info->dpy, section->name, XkbMessage),
3451 XkbAtomText(info->dpy, oi->name, XkbMessage));
3452 ACTION("Definition ignored\n");
3455 /* now prune out keys that aren't in the section */
3456 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3458 next = (OverlayKeyInfo *) oi->keys->defs.next;
3463 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3465 next = (OverlayKeyInfo *) ki->defs.next;
3466 if (next->sectionRow == _GOK_UnknownRow)
3468 ki->defs.next = next->defs.next;
3471 next = (OverlayKeyInfo *) ki->defs.next;
3476 ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3477 XkbAtomText(info->dpy, oi->name, XkbMessage),
3478 XkbAtomText(info->dpy, section->name, XkbMessage));
3479 ACTION("Overlay definition ignored\n");
3482 /* now figure out how many rows are defined for the overlay */
3483 bzero(rowSize, sizeof(short) * 256);
3484 for (k = 0; k < 256; k++)
3489 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3491 if (rowMap[ki->sectionRow] == -1)
3492 rowMap[ki->sectionRow] = oi->nRows++;
3493 ki->overlayRow = rowMap[ki->sectionRow];
3494 rowSize[ki->overlayRow]++;
3500 CopyOverlayDef(XkbGeometryPtr geom,
3501 XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
3505 XkbOverlayRowPtr row;
3506 XkbOverlayKeyPtr key;
3508 short rowMap[256], rowSize[256];
3511 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3513 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, oi->name), False);
3514 ol = XkbAddGeomOverlay(section, name, oi->nRows);
3517 WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n",
3518 XkbAtomText(info->dpy, name, XkbMessage),
3519 XkbAtomText(info->dpy, section->name, XkbMessage));
3522 for (i = 0; i < oi->nRows; i++)
3525 for (tmp = 0, row_under = -1;
3526 (tmp < section->num_rows) && (row_under < 0); tmp++)
3528 if (rowMap[tmp] == i)
3531 if (!XkbAddGeomOverlayRow(ol, row_under, rowSize[i]))
3534 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3535 i, XkbAtomText(info->dpy, name, XkbMessage),
3536 XkbAtomText(info->dpy, section->name, XkbMessage));
3540 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3542 row = &ol->rows[ki->overlayRow];
3543 key = &row->keys[row->num_keys++];
3544 bzero(key, sizeof(XkbOverlayKeyRec));
3545 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3546 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3551 /***====================================================================***/
3554 CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
3556 XkbSectionPtr section;
3563 name = XkbInternAtom(NULL, XkbAtomGetString(NULL, si->name), False);
3565 XkbAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays);
3566 if (section == NULL)
3568 WSGO("Couldn't allocate section in geometry\n");
3569 ACTION1("Section %s not compiled\n", scText(info->dpy, si));
3572 section->top = si->top;
3573 section->left = si->left;
3574 section->width = si->width;
3575 section->height = si->height;
3576 section->angle = si->angle;
3577 section->priority = si->priority;
3578 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3580 row = XkbAddGeomRow(section, ri->nKeys);
3583 WSGO("Couldn't allocate row in section\n");
3584 ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
3588 row->left = ri->left;
3589 row->vertical = ri->vertical;
3590 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3593 if ((ki->defs.defined & _GK_Name) == 0)
3595 ERROR3("Key %d of row %d in section %s has no name\n",
3596 (int) ki->index, (int) ri->index,
3597 scText(info->dpy, si));
3598 ACTION1("Section %s ignored\n", scText(info->dpy, si));
3601 key = XkbAddGeomKey(row);
3604 WSGO("Couldn't allocate key in row\n");
3605 ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
3608 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3610 if (ki->shape == None)
3615 sinfo = FindShape(info, ki->shape, "key", keyText(ki));
3618 key->shape_ndx = sinfo->index;
3620 if (ki->color != None)
3622 XkbAddGeomColor(geom,
3623 XkbAtomGetString(NULL, ki->color),
3626 color = XkbAddGeomColor(geom, "white", geom->num_colors);
3627 XkbSetKeyColor(geom, key, color);
3630 if (si->doodads != NULL)
3633 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3635 CopyDoodadDef(geom, section, di, info);
3638 if (si->overlays != NULL)
3641 for (oi = si->overlays; oi != NULL;
3642 oi = (OverlayInfo *) oi->defs.next)
3644 CopyOverlayDef(geom, section, oi, info);
3647 if (XkbComputeSectionBounds(geom, section))
3649 /* 7/6/94 (ef) -- check for negative origin and translate */
3650 if ((si->defs.defined & _GS_Width) == 0)
3651 section->width = section->bounds.x2;
3652 if ((si->defs.defined & _GS_Height) == 0)
3653 section->height = section->bounds.y2;
3658 /***====================================================================***/
3661 CompileGeometry(XkbFile * file, XkbFileInfo * result, unsigned merge)
3667 InitGeometryInfo(&info, file->id, merge);
3668 info.dpy = xkb->dpy;
3669 HandleGeometryFile(file, xkb, merge, &info);
3671 if (info.errorCount == 0)
3673 XkbGeometryPtr geom;
3674 XkbGeometrySizesRec sizes;
3675 bzero(&sizes, sizeof(sizes));
3676 sizes.which = XkbGeomAllMask;
3677 sizes.num_properties = info.nProps;
3678 sizes.num_colors = 8;
3679 sizes.num_shapes = info.nShapes;
3680 sizes.num_sections = info.nSections;
3681 sizes.num_doodads = info.nDoodads;
3682 if (XkbAllocGeometry(xkb, &sizes) != Success)
3684 WSGO("Couldn't allocate GeometryRec\n");
3685 ACTION("Geometry not compiled\n");
3690 geom->width_mm = info.widthMM;
3691 geom->height_mm = info.heightMM;
3692 if (info.name != NULL)
3694 geom->name = XkbInternAtom(xkb->dpy, info.name, False);
3695 if (XkbAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3696 xkb->names->geometry = geom->name;
3698 if (info.fontSpec != None)
3700 uStringDup(XkbAtomGetString(NULL, info.fontSpec));
3702 geom->label_font = FontFromParts(info.font, info.fontWeight,
3708 XkbAddGeomColor(geom, "black", geom->num_colors);
3709 XkbAddGeomColor(geom, "white", geom->num_colors);
3711 if (info.baseColor == None)
3712 info.baseColor = XkbInternAtom(NULL, "white", False);
3713 if (info.labelColor == None)
3714 info.labelColor = XkbInternAtom(NULL, "black", False);
3716 XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.baseColor),
3719 XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.labelColor),
3725 for (pi = info.props; pi != NULL;
3726 pi = (PropertyInfo *) pi->defs.next)
3728 if (!XkbAddGeomProperty(geom, pi->name, pi->value))
3735 for (si = info.shapes; si != NULL;
3736 si = (ShapeInfo *) si->defs.next)
3738 if (!CopyShapeDef(xkb->dpy, geom, si))
3745 for (si = info.sections; si != NULL;
3746 si = (SectionInfo *) si->defs.next)
3748 if (!CopySectionDef(geom, si, &info))
3755 for (di = info.doodads; di != NULL;
3756 di = (DoodadInfo *) di->defs.next)
3758 if (!CopyDoodadDef(geom, NULL, di, &info))
3763 ApplyAliases(xkb, True, &info.aliases);
3764 ClearGeometryInfo(&info);