diff options
Diffstat (limited to 'xkbcomp')
-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 6eb3fb880..b5c468bfc 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 oiText(d,o) ((o)?XkbAtomText((d),(o)->name,XkbMessage):"default") - - -#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", - oiText(info->dpy, &ol), 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;
+}
|