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;
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;
162 ((r) ? XkbcAtomText((r)->section->name) : "default")
164 #define _GOK_UnknownRow -1
165 typedef struct _OverlayKeyInfo
170 char over[XkbKeyNameLength + 1];
171 char under[XkbKeyNameLength + 1];
174 typedef struct _OverlayInfo
178 unsigned short nRows;
179 unsigned short nKeys;
180 OverlayKeyInfo *keys;
183 ((o) ? XkbcAtomText((o)->name) : "default")
186 #define _GS_Default (1<<0)
187 #define _GS_Name (1<<1)
188 #define _GS_Top (1<<2)
189 #define _GS_Left (1<<3)
190 #define _GS_Width (1<<4)
191 #define _GS_Height (1<<5)
192 #define _GS_Angle (1<<6)
193 #define _GS_Priority (1<<7)
194 typedef struct _SectionInfo
200 unsigned short width;
201 unsigned short height;
202 unsigned short angle;
203 unsigned short nRows;
204 unsigned short nDoodads;
205 unsigned short nOverlays;
206 unsigned char priority;
207 unsigned char nextDoodadPriority;
211 DoodadInfo *dfltDoodads;
212 OverlayInfo *overlays;
213 struct _GeometryInfo *geometry;
216 ((s) ? XkbcAtomText((s)->name) : "default")
218 typedef struct _GeometryInfo
224 unsigned nextPriority;
231 SectionInfo *sections;
245 int dfltCornerRadius;
246 SectionInfo dfltSection;
247 DoodadInfo *dfltDoodads;
252 ddText(DoodadInfo * di)
258 strcpy(buf, "default");
263 sprintf(buf, "%s in section %s",
264 XkbcAtomText(di->name), scText(di->section));
267 return XkbcAtomText(di->name);
270 /***====================================================================***/
273 InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
275 pi->defs.defined = 0;
276 pi->defs.fileID = info->fileID;
277 pi->defs.merge = info->merge;
278 pi->name = pi->value = NULL;
283 FreeProperties(PropertyInfo * pi, GeometryInfo * info)
288 if (info->props == pi)
293 for (tmp = pi; tmp != NULL; tmp = next)
299 tmp->name = tmp->value = NULL;
300 next = (PropertyInfo *) tmp->defs.next;
307 InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
310 if (key != &row->dfltKey)
313 strcpy(key->name, "unknown");
314 key->defs.defined &= ~_GK_Default;
318 bzero(key, sizeof(KeyInfo));
319 strcpy(key->name, "default");
320 key->defs.defined = _GK_Default;
321 key->defs.fileID = info->fileID;
322 key->defs.merge = info->merge;
323 key->defs.next = NULL;
330 ClearKeyInfo(KeyInfo * key)
332 key->defs.defined &= ~_GK_Default;
333 strcpy(key->name, "default");
341 FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
346 if (row->keys == key)
351 for (tmp = key; tmp != NULL; tmp = next)
354 next = (KeyInfo *) tmp->defs.next;
361 InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
363 if (row != §ion->dfltRow)
365 *row = section->dfltRow;
366 row->defs.defined &= ~_GR_Default;
370 bzero(row, sizeof(RowInfo *));
371 row->defs.defined = _GR_Default;
372 row->defs.fileID = info->fileID;
373 row->defs.merge = info->merge;
374 row->defs.next = NULL;
375 row->section = section;
378 InitKeyInfo(&row->dfltKey, row, info);
384 ClearRowInfo(RowInfo * row, GeometryInfo * info)
386 row->defs.defined &= ~_GR_Default;
387 row->top = row->left = 0;
388 row->vertical = False;
391 FreeKeys(row->keys, row, info);
392 ClearKeyInfo(&row->dfltKey);
393 row->dfltKey.defs.defined |= _GK_Default;
398 FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
403 if (row == section->rows)
406 section->rows = NULL;
408 for (tmp = row; tmp != NULL; tmp = next)
410 ClearRowInfo(tmp, info);
411 next = (RowInfo *) tmp->defs.next;
418 FindDoodadByType(DoodadInfo * di, unsigned type)
422 if (di->type == type)
424 di = (DoodadInfo *) di->defs.next;
430 FindDoodadByName(DoodadInfo * di, Atom name)
434 if (di->name == name)
436 di = (DoodadInfo *) di->defs.next;
442 InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
448 if (si && si->dfltDoodads)
449 dflt = FindDoodadByType(si->dfltDoodads, type);
450 if ((dflt == NULL) && (info->dfltDoodads))
451 dflt = FindDoodadByType(info->dfltDoodads, type);
455 di->defs.next = NULL;
459 bzero(di, sizeof(DoodadInfo));
460 di->defs.fileID = info->fileID;
466 di->priority = si->nextDoodadPriority++;
467 #if XkbGeomMaxPriority < 255
468 if (si->nextDoodadPriority > XkbGeomMaxPriority)
469 si->nextDoodadPriority = XkbGeomMaxPriority;
474 di->priority = info->nextPriority++;
475 if (info->nextPriority > XkbGeomMaxPriority)
476 info->nextPriority = XkbGeomMaxPriority;
482 ClearDoodadInfo(DoodadInfo * di)
487 bzero(di, sizeof(DoodadInfo));
489 di->defs.defined = 0;
494 ClearOverlayInfo(OverlayInfo * ol)
498 ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
505 FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
512 if (si->doodads == di)
517 if (si->dfltDoodads == di)
518 si->dfltDoodads = NULL;
520 if (info->doodads == di)
522 info->doodads = NULL;
525 if (info->dfltDoodads == di)
526 info->dfltDoodads = NULL;
527 for (tmp = di; tmp != NULL; tmp = next)
529 next = (DoodadInfo *) tmp->defs.next;
530 ClearDoodadInfo(tmp);
537 InitSectionInfo(SectionInfo * si, GeometryInfo * info)
539 if (si != &info->dfltSection)
541 *si = info->dfltSection;
542 si->defs.defined &= ~_GS_Default;
543 si->name = XkbcInternAtom("unknown", False);
544 si->priority = info->nextPriority++;
545 if (info->nextPriority > XkbGeomMaxPriority)
546 info->nextPriority = XkbGeomMaxPriority;
550 bzero(si, sizeof(SectionInfo));
551 si->defs.fileID = info->fileID;
552 si->defs.merge = info->merge;
553 si->defs.next = NULL;
555 si->name = XkbcInternAtom("default", False);
556 InitRowInfo(&si->dfltRow, si, info);
562 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
568 into->defs.fileID = defs.fileID;
569 into->defs.merge = defs.merge;
570 into->defs.next = NULL;
571 into->dfltRow.defs.fileID = defs.fileID;
572 into->dfltRow.defs.merge = defs.merge;
573 into->dfltRow.defs.next = NULL;
574 into->dfltRow.section = into;
575 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
576 into->dfltRow.dfltKey.defs.merge = defs.merge;
577 into->dfltRow.dfltKey.defs.next = NULL;
578 into->dfltRow.dfltKey.row = &into->dfltRow;
583 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
586 si->defs.defined &= ~_GS_Default;
587 si->name = XkbcInternAtom("default", False);
588 si->top = si->left = 0;
589 si->width = si->height = 0;
593 FreeRows(si->rows, si, info);
596 ClearRowInfo(&si->dfltRow, info);
599 FreeDoodads(si->doodads, si, info);
602 si->dfltRow.defs.defined = _GR_Default;
607 FreeSections(SectionInfo * si, GeometryInfo * info)
612 if (si == info->sections)
615 info->sections = NULL;
617 for (tmp = si; tmp != NULL; tmp = next)
619 ClearSectionInfo(tmp, info);
620 next = (SectionInfo *) tmp->defs.next;
627 FreeShapes(ShapeInfo * si, GeometryInfo * info)
632 if (si == info->shapes)
637 for (tmp = si; tmp != NULL; tmp = next)
642 for (i = 0; i < tmp->nOutlines; i++)
644 if (tmp->outlines[i].points != NULL)
646 uFree(tmp->outlines[i].points);
647 tmp->outlines[i].num_points = 0;
648 tmp->outlines[i].points = NULL;
651 uFree(tmp->outlines);
654 tmp->outlines = NULL;
655 tmp->primary = tmp->approx = NULL;
657 next = (ShapeInfo *) tmp->defs.next;
663 /***====================================================================***/
666 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
668 bzero(info, sizeof(GeometryInfo));
669 info->fileID = fileID;
671 InitSectionInfo(&info->dfltSection, info);
672 info->dfltSection.defs.defined = _GS_Default;
677 ClearGeometryInfo(GeometryInfo * info)
683 FreeProperties(info->props, info);
685 FreeShapes(info->shapes, info);
687 FreeSections(info->sections, info);
690 info->dfltCornerRadius = 0;
691 ClearSectionInfo(&info->dfltSection, info);
692 info->dfltSection.defs.defined = _GS_Default;
694 ClearAliases(&info->aliases);
698 /***====================================================================***/
700 static PropertyInfo *
701 NextProperty(GeometryInfo * info)
705 pi = uTypedAlloc(PropertyInfo);
708 bzero((char *) pi, sizeof(PropertyInfo));
709 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
716 static PropertyInfo *
717 FindProperty(GeometryInfo * info, char *name)
723 for (old = info->props; old != NULL;
724 old = (PropertyInfo *) old->defs.next)
726 if ((old->name) && (uStringEqual(name, old->name)))
733 AddProperty(GeometryInfo * info, PropertyInfo * new)
737 if ((!new) || (!new->value) || (!new->name))
739 old = FindProperty(info, new->name);
742 if ((new->defs.merge == MergeReplace)
743 || (new->defs.merge == MergeOverride))
745 if (((old->defs.fileID == new->defs.fileID)
746 && (warningLevel > 0)) || (warningLevel > 9))
748 WARN("Multiple definitions for the \"%s\" property\n",
750 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
755 old->value = uStringDup(new->value);
758 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
759 || (warningLevel > 9))
761 WARN("Multiple definitions for \"%s\" property\n", new->name);
762 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
768 if ((new = NextProperty(info)) == NULL)
770 new->defs.next = NULL;
771 new->name = uStringDup(old->name);
772 new->value = uStringDup(old->value);
776 /***====================================================================***/
779 NextShape(GeometryInfo * info)
783 si = uTypedAlloc(ShapeInfo);
786 bzero((char *) si, sizeof(ShapeInfo));
787 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
790 si->dfltCornerRadius = info->dfltCornerRadius;
796 FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
800 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
802 if (name == old->name)
808 WARN("Unknown shape \"%s\" for %s %s\n",
809 XkbcAtomText(name), type, which);
812 ACTION("Using default shape %s instead\n", shText(old));
815 ACTION("No default shape; definition ignored\n");
822 AddShape(GeometryInfo * info, ShapeInfo * new)
826 old = FindShape(info, new->name, NULL, NULL);
829 if ((new->defs.merge == MergeReplace)
830 || (new->defs.merge == MergeOverride))
832 ShapeInfo *next = (ShapeInfo *) old->defs.next;
833 if (((old->defs.fileID == new->defs.fileID)
834 && (warningLevel > 0)) || (warningLevel > 9))
836 WARN("Duplicate shape name \"%s\"\n", shText(old));
837 ACTION("Using last definition\n");
840 old->defs.next = &next->defs;
843 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
844 || (warningLevel > 9))
846 WARN("Multiple shapes named \"%s\"\n", shText(old));
847 ACTION("Using first definition\n");
852 if ((new = NextShape(info)) == NULL)
855 new->defs.next = NULL;
856 old->szOutlines = old->nOutlines = 0;
857 old->outlines = NULL;
863 /***====================================================================***/
866 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
870 next = into->defs.next;
871 ClearDoodadInfo(into);
873 into->defs.next = next;
874 next = from->defs.next;
875 ClearDoodadInfo(from);
876 from->defs.next = next;
881 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
885 di = uTypedCalloc(1, DoodadInfo);
891 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
897 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
904 NextDoodad(SectionInfo * si, GeometryInfo * info)
908 di = uTypedCalloc(1, DoodadInfo);
913 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
920 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
929 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
933 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
936 if ((new->defs.merge == MergeReplace)
937 || (new->defs.merge == MergeOverride))
939 if (((old->defs.fileID == new->defs.fileID)
940 && (warningLevel > 0)) || (warningLevel > 9))
942 WARN("Multiple doodads named \"%s\"\n",
943 XkbcAtomText(old->name));
944 ACTION("Using last definition\n");
946 ReplaceDoodad(old, new);
950 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
951 || (warningLevel > 9))
953 WARN("Multiple doodads named \"%s\"\n",
954 XkbcAtomText(old->name));
955 ACTION("Using first definition\n");
960 if ((new = NextDoodad(si, info)) == NULL)
962 ReplaceDoodad(new, old);
964 new->defs.next = NULL;
969 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
974 if (uStrCaseCmp(name, "outline") == 0)
975 type = XkbOutlineDoodad;
976 else if (uStrCaseCmp(name, "solid") == 0)
977 type = XkbSolidDoodad;
978 else if (uStrCaseCmp(name, "text") == 0)
979 type = XkbTextDoodad;
980 else if (uStrCaseCmp(name, "indicator") == 0)
981 type = XkbIndicatorDoodad;
982 else if (uStrCaseCmp(name, "logo") == 0)
983 type = XkbLogoDoodad;
986 if ((si) && (si->dfltDoodads))
987 dflt = FindDoodadByType(si->dfltDoodads, type);
990 if ((!dflt) && (info->dfltDoodads))
991 dflt = FindDoodadByType(info->dfltDoodads, type);
994 dflt = NextDfltDoodad(si, info);
1004 /***====================================================================***/
1007 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1011 for (old = si->overlays; old != NULL;
1012 old = (OverlayInfo *) old->defs.next)
1014 if (old->name == new->name)
1019 if ((new->defs.merge == MergeReplace)
1020 || (new->defs.merge == MergeOverride))
1022 if (((old->defs.fileID == new->defs.fileID)
1023 && (warningLevel > 0)) || (warningLevel > 9))
1026 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1027 XkbcAtomText(old->name), XkbcAtomText(si->name));
1028 ACTION("Using last definition\n");
1030 ClearOverlayInfo(old);
1031 old->nKeys = new->nKeys;
1032 old->keys = new->keys;
1037 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1038 || (warningLevel > 9))
1040 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1041 XkbcAtomText(old->name), XkbcAtomText(si->name));
1042 ACTION("Using first definition\n");
1047 new = uTypedCalloc(1, OverlayInfo);
1050 if (warningLevel > 0)
1052 WSGO("Couldn't allocate a new OverlayInfo\n");
1054 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1055 XkbcAtomText(old->name), XkbcAtomText(si->name));
1062 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1063 (CommonInfo *) new);
1068 /***====================================================================***/
1070 static SectionInfo *
1071 NextSection(GeometryInfo * info)
1075 si = uTypedAlloc(SectionInfo);
1078 *si = info->dfltSection;
1079 si->defs.defined &= ~_GS_Default;
1080 si->defs.next = NULL;
1084 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1091 static SectionInfo *
1092 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1096 for (old = info->sections; old != NULL;
1097 old = (SectionInfo *) old->defs.next)
1099 if (new->name == old->name)
1106 AddSection(GeometryInfo * info, SectionInfo * new)
1110 old = FindMatchingSection(info, new);
1114 if ((new->defs.merge == MergeReplace)
1115 || (new->defs.merge == MergeOverride))
1117 SectionInfo *next = (SectionInfo *) old->defs.next;
1118 if (((old->defs.fileID == new->defs.fileID)
1119 && (warningLevel > 0)) || (warningLevel > 9))
1121 WARN("Duplicate shape name \"%s\"\n", shText(old));
1122 ACTION("Using last definition\n");
1125 old->defs.next = &next->defs;
1128 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1129 || (warningLevel > 9))
1131 WARN("Multiple shapes named \"%s\"\n", shText(old));
1132 ACTION("Using first definition\n");
1136 WARN("Don't know how to merge sections yet\n");
1140 if ((new = NextSection(info)) == NULL)
1143 new->defs.next = NULL;
1144 old->nRows = old->nDoodads = old->nOverlays = 0;
1146 old->doodads = NULL;
1147 old->overlays = NULL;
1151 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1159 /***====================================================================***/
1162 NextRow(SectionInfo * si)
1166 row = uTypedAlloc(RowInfo);
1170 row->defs.defined &= ~_GR_Default;
1171 row->defs.next = NULL;
1175 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1176 row->index = si->nRows++;
1182 AddRow(SectionInfo * si, RowInfo * new)
1187 if ((new = NextRow(si)) == NULL)
1190 new->defs.next = NULL;
1196 /***====================================================================***/
1199 NextKey(RowInfo * row)
1203 key = uTypedAlloc(KeyInfo);
1206 *key = row->dfltKey;
1207 key->defs.defined &= ~_GK_Default;
1208 key->defs.next = NULL;
1209 key->index = row->nKeys++;
1215 AddKey(RowInfo * row, KeyInfo * new)
1220 if ((new = NextKey(row)) == NULL)
1223 new->defs.next = NULL;
1225 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1229 /***====================================================================***/
1232 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1237 if (from->errorCount > 0)
1239 into->errorCount += from->errorCount;
1242 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1243 if (into->name == NULL)
1245 into->name = from->name;
1248 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1249 into->widthMM = from->widthMM;
1250 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1251 into->heightMM = from->heightMM;
1252 if ((into->font == None) || ((from->font != None) && clobber))
1253 into->font = from->font;
1254 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1255 into->fontSlant = from->fontSlant;
1256 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1257 into->fontWeight = from->fontWeight;
1258 if ((into->fontSetWidth == None)
1259 || ((from->fontSetWidth != None) && clobber))
1260 into->fontSetWidth = from->fontSetWidth;
1261 if ((into->fontVariant == None)
1262 || ((from->fontVariant != None) && clobber))
1263 into->fontVariant = from->fontVariant;
1264 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1265 into->fontSize = from->fontSize;
1266 if ((into->fontEncoding == None)
1267 || ((from->fontEncoding != None) && clobber))
1268 into->fontEncoding = from->fontEncoding;
1269 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1270 into->fontSpec = from->fontSpec;
1271 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1272 into->baseColor = from->baseColor;
1273 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1274 into->labelColor = from->labelColor;
1275 into->nextPriority = from->nextPriority;
1276 if (from->props != NULL)
1279 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1281 if (!AddProperty(into, pi))
1285 if (from->shapes != NULL)
1289 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1291 if (!AddShape(into, si))
1295 if (from->sections != NULL)
1299 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1301 if (!AddSection(into, si))
1305 if (from->doodads != NULL)
1309 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1311 if (!AddDoodad(NULL, into, di))
1315 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1320 typedef void (*FileHandler) (XkbFile * /* file */ ,
1321 XkbcDescPtr /* xkb */ ,
1322 unsigned /* merge */ ,
1323 GeometryInfo * /* info */
1327 HandleIncludeGeometry(IncludeStmt * stmt, XkbcDescPtr xkb, GeometryInfo * info,
1332 GeometryInfo included;
1336 if ((stmt->file == NULL) && (stmt->map == NULL))
1340 bzero(info, sizeof(GeometryInfo));
1342 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1344 InitGeometryInfo(&included, rtrn->id, newMerge);
1345 included.nextPriority = info->nextPriority;
1346 included.dfltCornerRadius = info->dfltCornerRadius;
1347 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1348 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1349 if (stmt->stmt != NULL)
1351 if (included.name != NULL)
1352 uFree(included.name);
1353 included.name = stmt->stmt;
1359 info->errorCount += 10;
1362 if ((stmt->next != NULL) && (included.errorCount < 1))
1366 GeometryInfo next_incl;
1368 for (next = stmt->next; next != NULL; next = next->next)
1370 if ((next->file == NULL) && (next->map == NULL))
1373 MergeIncludedGeometry(&included, info, next->merge);
1374 ClearGeometryInfo(info);
1376 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1378 InitGeometryInfo(&next_incl, rtrn->id, op);
1379 next_incl.nextPriority = included.nextPriority;
1380 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1381 DupSectionInfo(&next_incl.dfltSection,
1382 &included.dfltSection, &included);
1383 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1384 MergeIncludedGeometry(&included, &next_incl, op);
1385 ClearGeometryInfo(&next_incl);
1389 info->errorCount += 10;
1398 MergeIncludedGeometry(info, &included, newMerge);
1399 ClearGeometryInfo(&included);
1401 return (info->errorCount == 0);
1405 SetShapeField(ShapeInfo * si,
1407 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1411 if ((uStrCaseCmp(field, "radius") == 0)
1412 || (uStrCaseCmp(field, "corner") == 0)
1413 || (uStrCaseCmp(field, "cornerradius") == 0))
1415 if (arrayNdx != NULL)
1418 return ReportNotArray("key shape", field, shText(si));
1420 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1423 return ReportBadType("key shape", field, shText(si), "number");
1426 si->dfltCornerRadius = tmp.ival;
1428 info->dfltCornerRadius = tmp.ival;
1432 return ReportBadField("key shape", field, shText(si));
1436 SetShapeDoodadField(DoodadInfo * di,
1439 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1442 const char *typeName;
1445 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1446 if ((!uStrCaseCmp(field, "corner"))
1447 || (!uStrCaseCmp(field, "cornerradius")))
1449 if (arrayNdx != NULL)
1452 return ReportNotArray(typeName, field, ddText(di));
1454 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1457 return ReportBadType(typeName, field, ddText(di), "number");
1459 di->defs.defined |= _GD_Corner;
1460 di->corner = tmp.ival;
1463 else if (uStrCaseCmp(field, "angle") == 0)
1465 if (arrayNdx != NULL)
1468 return ReportNotArray(typeName, field, ddText(di));
1470 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1473 return ReportBadType(typeName, field, ddText(di), "number");
1475 di->defs.defined |= _GD_Angle;
1476 di->angle = tmp.ival;
1479 else if (uStrCaseCmp(field, "shape") == 0)
1481 if (arrayNdx != NULL)
1484 return ReportNotArray(typeName, field, ddText(di));
1486 if (!ExprResolveString(value, &tmp, NULL, NULL))
1489 return ReportBadType(typeName, field, ddText(di), "string");
1491 di->shape = XkbcInternAtom(tmp.str, False);
1492 di->defs.defined |= _GD_Shape;
1495 return ReportBadField(typeName, field, ddText(di));
1498 #define FIELD_STRING 0
1499 #define FIELD_SHORT 1
1500 #define FIELD_USHORT 2
1503 SetTextDoodadField(DoodadInfo * di,
1506 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1511 char *typeName = "text doodad";
1516 unsigned short *uval;
1519 if (uStrCaseCmp(field, "angle") == 0)
1521 if (arrayNdx != NULL)
1524 return ReportNotArray(typeName, field, ddText(di));
1526 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1529 return ReportBadType(typeName, field, ddText(di), "number");
1531 di->defs.defined |= _GD_Angle;
1532 di->angle = tmp.ival;
1535 if (uStrCaseCmp(field, "width") == 0)
1537 type = FIELD_USHORT;
1538 pField.uval = &di->width;
1541 else if (uStrCaseCmp(field, "height") == 0)
1543 type = FIELD_USHORT;
1544 pField.uval = &di->height;
1547 else if (uStrCaseCmp(field, "text") == 0)
1549 type = FIELD_STRING;
1550 pField.str = &di->text;
1553 else if (uStrCaseCmp(field, "font") == 0)
1555 type = FIELD_STRING;
1556 pField.str = &di->font;
1559 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1560 (uStrCaseCmp(field, "slant") == 0))
1562 type = FIELD_STRING;
1563 pField.str = &di->fontSlant;
1564 def = _GD_FontSlant;
1566 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1567 (uStrCaseCmp(field, "weight") == 0))
1569 type = FIELD_STRING;
1570 pField.str = &di->fontWeight;
1571 def = _GD_FontWeight;
1573 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1574 (uStrCaseCmp(field, "setwidth") == 0))
1576 type = FIELD_STRING;
1577 pField.str = &di->fontSetWidth;
1578 def = _GD_FontSetWidth;
1580 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1581 (uStrCaseCmp(field, "variant") == 0))
1583 type = FIELD_STRING;
1584 pField.str = &di->fontVariant;
1585 def = _GD_FontVariant;
1587 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1588 (uStrCaseCmp(field, "encoding") == 0))
1590 type = FIELD_STRING;
1591 pField.str = &di->fontEncoding;
1592 def = _GD_FontEncoding;
1594 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1595 (uStrCaseCmp(field, "xfontname") == 0))
1597 type = FIELD_STRING;
1598 pField.str = &di->fontSpec;
1601 else if (uStrCaseCmp(field, "fontsize") == 0)
1603 type = FIELD_USHORT;
1604 pField.uval = &di->fontSize;
1609 return ReportBadField(typeName, field, ddText(di));
1611 if (arrayNdx != NULL)
1614 return ReportNotArray(typeName, field, ddText(di));
1616 if (type == FIELD_STRING)
1618 if (!ExprResolveString(value, &tmp, NULL, NULL))
1621 return ReportBadType(typeName, field, ddText(di), "string");
1623 di->defs.defined |= def;
1624 *pField.str = XkbcInternAtom(tmp.str, False);
1628 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1631 return ReportBadType(typeName, field, ddText(di), "number");
1633 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1637 ReportBadType(typeName, field, ddText(di), "unsigned");
1639 di->defs.defined |= def;
1640 if (type == FIELD_USHORT)
1641 *pField.uval = tmp.uval;
1643 *pField.ival = tmp.ival;
1649 SetIndicatorDoodadField(DoodadInfo * di,
1653 SectionInfo * si, GeometryInfo * info)
1657 if ((uStrCaseCmp(field, "oncolor") == 0)
1658 || (uStrCaseCmp(field, "offcolor") == 0)
1659 || (uStrCaseCmp(field, "shape") == 0))
1661 if (arrayNdx != NULL)
1664 return ReportNotArray("indicator doodad", field, ddText(di));
1666 if (!ExprResolveString(value, &tmp, NULL, NULL))
1669 return ReportBadType("indicator doodad", field,
1670 ddText(di), "string");
1672 if (uStrCaseCmp(field, "oncolor") == 0)
1674 di->defs.defined |= _GD_Color;
1675 di->color = XkbcInternAtom(tmp.str, False);
1677 else if (uStrCaseCmp(field, "offcolor") == 0)
1679 di->defs.defined |= _GD_OffColor;
1680 di->offColor = XkbcInternAtom(tmp.str, False);
1682 else if (uStrCaseCmp(field, "shape") == 0)
1684 di->defs.defined |= _GD_Shape;
1685 di->shape = XkbcInternAtom(tmp.str, False);
1689 return ReportBadField("indicator doodad", field, ddText(di));
1693 SetLogoDoodadField(DoodadInfo * di,
1696 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1699 char *typeName = "logo doodad";
1701 if ((!uStrCaseCmp(field, "corner"))
1702 || (!uStrCaseCmp(field, "cornerradius")))
1704 if (arrayNdx != NULL)
1707 return ReportNotArray(typeName, field, ddText(di));
1709 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1712 return ReportBadType(typeName, field, ddText(di), "number");
1714 di->defs.defined |= _GD_Corner;
1715 di->corner = tmp.ival;
1718 else if (uStrCaseCmp(field, "angle") == 0)
1720 if (arrayNdx != NULL)
1723 return ReportNotArray(typeName, field, ddText(di));
1725 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1728 return ReportBadType(typeName, field, ddText(di), "number");
1730 di->defs.defined |= _GD_Angle;
1731 di->angle = tmp.ival;
1734 else if (uStrCaseCmp(field, "shape") == 0)
1736 if (arrayNdx != NULL)
1739 return ReportNotArray(typeName, field, ddText(di));
1741 if (!ExprResolveString(value, &tmp, NULL, NULL))
1744 return ReportBadType(typeName, field, ddText(di), "string");
1746 di->shape = XkbcInternAtom(tmp.str, False);
1747 di->defs.defined |= _GD_Shape;
1750 else if ((!uStrCaseCmp(field, "logoname"))
1751 || (!uStrCaseCmp(field, "name")))
1753 if (arrayNdx != NULL)
1756 return ReportNotArray(typeName, field, ddText(di));
1758 if (!ExprResolveString(value, &tmp, NULL, NULL))
1761 return ReportBadType(typeName, field, ddText(di),
1764 di->logoName = uStringDup(tmp.str);
1767 return ReportBadField(typeName, field, ddText(di));
1771 SetDoodadField(DoodadInfo * di,
1774 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1778 if (uStrCaseCmp(field, "priority") == 0)
1780 if (arrayNdx != NULL)
1783 return ReportNotArray("doodad", field, ddText(di));
1785 if (!ExprResolveInteger(value, &tmp, NULL, NULL))
1788 return ReportBadType("doodad", field, ddText(di), "integer");
1790 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1793 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1794 tmp.ival, XkbGeomMaxPriority);
1795 ACTION("Priority for doodad %s not changed", ddText(di));
1798 di->defs.defined |= _GD_Priority;
1799 di->priority = tmp.ival;
1802 else if (uStrCaseCmp(field, "left") == 0)
1804 if (arrayNdx != NULL)
1807 return ReportNotArray("doodad", field, ddText(di));
1809 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1812 return ReportBadType("doodad", field, ddText(di), "number");
1814 di->defs.defined |= _GD_Left;
1815 di->left = tmp.ival;
1818 else if (uStrCaseCmp(field, "top") == 0)
1820 if (arrayNdx != NULL)
1823 return ReportNotArray("doodad", field, ddText(di));
1825 if (!ExprResolveFloat(value, &tmp, NULL, NULL))
1828 return ReportBadType("doodad", field, ddText(di), "number");
1830 di->defs.defined |= _GD_Top;
1834 else if (uStrCaseCmp(field, "color") == 0)
1836 if (arrayNdx != NULL)
1839 return ReportNotArray("doodad", field, ddText(di));
1841 if (!ExprResolveString(value, &tmp, NULL, NULL))
1844 return ReportBadType("doodad", field, ddText(di), "string");
1846 di->defs.defined |= _GD_Color;
1847 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);
2050 else if ((uStrCaseCmp(field, "color") == 0) ||
2051 (uStrCaseCmp(field, "keycolor") == 0))
2053 if (arrayNdx != NULL)
2056 return ReportNotArray("key", field, keyText(key));
2058 if (!ExprResolveString(value, &tmp, NULL, NULL))
2061 return ReportBadType("key", field, keyText(key), "string");
2063 key->defs.defined |= _GK_Color;
2064 key->color = XkbcInternAtom(tmp.str, False);
2066 else if ((uStrCaseCmp(field, "name") == 0)
2067 || (uStrCaseCmp(field, "keyname") == 0))
2069 if (arrayNdx != NULL)
2072 return ReportNotArray("key", field, keyText(key));
2074 if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
2077 return ReportBadType("key", field, keyText(key), "key name");
2079 key->defs.defined |= _GK_Name;
2080 bzero(key->name, XkbKeyNameLength + 1);
2081 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2086 return ReportBadField("key", field, keyText(key));
2092 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2097 InitPropertyInfo(&pi, info);
2099 if (!ExprResolveString(value, &result, NULL, NULL))
2102 ERROR("Property values must be type string\n");
2103 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2106 pi.value = result.str;
2107 return AddProperty(info, &pi);
2111 HandleGeometryVar(VarDef * stmt, XkbcDescPtr xkb, GeometryInfo * info)
2113 ExprResult elem, field, tmp;
2118 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2119 return 0; /* internal error, already reported */
2120 if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0))
2121 return SetShapeField(NULL, field.str, ndx, stmt->value, info);
2122 if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
2123 return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2124 field.str, ndx, stmt->value, info);
2125 if (elem.str && (uStrCaseCmp(elem.str, "row") == 0))
2126 return SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2128 if (elem.str && (uStrCaseCmp(elem.str, "section") == 0))
2130 return SetSectionField(&info->dfltSection, field.str, ndx,
2133 if (elem.str && (uStrCaseCmp(elem.str, "property") == 0))
2138 ERROR("The %s geometry property is not an array\n", field.str);
2139 ACTION("Ignoring illegal property definition\n");
2142 return SetGeometryProperty(info, field.str, stmt->value);
2145 && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL))
2147 return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2149 if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0))
2152 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2154 dflt = NextDfltDoodad(NULL, info);
2155 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2157 if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0))
2160 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2162 dflt = NextDfltDoodad(NULL, info);
2163 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2165 if (elem.str && (uStrCaseCmp(elem.str, "text") == 0))
2168 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2170 dflt = NextDfltDoodad(NULL, info);
2171 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2173 if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
2176 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2178 dflt = NextDfltDoodad(NULL, info);
2179 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2181 if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0))
2184 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2186 dflt = NextDfltDoodad(NULL, info);
2187 return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2191 WARN("Assignment to field of unknown element\n");
2192 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2196 if ((uStrCaseCmp(field.str, "width") == 0) ||
2197 (uStrCaseCmp(field.str, "widthmm") == 0))
2202 return ReportNotArray("keyboard", field.str, "geometry");
2204 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2207 return ReportBadType("keyboard", field.str, "geometry", "number");
2211 WARN("Keyboard width must be positive\n");
2212 ACTION("Ignoring illegal keyboard width %s\n",
2213 XkbcGeomFPText(tmp.ival));
2216 if (info->widthMM != 0)
2218 WARN("Keyboard width multiply defined\n");
2219 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2220 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2222 info->widthMM = tmp.ival;
2225 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2226 (uStrCaseCmp(field.str, "heightmm") == 0))
2231 return ReportNotArray("keyboard", field.str, "geometry");
2233 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2236 return ReportBadType("keyboard", field.str, "geometry", "number");
2240 WARN("Keyboard height must be positive\n");
2241 ACTION("Ignoring illegal keyboard height %s\n",
2242 XkbcGeomFPText(tmp.ival));
2245 if (info->heightMM != 0)
2247 WARN("Keyboard height multiply defined\n");
2248 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2249 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2251 info->heightMM = tmp.ival;
2254 else if (uStrCaseCmp(field.str, "font") == 0)
2256 pField = &info->font;
2258 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2259 (uStrCaseCmp(field.str, "slant") == 0))
2261 pField = &info->fontSlant;
2263 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2264 (uStrCaseCmp(field.str, "weight") == 0))
2266 pField = &info->fontWeight;
2268 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2269 (uStrCaseCmp(field.str, "setwidth") == 0))
2271 pField = &info->fontWeight;
2273 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2274 (uStrCaseCmp(field.str, "encoding") == 0))
2276 pField = &info->fontEncoding;
2278 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2279 (uStrCaseCmp(field.str, "xfontname") == 0))
2281 pField = &info->fontSpec;
2283 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2288 return ReportNotArray("keyboard", field.str, "geometry");
2290 if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
2293 return ReportBadType("keyboard", field.str, "geometry", "number");
2295 if ((tmp.ival < 40) || (tmp.ival > 2550))
2298 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2299 ACTION("Ignoring font size in keyboard geometry\n");
2302 info->fontSize = tmp.ival;
2305 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2306 (uStrCaseCmp(field.str, "basecolor") == 0))
2311 return ReportNotArray("keyboard", field.str, "geometry");
2313 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2316 return ReportBadType("keyboard", field.str, "geometry", "string");
2318 info->baseColor = XkbcInternAtom(tmp.str, False);
2321 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2326 return ReportNotArray("keyboard", field.str, "geometry");
2328 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2331 return ReportBadType("keyboard", field.str, "geometry", "string");
2333 info->labelColor = XkbcInternAtom(tmp.str, False);
2338 return SetGeometryProperty(info, field.str, stmt->value);
2344 return ReportNotArray("keyboard", field.str, "geometry");
2346 if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
2349 return ReportBadType("keyboard", field.str, "geometry", "string");
2351 *pField = XkbcInternAtom(tmp.str, False);
2355 /***====================================================================***/
2358 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2359 GeometryInfo * info)
2363 XkbOutlinePtr outline;
2366 if (def->nOutlines < 1)
2368 WARN("Shape \"%s\" has no outlines\n", shText(si));
2369 ACTION("Definition ignored\n");
2372 si->nOutlines = def->nOutlines;
2373 si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
2376 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2377 ACTION("Definition ignored\n");
2381 for (nOut = 0, ol = def->outlines; ol != NULL;
2382 ol = (OutlineDef *) ol->common.next)
2384 if (ol->nPoints < 1)
2386 SetShapeField(si, XkbcAtomGetString(ol->field), NULL,
2391 outline = &si->outlines[nOut++];
2392 outline->num_points = ol->nPoints;
2393 outline->corner_radius = si->dfltCornerRadius;
2394 outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
2395 if (!outline->points)
2397 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2398 ACTION("Definition ignored\n");
2402 for (nPt = 0, pt = ol->points; pt != NULL;
2403 pt = (ExprDef *) pt->common.next)
2405 outline->points[nPt].x = pt->value.coord.x;
2406 outline->points[nPt].y = pt->value.coord.y;
2409 if (ol->field != None)
2411 char *str = XkbcAtomText(ol->field);
2412 if ((uStrCaseCmp(str, "approximation") == 0) ||
2413 (uStrCaseCmp(str, "approx") == 0))
2415 if (si->approx == NULL)
2416 si->approx = outline;
2419 WARN("Multiple approximations for \"%s\"\n",
2421 ACTION("Treating all but the first as normal outlines\n");
2424 else if (uStrCaseCmp(str, "primary") == 0)
2426 if (si->primary == NULL)
2427 si->primary = outline;
2430 WARN("Multiple primary outlines for \"%s\"\n",
2432 ACTION("Treating all but the first as normal outlines\n");
2437 WARN("Unknown outline type %s for \"%s\"\n", str,
2439 ACTION("Treated as a normal outline\n");
2443 if (nOut != si->nOutlines)
2445 WSGO("Expected %d outlines, got %d\n",
2446 (unsigned int) si->nOutlines, nOut);
2447 si->nOutlines = nOut;
2453 HandleShapeDef(ShapeDef * def, XkbcDescPtr xkb, unsigned merge,
2454 GeometryInfo * info)
2458 if (def->merge != MergeDefault)
2461 bzero(&si, sizeof(ShapeInfo));
2462 si.defs.merge = merge;
2464 XkbcInternAtom(XkbcAtomGetString(def->name), False);
2465 si.dfltCornerRadius = info->dfltCornerRadius;
2466 if (!HandleShapeBody(def, &si, merge, info))
2468 if (!AddShape(info, &si))
2473 /***====================================================================***/
2476 HandleDoodadDef(DoodadDef * def,
2477 unsigned merge, SectionInfo * si, GeometryInfo * info)
2479 ExprResult elem, field;
2484 if (def->common.stmtType == StmtIndicatorMapDef)
2486 def->common.stmtType = StmtDoodadDef;
2487 def->type = XkbIndicatorDoodad;
2489 InitDoodadInfo(&new, def->type, si, info);
2491 XkbcInternAtom(XkbcAtomGetString(def->name), False);
2492 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
2494 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2495 return 0; /* internal error, already reported */
2496 if (elem.str != NULL)
2498 WARN("Assignment to field of unknown element in doodad %s\n",
2500 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2502 else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info))
2505 if (!AddDoodad(si, info, &new))
2507 ClearDoodadInfo(&new);
2511 /***====================================================================***/
2514 HandleOverlayDef(OverlayDef * def,
2515 unsigned merge, SectionInfo * si, GeometryInfo * info)
2517 OverlayKeyDef *keyDef;
2518 OverlayKeyInfo *key;
2521 if ((def->nKeys < 1) && (warningLevel > 3))
2523 WARN("Overlay \"%s\" in section \"%s\" has no keys\n",
2524 XkbcAtomText(def->name), scText(si));
2525 ACTION("Overlay ignored\n");
2528 bzero(&ol, sizeof(OverlayInfo));
2530 XkbcInternAtom(XkbcAtomGetString(def->name), False);
2531 for (keyDef = def->keys; keyDef;
2532 keyDef = (OverlayKeyDef *) keyDef->common.next)
2534 key = uTypedCalloc(1, OverlayKeyInfo);
2535 if ((!key) && warningLevel > 0)
2537 WSGO("Couldn't allocate OverlayKeyInfo\n");
2538 ACTION("Overlay %s for section %s will be incomplete\n",
2539 XkbcAtomText(ol.name), scText(si));
2542 strncpy(key->over, keyDef->over, XkbKeyNameLength);
2543 strncpy(key->under, keyDef->under, XkbKeyNameLength);
2544 key->sectionRow = _GOK_UnknownRow;
2545 key->overlayRow = _GOK_UnknownRow;
2546 ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
2547 (CommonInfo *) key);
2550 if (!AddOverlay(si, info, &ol))
2552 ClearOverlayInfo(&ol);
2556 /***====================================================================***/
2559 HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
2565 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2567 if (expr->op == OpAssign)
2571 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2572 return False; /* internal error, already reported */
2573 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2576 (key, f.str, ndx, expr->value.binary.right, info))
2581 ERROR("Illegal element used in a key definition\n");
2582 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2592 if (!SetKeyField(key, "gap", NULL, expr, info))
2596 if (!SetKeyField(key, "shape", NULL, expr, info))
2600 if (!SetKeyField(key, "name", NULL, expr, info))
2604 ERROR("Cannot determine field for unnamed expression\n");
2605 ACTION("Ignoring key %d in row %d of section %s\n",
2606 row->nKeys + 1, row->section->nRows + 1,
2616 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2617 GeometryInfo * info)
2621 if ((def->nKeys < 1) && (warningLevel > 3))
2623 ERROR("Row in section %s has no keys\n", rowText(row));
2624 ACTION("Section ignored\n");
2627 for (keyDef = def->keys; keyDef != NULL;
2628 keyDef = (KeyDef *) keyDef->common.next)
2630 if (keyDef->common.stmtType == StmtVarDef)
2632 VarDef *var = (VarDef *) keyDef;
2633 ExprResult elem, field;
2635 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2636 return 0; /* internal error, already reported */
2637 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2639 if (!SetRowField(row, field.str, ndx, var->value, info))
2642 else if (uStrCaseCmp(elem.str, "key") == 0)
2645 (&row->dfltKey, field.str, ndx, var->value, info))
2650 WARN("Assignment to field of unknown element in row\n");
2651 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2654 else if (keyDef->common.stmtType == StmtKeyDef)
2657 InitKeyInfo(&key, row, info);
2658 if (keyDef->name != NULL)
2660 int len = strlen(keyDef->name);
2661 if ((len < 1) || (len > XkbKeyNameLength))
2663 ERROR("Illegal name %s for key in section %s\n",
2664 keyDef->name, rowText(row));
2665 ACTION("Section not compiled\n");
2668 bzero(key.name, XkbKeyNameLength + 1);
2669 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2670 key.defs.defined |= _GK_Name;
2672 else if (!HandleComplexKey(keyDef, &key, info))
2674 if (!AddKey(row, &key))
2679 WSGO("Unexpected statement (type %d) in row body\n",
2680 keyDef->common.stmtType);
2688 HandleSectionBody(SectionDef * def,
2689 SectionInfo * si, unsigned merge, GeometryInfo * info)
2694 for (rowDef = def->rows; rowDef != NULL;
2695 rowDef = (RowDef *) rowDef->common.next)
2697 if (rowDef->common.stmtType == StmtVarDef)
2699 VarDef *var = (VarDef *) rowDef;
2700 ExprResult elem, field;
2702 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2703 return 0; /* internal error, already reported */
2704 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2706 if (!SetSectionField(si, field.str, ndx, var->value, info))
2709 else if (uStrCaseCmp(elem.str, "row") == 0)
2712 (&si->dfltRow, field.str, ndx, var->value, info))
2715 else if (uStrCaseCmp(elem.str, "key") == 0)
2717 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2722 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2724 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2729 WARN("Assignment to field of unknown element in section\n");
2730 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2733 else if (rowDef->common.stmtType == StmtRowDef)
2736 InitRowInfo(&row, si, info);
2737 if (!HandleRowBody(rowDef, &row, merge, info))
2739 if (!AddRow(si, &row))
2741 /* ClearRowInfo(&row,info);*/
2743 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2744 (rowDef->common.stmtType == StmtIndicatorMapDef))
2746 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2749 else if (rowDef->common.stmtType == StmtOverlayDef)
2751 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2756 WSGO("Unexpected statement (type %d) in section body\n",
2757 rowDef->common.stmtType);
2761 if (si->nRows != def->nRows)
2763 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2764 (unsigned int) si->nRows);
2765 ACTION("Definition of section %s might be incorrect\n", scText(si));
2771 HandleSectionDef(SectionDef * def,
2772 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2777 if (def->merge != MergeDefault)
2779 InitSectionInfo(&si, info);
2780 si.defs.merge = merge;
2781 str = XkbcAtomGetString(def->name);
2782 if ((str == NULL) || (strlen(str) < 1))
2784 ERROR("Section defined without a name\n");
2785 ACTION("Definition ignored\n");
2789 XkbcInternAtom(XkbcAtomGetString(def->name), False);
2790 if (!HandleSectionBody(def, &si, merge, info))
2792 if (!AddSection(info, &si))
2797 /***====================================================================***/
2800 HandleGeometryFile(XkbFile * file,
2801 XkbcDescPtr xkb, unsigned merge, GeometryInfo * info)
2806 if (merge == MergeDefault)
2807 merge = MergeAugment;
2808 info->name = uStringDup(file->name);
2813 switch (stmt->stmtType)
2816 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2817 HandleGeometryFile))
2820 case StmtKeyAliasDef:
2821 if (!HandleAliasDef((KeyAliasDef *) stmt,
2822 merge, info->fileID, &info->aliases))
2828 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2832 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2835 case StmtSectionDef:
2836 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2839 case StmtIndicatorMapDef:
2841 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2846 failWhat = "virtual modfier";
2849 failWhat = "symbol interpretation";
2850 case StmtGroupCompatDef:
2852 failWhat = "group compatibility map";
2853 case StmtKeycodeDef:
2855 failWhat = "key name";
2856 ERROR("Interpretation files may not include other types\n");
2857 ACTION("Ignoring %s definition.\n", failWhat);
2861 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2866 if (info->errorCount > 10)
2869 ERROR("Too many errors\n");
2871 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2878 /***====================================================================***/
2881 CopyShapeDef(XkbGeometryPtr geom, ShapeInfo * si)
2885 XkbOutlinePtr old_outline, outline;
2888 si->index = geom->num_shapes;
2889 name = XkbcInternAtom(XkbcAtomGetString(si->name), False);
2890 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2893 WSGO("Couldn't allocate shape in geometry\n");
2894 ACTION("Shape %s not compiled\n", shText(si));
2897 old_outline = si->outlines;
2898 for (i = 0; i < si->nOutlines; i++, old_outline++)
2900 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2903 WSGO("Couldn't allocate outline in shape\n");
2904 ACTION("Shape %s is incomplete\n", shText(si));
2907 n = old_outline->num_points;
2908 memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec));
2909 outline->num_points = old_outline->num_points;
2910 outline->corner_radius = old_outline->corner_radius;
2914 n = (si->approx - si->outlines);
2915 shape->approx = &shape->outlines[n];
2919 n = (si->primary - si->outlines);
2920 shape->primary = &shape->outlines[n];
2922 XkbcComputeShapeBounds(shape);
2927 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2929 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2931 if (warningLevel < 9)
2933 ERROR("No position defined for doodad %s\n",
2935 ACTION("Illegal doodad ignored\n");
2939 if ((di->defs.defined & _GD_Priority) == 0)
2941 /* calculate priority -- should be just above previous doodad/row */
2945 case XkbOutlineDoodad:
2946 case XkbSolidDoodad:
2947 if ((di->defs.defined & _GD_Shape) == 0)
2949 ERROR("No shape defined for %s doodad %s\n",
2950 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
2952 ACTION("Incomplete definition ignored\n");
2958 si = FindShape(info, di->shape,
2960 XkbOutlineDoodad ? "outline doodad" :
2961 "solid doodad"), ddText(di));
2963 di->shape = si->name;
2966 ERROR("No legal shape for %s\n", ddText(di));
2967 ACTION("Incomplete definition ignored\n");
2971 if ((di->defs.defined & _GD_Color) == 0)
2973 if (warningLevel > 5)
2975 WARN("No color for doodad %s\n", ddText(di));
2976 ACTION("Using black\n");
2978 di->color = XkbcInternAtom("black", False);
2982 if ((di->defs.defined & _GD_Text) == 0)
2984 ERROR("No text specified for text doodad %s\n", ddText(di));
2985 ACTION("Illegal doodad definition ignored\n");
2988 if ((di->defs.defined & _GD_Angle) == 0)
2990 if ((di->defs.defined & _GD_Color) == 0)
2992 if (warningLevel > 5)
2994 WARN("No color specified for doodad %s\n", ddText(di));
2995 ACTION("Using black\n");
2997 di->color = XkbcInternAtom("black", False);
2999 if ((di->defs.defined & _GD_FontSpec) != 0)
3001 if ((di->defs.defined & _GD_FontParts) == 0)
3003 if (warningLevel < 9)
3006 ("Text doodad %s has full and partial font definition\n",
3008 ACTION("Full specification ignored\n");
3010 di->defs.defined &= ~_GD_FontSpec;
3011 di->fontSpec = None;
3013 if ((di->defs.defined & _GD_Font) == 0)
3015 if (warningLevel > 5)
3017 WARN("No font specified for doodad %s\n", ddText(di));
3018 ACTION("Using \"%s\"\n", DFLT_FONT);
3020 di->font = XkbcInternAtom(DFLT_FONT, False);
3022 if ((di->defs.defined & _GD_FontSlant) == 0)
3024 if (warningLevel > 7)
3026 WARN("No font slant for text doodad %s\n", ddText(di));
3027 ACTION("Using \"%s\"\n", DFLT_SLANT);
3029 di->fontSlant = XkbcInternAtom(DFLT_SLANT, False);
3031 if ((di->defs.defined & _GD_FontWeight) == 0)
3033 if (warningLevel > 7)
3035 WARN("No font weight for text doodad %s\n", ddText(di));
3036 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3038 di->fontWeight = XkbcInternAtom(DFLT_WEIGHT, False);
3040 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3042 if (warningLevel > 9)
3044 WARN("No font set width for text doodad %s\n", ddText(di));
3045 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3047 di->fontSetWidth = XkbcInternAtom(DFLT_SET_WIDTH, False);
3049 if ((di->defs.defined & _GD_FontVariant) == 0)
3051 if (warningLevel > 9)
3053 WARN("No font variant for text doodad %s\n", ddText(di));
3054 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3056 di->fontVariant = XkbcInternAtom(DFLT_VARIANT, False);
3058 if ((di->defs.defined & _GD_FontEncoding) == 0)
3060 if (warningLevel > 7)
3062 WARN("No font encoding for doodad %s\n", ddText(di));
3063 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3065 di->fontEncoding = XkbcInternAtom(DFLT_ENCODING, False);
3067 if ((di->defs.defined & _GD_FontSize) == 0)
3069 if (warningLevel > 7)
3071 WARN("No font size for text doodad %s\n", ddText(di));
3072 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3074 di->fontSize = DFLT_SIZE;
3076 if ((di->defs.defined & _GD_Height) == 0)
3078 unsigned size, nLines;
3080 size = (di->fontSize * 120) / 100;
3081 size = (size * 254) / 720; /* convert to mm/10 */
3082 for (nLines = 1, tmp = XkbcAtomGetString(di->text); *tmp;
3089 if (warningLevel > 5)
3091 WARN("No height for text doodad %s\n", ddText(di));
3092 ACTION("Using calculated height %s millimeters\n",
3093 XkbcGeomFPText(size));
3097 if ((di->defs.defined & _GD_Width) == 0)
3099 unsigned width, tmp;
3102 for (str = XkbcAtomGetString(di->text); *str; str++)
3115 width *= (di->height * 2) / 3;
3116 if (warningLevel > 5)
3118 WARN("No width for text doodad %s\n", ddText(di));
3119 ACTION("Using calculated width %s millimeters\n",
3120 XkbcGeomFPText(width));
3125 case XkbIndicatorDoodad:
3126 if ((di->defs.defined & _GD_Shape) == 0)
3128 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3129 ACTION("Incomplete definition ignored\n");
3135 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3137 di->shape = si->name;
3140 ERROR("No legal shape for doodad %s\n", ddText(di));
3141 ACTION("Incomplete definition ignored\n");
3145 if ((di->defs.defined & _GD_Color) == 0)
3147 if (warningLevel > 5)
3149 WARN("No \"on\" color for indicator doodad %s\n",
3151 ACTION("Using green\n");
3153 di->color = XkbcInternAtom("green", False);
3155 if ((di->defs.defined & _GD_OffColor) == 0)
3157 if (warningLevel > 5)
3159 WARN("No \"off\" color for indicator doodad %s\n",
3161 ACTION("Using black\n");
3163 di->offColor = XkbcInternAtom("black", False);
3167 if (di->logoName == NULL)
3169 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3170 ACTION("Incomplete definition ignored\n");
3173 if ((di->defs.defined & _GD_Shape) == 0)
3175 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3176 ACTION("Incomplete definition ignored\n");
3182 si = FindShape(info, di->shape, "logo doodad",
3185 di->shape = si->name;
3188 ERROR("No legal shape for %s\n", ddText(di));
3189 ACTION("Incomplete definition ignored\n");
3193 if ((di->defs.defined & _GD_Color) == 0)
3195 if (warningLevel > 5)
3197 WARN("No color for doodad %s\n", ddText(di));
3198 ACTION("Using black\n");
3200 di->color = XkbcInternAtom("black", False);
3204 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3205 (unsigned int) di->type);
3211 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3214 FontFromParts(Atom fontTok,
3217 Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
3220 char *font, *weight, *slant, *setWidth, *variant, *encoding;
3223 font = (fontTok != None ? XkbcAtomGetString(fontTok) : DFLT_FONT);
3225 (weightTok != None ? XkbcAtomGetString(weightTok) : DFLT_WEIGHT);
3227 (slantTok != None ? XkbcAtomGetString(slantTok) : DFLT_SLANT);
3230 None ? XkbcAtomGetString(setWidthTok) : DFLT_SET_WIDTH);
3232 (varTok != None ? XkbcAtomGetString(varTok) : DFLT_VARIANT);
3235 None ? XkbcAtomGetString(encodingTok) : DFLT_ENCODING);
3239 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3240 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3241 rtrn = uCalloc(totalSize, 1);
3244 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3251 CopyDoodadDef(XkbGeometryPtr geom,
3252 XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info)
3255 XkbDoodadPtr doodad;
3260 if (!VerifyDoodadInfo(di, info))
3262 name = XkbcInternAtom(XkbcAtomGetString(di->name), False);
3263 doodad = XkbcAddGeomDoodad(geom, section, name);
3266 WSGO("Couldn't allocate doodad in %s\n",
3267 (section ? "section" : "geometry"));
3268 ACTION("Cannot copy doodad %s\n", ddText(di));
3271 doodad->any.type = di->type;
3272 doodad->any.priority = di->priority;
3273 doodad->any.top = di->top;
3274 doodad->any.left = di->left;
3277 case XkbOutlineDoodad:
3278 case XkbSolidDoodad:
3279 si = FindShape(info, di->shape, NULL, NULL);
3282 doodad->shape.angle = di->angle;
3284 XkbcAddGeomColor(geom, XkbcAtomGetString(di->color),
3286 shape = &geom->shapes[si->index];
3287 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3288 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3291 doodad->text.angle = di->angle;
3292 doodad->text.width = di->width;
3293 doodad->text.height = di->height;
3294 if (di->fontSpec == None)
3295 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3298 di->fontVariant, di->fontSize,
3301 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3302 doodad->text.text = XkbcAtomGetString(di->text);
3304 XkbcAddGeomColor(geom, XkbcAtomGetString(di->color),
3306 XkbSetTextDoodadColor(geom, &doodad->text, color);
3308 case XkbIndicatorDoodad:
3309 si = FindShape(info, di->shape, NULL, NULL);
3312 shape = &geom->shapes[si->index];
3314 XkbcAddGeomColor(geom, XkbcAtomGetString(di->color),
3316 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3317 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3319 XkbcAddGeomColor(geom, XkbcAtomGetString(di->offColor),
3321 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3324 si = FindShape(info, di->shape, NULL, NULL);
3327 doodad->logo.angle = di->angle;
3329 XkbcAddGeomColor(geom, XkbcAtomGetString(di->color),
3331 shape = &geom->shapes[si->index];
3332 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3333 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3334 doodad->logo.logo_name = di->logoName;
3335 di->logoName = NULL;
3341 /***====================================================================***/
3344 VerifyOverlayInfo(XkbGeometryPtr geom,
3345 XkbSectionPtr section,
3347 GeometryInfo * info, short rowMap[256], short rowSize[256])
3349 register OverlayKeyInfo *ki, *next;
3350 unsigned long oKey, uKey, sKey;
3355 /* find out which row each key is in */
3356 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3358 oKey = KeyNameToLong(ki->over);
3359 uKey = KeyNameToLong(ki->under);
3360 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3363 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3366 sKey = KeyNameToLong(key->name.name);
3369 if (warningLevel > 0)
3372 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3373 XkbcKeyNameText(key->name.name),
3374 XkbcAtomText(section->name),
3375 XkbcAtomText(oi->name));
3376 ACTION("Overlay definition ignored\n");
3380 else if (sKey == uKey)
3387 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3390 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3391 XkbcKeyNameText(ki->under),
3392 XkbcAtomText(section->name),
3393 XkbcAtomText(oi->name));
3394 ACTION("Definition ignored\n");
3397 /* now prune out keys that aren't in the section */
3398 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3400 next = (OverlayKeyInfo *) oi->keys->defs.next;
3405 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3407 next = (OverlayKeyInfo *) ki->defs.next;
3408 if (next->sectionRow == _GOK_UnknownRow)
3410 ki->defs.next = next->defs.next;
3413 next = (OverlayKeyInfo *) ki->defs.next;
3418 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3419 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3420 ACTION("Overlay definition ignored\n");
3423 /* now figure out how many rows are defined for the overlay */
3424 bzero(rowSize, sizeof(short) * 256);
3425 for (k = 0; k < 256; k++)
3430 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3432 if (rowMap[ki->sectionRow] == -1)
3433 rowMap[ki->sectionRow] = oi->nRows++;
3434 ki->overlayRow = rowMap[ki->sectionRow];
3435 rowSize[ki->overlayRow]++;
3441 CopyOverlayDef(XkbGeometryPtr geom,
3442 XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
3446 XkbOverlayRowPtr row;
3447 XkbOverlayKeyPtr key;
3449 short rowMap[256], rowSize[256];
3452 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3454 name = XkbcInternAtom(XkbcAtomGetString(oi->name), False);
3455 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3458 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3459 XkbcAtomText(name), XkbcAtomText(section->name));
3462 for (i = 0; i < oi->nRows; i++)
3465 for (tmp = 0, row_under = -1;
3466 (tmp < section->num_rows) && (row_under < 0); tmp++)
3468 if (rowMap[tmp] == i)
3471 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3474 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3475 i, XkbcAtomText(name), XkbcAtomText(section->name));
3479 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3481 row = &ol->rows[ki->overlayRow];
3482 key = &row->keys[row->num_keys++];
3483 bzero(key, sizeof(XkbOverlayKeyRec));
3484 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3485 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3490 /***====================================================================***/
3493 CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
3495 XkbSectionPtr section;
3502 name = XkbcInternAtom(XkbcAtomGetString(si->name), False);
3504 XkbcAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays);
3505 if (section == NULL)
3507 WSGO("Couldn't allocate section in geometry\n");
3508 ACTION("Section %s not compiled\n", scText(si));
3511 section->top = si->top;
3512 section->left = si->left;
3513 section->width = si->width;
3514 section->height = si->height;
3515 section->angle = si->angle;
3516 section->priority = si->priority;
3517 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3519 row = XkbcAddGeomRow(section, ri->nKeys);
3522 WSGO("Couldn't allocate row in section\n");
3523 ACTION("Section %s is incomplete\n", scText(si));
3527 row->left = ri->left;
3528 row->vertical = ri->vertical;
3529 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3532 if ((ki->defs.defined & _GK_Name) == 0)
3534 ERROR("Key %d of row %d in section %s has no name\n",
3535 (int) ki->index, (int) ri->index, scText(si));
3536 ACTION("Section %s ignored\n", scText(si));
3539 key = XkbcAddGeomKey(row);
3542 WSGO("Couldn't allocate key in row\n");
3543 ACTION("Section %s is incomplete\n", scText(si));
3546 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3548 if (ki->shape == None)
3553 si = FindShape(info, ki->shape, "key", keyText(ki));
3556 key->shape_ndx = si->index;
3558 if (ki->color != None)
3560 XkbcAddGeomColor(geom,
3561 XkbcAtomGetString(ki->color),
3564 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3565 XkbSetKeyColor(geom, key, color);
3568 if (si->doodads != NULL)
3571 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3573 CopyDoodadDef(geom, section, di, info);
3576 if (si->overlays != NULL)
3579 for (oi = si->overlays; oi != NULL;
3580 oi = (OverlayInfo *) oi->defs.next)
3582 CopyOverlayDef(geom, section, oi, info);
3585 if (XkbcComputeSectionBounds(geom, section))
3587 /* 7/6/94 (ef) -- check for negative origin and translate */
3588 if ((si->defs.defined & _GS_Width) == 0)
3589 section->width = section->bounds.x2;
3590 if ((si->defs.defined & _GS_Height) == 0)
3591 section->height = section->bounds.y2;
3596 /***====================================================================***/
3599 CompileGeometry(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
3603 InitGeometryInfo(&info, file->id, merge);
3604 HandleGeometryFile(file, xkb, merge, &info);
3606 if (info.errorCount == 0)
3608 XkbGeometryPtr geom;
3609 XkbGeometrySizesRec sizes;
3610 bzero(&sizes, sizeof(sizes));
3611 sizes.which = XkbGeomAllMask;
3612 sizes.num_properties = info.nProps;
3613 sizes.num_colors = 8;
3614 sizes.num_shapes = info.nShapes;
3615 sizes.num_sections = info.nSections;
3616 sizes.num_doodads = info.nDoodads;
3617 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3619 WSGO("Couldn't allocate GeometryRec\n");
3620 ACTION("Geometry not compiled\n");
3625 geom->width_mm = info.widthMM;
3626 geom->height_mm = info.heightMM;
3627 if (info.name != NULL)
3629 geom->name = XkbcInternAtom(info.name, False);
3630 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3631 xkb->names->geometry = geom->name;
3633 if (info.fontSpec != None)
3635 uStringDup(XkbcAtomGetString(info.fontSpec));
3637 geom->label_font = FontFromParts(info.font, info.fontWeight,
3643 XkbcAddGeomColor(geom, "black", geom->num_colors);
3644 XkbcAddGeomColor(geom, "white", geom->num_colors);
3646 if (info.baseColor == None)
3647 info.baseColor = XkbcInternAtom("white", False);
3648 if (info.labelColor == None)
3649 info.labelColor = XkbcInternAtom("black", False);
3651 XkbcAddGeomColor(geom, XkbcAtomGetString(info.baseColor),
3654 XkbcAddGeomColor(geom, XkbcAtomGetString(info.labelColor),
3660 for (pi = info.props; pi != NULL;
3661 pi = (PropertyInfo *) pi->defs.next)
3663 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3670 for (si = info.shapes; si != NULL;
3671 si = (ShapeInfo *) si->defs.next)
3673 if (!CopyShapeDef(geom, si))
3680 for (si = info.sections; si != NULL;
3681 si = (SectionInfo *) si->defs.next)
3683 if (!CopySectionDef(geom, si, &info))
3690 for (di = info.doodads; di != NULL;
3691 di = (DoodadInfo *) di->defs.next)
3693 if (!CopyDoodadDef(geom, NULL, di, &info))
3698 ApplyAliases(xkb, True, &info.aliases);
3699 ClearGeometryInfo(&info);