diff options
Diffstat (limited to 'xkbcomp/geometry.c')
-rw-r--r-- | xkbcomp/geometry.c | 7536 |
1 files changed, 3768 insertions, 3768 deletions
diff --git a/xkbcomp/geometry.c b/xkbcomp/geometry.c index b5c468bfc..6d2ca7f90 100644 --- a/xkbcomp/geometry.c +++ b/xkbcomp/geometry.c @@ -1,3768 +1,3768 @@ -/************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
-
- Permission to use, copy, modify, and distribute this
- software and its documentation for any purpose and without
- fee is hereby granted, provided that the above copyright
- notice appear in all copies and that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ********************************************************/
-
-#include "xkbcomp.h"
-#include "tokens.h"
-#include "expr.h"
-#include "vmod.h"
-#include "misc.h"
-#include "indicators.h"
-#include "action.h"
-#include "keycodes.h"
-#include "alias.h"
-
-#include "X11/extensions/XKBgeom.h"
-
-#define DFLT_FONT "helvetica"
-#define DFLT_SLANT "r"
-#define DFLT_WEIGHT "medium"
-#define DFLT_SET_WIDTH "normal"
-#define DFLT_VARIANT ""
-#define DFLT_ENCODING "iso8859-1"
-#define DFLT_SIZE 120
-
-typedef struct _PropertyInfo
-{
- CommonInfo defs;
- char *name;
- char *value;
-} PropertyInfo;
-
-#define _GSh_Outlines (1<<1)
-#define _GSh_Approx (1<<2)
-#define _GSh_Primary (1<<3)
-typedef struct _ShapeInfo
-{
- CommonInfo defs;
- Atom name;
- short index;
- unsigned short nOutlines;
- unsigned short szOutlines;
- XkbOutlinePtr outlines;
- XkbOutlinePtr approx;
- XkbOutlinePtr primary;
- int dfltCornerRadius;
-} ShapeInfo;
-
-#define shText(d,s) \
- ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default shape")
-
-#define _GD_Priority (1<<0)
-#define _GD_Top (1<<1)
-#define _GD_Left (1<<2)
-#define _GD_Angle (1<<3)
-#define _GD_Shape (1<<4)
-#define _GD_FontVariant (1<<4) /* CHEATING */
-#define _GD_Corner (1<<5)
-#define _GD_Width (1<<5) /* CHEATING */
-#define _GD_Color (1<<6)
-#define _GD_OffColor (1<<7)
-#define _GD_Height (1<<7) /* CHEATING */
-#define _GD_Text (1<<8)
-#define _GD_Font (1<<9)
-#define _GD_FontSlant (1<<10)
-#define _GD_FontWeight (1<<11)
-#define _GD_FontSetWidth (1<<12)
-#define _GD_FontSize (1<<13)
-#define _GD_FontEncoding (1<<14)
-#define _GD_FontSpec (1<<15)
-
-
-#define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant)
-
-typedef struct _DoodadInfo
-{
- CommonInfo defs;
- Atom name;
- unsigned char type;
- unsigned char priority;
- short top;
- short left;
- short angle;
- unsigned short corner;
- unsigned short width;
- unsigned short height;
- Atom shape;
- Atom color;
- Atom offColor;
- Atom text;
- Atom font;
- Atom fontSlant;
- Atom fontWeight;
- Atom fontSetWidth;
- Atom fontVariant;
- unsigned short fontSize;
- Atom fontEncoding;
- Atom fontSpec;
- char *logoName;
- struct _SectionInfo *section;
-} DoodadInfo;
-
-#define Yes 1
-#define No 0
-#define Undefined -1
-
-#define _GK_Default (1<<0)
-#define _GK_Name (1<<1)
-#define _GK_Gap (1<<2)
-#define _GK_Shape (1<<3)
-#define _GK_Color (1<<4)
-typedef struct _KeyInfo
-{
- CommonInfo defs;
- char name[8];
- short gap;
- short index;
- Atom shape;
- Atom color;
- struct _RowInfo *row;
-} KeyInfo;
-#define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default")
-
-#define _GR_Default (1<<0)
-#define _GR_Vertical (1<<1)
-#define _GR_Top (1<<2)
-#define _GR_Left (1<<3)
-typedef struct _RowInfo
-{
- CommonInfo defs;
- unsigned short top;
- unsigned short left;
- short index;
- Bool vertical;
- unsigned short nKeys;
- KeyInfo *keys;
- KeyInfo dfltKey;
- struct _SectionInfo *section;
-} RowInfo;
-#define rowText(d,r) \
- ((r)?XkbAtomText((d),(r)->section->name,XkbMessage):"default")
-
-#define _GOK_UnknownRow -1
-typedef struct _OverlayKeyInfo
-{
- CommonInfo defs;
- short sectionRow;
- short overlayRow;
- char over[XkbKeyNameLength + 1];
- char under[XkbKeyNameLength + 1];
-} OverlayKeyInfo;
-
-typedef struct _OverlayInfo
-{
- CommonInfo defs;
- Atom name;
- unsigned short nRows;
- unsigned short nKeys;
- OverlayKeyInfo *keys;
-} OverlayInfo;
-
-
-#define _GS_Default (1<<0)
-#define _GS_Name (1<<1)
-#define _GS_Top (1<<2)
-#define _GS_Left (1<<3)
-#define _GS_Width (1<<4)
-#define _GS_Height (1<<5)
-#define _GS_Angle (1<<6)
-#define _GS_Priority (1<<7)
-typedef struct _SectionInfo
-{
- CommonInfo defs;
- Atom name;
- unsigned short top;
- unsigned short left;
- unsigned short width;
- unsigned short height;
- unsigned short angle;
- unsigned short nRows;
- unsigned short nDoodads;
- unsigned short nOverlays;
- unsigned char priority;
- unsigned char nextDoodadPriority;
- RowInfo *rows;
- DoodadInfo *doodads;
- RowInfo dfltRow;
- DoodadInfo *dfltDoodads;
- OverlayInfo *overlays;
- struct _GeometryInfo *geometry;
-} SectionInfo;
-#define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default")
-
-typedef struct _GeometryInfo
-{
- char *name;
- Display *dpy;
- unsigned fileID;
- unsigned merge;
- int errorCount;
- unsigned nextPriority;
- int nProps;
- int nShapes;
- int nSections;
- int nDoodads;
- PropertyInfo *props;
- ShapeInfo *shapes;
- SectionInfo *sections;
- DoodadInfo *doodads;
- int widthMM;
- int heightMM;
- Atom font;
- Atom fontSlant;
- Atom fontWeight;
- Atom fontSetWidth;
- Atom fontVariant;
- unsigned fontSize;
- Atom fontEncoding;
- Atom fontSpec;
- Atom baseColor;
- Atom labelColor;
- int dfltCornerRadius;
- SectionInfo dfltSection;
- DoodadInfo *dfltDoodads;
- AliasInfo *aliases;
-} GeometryInfo;
-
-static char *
-ddText(Display * dpy, DoodadInfo * di)
-{
- static char buf[64];
-
- if (di == NULL)
- {
- strcpy(buf, "default");
- return buf;
- }
- if (di->section)
- {
- sprintf(buf, "%s in section %s",
- XkbAtomText(dpy, di->name, XkbMessage), scText(dpy,
- di->section));
- return buf;
- }
- return XkbAtomText(dpy, di->name, XkbMessage);
-}
-
-/***====================================================================***/
-
-static void
-InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info)
-{
- pi->defs.defined = 0;
- pi->defs.fileID = info->fileID;
- pi->defs.merge = info->merge;
- pi->name = pi->value = NULL;
- return;
-}
-
-static void
-FreeProperties(PropertyInfo * pi, GeometryInfo * info)
-{
- PropertyInfo *tmp;
- PropertyInfo *next;
-
- if (info->props == pi)
- {
- info->props = NULL;
- info->nProps = 0;
- }
- for (tmp = pi; tmp != NULL; tmp = next)
- {
- if (tmp->name)
- uFree(tmp->name);
- if (tmp->value)
- uFree(tmp->value);
- tmp->name = tmp->value = NULL;
- next = (PropertyInfo *) tmp->defs.next;
- uFree(tmp);
- }
- return;
-}
-
-static void
-InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info)
-{
-
- if (key != &row->dfltKey)
- {
- *key = row->dfltKey;
- strcpy(key->name, "unknown");
- key->defs.defined &= ~_GK_Default;
- }
- else
- {
- bzero(key, sizeof(KeyInfo));
- strcpy(key->name, "default");
- key->defs.defined = _GK_Default;
- key->defs.fileID = info->fileID;
- key->defs.merge = info->merge;
- key->defs.next = NULL;
- key->row = row;
- }
- return;
-}
-
-static void
-ClearKeyInfo(KeyInfo * key)
-{
- key->defs.defined &= ~_GK_Default;
- strcpy(key->name, "default");
- key->gap = 0;
- key->shape = None;
- key->color = None;
- return;
-}
-
-static void
-FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info)
-{
- KeyInfo *tmp;
- KeyInfo *next;
-
- if (row->keys == key)
- {
- row->nKeys = 0;
- row->keys = NULL;
- }
- for (tmp = key; tmp != NULL; tmp = next)
- {
- ClearKeyInfo(tmp);
- next = (KeyInfo *) tmp->defs.next;
- uFree(tmp);
- }
- return;
-}
-
-static void
-InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info)
-{
- if (row != §ion->dfltRow)
- {
- *row = section->dfltRow;
- row->defs.defined &= ~_GR_Default;
- }
- else
- {
- bzero(row, sizeof(RowInfo *));
- row->defs.defined = _GR_Default;
- row->defs.fileID = info->fileID;
- row->defs.merge = info->merge;
- row->defs.next = NULL;
- row->section = section;
- row->nKeys = 0;
- row->keys = NULL;
- InitKeyInfo(&row->dfltKey, row, info);
- }
- return;
-}
-
-static void
-ClearRowInfo(RowInfo * row, GeometryInfo * info)
-{
- row->defs.defined &= ~_GR_Default;
- row->top = row->left = 0;
- row->vertical = False;
- row->nKeys = 0;
- if (row->keys)
- FreeKeys(row->keys, row, info);
- ClearKeyInfo(&row->dfltKey);
- row->dfltKey.defs.defined |= _GK_Default;
- return;
-}
-
-static void
-FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info)
-{
- RowInfo *next;
- RowInfo *tmp;
-
- if (row == section->rows)
- {
- section->nRows = 0;
- section->rows = NULL;
- }
- for (tmp = row; tmp != NULL; tmp = next)
- {
- ClearRowInfo(tmp, info);
- next = (RowInfo *) tmp->defs.next;
- uFree(tmp);
- }
- return;
-}
-
-static DoodadInfo *
-FindDoodadByType(DoodadInfo * di, unsigned type)
-{
- while (di)
- {
- if (di->type == type)
- return di;
- di = (DoodadInfo *) di->defs.next;
- }
- return NULL;
-}
-
-static DoodadInfo *
-FindDoodadByName(DoodadInfo * di, Atom name)
-{
- while (di)
- {
- if (di->name == name)
- return di;
- di = (DoodadInfo *) di->defs.next;
- }
- return NULL;
-}
-
-static void
-InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si,
- GeometryInfo * info)
-{
- DoodadInfo *dflt;
-
- dflt = NULL;
- if (si && si->dfltDoodads)
- dflt = FindDoodadByType(si->dfltDoodads, type);
- if ((dflt == NULL) && (info->dfltDoodads))
- dflt = FindDoodadByType(info->dfltDoodads, type);
- if (dflt != NULL)
- {
- *di = *dflt;
- di->defs.next = NULL;
- }
- else
- {
- bzero(di, sizeof(DoodadInfo));
- di->defs.fileID = info->fileID;
- di->type = type;
- }
- di->section = si;
- if (si != NULL)
- {
- di->priority = si->nextDoodadPriority++;
-#if XkbGeomMaxPriority < 255
- if (si->nextDoodadPriority > XkbGeomMaxPriority)
- si->nextDoodadPriority = XkbGeomMaxPriority;
-#endif
- }
- else
- {
- di->priority = info->nextPriority++;
- if (info->nextPriority > XkbGeomMaxPriority)
- info->nextPriority = XkbGeomMaxPriority;
- }
- return;
-}
-
-static void
-ClearDoodadInfo(DoodadInfo * di)
-{
- CommonInfo defs;
-
- defs = di->defs;
- bzero(di, sizeof(DoodadInfo));
- di->defs = defs;
- di->defs.defined = 0;
- return;
-}
-
-static void
-ClearOverlayInfo(OverlayInfo * ol)
-{
- if (ol && ol->keys)
- {
- ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs);
- ol->nKeys = 0;
- }
- return;
-}
-
-static void
-FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info)
-{
- DoodadInfo *tmp;
- DoodadInfo *next;
-
- if (si)
- {
- if (si->doodads == di)
- {
- si->doodads = NULL;
- si->nDoodads = 0;
- }
- if (si->dfltDoodads == di)
- si->dfltDoodads = NULL;
- }
- if (info->doodads == di)
- {
- info->doodads = NULL;
- info->nDoodads = 0;
- }
- if (info->dfltDoodads == di)
- info->dfltDoodads = NULL;
- for (tmp = di; tmp != NULL; tmp = next)
- {
- next = (DoodadInfo *) tmp->defs.next;
- ClearDoodadInfo(tmp);
- uFree(tmp);
- }
- return;
-}
-
-static void
-InitSectionInfo(SectionInfo * si, GeometryInfo * info)
-{
- if (si != &info->dfltSection)
- {
- *si = info->dfltSection;
- si->defs.defined &= ~_GS_Default;
- si->name = XkbInternAtom(info->dpy, "unknown", False);
- si->priority = info->nextPriority++;
- if (info->nextPriority > XkbGeomMaxPriority)
- info->nextPriority = XkbGeomMaxPriority;
- }
- else
- {
- bzero(si, sizeof(SectionInfo));
- si->defs.fileID = info->fileID;
- si->defs.merge = info->merge;
- si->defs.next = NULL;
- si->geometry = info;
- si->name = XkbInternAtom(info->dpy, "default", False);
- InitRowInfo(&si->dfltRow, si, info);
- }
- return;
-}
-
-static void
-DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info)
-{
- CommonInfo defs;
-
- defs = into->defs;
- *into = *from;
- into->defs.fileID = defs.fileID;
- into->defs.merge = defs.merge;
- into->defs.next = NULL;
- into->dfltRow.defs.fileID = defs.fileID;
- into->dfltRow.defs.merge = defs.merge;
- into->dfltRow.defs.next = NULL;
- into->dfltRow.section = into;
- into->dfltRow.dfltKey.defs.fileID = defs.fileID;
- into->dfltRow.dfltKey.defs.merge = defs.merge;
- into->dfltRow.dfltKey.defs.next = NULL;
- into->dfltRow.dfltKey.row = &into->dfltRow;
- return;
-}
-
-static void
-ClearSectionInfo(SectionInfo * si, GeometryInfo * info)
-{
-
- si->defs.defined &= ~_GS_Default;
- si->name = XkbInternAtom(info->dpy, "default", False);
- si->top = si->left = 0;
- si->width = si->height = 0;
- si->angle = 0;
- if (si->rows)
- {
- FreeRows(si->rows, si, info);
- si->rows = NULL;
- }
- ClearRowInfo(&si->dfltRow, info);
- if (si->doodads)
- {
- FreeDoodads(si->doodads, si, info);
- si->doodads = NULL;
- }
- si->dfltRow.defs.defined = _GR_Default;
- return;
-}
-
-static void
-FreeSections(SectionInfo * si, GeometryInfo * info)
-{
- SectionInfo *tmp;
- SectionInfo *next;
-
- if (si == info->sections)
- {
- info->nSections = 0;
- info->sections = NULL;
- }
- for (tmp = si; tmp != NULL; tmp = next)
- {
- ClearSectionInfo(tmp, info);
- next = (SectionInfo *) tmp->defs.next;
- uFree(tmp);
- }
- return;
-}
-
-static void
-FreeShapes(ShapeInfo * si, GeometryInfo * info)
-{
- ShapeInfo *tmp;
- ShapeInfo *next;
-
- if (si == info->shapes)
- {
- info->nShapes = 0;
- info->shapes = NULL;
- }
- for (tmp = si; tmp != NULL; tmp = next)
- {
- if (tmp->outlines)
- {
- register int i;
- for (i = 0; i < tmp->nOutlines; i++)
- {
- if (tmp->outlines[i].points != NULL)
- {
- uFree(tmp->outlines[i].points);
- tmp->outlines[i].num_points = 0;
- tmp->outlines[i].points = NULL;
- }
- }
- uFree(tmp->outlines);
- tmp->szOutlines = 0;
- tmp->nOutlines = 0;
- tmp->outlines = NULL;
- tmp->primary = tmp->approx = NULL;
- }
- next = (ShapeInfo *) tmp->defs.next;
- uFree(tmp);
- }
- return;
-}
-
-/***====================================================================***/
-
-static void
-InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge)
-{
- bzero(info, sizeof(GeometryInfo));
- info->fileID = fileID;
- info->merge = merge;
- InitSectionInfo(&info->dfltSection, info);
- info->dfltSection.defs.defined = _GS_Default;
- return;
-}
-
-static void
-ClearGeometryInfo(GeometryInfo * info)
-{
- if (info->name)
- uFree(info->name);
- info->name = NULL;
- if (info->props)
- FreeProperties(info->props, info);
- if (info->shapes)
- FreeShapes(info->shapes, info);
- if (info->sections)
- FreeSections(info->sections, info);
- info->widthMM = 0;
- info->heightMM = 0;
- info->dfltCornerRadius = 0;
- ClearSectionInfo(&info->dfltSection, info);
- info->dfltSection.defs.defined = _GS_Default;
- if (info->aliases)
- ClearAliases(&info->aliases);
- return;
-}
-
-/***====================================================================***/
-
-static PropertyInfo *
-NextProperty(GeometryInfo * info)
-{
- PropertyInfo *pi;
-
- pi = uTypedAlloc(PropertyInfo);
- if (pi)
- {
- bzero((char *) pi, sizeof(PropertyInfo));
- info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs,
- (CommonInfo *) pi);
- info->nProps++;
- }
- return pi;
-}
-
-static PropertyInfo *
-FindProperty(GeometryInfo * info, char *name)
-{
- PropertyInfo *old;
-
- if (!name)
- return NULL;
- for (old = info->props; old != NULL;
- old = (PropertyInfo *) old->defs.next)
- {
- if ((old->name) && (uStringEqual(name, old->name)))
- return old;
- }
- return NULL;
-}
-
-static Bool
-AddProperty(GeometryInfo * info, PropertyInfo * new)
-{
- PropertyInfo *old;
-
- if ((!new) || (!new->value) || (!new->name))
- return False;
- old = FindProperty(info, new->name);
- if (old != NULL)
- {
- if ((new->defs.merge == MergeReplace)
- || (new->defs.merge == MergeOverride))
- {
- if (((old->defs.fileID == new->defs.fileID)
- && (warningLevel > 0)) || (warningLevel > 9))
- {
- WARN1("Multiple definitions for the \"%s\" property\n",
- new->name);
- ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value,
- new->value);
- }
- if (old->value)
- uFree(old->value);
- old->value = uStringDup(new->value);
- return True;
- }
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple definitions for \"%s\" property\n", new->name);
- ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value,
- new->value);
- }
- return True;
- }
- old = new;
- if ((new = NextProperty(info)) == NULL)
- return False;
- new->defs.next = NULL;
- new->name = uStringDup(old->name);
- new->value = uStringDup(old->value);
- return True;
-}
-
-/***====================================================================***/
-
-static ShapeInfo *
-NextShape(GeometryInfo * info)
-{
- ShapeInfo *si;
-
- si = uTypedAlloc(ShapeInfo);
- if (si)
- {
- bzero((char *) si, sizeof(ShapeInfo));
- info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs,
- (CommonInfo *) si);
- info->nShapes++;
- si->dfltCornerRadius = info->dfltCornerRadius;
- }
- return si;
-}
-
-static ShapeInfo *
-FindShape(GeometryInfo * info, Atom name, const char *type, const char *which)
-{
- ShapeInfo *old;
-
- for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next)
- {
- if (name == old->name)
- return old;
- }
- if (type != NULL)
- {
- old = info->shapes;
- WARN3("Unknown shape \"%s\" for %s %s\n",
- XkbAtomText(info->dpy, name, XkbMessage), type, which);
- if (old)
- {
- ACTION1("Using default shape %s instead\n",
- shText(info->dpy, old));
- return old;
- }
- ACTION("No default shape; definition ignored\n");
- return NULL;
- }
- return NULL;
-}
-
-static Bool
-AddShape(GeometryInfo * info, ShapeInfo * new)
-{
- ShapeInfo *old;
-
- old = FindShape(info, new->name, NULL, NULL);
- if (old != NULL)
- {
- if ((new->defs.merge == MergeReplace)
- || (new->defs.merge == MergeOverride))
- {
- ShapeInfo *next = (ShapeInfo *) old->defs.next;
- if (((old->defs.fileID == new->defs.fileID)
- && (warningLevel > 0)) || (warningLevel > 9))
- {
- WARN1("Duplicate shape name \"%s\"\n",
- shText(info->dpy, old));
- ACTION("Using last definition\n");
- }
- *old = *new;
- old->defs.next = &next->defs;
- return True;
- }
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
- ACTION("Using first definition\n");
- }
- return True;
- }
- old = new;
- if ((new = NextShape(info)) == NULL)
- return False;
- *new = *old;
- new->defs.next = NULL;
- old->szOutlines = old->nOutlines = 0;
- old->outlines = NULL;
- old->approx = NULL;
- old->primary = NULL;
- return True;
-}
-
-/***====================================================================***/
-
-static void
-ReplaceDoodad(DoodadInfo * into, DoodadInfo * from)
-{
- CommonInfo *next;
-
- next = into->defs.next;
- ClearDoodadInfo(into);
- *into = *from;
- into->defs.next = next;
- next = from->defs.next;
- ClearDoodadInfo(from);
- from->defs.next = next;
- return;
-}
-
-static DoodadInfo *
-NextDfltDoodad(SectionInfo * si, GeometryInfo * info)
-{
- DoodadInfo *di;
-
- di = uTypedCalloc(1, DoodadInfo);
- if (!di)
- return NULL;
- if (si)
- {
- si->dfltDoodads =
- (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs,
- (CommonInfo *) di);
- }
- else
- {
- info->dfltDoodads =
- (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs,
- (CommonInfo *) di);
- }
- return di;
-}
-
-static DoodadInfo *
-NextDoodad(SectionInfo * si, GeometryInfo * info)
-{
- DoodadInfo *di;
-
- di = uTypedCalloc(1, DoodadInfo);
- if (di)
- {
- if (si)
- {
- si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs,
- (CommonInfo *) di);
- si->nDoodads++;
- }
- else
- {
- info->doodads =
- (DoodadInfo *) AddCommonInfo(&info->doodads->defs,
- (CommonInfo *) di);
- info->nDoodads++;
- }
- }
- return di;
-}
-
-static Bool
-AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
-{
- DoodadInfo *old;
-
- old = FindDoodadByName((si ? si->doodads : info->doodads), new->name);
- if (old != NULL)
- {
- if ((new->defs.merge == MergeReplace)
- || (new->defs.merge == MergeOverride))
- {
- if (((old->defs.fileID == new->defs.fileID)
- && (warningLevel > 0)) || (warningLevel > 9))
- {
- WARN1("Multiple doodads named \"%s\"\n",
- XkbAtomText(info->dpy, old->name, XkbMessage));
- ACTION("Using last definition\n");
- }
- ReplaceDoodad(old, new);
- old->section = si;
- return True;
- }
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple doodads named \"%s\"\n",
- XkbAtomText(info->dpy, old->name, XkbMessage));
- ACTION("Using first definition\n");
- }
- return True;
- }
- old = new;
- if ((new = NextDoodad(si, info)) == NULL)
- return False;
- ReplaceDoodad(new, old);
- new->section = si;
- new->defs.next = NULL;
- return True;
-}
-
-static DoodadInfo *
-FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
-{
- DoodadInfo *dflt;
- unsigned type;
-
- if (uStrCaseCmp(name, "outline") == 0)
- type = XkbOutlineDoodad;
- else if (uStrCaseCmp(name, "solid") == 0)
- type = XkbSolidDoodad;
- else if (uStrCaseCmp(name, "text") == 0)
- type = XkbTextDoodad;
- else if (uStrCaseCmp(name, "indicator") == 0)
- type = XkbIndicatorDoodad;
- else if (uStrCaseCmp(name, "logo") == 0)
- type = XkbLogoDoodad;
- else
- return NULL;
- if ((si) && (si->dfltDoodads))
- dflt = FindDoodadByType(si->dfltDoodads, type);
- else
- dflt = NULL;
- if ((!dflt) && (info->dfltDoodads))
- dflt = FindDoodadByType(info->dfltDoodads, type);
- if (dflt == NULL)
- {
- dflt = NextDfltDoodad(si, info);
- if (dflt != NULL)
- {
- dflt->name = None;
- dflt->type = type;
- }
- }
- return dflt;
-}
-
-/***====================================================================***/
-
-static Bool
-AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new)
-{
- OverlayInfo *old;
-
- for (old = si->overlays; old != NULL;
- old = (OverlayInfo *) old->defs.next)
- {
- if (old->name == new->name)
- break;
- }
- if (old != NULL)
- {
- if ((new->defs.merge == MergeReplace)
- || (new->defs.merge == MergeOverride))
- {
- if (((old->defs.fileID == new->defs.fileID)
- && (warningLevel > 0)) || (warningLevel > 9))
- {
- WARN2
- ("Multiple overlays named \"%s\" for section \"%s\"\n",
- XkbAtomText(info->dpy, old->name, XkbMessage),
- XkbAtomText(info->dpy, si->name, XkbMessage));
- ACTION("Using last definition\n");
- }
- ClearOverlayInfo(old);
- old->nKeys = new->nKeys;
- old->keys = new->keys;
- new->nKeys = 0;
- new->keys = NULL;
- return True;
- }
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN2("Multiple doodads named \"%s\" in section \"%s\"\n",
- XkbAtomText(info->dpy, old->name, XkbMessage),
- XkbAtomText(info->dpy, si->name, XkbMessage));
- ACTION("Using first definition\n");
- }
- return True;
- }
- old = new;
- new = uTypedCalloc(1, OverlayInfo);
- if (!new)
- {
- if (warningLevel > 0)
- {
- WSGO("Couldn't allocate a new OverlayInfo\n");
- ACTION2
- ("Overlay \"%s\" in section \"%s\" will be incomplete\n",
- XkbAtomText(info->dpy, old->name, XkbMessage),
- XkbAtomText(info->dpy, si->name, XkbMessage));
- }
- return False;
- }
- *new = *old;
- old->nKeys = 0;
- old->keys = NULL;
- si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs,
- (CommonInfo *) new);
- si->nOverlays++;
- return True;
-}
-
-/***====================================================================***/
-
-static SectionInfo *
-NextSection(GeometryInfo * info)
-{
- SectionInfo *si;
-
- si = uTypedAlloc(SectionInfo);
- if (si)
- {
- *si = info->dfltSection;
- si->defs.defined &= ~_GS_Default;
- si->defs.next = NULL;
- si->nRows = 0;
- si->rows = NULL;
- info->sections =
- (SectionInfo *) AddCommonInfo(&info->sections->defs,
- (CommonInfo *) si);
- info->nSections++;
- }
- return si;
-}
-
-static SectionInfo *
-FindMatchingSection(GeometryInfo * info, SectionInfo * new)
-{
- SectionInfo *old;
-
- for (old = info->sections; old != NULL;
- old = (SectionInfo *) old->defs.next)
- {
- if (new->name == old->name)
- return old;
- }
- return NULL;
-}
-
-static Bool
-AddSection(GeometryInfo * info, SectionInfo * new)
-{
- SectionInfo *old;
-
- old = FindMatchingSection(info, new);
- if (old != NULL)
- {
-#ifdef NOTDEF
- if ((new->defs.merge == MergeReplace)
- || (new->defs.merge == MergeOverride))
- {
- SectionInfo *next = (SectionInfo *) old->defs.next;
- if (((old->defs.fileID == new->defs.fileID)
- && (warningLevel > 0)) || (warningLevel > 9))
- {
- WARN1("Duplicate shape name \"%s\"\n",
- shText(info->dpy, old));
- ACTION("Using last definition\n");
- }
- *old = *new;
- old->defs.next = &next->defs;
- return True;
- }
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old));
- ACTION("Using first definition\n");
- }
- return True;
-#else
- WARN("Don't know how to merge sections yet\n");
-#endif
- }
- old = new;
- if ((new = NextSection(info)) == NULL)
- return False;
- *new = *old;
- new->defs.next = NULL;
- old->nRows = old->nDoodads = old->nOverlays = 0;
- old->rows = NULL;
- old->doodads = NULL;
- old->overlays = NULL;
- if (new->doodads)
- {
- DoodadInfo *di;
- for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next)
- {
- di->section = new;
- }
- }
- return True;
-}
-
-/***====================================================================***/
-
-static RowInfo *
-NextRow(SectionInfo * si)
-{
- RowInfo *row;
-
- row = uTypedAlloc(RowInfo);
- if (row)
- {
- *row = si->dfltRow;
- row->defs.defined &= ~_GR_Default;
- row->defs.next = NULL;
- row->nKeys = 0;
- row->keys = NULL;
- si->rows =
- (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row);
- row->index = si->nRows++;
- }
- return row;
-}
-
-static Bool
-AddRow(SectionInfo * si, RowInfo * new)
-{
- RowInfo *old;
-
- old = new;
- if ((new = NextRow(si)) == NULL)
- return False;
- *new = *old;
- new->defs.next = NULL;
- old->nKeys = 0;
- old->keys = NULL;
- return True;
-}
-
-/***====================================================================***/
-
-static KeyInfo *
-NextKey(RowInfo * row)
-{
- KeyInfo *key;
-
- key = uTypedAlloc(KeyInfo);
- if (key)
- {
- *key = row->dfltKey;
- key->defs.defined &= ~_GK_Default;
- key->defs.next = NULL;
- key->index = row->nKeys++;
- }
- return key;
-}
-
-static Bool
-AddKey(RowInfo * row, KeyInfo * new)
-{
- KeyInfo *old;
-
- old = new;
- if ((new = NextKey(row)) == NULL)
- return False;
- *new = *old;
- new->defs.next = NULL;
- row->keys =
- (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new);
- return True;
-}
-
-/***====================================================================***/
-
-static void
-MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from,
- unsigned merge)
-{
- Bool clobber;
-
- if (from->errorCount > 0)
- {
- into->errorCount += from->errorCount;
- return;
- }
- clobber = (merge == MergeOverride) || (merge == MergeReplace);
- if (into->name == NULL)
- {
- into->name = from->name;
- from->name = NULL;
- }
- if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber))
- into->widthMM = from->widthMM;
- if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber))
- into->heightMM = from->heightMM;
- if ((into->font == None) || ((from->font != None) && clobber))
- into->font = from->font;
- if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber))
- into->fontSlant = from->fontSlant;
- if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber))
- into->fontWeight = from->fontWeight;
- if ((into->fontSetWidth == None)
- || ((from->fontSetWidth != None) && clobber))
- into->fontSetWidth = from->fontSetWidth;
- if ((into->fontVariant == None)
- || ((from->fontVariant != None) && clobber))
- into->fontVariant = from->fontVariant;
- if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber))
- into->fontSize = from->fontSize;
- if ((into->fontEncoding == None)
- || ((from->fontEncoding != None) && clobber))
- into->fontEncoding = from->fontEncoding;
- if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber))
- into->fontSpec = from->fontSpec;
- if ((into->baseColor == None) || ((from->baseColor != None) && clobber))
- into->baseColor = from->baseColor;
- if ((into->labelColor == None) || ((from->labelColor != None) && clobber))
- into->labelColor = from->labelColor;
- into->nextPriority = from->nextPriority;
- if (from->props != NULL)
- {
- PropertyInfo *pi;
- for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next)
- {
- if (!AddProperty(into, pi))
- into->errorCount++;
- }
- }
- if (from->shapes != NULL)
- {
- ShapeInfo *si;
-
- for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next)
- {
- if (!AddShape(into, si))
- into->errorCount++;
- }
- }
- if (from->sections != NULL)
- {
- SectionInfo *si;
-
- for (si = from->sections; si; si = (SectionInfo *) si->defs.next)
- {
- if (!AddSection(into, si))
- into->errorCount++;
- }
- }
- if (from->doodads != NULL)
- {
- DoodadInfo *di;
-
- for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next)
- {
- if (!AddDoodad(NULL, into, di))
- into->errorCount++;
- }
- }
- if (!MergeAliases(&into->aliases, &from->aliases, merge))
- into->errorCount++;
- return;
-}
-
-typedef void (*FileHandler) (XkbFile * /* file */ ,
- XkbDescPtr /* xkb */ ,
- unsigned /* merge */ ,
- GeometryInfo * /* info */
- );
-
-static Bool
-HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info,
- FileHandler hndlr)
-{
- unsigned newMerge;
- XkbFile *rtrn;
- GeometryInfo included;
- Bool haveSelf;
-
- haveSelf = False;
- if ((stmt->file == NULL) && (stmt->map == NULL))
- {
- haveSelf = True;
- included = *info;
- bzero(info, sizeof(GeometryInfo));
- }
- else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge))
- {
- InitGeometryInfo(&included, rtrn->id, newMerge);
- included.nextPriority = info->nextPriority;
- included.dfltCornerRadius = info->dfltCornerRadius;
- DupSectionInfo(&included.dfltSection, &info->dfltSection, info);
- (*hndlr) (rtrn, xkb, MergeOverride, &included);
- if (stmt->stmt != NULL)
- {
- if (included.name != NULL)
- uFree(included.name);
- included.name = stmt->stmt;
- stmt->stmt = NULL;
- }
- }
- else
- {
- info->errorCount += 10;
- return False;
- }
- if ((stmt->next != NULL) && (included.errorCount < 1))
- {
- IncludeStmt *next;
- unsigned op;
- GeometryInfo next_incl;
-
- for (next = stmt->next; next != NULL; next = next->next)
- {
- if ((next->file == NULL) && (next->map == NULL))
- {
- haveSelf = True;
- MergeIncludedGeometry(&included, info, next->merge);
- ClearGeometryInfo(info);
- }
- else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op))
- {
- InitGeometryInfo(&next_incl, rtrn->id, op);
- next_incl.nextPriority = included.nextPriority;
- next_incl.dfltCornerRadius = included.dfltCornerRadius;
- DupSectionInfo(&next_incl.dfltSection,
- &included.dfltSection, &included);
- (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
- MergeIncludedGeometry(&included, &next_incl, op);
- ClearGeometryInfo(&next_incl);
- }
- else
- {
- info->errorCount += 10;
- return False;
- }
- }
- }
- if (haveSelf)
- *info = included;
- else
- {
- MergeIncludedGeometry(info, &included, newMerge);
- ClearGeometryInfo(&included);
- }
- return (info->errorCount == 0);
-}
-
-static int
-SetShapeField(ShapeInfo * si,
- char *field,
- ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
-{
- ExprResult tmp;
-
- if ((uStrCaseCmp(field, "radius") == 0)
- || (uStrCaseCmp(field, "corner") == 0)
- || (uStrCaseCmp(field, "cornerradius") == 0))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("key shape", field, shText(info->dpy, si));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("key shape", field,
- shText(info->dpy, si), "number");
- }
- if (si)
- si->dfltCornerRadius = tmp.ival;
- else
- info->dfltCornerRadius = tmp.ival;
- return True;
- }
- info->errorCount++;
- return ReportBadField("key shape", field, shText(info->dpy, si));
-}
-
-static int
-SetShapeDoodadField(DoodadInfo * di,
- char *field,
- ExprDef * arrayNdx,
- ExprDef * value, SectionInfo * si, GeometryInfo * info)
-{
- ExprResult tmp;
- const char *typeName;
-
- typeName =
- (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad");
- if ((!uStrCaseCmp(field, "corner"))
- || (!uStrCaseCmp(field, "cornerradius")))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Corner;
- di->corner = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "angle") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Angle;
- di->angle = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "shape") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "string");
- }
- di->shape = XkbInternAtom(info->dpy, tmp.str, False);
- di->defs.defined |= _GD_Shape;
- return True;
- }
- return ReportBadField(typeName, field, ddText(info->dpy, di));
-}
-
-#define FIELD_STRING 0
-#define FIELD_SHORT 1
-#define FIELD_USHORT 2
-
-static int
-SetTextDoodadField(DoodadInfo * di,
- char *field,
- ExprDef * arrayNdx,
- ExprDef * value, SectionInfo * si, GeometryInfo * info)
-{
- ExprResult tmp;
- unsigned def;
- unsigned type;
- char *typeName = "text doodad";
- union
- {
- Atom *str;
- short *ival;
- unsigned short *uval;
- } pField;
-
- if (uStrCaseCmp(field, "angle") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Angle;
- di->angle = tmp.ival;
- return True;
- }
- if (uStrCaseCmp(field, "width") == 0)
- {
- type = FIELD_USHORT;
- pField.uval = &di->width;
- def = _GD_Width;
- }
- else if (uStrCaseCmp(field, "height") == 0)
- {
- type = FIELD_USHORT;
- pField.uval = &di->height;
- def = _GD_Height;
- }
- else if (uStrCaseCmp(field, "text") == 0)
- {
- type = FIELD_STRING;
- pField.str = &di->text;
- def = _GD_Text;
- }
- else if (uStrCaseCmp(field, "font") == 0)
- {
- type = FIELD_STRING;
- pField.str = &di->font;
- def = _GD_Font;
- }
- else if ((uStrCaseCmp(field, "fontslant") == 0) ||
- (uStrCaseCmp(field, "slant") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontSlant;
- def = _GD_FontSlant;
- }
- else if ((uStrCaseCmp(field, "fontweight") == 0) ||
- (uStrCaseCmp(field, "weight") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontWeight;
- def = _GD_FontWeight;
- }
- else if ((uStrCaseCmp(field, "fontwidth") == 0) ||
- (uStrCaseCmp(field, "setwidth") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontSetWidth;
- def = _GD_FontSetWidth;
- }
- else if ((uStrCaseCmp(field, "fontvariant") == 0) ||
- (uStrCaseCmp(field, "variant") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontVariant;
- def = _GD_FontVariant;
- }
- else if ((uStrCaseCmp(field, "fontencoding") == 0) ||
- (uStrCaseCmp(field, "encoding") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontEncoding;
- def = _GD_FontEncoding;
- }
- else if ((uStrCaseCmp(field, "xfont") == 0) ||
- (uStrCaseCmp(field, "xfontname") == 0))
- {
- type = FIELD_STRING;
- pField.str = &di->fontSpec;
- def = _GD_FontSpec;
- }
- else if (uStrCaseCmp(field, "fontsize") == 0)
- {
- type = FIELD_USHORT;
- pField.uval = &di->fontSize;
- def = _GD_FontSize;
- }
- else
- {
- return ReportBadField(typeName, field, ddText(info->dpy, di));
- }
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (type == FIELD_STRING)
- {
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "string");
- }
- di->defs.defined |= def;
- *pField.str = XkbInternAtom(NULL, tmp.str, False);
- }
- else
- {
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- if ((type == FIELD_USHORT) && (tmp.ival < 0))
- {
- info->errorCount++;
- return
- ReportBadType(typeName, field, ddText(info->dpy, di),
- "unsigned");
- }
- di->defs.defined |= def;
- if (type == FIELD_USHORT)
- *pField.uval = tmp.uval;
- else
- *pField.ival = tmp.ival;
- }
- return True;
-}
-
-static int
-SetIndicatorDoodadField(DoodadInfo * di,
- char *field,
- ExprDef * arrayNdx,
- ExprDef * value,
- SectionInfo * si, GeometryInfo * info)
-{
- ExprResult tmp;
-
- if ((uStrCaseCmp(field, "oncolor") == 0)
- || (uStrCaseCmp(field, "offcolor") == 0)
- || (uStrCaseCmp(field, "shape") == 0))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("indicator doodad", field,
- ddText(info->dpy, di));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("indicator doodad", field,
- ddText(info->dpy, di), "string");
- }
- if (uStrCaseCmp(field, "oncolor") == 0)
- {
- di->defs.defined |= _GD_Color;
- di->color = XkbInternAtom(NULL, tmp.str, False);
- }
- else if (uStrCaseCmp(field, "offcolor") == 0)
- {
- di->defs.defined |= _GD_OffColor;
- di->offColor = XkbInternAtom(NULL, tmp.str, False);
- }
- else if (uStrCaseCmp(field, "shape") == 0)
- {
- di->defs.defined |= _GD_Shape;
- di->shape = XkbInternAtom(info->dpy, tmp.str, False);
- }
- return True;
- }
- return ReportBadField("indicator doodad", field, ddText(info->dpy, di));
-}
-
-static int
-SetLogoDoodadField(DoodadInfo * di,
- char *field,
- ExprDef * arrayNdx,
- ExprDef * value, SectionInfo * si, GeometryInfo * info)
-{
- ExprResult tmp;
- char *typeName = "logo doodad";
-
- if ((!uStrCaseCmp(field, "corner"))
- || (!uStrCaseCmp(field, "cornerradius")))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Corner;
- di->corner = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "angle") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Angle;
- di->angle = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "shape") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "string");
- }
- di->shape = XkbInternAtom(info->dpy, tmp.str, False);
- di->defs.defined |= _GD_Shape;
- return True;
- }
- else if ((!uStrCaseCmp(field, "logoname"))
- || (!uStrCaseCmp(field, "name")))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray(typeName, field, ddText(info->dpy, di));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType(typeName, field, ddText(info->dpy, di),
- "string");
- }
- di->logoName = uStringDup(tmp.str);
- return True;
- }
- return ReportBadField(typeName, field, ddText(info->dpy, di));
-}
-
-static int
-SetDoodadField(DoodadInfo * di,
- char *field,
- ExprDef * arrayNdx,
- ExprDef * value, SectionInfo * si, GeometryInfo * info)
-{
- ExprResult tmp;
-
- if (uStrCaseCmp(field, "priority") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("doodad", field, ddText(info->dpy, di));
- }
- if (!ExprResolveInteger(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("doodad", field, ddText(info->dpy, di),
- "integer");
- }
- if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
- {
- info->errorCount++;
- ERROR2("Doodad priority %d out of range (must be 0..%d)\n",
- tmp.ival, XkbGeomMaxPriority);
- ACTION1("Priority for doodad %s not changed",
- ddText(info->dpy, di));
- return False;
- }
- di->defs.defined |= _GD_Priority;
- di->priority = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "left") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("doodad", field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("doodad", field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Left;
- di->left = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "top") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("doodad", field, ddText(info->dpy, di));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("doodad", field, ddText(info->dpy, di),
- "number");
- }
- di->defs.defined |= _GD_Top;
- di->top = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field, "color") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("doodad", field, ddText(info->dpy, di));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("doodad", field, ddText(info->dpy, di),
- "string");
- }
- di->defs.defined |= _GD_Color;
- di->color = XkbInternAtom(NULL, tmp.str, False);
- return True;
- }
- switch (di->type)
- {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- return SetShapeDoodadField(di, field, arrayNdx, value, si, info);
- case XkbTextDoodad:
- return SetTextDoodadField(di, field, arrayNdx, value, si, info);
- case XkbIndicatorDoodad:
- return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info);
- case XkbLogoDoodad:
- return SetLogoDoodadField(di, field, arrayNdx, value, si, info);
- }
- WSGO1("Unknown doodad type %d in SetDoodadField\n",
- (unsigned int) di->type);
- ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di));
- return False;
-}
-
-static int
-SetSectionField(SectionInfo * si,
- char *field,
- ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
-{
- unsigned short *pField;
- unsigned def;
- ExprResult tmp;
-
- pField = NULL;
- def = 0;
- if (uStrCaseCmp(field, "priority") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard section", field,
- scText(info->dpy, si));
- }
- if (!ExprResolveInteger(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- ReportBadType("keyboard section", field,
- scText(info->dpy, si), "integer");
- return False;
- }
- if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority))
- {
- info->errorCount++;
- ERROR2("Section priority %d out of range (must be 0..%d)\n",
- tmp.ival, XkbGeomMaxPriority);
- ACTION1("Priority for section %s not changed",
- scText(info->dpy, si));
- return False;
- }
- si->priority = tmp.ival;
- si->defs.defined |= _GS_Priority;
- return True;
- }
- else if (uStrCaseCmp(field, "top") == 0)
- {
- pField = &si->top;
- def = _GS_Top;
- }
- else if (uStrCaseCmp(field, "left") == 0)
- {
- pField = &si->left;
- def = _GS_Left;
- }
- else if (uStrCaseCmp(field, "width") == 0)
- {
- pField = &si->width;
- def = _GS_Width;
- }
- else if (uStrCaseCmp(field, "height") == 0)
- {
- pField = &si->height;
- def = _GS_Height;
- }
- else if (uStrCaseCmp(field, "angle") == 0)
- {
- pField = &si->angle;
- def = _GS_Angle;
- }
- else
- {
- info->errorCount++;
- return ReportBadField("keyboard section", field,
- scText(info->dpy, si));
- }
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard section", field,
- scText(info->dpy, si));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- ReportBadType("keyboard section", field, scText(info->dpy, si),
- "number");
- return False;
- }
- si->defs.defined |= def;
- *pField = tmp.uval;
- return True;
-}
-
-static int
-SetRowField(RowInfo * row,
- char *field,
- ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
-{
- ExprResult tmp;
-
- if (uStrCaseCmp(field, "top") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard row", field,
- rowText(info->dpy, row));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard row", field,
- rowText(info->dpy, row), "number");
- }
- row->defs.defined |= _GR_Top;
- row->top = tmp.uval;
- }
- else if (uStrCaseCmp(field, "left") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard row", field,
- rowText(info->dpy, row));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard row", field,
- rowText(info->dpy, row), "number");
- }
- row->defs.defined |= _GR_Left;
- row->left = tmp.uval;
- }
- else if (uStrCaseCmp(field, "vertical") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard row", field,
- rowText(info->dpy, row));
- }
- if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard row", field,
- rowText(info->dpy, row), "boolean");
- }
- row->defs.defined |= _GR_Vertical;
- row->vertical = tmp.uval;
- }
- else
- {
- info->errorCount++;
- return ReportBadField("keyboard row", field, rowText(info->dpy, row));
- }
- return True;
-}
-
-static int
-SetKeyField(KeyInfo * key,
- const char *field,
- ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
-{
- ExprResult tmp;
-
- if (uStrCaseCmp(field, "gap") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("key", field, keyText(key));
- }
- if (!ExprResolveFloat(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("key", field, keyText(key), "number");
- }
- key->defs.defined |= _GK_Gap;
- key->gap = tmp.ival;
- }
- else if (uStrCaseCmp(field, "shape") == 0)
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("key", field, keyText(key));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("key", field, keyText(key), "string");
- }
- key->defs.defined |= _GK_Shape;
- key->shape = XkbInternAtom(info->dpy, tmp.str, False);
- }
- else if ((uStrCaseCmp(field, "color") == 0) ||
- (uStrCaseCmp(field, "keycolor") == 0))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("key", field, keyText(key));
- }
- if (!ExprResolveString(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("key", field, keyText(key), "string");
- }
- key->defs.defined |= _GK_Color;
- key->color = XkbInternAtom(NULL, tmp.str, False);
- }
- else if ((uStrCaseCmp(field, "name") == 0)
- || (uStrCaseCmp(field, "keyname") == 0))
- {
- if (arrayNdx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("key", field, keyText(key));
- }
- if (!ExprResolveKeyName(value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("key", field, keyText(key), "key name");
- }
- key->defs.defined |= _GK_Name;
- bzero(key->name, XkbKeyNameLength + 1);
- strncpy(key->name, tmp.keyName.name, XkbKeyNameLength);
- }
- else
- {
- info->errorCount++;
- return ReportBadField("key", field, keyText(key));
- }
- return True;
-}
-
-static int
-SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value)
-{
- PropertyInfo pi;
- ExprResult result;
-
- InitPropertyInfo(&pi, info);
- pi.name = property;
- if (!ExprResolveString(value, &result, NULL, NULL))
- {
- info->errorCount++;
- ERROR("Property values must be type string\n");
- ACTION1("Ignoring illegal definition of \"%s\" property\n", property);
- return False;
- }
- pi.value = result.str;
- return AddProperty(info, &pi);
-}
-
-static int
-HandleGeometryVar(VarDef * stmt, XkbDescPtr xkb, GeometryInfo * info)
-{
- ExprResult elem, field, tmp;
- ExprDef *ndx;
- DoodadInfo *di;
- Atom *pField;
-
- if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
- return 0; /* internal error, already reported */
- if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0))
- return SetShapeField(NULL, field.str, ndx, stmt->value, info);
- if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
- return SetKeyField(&info->dfltSection.dfltRow.dfltKey,
- field.str, ndx, stmt->value, info);
- if (elem.str && (uStrCaseCmp(elem.str, "row") == 0))
- return SetRowField(&info->dfltSection.dfltRow, field.str, ndx,
- stmt->value, info);
- if (elem.str && (uStrCaseCmp(elem.str, "section") == 0))
- {
- return SetSectionField(&info->dfltSection, field.str, ndx,
- stmt->value, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "property") == 0))
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- ERROR1("The %s geometry property is not an array\n", field.str);
- ACTION("Ignoring illegal property definition\n");
- return False;
- }
- return SetGeometryProperty(info, field.str, stmt->value);
- }
- if (elem.str
- && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL))
- {
- return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0))
- {
- DoodadInfo *dflt;
- dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad);
- if (dflt == NULL)
- dflt = NextDfltDoodad(NULL, info);
- return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0))
- {
- DoodadInfo *dflt;
- dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad);
- if (dflt == NULL)
- dflt = NextDfltDoodad(NULL, info);
- return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "text") == 0))
- {
- DoodadInfo *dflt;
- dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad);
- if (dflt == NULL)
- dflt = NextDfltDoodad(NULL, info);
- return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0))
- {
- DoodadInfo *dflt;
- dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad);
- if (dflt == NULL)
- dflt = NextDfltDoodad(NULL, info);
- return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0))
- {
- DoodadInfo *dflt;
- dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad);
- if (dflt == NULL)
- dflt = NextDfltDoodad(NULL, info);
- return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info);
- }
- if (elem.str)
- {
- WARN("Assignment to field of unknown element\n");
- ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
- return False;
- }
-
- if ((uStrCaseCmp(field.str, "width") == 0) ||
- (uStrCaseCmp(field.str, "widthmm") == 0))
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "number");
- }
- if (tmp.ival < 1)
- {
- WARN("Keyboard width must be positive\n");
- ACTION1("Ignoring illegal keyboard width %s\n",
- XkbGeomFPText(tmp.ival, XkbMessage));
- return True;
- }
- if (info->widthMM != 0)
- {
- WARN("Keyboard width multiply defined\n");
- ACTION1("Using last definition (%s),",
- XkbGeomFPText(tmp.ival, XkbMessage));
- INFO1(" ignoring first (%s)\n",
- XkbGeomFPText(info->widthMM, XkbMessage));
- }
- info->widthMM = tmp.ival;
- return True;
- }
- else if ((uStrCaseCmp(field.str, "height") == 0) ||
- (uStrCaseCmp(field.str, "heightmm") == 0))
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "number");
- }
- if (tmp.ival < 1)
- {
- WARN("Keyboard height must be positive\n");
- ACTION1("Ignoring illegal keyboard height %s\n",
- XkbGeomFPText(tmp.ival, XkbMessage));
- return True;
- }
- if (info->heightMM != 0)
- {
- WARN("Keyboard height multiply defined\n");
- ACTION1("Using last definition (%s),",
- XkbGeomFPText(tmp.ival, XkbMessage));
- INFO1(" ignoring first (%s)\n",
- XkbGeomFPText(info->heightMM, XkbMessage));
- }
- info->heightMM = tmp.ival;
- return True;
- }
- else if (uStrCaseCmp(field.str, "font") == 0)
- {
- pField = &info->font;
- }
- else if ((uStrCaseCmp(field.str, "fontslant") == 0) ||
- (uStrCaseCmp(field.str, "slant") == 0))
- {
- pField = &info->fontSlant;
- }
- else if ((uStrCaseCmp(field.str, "fontweight") == 0) ||
- (uStrCaseCmp(field.str, "weight") == 0))
- {
- pField = &info->fontWeight;
- }
- else if ((uStrCaseCmp(field.str, "fontwidth") == 0) ||
- (uStrCaseCmp(field.str, "setwidth") == 0))
- {
- pField = &info->fontWeight;
- }
- else if ((uStrCaseCmp(field.str, "fontencoding") == 0) ||
- (uStrCaseCmp(field.str, "encoding") == 0))
- {
- pField = &info->fontEncoding;
- }
- else if ((uStrCaseCmp(field.str, "xfont") == 0) ||
- (uStrCaseCmp(field.str, "xfontname") == 0))
- {
- pField = &info->fontSpec;
- }
- else if (uStrCaseCmp(field.str, "fontsize") == 0)
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "number");
- }
- if ((tmp.ival < 40) || (tmp.ival > 2550))
- {
- info->errorCount++;
- ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival);
- ACTION("Ignoring font size in keyboard geometry\n");
- return False;
- }
- info->fontSize = tmp.ival;
- return True;
- }
- else if ((uStrCaseCmp(field.str, "color") == 0) ||
- (uStrCaseCmp(field.str, "basecolor") == 0))
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "string");
- }
- info->baseColor = XkbInternAtom(NULL, tmp.str, False);
- return True;
- }
- else if (uStrCaseCmp(field.str, "labelcolor") == 0)
- {
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "string");
- }
- info->labelColor = XkbInternAtom(NULL, tmp.str, False);
- return True;
- }
- else
- {
- return SetGeometryProperty(info, field.str, stmt->value);
- }
-
- if (ndx != NULL)
- {
- info->errorCount++;
- return ReportNotArray("keyboard", field.str, "geometry");
- }
- if (!ExprResolveString(stmt->value, &tmp, NULL, NULL))
- {
- info->errorCount++;
- return ReportBadType("keyboard", field.str, "geometry", "string");
- }
- *pField = XkbInternAtom(NULL, tmp.str, False);
- return True;
-}
-
-/***====================================================================***/
-
-static Bool
-HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge,
- GeometryInfo * info)
-{
- OutlineDef *ol;
- int nOut, nPt;
- XkbOutlinePtr outline;
- ExprDef *pt;
-
- if (def->nOutlines < 1)
- {
- WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si));
- ACTION("Definition ignored\n");
- return True;
- }
- si->nOutlines = def->nOutlines;
- si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec);
- if (!si->outlines)
- {
- ERROR1("Couldn't allocate outlines for \"%s\"\n",
- shText(info->dpy, si));
- ACTION("Definition ignored\n");
- info->errorCount++;
- return False;
- }
- for (nOut = 0, ol = def->outlines; ol != NULL;
- ol = (OutlineDef *) ol->common.next)
- {
- if (ol->nPoints < 1)
- {
- SetShapeField(si, XkbAtomGetString(NULL, ol->field), NULL,
- ol->points, info);
- continue;
- }
- outline = NULL;
- outline = &si->outlines[nOut++];
- outline->num_points = ol->nPoints;
- outline->corner_radius = si->dfltCornerRadius;
- outline->points = uTypedCalloc(ol->nPoints, XkbPointRec);
- if (!outline->points)
- {
- ERROR1("Can't allocate points for \"%s\"\n",
- shText(info->dpy, si));
- ACTION("Definition ignored\n");
- info->errorCount++;
- return False;
- }
- for (nPt = 0, pt = ol->points; pt != NULL;
- pt = (ExprDef *) pt->common.next)
- {
- outline->points[nPt].x = pt->value.coord.x;
- outline->points[nPt].y = pt->value.coord.y;
- nPt++;
- }
- if (ol->field != None)
- {
- char *str = XkbAtomText(NULL, ol->field, XkbMessage);
- if ((uStrCaseCmp(str, "approximation") == 0) ||
- (uStrCaseCmp(str, "approx") == 0))
- {
- if (si->approx == NULL)
- si->approx = outline;
- else
- {
- WARN1("Multiple approximations for \"%s\"\n",
- shText(info->dpy, si));
- ACTION("Treating all but the first as normal outlines\n");
- }
- }
- else if (uStrCaseCmp(str, "primary") == 0)
- {
- if (si->primary == NULL)
- si->primary = outline;
- else
- {
- WARN1("Multiple primary outlines for \"%s\"\n",
- shText(info->dpy, si));
- ACTION("Treating all but the first as normal outlines\n");
- }
- }
- else
- {
- WARN2("Unknown outline type %s for \"%s\"\n", str,
- shText(info->dpy, si));
- ACTION("Treated as a normal outline\n");
- }
- }
- }
- if (nOut != si->nOutlines)
- {
- WSGO2("Expected %d outlines, got %d\n",
- (unsigned int) si->nOutlines, nOut);
- si->nOutlines = nOut;
- }
- return True;
-}
-
-static int
-HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge,
- GeometryInfo * info)
-{
- ShapeInfo si;
-
- if (def->merge != MergeDefault)
- merge = def->merge;
-
- bzero(&si, sizeof(ShapeInfo));
- si.defs.merge = merge;
- si.name =
- XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
- si.dfltCornerRadius = info->dfltCornerRadius;
- if (!HandleShapeBody(def, &si, merge, info))
- return False;
- if (!AddShape(info, &si))
- return False;
- return True;
-}
-
-/***====================================================================***/
-
-static int
-HandleDoodadDef(DoodadDef * def,
- unsigned merge, SectionInfo * si, GeometryInfo * info)
-{
- ExprResult elem, field;
- ExprDef *ndx;
- DoodadInfo new;
- VarDef *var;
-
- if (def->common.stmtType == StmtIndicatorMapDef)
- {
- def->common.stmtType = StmtDoodadDef;
- def->type = XkbIndicatorDoodad;
- }
- InitDoodadInfo(&new, def->type, si, info);
- new.name =
- XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
- for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
- {
- if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
- return 0; /* internal error, already reported */
- if (elem.str != NULL)
- {
- WARN1("Assignment to field of unknown element in doodad %s\n",
- ddText(info->dpy, &new));
- ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
- }
- else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info))
- return False;
- }
- if (!AddDoodad(si, info, &new))
- return False;
- ClearDoodadInfo(&new);
- return True;
-}
-
-/***====================================================================***/
-
-static int
-HandleOverlayDef(OverlayDef * def,
- unsigned merge, SectionInfo * si, GeometryInfo * info)
-{
- OverlayKeyDef *keyDef;
- OverlayKeyInfo *key;
- OverlayInfo ol;
-
- if ((def->nKeys < 1) && (warningLevel > 3))
- {
- WARN2("Overlay \"%s\" in section \"%s\" has no keys\n",
- XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy,
- si));
- ACTION("Overlay ignored\n");
- return True;
- }
- bzero(&ol, sizeof(OverlayInfo));
- ol.name =
- XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
- for (keyDef = def->keys; keyDef;
- keyDef = (OverlayKeyDef *) keyDef->common.next)
- {
- key = uTypedCalloc(1, OverlayKeyInfo);
- if ((!key) && warningLevel > 0)
- {
- WSGO("Couldn't allocate OverlayKeyInfo\n");
- ACTION2("Overlay %s for section %s will be incomplete\n",
- XkbAtomText(info->dpy, ol.name, XkbMessage),
- scText(info->dpy, si));
- return False;
- }
- strncpy(key->over, keyDef->over, XkbKeyNameLength);
- strncpy(key->under, keyDef->under, XkbKeyNameLength);
- key->sectionRow = _GOK_UnknownRow;
- key->overlayRow = _GOK_UnknownRow;
- ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs,
- (CommonInfo *) key);
- ol.nKeys++;
- }
- if (!AddOverlay(si, info, &ol))
- return False;
- ClearOverlayInfo(&ol);
- return True;
-}
-
-/***====================================================================***/
-
-static Bool
-HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info)
-{
- RowInfo *row;
- ExprDef *expr;
-
- row = key->row;
- for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next)
- {
- if (expr->op == OpAssign)
- {
- ExprResult elem, f;
- ExprDef *ndx;
- if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0)
- return False; /* internal error, already reported */
- if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0))
- {
- if (!SetKeyField
- (key, f.str, ndx, expr->value.binary.right, info))
- return False;
- }
- else
- {
- ERROR("Illegal element used in a key definition\n");
- ACTION2("Assignment to %s.%s ignored\n", elem.str, f.str);
- return False;
- }
- }
- else
- {
- switch (expr->type)
- {
- case TypeInt:
- case TypeFloat:
- if (!SetKeyField(key, "gap", NULL, expr, info))
- return False;
- break;
- case TypeString:
- if (!SetKeyField(key, "shape", NULL, expr, info))
- return False;
- break;
- case TypeKeyName:
- if (!SetKeyField(key, "name", NULL, expr, info))
- return False;
- break;
- default:
- ERROR("Cannot determine field for unnamed expression\n");
- ACTION3("Ignoring key %d in row %d of section %s\n",
- row->nKeys + 1, row->section->nRows + 1,
- rowText(info->dpy, row));
- return False;
- }
- }
- }
- return True;
-}
-
-static Bool
-HandleRowBody(RowDef * def, RowInfo * row, unsigned merge,
- GeometryInfo * info)
-{
- KeyDef *keyDef;
-
- if ((def->nKeys < 1) && (warningLevel > 3))
- {
- ERROR1("Row in section %s has no keys\n", rowText(info->dpy, row));
- ACTION("Section ignored\n");
- return True;
- }
- for (keyDef = def->keys; keyDef != NULL;
- keyDef = (KeyDef *) keyDef->common.next)
- {
- if (keyDef->common.stmtType == StmtVarDef)
- {
- VarDef *var = (VarDef *) keyDef;
- ExprResult elem, field;
- ExprDef *ndx;
- if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
- return 0; /* internal error, already reported */
- if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0))
- {
- if (!SetRowField(row, field.str, ndx, var->value, info))
- return False;
- }
- else if (uStrCaseCmp(elem.str, "key") == 0)
- {
- if (!SetKeyField
- (&row->dfltKey, field.str, ndx, var->value, info))
- return False;
- }
- else
- {
- WARN("Assignment to field of unknown element in row\n");
- ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
- }
- }
- else if (keyDef->common.stmtType == StmtKeyDef)
- {
- KeyInfo key;
- InitKeyInfo(&key, row, info);
- if (keyDef->name != NULL)
- {
- int len = strlen(keyDef->name);
- if ((len < 1) || (len > XkbKeyNameLength))
- {
- ERROR2("Illegal name %s for key in section %s\n",
- keyDef->name, rowText(info->dpy, row));
- ACTION("Section not compiled\n");
- return False;
- }
- bzero(key.name, XkbKeyNameLength + 1);
- strncpy(key.name, keyDef->name, XkbKeyNameLength);
- key.defs.defined |= _GK_Name;
- }
- else if (!HandleComplexKey(keyDef, &key, info))
- return False;
- if (!AddKey(row, &key))
- return False;
- }
- else
- {
- WSGO1("Unexpected statement (type %d) in row body\n",
- keyDef->common.stmtType);
- return False;
- }
- }
- return True;
-}
-
-static Bool
-HandleSectionBody(SectionDef * def,
- SectionInfo * si, unsigned merge, GeometryInfo * info)
-{
- RowDef *rowDef;
- DoodadInfo *di;
-
- for (rowDef = def->rows; rowDef != NULL;
- rowDef = (RowDef *) rowDef->common.next)
- {
- if (rowDef->common.stmtType == StmtVarDef)
- {
- VarDef *var = (VarDef *) rowDef;
- ExprResult elem, field;
- ExprDef *ndx;
- if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0)
- return 0; /* internal error, already reported */
- if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0))
- {
- if (!SetSectionField(si, field.str, ndx, var->value, info))
- return False;
- }
- else if (uStrCaseCmp(elem.str, "row") == 0)
- {
- if (!SetRowField
- (&si->dfltRow, field.str, ndx, var->value, info))
- return False;
- }
- else if (uStrCaseCmp(elem.str, "key") == 0)
- {
- if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx,
- var->value, info))
- return False;
- }
- else if ((di =
- FindDfltDoodadByTypeName(elem.str, si, info)) != NULL)
- {
- if (!SetDoodadField(di, field.str, ndx, var->value, si, info))
- return False;
- }
- else
- {
- WARN("Assignment to field of unknown element in section\n");
- ACTION2("No value assigned to %s.%s\n", elem.str, field.str);
- }
- }
- else if (rowDef->common.stmtType == StmtRowDef)
- {
- RowInfo row;
- InitRowInfo(&row, si, info);
- if (!HandleRowBody(rowDef, &row, merge, info))
- return False;
- if (!AddRow(si, &row))
- return False;
-/* ClearRowInfo(&row,info);*/
- }
- else if ((rowDef->common.stmtType == StmtDoodadDef) ||
- (rowDef->common.stmtType == StmtIndicatorMapDef))
- {
- if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info))
- return False;
- }
- else if (rowDef->common.stmtType == StmtOverlayDef)
- {
- if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info))
- return False;
- }
- else
- {
- WSGO1("Unexpected statement (type %d) in section body\n",
- rowDef->common.stmtType);
- return False;
- }
- }
- if (si->nRows != def->nRows)
- {
- WSGO2("Expected %d rows, found %d\n", (unsigned int) def->nRows,
- (unsigned int) si->nRows);
- ACTION1("Definition of section %s might be incorrect\n",
- scText(info->dpy, si));
- }
- return True;
-}
-
-static int
-HandleSectionDef(SectionDef * def,
- XkbDescPtr xkb, unsigned merge, GeometryInfo * info)
-{
- SectionInfo si;
- char *str;
-
- if (def->merge != MergeDefault)
- merge = def->merge;
- InitSectionInfo(&si, info);
- si.defs.merge = merge;
- str = XkbAtomGetString(NULL, def->name);
- if ((str == NULL) || (strlen(str) < 1))
- {
- ERROR("Section defined without a name\n");
- ACTION("Definition ignored\n");
- return False;
- }
- si.name =
- XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False);
- if (!HandleSectionBody(def, &si, merge, info))
- return False;
- if (!AddSection(info, &si))
- return False;
- return True;
-}
-
-/***====================================================================***/
-
-static void
-HandleGeometryFile(XkbFile * file,
- XkbDescPtr xkb, unsigned merge, GeometryInfo * info)
-{
- ParseCommon *stmt;
- char *failWhat;
-
- if (merge == MergeDefault)
- merge = MergeAugment;
- info->name = uStringDup(file->name);
- stmt = file->defs;
- while (stmt)
- {
- failWhat = NULL;
- switch (stmt->stmtType)
- {
- case StmtInclude:
- if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info,
- HandleGeometryFile))
- info->errorCount++;
- break;
- case StmtKeyAliasDef:
- if (!HandleAliasDef((KeyAliasDef *) stmt,
- merge, info->fileID, &info->aliases))
- {
- info->errorCount++;
- }
- break;
- case StmtVarDef:
- if (!HandleGeometryVar((VarDef *) stmt, xkb, info))
- info->errorCount++;
- break;
- case StmtShapeDef:
- if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info))
- info->errorCount++;
- break;
- case StmtSectionDef:
- if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info))
- info->errorCount++;
- break;
- case StmtIndicatorMapDef:
- case StmtDoodadDef:
- if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info))
- info->errorCount++;
- break;
- case StmtVModDef:
- if (!failWhat)
- failWhat = "virtual modfier";
- case StmtInterpDef:
- if (!failWhat)
- failWhat = "symbol interpretation";
- case StmtGroupCompatDef:
- if (!failWhat)
- failWhat = "group compatibility map";
- case StmtKeycodeDef:
- if (!failWhat)
- failWhat = "key name";
- ERROR("Interpretation files may not include other types\n");
- ACTION1("Ignoring %s definition.\n", failWhat);
- info->errorCount++;
- break;
- default:
- WSGO1("Unexpected statement type %d in HandleGeometryFile\n",
- stmt->stmtType);
- break;
- }
- stmt = stmt->next;
- if (info->errorCount > 10)
- {
-#ifdef NOISY
- ERROR("Too many errors\n");
-#endif
- ACTION1("Abandoning geometry file \"%s\"\n", file->topName);
- break;
- }
- }
- return;
-}
-
-/***====================================================================***/
-
-static Bool
-CopyShapeDef(Display * dpy, XkbGeometryPtr geom, ShapeInfo * si)
-{
- register int i, n;
- XkbShapePtr shape;
- XkbOutlinePtr old_outline, outline;
- Atom name;
-
- si->index = geom->num_shapes;
- name = XkbInternAtom(dpy, XkbAtomGetString(NULL, si->name), False);
- shape = XkbAddGeomShape(geom, name, si->nOutlines);
- if (!shape)
- {
- WSGO("Couldn't allocate shape in geometry\n");
- ACTION1("Shape %s not compiled\n", shText(dpy, si));
- return False;
- }
- old_outline = si->outlines;
- for (i = 0; i < si->nOutlines; i++, old_outline++)
- {
- outline = XkbAddGeomOutline(shape, old_outline->num_points);
- if (!outline)
- {
- WSGO("Couldn't allocate outline in shape\n");
- ACTION1("Shape %s is incomplete\n", shText(dpy, si));
- return False;
- }
- n = old_outline->num_points;
- memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec));
- outline->num_points = old_outline->num_points;
- outline->corner_radius = old_outline->corner_radius;
- }
- if (si->approx)
- {
- n = (si->approx - si->outlines);
- shape->approx = &shape->outlines[n];
- }
- if (si->primary)
- {
- n = (si->primary - si->outlines);
- shape->primary = &shape->outlines[n];
- }
- XkbComputeShapeBounds(shape);
- return True;
-}
-
-static Bool
-VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info)
-{
- if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left))
- {
- if (warningLevel < 9)
- {
- ERROR1("No position defined for doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Illegal doodad ignored\n");
- return False;
- }
- }
- if ((di->defs.defined & _GD_Priority) == 0)
- {
- /* calculate priority -- should be just above previous doodad/row */
- }
- switch (di->type)
- {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- if ((di->defs.defined & _GD_Shape) == 0)
- {
- ERROR2("No shape defined for %s doodad %s\n",
- (di->type == XkbOutlineDoodad ? "outline" : "filled"),
- ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- else
- {
- ShapeInfo *si;
- si = FindShape(info, di->shape,
- (di->type ==
- XkbOutlineDoodad ? "outline doodad" :
- "solid doodad"), ddText(info->dpy, di));
- if (si)
- di->shape = si->name;
- else
- {
- ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- }
- if ((di->defs.defined & _GD_Color) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No color for doodad %s\n", ddText(info->dpy, di));
- ACTION("Using black\n");
- }
- di->color = XkbInternAtom(NULL, "black", False);
- }
- break;
- case XkbTextDoodad:
- if ((di->defs.defined & _GD_Text) == 0)
- {
- ERROR1("No text specified for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Illegal doodad definition ignored\n");
- return False;
- }
- if ((di->defs.defined & _GD_Angle) == 0)
- di->angle = 0;
- if ((di->defs.defined & _GD_Color) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No color specified for doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Using black\n");
- }
- di->color = XkbInternAtom(NULL, "black", False);
- }
- if ((di->defs.defined & _GD_FontSpec) != 0)
- {
- if ((di->defs.defined & _GD_FontParts) == 0)
- return True;
- if (warningLevel < 9)
- {
- WARN1
- ("Text doodad %s has full and partial font definition\n",
- ddText(info->dpy, di));
- ACTION("Full specification ignored\n");
- }
- di->defs.defined &= ~_GD_FontSpec;
- di->fontSpec = None;
- }
- if ((di->defs.defined & _GD_Font) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No font specified for doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_FONT);
- }
- di->font = XkbInternAtom(NULL, DFLT_FONT, False);
- }
- if ((di->defs.defined & _GD_FontSlant) == 0)
- {
- if (warningLevel > 7)
- {
- WARN1("No font slant for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_SLANT);
- }
- di->fontSlant = XkbInternAtom(NULL, DFLT_SLANT, False);
- }
- if ((di->defs.defined & _GD_FontWeight) == 0)
- {
- if (warningLevel > 7)
- {
- WARN1("No font weight for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_WEIGHT);
- }
- di->fontWeight = XkbInternAtom(NULL, DFLT_WEIGHT, False);
- }
- if ((di->defs.defined & _GD_FontSetWidth) == 0)
- {
- if (warningLevel > 9)
- {
- WARN1("No font set width for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_SET_WIDTH);
- }
- di->fontSetWidth = XkbInternAtom(NULL, DFLT_SET_WIDTH, False);
- }
- if ((di->defs.defined & _GD_FontVariant) == 0)
- {
- if (warningLevel > 9)
- {
- WARN1("No font variant for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_VARIANT);
- }
- di->fontVariant = XkbInternAtom(NULL, DFLT_VARIANT, False);
- }
- if ((di->defs.defined & _GD_FontEncoding) == 0)
- {
- if (warningLevel > 7)
- {
- WARN1("No font encoding for doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using \"%s\"\n", DFLT_ENCODING);
- }
- di->fontEncoding = XkbInternAtom(NULL, DFLT_ENCODING, False);
- }
- if ((di->defs.defined & _GD_FontSize) == 0)
- {
- if (warningLevel > 7)
- {
- WARN1("No font size for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using %s point text\n",
- XkbGeomFPText(DFLT_SIZE, XkbMessage));
- }
- di->fontSize = DFLT_SIZE;
- }
- if ((di->defs.defined & _GD_Height) == 0)
- {
- unsigned size, nLines;
- char *tmp;
- size = (di->fontSize * 120) / 100;
- size = (size * 254) / 720; /* convert to mm/10 */
- for (nLines = 1, tmp = XkbAtomGetString(NULL, di->text); *tmp;
- tmp++)
- {
- if (*tmp == '\n')
- nLines++;
- }
- size *= nLines;
- if (warningLevel > 5)
- {
- WARN1("No height for text doodad %s\n",
- ddText(info->dpy, di));
- ACTION1("Using calculated height %s millimeters\n",
- XkbGeomFPText(size, XkbMessage));
- }
- di->height = size;
- }
- if ((di->defs.defined & _GD_Width) == 0)
- {
- unsigned width, tmp;
- char *str;
- width = tmp = 0;
- for (str = XkbAtomGetString(NULL, di->text); *str; str++)
- {
- if (*str != '\n')
- tmp++;
- else
- {
- if (tmp > width)
- width = tmp;
- tmp = 1;
- }
- }
- if (width == 0)
- width = tmp;
- width *= (di->height * 2) / 3;
- if (warningLevel > 5)
- {
- WARN1("No width for text doodad %s\n", ddText(info->dpy, di));
- ACTION1("Using calculated width %s millimeters\n",
- XkbGeomFPText(width, XkbMessage));
- }
- di->width = width;
- }
- break;
- case XkbIndicatorDoodad:
- if ((di->defs.defined & _GD_Shape) == 0)
- {
- ERROR1("No shape defined for indicator doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- else
- {
- ShapeInfo *si;
- si = FindShape(info, di->shape, "indicator doodad",
- ddText(info->dpy, di));
- if (si)
- di->shape = si->name;
- else
- {
- ERROR1("No legal shape for doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- }
- if ((di->defs.defined & _GD_Color) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No \"on\" color for indicator doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Using green\n");
- }
- di->color = XkbInternAtom(NULL, "green", False);
- }
- if ((di->defs.defined & _GD_OffColor) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No \"off\" color for indicator doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Using black\n");
- }
- di->offColor = XkbInternAtom(NULL, "black", False);
- }
- break;
- case XkbLogoDoodad:
- if (di->logoName == NULL)
- {
- ERROR1("No logo name defined for logo doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- if ((di->defs.defined & _GD_Shape) == 0)
- {
- ERROR1("No shape defined for logo doodad %s\n",
- ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- else
- {
- ShapeInfo *si;
- si = FindShape(info, di->shape, "logo doodad",
- ddText(info->dpy, di));
- if (si)
- di->shape = si->name;
- else
- {
- ERROR1("No legal shape for %s\n", ddText(info->dpy, di));
- ACTION("Incomplete definition ignored\n");
- return False;
- }
- }
- if ((di->defs.defined & _GD_Color) == 0)
- {
- if (warningLevel > 5)
- {
- WARN1("No color for doodad %s\n", ddText(info->dpy, di));
- ACTION("Using black\n");
- }
- di->color = XkbInternAtom(NULL, "black", False);
- }
- break;
- default:
- WSGO1("Uknown doodad type %d in VerifyDoodad\n",
- (unsigned int) di->type);
- return False;
- }
- return True;
-}
-
-#define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s"
-
-static char *
-FontFromParts(Atom fontTok,
- Atom weightTok,
- Atom slantTok,
- Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
-{
- int totalSize;
- char *font, *weight, *slant, *setWidth, *variant, *encoding;
- char *rtrn;
-
- font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT);
- weight =
- (weightTok != None ? XkbAtomGetString(NULL, weightTok) : DFLT_WEIGHT);
- slant =
- (slantTok != None ? XkbAtomGetString(NULL, slantTok) : DFLT_SLANT);
- setWidth =
- (setWidthTok !=
- None ? XkbAtomGetString(NULL, setWidthTok) : DFLT_SET_WIDTH);
- variant =
- (varTok != None ? XkbAtomGetString(NULL, varTok) : DFLT_VARIANT);
- encoding =
- (encodingTok !=
- None ? XkbAtomGetString(NULL, encodingTok) : DFLT_ENCODING);
- if (size == 0)
- size = DFLT_SIZE;
- totalSize =
- strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant);
- totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding);
- rtrn = uCalloc(totalSize, 1);
- if (rtrn)
- {
- sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
- size, encoding);
- }
- return rtrn;
-}
-
-static Bool
-CopyDoodadDef(XkbGeometryPtr geom,
- XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info)
-{
- Atom name;
- XkbDoodadPtr doodad;
- XkbColorPtr color;
- XkbShapePtr shape;
- ShapeInfo *si;
-
- if (!VerifyDoodadInfo(di, info))
- return False;
- name = XkbInternAtom(NULL, XkbAtomGetString(NULL, di->name), False);
- doodad = XkbAddGeomDoodad(geom, section, name);
- if (!doodad)
- {
- WSGO1("Couldn't allocate doodad in %s\n",
- (section ? "section" : "geometry"));
- ACTION1("Cannot copy doodad %s\n", ddText(info->dpy, di));
- return False;
- }
- doodad->any.type = di->type;
- doodad->any.priority = di->priority;
- doodad->any.top = di->top;
- doodad->any.left = di->left;
- switch (di->type)
- {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- si = FindShape(info, di->shape, NULL, NULL);
- if (!si)
- return False;
- doodad->shape.angle = di->angle;
- color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
- geom->num_colors);
- shape = &geom->shapes[si->index];
- XkbSetShapeDoodadColor(geom, &doodad->shape, color);
- XkbSetShapeDoodadShape(geom, &doodad->shape, shape);
- break;
- case XkbTextDoodad:
- doodad->text.angle = di->angle;
- doodad->text.width = di->width;
- doodad->text.height = di->height;
- if (di->fontSpec == None)
- doodad->text.font = FontFromParts(di->font, di->fontWeight,
- di->fontSlant,
- di->fontSetWidth,
- di->fontVariant, di->fontSize,
- di->fontEncoding);
- else
- doodad->text.font = XkbAtomGetString(NULL, di->fontSpec);
- doodad->text.text = XkbAtomGetString(NULL, di->text);
- color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
- geom->num_colors);
- XkbSetTextDoodadColor(geom, &doodad->text, color);
- break;
- case XkbIndicatorDoodad:
- si = FindShape(info, di->shape, NULL, NULL);
- if (!si)
- return False;
- shape = &geom->shapes[si->index];
- color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
- geom->num_colors);
- XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape);
- XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color);
- color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->offColor),
- geom->num_colors);
- XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color);
- break;
- case XkbLogoDoodad:
- si = FindShape(info, di->shape, NULL, NULL);
- if (!si)
- return False;
- doodad->logo.angle = di->angle;
- color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color),
- geom->num_colors);
- shape = &geom->shapes[si->index];
- XkbSetLogoDoodadColor(geom, &doodad->logo, color);
- XkbSetLogoDoodadShape(geom, &doodad->logo, shape);
- doodad->logo.logo_name = di->logoName;
- di->logoName = NULL;
- break;
- }
- return True;
-}
-
-/***====================================================================***/
-
-static Bool
-VerifyOverlayInfo(XkbGeometryPtr geom,
- XkbSectionPtr section,
- OverlayInfo * oi,
- GeometryInfo * info, short rowMap[256], short rowSize[256])
-{
- register OverlayKeyInfo *ki, *next;
- unsigned long oKey, uKey, sKey;
- XkbRowPtr row;
- XkbKeyPtr key;
- int r, k;
-
- /* find out which row each key is in */
- for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
- {
- oKey = KeyNameToLong(ki->over);
- uKey = KeyNameToLong(ki->under);
- for (r = 0, row = section->rows; (r < section->num_rows) && oKey;
- r++, row++)
- {
- for (k = 0, key = row->keys; (k < row->num_keys) && oKey;
- k++, key++)
- {
- sKey = KeyNameToLong(key->name.name);
- if (sKey == oKey)
- {
- if (warningLevel > 0)
- {
- WARN3
- ("Key %s in section \"%s\" and overlay \"%s\"\n",
- XkbKeyNameText(key->name.name,
- XkbMessage),
- XkbAtomText(info->dpy, section->name,
- XkbMessage),
- XkbAtomText(info->dpy, oi->name, XkbMessage));
- ACTION("Overlay definition ignored\n");
- }
- oKey = 0;
- }
- else if (sKey == uKey)
- {
- ki->sectionRow = r;
- oKey = 0;
- }
- }
- }
- if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0))
- {
- WARN3
- ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n",
- XkbKeyNameText(ki->under, XkbMessage),
- XkbAtomText(info->dpy, section->name, XkbMessage),
- XkbAtomText(info->dpy, oi->name, XkbMessage));
- ACTION("Definition ignored\n");
- }
- }
- /* now prune out keys that aren't in the section */
- while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow))
- {
- next = (OverlayKeyInfo *) oi->keys->defs.next;
- uFree(oi->keys);
- oi->keys = next;
- oi->nKeys--;
- }
- for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next)
- {
- next = (OverlayKeyInfo *) ki->defs.next;
- if (next->sectionRow == _GOK_UnknownRow)
- {
- ki->defs.next = next->defs.next;
- oi->nKeys--;
- uFree(next);
- next = (OverlayKeyInfo *) ki->defs.next;
- }
- }
- if (oi->nKeys < 1)
- {
- ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n",
- XkbAtomText(info->dpy, oi->name, XkbMessage),
- XkbAtomText(info->dpy, section->name, XkbMessage));
- ACTION("Overlay definition ignored\n");
- return False;
- }
- /* now figure out how many rows are defined for the overlay */
- bzero(rowSize, sizeof(short) * 256);
- for (k = 0; k < 256; k++)
- {
- rowMap[k] = -1;
- }
- oi->nRows = 0;
- for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
- {
- if (rowMap[ki->sectionRow] == -1)
- rowMap[ki->sectionRow] = oi->nRows++;
- ki->overlayRow = rowMap[ki->sectionRow];
- rowSize[ki->overlayRow]++;
- }
- return True;
-}
-
-static Bool
-CopyOverlayDef(XkbGeometryPtr geom,
- XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info)
-{
- Atom name;
- XkbOverlayPtr ol;
- XkbOverlayRowPtr row;
- XkbOverlayKeyPtr key;
- OverlayKeyInfo *ki;
- short rowMap[256], rowSize[256];
- int i;
-
- if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize))
- return False;
- name = XkbInternAtom(NULL, XkbAtomGetString(NULL, oi->name), False);
- ol = XkbAddGeomOverlay(section, name, oi->nRows);
- if (!ol)
- {
- WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n",
- XkbAtomText(info->dpy, name, XkbMessage),
- XkbAtomText(info->dpy, section->name, XkbMessage));
- return False;
- }
- for (i = 0; i < oi->nRows; i++)
- {
- int tmp, row_under;
- for (tmp = 0, row_under = -1;
- (tmp < section->num_rows) && (row_under < 0); tmp++)
- {
- if (rowMap[tmp] == i)
- row_under = tmp;
- }
- if (!XkbAddGeomOverlayRow(ol, row_under, rowSize[i]))
- {
- WSGO3
- ("Can't add row %d to overlay \"%s\" of section \"%s\"\n",
- i, XkbAtomText(info->dpy, name, XkbMessage),
- XkbAtomText(info->dpy, section->name, XkbMessage));
- return False;
- }
- }
- for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next)
- {
- row = &ol->rows[ki->overlayRow];
- key = &row->keys[row->num_keys++];
- bzero(key, sizeof(XkbOverlayKeyRec));
- strncpy(key->over.name, ki->over, XkbKeyNameLength);
- strncpy(key->under.name, ki->under, XkbKeyNameLength);
- }
- return True;
-}
-
-/***====================================================================***/
-
-static Bool
-CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info)
-{
- XkbSectionPtr section;
- XkbRowPtr row;
- XkbKeyPtr key;
- KeyInfo *ki;
- RowInfo *ri;
- Atom name;
-
- name = XkbInternAtom(NULL, XkbAtomGetString(NULL, si->name), False);
- section =
- XkbAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays);
- if (section == NULL)
- {
- WSGO("Couldn't allocate section in geometry\n");
- ACTION1("Section %s not compiled\n", scText(info->dpy, si));
- return False;
- }
- section->top = si->top;
- section->left = si->left;
- section->width = si->width;
- section->height = si->height;
- section->angle = si->angle;
- section->priority = si->priority;
- for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next)
- {
- row = XkbAddGeomRow(section, ri->nKeys);
- if (row == NULL)
- {
- WSGO("Couldn't allocate row in section\n");
- ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
- return False;
- }
- row->top = ri->top;
- row->left = ri->left;
- row->vertical = ri->vertical;
- for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next)
- {
- XkbColorPtr color;
- if ((ki->defs.defined & _GK_Name) == 0)
- {
- ERROR3("Key %d of row %d in section %s has no name\n",
- (int) ki->index, (int) ri->index,
- scText(info->dpy, si));
- ACTION1("Section %s ignored\n", scText(info->dpy, si));
- return False;
- }
- key = XkbAddGeomKey(row);
- if (key == NULL)
- {
- WSGO("Couldn't allocate key in row\n");
- ACTION1("Section %s is incomplete\n", scText(info->dpy, si));
- return False;
- }
- memcpy(key->name.name, ki->name, XkbKeyNameLength);
- key->gap = ki->gap;
- if (ki->shape == None)
- key->shape_ndx = 0;
- else
- {
- ShapeInfo *si;
- si = FindShape(info, ki->shape, "key", keyText(ki));
- if (!si)
- return False;
- key->shape_ndx = si->index;
- }
- if (ki->color != None)
- color =
- XkbAddGeomColor(geom,
- XkbAtomGetString(NULL, ki->color),
- geom->num_colors);
- else
- color = XkbAddGeomColor(geom, "white", geom->num_colors);
- XkbSetKeyColor(geom, key, color);
- }
- }
- if (si->doodads != NULL)
- {
- DoodadInfo *di;
- for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next)
- {
- CopyDoodadDef(geom, section, di, info);
- }
- }
- if (si->overlays != NULL)
- {
- OverlayInfo *oi;
- for (oi = si->overlays; oi != NULL;
- oi = (OverlayInfo *) oi->defs.next)
- {
- CopyOverlayDef(geom, section, oi, info);
- }
- }
- if (XkbComputeSectionBounds(geom, section))
- {
- /* 7/6/94 (ef) -- check for negative origin and translate */
- if ((si->defs.defined & _GS_Width) == 0)
- section->width = section->bounds.x2;
- if ((si->defs.defined & _GS_Height) == 0)
- section->height = section->bounds.y2;
- }
- return True;
-}
-
-/***====================================================================***/
-
-Bool
-CompileGeometry(XkbFile * file, XkbFileInfo * result, unsigned merge)
-{
- GeometryInfo info;
- XkbDescPtr xkb;
-
- xkb = result->xkb;
- InitGeometryInfo(&info, file->id, merge);
- info.dpy = xkb->dpy;
- HandleGeometryFile(file, xkb, merge, &info);
-
- if (info.errorCount == 0)
- {
- XkbGeometryPtr geom;
- XkbGeometrySizesRec sizes;
- bzero(&sizes, sizeof(sizes));
- sizes.which = XkbGeomAllMask;
- sizes.num_properties = info.nProps;
- sizes.num_colors = 8;
- sizes.num_shapes = info.nShapes;
- sizes.num_sections = info.nSections;
- sizes.num_doodads = info.nDoodads;
- if (XkbAllocGeometry(xkb, &sizes) != Success)
- {
- WSGO("Couldn't allocate GeometryRec\n");
- ACTION("Geometry not compiled\n");
- return False;
- }
- geom = xkb->geom;
-
- geom->width_mm = info.widthMM;
- geom->height_mm = info.heightMM;
- if (info.name != NULL)
- {
- geom->name = XkbInternAtom(xkb->dpy, info.name, False);
- if (XkbAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success)
- xkb->names->geometry = geom->name;
- }
- if (info.fontSpec != None)
- geom->label_font =
- uStringDup(XkbAtomGetString(NULL, info.fontSpec));
- else
- geom->label_font = FontFromParts(info.font, info.fontWeight,
- info.fontSlant,
- info.fontSetWidth,
- info.fontVariant,
- info.fontSize,
- info.fontEncoding);
- XkbAddGeomColor(geom, "black", geom->num_colors);
- XkbAddGeomColor(geom, "white", geom->num_colors);
-
- if (info.baseColor == None)
- info.baseColor = XkbInternAtom(NULL, "white", False);
- if (info.labelColor == None)
- info.labelColor = XkbInternAtom(NULL, "black", False);
- geom->base_color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.baseColor),
- geom->num_colors);
- geom->label_color =
- XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.labelColor),
- geom->num_colors);
-
- if (info.props)
- {
- PropertyInfo *pi;
- for (pi = info.props; pi != NULL;
- pi = (PropertyInfo *) pi->defs.next)
- {
- if (!XkbAddGeomProperty(geom, pi->name, pi->value))
- return False;
- }
- }
- if (info.shapes)
- {
- ShapeInfo *si;
- for (si = info.shapes; si != NULL;
- si = (ShapeInfo *) si->defs.next)
- {
- if (!CopyShapeDef(xkb->dpy, geom, si))
- return False;
- }
- }
- if (info.sections)
- {
- SectionInfo *si;
- for (si = info.sections; si != NULL;
- si = (SectionInfo *) si->defs.next)
- {
- if (!CopySectionDef(geom, si, &info))
- return False;
- }
- }
- if (info.doodads)
- {
- DoodadInfo *di;
- for (di = info.doodads; di != NULL;
- di = (DoodadInfo *) di->defs.next)
- {
- if (!CopyDoodadDef(geom, NULL, di, &info))
- return False;
- }
- }
- if (info.aliases)
- ApplyAliases(xkb, True, &info.aliases);
- ClearGeometryInfo(&info);
- return True;
- }
- return False;
-}
+/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + Permission to use, copy, modify, and distribute this + software and its documentation for any purpose and without + fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH + THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ********************************************************/ + +#include "xkbcomp.h" +#include "tokens.h" +#include "expr.h" +#include "vmod.h" +#include "misc.h" +#include "indicators.h" +#include "action.h" +#include "keycodes.h" +#include "alias.h" + +#include "X11/extensions/XKBgeom.h" + +#define DFLT_FONT "helvetica" +#define DFLT_SLANT "r" +#define DFLT_WEIGHT "medium" +#define DFLT_SET_WIDTH "normal" +#define DFLT_VARIANT "" +#define DFLT_ENCODING "iso8859-1" +#define DFLT_SIZE 120 + +typedef struct _PropertyInfo +{ + CommonInfo defs; + char *name; + char *value; +} PropertyInfo; + +#define _GSh_Outlines (1<<1) +#define _GSh_Approx (1<<2) +#define _GSh_Primary (1<<3) +typedef struct _ShapeInfo +{ + CommonInfo defs; + Atom name; + short index; + unsigned short nOutlines; + unsigned short szOutlines; + XkbOutlinePtr outlines; + XkbOutlinePtr approx; + XkbOutlinePtr primary; + int dfltCornerRadius; +} ShapeInfo; + +#define shText(d,s) \ + ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default shape") + +#define _GD_Priority (1<<0) +#define _GD_Top (1<<1) +#define _GD_Left (1<<2) +#define _GD_Angle (1<<3) +#define _GD_Shape (1<<4) +#define _GD_FontVariant (1<<4) /* CHEATING */ +#define _GD_Corner (1<<5) +#define _GD_Width (1<<5) /* CHEATING */ +#define _GD_Color (1<<6) +#define _GD_OffColor (1<<7) +#define _GD_Height (1<<7) /* CHEATING */ +#define _GD_Text (1<<8) +#define _GD_Font (1<<9) +#define _GD_FontSlant (1<<10) +#define _GD_FontWeight (1<<11) +#define _GD_FontSetWidth (1<<12) +#define _GD_FontSize (1<<13) +#define _GD_FontEncoding (1<<14) +#define _GD_FontSpec (1<<15) + + +#define _GD_FontParts (_GD_Font|_GD_FontSlant|_GD_FontWeight|_GD_FontSetWidth|_GD_FontSize|_GD_FontEncoding|_GD_FontVariant) + +typedef struct _DoodadInfo +{ + CommonInfo defs; + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short corner; + unsigned short width; + unsigned short height; + Atom shape; + Atom color; + Atom offColor; + Atom text; + Atom font; + Atom fontSlant; + Atom fontWeight; + Atom fontSetWidth; + Atom fontVariant; + unsigned short fontSize; + Atom fontEncoding; + Atom fontSpec; + char *logoName; + struct _SectionInfo *section; +} DoodadInfo; + +#define Yes 1 +#define No 0 +#define Undefined -1 + +#define _GK_Default (1<<0) +#define _GK_Name (1<<1) +#define _GK_Gap (1<<2) +#define _GK_Shape (1<<3) +#define _GK_Color (1<<4) +typedef struct _KeyInfo +{ + CommonInfo defs; + char name[8]; + short gap; + short index; + Atom shape; + Atom color; + struct _RowInfo *row; +} KeyInfo; +#define keyText(k) ((k)&&(k)->name[0]?(k)->name:"default") + +#define _GR_Default (1<<0) +#define _GR_Vertical (1<<1) +#define _GR_Top (1<<2) +#define _GR_Left (1<<3) +typedef struct _RowInfo +{ + CommonInfo defs; + unsigned short top; + unsigned short left; + short index; + Bool vertical; + unsigned short nKeys; + KeyInfo *keys; + KeyInfo dfltKey; + struct _SectionInfo *section; +} RowInfo; +#define rowText(d,r) \ + ((r)?XkbAtomText((d),(r)->section->name,XkbMessage):"default") + +#define _GOK_UnknownRow -1 +typedef struct _OverlayKeyInfo +{ + CommonInfo defs; + short sectionRow; + short overlayRow; + char over[XkbKeyNameLength + 1]; + char under[XkbKeyNameLength + 1]; +} OverlayKeyInfo; + +typedef struct _OverlayInfo +{ + CommonInfo defs; + Atom name; + unsigned short nRows; + unsigned short nKeys; + OverlayKeyInfo *keys; +} OverlayInfo; + + +#define _GS_Default (1<<0) +#define _GS_Name (1<<1) +#define _GS_Top (1<<2) +#define _GS_Left (1<<3) +#define _GS_Width (1<<4) +#define _GS_Height (1<<5) +#define _GS_Angle (1<<6) +#define _GS_Priority (1<<7) +typedef struct _SectionInfo +{ + CommonInfo defs; + Atom name; + unsigned short top; + unsigned short left; + unsigned short width; + unsigned short height; + unsigned short angle; + unsigned short nRows; + unsigned short nDoodads; + unsigned short nOverlays; + unsigned char priority; + unsigned char nextDoodadPriority; + RowInfo *rows; + DoodadInfo *doodads; + RowInfo dfltRow; + DoodadInfo *dfltDoodads; + OverlayInfo *overlays; + struct _GeometryInfo *geometry; +} SectionInfo; +#define scText(d,s) ((s)?XkbAtomText((d),(s)->name,XkbMessage):"default") + +typedef struct _GeometryInfo +{ + char *name; + Display *dpy; + unsigned fileID; + unsigned merge; + int errorCount; + unsigned nextPriority; + int nProps; + int nShapes; + int nSections; + int nDoodads; + PropertyInfo *props; + ShapeInfo *shapes; + SectionInfo *sections; + DoodadInfo *doodads; + int widthMM; + int heightMM; + Atom font; + Atom fontSlant; + Atom fontWeight; + Atom fontSetWidth; + Atom fontVariant; + unsigned fontSize; + Atom fontEncoding; + Atom fontSpec; + Atom baseColor; + Atom labelColor; + int dfltCornerRadius; + SectionInfo dfltSection; + DoodadInfo *dfltDoodads; + AliasInfo *aliases; +} GeometryInfo; + +static char * +ddText(Display * dpy, DoodadInfo * di) +{ + static char buf[64]; + + if (di == NULL) + { + strcpy(buf, "default"); + return buf; + } + if (di->section) + { + sprintf(buf, "%s in section %s", + XkbAtomText(dpy, di->name, XkbMessage), scText(dpy, + di->section)); + return buf; + } + return XkbAtomText(dpy, di->name, XkbMessage); +} + +/***====================================================================***/ + +static void +InitPropertyInfo(PropertyInfo * pi, GeometryInfo * info) +{ + pi->defs.defined = 0; + pi->defs.fileID = info->fileID; + pi->defs.merge = info->merge; + pi->name = pi->value = NULL; + return; +} + +static void +FreeProperties(PropertyInfo * pi, GeometryInfo * info) +{ + PropertyInfo *tmp; + PropertyInfo *next; + + if (info->props == pi) + { + info->props = NULL; + info->nProps = 0; + } + for (tmp = pi; tmp != NULL; tmp = next) + { + if (tmp->name) + uFree(tmp->name); + if (tmp->value) + uFree(tmp->value); + tmp->name = tmp->value = NULL; + next = (PropertyInfo *) tmp->defs.next; + uFree(tmp); + } + return; +} + +static void +InitKeyInfo(KeyInfo * key, RowInfo * row, GeometryInfo * info) +{ + + if (key != &row->dfltKey) + { + *key = row->dfltKey; + strcpy(key->name, "unknown"); + key->defs.defined &= ~_GK_Default; + } + else + { + bzero(key, sizeof(KeyInfo)); + strcpy(key->name, "default"); + key->defs.defined = _GK_Default; + key->defs.fileID = info->fileID; + key->defs.merge = info->merge; + key->defs.next = NULL; + key->row = row; + } + return; +} + +static void +ClearKeyInfo(KeyInfo * key) +{ + key->defs.defined &= ~_GK_Default; + strcpy(key->name, "default"); + key->gap = 0; + key->shape = None; + key->color = None; + return; +} + +static void +FreeKeys(KeyInfo * key, RowInfo * row, GeometryInfo * info) +{ + KeyInfo *tmp; + KeyInfo *next; + + if (row->keys == key) + { + row->nKeys = 0; + row->keys = NULL; + } + for (tmp = key; tmp != NULL; tmp = next) + { + ClearKeyInfo(tmp); + next = (KeyInfo *) tmp->defs.next; + uFree(tmp); + } + return; +} + +static void +InitRowInfo(RowInfo * row, SectionInfo * section, GeometryInfo * info) +{ + if (row != §ion->dfltRow) + { + *row = section->dfltRow; + row->defs.defined &= ~_GR_Default; + } + else + { + bzero(row, sizeof(RowInfo *)); + row->defs.defined = _GR_Default; + row->defs.fileID = info->fileID; + row->defs.merge = info->merge; + row->defs.next = NULL; + row->section = section; + row->nKeys = 0; + row->keys = NULL; + InitKeyInfo(&row->dfltKey, row, info); + } + return; +} + +static void +ClearRowInfo(RowInfo * row, GeometryInfo * info) +{ + row->defs.defined &= ~_GR_Default; + row->top = row->left = 0; + row->vertical = False; + row->nKeys = 0; + if (row->keys) + FreeKeys(row->keys, row, info); + ClearKeyInfo(&row->dfltKey); + row->dfltKey.defs.defined |= _GK_Default; + return; +} + +static void +FreeRows(RowInfo * row, SectionInfo * section, GeometryInfo * info) +{ + RowInfo *next; + RowInfo *tmp; + + if (row == section->rows) + { + section->nRows = 0; + section->rows = NULL; + } + for (tmp = row; tmp != NULL; tmp = next) + { + ClearRowInfo(tmp, info); + next = (RowInfo *) tmp->defs.next; + uFree(tmp); + } + return; +} + +static DoodadInfo * +FindDoodadByType(DoodadInfo * di, unsigned type) +{ + while (di) + { + if (di->type == type) + return di; + di = (DoodadInfo *) di->defs.next; + } + return NULL; +} + +static DoodadInfo * +FindDoodadByName(DoodadInfo * di, Atom name) +{ + while (di) + { + if (di->name == name) + return di; + di = (DoodadInfo *) di->defs.next; + } + return NULL; +} + +static void +InitDoodadInfo(DoodadInfo * di, unsigned type, SectionInfo * si, + GeometryInfo * info) +{ + DoodadInfo *dflt; + + dflt = NULL; + if (si && si->dfltDoodads) + dflt = FindDoodadByType(si->dfltDoodads, type); + if ((dflt == NULL) && (info->dfltDoodads)) + dflt = FindDoodadByType(info->dfltDoodads, type); + if (dflt != NULL) + { + *di = *dflt; + di->defs.next = NULL; + } + else + { + bzero(di, sizeof(DoodadInfo)); + di->defs.fileID = info->fileID; + di->type = type; + } + di->section = si; + if (si != NULL) + { + di->priority = si->nextDoodadPriority++; +#if XkbGeomMaxPriority < 255 + if (si->nextDoodadPriority > XkbGeomMaxPriority) + si->nextDoodadPriority = XkbGeomMaxPriority; +#endif + } + else + { + di->priority = info->nextPriority++; + if (info->nextPriority > XkbGeomMaxPriority) + info->nextPriority = XkbGeomMaxPriority; + } + return; +} + +static void +ClearDoodadInfo(DoodadInfo * di) +{ + CommonInfo defs; + + defs = di->defs; + bzero(di, sizeof(DoodadInfo)); + di->defs = defs; + di->defs.defined = 0; + return; +} + +static void +ClearOverlayInfo(OverlayInfo * ol) +{ + if (ol && ol->keys) + { + ol->keys = (OverlayKeyInfo *) ClearCommonInfo(&ol->keys->defs); + ol->nKeys = 0; + } + return; +} + +static void +FreeDoodads(DoodadInfo * di, SectionInfo * si, GeometryInfo * info) +{ + DoodadInfo *tmp; + DoodadInfo *next; + + if (si) + { + if (si->doodads == di) + { + si->doodads = NULL; + si->nDoodads = 0; + } + if (si->dfltDoodads == di) + si->dfltDoodads = NULL; + } + if (info->doodads == di) + { + info->doodads = NULL; + info->nDoodads = 0; + } + if (info->dfltDoodads == di) + info->dfltDoodads = NULL; + for (tmp = di; tmp != NULL; tmp = next) + { + next = (DoodadInfo *) tmp->defs.next; + ClearDoodadInfo(tmp); + uFree(tmp); + } + return; +} + +static void +InitSectionInfo(SectionInfo * si, GeometryInfo * info) +{ + if (si != &info->dfltSection) + { + *si = info->dfltSection; + si->defs.defined &= ~_GS_Default; + si->name = XkbInternAtom(info->dpy, "unknown", False); + si->priority = info->nextPriority++; + if (info->nextPriority > XkbGeomMaxPriority) + info->nextPriority = XkbGeomMaxPriority; + } + else + { + bzero(si, sizeof(SectionInfo)); + si->defs.fileID = info->fileID; + si->defs.merge = info->merge; + si->defs.next = NULL; + si->geometry = info; + si->name = XkbInternAtom(info->dpy, "default", False); + InitRowInfo(&si->dfltRow, si, info); + } + return; +} + +static void +DupSectionInfo(SectionInfo * into, SectionInfo * from, GeometryInfo * info) +{ + CommonInfo defs; + + defs = into->defs; + *into = *from; + into->defs.fileID = defs.fileID; + into->defs.merge = defs.merge; + into->defs.next = NULL; + into->dfltRow.defs.fileID = defs.fileID; + into->dfltRow.defs.merge = defs.merge; + into->dfltRow.defs.next = NULL; + into->dfltRow.section = into; + into->dfltRow.dfltKey.defs.fileID = defs.fileID; + into->dfltRow.dfltKey.defs.merge = defs.merge; + into->dfltRow.dfltKey.defs.next = NULL; + into->dfltRow.dfltKey.row = &into->dfltRow; + return; +} + +static void +ClearSectionInfo(SectionInfo * si, GeometryInfo * info) +{ + + si->defs.defined &= ~_GS_Default; + si->name = XkbInternAtom(info->dpy, "default", False); + si->top = si->left = 0; + si->width = si->height = 0; + si->angle = 0; + if (si->rows) + { + FreeRows(si->rows, si, info); + si->rows = NULL; + } + ClearRowInfo(&si->dfltRow, info); + if (si->doodads) + { + FreeDoodads(si->doodads, si, info); + si->doodads = NULL; + } + si->dfltRow.defs.defined = _GR_Default; + return; +} + +static void +FreeSections(SectionInfo * si, GeometryInfo * info) +{ + SectionInfo *tmp; + SectionInfo *next; + + if (si == info->sections) + { + info->nSections = 0; + info->sections = NULL; + } + for (tmp = si; tmp != NULL; tmp = next) + { + ClearSectionInfo(tmp, info); + next = (SectionInfo *) tmp->defs.next; + uFree(tmp); + } + return; +} + +static void +FreeShapes(ShapeInfo * si, GeometryInfo * info) +{ + ShapeInfo *tmp; + ShapeInfo *next; + + if (si == info->shapes) + { + info->nShapes = 0; + info->shapes = NULL; + } + for (tmp = si; tmp != NULL; tmp = next) + { + if (tmp->outlines) + { + register int i; + for (i = 0; i < tmp->nOutlines; i++) + { + if (tmp->outlines[i].points != NULL) + { + uFree(tmp->outlines[i].points); + tmp->outlines[i].num_points = 0; + tmp->outlines[i].points = NULL; + } + } + uFree(tmp->outlines); + tmp->szOutlines = 0; + tmp->nOutlines = 0; + tmp->outlines = NULL; + tmp->primary = tmp->approx = NULL; + } + next = (ShapeInfo *) tmp->defs.next; + uFree(tmp); + } + return; +} + +/***====================================================================***/ + +static void +InitGeometryInfo(GeometryInfo * info, unsigned fileID, unsigned merge) +{ + bzero(info, sizeof(GeometryInfo)); + info->fileID = fileID; + info->merge = merge; + InitSectionInfo(&info->dfltSection, info); + info->dfltSection.defs.defined = _GS_Default; + return; +} + +static void +ClearGeometryInfo(GeometryInfo * info) +{ + if (info->name) + uFree(info->name); + info->name = NULL; + if (info->props) + FreeProperties(info->props, info); + if (info->shapes) + FreeShapes(info->shapes, info); + if (info->sections) + FreeSections(info->sections, info); + info->widthMM = 0; + info->heightMM = 0; + info->dfltCornerRadius = 0; + ClearSectionInfo(&info->dfltSection, info); + info->dfltSection.defs.defined = _GS_Default; + if (info->aliases) + ClearAliases(&info->aliases); + return; +} + +/***====================================================================***/ + +static PropertyInfo * +NextProperty(GeometryInfo * info) +{ + PropertyInfo *pi; + + pi = uTypedAlloc(PropertyInfo); + if (pi) + { + bzero((char *) pi, sizeof(PropertyInfo)); + info->props = (PropertyInfo *) AddCommonInfo(&info->props->defs, + (CommonInfo *) pi); + info->nProps++; + } + return pi; +} + +static PropertyInfo * +FindProperty(GeometryInfo * info, char *name) +{ + PropertyInfo *old; + + if (!name) + return NULL; + for (old = info->props; old != NULL; + old = (PropertyInfo *) old->defs.next) + { + if ((old->name) && (uStringEqual(name, old->name))) + return old; + } + return NULL; +} + +static Bool +AddProperty(GeometryInfo * info, PropertyInfo * new) +{ + PropertyInfo *old; + + if ((!new) || (!new->value) || (!new->name)) + return False; + old = FindProperty(info, new->name); + if (old != NULL) + { + if ((new->defs.merge == MergeReplace) + || (new->defs.merge == MergeOverride)) + { + if (((old->defs.fileID == new->defs.fileID) + && (warningLevel > 0)) || (warningLevel > 9)) + { + WARN1("Multiple definitions for the \"%s\" property\n", + new->name); + ACTION2("Ignoring \"%s\", using \"%s\"\n", old->value, + new->value); + } + if (old->value) + uFree(old->value); + old->value = uStringDup(new->value); + return True; + } + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple definitions for \"%s\" property\n", new->name); + ACTION2("Using \"%s\", ignoring \"%s\" \n", old->value, + new->value); + } + return True; + } + old = new; + if ((new = NextProperty(info)) == NULL) + return False; + new->defs.next = NULL; + new->name = uStringDup(old->name); + new->value = uStringDup(old->value); + return True; +} + +/***====================================================================***/ + +static ShapeInfo * +NextShape(GeometryInfo * info) +{ + ShapeInfo *si; + + si = uTypedAlloc(ShapeInfo); + if (si) + { + bzero((char *) si, sizeof(ShapeInfo)); + info->shapes = (ShapeInfo *) AddCommonInfo(&info->shapes->defs, + (CommonInfo *) si); + info->nShapes++; + si->dfltCornerRadius = info->dfltCornerRadius; + } + return si; +} + +static ShapeInfo * +FindShape(GeometryInfo * info, Atom name, const char *type, const char *which) +{ + ShapeInfo *old; + + for (old = info->shapes; old != NULL; old = (ShapeInfo *) old->defs.next) + { + if (name == old->name) + return old; + } + if (type != NULL) + { + old = info->shapes; + WARN3("Unknown shape \"%s\" for %s %s\n", + XkbAtomText(info->dpy, name, XkbMessage), type, which); + if (old) + { + ACTION1("Using default shape %s instead\n", + shText(info->dpy, old)); + return old; + } + ACTION("No default shape; definition ignored\n"); + return NULL; + } + return NULL; +} + +static Bool +AddShape(GeometryInfo * info, ShapeInfo * new) +{ + ShapeInfo *old; + + old = FindShape(info, new->name, NULL, NULL); + if (old != NULL) + { + if ((new->defs.merge == MergeReplace) + || (new->defs.merge == MergeOverride)) + { + ShapeInfo *next = (ShapeInfo *) old->defs.next; + if (((old->defs.fileID == new->defs.fileID) + && (warningLevel > 0)) || (warningLevel > 9)) + { + WARN1("Duplicate shape name \"%s\"\n", + shText(info->dpy, old)); + ACTION("Using last definition\n"); + } + *old = *new; + old->defs.next = &next->defs; + return True; + } + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old)); + ACTION("Using first definition\n"); + } + return True; + } + old = new; + if ((new = NextShape(info)) == NULL) + return False; + *new = *old; + new->defs.next = NULL; + old->szOutlines = old->nOutlines = 0; + old->outlines = NULL; + old->approx = NULL; + old->primary = NULL; + return True; +} + +/***====================================================================***/ + +static void +ReplaceDoodad(DoodadInfo * into, DoodadInfo * from) +{ + CommonInfo *next; + + next = into->defs.next; + ClearDoodadInfo(into); + *into = *from; + into->defs.next = next; + next = from->defs.next; + ClearDoodadInfo(from); + from->defs.next = next; + return; +} + +static DoodadInfo * +NextDfltDoodad(SectionInfo * si, GeometryInfo * info) +{ + DoodadInfo *di; + + di = uTypedCalloc(1, DoodadInfo); + if (!di) + return NULL; + if (si) + { + si->dfltDoodads = + (DoodadInfo *) AddCommonInfo(&si->dfltDoodads->defs, + (CommonInfo *) di); + } + else + { + info->dfltDoodads = + (DoodadInfo *) AddCommonInfo(&info->dfltDoodads->defs, + (CommonInfo *) di); + } + return di; +} + +static DoodadInfo * +NextDoodad(SectionInfo * si, GeometryInfo * info) +{ + DoodadInfo *di; + + di = uTypedCalloc(1, DoodadInfo); + if (di) + { + if (si) + { + si->doodads = (DoodadInfo *) AddCommonInfo(&si->doodads->defs, + (CommonInfo *) di); + si->nDoodads++; + } + else + { + info->doodads = + (DoodadInfo *) AddCommonInfo(&info->doodads->defs, + (CommonInfo *) di); + info->nDoodads++; + } + } + return di; +} + +static Bool +AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new) +{ + DoodadInfo *old; + + old = FindDoodadByName((si ? si->doodads : info->doodads), new->name); + if (old != NULL) + { + if ((new->defs.merge == MergeReplace) + || (new->defs.merge == MergeOverride)) + { + if (((old->defs.fileID == new->defs.fileID) + && (warningLevel > 0)) || (warningLevel > 9)) + { + WARN1("Multiple doodads named \"%s\"\n", + XkbAtomText(info->dpy, old->name, XkbMessage)); + ACTION("Using last definition\n"); + } + ReplaceDoodad(old, new); + old->section = si; + return True; + } + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple doodads named \"%s\"\n", + XkbAtomText(info->dpy, old->name, XkbMessage)); + ACTION("Using first definition\n"); + } + return True; + } + old = new; + if ((new = NextDoodad(si, info)) == NULL) + return False; + ReplaceDoodad(new, old); + new->section = si; + new->defs.next = NULL; + return True; +} + +static DoodadInfo * +FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info) +{ + DoodadInfo *dflt; + unsigned type; + + if (uStrCaseCmp(name, "outline") == 0) + type = XkbOutlineDoodad; + else if (uStrCaseCmp(name, "solid") == 0) + type = XkbSolidDoodad; + else if (uStrCaseCmp(name, "text") == 0) + type = XkbTextDoodad; + else if (uStrCaseCmp(name, "indicator") == 0) + type = XkbIndicatorDoodad; + else if (uStrCaseCmp(name, "logo") == 0) + type = XkbLogoDoodad; + else + return NULL; + if ((si) && (si->dfltDoodads)) + dflt = FindDoodadByType(si->dfltDoodads, type); + else + dflt = NULL; + if ((!dflt) && (info->dfltDoodads)) + dflt = FindDoodadByType(info->dfltDoodads, type); + if (dflt == NULL) + { + dflt = NextDfltDoodad(si, info); + if (dflt != NULL) + { + dflt->name = None; + dflt->type = type; + } + } + return dflt; +} + +/***====================================================================***/ + +static Bool +AddOverlay(SectionInfo * si, GeometryInfo * info, OverlayInfo * new) +{ + OverlayInfo *old; + + for (old = si->overlays; old != NULL; + old = (OverlayInfo *) old->defs.next) + { + if (old->name == new->name) + break; + } + if (old != NULL) + { + if ((new->defs.merge == MergeReplace) + || (new->defs.merge == MergeOverride)) + { + if (((old->defs.fileID == new->defs.fileID) + && (warningLevel > 0)) || (warningLevel > 9)) + { + WARN2 + ("Multiple overlays named \"%s\" for section \"%s\"\n", + XkbAtomText(info->dpy, old->name, XkbMessage), + XkbAtomText(info->dpy, si->name, XkbMessage)); + ACTION("Using last definition\n"); + } + ClearOverlayInfo(old); + old->nKeys = new->nKeys; + old->keys = new->keys; + new->nKeys = 0; + new->keys = NULL; + return True; + } + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN2("Multiple doodads named \"%s\" in section \"%s\"\n", + XkbAtomText(info->dpy, old->name, XkbMessage), + XkbAtomText(info->dpy, si->name, XkbMessage)); + ACTION("Using first definition\n"); + } + return True; + } + old = new; + new = uTypedCalloc(1, OverlayInfo); + if (!new) + { + if (warningLevel > 0) + { + WSGO("Couldn't allocate a new OverlayInfo\n"); + ACTION2 + ("Overlay \"%s\" in section \"%s\" will be incomplete\n", + XkbAtomText(info->dpy, old->name, XkbMessage), + XkbAtomText(info->dpy, si->name, XkbMessage)); + } + return False; + } + *new = *old; + old->nKeys = 0; + old->keys = NULL; + si->overlays = (OverlayInfo *) AddCommonInfo(&si->overlays->defs, + (CommonInfo *) new); + si->nOverlays++; + return True; +} + +/***====================================================================***/ + +static SectionInfo * +NextSection(GeometryInfo * info) +{ + SectionInfo *si; + + si = uTypedAlloc(SectionInfo); + if (si) + { + *si = info->dfltSection; + si->defs.defined &= ~_GS_Default; + si->defs.next = NULL; + si->nRows = 0; + si->rows = NULL; + info->sections = + (SectionInfo *) AddCommonInfo(&info->sections->defs, + (CommonInfo *) si); + info->nSections++; + } + return si; +} + +static SectionInfo * +FindMatchingSection(GeometryInfo * info, SectionInfo * new) +{ + SectionInfo *old; + + for (old = info->sections; old != NULL; + old = (SectionInfo *) old->defs.next) + { + if (new->name == old->name) + return old; + } + return NULL; +} + +static Bool +AddSection(GeometryInfo * info, SectionInfo * new) +{ + SectionInfo *old; + + old = FindMatchingSection(info, new); + if (old != NULL) + { +#ifdef NOTDEF + if ((new->defs.merge == MergeReplace) + || (new->defs.merge == MergeOverride)) + { + SectionInfo *next = (SectionInfo *) old->defs.next; + if (((old->defs.fileID == new->defs.fileID) + && (warningLevel > 0)) || (warningLevel > 9)) + { + WARN1("Duplicate shape name \"%s\"\n", + shText(info->dpy, old)); + ACTION("Using last definition\n"); + } + *old = *new; + old->defs.next = &next->defs; + return True; + } + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple shapes named \"%s\"\n", shText(info->dpy, old)); + ACTION("Using first definition\n"); + } + return True; +#else + WARN("Don't know how to merge sections yet\n"); +#endif + } + old = new; + if ((new = NextSection(info)) == NULL) + return False; + *new = *old; + new->defs.next = NULL; + old->nRows = old->nDoodads = old->nOverlays = 0; + old->rows = NULL; + old->doodads = NULL; + old->overlays = NULL; + if (new->doodads) + { + DoodadInfo *di; + for (di = new->doodads; di; di = (DoodadInfo *) di->defs.next) + { + di->section = new; + } + } + return True; +} + +/***====================================================================***/ + +static RowInfo * +NextRow(SectionInfo * si) +{ + RowInfo *row; + + row = uTypedAlloc(RowInfo); + if (row) + { + *row = si->dfltRow; + row->defs.defined &= ~_GR_Default; + row->defs.next = NULL; + row->nKeys = 0; + row->keys = NULL; + si->rows = + (RowInfo *) AddCommonInfo(&si->rows->defs, (CommonInfo *) row); + row->index = si->nRows++; + } + return row; +} + +static Bool +AddRow(SectionInfo * si, RowInfo * new) +{ + RowInfo *old; + + old = new; + if ((new = NextRow(si)) == NULL) + return False; + *new = *old; + new->defs.next = NULL; + old->nKeys = 0; + old->keys = NULL; + return True; +} + +/***====================================================================***/ + +static KeyInfo * +NextKey(RowInfo * row) +{ + KeyInfo *key; + + key = uTypedAlloc(KeyInfo); + if (key) + { + *key = row->dfltKey; + key->defs.defined &= ~_GK_Default; + key->defs.next = NULL; + key->index = row->nKeys++; + } + return key; +} + +static Bool +AddKey(RowInfo * row, KeyInfo * new) +{ + KeyInfo *old; + + old = new; + if ((new = NextKey(row)) == NULL) + return False; + *new = *old; + new->defs.next = NULL; + row->keys = + (KeyInfo *) AddCommonInfo(&row->keys->defs, (CommonInfo *) new); + return True; +} + +/***====================================================================***/ + +static void +MergeIncludedGeometry(GeometryInfo * into, GeometryInfo * from, + unsigned merge) +{ + Bool clobber; + + if (from->errorCount > 0) + { + into->errorCount += from->errorCount; + return; + } + clobber = (merge == MergeOverride) || (merge == MergeReplace); + if (into->name == NULL) + { + into->name = from->name; + from->name = NULL; + } + if ((into->widthMM == 0) || ((from->widthMM != 0) && clobber)) + into->widthMM = from->widthMM; + if ((into->heightMM == 0) || ((from->heightMM != 0) && clobber)) + into->heightMM = from->heightMM; + if ((into->font == None) || ((from->font != None) && clobber)) + into->font = from->font; + if ((into->fontSlant == None) || ((from->fontSlant != None) && clobber)) + into->fontSlant = from->fontSlant; + if ((into->fontWeight == None) || ((from->fontWeight != None) && clobber)) + into->fontWeight = from->fontWeight; + if ((into->fontSetWidth == None) + || ((from->fontSetWidth != None) && clobber)) + into->fontSetWidth = from->fontSetWidth; + if ((into->fontVariant == None) + || ((from->fontVariant != None) && clobber)) + into->fontVariant = from->fontVariant; + if ((into->fontSize == 0) || ((from->fontSize != 0) && clobber)) + into->fontSize = from->fontSize; + if ((into->fontEncoding == None) + || ((from->fontEncoding != None) && clobber)) + into->fontEncoding = from->fontEncoding; + if ((into->fontSpec == None) || ((from->fontSpec != None) && clobber)) + into->fontSpec = from->fontSpec; + if ((into->baseColor == None) || ((from->baseColor != None) && clobber)) + into->baseColor = from->baseColor; + if ((into->labelColor == None) || ((from->labelColor != None) && clobber)) + into->labelColor = from->labelColor; + into->nextPriority = from->nextPriority; + if (from->props != NULL) + { + PropertyInfo *pi; + for (pi = from->props; pi; pi = (PropertyInfo *) pi->defs.next) + { + if (!AddProperty(into, pi)) + into->errorCount++; + } + } + if (from->shapes != NULL) + { + ShapeInfo *si; + + for (si = from->shapes; si; si = (ShapeInfo *) si->defs.next) + { + if (!AddShape(into, si)) + into->errorCount++; + } + } + if (from->sections != NULL) + { + SectionInfo *si; + + for (si = from->sections; si; si = (SectionInfo *) si->defs.next) + { + if (!AddSection(into, si)) + into->errorCount++; + } + } + if (from->doodads != NULL) + { + DoodadInfo *di; + + for (di = from->doodads; di; di = (DoodadInfo *) di->defs.next) + { + if (!AddDoodad(NULL, into, di)) + into->errorCount++; + } + } + if (!MergeAliases(&into->aliases, &from->aliases, merge)) + into->errorCount++; + return; +} + +typedef void (*FileHandler) (XkbFile * /* file */ , + XkbDescPtr /* xkb */ , + unsigned /* merge */ , + GeometryInfo * /* info */ + ); + +static Bool +HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info, + FileHandler hndlr) +{ + unsigned newMerge; + XkbFile *rtrn; + GeometryInfo included; + Bool haveSelf; + + haveSelf = False; + if ((stmt->file == NULL) && (stmt->map == NULL)) + { + haveSelf = True; + included = *info; + bzero(info, sizeof(GeometryInfo)); + } + else if (ProcessIncludeFile(stmt, XkmGeometryIndex, &rtrn, &newMerge)) + { + InitGeometryInfo(&included, rtrn->id, newMerge); + included.nextPriority = info->nextPriority; + included.dfltCornerRadius = info->dfltCornerRadius; + DupSectionInfo(&included.dfltSection, &info->dfltSection, info); + (*hndlr) (rtrn, xkb, MergeOverride, &included); + if (stmt->stmt != NULL) + { + if (included.name != NULL) + uFree(included.name); + included.name = stmt->stmt; + stmt->stmt = NULL; + } + } + else + { + info->errorCount += 10; + return False; + } + if ((stmt->next != NULL) && (included.errorCount < 1)) + { + IncludeStmt *next; + unsigned op; + GeometryInfo next_incl; + + for (next = stmt->next; next != NULL; next = next->next) + { + if ((next->file == NULL) && (next->map == NULL)) + { + haveSelf = True; + MergeIncludedGeometry(&included, info, next->merge); + ClearGeometryInfo(info); + } + else if (ProcessIncludeFile(next, XkmGeometryIndex, &rtrn, &op)) + { + InitGeometryInfo(&next_incl, rtrn->id, op); + next_incl.nextPriority = included.nextPriority; + next_incl.dfltCornerRadius = included.dfltCornerRadius; + DupSectionInfo(&next_incl.dfltSection, + &included.dfltSection, &included); + (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); + MergeIncludedGeometry(&included, &next_incl, op); + ClearGeometryInfo(&next_incl); + } + else + { + info->errorCount += 10; + return False; + } + } + } + if (haveSelf) + *info = included; + else + { + MergeIncludedGeometry(info, &included, newMerge); + ClearGeometryInfo(&included); + } + return (info->errorCount == 0); +} + +static int +SetShapeField(ShapeInfo * si, + char *field, + ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) +{ + ExprResult tmp; + + if ((uStrCaseCmp(field, "radius") == 0) + || (uStrCaseCmp(field, "corner") == 0) + || (uStrCaseCmp(field, "cornerradius") == 0)) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("key shape", field, shText(info->dpy, si)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("key shape", field, + shText(info->dpy, si), "number"); + } + if (si) + si->dfltCornerRadius = tmp.ival; + else + info->dfltCornerRadius = tmp.ival; + return True; + } + info->errorCount++; + return ReportBadField("key shape", field, shText(info->dpy, si)); +} + +static int +SetShapeDoodadField(DoodadInfo * di, + char *field, + ExprDef * arrayNdx, + ExprDef * value, SectionInfo * si, GeometryInfo * info) +{ + ExprResult tmp; + const char *typeName; + + typeName = + (di->type == XkbSolidDoodad ? "solid doodad" : "outline doodad"); + if ((!uStrCaseCmp(field, "corner")) + || (!uStrCaseCmp(field, "cornerradius"))) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Corner; + di->corner = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "angle") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Angle; + di->angle = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "shape") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "string"); + } + di->shape = XkbInternAtom(info->dpy, tmp.str, False); + di->defs.defined |= _GD_Shape; + return True; + } + return ReportBadField(typeName, field, ddText(info->dpy, di)); +} + +#define FIELD_STRING 0 +#define FIELD_SHORT 1 +#define FIELD_USHORT 2 + +static int +SetTextDoodadField(DoodadInfo * di, + char *field, + ExprDef * arrayNdx, + ExprDef * value, SectionInfo * si, GeometryInfo * info) +{ + ExprResult tmp; + unsigned def; + unsigned type; + char *typeName = "text doodad"; + union + { + Atom *str; + short *ival; + unsigned short *uval; + } pField; + + if (uStrCaseCmp(field, "angle") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Angle; + di->angle = tmp.ival; + return True; + } + if (uStrCaseCmp(field, "width") == 0) + { + type = FIELD_USHORT; + pField.uval = &di->width; + def = _GD_Width; + } + else if (uStrCaseCmp(field, "height") == 0) + { + type = FIELD_USHORT; + pField.uval = &di->height; + def = _GD_Height; + } + else if (uStrCaseCmp(field, "text") == 0) + { + type = FIELD_STRING; + pField.str = &di->text; + def = _GD_Text; + } + else if (uStrCaseCmp(field, "font") == 0) + { + type = FIELD_STRING; + pField.str = &di->font; + def = _GD_Font; + } + else if ((uStrCaseCmp(field, "fontslant") == 0) || + (uStrCaseCmp(field, "slant") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontSlant; + def = _GD_FontSlant; + } + else if ((uStrCaseCmp(field, "fontweight") == 0) || + (uStrCaseCmp(field, "weight") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontWeight; + def = _GD_FontWeight; + } + else if ((uStrCaseCmp(field, "fontwidth") == 0) || + (uStrCaseCmp(field, "setwidth") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontSetWidth; + def = _GD_FontSetWidth; + } + else if ((uStrCaseCmp(field, "fontvariant") == 0) || + (uStrCaseCmp(field, "variant") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontVariant; + def = _GD_FontVariant; + } + else if ((uStrCaseCmp(field, "fontencoding") == 0) || + (uStrCaseCmp(field, "encoding") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontEncoding; + def = _GD_FontEncoding; + } + else if ((uStrCaseCmp(field, "xfont") == 0) || + (uStrCaseCmp(field, "xfontname") == 0)) + { + type = FIELD_STRING; + pField.str = &di->fontSpec; + def = _GD_FontSpec; + } + else if (uStrCaseCmp(field, "fontsize") == 0) + { + type = FIELD_USHORT; + pField.uval = &di->fontSize; + def = _GD_FontSize; + } + else + { + return ReportBadField(typeName, field, ddText(info->dpy, di)); + } + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (type == FIELD_STRING) + { + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "string"); + } + di->defs.defined |= def; + *pField.str = XkbInternAtom(NULL, tmp.str, False); + } + else + { + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + if ((type == FIELD_USHORT) && (tmp.ival < 0)) + { + info->errorCount++; + return + ReportBadType(typeName, field, ddText(info->dpy, di), + "unsigned"); + } + di->defs.defined |= def; + if (type == FIELD_USHORT) + *pField.uval = tmp.uval; + else + *pField.ival = tmp.ival; + } + return True; +} + +static int +SetIndicatorDoodadField(DoodadInfo * di, + char *field, + ExprDef * arrayNdx, + ExprDef * value, + SectionInfo * si, GeometryInfo * info) +{ + ExprResult tmp; + + if ((uStrCaseCmp(field, "oncolor") == 0) + || (uStrCaseCmp(field, "offcolor") == 0) + || (uStrCaseCmp(field, "shape") == 0)) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("indicator doodad", field, + ddText(info->dpy, di)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("indicator doodad", field, + ddText(info->dpy, di), "string"); + } + if (uStrCaseCmp(field, "oncolor") == 0) + { + di->defs.defined |= _GD_Color; + di->color = XkbInternAtom(NULL, tmp.str, False); + } + else if (uStrCaseCmp(field, "offcolor") == 0) + { + di->defs.defined |= _GD_OffColor; + di->offColor = XkbInternAtom(NULL, tmp.str, False); + } + else if (uStrCaseCmp(field, "shape") == 0) + { + di->defs.defined |= _GD_Shape; + di->shape = XkbInternAtom(info->dpy, tmp.str, False); + } + return True; + } + return ReportBadField("indicator doodad", field, ddText(info->dpy, di)); +} + +static int +SetLogoDoodadField(DoodadInfo * di, + char *field, + ExprDef * arrayNdx, + ExprDef * value, SectionInfo * si, GeometryInfo * info) +{ + ExprResult tmp; + char *typeName = "logo doodad"; + + if ((!uStrCaseCmp(field, "corner")) + || (!uStrCaseCmp(field, "cornerradius"))) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Corner; + di->corner = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "angle") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Angle; + di->angle = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "shape") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "string"); + } + di->shape = XkbInternAtom(info->dpy, tmp.str, False); + di->defs.defined |= _GD_Shape; + return True; + } + else if ((!uStrCaseCmp(field, "logoname")) + || (!uStrCaseCmp(field, "name"))) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray(typeName, field, ddText(info->dpy, di)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType(typeName, field, ddText(info->dpy, di), + "string"); + } + di->logoName = uStringDup(tmp.str); + return True; + } + return ReportBadField(typeName, field, ddText(info->dpy, di)); +} + +static int +SetDoodadField(DoodadInfo * di, + char *field, + ExprDef * arrayNdx, + ExprDef * value, SectionInfo * si, GeometryInfo * info) +{ + ExprResult tmp; + + if (uStrCaseCmp(field, "priority") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("doodad", field, ddText(info->dpy, di)); + } + if (!ExprResolveInteger(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("doodad", field, ddText(info->dpy, di), + "integer"); + } + if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority)) + { + info->errorCount++; + ERROR2("Doodad priority %d out of range (must be 0..%d)\n", + tmp.ival, XkbGeomMaxPriority); + ACTION1("Priority for doodad %s not changed", + ddText(info->dpy, di)); + return False; + } + di->defs.defined |= _GD_Priority; + di->priority = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "left") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("doodad", field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("doodad", field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Left; + di->left = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "top") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("doodad", field, ddText(info->dpy, di)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("doodad", field, ddText(info->dpy, di), + "number"); + } + di->defs.defined |= _GD_Top; + di->top = tmp.ival; + return True; + } + else if (uStrCaseCmp(field, "color") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("doodad", field, ddText(info->dpy, di)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("doodad", field, ddText(info->dpy, di), + "string"); + } + di->defs.defined |= _GD_Color; + di->color = XkbInternAtom(NULL, tmp.str, False); + return True; + } + switch (di->type) + { + case XkbOutlineDoodad: + case XkbSolidDoodad: + return SetShapeDoodadField(di, field, arrayNdx, value, si, info); + case XkbTextDoodad: + return SetTextDoodadField(di, field, arrayNdx, value, si, info); + case XkbIndicatorDoodad: + return SetIndicatorDoodadField(di, field, arrayNdx, value, si, info); + case XkbLogoDoodad: + return SetLogoDoodadField(di, field, arrayNdx, value, si, info); + } + WSGO1("Unknown doodad type %d in SetDoodadField\n", + (unsigned int) di->type); + ACTION2("Definition of %s in %s ignored\n", field, ddText(info->dpy, di)); + return False; +} + +static int +SetSectionField(SectionInfo * si, + char *field, + ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) +{ + unsigned short *pField; + unsigned def; + ExprResult tmp; + + pField = NULL; + def = 0; + if (uStrCaseCmp(field, "priority") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard section", field, + scText(info->dpy, si)); + } + if (!ExprResolveInteger(value, &tmp, NULL, NULL)) + { + info->errorCount++; + ReportBadType("keyboard section", field, + scText(info->dpy, si), "integer"); + return False; + } + if ((tmp.ival < 0) || (tmp.ival > XkbGeomMaxPriority)) + { + info->errorCount++; + ERROR2("Section priority %d out of range (must be 0..%d)\n", + tmp.ival, XkbGeomMaxPriority); + ACTION1("Priority for section %s not changed", + scText(info->dpy, si)); + return False; + } + si->priority = tmp.ival; + si->defs.defined |= _GS_Priority; + return True; + } + else if (uStrCaseCmp(field, "top") == 0) + { + pField = &si->top; + def = _GS_Top; + } + else if (uStrCaseCmp(field, "left") == 0) + { + pField = &si->left; + def = _GS_Left; + } + else if (uStrCaseCmp(field, "width") == 0) + { + pField = &si->width; + def = _GS_Width; + } + else if (uStrCaseCmp(field, "height") == 0) + { + pField = &si->height; + def = _GS_Height; + } + else if (uStrCaseCmp(field, "angle") == 0) + { + pField = &si->angle; + def = _GS_Angle; + } + else + { + info->errorCount++; + return ReportBadField("keyboard section", field, + scText(info->dpy, si)); + } + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard section", field, + scText(info->dpy, si)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + ReportBadType("keyboard section", field, scText(info->dpy, si), + "number"); + return False; + } + si->defs.defined |= def; + *pField = tmp.uval; + return True; +} + +static int +SetRowField(RowInfo * row, + char *field, + ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) +{ + ExprResult tmp; + + if (uStrCaseCmp(field, "top") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard row", field, + rowText(info->dpy, row)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard row", field, + rowText(info->dpy, row), "number"); + } + row->defs.defined |= _GR_Top; + row->top = tmp.uval; + } + else if (uStrCaseCmp(field, "left") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard row", field, + rowText(info->dpy, row)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard row", field, + rowText(info->dpy, row), "number"); + } + row->defs.defined |= _GR_Left; + row->left = tmp.uval; + } + else if (uStrCaseCmp(field, "vertical") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard row", field, + rowText(info->dpy, row)); + } + if (!ExprResolveBoolean(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard row", field, + rowText(info->dpy, row), "boolean"); + } + row->defs.defined |= _GR_Vertical; + row->vertical = tmp.uval; + } + else + { + info->errorCount++; + return ReportBadField("keyboard row", field, rowText(info->dpy, row)); + } + return True; +} + +static int +SetKeyField(KeyInfo * key, + const char *field, + ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) +{ + ExprResult tmp; + + if (uStrCaseCmp(field, "gap") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("key", field, keyText(key)); + } + if (!ExprResolveFloat(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("key", field, keyText(key), "number"); + } + key->defs.defined |= _GK_Gap; + key->gap = tmp.ival; + } + else if (uStrCaseCmp(field, "shape") == 0) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("key", field, keyText(key)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("key", field, keyText(key), "string"); + } + key->defs.defined |= _GK_Shape; + key->shape = XkbInternAtom(info->dpy, tmp.str, False); + } + else if ((uStrCaseCmp(field, "color") == 0) || + (uStrCaseCmp(field, "keycolor") == 0)) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("key", field, keyText(key)); + } + if (!ExprResolveString(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("key", field, keyText(key), "string"); + } + key->defs.defined |= _GK_Color; + key->color = XkbInternAtom(NULL, tmp.str, False); + } + else if ((uStrCaseCmp(field, "name") == 0) + || (uStrCaseCmp(field, "keyname") == 0)) + { + if (arrayNdx != NULL) + { + info->errorCount++; + return ReportNotArray("key", field, keyText(key)); + } + if (!ExprResolveKeyName(value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("key", field, keyText(key), "key name"); + } + key->defs.defined |= _GK_Name; + bzero(key->name, XkbKeyNameLength + 1); + strncpy(key->name, tmp.keyName.name, XkbKeyNameLength); + } + else + { + info->errorCount++; + return ReportBadField("key", field, keyText(key)); + } + return True; +} + +static int +SetGeometryProperty(GeometryInfo * info, char *property, ExprDef * value) +{ + PropertyInfo pi; + ExprResult result; + + InitPropertyInfo(&pi, info); + pi.name = property; + if (!ExprResolveString(value, &result, NULL, NULL)) + { + info->errorCount++; + ERROR("Property values must be type string\n"); + ACTION1("Ignoring illegal definition of \"%s\" property\n", property); + return False; + } + pi.value = result.str; + return AddProperty(info, &pi); +} + +static int +HandleGeometryVar(VarDef * stmt, XkbDescPtr xkb, GeometryInfo * info) +{ + ExprResult elem, field, tmp; + ExprDef *ndx; + DoodadInfo *di; + Atom *pField; + + if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0) + return 0; /* internal error, already reported */ + if (elem.str && (uStrCaseCmp(elem.str, "shape") == 0)) + return SetShapeField(NULL, field.str, ndx, stmt->value, info); + if (elem.str && (uStrCaseCmp(elem.str, "key") == 0)) + return SetKeyField(&info->dfltSection.dfltRow.dfltKey, + field.str, ndx, stmt->value, info); + if (elem.str && (uStrCaseCmp(elem.str, "row") == 0)) + return SetRowField(&info->dfltSection.dfltRow, field.str, ndx, + stmt->value, info); + if (elem.str && (uStrCaseCmp(elem.str, "section") == 0)) + { + return SetSectionField(&info->dfltSection, field.str, ndx, + stmt->value, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "property") == 0)) + { + if (ndx != NULL) + { + info->errorCount++; + ERROR1("The %s geometry property is not an array\n", field.str); + ACTION("Ignoring illegal property definition\n"); + return False; + } + return SetGeometryProperty(info, field.str, stmt->value); + } + if (elem.str + && ((di = FindDfltDoodadByTypeName(elem.str, NULL, info)) != NULL)) + { + return SetDoodadField(di, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "solid") == 0)) + { + DoodadInfo *dflt; + dflt = FindDoodadByType(info->dfltDoodads, XkbSolidDoodad); + if (dflt == NULL) + dflt = NextDfltDoodad(NULL, info); + return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "outline") == 0)) + { + DoodadInfo *dflt; + dflt = FindDoodadByType(info->dfltDoodads, XkbOutlineDoodad); + if (dflt == NULL) + dflt = NextDfltDoodad(NULL, info); + return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "text") == 0)) + { + DoodadInfo *dflt; + dflt = FindDoodadByType(info->dfltDoodads, XkbTextDoodad); + if (dflt == NULL) + dflt = NextDfltDoodad(NULL, info); + return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0)) + { + DoodadInfo *dflt; + dflt = FindDoodadByType(info->dfltDoodads, XkbIndicatorDoodad); + if (dflt == NULL) + dflt = NextDfltDoodad(NULL, info); + return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str && (uStrCaseCmp(elem.str, "logo") == 0)) + { + DoodadInfo *dflt; + dflt = FindDoodadByType(info->dfltDoodads, XkbLogoDoodad); + if (dflt == NULL) + dflt = NextDfltDoodad(NULL, info); + return SetDoodadField(dflt, field.str, ndx, stmt->value, NULL, info); + } + if (elem.str) + { + WARN("Assignment to field of unknown element\n"); + ACTION2("No value assigned to %s.%s\n", elem.str, field.str); + return False; + } + + if ((uStrCaseCmp(field.str, "width") == 0) || + (uStrCaseCmp(field.str, "widthmm") == 0)) + { + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "number"); + } + if (tmp.ival < 1) + { + WARN("Keyboard width must be positive\n"); + ACTION1("Ignoring illegal keyboard width %s\n", + XkbGeomFPText(tmp.ival, XkbMessage)); + return True; + } + if (info->widthMM != 0) + { + WARN("Keyboard width multiply defined\n"); + ACTION1("Using last definition (%s),", + XkbGeomFPText(tmp.ival, XkbMessage)); + INFO1(" ignoring first (%s)\n", + XkbGeomFPText(info->widthMM, XkbMessage)); + } + info->widthMM = tmp.ival; + return True; + } + else if ((uStrCaseCmp(field.str, "height") == 0) || + (uStrCaseCmp(field.str, "heightmm") == 0)) + { + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "number"); + } + if (tmp.ival < 1) + { + WARN("Keyboard height must be positive\n"); + ACTION1("Ignoring illegal keyboard height %s\n", + XkbGeomFPText(tmp.ival, XkbMessage)); + return True; + } + if (info->heightMM != 0) + { + WARN("Keyboard height multiply defined\n"); + ACTION1("Using last definition (%s),", + XkbGeomFPText(tmp.ival, XkbMessage)); + INFO1(" ignoring first (%s)\n", + XkbGeomFPText(info->heightMM, XkbMessage)); + } + info->heightMM = tmp.ival; + return True; + } + else if (uStrCaseCmp(field.str, "font") == 0) + { + pField = &info->font; + } + else if ((uStrCaseCmp(field.str, "fontslant") == 0) || + (uStrCaseCmp(field.str, "slant") == 0)) + { + pField = &info->fontSlant; + } + else if ((uStrCaseCmp(field.str, "fontweight") == 0) || + (uStrCaseCmp(field.str, "weight") == 0)) + { + pField = &info->fontWeight; + } + else if ((uStrCaseCmp(field.str, "fontwidth") == 0) || + (uStrCaseCmp(field.str, "setwidth") == 0)) + { + pField = &info->fontWeight; + } + else if ((uStrCaseCmp(field.str, "fontencoding") == 0) || + (uStrCaseCmp(field.str, "encoding") == 0)) + { + pField = &info->fontEncoding; + } + else if ((uStrCaseCmp(field.str, "xfont") == 0) || + (uStrCaseCmp(field.str, "xfontname") == 0)) + { + pField = &info->fontSpec; + } + else if (uStrCaseCmp(field.str, "fontsize") == 0) + { + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveFloat(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "number"); + } + if ((tmp.ival < 40) || (tmp.ival > 2550)) + { + info->errorCount++; + ERROR1("Illegal font size %d (must be 4..255)\n", tmp.ival); + ACTION("Ignoring font size in keyboard geometry\n"); + return False; + } + info->fontSize = tmp.ival; + return True; + } + else if ((uStrCaseCmp(field.str, "color") == 0) || + (uStrCaseCmp(field.str, "basecolor") == 0)) + { + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "string"); + } + info->baseColor = XkbInternAtom(NULL, tmp.str, False); + return True; + } + else if (uStrCaseCmp(field.str, "labelcolor") == 0) + { + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "string"); + } + info->labelColor = XkbInternAtom(NULL, tmp.str, False); + return True; + } + else + { + return SetGeometryProperty(info, field.str, stmt->value); + } + + if (ndx != NULL) + { + info->errorCount++; + return ReportNotArray("keyboard", field.str, "geometry"); + } + if (!ExprResolveString(stmt->value, &tmp, NULL, NULL)) + { + info->errorCount++; + return ReportBadType("keyboard", field.str, "geometry", "string"); + } + *pField = XkbInternAtom(NULL, tmp.str, False); + return True; +} + +/***====================================================================***/ + +static Bool +HandleShapeBody(ShapeDef * def, ShapeInfo * si, unsigned merge, + GeometryInfo * info) +{ + OutlineDef *ol; + int nOut, nPt; + XkbOutlinePtr outline; + ExprDef *pt; + + if (def->nOutlines < 1) + { + WARN1("Shape \"%s\" has no outlines\n", shText(info->dpy, si)); + ACTION("Definition ignored\n"); + return True; + } + si->nOutlines = def->nOutlines; + si->outlines = uTypedCalloc(def->nOutlines, XkbOutlineRec); + if (!si->outlines) + { + ERROR1("Couldn't allocate outlines for \"%s\"\n", + shText(info->dpy, si)); + ACTION("Definition ignored\n"); + info->errorCount++; + return False; + } + for (nOut = 0, ol = def->outlines; ol != NULL; + ol = (OutlineDef *) ol->common.next) + { + if (ol->nPoints < 1) + { + SetShapeField(si, XkbAtomGetString(NULL, ol->field), NULL, + ol->points, info); + continue; + } + outline = NULL; + outline = &si->outlines[nOut++]; + outline->num_points = ol->nPoints; + outline->corner_radius = si->dfltCornerRadius; + outline->points = uTypedCalloc(ol->nPoints, XkbPointRec); + if (!outline->points) + { + ERROR1("Can't allocate points for \"%s\"\n", + shText(info->dpy, si)); + ACTION("Definition ignored\n"); + info->errorCount++; + return False; + } + for (nPt = 0, pt = ol->points; pt != NULL; + pt = (ExprDef *) pt->common.next) + { + outline->points[nPt].x = pt->value.coord.x; + outline->points[nPt].y = pt->value.coord.y; + nPt++; + } + if (ol->field != None) + { + char *str = XkbAtomText(NULL, ol->field, XkbMessage); + if ((uStrCaseCmp(str, "approximation") == 0) || + (uStrCaseCmp(str, "approx") == 0)) + { + if (si->approx == NULL) + si->approx = outline; + else + { + WARN1("Multiple approximations for \"%s\"\n", + shText(info->dpy, si)); + ACTION("Treating all but the first as normal outlines\n"); + } + } + else if (uStrCaseCmp(str, "primary") == 0) + { + if (si->primary == NULL) + si->primary = outline; + else + { + WARN1("Multiple primary outlines for \"%s\"\n", + shText(info->dpy, si)); + ACTION("Treating all but the first as normal outlines\n"); + } + } + else + { + WARN2("Unknown outline type %s for \"%s\"\n", str, + shText(info->dpy, si)); + ACTION("Treated as a normal outline\n"); + } + } + } + if (nOut != si->nOutlines) + { + WSGO2("Expected %d outlines, got %d\n", + (unsigned int) si->nOutlines, nOut); + si->nOutlines = nOut; + } + return True; +} + +static int +HandleShapeDef(ShapeDef * def, XkbDescPtr xkb, unsigned merge, + GeometryInfo * info) +{ + ShapeInfo si; + + if (def->merge != MergeDefault) + merge = def->merge; + + bzero(&si, sizeof(ShapeInfo)); + si.defs.merge = merge; + si.name = + XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); + si.dfltCornerRadius = info->dfltCornerRadius; + if (!HandleShapeBody(def, &si, merge, info)) + return False; + if (!AddShape(info, &si)) + return False; + return True; +} + +/***====================================================================***/ + +static int +HandleDoodadDef(DoodadDef * def, + unsigned merge, SectionInfo * si, GeometryInfo * info) +{ + ExprResult elem, field; + ExprDef *ndx; + DoodadInfo new; + VarDef *var; + + if (def->common.stmtType == StmtIndicatorMapDef) + { + def->common.stmtType = StmtDoodadDef; + def->type = XkbIndicatorDoodad; + } + InitDoodadInfo(&new, def->type, si, info); + new.name = + XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); + for (var = def->body; var != NULL; var = (VarDef *) var->common.next) + { + if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) + return 0; /* internal error, already reported */ + if (elem.str != NULL) + { + WARN1("Assignment to field of unknown element in doodad %s\n", + ddText(info->dpy, &new)); + ACTION2("No value assigned to %s.%s\n", elem.str, field.str); + } + else if (!SetDoodadField(&new, field.str, ndx, var->value, si, info)) + return False; + } + if (!AddDoodad(si, info, &new)) + return False; + ClearDoodadInfo(&new); + return True; +} + +/***====================================================================***/ + +static int +HandleOverlayDef(OverlayDef * def, + unsigned merge, SectionInfo * si, GeometryInfo * info) +{ + OverlayKeyDef *keyDef; + OverlayKeyInfo *key; + OverlayInfo ol; + + if ((def->nKeys < 1) && (warningLevel > 3)) + { + WARN2("Overlay \"%s\" in section \"%s\" has no keys\n", + XkbAtomText(NULL, def->name, XkbMessage), scText(info->dpy, + si)); + ACTION("Overlay ignored\n"); + return True; + } + bzero(&ol, sizeof(OverlayInfo)); + ol.name = + XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); + for (keyDef = def->keys; keyDef; + keyDef = (OverlayKeyDef *) keyDef->common.next) + { + key = uTypedCalloc(1, OverlayKeyInfo); + if ((!key) && warningLevel > 0) + { + WSGO("Couldn't allocate OverlayKeyInfo\n"); + ACTION2("Overlay %s for section %s will be incomplete\n", + XkbAtomText(info->dpy, ol.name, XkbMessage), + scText(info->dpy, si)); + return False; + } + strncpy(key->over, keyDef->over, XkbKeyNameLength); + strncpy(key->under, keyDef->under, XkbKeyNameLength); + key->sectionRow = _GOK_UnknownRow; + key->overlayRow = _GOK_UnknownRow; + ol.keys = (OverlayKeyInfo *) AddCommonInfo(&ol.keys->defs, + (CommonInfo *) key); + ol.nKeys++; + } + if (!AddOverlay(si, info, &ol)) + return False; + ClearOverlayInfo(&ol); + return True; +} + +/***====================================================================***/ + +static Bool +HandleComplexKey(KeyDef * def, KeyInfo * key, GeometryInfo * info) +{ + RowInfo *row; + ExprDef *expr; + + row = key->row; + for (expr = def->expr; expr != NULL; expr = (ExprDef *) expr->common.next) + { + if (expr->op == OpAssign) + { + ExprResult elem, f; + ExprDef *ndx; + if (ExprResolveLhs(expr->value.binary.left, &elem, &f, &ndx) == 0) + return False; /* internal error, already reported */ + if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "key") == 0)) + { + if (!SetKeyField + (key, f.str, ndx, expr->value.binary.right, info)) + return False; + } + else + { + ERROR("Illegal element used in a key definition\n"); + ACTION2("Assignment to %s.%s ignored\n", elem.str, f.str); + return False; + } + } + else + { + switch (expr->type) + { + case TypeInt: + case TypeFloat: + if (!SetKeyField(key, "gap", NULL, expr, info)) + return False; + break; + case TypeString: + if (!SetKeyField(key, "shape", NULL, expr, info)) + return False; + break; + case TypeKeyName: + if (!SetKeyField(key, "name", NULL, expr, info)) + return False; + break; + default: + ERROR("Cannot determine field for unnamed expression\n"); + ACTION3("Ignoring key %d in row %d of section %s\n", + row->nKeys + 1, row->section->nRows + 1, + rowText(info->dpy, row)); + return False; + } + } + } + return True; +} + +static Bool +HandleRowBody(RowDef * def, RowInfo * row, unsigned merge, + GeometryInfo * info) +{ + KeyDef *keyDef; + + if ((def->nKeys < 1) && (warningLevel > 3)) + { + ERROR1("Row in section %s has no keys\n", rowText(info->dpy, row)); + ACTION("Section ignored\n"); + return True; + } + for (keyDef = def->keys; keyDef != NULL; + keyDef = (KeyDef *) keyDef->common.next) + { + if (keyDef->common.stmtType == StmtVarDef) + { + VarDef *var = (VarDef *) keyDef; + ExprResult elem, field; + ExprDef *ndx; + if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) + return 0; /* internal error, already reported */ + if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "row") == 0)) + { + if (!SetRowField(row, field.str, ndx, var->value, info)) + return False; + } + else if (uStrCaseCmp(elem.str, "key") == 0) + { + if (!SetKeyField + (&row->dfltKey, field.str, ndx, var->value, info)) + return False; + } + else + { + WARN("Assignment to field of unknown element in row\n"); + ACTION2("No value assigned to %s.%s\n", elem.str, field.str); + } + } + else if (keyDef->common.stmtType == StmtKeyDef) + { + KeyInfo key; + InitKeyInfo(&key, row, info); + if (keyDef->name != NULL) + { + int len = strlen(keyDef->name); + if ((len < 1) || (len > XkbKeyNameLength)) + { + ERROR2("Illegal name %s for key in section %s\n", + keyDef->name, rowText(info->dpy, row)); + ACTION("Section not compiled\n"); + return False; + } + bzero(key.name, XkbKeyNameLength + 1); + strncpy(key.name, keyDef->name, XkbKeyNameLength); + key.defs.defined |= _GK_Name; + } + else if (!HandleComplexKey(keyDef, &key, info)) + return False; + if (!AddKey(row, &key)) + return False; + } + else + { + WSGO1("Unexpected statement (type %d) in row body\n", + keyDef->common.stmtType); + return False; + } + } + return True; +} + +static Bool +HandleSectionBody(SectionDef * def, + SectionInfo * si, unsigned merge, GeometryInfo * info) +{ + RowDef *rowDef; + DoodadInfo *di; + + for (rowDef = def->rows; rowDef != NULL; + rowDef = (RowDef *) rowDef->common.next) + { + if (rowDef->common.stmtType == StmtVarDef) + { + VarDef *var = (VarDef *) rowDef; + ExprResult elem, field; + ExprDef *ndx; + if (ExprResolveLhs(var->name, &elem, &field, &ndx) == 0) + return 0; /* internal error, already reported */ + if ((elem.str == NULL) || (uStrCaseCmp(elem.str, "section") == 0)) + { + if (!SetSectionField(si, field.str, ndx, var->value, info)) + return False; + } + else if (uStrCaseCmp(elem.str, "row") == 0) + { + if (!SetRowField + (&si->dfltRow, field.str, ndx, var->value, info)) + return False; + } + else if (uStrCaseCmp(elem.str, "key") == 0) + { + if (!SetKeyField(&si->dfltRow.dfltKey, field.str, ndx, + var->value, info)) + return False; + } + else if ((di = + FindDfltDoodadByTypeName(elem.str, si, info)) != NULL) + { + if (!SetDoodadField(di, field.str, ndx, var->value, si, info)) + return False; + } + else + { + WARN("Assignment to field of unknown element in section\n"); + ACTION2("No value assigned to %s.%s\n", elem.str, field.str); + } + } + else if (rowDef->common.stmtType == StmtRowDef) + { + RowInfo row; + InitRowInfo(&row, si, info); + if (!HandleRowBody(rowDef, &row, merge, info)) + return False; + if (!AddRow(si, &row)) + return False; +/* ClearRowInfo(&row,info);*/ + } + else if ((rowDef->common.stmtType == StmtDoodadDef) || + (rowDef->common.stmtType == StmtIndicatorMapDef)) + { + if (!HandleDoodadDef((DoodadDef *) rowDef, merge, si, info)) + return False; + } + else if (rowDef->common.stmtType == StmtOverlayDef) + { + if (!HandleOverlayDef((OverlayDef *) rowDef, merge, si, info)) + return False; + } + else + { + WSGO1("Unexpected statement (type %d) in section body\n", + rowDef->common.stmtType); + return False; + } + } + if (si->nRows != def->nRows) + { + WSGO2("Expected %d rows, found %d\n", (unsigned int) def->nRows, + (unsigned int) si->nRows); + ACTION1("Definition of section %s might be incorrect\n", + scText(info->dpy, si)); + } + return True; +} + +static int +HandleSectionDef(SectionDef * def, + XkbDescPtr xkb, unsigned merge, GeometryInfo * info) +{ + SectionInfo si; + char *str; + + if (def->merge != MergeDefault) + merge = def->merge; + InitSectionInfo(&si, info); + si.defs.merge = merge; + str = XkbAtomGetString(NULL, def->name); + if ((str == NULL) || (strlen(str) < 1)) + { + ERROR("Section defined without a name\n"); + ACTION("Definition ignored\n"); + return False; + } + si.name = + XkbInternAtom(info->dpy, XkbAtomGetString(NULL, def->name), False); + if (!HandleSectionBody(def, &si, merge, info)) + return False; + if (!AddSection(info, &si)) + return False; + return True; +} + +/***====================================================================***/ + +static void +HandleGeometryFile(XkbFile * file, + XkbDescPtr xkb, unsigned merge, GeometryInfo * info) +{ + ParseCommon *stmt; + char *failWhat; + + if (merge == MergeDefault) + merge = MergeAugment; + info->name = uStringDup(file->name); + stmt = file->defs; + while (stmt) + { + failWhat = NULL; + switch (stmt->stmtType) + { + case StmtInclude: + if (!HandleIncludeGeometry((IncludeStmt *) stmt, xkb, info, + HandleGeometryFile)) + info->errorCount++; + break; + case StmtKeyAliasDef: + if (!HandleAliasDef((KeyAliasDef *) stmt, + merge, info->fileID, &info->aliases)) + { + info->errorCount++; + } + break; + case StmtVarDef: + if (!HandleGeometryVar((VarDef *) stmt, xkb, info)) + info->errorCount++; + break; + case StmtShapeDef: + if (!HandleShapeDef((ShapeDef *) stmt, xkb, merge, info)) + info->errorCount++; + break; + case StmtSectionDef: + if (!HandleSectionDef((SectionDef *) stmt, xkb, merge, info)) + info->errorCount++; + break; + case StmtIndicatorMapDef: + case StmtDoodadDef: + if (!HandleDoodadDef((DoodadDef *) stmt, merge, NULL, info)) + info->errorCount++; + break; + case StmtVModDef: + if (!failWhat) + failWhat = "virtual modfier"; + case StmtInterpDef: + if (!failWhat) + failWhat = "symbol interpretation"; + case StmtGroupCompatDef: + if (!failWhat) + failWhat = "group compatibility map"; + case StmtKeycodeDef: + if (!failWhat) + failWhat = "key name"; + ERROR("Interpretation files may not include other types\n"); + ACTION1("Ignoring %s definition.\n", failWhat); + info->errorCount++; + break; + default: + WSGO1("Unexpected statement type %d in HandleGeometryFile\n", + stmt->stmtType); + break; + } + stmt = stmt->next; + if (info->errorCount > 10) + { +#ifdef NOISY + ERROR("Too many errors\n"); +#endif + ACTION1("Abandoning geometry file \"%s\"\n", file->topName); + break; + } + } + return; +} + +/***====================================================================***/ + +static Bool +CopyShapeDef(Display * dpy, XkbGeometryPtr geom, ShapeInfo * si) +{ + register int i, n; + XkbShapePtr shape; + XkbOutlinePtr old_outline, outline; + Atom name; + + si->index = geom->num_shapes; + name = XkbInternAtom(dpy, XkbAtomGetString(NULL, si->name), False); + shape = XkbAddGeomShape(geom, name, si->nOutlines); + if (!shape) + { + WSGO("Couldn't allocate shape in geometry\n"); + ACTION1("Shape %s not compiled\n", shText(dpy, si)); + return False; + } + old_outline = si->outlines; + for (i = 0; i < si->nOutlines; i++, old_outline++) + { + outline = XkbAddGeomOutline(shape, old_outline->num_points); + if (!outline) + { + WSGO("Couldn't allocate outline in shape\n"); + ACTION1("Shape %s is incomplete\n", shText(dpy, si)); + return False; + } + n = old_outline->num_points; + memcpy(outline->points, old_outline->points, n * sizeof(XkbPointRec)); + outline->num_points = old_outline->num_points; + outline->corner_radius = old_outline->corner_radius; + } + if (si->approx) + { + n = (si->approx - si->outlines); + shape->approx = &shape->outlines[n]; + } + if (si->primary) + { + n = (si->primary - si->outlines); + shape->primary = &shape->outlines[n]; + } + XkbComputeShapeBounds(shape); + return True; +} + +static Bool +VerifyDoodadInfo(DoodadInfo * di, GeometryInfo * info) +{ + if ((di->defs.defined & (_GD_Top | _GD_Left)) != (_GD_Top | _GD_Left)) + { + if (warningLevel < 9) + { + ERROR1("No position defined for doodad %s\n", + ddText(info->dpy, di)); + ACTION("Illegal doodad ignored\n"); + return False; + } + } + if ((di->defs.defined & _GD_Priority) == 0) + { + /* calculate priority -- should be just above previous doodad/row */ + } + switch (di->type) + { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if ((di->defs.defined & _GD_Shape) == 0) + { + ERROR2("No shape defined for %s doodad %s\n", + (di->type == XkbOutlineDoodad ? "outline" : "filled"), + ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + else + { + ShapeInfo *si; + si = FindShape(info, di->shape, + (di->type == + XkbOutlineDoodad ? "outline doodad" : + "solid doodad"), ddText(info->dpy, di)); + if (si) + di->shape = si->name; + else + { + ERROR1("No legal shape for %s\n", ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + } + if ((di->defs.defined & _GD_Color) == 0) + { + if (warningLevel > 5) + { + WARN1("No color for doodad %s\n", ddText(info->dpy, di)); + ACTION("Using black\n"); + } + di->color = XkbInternAtom(NULL, "black", False); + } + break; + case XkbTextDoodad: + if ((di->defs.defined & _GD_Text) == 0) + { + ERROR1("No text specified for text doodad %s\n", + ddText(info->dpy, di)); + ACTION("Illegal doodad definition ignored\n"); + return False; + } + if ((di->defs.defined & _GD_Angle) == 0) + di->angle = 0; + if ((di->defs.defined & _GD_Color) == 0) + { + if (warningLevel > 5) + { + WARN1("No color specified for doodad %s\n", + ddText(info->dpy, di)); + ACTION("Using black\n"); + } + di->color = XkbInternAtom(NULL, "black", False); + } + if ((di->defs.defined & _GD_FontSpec) != 0) + { + if ((di->defs.defined & _GD_FontParts) == 0) + return True; + if (warningLevel < 9) + { + WARN1 + ("Text doodad %s has full and partial font definition\n", + ddText(info->dpy, di)); + ACTION("Full specification ignored\n"); + } + di->defs.defined &= ~_GD_FontSpec; + di->fontSpec = None; + } + if ((di->defs.defined & _GD_Font) == 0) + { + if (warningLevel > 5) + { + WARN1("No font specified for doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_FONT); + } + di->font = XkbInternAtom(NULL, DFLT_FONT, False); + } + if ((di->defs.defined & _GD_FontSlant) == 0) + { + if (warningLevel > 7) + { + WARN1("No font slant for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_SLANT); + } + di->fontSlant = XkbInternAtom(NULL, DFLT_SLANT, False); + } + if ((di->defs.defined & _GD_FontWeight) == 0) + { + if (warningLevel > 7) + { + WARN1("No font weight for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_WEIGHT); + } + di->fontWeight = XkbInternAtom(NULL, DFLT_WEIGHT, False); + } + if ((di->defs.defined & _GD_FontSetWidth) == 0) + { + if (warningLevel > 9) + { + WARN1("No font set width for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_SET_WIDTH); + } + di->fontSetWidth = XkbInternAtom(NULL, DFLT_SET_WIDTH, False); + } + if ((di->defs.defined & _GD_FontVariant) == 0) + { + if (warningLevel > 9) + { + WARN1("No font variant for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_VARIANT); + } + di->fontVariant = XkbInternAtom(NULL, DFLT_VARIANT, False); + } + if ((di->defs.defined & _GD_FontEncoding) == 0) + { + if (warningLevel > 7) + { + WARN1("No font encoding for doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using \"%s\"\n", DFLT_ENCODING); + } + di->fontEncoding = XkbInternAtom(NULL, DFLT_ENCODING, False); + } + if ((di->defs.defined & _GD_FontSize) == 0) + { + if (warningLevel > 7) + { + WARN1("No font size for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using %s point text\n", + XkbGeomFPText(DFLT_SIZE, XkbMessage)); + } + di->fontSize = DFLT_SIZE; + } + if ((di->defs.defined & _GD_Height) == 0) + { + unsigned size, nLines; + char *tmp; + size = (di->fontSize * 120) / 100; + size = (size * 254) / 720; /* convert to mm/10 */ + for (nLines = 1, tmp = XkbAtomGetString(NULL, di->text); *tmp; + tmp++) + { + if (*tmp == '\n') + nLines++; + } + size *= nLines; + if (warningLevel > 5) + { + WARN1("No height for text doodad %s\n", + ddText(info->dpy, di)); + ACTION1("Using calculated height %s millimeters\n", + XkbGeomFPText(size, XkbMessage)); + } + di->height = size; + } + if ((di->defs.defined & _GD_Width) == 0) + { + unsigned width, tmp; + char *str; + width = tmp = 0; + for (str = XkbAtomGetString(NULL, di->text); *str; str++) + { + if (*str != '\n') + tmp++; + else + { + if (tmp > width) + width = tmp; + tmp = 1; + } + } + if (width == 0) + width = tmp; + width *= (di->height * 2) / 3; + if (warningLevel > 5) + { + WARN1("No width for text doodad %s\n", ddText(info->dpy, di)); + ACTION1("Using calculated width %s millimeters\n", + XkbGeomFPText(width, XkbMessage)); + } + di->width = width; + } + break; + case XkbIndicatorDoodad: + if ((di->defs.defined & _GD_Shape) == 0) + { + ERROR1("No shape defined for indicator doodad %s\n", + ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + else + { + ShapeInfo *si; + si = FindShape(info, di->shape, "indicator doodad", + ddText(info->dpy, di)); + if (si) + di->shape = si->name; + else + { + ERROR1("No legal shape for doodad %s\n", + ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + } + if ((di->defs.defined & _GD_Color) == 0) + { + if (warningLevel > 5) + { + WARN1("No \"on\" color for indicator doodad %s\n", + ddText(info->dpy, di)); + ACTION("Using green\n"); + } + di->color = XkbInternAtom(NULL, "green", False); + } + if ((di->defs.defined & _GD_OffColor) == 0) + { + if (warningLevel > 5) + { + WARN1("No \"off\" color for indicator doodad %s\n", + ddText(info->dpy, di)); + ACTION("Using black\n"); + } + di->offColor = XkbInternAtom(NULL, "black", False); + } + break; + case XkbLogoDoodad: + if (di->logoName == NULL) + { + ERROR1("No logo name defined for logo doodad %s\n", + ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + if ((di->defs.defined & _GD_Shape) == 0) + { + ERROR1("No shape defined for logo doodad %s\n", + ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + else + { + ShapeInfo *si; + si = FindShape(info, di->shape, "logo doodad", + ddText(info->dpy, di)); + if (si) + di->shape = si->name; + else + { + ERROR1("No legal shape for %s\n", ddText(info->dpy, di)); + ACTION("Incomplete definition ignored\n"); + return False; + } + } + if ((di->defs.defined & _GD_Color) == 0) + { + if (warningLevel > 5) + { + WARN1("No color for doodad %s\n", ddText(info->dpy, di)); + ACTION("Using black\n"); + } + di->color = XkbInternAtom(NULL, "black", False); + } + break; + default: + WSGO1("Uknown doodad type %d in VerifyDoodad\n", + (unsigned int) di->type); + return False; + } + return True; +} + +#define FONT_TEMPLATE "-*-%s-%s-%s-%s-%s-*-%d-*-*-*-*-%s" + +static char * +FontFromParts(Atom fontTok, + Atom weightTok, + Atom slantTok, + Atom setWidthTok, Atom varTok, int size, Atom encodingTok) +{ + int totalSize; + char *font, *weight, *slant, *setWidth, *variant, *encoding; + char *rtrn; + + font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT); + weight = + (weightTok != None ? XkbAtomGetString(NULL, weightTok) : DFLT_WEIGHT); + slant = + (slantTok != None ? XkbAtomGetString(NULL, slantTok) : DFLT_SLANT); + setWidth = + (setWidthTok != + None ? XkbAtomGetString(NULL, setWidthTok) : DFLT_SET_WIDTH); + variant = + (varTok != None ? XkbAtomGetString(NULL, varTok) : DFLT_VARIANT); + encoding = + (encodingTok != + None ? XkbAtomGetString(NULL, encodingTok) : DFLT_ENCODING); + if (size == 0) + size = DFLT_SIZE; + totalSize = + strlen(FONT_TEMPLATE) + strlen(font) + strlen(weight) + strlen(slant); + totalSize += strlen(setWidth) + strlen(variant) + strlen(encoding); + rtrn = uCalloc(totalSize, 1); + if (rtrn) + { + sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant, + size, encoding); + } + return rtrn; +} + +static Bool +CopyDoodadDef(XkbGeometryPtr geom, + XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info) +{ + Atom name; + XkbDoodadPtr doodad; + XkbColorPtr color; + XkbShapePtr shape; + ShapeInfo *si; + + if (!VerifyDoodadInfo(di, info)) + return False; + name = XkbInternAtom(NULL, XkbAtomGetString(NULL, di->name), False); + doodad = XkbAddGeomDoodad(geom, section, name); + if (!doodad) + { + WSGO1("Couldn't allocate doodad in %s\n", + (section ? "section" : "geometry")); + ACTION1("Cannot copy doodad %s\n", ddText(info->dpy, di)); + return False; + } + doodad->any.type = di->type; + doodad->any.priority = di->priority; + doodad->any.top = di->top; + doodad->any.left = di->left; + switch (di->type) + { + case XkbOutlineDoodad: + case XkbSolidDoodad: + si = FindShape(info, di->shape, NULL, NULL); + if (!si) + return False; + doodad->shape.angle = di->angle; + color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), + geom->num_colors); + shape = &geom->shapes[si->index]; + XkbSetShapeDoodadColor(geom, &doodad->shape, color); + XkbSetShapeDoodadShape(geom, &doodad->shape, shape); + break; + case XkbTextDoodad: + doodad->text.angle = di->angle; + doodad->text.width = di->width; + doodad->text.height = di->height; + if (di->fontSpec == None) + doodad->text.font = FontFromParts(di->font, di->fontWeight, + di->fontSlant, + di->fontSetWidth, + di->fontVariant, di->fontSize, + di->fontEncoding); + else + doodad->text.font = XkbAtomGetString(NULL, di->fontSpec); + doodad->text.text = XkbAtomGetString(NULL, di->text); + color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), + geom->num_colors); + XkbSetTextDoodadColor(geom, &doodad->text, color); + break; + case XkbIndicatorDoodad: + si = FindShape(info, di->shape, NULL, NULL); + if (!si) + return False; + shape = &geom->shapes[si->index]; + color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), + geom->num_colors); + XkbSetIndicatorDoodadShape(geom, &doodad->indicator, shape); + XkbSetIndicatorDoodadOnColor(geom, &doodad->indicator, color); + color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->offColor), + geom->num_colors); + XkbSetIndicatorDoodadOffColor(geom, &doodad->indicator, color); + break; + case XkbLogoDoodad: + si = FindShape(info, di->shape, NULL, NULL); + if (!si) + return False; + doodad->logo.angle = di->angle; + color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, di->color), + geom->num_colors); + shape = &geom->shapes[si->index]; + XkbSetLogoDoodadColor(geom, &doodad->logo, color); + XkbSetLogoDoodadShape(geom, &doodad->logo, shape); + doodad->logo.logo_name = di->logoName; + di->logoName = NULL; + break; + } + return True; +} + +/***====================================================================***/ + +static Bool +VerifyOverlayInfo(XkbGeometryPtr geom, + XkbSectionPtr section, + OverlayInfo * oi, + GeometryInfo * info, short rowMap[256], short rowSize[256]) +{ + register OverlayKeyInfo *ki, *next; + unsigned long oKey, uKey, sKey; + XkbRowPtr row; + XkbKeyPtr key; + int r, k; + + /* find out which row each key is in */ + for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) + { + oKey = KeyNameToLong(ki->over); + uKey = KeyNameToLong(ki->under); + for (r = 0, row = section->rows; (r < section->num_rows) && oKey; + r++, row++) + { + for (k = 0, key = row->keys; (k < row->num_keys) && oKey; + k++, key++) + { + sKey = KeyNameToLong(key->name.name); + if (sKey == oKey) + { + if (warningLevel > 0) + { + WARN3 + ("Key %s in section \"%s\" and overlay \"%s\"\n", + XkbKeyNameText(key->name.name, + XkbMessage), + XkbAtomText(info->dpy, section->name, + XkbMessage), + XkbAtomText(info->dpy, oi->name, XkbMessage)); + ACTION("Overlay definition ignored\n"); + } + oKey = 0; + } + else if (sKey == uKey) + { + ki->sectionRow = r; + oKey = 0; + } + } + } + if ((ki->sectionRow == _GOK_UnknownRow) && (warningLevel > 0)) + { + WARN3 + ("Key %s not in \"%s\", but has an overlay key in \"%s\"\n", + XkbKeyNameText(ki->under, XkbMessage), + XkbAtomText(info->dpy, section->name, XkbMessage), + XkbAtomText(info->dpy, oi->name, XkbMessage)); + ACTION("Definition ignored\n"); + } + } + /* now prune out keys that aren't in the section */ + while ((oi->keys != NULL) && (oi->keys->sectionRow == _GOK_UnknownRow)) + { + next = (OverlayKeyInfo *) oi->keys->defs.next; + uFree(oi->keys); + oi->keys = next; + oi->nKeys--; + } + for (ki = oi->keys; (ki != NULL) && (ki->defs.next != NULL); ki = next) + { + next = (OverlayKeyInfo *) ki->defs.next; + if (next->sectionRow == _GOK_UnknownRow) + { + ki->defs.next = next->defs.next; + oi->nKeys--; + uFree(next); + next = (OverlayKeyInfo *) ki->defs.next; + } + } + if (oi->nKeys < 1) + { + ERROR2("Overlay \"%s\" for section \"%s\" has no legal keys\n", + XkbAtomText(info->dpy, oi->name, XkbMessage), + XkbAtomText(info->dpy, section->name, XkbMessage)); + ACTION("Overlay definition ignored\n"); + return False; + } + /* now figure out how many rows are defined for the overlay */ + bzero(rowSize, sizeof(short) * 256); + for (k = 0; k < 256; k++) + { + rowMap[k] = -1; + } + oi->nRows = 0; + for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) + { + if (rowMap[ki->sectionRow] == -1) + rowMap[ki->sectionRow] = oi->nRows++; + ki->overlayRow = rowMap[ki->sectionRow]; + rowSize[ki->overlayRow]++; + } + return True; +} + +static Bool +CopyOverlayDef(XkbGeometryPtr geom, + XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info) +{ + Atom name; + XkbOverlayPtr ol; + XkbOverlayRowPtr row; + XkbOverlayKeyPtr key; + OverlayKeyInfo *ki; + short rowMap[256], rowSize[256]; + int i; + + if (!VerifyOverlayInfo(geom, section, oi, info, rowMap, rowSize)) + return False; + name = XkbInternAtom(NULL, XkbAtomGetString(NULL, oi->name), False); + ol = XkbAddGeomOverlay(section, name, oi->nRows); + if (!ol) + { + WSGO2("Couldn't add overlay \"%s\" to section \"%s\"\n", + XkbAtomText(info->dpy, name, XkbMessage), + XkbAtomText(info->dpy, section->name, XkbMessage)); + return False; + } + for (i = 0; i < oi->nRows; i++) + { + int tmp, row_under; + for (tmp = 0, row_under = -1; + (tmp < section->num_rows) && (row_under < 0); tmp++) + { + if (rowMap[tmp] == i) + row_under = tmp; + } + if (!XkbAddGeomOverlayRow(ol, row_under, rowSize[i])) + { + WSGO3 + ("Can't add row %d to overlay \"%s\" of section \"%s\"\n", + i, XkbAtomText(info->dpy, name, XkbMessage), + XkbAtomText(info->dpy, section->name, XkbMessage)); + return False; + } + } + for (ki = oi->keys; ki != NULL; ki = (OverlayKeyInfo *) ki->defs.next) + { + row = &ol->rows[ki->overlayRow]; + key = &row->keys[row->num_keys++]; + bzero(key, sizeof(XkbOverlayKeyRec)); + strncpy(key->over.name, ki->over, XkbKeyNameLength); + strncpy(key->under.name, ki->under, XkbKeyNameLength); + } + return True; +} + +/***====================================================================***/ + +static Bool +CopySectionDef(XkbGeometryPtr geom, SectionInfo * si, GeometryInfo * info) +{ + XkbSectionPtr section; + XkbRowPtr row; + XkbKeyPtr key; + KeyInfo *ki; + RowInfo *ri; + Atom name; + + name = XkbInternAtom(NULL, XkbAtomGetString(NULL, si->name), False); + section = + XkbAddGeomSection(geom, name, si->nRows, si->nDoodads, si->nOverlays); + if (section == NULL) + { + WSGO("Couldn't allocate section in geometry\n"); + ACTION1("Section %s not compiled\n", scText(info->dpy, si)); + return False; + } + section->top = si->top; + section->left = si->left; + section->width = si->width; + section->height = si->height; + section->angle = si->angle; + section->priority = si->priority; + for (ri = si->rows; ri != NULL; ri = (RowInfo *) ri->defs.next) + { + row = XkbAddGeomRow(section, ri->nKeys); + if (row == NULL) + { + WSGO("Couldn't allocate row in section\n"); + ACTION1("Section %s is incomplete\n", scText(info->dpy, si)); + return False; + } + row->top = ri->top; + row->left = ri->left; + row->vertical = ri->vertical; + for (ki = ri->keys; ki != NULL; ki = (KeyInfo *) ki->defs.next) + { + XkbColorPtr color; + if ((ki->defs.defined & _GK_Name) == 0) + { + ERROR3("Key %d of row %d in section %s has no name\n", + (int) ki->index, (int) ri->index, + scText(info->dpy, si)); + ACTION1("Section %s ignored\n", scText(info->dpy, si)); + return False; + } + key = XkbAddGeomKey(row); + if (key == NULL) + { + WSGO("Couldn't allocate key in row\n"); + ACTION1("Section %s is incomplete\n", scText(info->dpy, si)); + return False; + } + memcpy(key->name.name, ki->name, XkbKeyNameLength); + key->gap = ki->gap; + if (ki->shape == None) + key->shape_ndx = 0; + else + { + ShapeInfo *si; + si = FindShape(info, ki->shape, "key", keyText(ki)); + if (!si) + return False; + key->shape_ndx = si->index; + } + if (ki->color != None) + color = + XkbAddGeomColor(geom, + XkbAtomGetString(NULL, ki->color), + geom->num_colors); + else + color = XkbAddGeomColor(geom, "white", geom->num_colors); + XkbSetKeyColor(geom, key, color); + } + } + if (si->doodads != NULL) + { + DoodadInfo *di; + for (di = si->doodads; di != NULL; di = (DoodadInfo *) di->defs.next) + { + CopyDoodadDef(geom, section, di, info); + } + } + if (si->overlays != NULL) + { + OverlayInfo *oi; + for (oi = si->overlays; oi != NULL; + oi = (OverlayInfo *) oi->defs.next) + { + CopyOverlayDef(geom, section, oi, info); + } + } + if (XkbComputeSectionBounds(geom, section)) + { + /* 7/6/94 (ef) -- check for negative origin and translate */ + if ((si->defs.defined & _GS_Width) == 0) + section->width = section->bounds.x2; + if ((si->defs.defined & _GS_Height) == 0) + section->height = section->bounds.y2; + } + return True; +} + +/***====================================================================***/ + +Bool +CompileGeometry(XkbFile * file, XkbFileInfo * result, unsigned merge) +{ + GeometryInfo info; + XkbDescPtr xkb; + + xkb = result->xkb; + InitGeometryInfo(&info, file->id, merge); + info.dpy = xkb->dpy; + HandleGeometryFile(file, xkb, merge, &info); + + if (info.errorCount == 0) + { + XkbGeometryPtr geom; + XkbGeometrySizesRec sizes; + bzero(&sizes, sizeof(sizes)); + sizes.which = XkbGeomAllMask; + sizes.num_properties = info.nProps; + sizes.num_colors = 8; + sizes.num_shapes = info.nShapes; + sizes.num_sections = info.nSections; + sizes.num_doodads = info.nDoodads; + if (XkbAllocGeometry(xkb, &sizes) != Success) + { + WSGO("Couldn't allocate GeometryRec\n"); + ACTION("Geometry not compiled\n"); + return False; + } + geom = xkb->geom; + + geom->width_mm = info.widthMM; + geom->height_mm = info.heightMM; + if (info.name != NULL) + { + geom->name = XkbInternAtom(xkb->dpy, info.name, False); + if (XkbAllocNames(xkb, XkbGeometryNameMask, 0, 0) == Success) + xkb->names->geometry = geom->name; + } + if (info.fontSpec != None) + geom->label_font = + uStringDup(XkbAtomGetString(NULL, info.fontSpec)); + else + geom->label_font = FontFromParts(info.font, info.fontWeight, + info.fontSlant, + info.fontSetWidth, + info.fontVariant, + info.fontSize, + info.fontEncoding); + XkbAddGeomColor(geom, "black", geom->num_colors); + XkbAddGeomColor(geom, "white", geom->num_colors); + + if (info.baseColor == None) + info.baseColor = XkbInternAtom(NULL, "white", False); + if (info.labelColor == None) + info.labelColor = XkbInternAtom(NULL, "black", False); + geom->base_color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.baseColor), + geom->num_colors); + geom->label_color = + XkbAddGeomColor(geom, XkbAtomGetString(NULL, info.labelColor), + geom->num_colors); + + if (info.props) + { + PropertyInfo *pi; + for (pi = info.props; pi != NULL; + pi = (PropertyInfo *) pi->defs.next) + { + if (!XkbAddGeomProperty(geom, pi->name, pi->value)) + return False; + } + } + if (info.shapes) + { + ShapeInfo *si; + for (si = info.shapes; si != NULL; + si = (ShapeInfo *) si->defs.next) + { + if (!CopyShapeDef(xkb->dpy, geom, si)) + return False; + } + } + if (info.sections) + { + SectionInfo *si; + for (si = info.sections; si != NULL; + si = (SectionInfo *) si->defs.next) + { + if (!CopySectionDef(geom, si, &info)) + return False; + } + } + if (info.doodads) + { + DoodadInfo *di; + for (di = info.doodads; di != NULL; + di = (DoodadInfo *) di->defs.next) + { + if (!CopyDoodadDef(geom, NULL, di, &info)) + return False; + } + } + if (info.aliases) + ApplyAliases(xkb, True, &info.aliases); + ClearGeometryInfo(&info); + return True; + } + return False; +} |