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 ********************************************************/
34 #include "indicators.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 struct xkb_outline * outlines;
65 struct xkb_outline * approx;
66 struct xkb_outline * 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;
115 uint32_t fontSetWidth;
116 uint32_t fontVariant;
117 unsigned short fontSize;
118 uint32_t fontEncoding;
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;
238 uint32_t fontSetWidth;
239 uint32_t fontVariant;
241 uint32_t fontEncoding;
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, uint32_t 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 = xkb_intern_atom("unknown");
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 = xkb_intern_atom("default");
556 InitRowInfo(&si->dfltRow, si, info);
562 DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
568 into->defs.next = NULL;
569 into->dfltRow.defs.fileID = defs.fileID;
570 into->dfltRow.defs.merge = defs.merge;
571 into->dfltRow.defs.next = NULL;
572 into->dfltRow.section = into;
573 into->dfltRow.dfltKey.defs.fileID = defs.fileID;
574 into->dfltRow.dfltKey.defs.merge = defs.merge;
575 into->dfltRow.dfltKey.defs.next = NULL;
576 into->dfltRow.dfltKey.row = &into->dfltRow;
581 ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
584 si->defs.defined &= ~_GS_Default;
585 si->name = xkb_intern_atom("default");
586 si->top = si->left = 0;
587 si->width = si->height = 0;
591 FreeRows(si->rows, si, info);
594 ClearRowInfo(&si->dfltRow, info);
597 FreeDoodads(si->doodads, si, info);
600 si->dfltRow.defs.defined = _GR_Default;
605 FreeSections(SectionInfo * si, GeometryInfo * info)
610 if (si == info->sections)
613 info->sections = NULL;
615 for (tmp = si; tmp != NULL; tmp = next)
617 ClearSectionInfo(tmp, info);
618 next = (SectionInfo *) tmp->defs.next;
625 FreeShapes(ShapeInfo * si, GeometryInfo * info)
630 if (si == info->shapes)
635 for (tmp = si; tmp != NULL; tmp = next)
640 for (i = 0; i < tmp->nOutlines; i++)
642 if (tmp->outlines[i].points != NULL)
644 free(tmp->outlines[i].points);
645 tmp->outlines[i].num_points = 0;
646 tmp->outlines[i].points = NULL;
652 tmp->outlines = NULL;
653 tmp->primary = tmp->approx = NULL;
655 next = (ShapeInfo *) tmp->defs.next;
661 /***====================================================================***/
664 InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
666 bzero(info, sizeof(GeometryInfo));
667 info->fileID = fileID;
669 InitSectionInfo(&info->dfltSection, info);
670 info->dfltSection.defs.defined = _GS_Default;
675 ClearGeometryInfo(GeometryInfo * info)
681 FreeProperties(info->props, info);
683 FreeShapes(info->shapes, info);
685 FreeSections(info->sections, info);
688 info->dfltCornerRadius = 0;
689 ClearSectionInfo(&info->dfltSection, info);
690 info->dfltSection.defs.defined = _GS_Default;
692 ClearAliases(&info->aliases);
696 /***====================================================================***/
698 static PropertyInfo *
699 NextProperty(GeometryInfo * info)
703 pi = uTypedAlloc(PropertyInfo);
706 bzero((char *) pi, sizeof(PropertyInfo));
707 info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
714 static PropertyInfo *
715 FindProperty(GeometryInfo * info, char *name)
721 for (old = info->props; old != NULL;
722 old = (PropertyInfo *) old->defs.next)
724 if ((old->name) && (uStringEqual(name, old->name)))
731 AddProperty(GeometryInfo * info, PropertyInfo * new)
735 if ((!new) || (!new->value) || (!new->name))
737 old = FindProperty(info, new->name);
740 if ((new->defs.merge == MergeReplace)
741 || (new->defs.merge == MergeOverride))
743 if (((old->defs.fileID == new->defs.fileID)
744 && (warningLevel > 0)) || (warningLevel > 9))
746 WARN("Multiple definitions for the \"%s\" property\n",
748 ACTION("Ignoring \"%s\", using \"%s\"\n", old->value,
753 old->value = _XkbDupString(new->value);
756 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
757 || (warningLevel > 9))
759 WARN("Multiple definitions for \"%s\" property\n", new->name);
760 ACTION("Using \"%s\", ignoring \"%s\" \n", old->value,
766 if ((new = NextProperty(info)) == NULL)
768 new->defs.next = NULL;
769 new->name = _XkbDupString(old->name);
770 new->value = _XkbDupString(old->value);
774 /***====================================================================***/
777 NextShape(GeometryInfo * info)
781 si = uTypedAlloc(ShapeInfo);
784 bzero((char *) si, sizeof(ShapeInfo));
785 info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
788 si->dfltCornerRadius = info->dfltCornerRadius;
794 FindShape(GeometryInfo * info, uint32_t name, const char *type, const char *which)
798 for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
800 if (name == old->name)
806 WARN("Unknown shape \"%s\" for %s %s\n",
807 XkbcAtomText(name), type, which);
810 ACTION("Using default shape %s instead\n", shText(old));
813 ACTION("No default shape; definition ignored\n");
820 AddShape(GeometryInfo * info, ShapeInfo * new)
824 old = FindShape(info, new->name, NULL, NULL);
827 if ((new->defs.merge == MergeReplace)
828 || (new->defs.merge == MergeOverride))
830 ShapeInfo *next = (ShapeInfo *) old->defs.next;
831 if (((old->defs.fileID == new->defs.fileID)
832 && (warningLevel > 0)) || (warningLevel > 9))
834 WARN("Duplicate shape name \"%s\"\n", shText(old));
835 ACTION("Using last definition\n");
838 old->defs.next = &next->defs;
841 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
842 || (warningLevel > 9))
844 WARN("Multiple shapes named \"%s\"\n", shText(old));
845 ACTION("Using first definition\n");
850 if ((new = NextShape(info)) == NULL)
853 new->defs.next = NULL;
854 old->szOutlines = old->nOutlines = 0;
855 old->outlines = NULL;
861 /***====================================================================***/
864 ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
868 next = into->defs.next;
869 ClearDoodadInfo(into);
871 into->defs.next = next;
872 next = from->defs.next;
873 ClearDoodadInfo(from);
874 from->defs.next = next;
879 NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
883 di = uTypedCalloc(1, DoodadInfo);
889 (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
895 (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
902 NextDoodad(SectionInfo * si, GeometryInfo * info)
906 di = uTypedCalloc(1, DoodadInfo);
911 si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
918 (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
927 AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
931 old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
934 if ((new->defs.merge == MergeReplace)
935 || (new->defs.merge == MergeOverride))
937 if (((old->defs.fileID == new->defs.fileID)
938 && (warningLevel > 0)) || (warningLevel > 9))
940 WARN("Multiple doodads named \"%s\"\n",
941 XkbcAtomText(old->name));
942 ACTION("Using last definition\n");
944 ReplaceDoodad(old, new);
948 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
949 || (warningLevel > 9))
951 WARN("Multiple doodads named \"%s\"\n",
952 XkbcAtomText(old->name));
953 ACTION("Using first definition\n");
958 if ((new = NextDoodad(si, info)) == NULL)
960 ReplaceDoodad(new, old);
962 new->defs.next = NULL;
967 FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
969 DoodadInfo *dflt = NULL;
972 if (uStrCaseCmp(name, "outline") == 0)
973 type = XkbOutlineDoodad;
974 else if (uStrCaseCmp(name, "solid") == 0)
975 type = XkbSolidDoodad;
976 else if (uStrCaseCmp(name, "text") == 0)
977 type = XkbTextDoodad;
978 else if (uStrCaseCmp(name, "indicator") == 0)
979 type = XkbIndicatorDoodad;
980 else if (uStrCaseCmp(name, "logo") == 0)
981 type = XkbLogoDoodad;
984 if ((si) && (si->dfltDoodads))
985 dflt = FindDoodadByType(si->dfltDoodads, type);
986 if ((!dflt) && (info->dfltDoodads))
987 dflt = FindDoodadByType(info->dfltDoodads, type);
990 dflt = NextDfltDoodad(si, info);
1000 /***====================================================================***/
1003 AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
1007 for (old = si->overlays; old != NULL;
1008 old = (OverlayInfo *) old->defs.next)
1010 if (old->name == new->name)
1015 if ((new->defs.merge == MergeReplace)
1016 || (new->defs.merge == MergeOverride))
1018 if (((old->defs.fileID == new->defs.fileID)
1019 && (warningLevel > 0)) || (warningLevel > 9))
1022 ("Multiple overlays named \"%s\" for section \"%s\"\n",
1023 XkbcAtomText(old->name), XkbcAtomText(si->name));
1024 ACTION("Using last definition\n");
1026 ClearOverlayInfo(old);
1027 old->nKeys = new->nKeys;
1028 old->keys = new->keys;
1033 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1034 || (warningLevel > 9))
1036 WARN("Multiple doodads named \"%s\" in section \"%s\"\n",
1037 XkbcAtomText(old->name), XkbcAtomText(si->name));
1038 ACTION("Using first definition\n");
1043 new = uTypedCalloc(1, OverlayInfo);
1046 if (warningLevel > 0)
1048 WSGO("Couldn't allocate a new OverlayInfo\n");
1050 ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
1051 XkbcAtomText(old->name), XkbcAtomText(si->name));
1058 si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
1059 (CommonInfo *) new);
1064 /***====================================================================***/
1066 static SectionInfo *
1067 NextSection(GeometryInfo * info)
1071 si = uTypedAlloc(SectionInfo);
1074 *si = info->dfltSection;
1075 si->defs.defined &= ~_GS_Default;
1076 si->defs.next = NULL;
1080 (SectionInfo *) AddCommonInfo(&info->sections->defs,
1087 static SectionInfo *
1088 FindMatchingSection(GeometryInfo * info, SectionInfo * new)
1092 for (old = info->sections; old != NULL;
1093 old = (SectionInfo *) old->defs.next)
1095 if (new->name == old->name)
1102 AddSection(GeometryInfo * info, SectionInfo * new)
1106 old = FindMatchingSection(info, new);
1110 if ((new->defs.merge == MergeReplace)
1111 || (new->defs.merge == MergeOverride))
1113 SectionInfo *next = (SectionInfo *) old->defs.next;
1114 if (((old->defs.fileID == new->defs.fileID)
1115 && (warningLevel > 0)) || (warningLevel > 9))
1117 WARN("Duplicate shape name \"%s\"\n", shText(old));
1118 ACTION("Using last definition\n");
1121 old->defs.next = &next->defs;
1124 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
1125 || (warningLevel > 9))
1127 WARN("Multiple shapes named \"%s\"\n", shText(old));
1128 ACTION("Using first definition\n");
1132 WARN("Don't know how to merge sections yet\n");
1136 if ((new = NextSection(info)) == NULL)
1139 new->defs.next = NULL;
1140 old->nRows = old->nDoodads = old->nOverlays = 0;
1142 old->doodads = NULL;
1143 old->overlays = NULL;
1147 for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
1155 /***====================================================================***/
1158 NextRow(SectionInfo * si)
1162 row = uTypedAlloc(RowInfo);
1166 row->defs.defined &= ~_GR_Default;
1167 row->defs.next = NULL;
1171 (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
1172 row->index = si->nRows++;
1178 AddRow(SectionInfo * si, RowInfo * new)
1183 if ((new = NextRow(si)) == NULL)
1186 new->defs.next = NULL;
1192 /***====================================================================***/
1195 NextKey(RowInfo * row)
1199 key = uTypedAlloc(KeyInfo);
1202 *key = row->dfltKey;
1203 key->defs.defined &= ~_GK_Default;
1204 key->defs.next = NULL;
1205 key->index = row->nKeys++;
1211 AddKey(RowInfo * row, KeyInfo * new)
1216 if ((new = NextKey(row)) == NULL)
1219 new->defs.next = NULL;
1221 (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
1225 /***====================================================================***/
1228 MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
1233 if (from->errorCount > 0)
1235 into->errorCount += from->errorCount;
1238 clobber = (merge == MergeOverride) || (merge == MergeReplace);
1239 if (into->name == NULL)
1241 into->name = from->name;
1244 if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
1245 into->widthMM = from->widthMM;
1246 if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
1247 into->heightMM = from->heightMM;
1248 if ((into->font == None) || ((from->font != None) && clobber))
1249 into->font = from->font;
1250 if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
1251 into->fontSlant = from->fontSlant;
1252 if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
1253 into->fontWeight = from->fontWeight;
1254 if ((into->fontSetWidth == None)
1255 || ((from->fontSetWidth != None) && clobber))
1256 into->fontSetWidth = from->fontSetWidth;
1257 if ((into->fontVariant == None)
1258 || ((from->fontVariant != None) && clobber))
1259 into->fontVariant = from->fontVariant;
1260 if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
1261 into->fontSize = from->fontSize;
1262 if ((into->fontEncoding == None)
1263 || ((from->fontEncoding != None) && clobber))
1264 into->fontEncoding = from->fontEncoding;
1265 if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
1266 into->fontSpec = from->fontSpec;
1267 if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
1268 into->baseColor = from->baseColor;
1269 if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
1270 into->labelColor = from->labelColor;
1271 into->nextPriority = from->nextPriority;
1272 if (from->props != NULL)
1275 for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
1277 if (!AddProperty(into, pi))
1281 if (from->shapes != NULL)
1285 for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
1287 if (!AddShape(into, si))
1291 if (from->sections != NULL)
1295 for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
1297 if (!AddSection(into, si))
1301 if (from->doodads != NULL)
1305 for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
1307 if (!AddDoodad(NULL, into, di))
1311 if (!MergeAliases(&into->aliases, &from->aliases, merge))
1316 typedef void (*FileHandler) (XkbFile * /* file */ ,
1317 struct xkb_desc * /* xkb */ ,
1318 unsigned /* merge */ ,
1319 GeometryInfo * /* info */
1323 HandleIncludeGeometry(IncludeStmt * stmt, struct xkb_desc * xkb, GeometryInfo * info,
1328 GeometryInfo included;
1332 if ((stmt->file == NULL) && (stmt->map == NULL))
1336 bzero(info, sizeof(GeometryInfo));
1338 else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
1340 InitGeometryInfo(&included, rtrn->id, newMerge);
1341 included.nextPriority = info->nextPriority;
1342 included.dfltCornerRadius = info->dfltCornerRadius;
1343 DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
1344 (*hndlr) (rtrn, xkb, MergeOverride, &included);
1345 if (stmt->stmt != NULL)
1347 if (included.name != NULL)
1348 free(included.name);
1349 included.name = stmt->stmt;
1355 info->errorCount += 10;
1358 if ((stmt->next != NULL) && (included.errorCount < 1))
1362 GeometryInfo next_incl;
1364 for (next = stmt->next; next != NULL; next = next->next)
1366 if ((next->file == NULL) && (next->map == NULL))
1369 MergeIncludedGeometry(&included, info, next->merge);
1370 ClearGeometryInfo(info);
1372 else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
1374 InitGeometryInfo(&next_incl, rtrn->id, op);
1375 next_incl.nextPriority = included.nextPriority;
1376 next_incl.dfltCornerRadius = included.dfltCornerRadius;
1377 DupSectionInfo(&next_incl.dfltSection,
1378 &included.dfltSection, &included);
1379 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
1380 MergeIncludedGeometry(&included, &next_incl, op);
1381 ClearGeometryInfo(&next_incl);
1385 info->errorCount += 10;
1394 MergeIncludedGeometry(info, &included, newMerge);
1395 ClearGeometryInfo(&included);
1397 return (info->errorCount == 0);
1401 SetShapeField(ShapeInfo * si,
1403 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1407 if ((uStrCaseCmp(field, "radius") == 0)
1408 || (uStrCaseCmp(field, "corner") == 0)
1409 || (uStrCaseCmp(field, "cornerradius") == 0))
1411 if (arrayNdx != NULL)
1414 return ReportNotArray("key shape", field, shText(si));
1416 if (!ExprResolveFloat(value, &tmp))
1419 return ReportBadType("key shape", field, shText(si), "number");
1422 si->dfltCornerRadius = tmp.ival;
1424 info->dfltCornerRadius = tmp.ival;
1428 return ReportBadField("key shape", field, shText(si));
1432 SetShapeDoodadField(DoodadInfo * di,
1435 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1438 const char *typeName;
1441 (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
1442 if ((!uStrCaseCmp(field, "corner"))
1443 || (!uStrCaseCmp(field, "cornerradius")))
1445 if (arrayNdx != NULL)
1448 return ReportNotArray(typeName, field, ddText(di));
1450 if (!ExprResolveFloat(value, &tmp))
1453 return ReportBadType(typeName, field, ddText(di), "number");
1455 di->defs.defined |= _GD_Corner;
1456 di->corner = tmp.ival;
1459 else if (uStrCaseCmp(field, "angle") == 0)
1461 if (arrayNdx != NULL)
1464 return ReportNotArray(typeName, field, ddText(di));
1466 if (!ExprResolveFloat(value, &tmp))
1469 return ReportBadType(typeName, field, ddText(di), "number");
1471 di->defs.defined |= _GD_Angle;
1472 di->angle = tmp.ival;
1475 else if (uStrCaseCmp(field, "shape") == 0)
1477 if (arrayNdx != NULL)
1480 return ReportNotArray(typeName, field, ddText(di));
1482 if (!ExprResolveString(value, &tmp))
1485 return ReportBadType(typeName, field, ddText(di), "string");
1487 di->shape = xkb_intern_atom(tmp.str);
1488 di->defs.defined |= _GD_Shape;
1492 return ReportBadField(typeName, field, ddText(di));
1495 #define FIELD_STRING 0
1496 #define FIELD_SHORT 1
1497 #define FIELD_USHORT 2
1500 SetTextDoodadField(DoodadInfo * di,
1503 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1508 char *typeName = "text doodad";
1513 unsigned short *uval;
1516 if (uStrCaseCmp(field, "angle") == 0)
1518 if (arrayNdx != NULL)
1521 return ReportNotArray(typeName, field, ddText(di));
1523 if (!ExprResolveFloat(value, &tmp))
1526 return ReportBadType(typeName, field, ddText(di), "number");
1528 di->defs.defined |= _GD_Angle;
1529 di->angle = tmp.ival;
1532 if (uStrCaseCmp(field, "width") == 0)
1534 type = FIELD_USHORT;
1535 pField.uval = &di->width;
1538 else if (uStrCaseCmp(field, "height") == 0)
1540 type = FIELD_USHORT;
1541 pField.uval = &di->height;
1544 else if (uStrCaseCmp(field, "text") == 0)
1546 type = FIELD_STRING;
1547 pField.str = &di->text;
1550 else if (uStrCaseCmp(field, "font") == 0)
1552 type = FIELD_STRING;
1553 pField.str = &di->font;
1556 else if ((uStrCaseCmp(field, "fontslant") == 0) ||
1557 (uStrCaseCmp(field, "slant") == 0))
1559 type = FIELD_STRING;
1560 pField.str = &di->fontSlant;
1561 def = _GD_FontSlant;
1563 else if ((uStrCaseCmp(field, "fontweight") == 0) ||
1564 (uStrCaseCmp(field, "weight") == 0))
1566 type = FIELD_STRING;
1567 pField.str = &di->fontWeight;
1568 def = _GD_FontWeight;
1570 else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
1571 (uStrCaseCmp(field, "setwidth") == 0))
1573 type = FIELD_STRING;
1574 pField.str = &di->fontSetWidth;
1575 def = _GD_FontSetWidth;
1577 else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
1578 (uStrCaseCmp(field, "variant") == 0))
1580 type = FIELD_STRING;
1581 pField.str = &di->fontVariant;
1582 def = _GD_FontVariant;
1584 else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
1585 (uStrCaseCmp(field, "encoding") == 0))
1587 type = FIELD_STRING;
1588 pField.str = &di->fontEncoding;
1589 def = _GD_FontEncoding;
1591 else if ((uStrCaseCmp(field, "xfont") == 0) ||
1592 (uStrCaseCmp(field, "xfontname") == 0))
1594 type = FIELD_STRING;
1595 pField.str = &di->fontSpec;
1598 else if (uStrCaseCmp(field, "fontsize") == 0)
1600 type = FIELD_USHORT;
1601 pField.uval = &di->fontSize;
1606 return ReportBadField(typeName, field, ddText(di));
1608 if (arrayNdx != NULL)
1611 return ReportNotArray(typeName, field, ddText(di));
1613 if (type == FIELD_STRING)
1615 if (!ExprResolveString(value, &tmp))
1618 return ReportBadType(typeName, field, ddText(di), "string");
1620 di->defs.defined |= def;
1621 *pField.str = xkb_intern_atom(tmp.str);
1626 if (!ExprResolveFloat(value, &tmp))
1629 return ReportBadType(typeName, field, ddText(di), "number");
1631 if ((type == FIELD_USHORT) && (tmp.ival < 0))
1635 ReportBadType(typeName, field, ddText(di), "unsigned");
1637 di->defs.defined |= def;
1638 if (type == FIELD_USHORT)
1639 *pField.uval = tmp.uval;
1641 *pField.ival = tmp.ival;
1647 SetIndicatorDoodadField(DoodadInfo * di,
1651 SectionInfo * si, GeometryInfo * info)
1655 if ((uStrCaseCmp(field, "oncolor") == 0)
1656 || (uStrCaseCmp(field, "offcolor") == 0)
1657 || (uStrCaseCmp(field, "shape") == 0))
1659 if (arrayNdx != NULL)
1662 return ReportNotArray("indicator doodad", field, ddText(di));
1664 if (!ExprResolveString(value, &tmp))
1667 return ReportBadType("indicator doodad", field,
1668 ddText(di), "string");
1670 if (uStrCaseCmp(field, "oncolor") == 0)
1672 di->defs.defined |= _GD_Color;
1673 di->color = xkb_intern_atom(tmp.str);
1675 else if (uStrCaseCmp(field, "offcolor") == 0)
1677 di->defs.defined |= _GD_OffColor;
1678 di->offColor = xkb_intern_atom(tmp.str);
1680 else if (uStrCaseCmp(field, "shape") == 0)
1682 di->defs.defined |= _GD_Shape;
1683 di->shape = xkb_intern_atom(tmp.str);
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))
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))
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))
1743 return ReportBadType(typeName, field, ddText(di), "string");
1745 di->shape = xkb_intern_atom(tmp.str);
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))
1761 return ReportBadType(typeName, field, ddText(di),
1764 di->logoName = _XkbDupString(tmp.str);
1768 return ReportBadField(typeName, field, ddText(di));
1772 SetDoodadField(DoodadInfo * di,
1775 ExprDef * value, SectionInfo * si, GeometryInfo * info)
1779 if (uStrCaseCmp(field, "priority") == 0)
1781 if (arrayNdx != NULL)
1784 return ReportNotArray("doodad", field, ddText(di));
1786 if (!ExprResolveInteger(value, &tmp))
1789 return ReportBadType("doodad", field, ddText(di), "integer");
1791 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1794 ERROR("Doodad priority %d out of range (must be 0..%d)\n",
1795 tmp.ival, XkbGeomMaxPriority);
1796 ACTION("Priority for doodad %s not changed", ddText(di));
1799 di->defs.defined |= _GD_Priority;
1800 di->priority = tmp.ival;
1803 else if (uStrCaseCmp(field, "left") == 0)
1805 if (arrayNdx != NULL)
1808 return ReportNotArray("doodad", field, ddText(di));
1810 if (!ExprResolveFloat(value, &tmp))
1813 return ReportBadType("doodad", field, ddText(di), "number");
1815 di->defs.defined |= _GD_Left;
1816 di->left = tmp.ival;
1819 else if (uStrCaseCmp(field, "top") == 0)
1821 if (arrayNdx != NULL)
1824 return ReportNotArray("doodad", field, ddText(di));
1826 if (!ExprResolveFloat(value, &tmp))
1829 return ReportBadType("doodad", field, ddText(di), "number");
1831 di->defs.defined |= _GD_Top;
1835 else if (uStrCaseCmp(field, "color") == 0)
1837 if (arrayNdx != NULL)
1840 return ReportNotArray("doodad", field, ddText(di));
1842 if (!ExprResolveString(value, &tmp))
1845 return ReportBadType("doodad", field, ddText(di), "string");
1847 di->defs.defined |= _GD_Color;
1848 di->color = xkb_intern_atom(tmp.str);
1854 case XkbOutlineDoodad:
1855 case XkbSolidDoodad:
1856 return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
1858 return SetTextDoodadField(di, field, arrayNdx, value, si, info);
1859 case XkbIndicatorDoodad:
1860 return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
1862 return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
1864 WSGO("Unknown doodad type %d in SetDoodadField\n",
1865 (unsigned int) di->type);
1866 ACTION("Definition of %s in %s ignored\n", field, ddText(di));
1871 SetSectionField(SectionInfo * si,
1873 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1875 unsigned short *pField;
1880 if (uStrCaseCmp(field, "priority") == 0)
1882 if (arrayNdx != NULL)
1885 return ReportNotArray("keyboard section", field, scText(si));
1887 if (!ExprResolveInteger(value, &tmp))
1890 ReportBadType("keyboard section", field, scText(si), "integer");
1893 if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
1896 ERROR("Section priority %d out of range (must be 0..%d)\n",
1897 tmp.ival, XkbGeomMaxPriority);
1898 ACTION("Priority for section %s not changed", scText(si));
1901 si->priority = tmp.ival;
1902 si->defs.defined |= _GS_Priority;
1905 else if (uStrCaseCmp(field, "top") == 0)
1910 else if (uStrCaseCmp(field, "left") == 0)
1915 else if (uStrCaseCmp(field, "width") == 0)
1917 pField = &si->width;
1920 else if (uStrCaseCmp(field, "height") == 0)
1922 pField = &si->height;
1925 else if (uStrCaseCmp(field, "angle") == 0)
1927 pField = &si->angle;
1933 return ReportBadField("keyboard section", field, scText(si));
1935 if (arrayNdx != NULL)
1938 return ReportNotArray("keyboard section", field, scText(si));
1940 if (!ExprResolveFloat(value, &tmp))
1943 ReportBadType("keyboard section", field, scText(si), "number");
1946 si->defs.defined |= def;
1952 SetRowField(RowInfo * row,
1954 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
1958 if (uStrCaseCmp(field, "top") == 0)
1960 if (arrayNdx != NULL)
1963 return ReportNotArray("keyboard row", field, rowText(row));
1965 if (!ExprResolveFloat(value, &tmp))
1968 return ReportBadType("keyboard row", field, rowText(row),
1971 row->defs.defined |= _GR_Top;
1972 row->top = tmp.uval;
1974 else if (uStrCaseCmp(field, "left") == 0)
1976 if (arrayNdx != NULL)
1979 return ReportNotArray("keyboard row", field, rowText(row));
1981 if (!ExprResolveFloat(value, &tmp))
1984 return ReportBadType("keyboard row", field, rowText(row),
1987 row->defs.defined |= _GR_Left;
1988 row->left = tmp.uval;
1990 else if (uStrCaseCmp(field, "vertical") == 0)
1992 if (arrayNdx != NULL)
1995 return ReportNotArray("keyboard row", field, rowText(row));
1997 if (!ExprResolveBoolean(value, &tmp))
2000 return ReportBadType("keyboard row", field, rowText(row),
2003 row->defs.defined |= _GR_Vertical;
2004 row->vertical = tmp.uval;
2009 return ReportBadField("keyboard row", field, rowText(row));
2015 SetKeyField(KeyInfo * key,
2017 ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
2021 if (uStrCaseCmp(field, "gap") == 0)
2023 if (arrayNdx != NULL)
2026 return ReportNotArray("key", field, keyText(key));
2028 if (!ExprResolveFloat(value, &tmp))
2031 return ReportBadType("key", field, keyText(key), "number");
2033 key->defs.defined |= _GK_Gap;
2034 key->gap = tmp.ival;
2036 else if (uStrCaseCmp(field, "shape") == 0)
2038 if (arrayNdx != NULL)
2041 return ReportNotArray("key", field, keyText(key));
2043 if (!ExprResolveString(value, &tmp))
2046 return ReportBadType("key", field, keyText(key), "string");
2048 key->defs.defined |= _GK_Shape;
2049 key->shape = xkb_intern_atom(tmp.str);
2052 else if ((uStrCaseCmp(field, "color") == 0) ||
2053 (uStrCaseCmp(field, "keycolor") == 0))
2055 if (arrayNdx != NULL)
2058 return ReportNotArray("key", field, keyText(key));
2060 if (!ExprResolveString(value, &tmp))
2063 return ReportBadType("key", field, keyText(key), "string");
2065 key->defs.defined |= _GK_Color;
2066 key->color = xkb_intern_atom(tmp.str);
2069 else if ((uStrCaseCmp(field, "name") == 0)
2070 || (uStrCaseCmp(field, "keyname") == 0))
2072 if (arrayNdx != NULL)
2075 return ReportNotArray("key", field, keyText(key));
2077 if (!ExprResolveKeyName(value, &tmp))
2080 return ReportBadType("key", field, keyText(key), "key name");
2082 key->defs.defined |= _GK_Name;
2083 bzero(key->name, XkbKeyNameLength + 1);
2084 strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
2089 return ReportBadField("key", field, keyText(key));
2095 SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
2101 InitPropertyInfo(&pi, info);
2103 if (!ExprResolveString(value, &result))
2106 ERROR("Property values must be type string\n");
2107 ACTION("Ignoring illegal definition of \"%s\" property\n", property);
2110 pi.value = result.str;
2111 ret = AddProperty(info, &pi);
2117 HandleGeometryVar(VarDef * stmt, struct xkb_desc * xkb, GeometryInfo * info)
2119 ExprResult elem, field, tmp;
2122 uint32_t *pField = NULL;
2123 int ret = True; /* default to no error */
2125 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
2126 return 0; /* internal error, already reported */
2129 if (uStrCaseCmp(elem.str, "shape") == 0)
2130 ret = SetShapeField(NULL, field.str, ndx, stmt->value, info);
2131 else if (uStrCaseCmp(elem.str, "key") == 0)
2132 ret = SetKeyField(&info->dfltSection.dfltRow.dfltKey,
2133 field.str, ndx, stmt->value, info);
2134 else if (uStrCaseCmp(elem.str, "row") == 0)
2135 ret = SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
2137 else if (uStrCaseCmp(elem.str, "section") == 0)
2138 ret = SetSectionField(&info->dfltSection, field.str, ndx,
2140 else if (uStrCaseCmp(elem.str, "property") == 0)
2145 ERROR("The %s geometry property is not an array\n", field.str);
2146 ACTION("Ignoring illegal property definition\n");
2150 ret = SetGeometryProperty(info, field.str, stmt->value);
2153 else if ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)
2154 ret = SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
2155 else if (uStrCaseCmp(elem.str, "solid") == 0)
2158 dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
2160 dflt = NextDfltDoodad(NULL, info);
2161 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2163 else if (uStrCaseCmp(elem.str, "outline") == 0)
2166 dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
2168 dflt = NextDfltDoodad(NULL, info);
2169 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2171 else if (uStrCaseCmp(elem.str, "text") == 0)
2174 dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
2176 dflt = NextDfltDoodad(NULL, info);
2177 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2179 else if (uStrCaseCmp(elem.str, "indicator") == 0)
2182 dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
2184 dflt = NextDfltDoodad(NULL, info);
2185 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2187 else if (uStrCaseCmp(elem.str, "logo") == 0)
2190 dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
2192 dflt = NextDfltDoodad(NULL, info);
2193 ret = SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
2197 WARN("Assignment to field of unknown element\n");
2198 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2206 if ((uStrCaseCmp(field.str, "width") == 0) ||
2207 (uStrCaseCmp(field.str, "widthmm") == 0))
2212 ret = ReportNotArray("keyboard", field.str, "geometry");
2214 else if (!ExprResolveFloat(stmt->value, &tmp))
2217 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2219 else if (tmp.ival < 1)
2221 WARN("Keyboard width must be positive\n");
2222 ACTION("Ignoring illegal keyboard width %s\n",
2223 XkbcGeomFPText(tmp.ival));
2227 if (info->widthMM != 0)
2229 WARN("Keyboard width multiply defined\n");
2230 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2231 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->widthMM));
2233 info->widthMM = tmp.ival;
2239 else if ((uStrCaseCmp(field.str, "height") == 0) ||
2240 (uStrCaseCmp(field.str, "heightmm") == 0))
2245 ret = ReportNotArray("keyboard", field.str, "geometry");
2247 if (!ExprResolveFloat(stmt->value, &tmp))
2250 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2254 WARN("Keyboard height must be positive\n");
2255 ACTION("Ignoring illegal keyboard height %s\n",
2256 XkbcGeomFPText(tmp.ival));
2260 if (info->heightMM != 0)
2262 WARN("Keyboard height multiply defined\n");
2263 ACTION("Using last definition (%s),", XkbcGeomFPText(tmp.ival));
2264 INFO(" ignoring first (%s)\n", XkbcGeomFPText(info->heightMM));
2266 info->heightMM = tmp.ival;
2272 else if (uStrCaseCmp(field.str, "fontsize") == 0)
2277 ret = ReportNotArray("keyboard", field.str, "geometry");
2279 else if (!ExprResolveFloat(stmt->value, &tmp))
2282 ret = ReportBadType("keyboard", field.str, "geometry", "number");
2284 else if ((tmp.ival < 40) || (tmp.ival > 2550))
2287 ERROR("Illegal font size %d (must be 4..255)\n", tmp.ival);
2288 ACTION("Ignoring font size in keyboard geometry\n");
2292 info->fontSize = tmp.ival;
2298 else if ((uStrCaseCmp(field.str, "color") == 0) ||
2299 (uStrCaseCmp(field.str, "basecolor") == 0))
2304 ret = ReportNotArray("keyboard", field.str, "geometry");
2306 if (!ExprResolveString(stmt->value, &tmp))
2309 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2312 info->baseColor = xkb_intern_atom(tmp.str);
2319 else if (uStrCaseCmp(field.str, "labelcolor") == 0)
2324 ret = ReportNotArray("keyboard", field.str, "geometry");
2326 if (!ExprResolveString(stmt->value, &tmp))
2329 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2332 info->labelColor = xkb_intern_atom(tmp.str);
2339 else if (uStrCaseCmp(field.str, "font") == 0)
2341 pField = &info->font;
2343 else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
2344 (uStrCaseCmp(field.str, "slant") == 0))
2346 pField = &info->fontSlant;
2348 else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
2349 (uStrCaseCmp(field.str, "weight") == 0))
2351 pField = &info->fontWeight;
2353 else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
2354 (uStrCaseCmp(field.str, "setwidth") == 0))
2356 pField = &info->fontWeight;
2358 else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
2359 (uStrCaseCmp(field.str, "encoding") == 0))
2361 pField = &info->fontEncoding;
2363 else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
2364 (uStrCaseCmp(field.str, "xfontname") == 0))
2366 pField = &info->fontSpec;
2370 ret = SetGeometryProperty(info, field.str, stmt->value);
2375 /* fallthrough for the cases that set pField */
2379 ret = ReportNotArray("keyboard", field.str, "geometry");
2381 else if (!ExprResolveString(stmt->value, &tmp))
2384 ret = ReportBadType("keyboard", field.str, "geometry", "string");
2387 *pField = xkb_intern_atom(tmp.str);
2394 /***====================================================================***/
2397 HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
2398 GeometryInfo * info)
2402 struct xkb_outline * outline;
2405 if (def->nOutlines < 1)
2407 WARN("Shape \"%s\" has no outlines\n", shText(si));
2408 ACTION("Definition ignored\n");
2411 si->nOutlines = def->nOutlines;
2412 si->outlines = uTypedCalloc(def->nOutlines, struct xkb_outline);
2415 ERROR("Couldn't allocate outlines for \"%s\"\n", shText(si));
2416 ACTION("Definition ignored\n");
2420 for (nOut = 0, ol = def->outlines; ol != NULL;
2421 ol = (OutlineDef *) ol->common.next)
2423 if (ol->nPoints < 1)
2425 SetShapeField(si, XkbcAtomText(ol->field), NULL, ol->points, info);
2429 outline = &si->outlines[nOut++];
2430 outline->num_points = ol->nPoints;
2431 outline->corner_radius = si->dfltCornerRadius;
2432 outline->points = uTypedCalloc(ol->nPoints, struct xkb_point);
2433 if (!outline->points)
2435 ERROR("Can't allocate points for \"%s\"\n", shText(si));
2436 ACTION("Definition ignored\n");
2441 for (nPt = 0, pt = ol->points; pt != NULL;
2442 pt = (ExprDef *) pt->common.next)
2444 outline->points[nPt].x = pt->value.coord.x;
2445 outline->points[nPt].y = pt->value.coord.y;
2448 if (ol->field != None)
2450 const char *str = XkbcAtomText(ol->field);
2451 if ((uStrCaseCmp(str, "approximation") == 0) ||
2452 (uStrCaseCmp(str, "approx") == 0))
2454 if (si->approx == NULL)
2455 si->approx = outline;
2458 WARN("Multiple approximations for \"%s\"\n",
2460 ACTION("Treating all but the first as normal outlines\n");
2463 else if (uStrCaseCmp(str, "primary") == 0)
2465 if (si->primary == NULL)
2466 si->primary = outline;
2469 WARN("Multiple primary outlines for \"%s\"\n",
2471 ACTION("Treating all but the first as normal outlines\n");
2476 WARN("Unknown outline type %s for \"%s\"\n", str,
2478 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, struct xkb_desc * 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)
2603 for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
2605 if (expr->op == OpAssign)
2609 if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
2610 return False; /* internal error, already reported */
2611 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
2614 (key, f.str, ndx, expr->value.binary.right, info))
2625 ERROR("Illegal element used in a key definition\n");
2626 ACTION("Assignment to %s.%s ignored\n", elem.str, f.str);
2634 RowInfo *row = key->row;
2639 if (!SetKeyField(key, "gap", NULL, expr, info))
2643 if (!SetKeyField(key, "shape", NULL, expr, info))
2647 if (!SetKeyField(key, "name", NULL, expr, info))
2651 ERROR("Cannot determine field for unnamed expression\n");
2652 ACTION("Ignoring key %d in row %d of section %s\n",
2653 row->nKeys + 1, row->section->nRows + 1,
2663 HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
2664 GeometryInfo * info)
2668 if ((def->nKeys < 1) && (warningLevel > 3))
2670 ERROR("Row in section %s has no keys\n", rowText(row));
2671 ACTION("Section ignored\n");
2674 for (keyDef = def->keys; keyDef != NULL;
2675 keyDef = (KeyDef *) keyDef->common.next)
2677 if (keyDef->common.stmtType == StmtVarDef)
2679 VarDef *var = (VarDef *) keyDef;
2680 ExprResult elem, field;
2682 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2683 return 0; /* internal error, already reported */
2684 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
2686 if (!SetRowField(row, field.str, ndx, var->value, info))
2689 else if (uStrCaseCmp(elem.str, "key") == 0)
2692 (&row->dfltKey, field.str, ndx, var->value, info))
2697 WARN("Assignment to field of unknown element in row\n");
2698 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2703 else if (keyDef->common.stmtType == StmtKeyDef)
2706 InitKeyInfo(&key, row, info);
2707 if (keyDef->name != NULL)
2709 int len = strlen(keyDef->name);
2710 if ((len < 1) || (len > XkbKeyNameLength))
2712 ERROR("Illegal name %s for key in section %s\n",
2713 keyDef->name, rowText(row));
2714 ACTION("Section not compiled\n");
2717 bzero(key.name, XkbKeyNameLength + 1);
2718 strncpy(key.name, keyDef->name, XkbKeyNameLength);
2719 key.defs.defined |= _GK_Name;
2721 else if (!HandleComplexKey(keyDef, &key, info))
2723 if (!AddKey(row, &key))
2728 WSGO("Unexpected statement (type %d) in row body\n",
2729 keyDef->common.stmtType);
2737 HandleSectionBody(SectionDef * def,
2738 SectionInfo * si, unsigned merge, GeometryInfo * info)
2743 for (rowDef = def->rows; rowDef != NULL;
2744 rowDef = (RowDef *) rowDef->common.next)
2746 if (rowDef->common.stmtType == StmtVarDef)
2748 VarDef *var = (VarDef *) rowDef;
2749 ExprResult elem, field;
2751 if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
2752 return 0; /* internal error, already reported */
2753 if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
2755 if (!SetSectionField(si, field.str, ndx, var->value, info))
2761 else if (uStrCaseCmp(elem.str, "row") == 0)
2764 (&si->dfltRow, field.str, ndx, var->value, info))
2770 else if (uStrCaseCmp(elem.str, "key") == 0)
2772 if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
2780 FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
2782 if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
2790 WARN("Assignment to field of unknown element in section\n");
2791 ACTION("No value assigned to %s.%s\n", elem.str, field.str);
2796 else if (rowDef->common.stmtType == StmtRowDef)
2799 InitRowInfo(&row, si, info);
2800 if (!HandleRowBody(rowDef, &row, merge, info))
2802 if (!AddRow(si, &row))
2804 /* ClearRowInfo(&row,info);*/
2806 else if ((rowDef->common.stmtType == StmtDoodadDef) ||
2807 (rowDef->common.stmtType == StmtIndicatorMapDef))
2809 if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
2812 else if (rowDef->common.stmtType == StmtOverlayDef)
2814 if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
2819 WSGO("Unexpected statement (type %d) in section body\n",
2820 rowDef->common.stmtType);
2824 if (si->nRows != def->nRows)
2826 WSGO("Expected %d rows, found %d\n", (unsigned int) def->nRows,
2827 (unsigned int) si->nRows);
2828 ACTION("Definition of section %s might be incorrect\n", scText(si));
2834 HandleSectionDef(SectionDef * def,
2835 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2839 if (def->merge != MergeDefault)
2841 InitSectionInfo(&si, info);
2842 si.defs.merge = merge;
2843 si.name = def->name;
2844 if (!HandleSectionBody(def, &si, merge, info))
2846 if (!AddSection(info, &si))
2851 /***====================================================================***/
2854 HandleGeometryFile(XkbFile * file,
2855 struct xkb_desc * xkb, unsigned merge, GeometryInfo * info)
2860 if (merge == MergeDefault)
2861 merge = MergeAugment;
2862 info->name = _XkbDupString(file->name);
2867 switch (stmt->stmtType)
2870 if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
2871 HandleGeometryFile))
2874 case StmtKeyAliasDef:
2875 if (!HandleAliasDef((KeyAliasDef *) stmt,
2876 merge, info->fileID, &info->aliases))
2882 if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
2886 if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
2889 case StmtSectionDef:
2890 if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
2893 case StmtIndicatorMapDef:
2895 if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
2900 failWhat = "virtual modfier";
2903 failWhat = "symbol interpretation";
2904 case StmtGroupCompatDef:
2906 failWhat = "group compatibility map";
2907 case StmtKeycodeDef:
2909 failWhat = "key name";
2910 ERROR("Interpretation files may not include other types\n");
2911 ACTION("Ignoring %s definition.\n", failWhat);
2915 WSGO("Unexpected statement type %d in HandleGeometryFile\n",
2920 if (info->errorCount > 10)
2923 ERROR("Too many errors\n");
2925 ACTION("Abandoning geometry file \"%s\"\n", file->topName);
2932 /***====================================================================***/
2935 CopyShapeDef(struct xkb_geometry * geom, ShapeInfo * si)
2938 struct xkb_shape * shape;
2939 struct xkb_outline *old_outline, *outline;
2942 si->index = geom->num_shapes;
2944 shape = XkbcAddGeomShape(geom, name, si->nOutlines);
2947 WSGO("Couldn't allocate shape in geometry\n");
2948 ACTION("Shape %s not compiled\n", shText(si));
2951 old_outline = si->outlines;
2952 for (i = 0; i < si->nOutlines; i++, old_outline++)
2954 outline = XkbcAddGeomOutline(shape, old_outline->num_points);
2957 WSGO("Couldn't allocate outline in shape\n");
2958 ACTION("Shape %s is incomplete\n", shText(si));
2961 n = old_outline->num_points;
2962 memcpy(outline->points, old_outline->points, n * sizeof(struct xkb_point));
2963 outline->num_points = old_outline->num_points;
2964 outline->corner_radius = old_outline->corner_radius;
2968 n = (si->approx - si->outlines);
2969 shape->approx = &shape->outlines[n];
2973 n = (si->primary - si->outlines);
2974 shape->primary = &shape->outlines[n];
2976 XkbcComputeShapeBounds(shape);
2981 VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
2983 if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
2985 if (warningLevel < 9)
2987 ERROR("No position defined for doodad %s\n",
2989 ACTION("Illegal doodad ignored\n");
2993 if ((di->defs.defined & _GD_Priority) == 0)
2995 /* calculate priority -- should be just above previous doodad/row */
2999 case XkbOutlineDoodad:
3000 case XkbSolidDoodad:
3001 if ((di->defs.defined & _GD_Shape) == 0)
3003 ERROR("No shape defined for %s doodad %s\n",
3004 (di->type == XkbOutlineDoodad ? "outline" : "filled"),
3006 ACTION("Incomplete definition ignored\n");
3012 si = FindShape(info, di->shape,
3014 XkbOutlineDoodad ? "outline doodad" :
3015 "solid doodad"), ddText(di));
3017 di->shape = si->name;
3020 ERROR("No legal shape for %s\n", ddText(di));
3021 ACTION("Incomplete definition ignored\n");
3025 if ((di->defs.defined & _GD_Color) == 0)
3027 if (warningLevel > 5)
3029 WARN("No color for doodad %s\n", ddText(di));
3030 ACTION("Using black\n");
3032 di->color = xkb_intern_atom("black");
3036 if ((di->defs.defined & _GD_Text) == 0)
3038 ERROR("No text specified for text doodad %s\n", ddText(di));
3039 ACTION("Illegal doodad definition ignored\n");
3042 if ((di->defs.defined & _GD_Angle) == 0)
3044 if ((di->defs.defined & _GD_Color) == 0)
3046 if (warningLevel > 5)
3048 WARN("No color specified for doodad %s\n", ddText(di));
3049 ACTION("Using black\n");
3051 di->color = xkb_intern_atom("black");
3053 if ((di->defs.defined & _GD_FontSpec) != 0)
3055 if ((di->defs.defined & _GD_FontParts) == 0)
3057 if (warningLevel < 9)
3060 ("Text doodad %s has full and partial font definition\n",
3062 ACTION("Full specification ignored\n");
3064 di->defs.defined &= ~_GD_FontSpec;
3065 di->fontSpec = None;
3067 if ((di->defs.defined & _GD_Font) == 0)
3069 if (warningLevel > 5)
3071 WARN("No font specified for doodad %s\n", ddText(di));
3072 ACTION("Using \"%s\"\n", DFLT_FONT);
3074 di->font = xkb_intern_atom(DFLT_FONT);
3076 if ((di->defs.defined & _GD_FontSlant) == 0)
3078 if (warningLevel > 7)
3080 WARN("No font slant for text doodad %s\n", ddText(di));
3081 ACTION("Using \"%s\"\n", DFLT_SLANT);
3083 di->fontSlant = xkb_intern_atom(DFLT_SLANT);
3085 if ((di->defs.defined & _GD_FontWeight) == 0)
3087 if (warningLevel > 7)
3089 WARN("No font weight for text doodad %s\n", ddText(di));
3090 ACTION("Using \"%s\"\n", DFLT_WEIGHT);
3092 di->fontWeight = xkb_intern_atom(DFLT_WEIGHT);
3094 if ((di->defs.defined & _GD_FontSetWidth) == 0)
3096 if (warningLevel > 9)
3098 WARN("No font set width for text doodad %s\n", ddText(di));
3099 ACTION("Using \"%s\"\n", DFLT_SET_WIDTH);
3101 di->fontSetWidth = xkb_intern_atom(DFLT_SET_WIDTH);
3103 if ((di->defs.defined & _GD_FontVariant) == 0)
3105 if (warningLevel > 9)
3107 WARN("No font variant for text doodad %s\n", ddText(di));
3108 ACTION("Using \"%s\"\n", DFLT_VARIANT);
3110 di->fontVariant = xkb_intern_atom(DFLT_VARIANT);
3112 if ((di->defs.defined & _GD_FontEncoding) == 0)
3114 if (warningLevel > 7)
3116 WARN("No font encoding for doodad %s\n", ddText(di));
3117 ACTION("Using \"%s\"\n", DFLT_ENCODING);
3119 di->fontEncoding = xkb_intern_atom(DFLT_ENCODING);
3121 if ((di->defs.defined & _GD_FontSize) == 0)
3123 if (warningLevel > 7)
3125 WARN("No font size for text doodad %s\n", ddText(di));
3126 ACTION("Using %s point text\n", XkbcGeomFPText(DFLT_SIZE));
3128 di->fontSize = DFLT_SIZE;
3130 if ((di->defs.defined & _GD_Height) == 0)
3132 unsigned size, nLines;
3134 size = (di->fontSize * 120) / 100;
3135 size = (size * 254) / 720; /* convert to mm/10 */
3136 for (nLines = 1, tmp = XkbcAtomText(di->text); *tmp; tmp++)
3142 if (warningLevel > 5)
3144 WARN("No height for text doodad %s\n", ddText(di));
3145 ACTION("Using calculated height %s millimeters\n",
3146 XkbcGeomFPText(size));
3150 if ((di->defs.defined & _GD_Width) == 0)
3152 unsigned width, tmp;
3155 for (str = XkbcAtomText(di->text); *str; str++)
3168 width *= (di->height * 2) / 3;
3169 if (warningLevel > 5)
3171 WARN("No width for text doodad %s\n", ddText(di));
3172 ACTION("Using calculated width %s millimeters\n",
3173 XkbcGeomFPText(width));
3178 case XkbIndicatorDoodad:
3179 if ((di->defs.defined & _GD_Shape) == 0)
3181 ERROR("No shape defined for indicator doodad %s\n", ddText(di));
3182 ACTION("Incomplete definition ignored\n");
3188 si = FindShape(info, di->shape, "indicator doodad", ddText(di));
3190 di->shape = si->name;
3193 ERROR("No legal shape for doodad %s\n", ddText(di));
3194 ACTION("Incomplete definition ignored\n");
3198 if ((di->defs.defined & _GD_Color) == 0)
3200 if (warningLevel > 5)
3202 WARN("No \"on\" color for indicator doodad %s\n",
3204 ACTION("Using green\n");
3206 di->color = xkb_intern_atom("green");
3208 if ((di->defs.defined & _GD_OffColor) == 0)
3210 if (warningLevel > 5)
3212 WARN("No \"off\" color for indicator doodad %s\n",
3214 ACTION("Using black\n");
3216 di->offColor = xkb_intern_atom("black");
3220 if (di->logoName == NULL)
3222 ERROR("No logo name defined for logo doodad %s\n", ddText(di));
3223 ACTION("Incomplete definition ignored\n");
3226 if ((di->defs.defined & _GD_Shape) == 0)
3228 ERROR("No shape defined for logo doodad %s\n", ddText(di));
3229 ACTION("Incomplete definition ignored\n");
3235 si = FindShape(info, di->shape, "logo doodad",
3238 di->shape = si->name;
3241 ERROR("No legal shape for %s\n", ddText(di));
3242 ACTION("Incomplete definition ignored\n");
3246 if ((di->defs.defined & _GD_Color) == 0)
3248 if (warningLevel > 5)
3250 WARN("No color for doodad %s\n", ddText(di));
3251 ACTION("Using black\n");
3253 di->color = xkb_intern_atom("black");
3257 WSGO("Uknown doodad type %d in VerifyDoodad\n",
3258 (unsigned int) di->type);
3264 #define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
3267 FontFromParts(uint32_t fontTok,
3270 uint32_t setWidthTok, uint32_t varTok, int size, uint32_t encodingTok)
3273 const char *font, *weight, *slant, *setWidth, *variant, *encoding;
3276 font = (fontTok != None ? XkbcAtomText(fontTok) : DFLT_FONT);
3277 weight = (weightTok != None ? XkbcAtomText(weightTok) : DFLT_WEIGHT);
3278 slant = (slantTok != None ? XkbcAtomText(slantTok) : DFLT_SLANT);
3280 (setWidthTok != None ? XkbcAtomText(setWidthTok) : DFLT_SET_WIDTH);
3281 variant = (varTok != None ? XkbcAtomText(varTok) : DFLT_VARIANT);
3283 (encodingTok != None ? XkbcAtomText(encodingTok) : DFLT_ENCODING);
3287 strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
3288 totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
3289 rtrn = calloc(totalSize, 1);
3291 sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
3297 CopyDoodadDef(struct xkb_geometry * geom,
3298 struct xkb_section * section, DoodadInfo * di, GeometryInfo * info)
3301 union xkb_doodad * doodad;
3302 struct xkb_color * color;
3303 struct xkb_shape * shape;
3306 if (!VerifyDoodadInfo(di, info))
3309 doodad = XkbcAddGeomDoodad(geom, section, name);
3312 WSGO("Couldn't allocate doodad in %s\n",
3313 (section ? "section" : "geometry"));
3314 ACTION("Cannot copy doodad %s\n", ddText(di));
3317 doodad->any.type = di->type;
3318 doodad->any.priority = di->priority;
3319 doodad->any.top = di->top;
3320 doodad->any.left = di->left;
3323 case XkbOutlineDoodad:
3324 case XkbSolidDoodad:
3325 si = FindShape(info, di->shape, NULL, NULL);
3328 doodad->shape.angle = di->angle;
3329 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3331 shape = &geom->shapes[si->index];
3332 XkbSetShapeDoodadColor(geom, &doodad->shape, color);
3333 XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
3336 doodad->text.angle = di->angle;
3337 doodad->text.width = di->width;
3338 doodad->text.height = di->height;
3339 if (di->fontSpec == None)
3340 doodad->text.font = FontFromParts(di->font, di->fontWeight,
3343 di->fontVariant, di->fontSize,
3346 doodad->text.font = XkbcAtomGetString(di->fontSpec);
3347 doodad->text.text = XkbcAtomGetString(di->text);
3348 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3350 XkbSetTextDoodadColor(geom, &doodad->text, color);
3352 case XkbIndicatorDoodad:
3353 si = FindShape(info, di->shape, NULL, NULL);
3356 shape = &geom->shapes[si->index];
3357 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3359 XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
3360 XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
3361 color = XkbcAddGeomColor(geom, XkbcAtomText(di->offColor),
3363 XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
3366 si = FindShape(info, di->shape, NULL, NULL);
3369 doodad->logo.angle = di->angle;
3370 color = XkbcAddGeomColor(geom, XkbcAtomText(di->color),
3372 shape = &geom->shapes[si->index];
3373 XkbSetLogoDoodadColor(geom, &doodad->logo, color);
3374 XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
3375 doodad->logo.logo_name = di->logoName;
3376 di->logoName = NULL;
3382 /***====================================================================***/
3385 VerifyOverlayInfo(struct xkb_geometry * geom,
3386 struct xkb_section * section,
3388 GeometryInfo * info, short rowMap[256], short rowSize[256])
3390 register OverlayKeyInfo *ki, *next;
3391 unsigned long oKey, uKey, sKey;
3392 struct xkb_row * row;
3393 struct xkb_key * key;
3396 /* find out which row each key is in */
3397 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3399 oKey = KeyNameToLong(ki->over);
3400 uKey = KeyNameToLong(ki->under);
3401 for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
3404 for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
3407 sKey = KeyNameToLong(key->name.name);
3410 if (warningLevel > 0)
3413 ("Key %s in section \"%s\" and overlay \"%s\"\n",
3414 XkbcKeyNameText(key->name.name),
3415 XkbcAtomText(section->name),
3416 XkbcAtomText(oi->name));
3417 ACTION("Overlay definition ignored\n");
3421 else if (sKey == uKey)
3428 if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
3431 ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
3432 XkbcKeyNameText(ki->under),
3433 XkbcAtomText(section->name),
3434 XkbcAtomText(oi->name));
3435 ACTION("Definition ignored\n");
3438 /* now prune out keys that aren't in the section */
3439 while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
3441 next = (OverlayKeyInfo *) oi->keys->defs.next;
3446 for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
3448 next = (OverlayKeyInfo *) ki->defs.next;
3449 if (next->sectionRow == _GOK_UnknownRow)
3451 ki->defs.next = next->defs.next;
3454 next = (OverlayKeyInfo *) ki->defs.next;
3459 ERROR("Overlay \"%s\" for section \"%s\" has no legal keys\n",
3460 XkbcAtomText(oi->name), XkbcAtomText(section->name));
3461 ACTION("Overlay definition ignored\n");
3464 /* now figure out how many rows are defined for the overlay */
3465 bzero(rowSize, sizeof(short) * 256);
3466 for (k = 0; k < 256; k++)
3471 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3473 if (rowMap[ki->sectionRow] == -1)
3474 rowMap[ki->sectionRow] = oi->nRows++;
3475 ki->overlayRow = rowMap[ki->sectionRow];
3476 rowSize[ki->overlayRow]++;
3482 CopyOverlayDef(struct xkb_geometry * geom,
3483 struct xkb_section * section, OverlayInfo * oi, GeometryInfo * info)
3486 struct xkb_overlay * ol;
3487 struct xkb_overlay_row * row;
3488 struct xkb_overlay_key * key;
3490 short rowMap[256], rowSize[256];
3493 if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
3496 ol = XkbcAddGeomOverlay(section, name, oi->nRows);
3499 WSGO("Couldn't add overlay \"%s\" to section \"%s\"\n",
3500 XkbcAtomText(name), XkbcAtomText(section->name));
3503 for (i = 0; i < oi->nRows; i++)
3506 for (tmp = 0, row_under = -1;
3507 (tmp < section->num_rows) && (row_under < 0); tmp++)
3509 if (rowMap[tmp] == i)
3512 if (!XkbcAddGeomOverlayRow(ol, row_under, rowSize[i]))
3515 ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
3516 i, XkbcAtomText(name), XkbcAtomText(section->name));
3520 for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
3522 row = &ol->rows[ki->overlayRow];
3523 key = &row->keys[row->num_keys++];
3524 bzero(key, sizeof(struct xkb_overlay_key));
3525 strncpy(key->over.name, ki->over, XkbKeyNameLength);
3526 strncpy(key->under.name, ki->under, XkbKeyNameLength);
3531 /***====================================================================***/
3534 CopySectionDef(struct xkb_geometry * geom, SectionInfo * si, GeometryInfo * info)
3536 struct xkb_section * section;
3537 struct xkb_row * row;
3538 struct xkb_key * key;
3542 section = XkbcAddGeomSection(geom, si->name, si->nRows, si->nDoodads,
3544 if (section == NULL)
3546 WSGO("Couldn't allocate section in geometry\n");
3547 ACTION("Section %s not compiled\n", scText(si));
3550 section->top = si->top;
3551 section->left = si->left;
3552 section->width = si->width;
3553 section->height = si->height;
3554 section->angle = si->angle;
3555 section->priority = si->priority;
3556 for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
3558 row = XkbcAddGeomRow(section, ri->nKeys);
3561 WSGO("Couldn't allocate row in section\n");
3562 ACTION("Section %s is incomplete\n", scText(si));
3566 row->left = ri->left;
3567 row->vertical = ri->vertical;
3568 for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
3570 struct xkb_color * color;
3571 if ((ki->defs.defined & _GK_Name) == 0)
3573 ERROR("Key %d of row %d in section %s has no name\n",
3574 (int) ki->index, (int) ri->index, scText(si));
3575 ACTION("Section %s ignored\n", scText(si));
3578 key = XkbcAddGeomKey(row);
3581 WSGO("Couldn't allocate key in row\n");
3582 ACTION("Section %s is incomplete\n", scText(si));
3585 memcpy(key->name.name, ki->name, XkbKeyNameLength);
3587 if (ki->shape == None)
3592 si = FindShape(info, ki->shape, "key", keyText(ki));
3595 key->shape_ndx = si->index;
3597 if (ki->color != None)
3599 XkbcAddGeomColor(geom, XkbcAtomText(ki->color),
3602 color = XkbcAddGeomColor(geom, "white", geom->num_colors);
3603 XkbSetKeyColor(geom, key, color);
3606 if (si->doodads != NULL)
3609 for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
3611 CopyDoodadDef(geom, section, di, info);
3614 if (si->overlays != NULL)
3617 for (oi = si->overlays; oi != NULL;
3618 oi = (OverlayInfo *) oi->defs.next)
3620 CopyOverlayDef(geom, section, oi, info);
3623 if (XkbcComputeSectionBounds(geom, section))
3625 /* 7/6/94 (ef) -- check for negative origin and translate */
3626 if ((si->defs.defined & _GS_Width) == 0)
3627 section->width = section->bounds.x2;
3628 if ((si->defs.defined & _GS_Height) == 0)
3629 section->height = section->bounds.y2;
3634 /***====================================================================***/
3637 CompileGeometry(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
3641 InitGeometryInfo(&info, file->id, merge);
3642 HandleGeometryFile(file, xkb, merge, &info);
3644 if (info.errorCount == 0)
3646 struct xkb_geometry * geom;
3647 struct xkb_geometry_sizes sizes;
3648 bzero(&sizes, sizeof(sizes));
3649 sizes.which = XkbGeomAllMask;
3650 sizes.num_properties = info.nProps;
3651 sizes.num_colors = 8;
3652 sizes.num_shapes = info.nShapes;
3653 sizes.num_sections = info.nSections;
3654 sizes.num_doodads = info.nDoodads;
3655 if (XkbcAllocGeometry(xkb, &sizes) != Success)
3657 WSGO("Couldn't allocate GeometryRec\n");
3658 ACTION("Geometry not compiled\n");
3663 geom->width_mm = info.widthMM;
3664 geom->height_mm = info.heightMM;
3665 if (info.name != NULL)
3667 geom->name = xkb_intern_atom(info.name);
3668 if (XkbcAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
3669 xkb->names->geometry = geom->name;
3671 if (info.fontSpec != None)
3672 geom->label_font = XkbcAtomGetString(info.fontSpec);
3674 geom->label_font = FontFromParts(info.font, info.fontWeight,
3680 XkbcAddGeomColor(geom, "black", geom->num_colors);
3681 XkbcAddGeomColor(geom, "white", geom->num_colors);
3683 if (info.baseColor == None)
3684 info.baseColor = xkb_intern_atom("white");
3685 if (info.labelColor == None)
3686 info.labelColor = xkb_intern_atom("black");
3688 XkbcAddGeomColor(geom, XkbcAtomText(info.baseColor),
3691 XkbcAddGeomColor(geom, XkbcAtomText(info.labelColor),
3697 for (pi = info.props; pi != NULL;
3698 pi = (PropertyInfo *) pi->defs.next)
3700 if (!XkbcAddGeomProperty(geom, pi->name, pi->value))
3707 for (si = info.shapes; si != NULL;
3708 si = (ShapeInfo *) si->defs.next)
3710 if (!CopyShapeDef(geom, si))
3717 for (si = info.sections; si != NULL;
3718 si = (SectionInfo *) si->defs.next)
3720 if (!CopySectionDef(geom, si, &info))
3727 for (di = info.doodads; di != NULL;
3728 di = (DoodadInfo *) di->defs.next)
3730 if (!CopyDoodadDef(geom, NULL, di, &info))
3735 ApplyAliases(xkb, True, &info.aliases);
3736 ClearGeometryInfo(&info);