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/XKBgeomcommon.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;
70 #define shText(d, s) \
71 ((s) ? XkbcAtomText((s)->name) : "default shape")
73 #define _GD_Priority (1<<0)
74 #define _GD_Top (1<<1)
75 #define _GD_Left (1<<2)
76 #define _GD_Angle (1<<3)
77 #define _GD_Shape (1<<4)
78 #define _GD_FontVariant (1<<4) /* CHEATING */
79 #define _GD_Corner (1<<5)
80 #define _GD_Width (1<<5) /* CHEATING */
81 #define _GD_Color (1<<6)
82 #define _GD_OffColor (1<<7)
83 #define _GD_Height (1<<7) /* CHEATING */
84 #define _GD_Text (1<<8)
85 #define _GD_Font (1<<9)
86 #define _GD_FontSlant (1<<10)
87 #define _GD_FontWeight (1<<11)
88 #define _GD_FontSetWidth (1<<12)
89 #define _GD_FontSize (1<<13)
90 #define _GD_FontEncoding (1<<14)
91 #define _GD_FontSpec (1<<15)
94 #define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
96 typedef struct _DoodadInfo
101 unsigned char priority;
105 unsigned short corner;
106 unsigned short width;
107 unsigned short height;
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) ? XkbcAtomText((r)->section->name) : "default")
164 #define _GOK_UnknownRow -1
165 typedef struct _OverlayKeyInfo
170 char over[XkbKeyNameLength + 1];
171 char under[XkbKeyNameLength + 1];
174 typedef struct _OverlayInfo
178 unsigned short nRows;
179 unsigned short nKeys;
180 OverlayKeyInfo *keys;
182 #define oiText(d, o) \
183 ((o) ? XkbcAtomText((o)->name) : "default")
186 #define _GS_Default (1<<0)
187 #define _GS_Name (1<<1)
188 #define _GS_Top (1<<2)
189 #define _GS_Left (1<<3)
190 #define _GS_Width (1<<4)
191 #define _GS_Height (1<<5)
192 #define _GS_Angle (1<<6)
193 #define _GS_Priority (1<<7)
194 typedef struct _SectionInfo
200 unsigned short width;
201 unsigned short height;
202 unsigned short angle;
203 unsigned short nRows;
204 unsigned short nDoodads;
205 unsigned short nOverlays;
206 unsigned char priority;
207 unsigned char nextDoodadPriority;
211 DoodadInfo *dfltDoodads;
212 OverlayInfo *overlays;
213 struct _GeometryInfo *geometry;
215 #define scText(d, s) \
216 ((s) ? XkbcAtomText((s)->name) : "default")
218 typedef struct _GeometryInfo
225 unsigned nextPriority;
232 SectionInfo *sections;
246 int dfltCornerRadius;
247 SectionInfo dfltSection;
248 DoodadInfo *dfltDoodads;
253 ddText(Display * dpy, DoodadInfo * di)
259 strcpy(buf, "default");
264 sprintf(buf, "%s in section %s",
265 XkbcAtomText(di->name), scText(dpy, di->section));
268 return XkbcAtomText(di->name);
271 /***====================================================================***/
274 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
276 pi->defs.defined = 0;
277 pi->defs.fileID = info->fileID;
278 pi->defs.merge = info->merge;
279 pi->name = pi->value = NULL;
284 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
289 if (info->props == pi)
294 for (tmp = pi; tmp != NULL; tmp = next)
300 tmp->name = tmp->value = NULL;
301 next = (PropertyInfo *) tmp->defs.next;
308 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
311 if (key != &row->dfltKey)
314 strcpy(key->name, "unknown");
315 key->defs.defined &= ~_GK_Default;
319 bzero(key, sizeof(KeyInfo));
320 strcpy(key->name, "default");
321 key->defs.defined = _GK_Default;
322 key->defs.fileID = info->fileID;
323 key->defs.merge = info->merge;
324 key->defs.next = NULL;
331 ClearKeyInfo(KeyInfo * key)
333 key->defs.defined &= ~_GK_Default;
334 strcpy(key->name, "default");
342 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
347 if (row->keys == key)
352 for (tmp = key; tmp != NULL; tmp = next)
355 next = (KeyInfo *) tmp->defs.next;
362 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
364 if (row != §ion->dfltRow)
366 *row = section->dfltRow;
367 row->defs.defined &= ~_GR_Default;
371 bzero(row, sizeof(RowInfo *));
372 row->defs.defined = _GR_Default;
373 row->defs.fileID = info->fileID;
374 row->defs.merge = info->merge;
375 row->defs.next = NULL;
376 row->section = section;
379 InitKeyInfo(&row->dfltKey, row, info);
385 ClearRowInfo(RowInfo * row, GeometryInfo * info)
387 row->defs.defined &= ~_GR_Default;
388 row->top = row->left = 0;
389 row->vertical = False;
392 FreeKeys(row->keys, row, info);
393 ClearKeyInfo(&row->dfltKey);
394 row->dfltKey.defs.defined |= _GK_Default;
399 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
404 if (row == section->rows)
407 section->rows = NULL;
409 for (tmp = row; tmp != NULL; tmp = next)
411 ClearRowInfo(tmp, info);
412 next = (RowInfo *) tmp->defs.next;
419 FindDoodadByType(DoodadInfo * di, unsigned type)
423 if (di->type == type)
425 di = (DoodadInfo *) di->defs.next;
431 FindDoodadByName(DoodadInfo * di, Atom name)
435 if (di->name == name)
437 di = (DoodadInfo *) di->defs.next;
443 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
449 if (si && si->dfltDoodads)
450 dflt = FindDoodadByType(si->dfltDoodads, type);
451 if ((dflt == NULL) && (info->dfltDoodads))
452 dflt = FindDoodadByType(info->dfltDoodads, type);
456 di->defs.next = NULL;
460 bzero(di, sizeof(DoodadInfo));
461 di->defs.fileID = info->fileID;
467 di->priority = si->nextDoodadPriority++;
468 #if XkbGeomMaxPriority < 255
469 if (si->nextDoodadPriority > XkbGeomMaxPriority)
470 si->nextDoodadPriority = XkbGeomMaxPriority;
475 di->priority = info->nextPriority++;
476 if (info->nextPriority > XkbGeomMaxPriority)
477 info->nextPriority = XkbGeomMaxPriority;
483 ClearDoodadInfo(DoodadInfo * di)
488 bzero(di, sizeof(DoodadInfo));
490 di->defs.defined = 0;
495 ClearOverlayInfo(OverlayInfo * ol)
499 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
506 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
513 if (si->doodads == di)
518 if (si->dfltDoodads == di)
519 si->dfltDoodads = NULL;
521 if (info->doodads == di)
523 info->doodads = NULL;
526 if (info->dfltDoodads == di)
527 info->dfltDoodads = NULL;
528 for (tmp = di; tmp != NULL; tmp = next)
530 next = (DoodadInfo *) tmp->defs.next;
531 ClearDoodadInfo(tmp);
538 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
540 if (si != &info->dfltSection)
542 *si = info->dfltSection;
543 si->defs.defined &= ~_GS_Default;
544 si->name = XkbcInternAtom("unknown", False);
545 si->priority = info->nextPriority++;
546 if (info->nextPriority > XkbGeomMaxPriority)
547 info->nextPriority = XkbGeomMaxPriority;
551 bzero(si, sizeof(SectionInfo));
552 si->defs.fileID = info->fileID;
553 si->defs.merge = info->merge;
554 si->defs.next = NULL;
556 si->name = XkbcInternAtom("default", False);
557 InitRowInfo(&si->dfltRow, si, info);
563 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
569 into->defs.fileID = defs.fileID;
570 into->defs.merge = defs.merge;
571 into->defs.next = NULL;
572 into->dfltRow.defs.fileID = defs.fileID;
573 into->dfltRow.defs.merge = defs.merge;
574 into->dfltRow.defs.next = NULL;
575 into->dfltRow.section = into;
576 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
577 into->dfltRow.dfltKey.defs.merge = defs.merge;
578 into->dfltRow.dfltKey.defs.next = NULL;
579 into->dfltRow.dfltKey.row = &into->dfltRow;
584 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
587 si->defs.defined &= ~_GS_Default;
588 si->name = XkbcInternAtom("default", False);
589 si->top = si->left = 0;
590 si->width = si->height = 0;
594 FreeRows(si->rows, si, info);
597 ClearRowInfo(&si->dfltRow, info);
600 FreeDoodads(si->doodads, si, info);
603 si->dfltRow.defs.defined = _GR_Default;
608 FreeSections(SectionInfo * si, GeometryInfo * info)
613 if (si == info->sections)
616 info->sections = NULL;
618 for (tmp = si; tmp != NULL; tmp = next)
620 ClearSectionInfo(tmp, info);
621 next = (SectionInfo *) tmp->defs.next;
628 FreeShapes(ShapeInfo * si, GeometryInfo * info)
633 if (si == info->shapes)
638 for (tmp = si; tmp != NULL; tmp = next)
643 for (i = 0; i < tmp->nOutlines; i++)
645 if (tmp->outlines[i].points != NULL)
647 uFree(tmp->outlines[i].points);
648 tmp->outlines[i].num_points = 0;
649 tmp->outlines[i].points = NULL;
652 uFree(tmp->outlines);
655 tmp->outlines = NULL;
656 tmp->primary = tmp->approx = NULL;
658 next = (ShapeInfo *) tmp->defs.next;
664 /***====================================================================***/
667 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
669 bzero(info, sizeof(GeometryInfo));
670 info->fileID = fileID;
672 InitSectionInfo(&info->dfltSection, info);
673 info->dfltSection.defs.defined = _GS_Default;
678 ClearGeometryInfo(GeometryInfo * info)
684 FreeProperties(info->props, info);
686 FreeShapes(info->shapes, info);
688 FreeSections(info->sections, info);
691 info->dfltCornerRadius = 0;
692 ClearSectionInfo(&info->dfltSection, info);
693 info->dfltSection.defs.defined = _GS_Default;
695 ClearAliases(&info->aliases);
699 /***====================================================================***/
701 static PropertyInfo *
702 NextProperty(GeometryInfo * info)
706 pi = uTypedAlloc(PropertyInfo);
709 bzero((char *) pi, sizeof(PropertyInfo));
710 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
717 static PropertyInfo *
718 FindProperty(GeometryInfo * info, char *name)
724 for (old = info->props; old != NULL;
725 old = (PropertyInfo *) old->defs.next)
727 if ((old->name) && (uStringEqual(name, old->name)))
734 AddProperty(GeometryInfo * info, PropertyInfo * new)
738 if ((!new) || (!new->value) || (!new->name))
740 old = FindProperty(info, new->name);
743 if ((new->defs.merge == MergeReplace)
744 || (new->defs.merge == MergeOverride))
746 if (((old->defs.fileID == new->defs.fileID)
747 && (warningLevel > 0)) || (warningLevel > 9))
749 WARN1("Multiple definitions for the \"%s\" property\n",
751 ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value,
756 old->value = uStringDup(new->value);
759 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
760 || (warningLevel > 9))
762 WARN1("Multiple definitions for \"%s\" property\n", new->name);
763 ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value,
769 if ((new = NextProperty(info)) == NULL)
771 new->defs.next = NULL;
772 new->name = uStringDup(old->name);
773 new->value = uStringDup(old->value);
777 /***====================================================================***/
780 NextShape(GeometryInfo * info)
784 si = uTypedAlloc(ShapeInfo);
787 bzero((char *) si, sizeof(ShapeInfo));
788 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
791 si->dfltCornerRadius = info->dfltCornerRadius;
797 FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
801 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
803 if (name == old->name)
809 WARN3("Unknown shape \"%s\" for %s %s\n",
810 XkbcAtomText(name), type, which);
813 ACTION1("Using default shape %s instead\n",
814 shText(info->dpy, old));
817 ACTION("No default shape; definition ignored\n");
824 AddShape(GeometryInfo * info, ShapeInfo * new)
828 old = FindShape(info, new->name, NULL, NULL);
831 if ((new->defs.merge == MergeReplace)
832 || (new->defs.merge == MergeOverride))
834 ShapeInfo *next = (ShapeInfo *) old->defs.next;
835 if (((old->defs.fileID == new->defs.fileID)
836 && (warningLevel > 0)) || (warningLevel > 9))
838 WARN1("Duplicate shape name \"%s\"\n",
839 shText(info->dpy, old));
840 ACTION("Using last definition\n");
843 old->defs.next = &next->defs;
846 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
847 || (warningLevel > 9))
849 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
850 ACTION("Using first definition\n");
855 if ((new = NextShape(info)) == NULL)
858 new->defs.next = NULL;
859 old->szOutlines = old->nOutlines = 0;
860 old->outlines = NULL;
866 /***====================================================================***/
869 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
873 next = into->defs.next;
874 ClearDoodadInfo(into);
876 into->defs.next = next;
877 next = from->defs.next;
878 ClearDoodadInfo(from);
879 from->defs.next = next;
884 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
888 di = uTypedCalloc(1, DoodadInfo);
894 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
900 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
907 NextDoodad(SectionInfo * si, GeometryInfo * info)
911 di = uTypedCalloc(1, DoodadInfo);
916 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
923 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
932 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
936 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
939 if ((new->defs.merge == MergeReplace)
940 || (new->defs.merge == MergeOverride))
942 if (((old->defs.fileID == new->defs.fileID)
943 && (warningLevel > 0)) || (warningLevel > 9))
945 WARN1("Multiple doodads named \"%s\"\n",
946 XkbcAtomText(old->name));
947 ACTION("Using last definition\n");
949 ReplaceDoodad(old, new);
953 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
954 || (warningLevel > 9))
956 WARN1("Multiple doodads named \"%s\"\n",
957 XkbcAtomText(old->name));
958 ACTION("Using first definition\n");
963 if ((new = NextDoodad(si, info)) == NULL)
965 ReplaceDoodad(new, old);
967 new->defs.next = NULL;
972 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
977 if (uStrCaseCmp(name, "outline") == 0)
978 type = XkbOutlineDoodad;
979 else if (uStrCaseCmp(name, "solid") == 0)
980 type = XkbSolidDoodad;
981 else if (uStrCaseCmp(name, "text") == 0)
982 type = XkbTextDoodad;
983 else if (uStrCaseCmp(name, "indicator") == 0)
984 type = XkbIndicatorDoodad;
985 else if (uStrCaseCmp(name, "logo") == 0)
986 type = XkbLogoDoodad;
989 if ((si) && (si->dfltDoodads))
990 dflt = FindDoodadByType(si->dfltDoodads, type);
993 if ((!dflt) && (info->dfltDoodads))
994 dflt = FindDoodadByType(info->dfltDoodads, type);
997 dflt = NextDfltDoodad(si, info);
1007 /***====================================================================***/
1010 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1014 for (old = si->overlays; old != NULL;
1015 old = (OverlayInfo *) old->defs.next)
1017 if (old->name == new->name)
1022 if ((new->defs.merge == MergeReplace)
1023 || (new->defs.merge == MergeOverride))
1025 if (((old->defs.fileID == new->defs.fileID)
1026 && (warningLevel > 0)) || (warningLevel > 9))
1029 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1030 XkbcAtomText(old->name), XkbcAtomText(si->name));
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 XkbcAtomText(old->name), XkbcAtomText(si->name));
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 XkbcAtomText(old->name), XkbcAtomText(si->name));
1065 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1066 (CommonInfo *) new);
1071 /***====================================================================***/
1073 static SectionInfo *
1074 NextSection(GeometryInfo * info)
1078 si = uTypedAlloc(SectionInfo);
1081 *si = info->dfltSection;
1082 si->defs.defined &= ~_GS_Default;
1083 si->defs.next = NULL;
1087 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1094 static SectionInfo *
1095 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1099 for (old = info->sections; old != NULL;
1100 old = (SectionInfo *) old->defs.next)
1102 if (new->name == old->name)
1109 AddSection(GeometryInfo * info, SectionInfo * new)
1113 old = FindMatchingSection(info, new);
1117 if ((new->defs.merge == MergeReplace)
1118 || (new->defs.merge == MergeOverride))
1120 SectionInfo *next = (SectionInfo *) old->defs.next;
1121 if (((old->defs.fileID == new->defs.fileID)
1122 && (warningLevel > 0)) || (warningLevel > 9))
1124 WARN1("Duplicate shape name \"%s\"\n",
1125 shText(info->dpy, old));
1126 ACTION("Using last definition\n");
1129 old->defs.next = &next->defs;
1132 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1133 || (warningLevel > 9))
1135 WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
1136 ACTION("Using first definition\n");
1140 WARN("Don't know how to merge sections yet\n");
1144 if ((new = NextSection(info)) == NULL)
1147 new->defs.next = NULL;
1148 old->nRows = old->nDoodads = old->nOverlays = 0;
1150 old->doodads = NULL;
1151 old->overlays = NULL;
1155 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1163 /***====================================================================***/
1166 NextRow(SectionInfo * si)
1170 row = uTypedAlloc(RowInfo);
1174 row->defs.defined &= ~_GR_Default;
1175 row->defs.next = NULL;
1179 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1180 row->index = si->nRows++;
1186 AddRow(SectionInfo * si, RowInfo * new)
1191 if ((new = NextRow(si)) == NULL)
1194 new->defs.next = NULL;
1200 /***====================================================================***/
1203 NextKey(RowInfo * row)
1207 key = uTypedAlloc(KeyInfo);
1210 *key = row->dfltKey;
1211 key->defs.defined &= ~_GK_Default;
1212 key->defs.next = NULL;
1213 key->index = row->nKeys++;
1219 AddKey(RowInfo * row, KeyInfo * new)
1224 if ((new = NextKey(row)) == NULL)
1227 new->defs.next = NULL;
1229 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1233 /***====================================================================***/
1236 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1241 if (from->errorCount > 0)
1243 into->errorCount += from->errorCount;
1246 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1247 if (into->name == NULL)
1249 into->name = from->name;
1252 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1253 into->widthMM = from->widthMM;
1254 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1255 into->heightMM = from->heightMM;
1256 if ((into->font == None) || ((from->font != None) && clobber))
1257 into->font = from->font;
1258 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1259 into->fontSlant = from->fontSlant;
1260 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1261 into->fontWeight = from->fontWeight;
1262 if ((into->fontSetWidth == None)
1263 || ((from->fontSetWidth != None) && clobber))
1264 into->fontSetWidth = from->fontSetWidth;
1265 if ((into->fontVariant == None)
1266 || ((from->fontVariant != None) && clobber))
1267 into->fontVariant = from->fontVariant;
1268 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1269 into->fontSize = from->fontSize;
1270 if ((into->fontEncoding == None)
1271 || ((from->fontEncoding != None) && clobber))
1272 into->fontEncoding = from->fontEncoding;
1273 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1274 into->fontSpec = from->fontSpec;
1275 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1276 into->baseColor = from->baseColor;
1277 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1278 into->labelColor = from->labelColor;
1279 into->nextPriority = from->nextPriority;
1280 if (from->props != NULL)
1283 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1285 if (!AddProperty(into, pi))
1289 if (from->shapes != NULL)
1293 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1295 if (!AddShape(into, si))
1299 if (from->sections != NULL)
1303 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1305 if (!AddSection(into, si))
1309 if (from->doodads != NULL)
1313 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1315 if (!AddDoodad(NULL, into, di))
1319 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1324 typedef void (*FileHandler) (XkbFile * /* file */ ,
1325 XkbcDescPtr /* xkb */ ,
1326 unsigned /* merge */ ,
1327 GeometryInfo * /* info */
1331 HandleIncludeGeometry(IncludeStmt * stmt, XkbcDescPtr xkb, GeometryInfo * info,
1336 GeometryInfo included;
1340 if ((stmt->file == NULL) && (stmt->map == NULL))
1344 bzero(info, sizeof(GeometryInfo));
1346 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1348 InitGeometryInfo(&included, rtrn->id, newMerge);
1349 included.nextPriority = info->nextPriority;
1350 included.dfltCornerRadius = info->dfltCornerRadius;
1351 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1352 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1353 if (stmt->stmt != NULL)
1355 if (included.name != NULL)
1356 uFree(included.name);
1357 included.name = stmt->stmt;
1363 info->errorCount += 10;
1366 if ((stmt->next != NULL) && (included.errorCount < 1))
1370 GeometryInfo next_incl;
1372 for (next = stmt->next; next != NULL; next = next->next)
1374 if ((next->file == NULL) && (next->map == NULL))
1377 MergeIncludedGeometry(&included, info, next->merge);
1378 ClearGeometryInfo(info);
1380 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1382 InitGeometryInfo(&next_incl, rtrn->id, op);
1383 next_incl.nextPriority = included.nextPriority;
1384 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1385 DupSectionInfo(&next_incl.dfltSection,
1386 &included.dfltSection, &included);
1387 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1388 MergeIncludedGeometry(&included, &next_incl, op);
1389 ClearGeometryInfo(&next_incl);
1393 info->errorCount += 10;
1402 MergeIncludedGeometry(info, &included, newMerge);
1403 ClearGeometryInfo(&included);
1405 return (info->errorCount == 0);
1409 SetShapeField(ShapeInfo * si,
1411 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1415 if ((uStrCaseCmp(field, "radius") == 0)
1416 || (uStrCaseCmp(field, "corner") == 0)
1417 || (uStrCaseCmp(field, "cornerradius") == 0))
1419 if (arrayNdx != NULL)
1422 return ReportNotArray("key shape", field, shText(info->dpy, si));
1424 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1427 return ReportBadType("key shape", field,
1428 shText(info->dpy, si), "number");
1431 si->dfltCornerRadius = tmp.ival;
1433 info->dfltCornerRadius = tmp.ival;
1437 return ReportBadField("key shape", field, shText(info->dpy, si));
1441 SetShapeDoodadField(DoodadInfo * di,
1444 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1447 const char *typeName;
1450 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1451 if ((!uStrCaseCmp(field, "corner"))
1452 || (!uStrCaseCmp(field, "cornerradius")))
1454 if (arrayNdx != NULL)
1457 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1459 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1462 return ReportBadType(typeName, field, ddText(info->dpy, di),
1465 di->defs.defined |= _GD_Corner;
1466 di->corner = tmp.ival;
1469 else if (uStrCaseCmp(field, "angle") == 0)
1471 if (arrayNdx != NULL)
1474 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1476 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1479 return ReportBadType(typeName, field, ddText(info->dpy, di),
1482 di->defs.defined |= _GD_Angle;
1483 di->angle = tmp.ival;
1486 else if (uStrCaseCmp(field, "shape") == 0)
1488 if (arrayNdx != NULL)
1491 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1493 if (!ExprResolveString(value, &tmp, NULL, NULL))
1496 return ReportBadType(typeName, field, ddText(info->dpy, di),
1499 di->shape = XkbcInternAtom(tmp.str, False);
1500 di->defs.defined |= _GD_Shape;
1503 return ReportBadField(typeName, field, ddText(info->dpy, di));
1506 #define FIELD_STRING 0
1507 #define FIELD_SHORT 1
1508 #define FIELD_USHORT 2
1511 SetTextDoodadField(DoodadInfo * di,
1514 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1519 char *typeName = "text doodad";
1524 unsigned short *uval;
1527 if (uStrCaseCmp(field, "angle") == 0)
1529 if (arrayNdx != NULL)
1532 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1534 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1537 return ReportBadType(typeName, field, ddText(info->dpy, di),
1540 di->defs.defined |= _GD_Angle;
1541 di->angle = tmp.ival;
1544 if (uStrCaseCmp(field, "width") == 0)
1546 type = FIELD_USHORT;
1547 pField.uval = &di->width;
1550 else if (uStrCaseCmp(field, "height") == 0)
1552 type = FIELD_USHORT;
1553 pField.uval = &di->height;
1556 else if (uStrCaseCmp(field, "text") == 0)
1558 type = FIELD_STRING;
1559 pField.str = &di->text;
1562 else if (uStrCaseCmp(field, "font") == 0)
1564 type = FIELD_STRING;
1565 pField.str = &di->font;
1568 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1569 (uStrCaseCmp(field, "slant") == 0))
1571 type = FIELD_STRING;
1572 pField.str = &di->fontSlant;
1573 def = _GD_FontSlant;
1575 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1576 (uStrCaseCmp(field, "weight") == 0))
1578 type = FIELD_STRING;
1579 pField.str = &di->fontWeight;
1580 def = _GD_FontWeight;
1582 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1583 (uStrCaseCmp(field, "setwidth") == 0))
1585 type = FIELD_STRING;
1586 pField.str = &di->fontSetWidth;
1587 def = _GD_FontSetWidth;
1589 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1590 (uStrCaseCmp(field, "variant") == 0))
1592 type = FIELD_STRING;
1593 pField.str = &di->fontVariant;
1594 def = _GD_FontVariant;
1596 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1597 (uStrCaseCmp(field, "encoding") == 0))
1599 type = FIELD_STRING;
1600 pField.str = &di->fontEncoding;
1601 def = _GD_FontEncoding;
1603 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1604 (uStrCaseCmp(field, "xfontname") == 0))
1606 type = FIELD_STRING;
1607 pField.str = &di->fontSpec;
1610 else if (uStrCaseCmp(field, "fontsize") == 0)
1612 type = FIELD_USHORT;
1613 pField.uval = &di->fontSize;
1618 return ReportBadField(typeName, field, ddText(info->dpy, di));
1620 if (arrayNdx != NULL)
1623 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1625 if (type == FIELD_STRING)
1627 if (!ExprResolveString(value, &tmp, NULL, NULL))
1630 return ReportBadType(typeName, field, ddText(info->dpy, di),
1633 di->defs.defined |= def;
1634 *pField.str = XkbcInternAtom(tmp.str, False);
1638 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1641 return ReportBadType(typeName, field, ddText(info->dpy, di),
1644 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1648 ReportBadType(typeName, field, ddText(info->dpy, di),
1651 di->defs.defined |= def;
1652 if (type == FIELD_USHORT)
1653 *pField.uval = tmp.uval;
1655 *pField.ival = tmp.ival;
1661 SetIndicatorDoodadField(DoodadInfo * di,
1665 SectionInfo * si, GeometryInfo * info)
1669 if ((uStrCaseCmp(field, "oncolor") == 0)
1670 || (uStrCaseCmp(field, "offcolor") == 0)
1671 || (uStrCaseCmp(field, "shape") == 0))
1673 if (arrayNdx != NULL)
1676 return ReportNotArray("indicator doodad", field,
1677 ddText(info->dpy, di));
1679 if (!ExprResolveString(value, &tmp, NULL, NULL))
1682 return ReportBadType("indicator doodad", field,
1683 ddText(info->dpy, di), "string");
1685 if (uStrCaseCmp(field, "oncolor") == 0)
1687 di->defs.defined |= _GD_Color;
1688 di->color = XkbcInternAtom(tmp.str, False);
1690 else if (uStrCaseCmp(field, "offcolor") == 0)
1692 di->defs.defined |= _GD_OffColor;
1693 di->offColor = XkbcInternAtom(tmp.str, False);
1695 else if (uStrCaseCmp(field, "shape") == 0)
1697 di->defs.defined |= _GD_Shape;
1698 di->shape = XkbcInternAtom(tmp.str, False);
1702 return ReportBadField("indicator doodad", field, ddText(info->dpy, di));
1706 SetLogoDoodadField(DoodadInfo * di,
1709 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1712 char *typeName = "logo doodad";
1714 if ((!uStrCaseCmp(field, "corner"))
1715 || (!uStrCaseCmp(field, "cornerradius")))
1717 if (arrayNdx != NULL)
1720 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1722 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1725 return ReportBadType(typeName, field, ddText(info->dpy, di),
1728 di->defs.defined |= _GD_Corner;
1729 di->corner = tmp.ival;
1732 else if (uStrCaseCmp(field, "angle") == 0)
1734 if (arrayNdx != NULL)
1737 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1739 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1742 return ReportBadType(typeName, field, ddText(info->dpy, di),
1745 di->defs.defined |= _GD_Angle;
1746 di->angle = tmp.ival;
1749 else if (uStrCaseCmp(field, "shape") == 0)
1751 if (arrayNdx != NULL)
1754 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1756 if (!ExprResolveString(value, &tmp, NULL, NULL))
1759 return ReportBadType(typeName, field, ddText(info->dpy, di),
1762 di->shape = XkbcInternAtom(tmp.str, False);
1763 di->defs.defined |= _GD_Shape;
1766 else if ((!uStrCaseCmp(field, "logoname"))
1767 || (!uStrCaseCmp(field, "name")))
1769 if (arrayNdx != NULL)
1772 return ReportNotArray(typeName, field, ddText(info->dpy, di));
1774 if (!ExprResolveString(value, &tmp, NULL, NULL))
1777 return ReportBadType(typeName, field, ddText(info->dpy, di),
1780 di->logoName = uStringDup(tmp.str);
1783 return ReportBadField(typeName, field, ddText(info->dpy, di));
1787 SetDoodadField(DoodadInfo * di,
1790 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1794 if (uStrCaseCmp(field, "priority") == 0)
1796 if (arrayNdx != NULL)
1799 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1801 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1804 return ReportBadType("doodad", field, ddText(info->dpy, di),
1807 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1810 ERROR2("Doodad priority %d out of range (must be 0..%d)\n",
1811 tmp.ival, XkbGeomMaxPriority);
1812 ACTION1("Priority for doodad %s not changed",
1813 ddText(info->dpy, di));
1816 di->defs.defined |= _GD_Priority;
1817 di->priority = tmp.ival;
1820 else if (uStrCaseCmp(field, "left") == 0)
1822 if (arrayNdx != NULL)
1825 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1827 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1830 return ReportBadType("doodad", field, ddText(info->dpy, di),
1833 di->defs.defined |= _GD_Left;
1834 di->left = tmp.ival;
1837 else if (uStrCaseCmp(field, "top") == 0)
1839 if (arrayNdx != NULL)
1842 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1844 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1847 return ReportBadType("doodad", field, ddText(info->dpy, di),
1850 di->defs.defined |= _GD_Top;
1854 else if (uStrCaseCmp(field, "color") == 0)
1856 if (arrayNdx != NULL)
1859 return ReportNotArray("doodad", field, ddText(info->dpy, di));
1861 if (!ExprResolveString(value, &tmp, NULL, NULL))
1864 return ReportBadType("doodad", field, ddText(info->dpy, di),
1867 di->defs.defined |= _GD_Color;
1868 di->color = XkbcInternAtom(tmp.str, False);
1873 case XkbOutlineDoodad:
1874 case XkbSolidDoodad:
1875 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1877 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1878 case XkbIndicatorDoodad:
1879 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1881 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1883 WSGO1("Unknown doodad type %d in SetDoodadField\n",
1884 (unsigned int) di->type);
1885 ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di));
1890 SetSectionField(SectionInfo * si,
1892 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1894 unsigned short *pField;
1900 if (uStrCaseCmp(field, "priority") == 0)
1902 if (arrayNdx != NULL)
1905 return ReportNotArray("keyboard section", field,
1906 scText(info->dpy, si));
1908 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1911 ReportBadType("keyboard section", field,
1912 scText(info->dpy, si), "integer");
1915 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1918 ERROR2("Section priority %d out of range (must be 0..%d)\n",
1919 tmp.ival, XkbGeomMaxPriority);
1920 ACTION1("Priority for section %s not changed",
1921 scText(info->dpy, si));
1924 si->priority = tmp.ival;
1925 si->defs.defined |= _GS_Priority;
1928 else if (uStrCaseCmp(field, "top") == 0)
1933 else if (uStrCaseCmp(field, "left") == 0)
1938 else if (uStrCaseCmp(field, "width") == 0)
1940 pField = &si->width;
1943 else if (uStrCaseCmp(field, "height") == 0)
1945 pField = &si->height;
1948 else if (uStrCaseCmp(field, "angle") == 0)
1950 pField = &si->angle;
1956 return ReportBadField("keyboard section", field,
1957 scText(info->dpy, si));
1959 if (arrayNdx != NULL)
1962 return ReportNotArray("keyboard section", field,
1963 scText(info->dpy, si));
1965 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1968 ReportBadType("keyboard section", field, scText(info->dpy, si),
1972 si->defs.defined |= def;
1978 SetRowField(RowInfo * row,
1980 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1984 if (uStrCaseCmp(field, "top") == 0)
1986 if (arrayNdx != NULL)
1989 return ReportNotArray("keyboard row", field,
1990 rowText(info->dpy, row));
1992 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1995 return ReportBadType("keyboard row", field,
1996 rowText(info->dpy, row), "number");
1998 row->defs.defined |= _GR_Top;
1999 row->top = tmp.uval;
2001 else if (uStrCaseCmp(field, "left") == 0)
2003 if (arrayNdx != NULL)
2006 return ReportNotArray("keyboard row", field,
2007 rowText(info->dpy, row));
2009 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2012 return ReportBadType("keyboard row", field,
2013 rowText(info->dpy, row), "number");
2015 row->defs.defined |= _GR_Left;
2016 row->left = tmp.uval;
2018 else if (uStrCaseCmp(field, "vertical") == 0)
2020 if (arrayNdx != NULL)
2023 return ReportNotArray("keyboard row", field,
2024 rowText(info->dpy, row));
2026 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
2029 return ReportBadType("keyboard row", field,
2030 rowText(info->dpy, row), "boolean");
2032 row->defs.defined |= _GR_Vertical;
2033 row->vertical = tmp.uval;
2038 return ReportBadField("keyboard row", field, rowText(info->dpy, row));
2044 SetKeyField(KeyInfo * key,
2046 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2050 if (uStrCaseCmp(field, "gap") == 0)
2052 if (arrayNdx != NULL)
2055 return ReportNotArray("key", field, keyText(key));
2057 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2060 return ReportBadType("key", field, keyText(key), "number");
2062 key->defs.defined |= _GK_Gap;
2063 key->gap = tmp.ival;
2065 else if (uStrCaseCmp(field, "shape") == 0)
2067 if (arrayNdx != NULL)
2070 return ReportNotArray("key", field, keyText(key));
2072 if (!ExprResolveString(value, &tmp, NULL, NULL))
2075 return ReportBadType("key", field, keyText(key), "string");
2077 key->defs.defined |= _GK_Shape;
2078 key->shape = XkbcInternAtom(tmp.str, False);
2080 else if ((uStrCaseCmp(field, "color") == 0) ||
2081 (uStrCaseCmp(field, "keycolor") == 0))
2083 if (arrayNdx != NULL)
2086 return ReportNotArray("key", field, keyText(key));
2088 if (!ExprResolveString(value, &tmp, NULL, NULL))
2091 return ReportBadType("key", field, keyText(key), "string");
2093 key->defs.defined |= _GK_Color;
2094 key->color = XkbcInternAtom(tmp.str, False);
2096 else if ((uStrCaseCmp(field, "name") == 0)
2097 || (uStrCaseCmp(field, "keyname") == 0))
2099 if (arrayNdx != NULL)
2102 return ReportNotArray("key", field, keyText(key));
2104 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2107 return ReportBadType("key", field, keyText(key), "key name");
2109 key->defs.defined |= _GK_Name;
2110 bzero(key->name, XkbKeyNameLength + 1);
2111 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2116 return ReportBadField("key", field, keyText(key));
2122 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2127 InitPropertyInfo(&pi, info);
2129 if (!ExprResolveString(value, &result, NULL, NULL))
2132 ERROR("Property values must be type string\n");
2133 ACTION1("Ignoring illegal definition of \"%s\" property\n", property);
2136 pi.value = result.str;
2137 return AddProperty(info, &pi);
2141 HandleGeometryVar(VarDef * stmt, XkbcDescPtr xkb, GeometryInfo * info)
2143 ExprResult elem, field, tmp;
2148 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2149 return 0; /* internal error, already reported */
2150 if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0))
2151 return SetShapeField(NULL, field.str, ndx, stmt->value, info);
2152 if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
2153 return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2154 field.str, ndx, stmt->value, info);
2155 if (elem.str && (uStrCaseCmp(elem.str, "row") == 0))
2156 return SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2158 if (elem.str && (uStrCaseCmp(elem.str, "section") == 0))
2160 return SetSectionField(&info->dfltSection, field.str, ndx,
2163 if (elem.str && (uStrCaseCmp(elem.str, "property") == 0))
2168 ERROR1("The %s geometry property is not an array\n", field.str);
2169 ACTION("Ignoring illegal property definition\n");
2172 return SetGeometryProperty(info, field.str, stmt->value);
2175 && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL))
2177 return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2179 if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0))
2182 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2184 dflt = NextDfltDoodad(NULL, info);
2185 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2187 if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0))
2190 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2192 dflt = NextDfltDoodad(NULL, info);
2193 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2195 if (elem.str && (uStrCaseCmp(elem.str, "text") == 0))
2198 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2200 dflt = NextDfltDoodad(NULL, info);
2201 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2203 if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
2206 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2208 dflt = NextDfltDoodad(NULL, info);
2209 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2211 if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0))
2214 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2216 dflt = NextDfltDoodad(NULL, info);
2217 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2221 WARN("Assignment to field of unknown element\n");
2222 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2226 if ((uStrCaseCmp(field.str, "width") == 0) ||
2227 (uStrCaseCmp(field.str, "widthmm") == 0))
2232 return ReportNotArray("keyboard", field.str, "geometry");
2234 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2237 return ReportBadType("keyboard", field.str, "geometry", "number");
2241 WARN("Keyboard width must be positive\n");
2242 ACTION1("Ignoring illegal keyboard width %s\n",
2243 XkbcGeomFPText(tmp.ival));
2246 if (info->widthMM != 0)
2248 WARN("Keyboard width multiply defined\n");
2249 ACTION1("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2250 INFO1(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2252 info->widthMM = tmp.ival;
2255 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2256 (uStrCaseCmp(field.str, "heightmm") == 0))
2261 return ReportNotArray("keyboard", field.str, "geometry");
2263 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2266 return ReportBadType("keyboard", field.str, "geometry", "number");
2270 WARN("Keyboard height must be positive\n");
2271 ACTION1("Ignoring illegal keyboard height %s\n",
2272 XkbcGeomFPText(tmp.ival));
2275 if (info->heightMM != 0)
2277 WARN("Keyboard height multiply defined\n");
2278 ACTION1("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2279 INFO1(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2281 info->heightMM = tmp.ival;
2284 else if (uStrCaseCmp(field.str, "font") == 0)
2286 pField = &info->font;
2288 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2289 (uStrCaseCmp(field.str, "slant") == 0))
2291 pField = &info->fontSlant;
2293 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2294 (uStrCaseCmp(field.str, "weight") == 0))
2296 pField = &info->fontWeight;
2298 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2299 (uStrCaseCmp(field.str, "setwidth") == 0))
2301 pField = &info->fontWeight;
2303 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2304 (uStrCaseCmp(field.str, "encoding") == 0))
2306 pField = &info->fontEncoding;
2308 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2309 (uStrCaseCmp(field.str, "xfontname") == 0))
2311 pField = &info->fontSpec;
2313 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2318 return ReportNotArray("keyboard", field.str, "geometry");
2320 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2323 return ReportBadType("keyboard", field.str, "geometry", "number");
2325 if ((tmp.ival < 40) || (tmp.ival > 2550))
2328 ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival);
2329 ACTION("Ignoring font size in keyboard geometry\n");
2332 info->fontSize = tmp.ival;
2335 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2336 (uStrCaseCmp(field.str, "basecolor") == 0))
2341 return ReportNotArray("keyboard", field.str, "geometry");
2343 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2346 return ReportBadType("keyboard", field.str, "geometry", "string");
2348 info->baseColor = XkbcInternAtom(tmp.str, False);
2351 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2356 return ReportNotArray("keyboard", field.str, "geometry");
2358 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2361 return ReportBadType("keyboard", field.str, "geometry", "string");
2363 info->labelColor = XkbcInternAtom(tmp.str, False);
2368 return SetGeometryProperty(info, field.str, stmt->value);
2374 return ReportNotArray("keyboard", field.str, "geometry");
2376 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2379 return ReportBadType("keyboard", field.str, "geometry", "string");
2381 *pField = XkbcInternAtom(tmp.str, False);
2385 /***====================================================================***/
2388 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2389 GeometryInfo * info)
2393 XkbOutlinePtr outline;
2396 if (def->nOutlines < 1)
2398 WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si));
2399 ACTION("Definition ignored\n");
2402 si->nOutlines = def->nOutlines;
2403 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
2406 ERROR1("Couldn't allocate outlines for \"%s\"\n",
2407 shText(info->dpy, si));
2408 ACTION("Definition ignored\n");
2412 for (nOut = 0, ol = def->outlines; ol != NULL;
2413 ol = (OutlineDef *) ol->common.next)
2415 if (ol->nPoints < 1)
2417 SetShapeField(si, XkbcAtomGetString(ol->field), NULL,
2422 outline = &si->outlines[nOut++];
2423 outline->num_points = ol->nPoints;
2424 outline->corner_radius = si->dfltCornerRadius;
2425 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
2426 if (!outline->points)
2428 ERROR1("Can't allocate points for \"%s\"\n",
2429 shText(info->dpy, si));
2430 ACTION("Definition ignored\n");
2434 for (nPt = 0, pt = ol->points; pt != NULL;
2435 pt = (ExprDef *) pt->common.next)
2437 outline->points[nPt].x = pt->value.coord.x;
2438 outline->points[nPt].y = pt->value.coord.y;
2441 if (ol->field != None)
2443 char *str = XkbcAtomText(ol->field);
2444 if ((uStrCaseCmp(str, "approximation") == 0) ||
2445 (uStrCaseCmp(str, "approx") == 0))
2447 if (si->approx == NULL)
2448 si->approx = outline;
2451 WARN1("Multiple approximations for \"%s\"\n",
2452 shText(info->dpy, si));
2453 ACTION("Treating all but the first as normal outlines\n");
2456 else if (uStrCaseCmp(str, "primary") == 0)
2458 if (si->primary == NULL)
2459 si->primary = outline;
2462 WARN1("Multiple primary outlines for \"%s\"\n",
2463 shText(info->dpy, si));
2464 ACTION("Treating all but the first as normal outlines\n");
2469 WARN2("Unknown outline type %s for \"%s\"\n", str,
2470 shText(info->dpy, si));
2471 ACTION("Treated as a normal outline\n");
2475 if (nOut != si->nOutlines)
2477 WSGO2("Expected %d outlines, got %d\n",
2478 (unsigned int) si->nOutlines, nOut);
2479 si->nOutlines = nOut;
2485 HandleShapeDef(ShapeDef * def, XkbcDescPtr xkb, unsigned merge,
2486 GeometryInfo * info)
2490 if (def->merge != MergeDefault)
2493 bzero(&si, sizeof(ShapeInfo));
2494 si.defs.merge = merge;
2496 XkbcInternAtom(info->dpy, XkbcAtomGetString(def->name), False);
2497 si.dfltCornerRadius = info->dfltCornerRadius;
2498 if (!HandleShapeBody(def, &si, merge, info))
2500 if (!AddShape(info, &si))
2505 /***====================================================================***/
2508 HandleDoodadDef(DoodadDef * def,
2509 unsigned merge, SectionInfo * si, GeometryInfo * info)
2511 ExprResult elem, field;
2516 if (def->common.stmtType == StmtIndicatorMapDef)
2518 def->common.stmtType = StmtDoodadDef;
2519 def->type = XkbIndicatorDoodad;
2521 InitDoodadInfo(&new, def->type, si, info);
2523 XkbcInternAtom(info->dpy, XkbcAtomGetString(def->name), False);
2524 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2526 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2527 return 0; /* internal error, already reported */
2528 if (elem.str != NULL)
2530 WARN1("Assignment to field of unknown element in doodad %s\n",
2531 ddText(info->dpy, &new));
2532 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2534 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info))
2537 if (!AddDoodad(si, info, &new))
2539 ClearDoodadInfo(&new);
2543 /***====================================================================***/
2546 HandleOverlayDef(OverlayDef * def,
2547 unsigned merge, SectionInfo * si, GeometryInfo * info)
2549 OverlayKeyDef *keyDef;
2550 OverlayKeyInfo *key;
2553 if ((def->nKeys < 1) && (warningLevel > 3))
2555 WARN2("Overlay \"%s\" in section \"%s\" has no keys\n",
2556 XkbcAtomText(def->name), scText(info->dpy, si));
2557 ACTION("Overlay ignored\n");
2560 bzero(&ol, sizeof(OverlayInfo));
2562 XkbcInternAtom(info->dpy, XkbcAtomGetString(def->name), False);
2563 for (keyDef = def->keys; keyDef;
2564 keyDef = (OverlayKeyDef *) keyDef->common.next)
2566 key = uTypedCalloc(1, OverlayKeyInfo);
2567 if ((!key) && warningLevel > 0)
2569 WSGO("Couldn't allocate OverlayKeyInfo\n");
2570 ACTION2("Overlay %s for section %s will be incomplete\n",
2571 oiText(info->dpy, &ol), scText(info->dpy, si));
2574 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2575 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2576 key->sectionRow = _GOK_UnknownRow;
2577 key->overlayRow = _GOK_UnknownRow;
2578 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2579 (CommonInfo *) key);
2582 if (!AddOverlay(si, info, &ol))
2584 ClearOverlayInfo(&ol);
2588 /***====================================================================***/
2591 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2597 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2599 if (expr->op == OpAssign)
2603 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2604 return False; /* internal error, already reported */
2605 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2608 (key, f.str, ndx, expr->value.binary.right, info))
2613 ERROR("Illegal element used in a key definition\n");
2614 ACTION2("Assignment to %s.%s ignored\n", elem.str, f.str);
2624 if (!SetKeyField(key, "gap", NULL, expr, info))
2628 if (!SetKeyField(key, "shape", NULL, expr, info))
2632 if (!SetKeyField(key, "name", NULL, expr, info))
2636 ERROR("Cannot determine field for unnamed expression\n");
2637 ACTION3("Ignoring key %d in row %d of section %s\n",
2638 row->nKeys + 1, row->section->nRows + 1,
2639 rowText(info->dpy, row));
2648 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2649 GeometryInfo * info)
2653 if ((def->nKeys < 1) && (warningLevel > 3))
2655 ERROR1("Row in section %s has no keys\n", rowText(info->dpy, row));
2656 ACTION("Section ignored\n");
2659 for (keyDef = def->keys; keyDef != NULL;
2660 keyDef = (KeyDef *) keyDef->common.next)
2662 if (keyDef->common.stmtType == StmtVarDef)
2664 VarDef *var = (VarDef *) keyDef;
2665 ExprResult elem, field;
2667 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2668 return 0; /* internal error, already reported */
2669 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2671 if (!SetRowField(row, field.str, ndx, var->value, info))
2674 else if (uStrCaseCmp(elem.str, "key") == 0)
2677 (&row->dfltKey, field.str, ndx, var->value, info))
2682 WARN("Assignment to field of unknown element in row\n");
2683 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2686 else if (keyDef->common.stmtType == StmtKeyDef)
2689 InitKeyInfo(&key, row, info);
2690 if (keyDef->name != NULL)
2692 int len = strlen(keyDef->name);
2693 if ((len < 1) || (len > XkbKeyNameLength))
2695 ERROR2("Illegal name %s for key in section %s\n",
2696 keyDef->name, rowText(info->dpy, row));
2697 ACTION("Section not compiled\n");
2700 bzero(key.name, XkbKeyNameLength + 1);
2701 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2702 key.defs.defined |= _GK_Name;
2704 else if (!HandleComplexKey(keyDef, &key, info))
2706 if (!AddKey(row, &key))
2711 WSGO1("Unexpected statement (type %d) in row body\n",
2712 keyDef->common.stmtType);
2720 HandleSectionBody(SectionDef * def,
2721 SectionInfo * si, unsigned merge, GeometryInfo * info)
2726 for (rowDef = def->rows; rowDef != NULL;
2727 rowDef = (RowDef *) rowDef->common.next)
2729 if (rowDef->common.stmtType == StmtVarDef)
2731 VarDef *var = (VarDef *) rowDef;
2732 ExprResult elem, field;
2734 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2735 return 0; /* internal error, already reported */
2736 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2738 if (!SetSectionField(si, field.str, ndx, var->value, info))
2741 else if (uStrCaseCmp(elem.str, "row") == 0)
2744 (&si->dfltRow, field.str, ndx, var->value, info))
2747 else if (uStrCaseCmp(elem.str, "key") == 0)
2749 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2754 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2756 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2761 WARN("Assignment to field of unknown element in section\n");
2762 ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
2765 else if (rowDef->common.stmtType == StmtRowDef)
2768 InitRowInfo(&row, si, info);
2769 if (!HandleRowBody(rowDef, &row, merge, info))
2771 if (!AddRow(si, &row))
2773 /* ClearRowInfo(&row,info);*/
2775 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2776 (rowDef->common.stmtType == StmtIndicatorMapDef))
2778 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2781 else if (rowDef->common.stmtType == StmtOverlayDef)
2783 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2788 WSGO1("Unexpected statement (type %d) in section body\n",
2789 rowDef->common.stmtType);
2793 if (si->nRows != def->nRows)
2795 WSGO2("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2796 (unsigned int) si->nRows);
2797 ACTION1("Definition of section %s might be incorrect\n",
2798 scText(info->dpy, si));
2804 HandleSectionDef(SectionDef * def,
2805 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2810 if (def->merge != MergeDefault)
2812 InitSectionInfo(&si, info);
2813 si.defs.merge = merge;
2814 str = XkbcAtomGetString(def->name);
2815 if ((str == NULL) || (strlen(str) < 1))
2817 ERROR("Section defined without a name\n");
2818 ACTION("Definition ignored\n");
2822 XkbcInternAtom(info->dpy, XkbcAtomGetString(def->name), False);
2823 if (!HandleSectionBody(def, &si, merge, info))
2825 if (!AddSection(info, &si))
2830 /***====================================================================***/
2833 HandleGeometryFile(XkbFile * file,
2834 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2839 if (merge == MergeDefault)
2840 merge = MergeAugment;
2841 info->name = uStringDup(file->name);
2846 switch (stmt->stmtType)
2849 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2850 HandleGeometryFile))
2853 case StmtKeyAliasDef:
2854 if (!HandleAliasDef((KeyAliasDef *) stmt,
2855 merge, info->fileID, &info->aliases))
2861 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2865 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2868 case StmtSectionDef:
2869 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2872 case StmtIndicatorMapDef:
2874 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2879 failWhat = "virtual modfier";
2882 failWhat = "symbol interpretation";
2883 case StmtGroupCompatDef:
2885 failWhat = "group compatibility map";
2886 case StmtKeycodeDef:
2888 failWhat = "key name";
2889 ERROR("Interpretation files may not include other types\n");
2890 ACTION1("Ignoring %s definition.\n", failWhat);
2894 WSGO1("Unexpected statement type %d in HandleGeometryFile\n",
2899 if (info->errorCount > 10)
2902 ERROR("Too many errors\n");
2904 ACTION1("Abandoning geometry file \"%s\"\n", file->topName);
2911 /***====================================================================***/
2914 CopyShapeDef(Display * dpy, XkbGeometryPtr geom, ShapeInfo * si)
2918 XkbOutlinePtr old_outline, outline;
2921 si->index = geom->num_shapes;
2922 name = XkbcInternAtom(dpy, XkbcAtomGetString(si->name), False);
2923 shape = XkbAddGeomShape(geom, name, si->nOutlines);
2926 WSGO("Couldn't allocate shape in geometry\n");
2927 ACTION1("Shape %s not compiled\n", shText(dpy, si));
2930 old_outline = si->outlines;
2931 for (i = 0; i < si->nOutlines; i++, old_outline++)
2933 outline = XkbAddGeomOutline(shape, old_outline->num_points);
2936 WSGO("Couldn't allocate outline in shape\n");
2937 ACTION1("Shape %s is incomplete\n", shText(dpy, si));
2940 n = old_outline->num_points;
2941 memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec));
2942 outline->num_points = old_outline->num_points;
2943 outline->corner_radius = old_outline->corner_radius;
2947 n = (si->approx - si->outlines);
2948 shape->approx = &shape->outlines[n];
2952 n = (si->primary - si->outlines);
2953 shape->primary = &shape->outlines[n];
2955 XkbComputeShapeBounds(shape);
2960 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2962 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2964 if (warningLevel < 9)
2966 ERROR1("No position defined for doodad %s\n",
2967 ddText(info->dpy, di));
2968 ACTION("Illegal doodad ignored\n");
2972 if ((di->defs.defined & _GD_Priority) == 0)
2974 /* calculate priority -- should be just above previous doodad/row */
2978 case XkbOutlineDoodad:
2979 case XkbSolidDoodad:
2980 if ((di->defs.defined & _GD_Shape) == 0)
2982 ERROR2("No shape defined for %s doodad %s\n",
2983 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2984 ddText(info->dpy, di));
2985 ACTION("Incomplete definition ignored\n");
2991 si = FindShape(info, di->shape,
2993 XkbOutlineDoodad ? "outline doodad" :
2994 "solid doodad"), ddText(info->dpy, di));
2996 di->shape = si->name;
2999 ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
3000 ACTION("Incomplete definition ignored\n");
3004 if ((di->defs.defined & _GD_Color) == 0)
3006 if (warningLevel > 5)
3008 WARN1("No color for doodad %s\n", ddText(info->dpy, di));
3009 ACTION("Using black\n");
3011 di->color = XkbcInternAtom("black", False);
3015 if ((di->defs.defined & _GD_Text) == 0)
3017 ERROR1("No text specified for text doodad %s\n",
3018 ddText(info->dpy, di));
3019 ACTION("Illegal doodad definition ignored\n");
3022 if ((di->defs.defined & _GD_Angle) == 0)
3024 if ((di->defs.defined & _GD_Color) == 0)
3026 if (warningLevel > 5)
3028 WARN1("No color specified for doodad %s\n",
3029 ddText(info->dpy, di));
3030 ACTION("Using black\n");
3032 di->color = XkbcInternAtom("black", False);
3034 if ((di->defs.defined & _GD_FontSpec) != 0)
3036 if ((di->defs.defined & _GD_FontParts) == 0)
3038 if (warningLevel < 9)
3041 ("Text doodad %s has full and partial font definition\n",
3042 ddText(info->dpy, di));
3043 ACTION("Full specification ignored\n");
3045 di->defs.defined &= ~_GD_FontSpec;
3046 di->fontSpec = None;
3048 if ((di->defs.defined & _GD_Font) == 0)
3050 if (warningLevel > 5)
3052 WARN1("No font specified for doodad %s\n",
3053 ddText(info->dpy, di));
3054 ACTION1("Using \"%s\"\n", DFLT_FONT);
3056 di->font = XkbcInternAtom(DFLT_FONT, False);
3058 if ((di->defs.defined & _GD_FontSlant) == 0)
3060 if (warningLevel > 7)
3062 WARN1("No font slant for text doodad %s\n",
3063 ddText(info->dpy, di));
3064 ACTION1("Using \"%s\"\n", DFLT_SLANT);
3066 di->fontSlant = XkbcInternAtom(DFLT_SLANT, False);
3068 if ((di->defs.defined & _GD_FontWeight) == 0)
3070 if (warningLevel > 7)
3072 WARN1("No font weight for text doodad %s\n",
3073 ddText(info->dpy, di));
3074 ACTION1("Using \"%s\"\n", DFLT_WEIGHT);
3076 di->fontWeight = XkbcInternAtom(DFLT_WEIGHT, False);
3078 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3080 if (warningLevel > 9)
3082 WARN1("No font set width for text doodad %s\n",
3083 ddText(info->dpy, di));
3084 ACTION1("Using \"%s\"\n", DFLT_SET_WIDTH);
3086 di->fontSetWidth = XkbcInternAtom(DFLT_SET_WIDTH, False);
3088 if ((di->defs.defined & _GD_FontVariant) == 0)
3090 if (warningLevel > 9)
3092 WARN1("No font variant for text doodad %s\n",
3093 ddText(info->dpy, di));
3094 ACTION1("Using \"%s\"\n", DFLT_VARIANT);
3096 di->fontVariant = XkbcInternAtom(DFLT_VARIANT, False);
3098 if ((di->defs.defined & _GD_FontEncoding) == 0)
3100 if (warningLevel > 7)
3102 WARN1("No font encoding for doodad %s\n",
3103 ddText(info->dpy, di));
3104 ACTION1("Using \"%s\"\n", DFLT_ENCODING);
3106 di->fontEncoding = XkbcInternAtom(DFLT_ENCODING, False);
3108 if ((di->defs.defined & _GD_FontSize) == 0)
3110 if (warningLevel > 7)
3112 WARN1("No font size for text doodad %s\n",
3113 ddText(info->dpy, di));
3114 ACTION1("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3116 di->fontSize = DFLT_SIZE;
3118 if ((di->defs.defined & _GD_Height) == 0)
3120 unsigned size, nLines;
3122 size = (di->fontSize * 120) / 100;
3123 size = (size * 254) / 720; /* convert to mm/10 */
3124 for (nLines = 1, tmp = XkbcAtomGetString(di->text); *tmp;
3131 if (warningLevel > 5)
3133 WARN1("No height for text doodad %s\n",
3134 ddText(info->dpy, di));
3135 ACTION1("Using calculated height %s millimeters\n",
3136 XkbcGeomFPText(size));
3140 if ((di->defs.defined & _GD_Width) == 0)
3142 unsigned width, tmp;
3145 for (str = XkbcAtomGetString(di->text); *str; str++)
3158 width *= (di->height * 2) / 3;
3159 if (warningLevel > 5)
3161 WARN1("No width for text doodad %s\n", ddText(info->dpy, di));
3162 ACTION1("Using calculated width %s millimeters\n",
3163 XkbcGeomFPText(width));
3168 case XkbIndicatorDoodad:
3169 if ((di->defs.defined & _GD_Shape) == 0)
3171 ERROR1("No shape defined for indicator doodad %s\n",
3172 ddText(info->dpy, di));
3173 ACTION("Incomplete definition ignored\n");
3179 si = FindShape(info, di->shape, "indicator doodad",
3180 ddText(info->dpy, di));
3182 di->shape = si->name;
3185 ERROR1("No legal shape for doodad %s\n",
3186 ddText(info->dpy, di));
3187 ACTION("Incomplete definition ignored\n");
3191 if ((di->defs.defined & _GD_Color) == 0)
3193 if (warningLevel > 5)
3195 WARN1("No \"on\" color for indicator doodad %s\n",
3196 ddText(info->dpy, di));
3197 ACTION("Using green\n");
3199 di->color = XkbcInternAtom("green", False);
3201 if ((di->defs.defined & _GD_OffColor) == 0)
3203 if (warningLevel > 5)
3205 WARN1("No \"off\" color for indicator doodad %s\n",
3206 ddText(info->dpy, di));
3207 ACTION("Using black\n");
3209 di->offColor = XkbcInternAtom("black", False);
3213 if (di->logoName == NULL)
3215 ERROR1("No logo name defined for logo doodad %s\n",
3216 ddText(info->dpy, di));
3217 ACTION("Incomplete definition ignored\n");
3220 if ((di->defs.defined & _GD_Shape) == 0)
3222 ERROR1("No shape defined for logo doodad %s\n",
3223 ddText(info->dpy, di));
3224 ACTION("Incomplete definition ignored\n");
3230 si = FindShape(info, di->shape, "logo doodad",
3231 ddText(info->dpy, di));
3233 di->shape = si->name;
3236 ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
3237 ACTION("Incomplete definition ignored\n");
3241 if ((di->defs.defined & _GD_Color) == 0)
3243 if (warningLevel > 5)
3245 WARN1("No color for doodad %s\n", ddText(info->dpy, di));
3246 ACTION("Using black\n");
3248 di->color = XkbcInternAtom("black", False);
3252 WSGO1("Uknown doodad type %d in VerifyDoodad\n",
3253 (unsigned int) di->type);
3259 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3262 FontFromParts(Atom fontTok,
3265 Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
3268 char *font, *weight, *slant, *setWidth, *variant, *encoding;
3271 font = (fontTok != None ? XkbcAtomGetString(fontTok) : DFLT_FONT);
3273 (weightTok != None ? XkbcAtomGetString(weightTok) : DFLT_WEIGHT);
3275 (slantTok != None ? XkbcAtomGetString(slantTok) : DFLT_SLANT);
3278 None ? XkbcAtomGetString(setWidthTok) : DFLT_SET_WIDTH);
3280 (varTok != None ? XkbcAtomGetString(varTok) : DFLT_VARIANT);
3283 None ? XkbcAtomGetString(encodingTok) : DFLT_ENCODING);
3287 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3288 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3289 rtrn = uCalloc(totalSize, 1);
3292 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3299 CopyDoodadDef(XkbGeometryPtr geom,
3300 XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info)
3303 XkbDoodadPtr doodad;
3308 if (!VerifyDoodadInfo(di, info))
3310 name = XkbcInternAtom(XkbcAtomGetString(di->name), False);
3311 doodad = XkbAddGeomDoodad(geom, section, name);
3314 WSGO1("Couldn't allocate doodad in %s\n",
3315 (section ? "section" : "geometry"));
3316 ACTION1("Cannot copy doodad %s\n", ddText(info->dpy, di));
3319 doodad->any.type = di->type;
3320 doodad->any.priority = di->priority;
3321 doodad->any.top = di->top;
3322 doodad->any.left = di->left;
3325 case XkbOutlineDoodad:
3326 case XkbSolidDoodad:
3327 si = FindShape(info, di->shape, NULL, NULL);
3330 doodad->shape.angle = di->angle;
3332 XkbAddGeomColor(geom, XkbcAtomGetString(di->color),
3334 shape = &geom->shapes[si->index];
3335 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3336 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3339 doodad->text.angle = di->angle;
3340 doodad->text.width = di->width;
3341 doodad->text.height = di->height;
3342 if (di->fontSpec == None)
3343 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3346 di->fontVariant, di->fontSize,
3349 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3350 doodad->text.text = XkbcAtomGetString(di->text);
3352 XkbAddGeomColor(geom, XkbcAtomGetString(di->color),
3354 XkbSetTextDoodadColor(geom, &doodad->text, color);
3356 case XkbIndicatorDoodad:
3357 si = FindShape(info, di->shape, NULL, NULL);
3360 shape = &geom->shapes[si->index];
3362 XkbAddGeomColor(geom, XkbcAtomGetString(di->color),
3364 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3365 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3367 XkbAddGeomColor(geom, XkbcAtomGetString(di->offColor),
3369 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3372 si = FindShape(info, di->shape, NULL, NULL);
3375 doodad->logo.angle = di->angle;
3377 XkbAddGeomColor(geom, XkbcAtomGetString(di->color),
3379 shape = &geom->shapes[si->index];
3380 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3381 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3382 doodad->logo.logo_name = di->logoName;
3383 di->logoName = NULL;
3389 /***====================================================================***/
3392 VerifyOverlayInfo(XkbGeometryPtr geom,
3393 XkbSectionPtr section,
3395 GeometryInfo * info, short rowMap[256], short rowSize[256])
3397 register OverlayKeyInfo *ki, *next;
3398 unsigned long oKey, uKey, sKey;
3403 /* find out which row each key is in */
3404 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3406 oKey = KeyNameToLong(ki->over);
3407 uKey = KeyNameToLong(ki->under);
3408 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3411 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3414 sKey = KeyNameToLong(key->name.name);
3417 if (warningLevel > 0)
3420 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3421 XkbcKeyNameText(key->name.name),
3422 XkbcAtomText(section->name),
3423 XkbcAtomText(oi->name));
3424 ACTION("Overlay definition ignored\n");
3428 else if (sKey == uKey)
3435 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3438 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3439 XkbcKeyNameText(ki->under),
3440 XkbcAtomText(section->name),
3441 XkbcAtomText(oi->name));
3442 ACTION("Definition ignored\n");
3445 /* now prune out keys that aren't in the section */
3446 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3448 next = (OverlayKeyInfo *) oi->keys->defs.next;
3453 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3455 next = (OverlayKeyInfo *) ki->defs.next;
3456 if (next->sectionRow == _GOK_UnknownRow)
3458 ki->defs.next = next->defs.next;
3461 next = (OverlayKeyInfo *) ki->defs.next;
3466 ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3467 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3468 ACTION("Overlay definition ignored\n");
3471 /* now figure out how many rows are defined for the overlay */
3472 bzero(rowSize, sizeof(short) * 256);
3473 for (k = 0; k < 256; k++)
3478 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3480 if (rowMap[ki->sectionRow] == -1)
3481 rowMap[ki->sectionRow] = oi->nRows++;
3482 ki->overlayRow = rowMap[ki->sectionRow];
3483 rowSize[ki->overlayRow]++;
3489 CopyOverlayDef(XkbGeometryPtr geom,
3490 XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
3494 XkbOverlayRowPtr row;
3495 XkbOverlayKeyPtr key;
3497 short rowMap[256], rowSize[256];
3500 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3502 name = XkbcInternAtom(XkbcAtomGetString(oi->name), False);
3503 ol = XkbAddGeomOverlay(section, name, oi->nRows);
3506 WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n",
3507 XkbcAtomText(name), XkbcAtomText(section->name));
3510 for (i = 0; i < oi->nRows; i++)
3513 for (tmp = 0, row_under = -1;
3514 (tmp < section->num_rows) && (row_under < 0); tmp++)
3516 if (rowMap[tmp] == i)
3519 if (!XkbAddGeomOverlayRow(ol, row_under, rowSize[i]))
3522 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3523 i, XkbcAtomText(name), XkbcAtomText(section->name));
3527 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3529 row = &ol->rows[ki->overlayRow];
3530 key = &row->keys[row->num_keys++];
3531 bzero(key, sizeof(XkbOverlayKeyRec));
3532 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3533 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3538 /***====================================================================***/
3541 CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
3543 XkbSectionPtr section;
3550 name = XkbcInternAtom(XkbcAtomGetString(si->name), False);
3552 XkbAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays);
3553 if (section == NULL)
3555 WSGO("Couldn't allocate section in geometry\n");
3556 ACTION1("Section %s not compiled\n", scText(info->dpy, si));
3559 section->top = si->top;
3560 section->left = si->left;
3561 section->width = si->width;
3562 section->height = si->height;
3563 section->angle = si->angle;
3564 section->priority = si->priority;
3565 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3567 row = XkbAddGeomRow(section, ri->nKeys);
3570 WSGO("Couldn't allocate row in section\n");
3571 ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
3575 row->left = ri->left;
3576 row->vertical = ri->vertical;
3577 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3580 if ((ki->defs.defined & _GK_Name) == 0)
3582 ERROR3("Key %d of row %d in section %s has no name\n",
3583 (int) ki->index, (int) ri->index,
3584 scText(info->dpy, si));
3585 ACTION1("Section %s ignored\n", scText(info->dpy, si));
3588 key = XkbAddGeomKey(row);
3591 WSGO("Couldn't allocate key in row\n");
3592 ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
3595 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3597 if (ki->shape == None)
3602 si = FindShape(info, ki->shape, "key", keyText(ki));
3605 key->shape_ndx = si->index;
3607 if (ki->color != None)
3609 XkbAddGeomColor(geom,
3610 XkbcAtomGetString(ki->color),
3613 color = XkbAddGeomColor(geom, "white", geom->num_colors);
3614 XkbSetKeyColor(geom, key, color);
3617 if (si->doodads != NULL)
3620 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3622 CopyDoodadDef(geom, section, di, info);
3625 if (si->overlays != NULL)
3628 for (oi = si->overlays; oi != NULL;
3629 oi = (OverlayInfo *) oi->defs.next)
3631 CopyOverlayDef(geom, section, oi, info);
3634 if (XkbComputeSectionBounds(geom, section))
3636 /* 7/6/94 (ef) -- check for negative origin and translate */
3637 if ((si->defs.defined & _GS_Width) == 0)
3638 section->width = section->bounds.x2;
3639 if ((si->defs.defined & _GS_Height) == 0)
3640 section->height = section->bounds.y2;
3645 /***====================================================================***/
3648 CompileGeometry(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
3652 InitGeometryInfo(&info, file->id, merge);
3653 info.dpy = xkb->dpy;
3654 HandleGeometryFile(file, xkb, merge, &info);
3656 if (info.errorCount == 0)
3658 XkbGeometryPtr geom;
3659 XkbGeometrySizesRec sizes;
3660 bzero(&sizes, sizeof(sizes));
3661 sizes.which = XkbGeomAllMask;
3662 sizes.num_properties = info.nProps;
3663 sizes.num_colors = 8;
3664 sizes.num_shapes = info.nShapes;
3665 sizes.num_sections = info.nSections;
3666 sizes.num_doodads = info.nDoodads;
3667 if (XkbAllocGeometry(xkb, &sizes) != Success)
3669 WSGO("Couldn't allocate GeometryRec\n");
3670 ACTION("Geometry not compiled\n");
3675 geom->width_mm = info.widthMM;
3676 geom->height_mm = info.heightMM;
3677 if (info.name != NULL)
3679 geom->name = XkbcInternAtom(info.name, False);
3680 if (XkbAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3681 xkb->names->geometry = geom->name;
3683 if (info.fontSpec != None)
3685 uStringDup(XkbcAtomGetString(info.fontSpec));
3687 geom->label_font = FontFromParts(info.font, info.fontWeight,
3693 XkbAddGeomColor(geom, "black", geom->num_colors);
3694 XkbAddGeomColor(geom, "white", geom->num_colors);
3696 if (info.baseColor == None)
3697 info.baseColor = XkbcInternAtom("white", False);
3698 if (info.labelColor == None)
3699 info.labelColor = XkbcInternAtom("black", False);
3701 XkbAddGeomColor(geom, XkbcAtomGetString(info.baseColor),
3704 XkbAddGeomColor(geom, XkbcAtomGetString(info.labelColor),
3710 for (pi = info.props; pi != NULL;
3711 pi = (PropertyInfo *) pi->defs.next)
3713 if (!XkbAddGeomProperty(geom, pi->name, pi->value))
3720 for (si = info.shapes; si != NULL;
3721 si = (ShapeInfo *) si->defs.next)
3723 if (!CopyShapeDef(xkb->dpy, geom, si))
3730 for (si = info.sections; si != NULL;
3731 si = (SectionInfo *) si->defs.next)
3733 if (!CopySectionDef(geom, si, &info))
3740 for (di = info.doodads; di != NULL;
3741 di = (DoodadInfo *) di->defs.next)
3743 if (!CopyDoodadDef(geom, NULL, di, &info))
3748 ApplyAliases(xkb, True, &info.aliases);
3749 ClearGeometryInfo(&info);