diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xkbcomp/geometry.c | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xkbcomp/geometry.c')
-rw-r--r-- | xkbcomp/geometry.c | 3277 |
1 files changed, 3277 insertions, 0 deletions
diff --git a/xkbcomp/geometry.c b/xkbcomp/geometry.c new file mode 100644 index 000000000..8e47d7e43 --- /dev/null +++ b/xkbcomp/geometry.c @@ -0,0 +1,3277 @@ +/* $Xorg: geometry.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */ +/************************************************************ + 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. + + ********************************************************/ +/* $XFree86: xc/programs/xkbcomp/geometry.c,v 1.5tsi Exp $ */ + +#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; +} |