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 ********************************************************/
35 #include "indicators.h"
40 #define DFLT_FONT "helvetica"
41 #define DFLT_SLANT "r"
42 #define DFLT_WEIGHT "medium"
43 #define DFLT_SET_WIDTH "normal"
44 #define DFLT_VARIANT ""
45 #define DFLT_ENCODING "iso8859-1"
48 typedef struct _PropertyInfo
55 #define _GSh_Outlines (1<<1)
56 #define _GSh_Approx (1<<2)
57 #define _GSh_Primary (1<<3)
58 typedef struct _ShapeInfo
63 unsigned short nOutlines;
64 unsigned short szOutlines;
65 XkbcOutlinePtr outlines;
66 XkbcOutlinePtr approx;
67 XkbcOutlinePtr primary;
72 ((s) ? XkbcAtomText((s)->name) : "default shape")
74 #define _GD_Priority (1<<0)
75 #define _GD_Top (1<<1)
76 #define _GD_Left (1<<2)
77 #define _GD_Angle (1<<3)
78 #define _GD_Shape (1<<4)
79 #define _GD_FontVariant (1<<4) /* CHEATING */
80 #define _GD_Corner (1<<5)
81 #define _GD_Width (1<<5) /* CHEATING */
82 #define _GD_Color (1<<6)
83 #define _GD_OffColor (1<<7)
84 #define _GD_Height (1<<7) /* CHEATING */
85 #define _GD_Text (1<<8)
86 #define _GD_Font (1<<9)
87 #define _GD_FontSlant (1<<10)
88 #define _GD_FontWeight (1<<11)
89 #define _GD_FontSetWidth (1<<12)
90 #define _GD_FontSize (1<<13)
91 #define _GD_FontEncoding (1<<14)
92 #define _GD_FontSpec (1<<15)
95 #define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
97 typedef struct _DoodadInfo
102 unsigned char priority;
106 unsigned short corner;
107 unsigned short width;
108 unsigned short height;
118 unsigned short fontSize;
122 struct _SectionInfo *section;
129 #define _GK_Default (1<<0)
130 #define _GK_Name (1<<1)
131 #define _GK_Gap (1<<2)
132 #define _GK_Shape (1<<3)
133 #define _GK_Color (1<<4)
134 typedef struct _KeyInfo
142 struct _RowInfo *row;
144 #define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
146 #define _GR_Default (1<<0)
147 #define _GR_Vertical (1<<1)
148 #define _GR_Top (1<<2)
149 #define _GR_Left (1<<3)
150 typedef struct _RowInfo
157 unsigned short nKeys;
160 struct _SectionInfo *section;
163 ((r) ? XkbcAtomText((r)->section->name) : "default")
165 #define _GOK_UnknownRow -1
166 typedef struct _OverlayKeyInfo
171 char over[XkbKeyNameLength + 1];
172 char under[XkbKeyNameLength + 1];
175 typedef struct _OverlayInfo
179 unsigned short nRows;
180 unsigned short nKeys;
181 OverlayKeyInfo *keys;
184 ((o) ? XkbcAtomText((o)->name) : "default")
187 #define _GS_Default (1<<0)
188 #define _GS_Name (1<<1)
189 #define _GS_Top (1<<2)
190 #define _GS_Left (1<<3)
191 #define _GS_Width (1<<4)
192 #define _GS_Height (1<<5)
193 #define _GS_Angle (1<<6)
194 #define _GS_Priority (1<<7)
195 typedef struct _SectionInfo
201 unsigned short width;
202 unsigned short height;
203 unsigned short angle;
204 unsigned short nRows;
205 unsigned short nDoodads;
206 unsigned short nOverlays;
207 unsigned char priority;
208 unsigned char nextDoodadPriority;
212 DoodadInfo *dfltDoodads;
213 OverlayInfo *overlays;
214 struct _GeometryInfo *geometry;
217 ((s) ? XkbcAtomText((s)->name) : "default")
219 typedef struct _GeometryInfo
225 unsigned nextPriority;
232 SectionInfo *sections;
246 int dfltCornerRadius;
247 SectionInfo dfltSection;
248 DoodadInfo *dfltDoodads;
253 ddText(DoodadInfo * di)
259 strcpy(buf, "default");
264 sprintf(buf, "%s in section %s",
265 XkbcAtomText(di->name), scText(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, CARD32 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 WARN("Multiple definitions for the \"%s\" property\n",
751 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
756 old->value = _XkbDupString(new->value);
759 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
760 || (warningLevel > 9))
762 WARN("Multiple definitions for \"%s\" property\n", new->name);
763 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
769 if ((new = NextProperty(info)) == NULL)
771 new->defs.next = NULL;
772 new->name = _XkbDupString(old->name);
773 new->value = _XkbDupString(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, CARD32 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 WARN("Unknown shape \"%s\" for %s %s\n",
810 XkbcAtomText(name), type, which);
813 ACTION("Using default shape %s instead\n", shText(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 WARN("Duplicate shape name \"%s\"\n", shText(old));
838 ACTION("Using last definition\n");
841 old->defs.next = &next->defs;
844 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
845 || (warningLevel > 9))
847 WARN("Multiple shapes named \"%s\"\n", shText(old));
848 ACTION("Using first definition\n");
853 if ((new = NextShape(info)) == NULL)
856 new->defs.next = NULL;
857 old->szOutlines = old->nOutlines = 0;
858 old->outlines = NULL;
864 /***====================================================================***/
867 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
871 next = into->defs.next;
872 ClearDoodadInfo(into);
874 into->defs.next = next;
875 next = from->defs.next;
876 ClearDoodadInfo(from);
877 from->defs.next = next;
882 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
886 di = uTypedCalloc(1, DoodadInfo);
892 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
898 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
905 NextDoodad(SectionInfo * si, GeometryInfo * info)
909 di = uTypedCalloc(1, DoodadInfo);
914 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
921 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
930 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
934 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
937 if ((new->defs.merge == MergeReplace)
938 || (new->defs.merge == MergeOverride))
940 if (((old->defs.fileID == new->defs.fileID)
941 && (warningLevel > 0)) || (warningLevel > 9))
943 WARN("Multiple doodads named \"%s\"\n",
944 XkbcAtomText(old->name));
945 ACTION("Using last definition\n");
947 ReplaceDoodad(old, new);
951 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
952 || (warningLevel > 9))
954 WARN("Multiple doodads named \"%s\"\n",
955 XkbcAtomText(old->name));
956 ACTION("Using first definition\n");
961 if ((new = NextDoodad(si, info)) == NULL)
963 ReplaceDoodad(new, old);
965 new->defs.next = NULL;
970 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
972 DoodadInfo *dflt = NULL;
975 if (uStrCaseCmp(name, "outline") == 0)
976 type = XkbOutlineDoodad;
977 else if (uStrCaseCmp(name, "solid") == 0)
978 type = XkbSolidDoodad;
979 else if (uStrCaseCmp(name, "text") == 0)
980 type = XkbTextDoodad;
981 else if (uStrCaseCmp(name, "indicator") == 0)
982 type = XkbIndicatorDoodad;
983 else if (uStrCaseCmp(name, "logo") == 0)
984 type = XkbLogoDoodad;
987 if ((si) && (si->dfltDoodads))
988 dflt = FindDoodadByType(si->dfltDoodads, type);
989 if ((!dflt) && (info->dfltDoodads))
990 dflt = FindDoodadByType(info->dfltDoodads, type);
993 dflt = NextDfltDoodad(si, info);
1003 /***====================================================================***/
1006 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1010 for (old = si->overlays; old != NULL;
1011 old = (OverlayInfo *) old->defs.next)
1013 if (old->name == new->name)
1018 if ((new->defs.merge == MergeReplace)
1019 || (new->defs.merge == MergeOverride))
1021 if (((old->defs.fileID == new->defs.fileID)
1022 && (warningLevel > 0)) || (warningLevel > 9))
1025 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1026 XkbcAtomText(old->name), XkbcAtomText(si->name));
1027 ACTION("Using last definition\n");
1029 ClearOverlayInfo(old);
1030 old->nKeys = new->nKeys;
1031 old->keys = new->keys;
1036 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1037 || (warningLevel > 9))
1039 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1040 XkbcAtomText(old->name), XkbcAtomText(si->name));
1041 ACTION("Using first definition\n");
1046 new = uTypedCalloc(1, OverlayInfo);
1049 if (warningLevel > 0)
1051 WSGO("Couldn't allocate a new OverlayInfo\n");
1053 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1054 XkbcAtomText(old->name), XkbcAtomText(si->name));
1061 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1062 (CommonInfo *) new);
1067 /***====================================================================***/
1069 static SectionInfo *
1070 NextSection(GeometryInfo * info)
1074 si = uTypedAlloc(SectionInfo);
1077 *si = info->dfltSection;
1078 si->defs.defined &= ~_GS_Default;
1079 si->defs.next = NULL;
1083 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1090 static SectionInfo *
1091 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1095 for (old = info->sections; old != NULL;
1096 old = (SectionInfo *) old->defs.next)
1098 if (new->name == old->name)
1105 AddSection(GeometryInfo * info, SectionInfo * new)
1109 old = FindMatchingSection(info, new);
1113 if ((new->defs.merge == MergeReplace)
1114 || (new->defs.merge == MergeOverride))
1116 SectionInfo *next = (SectionInfo *) old->defs.next;
1117 if (((old->defs.fileID == new->defs.fileID)
1118 && (warningLevel > 0)) || (warningLevel > 9))
1120 WARN("Duplicate shape name \"%s\"\n", shText(old));
1121 ACTION("Using last definition\n");
1124 old->defs.next = &next->defs;
1127 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1128 || (warningLevel > 9))
1130 WARN("Multiple shapes named \"%s\"\n", shText(old));
1131 ACTION("Using first definition\n");
1135 WARN("Don't know how to merge sections yet\n");
1139 if ((new = NextSection(info)) == NULL)
1142 new->defs.next = NULL;
1143 old->nRows = old->nDoodads = old->nOverlays = 0;
1145 old->doodads = NULL;
1146 old->overlays = NULL;
1150 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1158 /***====================================================================***/
1161 NextRow(SectionInfo * si)
1165 row = uTypedAlloc(RowInfo);
1169 row->defs.defined &= ~_GR_Default;
1170 row->defs.next = NULL;
1174 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1175 row->index = si->nRows++;
1181 AddRow(SectionInfo * si, RowInfo * new)
1186 if ((new = NextRow(si)) == NULL)
1189 new->defs.next = NULL;
1195 /***====================================================================***/
1198 NextKey(RowInfo * row)
1202 key = uTypedAlloc(KeyInfo);
1205 *key = row->dfltKey;
1206 key->defs.defined &= ~_GK_Default;
1207 key->defs.next = NULL;
1208 key->index = row->nKeys++;
1214 AddKey(RowInfo * row, KeyInfo * new)
1219 if ((new = NextKey(row)) == NULL)
1222 new->defs.next = NULL;
1224 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1228 /***====================================================================***/
1231 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1236 if (from->errorCount > 0)
1238 into->errorCount += from->errorCount;
1241 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1242 if (into->name == NULL)
1244 into->name = from->name;
1247 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1248 into->widthMM = from->widthMM;
1249 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1250 into->heightMM = from->heightMM;
1251 if ((into->font == None) || ((from->font != None) && clobber))
1252 into->font = from->font;
1253 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1254 into->fontSlant = from->fontSlant;
1255 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1256 into->fontWeight = from->fontWeight;
1257 if ((into->fontSetWidth == None)
1258 || ((from->fontSetWidth != None) && clobber))
1259 into->fontSetWidth = from->fontSetWidth;
1260 if ((into->fontVariant == None)
1261 || ((from->fontVariant != None) && clobber))
1262 into->fontVariant = from->fontVariant;
1263 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1264 into->fontSize = from->fontSize;
1265 if ((into->fontEncoding == None)
1266 || ((from->fontEncoding != None) && clobber))
1267 into->fontEncoding = from->fontEncoding;
1268 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1269 into->fontSpec = from->fontSpec;
1270 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1271 into->baseColor = from->baseColor;
1272 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1273 into->labelColor = from->labelColor;
1274 into->nextPriority = from->nextPriority;
1275 if (from->props != NULL)
1278 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1280 if (!AddProperty(into, pi))
1284 if (from->shapes != NULL)
1288 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1290 if (!AddShape(into, si))
1294 if (from->sections != NULL)
1298 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1300 if (!AddSection(into, si))
1304 if (from->doodads != NULL)
1308 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1310 if (!AddDoodad(NULL, into, di))
1314 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1319 typedef void (*FileHandler) (XkbFile * /* file */ ,
1320 XkbcDescPtr /* xkb */ ,
1321 unsigned /* merge */ ,
1322 GeometryInfo * /* info */
1326 HandleIncludeGeometry(IncludeStmt * stmt, XkbcDescPtr xkb, GeometryInfo * info,
1331 GeometryInfo included;
1335 if ((stmt->file == NULL) && (stmt->map == NULL))
1339 bzero(info, sizeof(GeometryInfo));
1341 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1343 InitGeometryInfo(&included, rtrn->id, newMerge);
1344 included.nextPriority = info->nextPriority;
1345 included.dfltCornerRadius = info->dfltCornerRadius;
1346 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1347 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1348 if (stmt->stmt != NULL)
1350 if (included.name != NULL)
1351 uFree(included.name);
1352 included.name = stmt->stmt;
1358 info->errorCount += 10;
1361 if ((stmt->next != NULL) && (included.errorCount < 1))
1365 GeometryInfo next_incl;
1367 for (next = stmt->next; next != NULL; next = next->next)
1369 if ((next->file == NULL) && (next->map == NULL))
1372 MergeIncludedGeometry(&included, info, next->merge);
1373 ClearGeometryInfo(info);
1375 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1377 InitGeometryInfo(&next_incl, rtrn->id, op);
1378 next_incl.nextPriority = included.nextPriority;
1379 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1380 DupSectionInfo(&next_incl.dfltSection,
1381 &included.dfltSection, &included);
1382 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1383 MergeIncludedGeometry(&included, &next_incl, op);
1384 ClearGeometryInfo(&next_incl);
1388 info->errorCount += 10;
1397 MergeIncludedGeometry(info, &included, newMerge);
1398 ClearGeometryInfo(&included);
1400 return (info->errorCount == 0);
1404 SetShapeField(ShapeInfo * si,
1406 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1410 if ((uStrCaseCmp(field, "radius") == 0)
1411 || (uStrCaseCmp(field, "corner") == 0)
1412 || (uStrCaseCmp(field, "cornerradius") == 0))
1414 if (arrayNdx != NULL)
1417 return ReportNotArray("key shape", field, shText(si));
1419 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1422 return ReportBadType("key shape", field, shText(si), "number");
1425 si->dfltCornerRadius = tmp.ival;
1427 info->dfltCornerRadius = tmp.ival;
1431 return ReportBadField("key shape", field, shText(si));
1435 SetShapeDoodadField(DoodadInfo * di,
1438 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1441 const char *typeName;
1444 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1445 if ((!uStrCaseCmp(field, "corner"))
1446 || (!uStrCaseCmp(field, "cornerradius")))
1448 if (arrayNdx != NULL)
1451 return ReportNotArray(typeName, field, ddText(di));
1453 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1456 return ReportBadType(typeName, field, ddText(di), "number");
1458 di->defs.defined |= _GD_Corner;
1459 di->corner = tmp.ival;
1462 else if (uStrCaseCmp(field, "angle") == 0)
1464 if (arrayNdx != NULL)
1467 return ReportNotArray(typeName, field, ddText(di));
1469 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1472 return ReportBadType(typeName, field, ddText(di), "number");
1474 di->defs.defined |= _GD_Angle;
1475 di->angle = tmp.ival;
1478 else if (uStrCaseCmp(field, "shape") == 0)
1480 if (arrayNdx != NULL)
1483 return ReportNotArray(typeName, field, ddText(di));
1485 if (!ExprResolveString(value, &tmp, NULL, NULL))
1488 return ReportBadType(typeName, field, ddText(di), "string");
1490 di->shape = XkbcInternAtom(tmp.str, False);
1491 di->defs.defined |= _GD_Shape;
1494 return ReportBadField(typeName, field, ddText(di));
1497 #define FIELD_STRING 0
1498 #define FIELD_SHORT 1
1499 #define FIELD_USHORT 2
1502 SetTextDoodadField(DoodadInfo * di,
1505 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1510 char *typeName = "text doodad";
1515 unsigned short *uval;
1518 if (uStrCaseCmp(field, "angle") == 0)
1520 if (arrayNdx != NULL)
1523 return ReportNotArray(typeName, field, ddText(di));
1525 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1528 return ReportBadType(typeName, field, ddText(di), "number");
1530 di->defs.defined |= _GD_Angle;
1531 di->angle = tmp.ival;
1534 if (uStrCaseCmp(field, "width") == 0)
1536 type = FIELD_USHORT;
1537 pField.uval = &di->width;
1540 else if (uStrCaseCmp(field, "height") == 0)
1542 type = FIELD_USHORT;
1543 pField.uval = &di->height;
1546 else if (uStrCaseCmp(field, "text") == 0)
1548 type = FIELD_STRING;
1549 pField.str = &di->text;
1552 else if (uStrCaseCmp(field, "font") == 0)
1554 type = FIELD_STRING;
1555 pField.str = &di->font;
1558 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1559 (uStrCaseCmp(field, "slant") == 0))
1561 type = FIELD_STRING;
1562 pField.str = &di->fontSlant;
1563 def = _GD_FontSlant;
1565 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1566 (uStrCaseCmp(field, "weight") == 0))
1568 type = FIELD_STRING;
1569 pField.str = &di->fontWeight;
1570 def = _GD_FontWeight;
1572 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1573 (uStrCaseCmp(field, "setwidth") == 0))
1575 type = FIELD_STRING;
1576 pField.str = &di->fontSetWidth;
1577 def = _GD_FontSetWidth;
1579 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1580 (uStrCaseCmp(field, "variant") == 0))
1582 type = FIELD_STRING;
1583 pField.str = &di->fontVariant;
1584 def = _GD_FontVariant;
1586 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1587 (uStrCaseCmp(field, "encoding") == 0))
1589 type = FIELD_STRING;
1590 pField.str = &di->fontEncoding;
1591 def = _GD_FontEncoding;
1593 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1594 (uStrCaseCmp(field, "xfontname") == 0))
1596 type = FIELD_STRING;
1597 pField.str = &di->fontSpec;
1600 else if (uStrCaseCmp(field, "fontsize") == 0)
1602 type = FIELD_USHORT;
1603 pField.uval = &di->fontSize;
1608 return ReportBadField(typeName, field, ddText(di));
1610 if (arrayNdx != NULL)
1613 return ReportNotArray(typeName, field, ddText(di));
1615 if (type == FIELD_STRING)
1617 if (!ExprResolveString(value, &tmp, NULL, NULL))
1620 return ReportBadType(typeName, field, ddText(di), "string");
1622 di->defs.defined |= def;
1623 *pField.str = XkbcInternAtom(tmp.str, False);
1627 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1630 return ReportBadType(typeName, field, ddText(di), "number");
1632 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1636 ReportBadType(typeName, field, ddText(di), "unsigned");
1638 di->defs.defined |= def;
1639 if (type == FIELD_USHORT)
1640 *pField.uval = tmp.uval;
1642 *pField.ival = tmp.ival;
1648 SetIndicatorDoodadField(DoodadInfo * di,
1652 SectionInfo * si, GeometryInfo * info)
1656 if ((uStrCaseCmp(field, "oncolor") == 0)
1657 || (uStrCaseCmp(field, "offcolor") == 0)
1658 || (uStrCaseCmp(field, "shape") == 0))
1660 if (arrayNdx != NULL)
1663 return ReportNotArray("indicator doodad", field, ddText(di));
1665 if (!ExprResolveString(value, &tmp, NULL, NULL))
1668 return ReportBadType("indicator doodad", field,
1669 ddText(di), "string");
1671 if (uStrCaseCmp(field, "oncolor") == 0)
1673 di->defs.defined |= _GD_Color;
1674 di->color = XkbcInternAtom(tmp.str, False);
1676 else if (uStrCaseCmp(field, "offcolor") == 0)
1678 di->defs.defined |= _GD_OffColor;
1679 di->offColor = XkbcInternAtom(tmp.str, False);
1681 else if (uStrCaseCmp(field, "shape") == 0)
1683 di->defs.defined |= _GD_Shape;
1684 di->shape = XkbcInternAtom(tmp.str, False);
1688 return ReportBadField("indicator doodad", field, ddText(di));
1692 SetLogoDoodadField(DoodadInfo * di,
1695 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1698 char *typeName = "logo doodad";
1700 if ((!uStrCaseCmp(field, "corner"))
1701 || (!uStrCaseCmp(field, "cornerradius")))
1703 if (arrayNdx != NULL)
1706 return ReportNotArray(typeName, field, ddText(di));
1708 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1711 return ReportBadType(typeName, field, ddText(di), "number");
1713 di->defs.defined |= _GD_Corner;
1714 di->corner = tmp.ival;
1717 else if (uStrCaseCmp(field, "angle") == 0)
1719 if (arrayNdx != NULL)
1722 return ReportNotArray(typeName, field, ddText(di));
1724 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1727 return ReportBadType(typeName, field, ddText(di), "number");
1729 di->defs.defined |= _GD_Angle;
1730 di->angle = tmp.ival;
1733 else if (uStrCaseCmp(field, "shape") == 0)
1735 if (arrayNdx != NULL)
1738 return ReportNotArray(typeName, field, ddText(di));
1740 if (!ExprResolveString(value, &tmp, NULL, NULL))
1743 return ReportBadType(typeName, field, ddText(di), "string");
1745 di->shape = XkbcInternAtom(tmp.str, False);
1746 di->defs.defined |= _GD_Shape;
1749 else if ((!uStrCaseCmp(field, "logoname"))
1750 || (!uStrCaseCmp(field, "name")))
1752 if (arrayNdx != NULL)
1755 return ReportNotArray(typeName, field, ddText(di));
1757 if (!ExprResolveString(value, &tmp, NULL, NULL))
1760 return ReportBadType(typeName, field, ddText(di),
1763 di->logoName = _XkbDupString(tmp.str);
1766 return ReportBadField(typeName, field, ddText(di));
1770 SetDoodadField(DoodadInfo * di,
1773 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1777 if (uStrCaseCmp(field, "priority") == 0)
1779 if (arrayNdx != NULL)
1782 return ReportNotArray("doodad", field, ddText(di));
1784 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1787 return ReportBadType("doodad", field, ddText(di), "integer");
1789 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1792 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1793 tmp.ival, XkbGeomMaxPriority);
1794 ACTION("Priority for doodad %s not changed", ddText(di));
1797 di->defs.defined |= _GD_Priority;
1798 di->priority = tmp.ival;
1801 else if (uStrCaseCmp(field, "left") == 0)
1803 if (arrayNdx != NULL)
1806 return ReportNotArray("doodad", field, ddText(di));
1808 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1811 return ReportBadType("doodad", field, ddText(di), "number");
1813 di->defs.defined |= _GD_Left;
1814 di->left = tmp.ival;
1817 else if (uStrCaseCmp(field, "top") == 0)
1819 if (arrayNdx != NULL)
1822 return ReportNotArray("doodad", field, ddText(di));
1824 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1827 return ReportBadType("doodad", field, ddText(di), "number");
1829 di->defs.defined |= _GD_Top;
1833 else if (uStrCaseCmp(field, "color") == 0)
1835 if (arrayNdx != NULL)
1838 return ReportNotArray("doodad", field, ddText(di));
1840 if (!ExprResolveString(value, &tmp, NULL, NULL))
1843 return ReportBadType("doodad", field, ddText(di), "string");
1845 di->defs.defined |= _GD_Color;
1846 di->color = XkbcInternAtom(tmp.str, False);
1852 case XkbOutlineDoodad:
1853 case XkbSolidDoodad:
1854 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1856 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1857 case XkbIndicatorDoodad:
1858 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1860 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1862 WSGO("Unknown doodad type %d in SetDoodadField\n",
1863 (unsigned int) di->type);
1864 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1869 SetSectionField(SectionInfo * si,
1871 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1873 unsigned short *pField;
1879 if (uStrCaseCmp(field, "priority") == 0)
1881 if (arrayNdx != NULL)
1884 return ReportNotArray("keyboard section", field, scText(si));
1886 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1889 ReportBadType("keyboard section", field, scText(si), "integer");
1892 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1895 ERROR("Section priority %d out of range (must be 0..%d)\n",
1896 tmp.ival, XkbGeomMaxPriority);
1897 ACTION("Priority for section %s not changed", scText(si));
1900 si->priority = tmp.ival;
1901 si->defs.defined |= _GS_Priority;
1904 else if (uStrCaseCmp(field, "top") == 0)
1909 else if (uStrCaseCmp(field, "left") == 0)
1914 else if (uStrCaseCmp(field, "width") == 0)
1916 pField = &si->width;
1919 else if (uStrCaseCmp(field, "height") == 0)
1921 pField = &si->height;
1924 else if (uStrCaseCmp(field, "angle") == 0)
1926 pField = &si->angle;
1932 return ReportBadField("keyboard section", field, scText(si));
1934 if (arrayNdx != NULL)
1937 return ReportNotArray("keyboard section", field, scText(si));
1939 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1942 ReportBadType("keyboard section", field, scText(si), "number");
1945 si->defs.defined |= def;
1951 SetRowField(RowInfo * row,
1953 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1957 if (uStrCaseCmp(field, "top") == 0)
1959 if (arrayNdx != NULL)
1962 return ReportNotArray("keyboard row", field, rowText(row));
1964 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1967 return ReportBadType("keyboard row", field, rowText(row),
1970 row->defs.defined |= _GR_Top;
1971 row->top = tmp.uval;
1973 else if (uStrCaseCmp(field, "left") == 0)
1975 if (arrayNdx != NULL)
1978 return ReportNotArray("keyboard row", field, rowText(row));
1980 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1983 return ReportBadType("keyboard row", field, rowText(row),
1986 row->defs.defined |= _GR_Left;
1987 row->left = tmp.uval;
1989 else if (uStrCaseCmp(field, "vertical") == 0)
1991 if (arrayNdx != NULL)
1994 return ReportNotArray("keyboard row", field, rowText(row));
1996 if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1999 return ReportBadType("keyboard row", field, rowText(row),
2002 row->defs.defined |= _GR_Vertical;
2003 row->vertical = tmp.uval;
2008 return ReportBadField("keyboard row", field, rowText(row));
2014 SetKeyField(KeyInfo * key,
2016 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2020 if (uStrCaseCmp(field, "gap") == 0)
2022 if (arrayNdx != NULL)
2025 return ReportNotArray("key", field, keyText(key));
2027 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
2030 return ReportBadType("key", field, keyText(key), "number");
2032 key->defs.defined |= _GK_Gap;
2033 key->gap = tmp.ival;
2035 else if (uStrCaseCmp(field, "shape") == 0)
2037 if (arrayNdx != NULL)
2040 return ReportNotArray("key", field, keyText(key));
2042 if (!ExprResolveString(value, &tmp, NULL, NULL))
2045 return ReportBadType("key", field, keyText(key), "string");
2047 key->defs.defined |= _GK_Shape;
2048 key->shape = XkbcInternAtom(tmp.str, False);
2051 else if ((uStrCaseCmp(field, "color") == 0) ||
2052 (uStrCaseCmp(field, "keycolor") == 0))
2054 if (arrayNdx != NULL)
2057 return ReportNotArray("key", field, keyText(key));
2059 if (!ExprResolveString(value, &tmp, NULL, NULL))
2062 return ReportBadType("key", field, keyText(key), "string");
2064 key->defs.defined |= _GK_Color;
2065 key->color = XkbcInternAtom(tmp.str, False);
2068 else if ((uStrCaseCmp(field, "name") == 0)
2069 || (uStrCaseCmp(field, "keyname") == 0))
2071 if (arrayNdx != NULL)
2074 return ReportNotArray("key", field, keyText(key));
2076 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2079 return ReportBadType("key", field, keyText(key), "key name");
2081 key->defs.defined |= _GK_Name;
2082 bzero(key->name, XkbKeyNameLength + 1);
2083 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2088 return ReportBadField("key", field, keyText(key));
2094 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2100 InitPropertyInfo(&pi, info);
2102 if (!ExprResolveString(value, &result, NULL, NULL))
2105 ERROR("Property values must be type string\n");
2106 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2109 pi.value = result.str;
2110 ret = AddProperty(info, &pi);
2116 HandleGeometryVar(VarDef * stmt, XkbcDescPtr xkb, GeometryInfo * info)
2118 ExprResult elem, field, tmp;
2121 CARD32 *pField = NULL;
2124 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2125 return 0; /* internal error, already reported */
2128 if (uStrCaseCmp(elem.str, "shape") == 0)
2129 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2130 else if (uStrCaseCmp(elem.str, "key") == 0)
2131 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2132 field.str, ndx, stmt->value, info);
2133 else if (uStrCaseCmp(elem.str, "row") == 0)
2134 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2136 else if (uStrCaseCmp(elem.str, "section") == 0)
2137 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2139 else if (uStrCaseCmp(elem.str, "property") == 0)
2144 ERROR("The %s geometry property is not an array\n", field.str);
2145 ACTION("Ignoring illegal property definition\n");
2149 ret = SetGeometryProperty(info, field.str, stmt->value);
2152 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2153 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2154 else if (uStrCaseCmp(elem.str, "solid") == 0)
2157 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2159 dflt = NextDfltDoodad(NULL, info);
2160 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2162 else if (uStrCaseCmp(elem.str, "outline") == 0)
2165 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2167 dflt = NextDfltDoodad(NULL, info);
2168 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2170 else if (uStrCaseCmp(elem.str, "text") == 0)
2173 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2175 dflt = NextDfltDoodad(NULL, info);
2176 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2178 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2181 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2183 dflt = NextDfltDoodad(NULL, info);
2184 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2186 else if (uStrCaseCmp(elem.str, "logo") == 0)
2189 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2191 dflt = NextDfltDoodad(NULL, info);
2192 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2196 WARN("Assignment to field of unknown element\n");
2197 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2205 if ((uStrCaseCmp(field.str, "width") == 0) ||
2206 (uStrCaseCmp(field.str, "widthmm") == 0))
2211 ret = ReportNotArray("keyboard", field.str, "geometry");
2213 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2216 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2218 else if (tmp.ival < 1)
2220 WARN("Keyboard width must be positive\n");
2221 ACTION("Ignoring illegal keyboard width %s\n",
2222 XkbcGeomFPText(tmp.ival));
2226 if (info->widthMM != 0)
2228 WARN("Keyboard width multiply defined\n");
2229 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2230 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2232 info->widthMM = tmp.ival;
2238 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2239 (uStrCaseCmp(field.str, "heightmm") == 0))
2244 ret = ReportNotArray("keyboard", field.str, "geometry");
2246 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2249 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2253 WARN("Keyboard height must be positive\n");
2254 ACTION("Ignoring illegal keyboard height %s\n",
2255 XkbcGeomFPText(tmp.ival));
2259 if (info->heightMM != 0)
2261 WARN("Keyboard height multiply defined\n");
2262 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2263 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2265 info->heightMM = tmp.ival;
2271 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2276 ret = ReportNotArray("keyboard", field.str, "geometry");
2278 else if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2281 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2283 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2286 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2287 ACTION("Ignoring font size in keyboard geometry\n");
2291 info->fontSize = tmp.ival;
2297 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2298 (uStrCaseCmp(field.str, "basecolor") == 0))
2303 ret = ReportNotArray("keyboard", field.str, "geometry");
2305 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2308 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2311 info->baseColor = XkbcInternAtom(tmp.str, False);
2318 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2323 ret = ReportNotArray("keyboard", field.str, "geometry");
2325 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2328 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2331 info->labelColor = XkbcInternAtom(tmp.str, False);
2338 else if (uStrCaseCmp(field.str, "font") == 0)
2340 pField = &info->font;
2342 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2343 (uStrCaseCmp(field.str, "slant") == 0))
2345 pField = &info->fontSlant;
2347 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2348 (uStrCaseCmp(field.str, "weight") == 0))
2350 pField = &info->fontWeight;
2352 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2353 (uStrCaseCmp(field.str, "setwidth") == 0))
2355 pField = &info->fontWeight;
2357 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2358 (uStrCaseCmp(field.str, "encoding") == 0))
2360 pField = &info->fontEncoding;
2362 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2363 (uStrCaseCmp(field.str, "xfontname") == 0))
2365 pField = &info->fontSpec;
2369 ret = SetGeometryProperty(info, field.str, stmt->value);
2374 /* fallthrough for the cases that set pField */
2378 ret = ReportNotArray("keyboard", field.str, "geometry");
2380 else if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2383 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2386 *pField = XkbcInternAtom(tmp.str, False);
2393 /***====================================================================***/
2396 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2397 GeometryInfo * info)
2401 XkbcOutlinePtr outline;
2404 if (def->nOutlines < 1)
2406 WARN("Shape \"%s\" has no outlines\n", shText(si));
2407 ACTION("Definition ignored\n");
2410 si->nOutlines = def->nOutlines;
2411 si->outlines = uTypedCalloc(def->nOutlines, XkbcOutlineRec);
2414 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2415 ACTION("Definition ignored\n");
2419 for (nOut = 0, ol = def->outlines; ol != NULL;
2420 ol = (OutlineDef *) ol->common.next)
2422 if (ol->nPoints < 1)
2424 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2428 outline = &si->outlines[nOut++];
2429 outline->num_points = ol->nPoints;
2430 outline->corner_radius = si->dfltCornerRadius;
2431 outline->points = uTypedCalloc(ol->nPoints, XkbcPointRec);
2432 if (!outline->points)
2434 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2435 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 = XkbcAtomText(ol->field);
2450 if ((uStrCaseCmp(str, "approximation") == 0) ||
2451 (uStrCaseCmp(str, "approx") == 0))
2453 if (si->approx == NULL)
2454 si->approx = outline;
2457 WARN("Multiple approximations for \"%s\"\n",
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 WARN("Multiple primary outlines for \"%s\"\n",
2470 ACTION("Treating all but the first as normal outlines\n");
2475 WARN("Unknown outline type %s for \"%s\"\n", str,
2477 ACTION("Treated as a normal outline\n");
2482 if (nOut != si->nOutlines)
2484 WSGO("Expected %d outlines, got %d\n",
2485 (unsigned int) si->nOutlines, nOut);
2486 si->nOutlines = nOut;
2492 HandleShapeDef(ShapeDef * def, XkbcDescPtr xkb, unsigned merge,
2493 GeometryInfo * info)
2497 if (def->merge != MergeDefault)
2500 bzero(&si, sizeof(ShapeInfo));
2501 si.defs.merge = merge;
2502 si.name = def->name;
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);
2528 new.name = def->name;
2529 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2531 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2532 return 0; /* internal error, already reported */
2533 if (elem.str != NULL)
2535 WARN("Assignment to field of unknown element in doodad %s\n",
2537 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2540 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) {
2546 if (!AddDoodad(si, info, &new))
2548 ClearDoodadInfo(&new);
2552 /***====================================================================***/
2555 HandleOverlayDef(OverlayDef * def,
2556 unsigned merge, SectionInfo * si, GeometryInfo * info)
2558 OverlayKeyDef *keyDef;
2559 OverlayKeyInfo *key;
2562 if ((def->nKeys < 1) && (warningLevel > 3))
2564 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2565 XkbcAtomText(def->name), scText(si));
2566 ACTION("Overlay ignored\n");
2569 bzero(&ol, sizeof(OverlayInfo));
2570 ol.name = def->name;
2571 for (keyDef = def->keys; keyDef;
2572 keyDef = (OverlayKeyDef *) keyDef->common.next)
2574 key = uTypedCalloc(1, OverlayKeyInfo);
2575 if ((!key) && warningLevel > 0)
2577 WSGO("Couldn't allocate OverlayKeyInfo\n");
2578 ACTION("Overlay %s for section %s will be incomplete\n",
2579 XkbcAtomText(ol.name), scText(si));
2582 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2583 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2584 key->sectionRow = _GOK_UnknownRow;
2585 key->overlayRow = _GOK_UnknownRow;
2586 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2587 (CommonInfo *) key);
2590 if (!AddOverlay(si, info, &ol))
2592 ClearOverlayInfo(&ol);
2596 /***====================================================================***/
2599 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2605 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2607 if (expr->op == OpAssign)
2611 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2612 return False; /* internal error, already reported */
2613 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2616 (key, f.str, ndx, expr->value.binary.right, info))
2621 ERROR("Illegal element used in a key definition\n");
2622 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2632 if (!SetKeyField(key, "gap", NULL, expr, info))
2636 if (!SetKeyField(key, "shape", NULL, expr, info))
2640 if (!SetKeyField(key, "name", NULL, expr, info))
2644 ERROR("Cannot determine field for unnamed expression\n");
2645 ACTION("Ignoring key %d in row %d of section %s\n",
2646 row->nKeys + 1, row->section->nRows + 1,
2656 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2657 GeometryInfo * info)
2661 if ((def->nKeys < 1) && (warningLevel > 3))
2663 ERROR("Row in section %s has no keys\n", rowText(row));
2664 ACTION("Section ignored\n");
2667 for (keyDef = def->keys; keyDef != NULL;
2668 keyDef = (KeyDef *) keyDef->common.next)
2670 if (keyDef->common.stmtType == StmtVarDef)
2672 VarDef *var = (VarDef *) keyDef;
2673 ExprResult elem, field;
2675 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2676 return 0; /* internal error, already reported */
2677 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2679 if (!SetRowField(row, field.str, ndx, var->value, info))
2682 else if (uStrCaseCmp(elem.str, "key") == 0)
2685 (&row->dfltKey, field.str, ndx, var->value, info))
2690 WARN("Assignment to field of unknown element in row\n");
2691 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2694 else if (keyDef->common.stmtType == StmtKeyDef)
2697 InitKeyInfo(&key, row, info);
2698 if (keyDef->name != NULL)
2700 int len = strlen(keyDef->name);
2701 if ((len < 1) || (len > XkbKeyNameLength))
2703 ERROR("Illegal name %s for key in section %s\n",
2704 keyDef->name, rowText(row));
2705 ACTION("Section not compiled\n");
2708 bzero(key.name, XkbKeyNameLength + 1);
2709 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2710 key.defs.defined |= _GK_Name;
2712 else if (!HandleComplexKey(keyDef, &key, info))
2714 if (!AddKey(row, &key))
2719 WSGO("Unexpected statement (type %d) in row body\n",
2720 keyDef->common.stmtType);
2728 HandleSectionBody(SectionDef * def,
2729 SectionInfo * si, unsigned merge, GeometryInfo * info)
2734 for (rowDef = def->rows; rowDef != NULL;
2735 rowDef = (RowDef *) rowDef->common.next)
2737 if (rowDef->common.stmtType == StmtVarDef)
2739 VarDef *var = (VarDef *) rowDef;
2740 ExprResult elem, field;
2742 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2743 return 0; /* internal error, already reported */
2744 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2746 if (!SetSectionField(si, field.str, ndx, var->value, info))
2752 else if (uStrCaseCmp(elem.str, "row") == 0)
2755 (&si->dfltRow, field.str, ndx, var->value, info))
2761 else if (uStrCaseCmp(elem.str, "key") == 0)
2763 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2771 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2773 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2781 WARN("Assignment to field of unknown element in section\n");
2782 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2787 else if (rowDef->common.stmtType == StmtRowDef)
2790 InitRowInfo(&row, si, info);
2791 if (!HandleRowBody(rowDef, &row, merge, info))
2793 if (!AddRow(si, &row))
2795 /* ClearRowInfo(&row,info);*/
2797 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2798 (rowDef->common.stmtType == StmtIndicatorMapDef))
2800 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2803 else if (rowDef->common.stmtType == StmtOverlayDef)
2805 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2810 WSGO("Unexpected statement (type %d) in section body\n",
2811 rowDef->common.stmtType);
2815 if (si->nRows != def->nRows)
2817 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2818 (unsigned int) si->nRows);
2819 ACTION("Definition of section %s might be incorrect\n", scText(si));
2825 HandleSectionDef(SectionDef * def,
2826 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2830 if (def->merge != MergeDefault)
2832 InitSectionInfo(&si, info);
2833 si.defs.merge = merge;
2834 si.name = def->name;
2835 if (!HandleSectionBody(def, &si, merge, info))
2837 if (!AddSection(info, &si))
2842 /***====================================================================***/
2845 HandleGeometryFile(XkbFile * file,
2846 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2851 if (merge == MergeDefault)
2852 merge = MergeAugment;
2853 info->name = _XkbDupString(file->name);
2858 switch (stmt->stmtType)
2861 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2862 HandleGeometryFile))
2865 case StmtKeyAliasDef:
2866 if (!HandleAliasDef((KeyAliasDef *) stmt,
2867 merge, info->fileID, &info->aliases))
2873 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2877 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2880 case StmtSectionDef:
2881 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2884 case StmtIndicatorMapDef:
2886 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2891 failWhat = "virtual modfier";
2894 failWhat = "symbol interpretation";
2895 case StmtGroupCompatDef:
2897 failWhat = "group compatibility map";
2898 case StmtKeycodeDef:
2900 failWhat = "key name";
2901 ERROR("Interpretation files may not include other types\n");
2902 ACTION("Ignoring %s definition.\n", failWhat);
2906 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2911 if (info->errorCount > 10)
2914 ERROR("Too many errors\n");
2916 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2923 /***====================================================================***/
2926 CopyShapeDef(XkbcGeometryPtr geom, ShapeInfo * si)
2930 XkbcOutlinePtr old_outline, outline;
2933 si->index = geom->num_shapes;
2935 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2938 WSGO("Couldn't allocate shape in geometry\n");
2939 ACTION("Shape %s not compiled\n", shText(si));
2942 old_outline = si->outlines;
2943 for (i = 0; i < si->nOutlines; i++, old_outline++)
2945 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2948 WSGO("Couldn't allocate outline in shape\n");
2949 ACTION("Shape %s is incomplete\n", shText(si));
2952 n = old_outline->num_points;
2953 memcpy(outline->points, old_outline->points, n * sizeof(XkbcPointRec));
2954 outline->num_points = old_outline->num_points;
2955 outline->corner_radius = old_outline->corner_radius;
2959 n = (si->approx - si->outlines);
2960 shape->approx = &shape->outlines[n];
2964 n = (si->primary - si->outlines);
2965 shape->primary = &shape->outlines[n];
2967 XkbcComputeShapeBounds(shape);
2972 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2974 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2976 if (warningLevel < 9)
2978 ERROR("No position defined for doodad %s\n",
2980 ACTION("Illegal doodad ignored\n");
2984 if ((di->defs.defined & _GD_Priority) == 0)
2986 /* calculate priority -- should be just above previous doodad/row */
2990 case XkbOutlineDoodad:
2991 case XkbSolidDoodad:
2992 if ((di->defs.defined & _GD_Shape) == 0)
2994 ERROR("No shape defined for %s doodad %s\n",
2995 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2997 ACTION("Incomplete definition ignored\n");
3003 si = FindShape(info, di->shape,
3005 XkbOutlineDoodad ? "outline doodad" :
3006 "solid doodad"), ddText(di));
3008 di->shape = si->name;
3011 ERROR("No legal shape for %s\n", ddText(di));
3012 ACTION("Incomplete definition ignored\n");
3016 if ((di->defs.defined & _GD_Color) == 0)
3018 if (warningLevel > 5)
3020 WARN("No color for doodad %s\n", ddText(di));
3021 ACTION("Using black\n");
3023 di->color = XkbcInternAtom("black", False);
3027 if ((di->defs.defined & _GD_Text) == 0)
3029 ERROR("No text specified for text doodad %s\n", ddText(di));
3030 ACTION("Illegal doodad definition ignored\n");
3033 if ((di->defs.defined & _GD_Angle) == 0)
3035 if ((di->defs.defined & _GD_Color) == 0)
3037 if (warningLevel > 5)
3039 WARN("No color specified for doodad %s\n", ddText(di));
3040 ACTION("Using black\n");
3042 di->color = XkbcInternAtom("black", False);
3044 if ((di->defs.defined & _GD_FontSpec) != 0)
3046 if ((di->defs.defined & _GD_FontParts) == 0)
3048 if (warningLevel < 9)
3051 ("Text doodad %s has full and partial font definition\n",
3053 ACTION("Full specification ignored\n");
3055 di->defs.defined &= ~_GD_FontSpec;
3056 di->fontSpec = None;
3058 if ((di->defs.defined & _GD_Font) == 0)
3060 if (warningLevel > 5)
3062 WARN("No font specified for doodad %s\n", ddText(di));
3063 ACTION("Using \"%s\"\n", DFLT_FONT);
3065 di->font = XkbcInternAtom(DFLT_FONT, False);
3067 if ((di->defs.defined & _GD_FontSlant) == 0)
3069 if (warningLevel > 7)
3071 WARN("No font slant for text doodad %s\n", ddText(di));
3072 ACTION("Using \"%s\"\n", DFLT_SLANT);
3074 di->fontSlant = XkbcInternAtom(DFLT_SLANT, False);
3076 if ((di->defs.defined & _GD_FontWeight) == 0)
3078 if (warningLevel > 7)
3080 WARN("No font weight for text doodad %s\n", ddText(di));
3081 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3083 di->fontWeight = XkbcInternAtom(DFLT_WEIGHT, False);
3085 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3087 if (warningLevel > 9)
3089 WARN("No font set width for text doodad %s\n", ddText(di));
3090 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3092 di->fontSetWidth = XkbcInternAtom(DFLT_SET_WIDTH, False);
3094 if ((di->defs.defined & _GD_FontVariant) == 0)
3096 if (warningLevel > 9)
3098 WARN("No font variant for text doodad %s\n", ddText(di));
3099 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3101 di->fontVariant = XkbcInternAtom(DFLT_VARIANT, False);
3103 if ((di->defs.defined & _GD_FontEncoding) == 0)
3105 if (warningLevel > 7)
3107 WARN("No font encoding for doodad %s\n", ddText(di));
3108 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3110 di->fontEncoding = XkbcInternAtom(DFLT_ENCODING, False);
3112 if ((di->defs.defined & _GD_FontSize) == 0)
3114 if (warningLevel > 7)
3116 WARN("No font size for text doodad %s\n", ddText(di));
3117 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3119 di->fontSize = DFLT_SIZE;
3121 if ((di->defs.defined & _GD_Height) == 0)
3123 unsigned size, nLines;
3125 size = (di->fontSize * 120) / 100;
3126 size = (size * 254) / 720; /* convert to mm/10 */
3127 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3133 if (warningLevel > 5)
3135 WARN("No height for text doodad %s\n", ddText(di));
3136 ACTION("Using calculated height %s millimeters\n",
3137 XkbcGeomFPText(size));
3141 if ((di->defs.defined & _GD_Width) == 0)
3143 unsigned width, tmp;
3146 for (str = XkbcAtomText(di->text); *str; str++)
3159 width *= (di->height * 2) / 3;
3160 if (warningLevel > 5)
3162 WARN("No width for text doodad %s\n", ddText(di));
3163 ACTION("Using calculated width %s millimeters\n",
3164 XkbcGeomFPText(width));
3169 case XkbIndicatorDoodad:
3170 if ((di->defs.defined & _GD_Shape) == 0)
3172 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3173 ACTION("Incomplete definition ignored\n");
3179 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3181 di->shape = si->name;
3184 ERROR("No legal shape for doodad %s\n", ddText(di));
3185 ACTION("Incomplete definition ignored\n");
3189 if ((di->defs.defined & _GD_Color) == 0)
3191 if (warningLevel > 5)
3193 WARN("No \"on\" color for indicator doodad %s\n",
3195 ACTION("Using green\n");
3197 di->color = XkbcInternAtom("green", False);
3199 if ((di->defs.defined & _GD_OffColor) == 0)
3201 if (warningLevel > 5)
3203 WARN("No \"off\" color for indicator doodad %s\n",
3205 ACTION("Using black\n");
3207 di->offColor = XkbcInternAtom("black", False);
3211 if (di->logoName == NULL)
3213 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3214 ACTION("Incomplete definition ignored\n");
3217 if ((di->defs.defined & _GD_Shape) == 0)
3219 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3220 ACTION("Incomplete definition ignored\n");
3226 si = FindShape(info, di->shape, "logo doodad",
3229 di->shape = si->name;
3232 ERROR("No legal shape for %s\n", ddText(di));
3233 ACTION("Incomplete definition ignored\n");
3237 if ((di->defs.defined & _GD_Color) == 0)
3239 if (warningLevel > 5)
3241 WARN("No color for doodad %s\n", ddText(di));
3242 ACTION("Using black\n");
3244 di->color = XkbcInternAtom("black", False);
3248 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3249 (unsigned int) di->type);
3255 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3258 FontFromParts(CARD32 fontTok,
3261 CARD32 setWidthTok, CARD32 varTok, int size, CARD32 encodingTok)
3264 char *font, *weight, *slant, *setWidth, *variant, *encoding;
3267 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3268 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3269 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3271 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3272 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3274 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3278 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3279 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3280 rtrn = uCalloc(totalSize, 1);
3282 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3288 CopyDoodadDef(XkbcGeometryPtr geom,
3289 XkbcSectionPtr section, DoodadInfo * di, GeometryInfo * info)
3292 XkbcDoodadPtr doodad;
3297 if (!VerifyDoodadInfo(di, info))
3300 doodad = XkbcAddGeomDoodad(geom, section, name);
3303 WSGO("Couldn't allocate doodad in %s\n",
3304 (section ? "section" : "geometry"));
3305 ACTION("Cannot copy doodad %s\n", ddText(di));
3308 doodad->any.type = di->type;
3309 doodad->any.priority = di->priority;
3310 doodad->any.top = di->top;
3311 doodad->any.left = di->left;
3314 case XkbOutlineDoodad:
3315 case XkbSolidDoodad:
3316 si = FindShape(info, di->shape, NULL, NULL);
3319 doodad->shape.angle = di->angle;
3320 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3322 shape = &geom->shapes[si->index];
3323 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3324 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3327 doodad->text.angle = di->angle;
3328 doodad->text.width = di->width;
3329 doodad->text.height = di->height;
3330 if (di->fontSpec == None)
3331 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3334 di->fontVariant, di->fontSize,
3337 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3338 doodad->text.text = XkbcAtomGetString(di->text);
3339 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3341 XkbSetTextDoodadColor(geom, &doodad->text, color);
3343 case XkbIndicatorDoodad:
3344 si = FindShape(info, di->shape, NULL, NULL);
3347 shape = &geom->shapes[si->index];
3348 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3350 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3351 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3352 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3354 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3357 si = FindShape(info, di->shape, NULL, NULL);
3360 doodad->logo.angle = di->angle;
3361 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3363 shape = &geom->shapes[si->index];
3364 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3365 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3366 doodad->logo.logo_name = di->logoName;
3367 di->logoName = NULL;
3373 /***====================================================================***/
3376 VerifyOverlayInfo(XkbcGeometryPtr geom,
3377 XkbcSectionPtr section,
3379 GeometryInfo * info, short rowMap[256], short rowSize[256])
3381 register OverlayKeyInfo *ki, *next;
3382 unsigned long oKey, uKey, sKey;
3387 /* find out which row each key is in */
3388 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3390 oKey = KeyNameToLong(ki->over);
3391 uKey = KeyNameToLong(ki->under);
3392 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3395 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3398 sKey = KeyNameToLong(key->name.name);
3401 if (warningLevel > 0)
3404 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3405 XkbcKeyNameText(key->name.name),
3406 XkbcAtomText(section->name),
3407 XkbcAtomText(oi->name));
3408 ACTION("Overlay definition ignored\n");
3412 else if (sKey == uKey)
3419 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3422 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3423 XkbcKeyNameText(ki->under),
3424 XkbcAtomText(section->name),
3425 XkbcAtomText(oi->name));
3426 ACTION("Definition ignored\n");
3429 /* now prune out keys that aren't in the section */
3430 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3432 next = (OverlayKeyInfo *) oi->keys->defs.next;
3437 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3439 next = (OverlayKeyInfo *) ki->defs.next;
3440 if (next->sectionRow == _GOK_UnknownRow)
3442 ki->defs.next = next->defs.next;
3445 next = (OverlayKeyInfo *) ki->defs.next;
3450 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3451 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3452 ACTION("Overlay definition ignored\n");
3455 /* now figure out how many rows are defined for the overlay */
3456 bzero(rowSize, sizeof(short) * 256);
3457 for (k = 0; k < 256; k++)
3462 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3464 if (rowMap[ki->sectionRow] == -1)
3465 rowMap[ki->sectionRow] = oi->nRows++;
3466 ki->overlayRow = rowMap[ki->sectionRow];
3467 rowSize[ki->overlayRow]++;
3473 CopyOverlayDef(XkbcGeometryPtr geom,
3474 XkbcSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
3478 XkbcOverlayRowPtr row;
3479 XkbcOverlayKeyPtr key;
3481 short rowMap[256], rowSize[256];
3484 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3487 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3490 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3491 XkbcAtomText(name), XkbcAtomText(section->name));
3494 for (i = 0; i < oi->nRows; i++)
3497 for (tmp = 0, row_under = -1;
3498 (tmp < section->num_rows) && (row_under < 0); tmp++)
3500 if (rowMap[tmp] == i)
3503 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3506 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3507 i, XkbcAtomText(name), XkbcAtomText(section->name));
3511 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3513 row = &ol->rows[ki->overlayRow];
3514 key = &row->keys[row->num_keys++];
3515 bzero(key, sizeof(XkbcOverlayKeyRec));
3516 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3517 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3522 /***====================================================================***/
3525 CopySectionDef(XkbcGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
3527 XkbcSectionPtr section;
3533 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3535 if (section == NULL)
3537 WSGO("Couldn't allocate section in geometry\n");
3538 ACTION("Section %s not compiled\n", scText(si));
3541 section->top = si->top;
3542 section->left = si->left;
3543 section->width = si->width;
3544 section->height = si->height;
3545 section->angle = si->angle;
3546 section->priority = si->priority;
3547 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3549 row = XkbcAddGeomRow(section, ri->nKeys);
3552 WSGO("Couldn't allocate row in section\n");
3553 ACTION("Section %s is incomplete\n", scText(si));
3557 row->left = ri->left;
3558 row->vertical = ri->vertical;
3559 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3562 if ((ki->defs.defined & _GK_Name) == 0)
3564 ERROR("Key %d of row %d in section %s has no name\n",
3565 (int) ki->index, (int) ri->index, scText(si));
3566 ACTION("Section %s ignored\n", scText(si));
3569 key = XkbcAddGeomKey(row);
3572 WSGO("Couldn't allocate key in row\n");
3573 ACTION("Section %s is incomplete\n", scText(si));
3576 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3578 if (ki->shape == None)
3583 si = FindShape(info, ki->shape, "key", keyText(ki));
3586 key->shape_ndx = si->index;
3588 if (ki->color != None)
3590 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3593 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3594 XkbSetKeyColor(geom, key, color);
3597 if (si->doodads != NULL)
3600 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3602 CopyDoodadDef(geom, section, di, info);
3605 if (si->overlays != NULL)
3608 for (oi = si->overlays; oi != NULL;
3609 oi = (OverlayInfo *) oi->defs.next)
3611 CopyOverlayDef(geom, section, oi, info);
3614 if (XkbcComputeSectionBounds(geom, section))
3616 /* 7/6/94 (ef) -- check for negative origin and translate */
3617 if ((si->defs.defined & _GS_Width) == 0)
3618 section->width = section->bounds.x2;
3619 if ((si->defs.defined & _GS_Height) == 0)
3620 section->height = section->bounds.y2;
3625 /***====================================================================***/
3628 CompileGeometry(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
3632 InitGeometryInfo(&info, file->id, merge);
3633 HandleGeometryFile(file, xkb, merge, &info);
3635 if (info.errorCount == 0)
3637 XkbcGeometryPtr geom;
3638 XkbcGeometrySizesRec sizes;
3639 bzero(&sizes, sizeof(sizes));
3640 sizes.which = XkbGeomAllMask;
3641 sizes.num_properties = info.nProps;
3642 sizes.num_colors = 8;
3643 sizes.num_shapes = info.nShapes;
3644 sizes.num_sections = info.nSections;
3645 sizes.num_doodads = info.nDoodads;
3646 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3648 WSGO("Couldn't allocate GeometryRec\n");
3649 ACTION("Geometry not compiled\n");
3654 geom->width_mm = info.widthMM;
3655 geom->height_mm = info.heightMM;
3656 if (info.name != NULL)
3658 geom->name = XkbcInternAtom(info.name, False);
3659 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3660 xkb->names->geometry = geom->name;
3662 if (info.fontSpec != None)
3663 geom->label_font = XkbcAtomGetString(info.fontSpec);
3665 geom->label_font = FontFromParts(info.font, info.fontWeight,
3671 XkbcAddGeomColor(geom, "black", geom->num_colors);
3672 XkbcAddGeomColor(geom, "white", geom->num_colors);
3674 if (info.baseColor == None)
3675 info.baseColor = XkbcInternAtom("white", False);
3676 if (info.labelColor == None)
3677 info.labelColor = XkbcInternAtom("black", False);
3679 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3682 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3688 for (pi = info.props; pi != NULL;
3689 pi = (PropertyInfo *) pi->defs.next)
3691 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3698 for (si = info.shapes; si != NULL;
3699 si = (ShapeInfo *) si->defs.next)
3701 if (!CopyShapeDef(geom, si))
3708 for (si = info.sections; si != NULL;
3709 si = (SectionInfo *) si->defs.next)
3711 if (!CopySectionDef(geom, si, &info))
3718 for (di = info.doodads; di != NULL;
3719 di = (DoodadInfo *) di->defs.next)
3721 if (!CopyDoodadDef(geom, NULL, di, &info))
3726 ApplyAliases(xkb, True, &info.aliases);
3727 ClearGeometryInfo(&info);