3278 lines
88 KiB
C
3278 lines
88 KiB
C
/* $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,char *type,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;
|
|
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,
|
|
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;
|
|
}
|