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;
182 #define oiText(d,o) ((o)?XkbAtomText((d),(o)->name,XkbMessage):"default")
185 #define _GS_Default (1<<0)
186 #define _GS_Name (1<<1)
187 #define _GS_Top (1<<2)
188 #define _GS_Left (1<<3)
189 #define _GS_Width (1<<4)
190 #define _GS_Height (1<<5)
191 #define _GS_Angle (1<<6)
192 #define _GS_Priority (1<<7)
193 typedef struct _SectionInfo
199 unsigned short width;
200 unsigned short height;
201 unsigned short angle;
202 unsigned short nRows;
203 unsigned short nDoodads;
204 unsigned short nOverlays;
205 unsigned char priority;
206 unsigned char nextDoodadPriority;
210 DoodadInfo *dfltDoodads;
211 OverlayInfo *overlays;
212 struct _GeometryInfo *geometry;
214 #define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default")
216 typedef struct _GeometryInfo
223 unsigned nextPriority;
230 SectionInfo *sections;
244 int dfltCornerRadius;
245 SectionInfo dfltSection;
246 DoodadInfo *dfltDoodads;
251 ddText(Display * dpy, DoodadInfo * di)
257 strcpy(buf, "default");
262 sprintf(buf, "%s in section %s",
263 XkbAtomText(dpy, di->name, XkbMessage), scText(dpy,
267 return XkbAtomText(dpy, di->name, XkbMessage);
270 /***====================================================================***/
273 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
275 pi->defs.defined = 0;
276 pi->defs.fileID = info->fileID;
277 pi->defs.merge = info->merge;
278 pi->name = pi->value = NULL;
283 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
288 if (info->props == pi)
293 for (tmp = pi; tmp != NULL; tmp = next)
299 tmp->name = tmp->value = NULL;
300 next = (PropertyInfo *) tmp->defs.next;
307 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
310 if (key != &row->dfltKey)
313 strcpy(key->name, "unknown");
314 key->defs.defined &= ~_GK_Default;
318 bzero(key, sizeof(KeyInfo));
319 strcpy(key->name, "default");
320 key->defs.defined = _GK_Default;
321 key->defs.fileID = info->fileID;
322 key->defs.merge = info->merge;
323 key->defs.next = NULL;
330 ClearKeyInfo(KeyInfo * key)
332 key->defs.defined &= ~_GK_Default;
333 strcpy(key->name, "default");
341 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
346 if (row->keys == key)
351 for (tmp = key; tmp != NULL; tmp = next)
354 next = (KeyInfo *) tmp->defs.next;
361 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
363 if (row != §ion->dfltRow)
365 *row = section->dfltRow;
366 row->defs.defined &= ~_GR_Default;
370 bzero(row, sizeof(RowInfo *));
371 row->defs.defined = _GR_Default;
372 row->defs.fileID = info->fileID;
373 row->defs.merge = info->merge;
374 row->defs.next = NULL;
375 row->section = section;
378 InitKeyInfo(&row->dfltKey, row, info);
384 ClearRowInfo(RowInfo * row, GeometryInfo * info)
386 row->defs.defined &= ~_GR_Default;
387 row->top = row->left = 0;
388 row->vertical = False;
391 FreeKeys(row->keys, row, info);
392 ClearKeyInfo(&row->dfltKey);
393 row->dfltKey.defs.defined |= _GK_Default;
398 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
403 if (row == section->rows)
406 section->rows = NULL;
408 for (tmp = row; tmp != NULL; tmp = next)
410 ClearRowInfo(tmp, info);
411 next = (RowInfo *) tmp->defs.next;
418 FindDoodadByType(DoodadInfo * di, unsigned type)
422 if (di->type == type)
424 di = (DoodadInfo *) di->defs.next;
430 FindDoodadByName(DoodadInfo * di, Atom name)
434 if (di->name == name)
436 di = (DoodadInfo *) di->defs.next;
442 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
448 if (si && si->dfltDoodads)
449 dflt = FindDoodadByType(si->dfltDoodads, type);
450 if ((dflt == NULL) && (info->dfltDoodads))
451 dflt = FindDoodadByType(info->dfltDoodads, type);
455 di->defs.next = NULL;
459 bzero(di, sizeof(DoodadInfo));
460 di->defs.fileID = info->fileID;
466 di->priority = si->nextDoodadPriority++;
467 #if XkbGeomMaxPriority < 255
468 if (si->nextDoodadPriority > XkbGeomMaxPriority)
469 si->nextDoodadPriority = XkbGeomMaxPriority;
474 di->priority = info->nextPriority++;
475 if (info->nextPriority > XkbGeomMaxPriority)
476 info->nextPriority = XkbGeomMaxPriority;
482 ClearDoodadInfo(DoodadInfo * di)
487 bzero(di, sizeof(DoodadInfo));
489 di->defs.defined = 0;
494 ClearOverlayInfo(OverlayInfo * ol)
498 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
505 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
512 if (si->doodads == di)
517 if (si->dfltDoodads == di)
518 si->dfltDoodads = NULL;
520 if (info->doodads == di)
522 info->doodads = NULL;
525 if (info->dfltDoodads == di)
526 info->dfltDoodads = NULL;
527 for (tmp = di; tmp != NULL; tmp = next)
529 next = (DoodadInfo *) tmp->defs.next;
530 ClearDoodadInfo(tmp);
537 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
539 if (si != &info->dfltSection)
541 *si = info->dfltSection;
542 si->defs.defined &= ~_GS_Default;
543 si->name = XkbInternAtom(info->dpy, "unknown", False);
544 si->priority = info->nextPriority++;
545 if (info->nextPriority > XkbGeomMaxPriority)
546 info->nextPriority = XkbGeomMaxPriority;
550 bzero(si, sizeof(SectionInfo));
551 si->defs.fileID = info->fileID;
552 si->defs.merge = info->merge;
553 si->defs.next = NULL;
555 si->name = XkbInternAtom(info->dpy, "default", False);
556 InitRowInfo(&si->dfltRow, si, info);
562 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
568 into->defs.fileID = defs.fileID;
569 into->defs.merge = defs.merge;
570 into->defs.next = NULL;
571 into->dfltRow.defs.fileID = defs.fileID;
572 into->dfltRow.defs.merge = defs.merge;
573 into->dfltRow.defs.next = NULL;
574 into->dfltRow.section = into;
575 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
576 into->dfltRow.dfltKey.defs.merge = defs.merge;
577 into->dfltRow.dfltKey.defs.next = NULL;
578 into->dfltRow.dfltKey.row = &into->dfltRow;
583 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
586 si->defs.defined &= ~_GS_Default;
587 si->name = XkbInternAtom(info->dpy, "default", False);
588 si->top = si->left = 0;
589 si->width = si->height = 0;
593 FreeRows(si->rows, si, info);
596 ClearRowInfo(&si->dfltRow, info);
599 FreeDoodads(si->doodads, si, info);
602 si->dfltRow.defs.defined = _GR_Default;
607 FreeSections(SectionInfo * si, GeometryInfo * info)
612 if (si == info->sections)
615 info->sections = NULL;
617 for (tmp = si; tmp != NULL; tmp = next)
619 ClearSectionInfo(tmp, info);
620 next = (SectionInfo *) tmp->defs.next;
627 FreeShapes(ShapeInfo * si, GeometryInfo * info)
632 if (si == info->shapes)
637 for (tmp = si; tmp != NULL; tmp = next)
642 for (i = 0; i < tmp->nOutlines; i++)
644 if (tmp->outlines[i].points != NULL)
646 uFree(tmp->outlines[i].points);
647 tmp->outlines[i].num_points = 0;
648 tmp->outlines[i].points = NULL;
651 uFree(tmp->outlines);
654 tmp->outlines = NULL;
655 tmp->primary = tmp->approx = NULL;
657 next = (ShapeInfo *) tmp->defs.next;
663 /***====================================================================***/
666 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
668 bzero(info, sizeof(GeometryInfo));
669 info->fileID = fileID;
671 InitSectionInfo(&info->dfltSection, info);
672 info->dfltSection.defs.defined = _GS_Default;
677 ClearGeometryInfo(GeometryInfo * info)
683 FreeProperties(info->props, info);
685 FreeShapes(info->shapes, info);
687 FreeSections(info->sections, info);
690 info->dfltCornerRadius = 0;
691 ClearSectionInfo(&info->dfltSection, info);
692 info->dfltSection.defs.defined = _GS_Default;
694 ClearAliases(&info->aliases);
698 /***====================================================================***/
700 static PropertyInfo *
701 NextProperty(GeometryInfo * info)
705 pi = uTypedAlloc(PropertyInfo);
708 bzero((char *) pi, sizeof(PropertyInfo));
709 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
716 static PropertyInfo *
717 FindProperty(GeometryInfo * info, char *name)
723 for (old = info->props; old != NULL;
724 old = (PropertyInfo *) old->defs.next)
726 if ((old->name) && (uStringEqual(name, old->name)))
733 AddProperty(GeometryInfo * info, PropertyInfo * new)
737 if ((!new) || (!new->value) || (!new->name))
739 old = FindProperty(info, new->name);
742 if ((new->defs.merge == MergeReplace)
743 || (new->defs.merge == MergeOverride))
745 if (((old->defs.fileID == new->defs.fileID)
746 && (warningLevel > 0)) || (warningLevel > 9))
748 WARN1("Multiple definitions for the \"%s\" property\n",
750 ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value,
755 old->value = uStringDup(new->value);
758 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
759 || (warningLevel > 9))
761 WARN1("Multiple definitions for \"%s\" property\n", new->name);
762 ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value,
768 if ((new = NextProperty(info)) == NULL)
770 new->defs.next = NULL;
771 new->name = uStringDup(old->name);
772 new->value = uStringDup(old->value);
776 /***====================================================================***/
779 NextShape(GeometryInfo * info)
783 si = uTypedAlloc(ShapeInfo);
786 bzero((char *) si, sizeof(ShapeInfo));
787 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
790 si->dfltCornerRadius = info->dfltCornerRadius;
796 FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
800 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
802 if (name == old->name)
808 WARN3("Unknown shape \"%s\" for %s %s\n",
809 XkbAtomText(info->dpy, name, XkbMessage), type, which);
812 ACTION1("Using default shape %s instead\n",
813 shText(info->dpy, old));
816 ACTION("No default shape; definition ignored\n");
823 AddShape(GeometryInfo * info, ShapeInfo * new)
827 old = FindShape(info, new->name, NULL, NULL);
830 if ((new->defs.merge == MergeReplace)
831 || (new->defs.merge == MergeOverride))
833 ShapeInfo *next = (ShapeInfo *) old->defs.next;
834 if (((old->defs.fileID == new->defs.fileID)
835 && (warningLevel > 0)) || (warningLevel > 9))
837 WARN1("Duplicate shape name \"%s\"\n",
838 shText(info->dpy, old));
839 ACTION("Using last definition\n");
842 old->defs.next = &next->defs;
845 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
846 || (warningLevel > 9))
848 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
849 ACTION("Using first definition\n");
854 if ((new = NextShape(info)) == NULL)
857 new->defs.next = NULL;
858 old->szOutlines = old->nOutlines = 0;
859 old->outlines = NULL;
865 /***====================================================================***/
868 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
872 next = into->defs.next;
873 ClearDoodadInfo(into);
875 into->defs.next = next;
876 next = from->defs.next;
877 ClearDoodadInfo(from);
878 from->defs.next = next;
883 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
887 di = uTypedCalloc(1, DoodadInfo);
893 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
899 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
906 NextDoodad(SectionInfo * si, GeometryInfo * info)
910 di = uTypedCalloc(1, DoodadInfo);
915 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
922 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
931 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
935 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
938 if ((new->defs.merge == MergeReplace)
939 || (new->defs.merge == MergeOverride))
941 if (((old->defs.fileID == new->defs.fileID)
942 && (warningLevel > 0)) || (warningLevel > 9))
944 WARN1("Multiple doodads named \"%s\"\n",
945 XkbAtomText(info->dpy, old->name, XkbMessage));
946 ACTION("Using last definition\n");
948 ReplaceDoodad(old, new);
952 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
953 || (warningLevel > 9))
955 WARN1("Multiple doodads named \"%s\"\n",
956 XkbAtomText(info->dpy, old->name, XkbMessage));
957 ACTION("Using first definition\n");
962 if ((new = NextDoodad(si, info)) == NULL)
964 ReplaceDoodad(new, old);
966 new->defs.next = NULL;
971 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
976 if (uStrCaseCmp(name, "outline") == 0)
977 type = XkbOutlineDoodad;
978 else if (uStrCaseCmp(name, "solid") == 0)
979 type = XkbSolidDoodad;
980 else if (uStrCaseCmp(name, "text") == 0)
981 type = XkbTextDoodad;
982 else if (uStrCaseCmp(name, "indicator") == 0)
983 type = XkbIndicatorDoodad;
984 else if (uStrCaseCmp(name, "logo") == 0)
985 type = XkbLogoDoodad;
988 if ((si) && (si->dfltDoodads))
989 dflt = FindDoodadByType(si->dfltDoodads, type);
992 if ((!dflt) && (info->dfltDoodads))
993 dflt = FindDoodadByType(info->dfltDoodads, type);
996 dflt = NextDfltDoodad(si, info);
1006 /***====================================================================***/
1009 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1013 for (old = si->overlays; old != NULL;
1014 old = (OverlayInfo *) old->defs.next)
1016 if (old->name == new->name)
1021 if ((new->defs.merge == MergeReplace)
1022 || (new->defs.merge == MergeOverride))
1024 if (((old->defs.fileID == new->defs.fileID)
1025 && (warningLevel > 0)) || (warningLevel > 9))
1028 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1029 XkbAtomText(info->dpy, old->name, XkbMessage),
1030 XkbAtomText(info->dpy, si->name, XkbMessage));
1031 ACTION("Using last definition\n");
1033 ClearOverlayInfo(old);
1034 old->nKeys = new->nKeys;
1035 old->keys = new->keys;
1040 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1041 || (warningLevel > 9))
1043 WARN2("Multiple doodads named \"%s\" in section \"%s\"\n",
1044 XkbAtomText(info->dpy, old->name, XkbMessage),
1045 XkbAtomText(info->dpy, si->name, XkbMessage));
1046 ACTION("Using first definition\n");
1051 new = uTypedCalloc(1, OverlayInfo);
1054 if (warningLevel > 0)
1056 WSGO("Couldn't allocate a new OverlayInfo\n");
1058 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1059 XkbAtomText(info->dpy, old->name, XkbMessage),
1060 XkbAtomText(info->dpy, si->name, XkbMessage));
1067 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1068 (CommonInfo *) new);
1073 /***====================================================================***/
1075 static SectionInfo *
1076 NextSection(GeometryInfo * info)
1080 si = uTypedAlloc(SectionInfo);
1083 *si = info->dfltSection;
1084 si->defs.defined &= ~_GS_Default;
1085 si->defs.next = NULL;
1089 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1096 static SectionInfo *
1097 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1101 for (old = info->sections; old != NULL;
1102 old = (SectionInfo *) old->defs.next)
1104 if (new->name == old->name)
1111 AddSection(GeometryInfo * info, SectionInfo * new)
1115 old = FindMatchingSection(info, new);
1119 if ((new->defs.merge == MergeReplace)
1120 || (new->defs.merge == MergeOverride))
1122 SectionInfo *next = (SectionInfo *) old->defs.next;
1123 if (((old->defs.fileID == new->defs.fileID)
1124 && (warningLevel > 0)) || (warningLevel > 9))
1126 WARN1("Duplicate shape name \"%s\"\n",
1127 shText(info->dpy, old));
1128 ACTION("Using last definition\n");
1131 old->defs.next = &next->defs;
1134 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1135 || (warningLevel > 9))
1137 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
1138 ACTION("Using first definition\n");
1142 WARN("Don't know how to merge sections yet\n");
1146 if ((new = NextSection(info)) == NULL)
1149 new->defs.next = NULL;
1150 old->nRows = old->nDoodads = old->nOverlays = 0;
1152 old->doodads = NULL;
1153 old->overlays = NULL;
1157 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1165 /***====================================================================***/
1168 NextRow(SectionInfo * si)
1172 row = uTypedAlloc(RowInfo);
1176 row->defs.defined &= ~_GR_Default;
1177 row->defs.next = NULL;
1181 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1182 row->index = si->nRows++;
1188 AddRow(SectionInfo * si, RowInfo * new)
1193 if ((new = NextRow(si)) == NULL)
1196 new->defs.next = NULL;
1202 /***====================================================================***/
1205 NextKey(RowInfo * row)
1209 key = uTypedAlloc(KeyInfo);
1212 *key = row->dfltKey;
1213 key->defs.defined &= ~_GK_Default;
1214 key->defs.next = NULL;
1215 key->index = row->nKeys++;
1221 AddKey(RowInfo * row, KeyInfo * new)
1226 if ((new = NextKey(row)) == NULL)
1229 new->defs.next = NULL;
1231 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1235 /***====================================================================***/
1238 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1243 if (from->errorCount > 0)
1245 into->errorCount += from->errorCount;
1248 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1249 if (into->name == NULL)
1251 into->name = from->name;
1254 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1255 into->widthMM = from->widthMM;
1256 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1257 into->heightMM = from->heightMM;
1258 if ((into->font == None) || ((from->font != None) && clobber))
1259 into->font = from->font;
1260 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1261 into->fontSlant = from->fontSlant;
1262 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1263 into->fontWeight = from->fontWeight;
1264 if ((into->fontSetWidth == None)
1265 || ((from->fontSetWidth != None) && clobber))
1266 into->fontSetWidth = from->fontSetWidth;
1267 if ((into->fontVariant == None)
1268 || ((from->fontVariant != None) && clobber))
1269 into->fontVariant = from->fontVariant;
1270 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1271 into->fontSize = from->fontSize;
1272 if ((into->fontEncoding == None)
1273 || ((from->fontEncoding != None) && clobber))
1274 into->fontEncoding = from->fontEncoding;
1275 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1276 into->fontSpec = from->fontSpec;
1277 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1278 into->baseColor = from->baseColor;
1279 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1280 into->labelColor = from->labelColor;
1281 into->nextPriority = from->nextPriority;
1282 if (from->props != NULL)
1285 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1287 if (!AddProperty(into, pi))
1291 if (from->shapes != NULL)
1295 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1297 if (!AddShape(into, si))
1301 if (from->sections != NULL)
1305 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1307 if (!AddSection(into, si))
1311 if (from->doodads != NULL)
1315 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1317 if (!AddDoodad(NULL, into, di))
1321 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1326 typedef void (*FileHandler) (XkbFile * /* file */ ,
1327 XkbDescPtr /* xkb */ ,
1328 unsigned /* merge */ ,
1329 GeometryInfo * /* info */
1333 HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info,
1338 GeometryInfo included;
1342 if ((stmt->file == NULL) && (stmt->map == NULL))
1346 bzero(info, sizeof(GeometryInfo));
1348 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1350 InitGeometryInfo(&included, rtrn->id, newMerge);
1351 included.nextPriority = info->nextPriority;
1352 included.dfltCornerRadius = info->dfltCornerRadius;
1353 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1354 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1355 if (stmt->stmt != NULL)
1357 if (included.name != NULL)
1358 uFree(included.name);
1359 included.name = stmt->stmt;
1365 info->errorCount += 10;
1368 if ((stmt->next != NULL) && (included.errorCount < 1))
1372 GeometryInfo next_incl;
1374 for (next = stmt->next; next != NULL; next = next->next)
1376 if ((next->file == NULL) && (next->map == NULL))
1379 MergeIncludedGeometry(&included, info, next->merge);
1380 ClearGeometryInfo(info);
1382 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1384 InitGeometryInfo(&next_incl, rtrn->id, op);
1385 next_incl.nextPriority = included.nextPriority;
1386 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1387 DupSectionInfo(&next_incl.dfltSection,
1388 &included.dfltSection, &included);
1389 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1390 MergeIncludedGeometry(&included, &next_incl, op);
1391 ClearGeometryInfo(&next_incl);
1395 info->errorCount += 10;
1404 MergeIncludedGeometry(info, &included, newMerge);
1405 ClearGeometryInfo(&included);
1407 return (info->errorCount == 0);
1411 SetShapeField(ShapeInfo * si,
1413 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1417 if ((uStrCaseCmp(field, "radius") == 0)
1418 || (uStrCaseCmp(field, "corner") == 0)
1419 || (uStrCaseCmp(field, "cornerradius") == 0))
1421 if (arrayNdx != NULL)
1424 return ReportNotArray("key shape", field, shText(info->dpy, si));
1426 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1429 return ReportBadType("key shape", field,
1430 shText(info->dpy, si), "number");
1433 si->dfltCornerRadius = tmp.ival;
1435 info->dfltCornerRadius = tmp.ival;
1439 return ReportBadField("key shape", field, shText(info->dpy, si));
1443 SetShapeDoodadField(DoodadInfo * di,
1446 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1449 const char *typeName;
1452 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1453 if ((!uStrCaseCmp(field, "corner"))
1454 || (!uStrCaseCmp(field, "cornerradius")))
1456 if (arrayNdx != NULL)
1459 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1461 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1464 return ReportBadType(typeName, field, ddText(info->dpy, di),
1467 di->defs.defined |= _GD_Corner;
1468 di->corner = tmp.ival;
1471 else if (uStrCaseCmp(field, "angle") == 0)
1473 if (arrayNdx != NULL)
1476 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1478 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1481 return ReportBadType(typeName, field, ddText(info->dpy, di),
1484 di->defs.defined |= _GD_Angle;
1485 di->angle = tmp.ival;
1488 else if (uStrCaseCmp(field, "shape") == 0)
1490 if (arrayNdx != NULL)
1493 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1495 if (!ExprResolveString(value, &tmp, NULL, NULL))
1498 return ReportBadType(typeName, field, ddText(info->dpy, di),
1501 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1502 di->defs.defined |= _GD_Shape;
1505 return ReportBadField(typeName, field, ddText(info->dpy, di));
1508 #define FIELD_STRING 0
1509 #define FIELD_SHORT 1
1510 #define FIELD_USHORT 2
1513 SetTextDoodadField(DoodadInfo * di,
1516 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1521 char *typeName = "text doodad";
1526 unsigned short *uval;
1529 if (uStrCaseCmp(field, "angle") == 0)
1531 if (arrayNdx != NULL)
1534 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1536 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1539 return ReportBadType(typeName, field, ddText(info->dpy, di),
1542 di->defs.defined |= _GD_Angle;
1543 di->angle = tmp.ival;
1546 if (uStrCaseCmp(field, "width") == 0)
1548 type = FIELD_USHORT;
1549 pField.uval = &di->width;
1552 else if (uStrCaseCmp(field, "height") == 0)
1554 type = FIELD_USHORT;
1555 pField.uval = &di->height;
1558 else if (uStrCaseCmp(field, "text") == 0)
1560 type = FIELD_STRING;
1561 pField.str = &di->text;
1564 else if (uStrCaseCmp(field, "font") == 0)
1566 type = FIELD_STRING;
1567 pField.str = &di->font;
1570 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1571 (uStrCaseCmp(field, "slant") == 0))
1573 type = FIELD_STRING;
1574 pField.str = &di->fontSlant;
1575 def = _GD_FontSlant;
1577 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1578 (uStrCaseCmp(field, "weight") == 0))
1580 type = FIELD_STRING;
1581 pField.str = &di->fontWeight;
1582 def = _GD_FontWeight;
1584 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1585 (uStrCaseCmp(field, "setwidth") == 0))
1587 type = FIELD_STRING;
1588 pField.str = &di->fontSetWidth;
1589 def = _GD_FontSetWidth;
1591 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1592 (uStrCaseCmp(field, "variant") == 0))
1594 type = FIELD_STRING;
1595 pField.str = &di->fontVariant;
1596 def = _GD_FontVariant;
1598 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1599 (uStrCaseCmp(field, "encoding") == 0))
1601 type = FIELD_STRING;
1602 pField.str = &di->fontEncoding;
1603 def = _GD_FontEncoding;
1605 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1606 (uStrCaseCmp(field, "xfontname") == 0))
1608 type = FIELD_STRING;
1609 pField.str = &di->fontSpec;
1612 else if (uStrCaseCmp(field, "fontsize") == 0)
1614 type = FIELD_USHORT;
1615 pField.uval = &di->fontSize;
1620 return ReportBadField(typeName, field, ddText(info->dpy, di));
1622 if (arrayNdx != NULL)
1625 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1627 if (type == FIELD_STRING)
1629 if (!ExprResolveString(value, &tmp, NULL, NULL))
1632 return ReportBadType(typeName, field, ddText(info->dpy, di),
1635 di->defs.defined |= def;
1636 *pField.str = XkbInternAtom(NULL, tmp.str, False);
1640 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1643 return ReportBadType(typeName, field, ddText(info->dpy, di),
1646 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1650 ReportBadType(typeName, field, ddText(info->dpy, di),
1653 di->defs.defined |= def;
1654 if (type == FIELD_USHORT)
1655 *pField.uval = tmp.uval;
1657 *pField.ival = tmp.ival;
1663 SetIndicatorDoodadField(DoodadInfo * di,
1667 SectionInfo * si, GeometryInfo * info)
1671 if ((uStrCaseCmp(field, "oncolor") == 0)
1672 || (uStrCaseCmp(field, "offcolor") == 0)
1673 || (uStrCaseCmp(field, "shape") == 0))
1675 if (arrayNdx != NULL)
1678 return ReportNotArray("indicator doodad", field,
1679 ddText(info->dpy, di));
1681 if (!ExprResolveString(value, &tmp, NULL, NULL))
1684 return ReportBadType("indicator doodad", field,
1685 ddText(info->dpy, di), "string");
1687 if (uStrCaseCmp(field, "oncolor") == 0)
1689 di->defs.defined |= _GD_Color;
1690 di->color = XkbInternAtom(NULL, tmp.str, False);
1692 else if (uStrCaseCmp(field, "offcolor") == 0)
1694 di->defs.defined |= _GD_OffColor;
1695 di->offColor = XkbInternAtom(NULL, tmp.str, False);
1697 else if (uStrCaseCmp(field, "shape") == 0)
1699 di->defs.defined |= _GD_Shape;
1700 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1704 return ReportBadField("indicator doodad", field, ddText(info->dpy, di));
1708 SetLogoDoodadField(DoodadInfo * di,
1711 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1714 char *typeName = "logo doodad";
1716 if ((!uStrCaseCmp(field, "corner"))
1717 || (!uStrCaseCmp(field, "cornerradius")))
1719 if (arrayNdx != NULL)
1722 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1724 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1727 return ReportBadType(typeName, field, ddText(info->dpy, di),
1730 di->defs.defined |= _GD_Corner;
1731 di->corner = tmp.ival;
1734 else if (uStrCaseCmp(field, "angle") == 0)
1736 if (arrayNdx != NULL)
1739 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1741 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1744 return ReportBadType(typeName, field, ddText(info->dpy, di),
1747 di->defs.defined |= _GD_Angle;
1748 di->angle = tmp.ival;
1751 else if (uStrCaseCmp(field, "shape") == 0)
1753 if (arrayNdx != NULL)
1756 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1758 if (!ExprResolveString(value, &tmp, NULL, NULL))
1761 return ReportBadType(typeName, field, ddText(info->dpy, di),
1764 di->shape = XkbInternAtom(info->dpy, tmp.str, False);
1765 di->defs.defined |= _GD_Shape;
1768 else if ((!uStrCaseCmp(field, "logoname"))
1769 || (!uStrCaseCmp(field, "name")))
1771 if (arrayNdx != NULL)
1774 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1776 if (!ExprResolveString(value, &tmp, NULL, NULL))
1779 return ReportBadType(typeName, field, ddText(info->dpy, di),
1782 di->logoName = uStringDup(tmp.str);
1785 return ReportBadField(typeName, field, ddText(info->dpy, di));
1789 SetDoodadField(DoodadInfo * di,
1792 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1796 if (uStrCaseCmp(field, "priority") == 0)
1798 if (arrayNdx != NULL)
1801 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1803 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1806 return ReportBadType("doodad", field, ddText(info->dpy, di),
1809 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1812 ERROR2("Doodad priority %d out of range (must be 0..%d)\n",
1813 tmp.ival, XkbGeomMaxPriority);
1814 ACTION1("Priority for doodad %s not changed",
1815 ddText(info->dpy, di));
1818 di->defs.defined |= _GD_Priority;
1819 di->priority = tmp.ival;
1822 else if (uStrCaseCmp(field, "left") == 0)
1824 if (arrayNdx != NULL)
1827 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1829 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1832 return ReportBadType("doodad", field, ddText(info->dpy, di),
1835 di->defs.defined |= _GD_Left;
1836 di->left = tmp.ival;
1839 else if (uStrCaseCmp(field, "top") == 0)
1841 if (arrayNdx != NULL)
1844 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1846 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1849 return ReportBadType("doodad", field, ddText(info->dpy, di),
1852 di->defs.defined |= _GD_Top;
1856 else if (uStrCaseCmp(field, "color") == 0)
1858 if (arrayNdx != NULL)
1861 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1863 if (!ExprResolveString(value, &tmp, NULL, NULL))
1866 return ReportBadType("doodad", field, ddText(info->dpy, di),
1869 di->defs.defined |= _GD_Color;
1870 di->color = XkbInternAtom(NULL, tmp.str, False);
1875 case XkbOutlineDoodad:
1876 case XkbSolidDoodad:
1877 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1879 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1880 case XkbIndicatorDoodad:
1881 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1883 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1885 WSGO1("Unknown doodad type %d in SetDoodadField\n",
1886 (unsigned int) di->type);
1887 ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di));
1892 SetSectionField(SectionInfo * si,
1894 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1896 unsigned short *pField;
1902 if (uStrCaseCmp(field, "priority") == 0)
1904 if (arrayNdx != NULL)
1907 return ReportNotArray("keyboard section", field,
1908 scText(info->dpy, si));
1910 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1913 ReportBadType("keyboard section", field,
1914 scText(info->dpy, si), "integer");
1917 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1920 ERROR2("Section priority %d out of range (must be 0..%d)\n",
1921 tmp.ival, XkbGeomMaxPriority);
1922 ACTION1("Priority for section %s not changed",
1923 scText(info->dpy, si));
1926 si->priority = tmp.ival;
1927 si->defs.defined |= _GS_Priority;
1930 else if (uStrCaseCmp(field, "top") == 0)
1935 else if (uStrCaseCmp(field, "left") == 0)
1940 else if (uStrCaseCmp(field, "width") == 0)
1942 pField = &si->width;
1945 else if (uStrCaseCmp(field, "height") == 0)
1947 pField = &si->height;
1950 else if (uStrCaseCmp(field, "angle") == 0)
1952 pField = &si->angle;
1958 return ReportBadField("keyboard section", field,
1959 scText(info->dpy, si));
1961 if (arrayNdx != NULL)
1964 return ReportNotArray("keyboard section", field,
1965 scText(info->dpy, si));
1967 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1970 ReportBadType("keyboard section", field, scText(info->dpy, si),
1974 si->defs.defined |= def;
1980 SetRowField(RowInfo * row,
1982 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1986 if (uStrCaseCmp(field, "top") == 0)
1988 if (arrayNdx != NULL)
1991 return ReportNotArray("keyboard row", field,
1992 rowText(info->dpy, row));
1994 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1997 return ReportBadType("keyboard row", field,
1998 rowText(info->dpy, row), "number");
2000 row->defs.defined |= _GR_Top;
2001 row->top = tmp.uval;
2003 else if (uStrCaseCmp(field, "left") == 0)
2005 if (arrayNdx != NULL)
2008 return ReportNotArray("keyboard row", field,
2009 rowText(info->dpy, row));
2011 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2014 return ReportBadType("keyboard row", field,
2015 rowText(info->dpy, row), "number");
2017 row->defs.defined |= _GR_Left;
2018 row->left = tmp.uval;
2020 else if (uStrCaseCmp(field, "vertical") == 0)
2022 if (arrayNdx != NULL)
2025 return ReportNotArray("keyboard row", field,
2026 rowText(info->dpy, row));
2028 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
2031 return ReportBadType("keyboard row", field,
2032 rowText(info->dpy, row), "boolean");
2034 row->defs.defined |= _GR_Vertical;
2035 row->vertical = tmp.uval;
2040 return ReportBadField("keyboard row", field, rowText(info->dpy, row));
2046 SetKeyField(KeyInfo * key,
2048 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2052 if (uStrCaseCmp(field, "gap") == 0)
2054 if (arrayNdx != NULL)
2057 return ReportNotArray("key", field, keyText(key));
2059 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2062 return ReportBadType("key", field, keyText(key), "number");
2064 key->defs.defined |= _GK_Gap;
2065 key->gap = tmp.ival;
2067 else if (uStrCaseCmp(field, "shape") == 0)
2069 if (arrayNdx != NULL)
2072 return ReportNotArray("key", field, keyText(key));
2074 if (!ExprResolveString(value, &tmp, NULL, NULL))
2077 return ReportBadType("key", field, keyText(key), "string");
2079 key->defs.defined |= _GK_Shape;
2080 key->shape = XkbInternAtom(info->dpy, tmp.str, False);
2082 else if ((uStrCaseCmp(field, "color") == 0) ||
2083 (uStrCaseCmp(field, "keycolor") == 0))
2085 if (arrayNdx != NULL)
2088 return ReportNotArray("key", field, keyText(key));
2090 if (!ExprResolveString(value, &tmp, NULL, NULL))
2093 return ReportBadType("key", field, keyText(key), "string");
2095 key->defs.defined |= _GK_Color;
2096 key->color = XkbInternAtom(NULL, tmp.str, False);
2098 else if ((uStrCaseCmp(field, "name") == 0)
2099 || (uStrCaseCmp(field, "keyname") == 0))
2101 if (arrayNdx != NULL)
2104 return ReportNotArray("key", field, keyText(key));
2106 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2109 return ReportBadType("key", field, keyText(key), "key name");
2111 key->defs.defined |= _GK_Name;
2112 bzero(key->name, XkbKeyNameLength + 1);
2113 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2118 return ReportBadField("key", field, keyText(key));
2124 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2129 InitPropertyInfo(&pi, info);
2131 if (!ExprResolveString(value, &result, NULL, NULL))
2134 ERROR("Property values must be type string\n");
2135 ACTION1("Ignoring illegal definition of \"%s\" property\n", property);
2138 pi.value = result.str;
2139 return AddProperty(info, &pi);
2143 HandleGeometryVar(VarDef * stmt, XkbDescPtr xkb, GeometryInfo * info)
2145 ExprResult elem, field, tmp;
2150 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2151 return 0; /* internal error, already reported */
2152 if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0))
2153 return SetShapeField(NULL, field.str, ndx, stmt->value, info);
2154 if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
2155 return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2156 field.str, ndx, stmt->value, info);
2157 if (elem.str && (uStrCaseCmp(elem.str, "row") == 0))
2158 return SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2160 if (elem.str && (uStrCaseCmp(elem.str, "section") == 0))
2162 return SetSectionField(&info->dfltSection, field.str, ndx,
2165 if (elem.str && (uStrCaseCmp(elem.str, "property") == 0))
2170 ERROR1("The %s geometry property is not an array\n", field.str);
2171 ACTION("Ignoring illegal property definition\n");
2174 return SetGeometryProperty(info, field.str, stmt->value);
2177 && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL))
2179 return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2181 if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0))
2184 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2186 dflt = NextDfltDoodad(NULL, info);
2187 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2189 if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0))
2192 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2194 dflt = NextDfltDoodad(NULL, info);
2195 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2197 if (elem.str && (uStrCaseCmp(elem.str, "text") == 0))
2200 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2202 dflt = NextDfltDoodad(NULL, info);
2203 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2205 if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
2208 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2210 dflt = NextDfltDoodad(NULL, info);
2211 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2213 if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0))
2216 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2218 dflt = NextDfltDoodad(NULL, info);
2219 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2223 WARN("Assignment to field of unknown element\n");
2224 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2228 if ((uStrCaseCmp(field.str, "width") == 0) ||
2229 (uStrCaseCmp(field.str, "widthmm") == 0))
2234 return ReportNotArray("keyboard", field.str, "geometry");
2236 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2239 return ReportBadType("keyboard", field.str, "geometry", "number");
2243 WARN("Keyboard width must be positive\n");
2244 ACTION1("Ignoring illegal keyboard width %s\n",
2245 XkbGeomFPText(tmp.ival, XkbMessage));
2248 if (info->widthMM != 0)
2250 WARN("Keyboard width multiply defined\n");
2251 ACTION1("Using last definition (%s),",
2252 XkbGeomFPText(tmp.ival, XkbMessage));
2253 INFO1(" ignoring first (%s)\n",
2254 XkbGeomFPText(info->widthMM, XkbMessage));
2256 info->widthMM = tmp.ival;
2259 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2260 (uStrCaseCmp(field.str, "heightmm") == 0))
2265 return ReportNotArray("keyboard", field.str, "geometry");
2267 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2270 return ReportBadType("keyboard", field.str, "geometry", "number");
2274 WARN("Keyboard height must be positive\n");
2275 ACTION1("Ignoring illegal keyboard height %s\n",
2276 XkbGeomFPText(tmp.ival, XkbMessage));
2279 if (info->heightMM != 0)
2281 WARN("Keyboard height multiply defined\n");
2282 ACTION1("Using last definition (%s),",
2283 XkbGeomFPText(tmp.ival, XkbMessage));
2284 INFO1(" ignoring first (%s)\n",
2285 XkbGeomFPText(info->heightMM, XkbMessage));
2287 info->heightMM = tmp.ival;
2290 else if (uStrCaseCmp(field.str, "font") == 0)
2292 pField = &info->font;
2294 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2295 (uStrCaseCmp(field.str, "slant") == 0))
2297 pField = &info->fontSlant;
2299 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2300 (uStrCaseCmp(field.str, "weight") == 0))
2302 pField = &info->fontWeight;
2304 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2305 (uStrCaseCmp(field.str, "setwidth") == 0))
2307 pField = &info->fontWeight;
2309 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2310 (uStrCaseCmp(field.str, "encoding") == 0))
2312 pField = &info->fontEncoding;
2314 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2315 (uStrCaseCmp(field.str, "xfontname") == 0))
2317 pField = &info->fontSpec;
2319 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2324 return ReportNotArray("keyboard", field.str, "geometry");
2326 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2329 return ReportBadType("keyboard", field.str, "geometry", "number");
2331 if ((tmp.ival < 40) || (tmp.ival > 2550))
2334 ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival);
2335 ACTION("Ignoring font size in keyboard geometry\n");
2338 info->fontSize = tmp.ival;
2341 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2342 (uStrCaseCmp(field.str, "basecolor") == 0))
2347 return ReportNotArray("keyboard", field.str, "geometry");
2349 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2352 return ReportBadType("keyboard", field.str, "geometry", "string");
2354 info->baseColor = XkbInternAtom(NULL, tmp.str, False);
2357 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2362 return ReportNotArray("keyboard", field.str, "geometry");
2364 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2367 return ReportBadType("keyboard", field.str, "geometry", "string");
2369 info->labelColor = XkbInternAtom(NULL, tmp.str, False);
2374 return SetGeometryProperty(info, field.str, stmt->value);
2380 return ReportNotArray("keyboard", field.str, "geometry");
2382 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2385 return ReportBadType("keyboard", field.str, "geometry", "string");
2387 *pField = XkbInternAtom(NULL, tmp.str, False);
2391 /***====================================================================***/
2394 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2395 GeometryInfo * info)
2399 XkbOutlinePtr outline;
2402 if (def->nOutlines < 1)
2404 WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si));
2405 ACTION("Definition ignored\n");
2408 si->nOutlines = def->nOutlines;
2409 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
2412 ERROR1("Couldn't allocate outlines for \"%s\"\n",
2413 shText(info->dpy, si));
2414 ACTION("Definition ignored\n");
2418 for (nOut = 0, ol = def->outlines; ol != NULL;
2419 ol = (OutlineDef *) ol->common.next)
2421 if (ol->nPoints < 1)
2423 SetShapeField(si, XkbAtomGetString(NULL, ol->field), NULL,
2428 outline = &si->outlines[nOut++];
2429 outline->num_points = ol->nPoints;
2430 outline->corner_radius = si->dfltCornerRadius;
2431 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
2432 if (!outline->points)
2434 ERROR1("Can't allocate points for \"%s\"\n",
2435 shText(info->dpy, si));
2436 ACTION("Definition ignored\n");
2440 for (nPt = 0, pt = ol->points; pt != NULL;
2441 pt = (ExprDef *) pt->common.next)
2443 outline->points[nPt].x = pt->value.coord.x;
2444 outline->points[nPt].y = pt->value.coord.y;
2447 if (ol->field != None)
2449 char *str = XkbAtomText(NULL, ol->field, XkbMessage);
2450 if ((uStrCaseCmp(str, "approximation") == 0) ||
2451 (uStrCaseCmp(str, "approx") == 0))
2453 if (si->approx == NULL)
2454 si->approx = outline;
2457 WARN1("Multiple approximations for \"%s\"\n",
2458 shText(info->dpy, si));
2459 ACTION("Treating all but the first as normal outlines\n");
2462 else if (uStrCaseCmp(str, "primary") == 0)
2464 if (si->primary == NULL)
2465 si->primary = outline;
2468 WARN1("Multiple primary outlines for \"%s\"\n",
2469 shText(info->dpy, si));
2470 ACTION("Treating all but the first as normal outlines\n");
2475 WARN2("Unknown outline type %s for \"%s\"\n", str,
2476 shText(info->dpy, si));
2477 ACTION("Treated as a normal outline\n");
2481 if (nOut != si->nOutlines)
2483 WSGO2("Expected %d outlines, got %d\n",
2484 (unsigned int) si->nOutlines, nOut);
2485 si->nOutlines = nOut;
2491 HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge,
2492 GeometryInfo * info)
2496 if (def->merge != MergeDefault)
2499 bzero(&si, sizeof(ShapeInfo));
2500 si.defs.merge = merge;
2502 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2503 si.dfltCornerRadius = info->dfltCornerRadius;
2504 if (!HandleShapeBody(def, &si, merge, info))
2506 if (!AddShape(info, &si))
2511 /***====================================================================***/
2514 HandleDoodadDef(DoodadDef * def,
2515 unsigned merge, SectionInfo * si, GeometryInfo * info)
2517 ExprResult elem, field;
2522 if (def->common.stmtType == StmtIndicatorMapDef)
2524 def->common.stmtType = StmtDoodadDef;
2525 def->type = XkbIndicatorDoodad;
2527 InitDoodadInfo(&new, def->type, si, info);
2529 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2530 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2532 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2533 return 0; /* internal error, already reported */
2534 if (elem.str != NULL)
2536 WARN1("Assignment to field of unknown element in doodad %s\n",
2537 ddText(info->dpy, &new));
2538 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2540 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info))
2543 if (!AddDoodad(si, info, &new))
2545 ClearDoodadInfo(&new);
2549 /***====================================================================***/
2552 HandleOverlayDef(OverlayDef * def,
2553 unsigned merge, SectionInfo * si, GeometryInfo * info)
2555 OverlayKeyDef *keyDef;
2556 OverlayKeyInfo *key;
2559 if ((def->nKeys < 1) && (warningLevel > 3))
2561 WARN2("Overlay \"%s\" in section \"%s\" has no keys\n",
2562 XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy,
2564 ACTION("Overlay ignored\n");
2567 bzero(&ol, sizeof(OverlayInfo));
2569 XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
2570 for (keyDef = def->keys; keyDef;
2571 keyDef = (OverlayKeyDef *) keyDef->common.next)
2573 key = uTypedCalloc(1, OverlayKeyInfo);
2574 if ((!key) && warningLevel > 0)
2576 WSGO("Couldn't allocate OverlayKeyInfo\n");
2577 ACTION2("Overlay %s for section %s will be incomplete\n",
2578 oiText(info->dpy, &ol), 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 si = FindShape(info, ki->shape, "key", keyText(ki));
3618 key->shape_ndx = si->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);