/* $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. ********************************************************/ #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 * #if NeedFunctionPrototypes ddText(Display *dpy,DoodadInfo *di) #else ddText(dpy,di) Display * dpy; DoodadInfo * di; #endif { 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 #if NeedFunctionPrototypes InitPropertyInfo(PropertyInfo *pi,GeometryInfo *info) #else InitPropertyInfo(pi,info) PropertyInfo * pi; GeometryInfo * info; #endif { pi->defs.defined= 0; pi->defs.fileID= info->fileID; pi->defs.merge= info->merge; pi->name= pi->value= NULL; return; } static void #if NeedFunctionPrototypes FreeProperties(PropertyInfo *pi,GeometryInfo *info) #else FreeProperties(pi,info) PropertyInfo * pi; GeometryInfo * info; #endif { PropertyInfo * tmp; PropertyInfo * next; if (info->props==pi) { info->props= NULL; info->nProps= 0; } for (tmp=pi;tmp!=NULL;tmp=next) { if (pi->name) uFree(pi->name); if (pi->value) uFree(pi->value); pi->name= pi->value=NULL; next= (PropertyInfo *)tmp->defs.next; uFree(tmp); } return; } static void #if NeedFunctionPrototypes InitKeyInfo(KeyInfo *key,RowInfo *row,GeometryInfo *info) #else InitKeyInfo(key,row,info) KeyInfo * key; RowInfo * row; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes ClearKeyInfo(KeyInfo *key) #else ClearKeyInfo(key) KeyInfo * key; #endif { key->defs.defined&= ~_GK_Default; strcpy(key->name,"default"); key->gap= 0; key->shape= None; key->color= None; return; } static void #if NeedFunctionPrototypes FreeKeys(KeyInfo *key,RowInfo *row,GeometryInfo *info) #else FreeKeys(key,row,info) KeyInfo * key; RowInfo * row; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes InitRowInfo(RowInfo *row,SectionInfo *section,GeometryInfo *info) #else InitRowInfo(row,section,info) RowInfo * row; SectionInfo * section; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes ClearRowInfo(RowInfo *row,GeometryInfo *info) #else ClearRowInfo(row,info) RowInfo * row; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes FreeRows(RowInfo *row,SectionInfo *section,GeometryInfo *info) #else FreeRows(row,section,info) RowInfo * row; SectionInfo * section; GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes FindDoodadByType(DoodadInfo *di,unsigned type) #else FindDoodadByType(di,type) DoodadInfo * di; unsigned type; #endif { while (di) { if (di->type==type) return di; di= (DoodadInfo *)di->defs.next; } return NULL; } static DoodadInfo * #if NeedFunctionPrototypes FindDoodadByName(DoodadInfo *di,Atom name) #else FindDoodadByName(di,name) DoodadInfo * di; Atom name; #endif { while (di) { if (di->name==name) return di; di= (DoodadInfo *)di->defs.next; } return NULL; } static void #if NeedFunctionPrototypes InitDoodadInfo(DoodadInfo *di,unsigned type,SectionInfo *si,GeometryInfo *info) #else InitDoodadInfo(di,type,si,info) DoodadInfo * di; unsigned type; SectionInfo * si; GeometryInfo * info; #endif { 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 (si->nextDoodadPriority>XkbGeomMaxPriority) si->nextDoodadPriority= XkbGeomMaxPriority; } else { di->priority= info->nextPriority++; if (info->nextPriority>XkbGeomMaxPriority) info->nextPriority= XkbGeomMaxPriority; } return; } static void #if NeedFunctionPrototypes ClearDoodadInfo(DoodadInfo *di) #else ClearDoodadInfo(di) DoodadInfo * di; #endif { CommonInfo defs; defs= di->defs; bzero(di,sizeof(DoodadInfo)); di->defs= defs; di->defs.defined= 0; return; } static void #if NeedFunctionPrototypes ClearOverlayInfo(OverlayInfo *ol) #else ClearOverlayInfo(ol) OverlayInfo * ol; #endif { if (ol && ol->keys) { ol->keys= (OverlayKeyInfo *)ClearCommonInfo(&ol->keys->defs); ol->nKeys= 0; } return; } static void #if NeedFunctionPrototypes FreeDoodads(DoodadInfo *di,SectionInfo *si,GeometryInfo *info) #else FreeDoodads(di,si,info) DoodadInfo * di; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes InitSectionInfo(SectionInfo *si,GeometryInfo *info) #else InitSectionInfo(si,info) SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes DupSectionInfo(SectionInfo *into,SectionInfo *from,GeometryInfo *info) #else DupSectionInfo(into,from,info) SectionInfo * into; SectionInfo * from; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes ClearSectionInfo(SectionInfo *si,GeometryInfo *info) #else ClearSectionInfo(si,info) SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes FreeSections(SectionInfo *si,GeometryInfo *info) #else FreeSections(si,info) SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes FreeShapes(ShapeInfo *si,GeometryInfo *info) #else FreeShapes(si,info) ShapeInfo * si; GeometryInfo * info; #endif { 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;inOutlines;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 #if NeedFunctionPrototypes InitGeometryInfo(GeometryInfo *info,unsigned fileID,unsigned merge) #else InitGeometryInfo(info,fileID,merge) GeometryInfo * info; unsigned fileID; unsigned merge; #endif { bzero(info,sizeof(GeometryInfo)); info->fileID= fileID; info->merge= merge; InitSectionInfo(&info->dfltSection,info); info->dfltSection.defs.defined= _GS_Default; return; } static void #if NeedFunctionPrototypes ClearGeometryInfo(GeometryInfo *info) #else ClearGeometryInfo(info) GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes NextProperty(GeometryInfo *info) #else NextProperty(info) GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes FindProperty(GeometryInfo *info,char *name) #else FindProperty(info,name) GeometryInfo * info; char * name; #endif { 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 #if NeedFunctionPrototypes AddProperty(GeometryInfo *info,PropertyInfo *new) #else AddProperty(info,new) GeometryInfo * info; PropertyInfo * new; #endif { 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 * #if NeedFunctionPrototypes NextShape(GeometryInfo *info) #else NextShape(info) GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes FindShape(GeometryInfo *info,Atom name,char *type,char *which) #else FindShape(info,name,type,which) GeometryInfo * info; Atom name; char * type; char * which; #endif { 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 #if NeedFunctionPrototypes AddShape(GeometryInfo *info,ShapeInfo *new) #else AddShape(info,new) GeometryInfo * info; ShapeInfo * new; #endif { 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 #if NeedFunctionPrototypes ReplaceDoodad(DoodadInfo *into,DoodadInfo *from) #else ReplaceDoodad(into,from) DoodadInfo * into; DoodadInfo * from; #endif { 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 * #if NeedFunctionPrototypes NextDfltDoodad(SectionInfo *si,GeometryInfo *info) #else NextDfltDoodad(si,info) SectionInfo * si; GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes NextDoodad(SectionInfo *si,GeometryInfo *info) #else NextDoodad(si,info) SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes AddDoodad(SectionInfo *si,GeometryInfo *info,DoodadInfo *new) #else AddDoodad(si,info,new) SectionInfo * si; GeometryInfo * info; DoodadInfo * new; #endif { 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 * #if NeedFunctionPrototypes FindDfltDoodadByTypeName(char *name,SectionInfo *si,GeometryInfo *info) #else FindDfltDoodadByTypeName(name,si,info) char * name; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes AddOverlay(SectionInfo *si,GeometryInfo *info,OverlayInfo *new) #else AddOverlay(si,info,new) SectionInfo *si; GeometryInfo *info; OverlayInfo *new; #endif { 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 * #if NeedFunctionPrototypes NextSection(GeometryInfo *info) #else NextSection(info) GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes FindMatchingSection(GeometryInfo *info,SectionInfo *new) #else FindMatchingSection(info,new) GeometryInfo * info; SectionInfo * new; #endif { SectionInfo * old; for (old=info->sections;old!=NULL;old=(SectionInfo *)old->defs.next) { if (new->name==old->name) return old; } return NULL; } static Bool #if NeedFunctionPrototypes AddSection(GeometryInfo *info,SectionInfo *new) #else AddSection(info,new) GeometryInfo * info; SectionInfo * new; #endif { 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 * #if NeedFunctionPrototypes NextRow(SectionInfo *si) #else NextRow(si) SectionInfo * si; #endif { 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 #if NeedFunctionPrototypes AddRow(SectionInfo *si,RowInfo *new) #else AddRow(si,new) SectionInfo * si; RowInfo * new; #endif { 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 * #if NeedFunctionPrototypes NextKey(RowInfo *row) #else NextKey(row) RowInfo * row; #endif { 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 #if NeedFunctionPrototypes AddKey(RowInfo *row,KeyInfo *new) #else AddKey(row,new) RowInfo * row; KeyInfo * new; #endif { 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 #if NeedFunctionPrototypes MergeIncludedGeometry(GeometryInfo *into,GeometryInfo *from,unsigned merge) #else MergeIncludedGeometry(into,from,merge) GeometryInfo * into; GeometryInfo * from; unsigned merge; #endif { 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)( #if NeedFunctionPrototypes XkbFile * /* file */, XkbDescPtr /* xkb */, unsigned /* merge */, GeometryInfo * /* info */ #endif ); static Bool #if NeedFunctionPrototypes HandleIncludeGeometry(IncludeStmt *stmt,XkbDescPtr xkb,GeometryInfo *info, FileHandler hndlr) #else HandleIncludeGeometry(stmt,xkb,info,hndlr) IncludeStmt * stmt; XkbDescPtr xkb; GeometryInfo * info; FileHandler hndlr; #endif { 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 #if NeedFunctionPrototypes SetShapeField( ShapeInfo * si, char * field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) #else SetShapeField(si,field,arrayNdx,value,info) ShapeInfo * si; char * field; ExprDef * arrayNdx; ExprDef * value; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetShapeDoodadField( DoodadInfo * di, char * field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) #else SetShapeDoodadField(di,field,arrayNdx,value,si,info) DoodadInfo * di; char * field; ExprDef * arrayNdx; ExprDef * value; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetTextDoodadField( DoodadInfo * di, char * field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) #else SetTextDoodadField(di,field,arrayNdx,value,si,info) DoodadInfo * di; char * field; ExprDef * arrayNdx; ExprDef * value; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetIndicatorDoodadField( DoodadInfo * di, char * field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) #else SetIndicatorDoodadField(di,field,arrayNdx,value,si,info) DoodadInfo * di; char * field; ExprDef * arrayNdx; ExprDef * value; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetLogoDoodadField( DoodadInfo * di, char * field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) #else SetLogoDoodadField(di,field,arrayNdx,value,si,info) DoodadInfo * di; char * field; ExprDef * arrayNdx; ExprDef * value; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetDoodadField( DoodadInfo * di, char * field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) #else SetDoodadField(di,field,arrayNdx,value,si,info) DoodadInfo * di; char * field; ExprDef * arrayNdx; ExprDef * value; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetSectionField( SectionInfo * si, char * field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) #else SetSectionField(si,field,arrayNdx,value,info) SectionInfo * si; char * field; ExprDef * arrayNdx; ExprDef * value; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetRowField( RowInfo * row, char * field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) #else SetRowField(row,field,arrayNdx,value,info) RowInfo * row; char * field; ExprDef * arrayNdx; ExprDef * value; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetKeyField( KeyInfo *key, char *field, ExprDef *arrayNdx, ExprDef *value, GeometryInfo *info) #else SetKeyField(key,field,arrayNdx,value,info) KeyInfo * key; char * field; ExprDef * arrayNdx; ExprDef * value; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes SetGeometryProperty(GeometryInfo *info,char *property,ExprDef *value) #else SetGeometryProperty(info,property,value) GeometryInfo * info; char * property; ExprDef * value; #endif { 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 #if NeedFunctionPrototypes HandleGeometryVar(VarDef *stmt,XkbDescPtr xkb,GeometryInfo *info) #else HandleGeometryVar(stmt,xkb,info) VarDef * stmt; XkbDescPtr xkb; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleShapeBody(ShapeDef *def,ShapeInfo *si,unsigned merge,GeometryInfo *info) #else HandleShapeBody(def,si,merge,info) ShapeDef * def; ShapeInfo * si; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleShapeDef(ShapeDef *def,XkbDescPtr xkb,unsigned merge,GeometryInfo *info) #else HandleShapeDef(def,xkb,merge,info) ShapeDef * def; XkbDescPtr xkb; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleDoodadDef( DoodadDef *def, unsigned merge, SectionInfo *si, GeometryInfo *info) #else HandleDoodadDef(def,merge,si,info) DoodadDef * def; unsigned merge; SectionInfo * si; GeometryInfo * info; #endif { ExprResult elem,field; ExprDef * ndx; DoodadInfo new; VarDef * var; if (def->common.stmtType==StmtIndicatorMapDef) { IndicatorMapDef *imap= (IndicatorMapDef *)def; Atom name= imap->name; VarDef * body= imap->body; def->common.stmtType= StmtDoodadDef; def->type= XkbIndicatorDoodad; def->name= name; def->body= body; } 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 #if NeedFunctionPrototypes HandleOverlayDef( OverlayDef * def, unsigned merge, SectionInfo * si, GeometryInfo * info) #else HandleOverlayDef(def,merge,si,info) OverlayDef * def; unsigned merge; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleComplexKey(KeyDef *def,KeyInfo *key,GeometryInfo *info) #else HandleComplexKey(def,key,info) KeyDef * def; KeyInfo * key; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleRowBody(RowDef *def,RowInfo *row,unsigned merge,GeometryInfo *info) #else HandleRowBody(def,row,merge,info) RowDef * def; RowInfo * row; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleSectionBody( SectionDef * def, SectionInfo * si, unsigned merge, GeometryInfo * info) #else HandleSectionBody(def,si,merge,info) SectionDef * def; SectionInfo * si; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleSectionDef( SectionDef * def, XkbDescPtr xkb, unsigned merge, GeometryInfo * info) #else HandleSectionDef(def,xkb,merge,info) SectionDef * def; XkbDescPtr xkb; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes HandleGeometryFile( XkbFile * file, XkbDescPtr xkb, unsigned merge, GeometryInfo * info) #else HandleGeometryFile(file,xkb,merge,info) XkbFile * file; XkbDescPtr xkb; unsigned merge; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes CopyShapeDef(Display *dpy,XkbGeometryPtr geom,ShapeInfo *si) #else CopyShapeDef(dpy,geom,si) Display * dpy; XkbGeometryPtr geom; ShapeInfo * si; #endif { 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;inOutlines;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 #if NeedFunctionPrototypes VerifyDoodadInfo(DoodadInfo *di,GeometryInfo *info) #else VerifyDoodadInfo(di,info) DoodadInfo * di; GeometryInfo * info; #endif { 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 * #if NeedFunctionPrototypes FontFromParts( Atom fontTok, Atom weightTok, Atom slantTok, Atom setWidthTok, Atom varTok, int size, Atom encodingTok) #else FontFromParts(fontTok,weightTok,slantTok,setWidthTok,varTok,size,encodingTok) Atom fontTok; Atom weightTok; Atom slantTok; Atom setWidthTok; Atom varTok; int size; Atom encodingTok; #endif { 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 #if NeedFunctionPrototypes CopyDoodadDef( XkbGeometryPtr geom, XkbSectionPtr section, DoodadInfo * di, GeometryInfo * info) #else CopyDoodadDef(geom,section,di,info) XkbGeometryPtr geom; XkbSectionPtr section; DoodadInfo * di; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes VerifyOverlayInfo( XkbGeometryPtr geom, XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info, short rowMap[256], short rowSize[256]) #else VerifyOverlayInfo(geom,section,oi,info,rowMap,rowSize) XkbGeometryPtr geom; XkbSectionPtr section; OverlayInfo * oi; GeometryInfo * info; short rowMap[256]; short rowSize[256]; #endif { 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;(rnum_rows)&&oKey;r++,row++) { for (k=0,key=row->keys;(knum_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 #if NeedFunctionPrototypes CopyOverlayDef( XkbGeometryPtr geom, XkbSectionPtr section, OverlayInfo * oi, GeometryInfo * info) #else CopyOverlayDef(geom,section,oi,info) XkbGeometryPtr geom; XkbSectionPtr section; OverlayInfo * oi; GeometryInfo * info; #endif { 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;inRows;i++) { int tmp,row_under; for (tmp=0,row_under=-1;(tmpnum_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 #if NeedFunctionPrototypes CopySectionDef(XkbGeometryPtr geom,SectionInfo *si,GeometryInfo *info) #else CopySectionDef(geom,si,info) XkbGeometryPtr geom; SectionInfo * si; GeometryInfo * info; #endif { 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 #if NeedFunctionPrototypes CompileGeometry(XkbFile *file,XkbFileInfo *result,unsigned merge) #else CompileGeometry(file,result,merge) XkbFile * file; XkbFileInfo * result; unsigned merge; #endif { 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; }