diff options
Diffstat (limited to 'xorg-server/xkeyboard-config')
18 files changed, 1333 insertions, 0 deletions
diff --git a/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh new file mode 100644 index 000000000..ccaaba7e0 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh @@ -0,0 +1,43 @@ +#!/bin/sh
+
+#
+# This script compares the group names which "have to be", according to the descriptions in base.xml -
+# and actually existing in the symbol files. Some differences are ok (like extra double quotes or
+# extra escaping character) - but all the rest should be in sync.
+#
+
+ROOT="`dirname $0`/.."
+F1=reg2ll.lst
+F2=gn2ll.lst
+
+xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.xml | sort | uniq > $F1
+
+for i in $ROOT/symbols/*; do
+ if [ -f $i ]; then
+ id="`basename $i`"
+ export id
+ gawk 'BEGIN{
+ FS = "\"";
+ id = ENVIRON["id"];
+ isDefault = 0;
+}
+/.*default.*/{
+ isDefault = 1;
+}
+/xkb_symbols/{
+ variant = $2;
+}/^[[:space:]]*name\[Group1\][[:space:]]*=/{
+ if (isDefault == 1)
+ {
+ printf "%s:\"%s\"\n",id,$2;
+ isDefault=0;
+ } else
+ {
+ name=$2;
+ printf "%s(%s):\"%s\"\n", id, variant, name;
+ }
+}' $i
+ fi
+done | sort | uniq > $F2
+
+diff $F1 $F2
diff --git a/xorg-server/xkeyboard-config/tests/listCI2.xsl b/xorg-server/xkeyboard-config/tests/listCI2.xsl new file mode 100644 index 000000000..09ee37abb --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/listCI2.xsl @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+<xsl:output method="text"/>
+
+ <xsl:param name="type"/>
+ <xsl:param name="parentId"/>
+
+ <xsl:template match="xkbConfigRegistry">
+ <xsl:apply-templates select=".//configItem[(name(..) = $type) and (../../../configItem/name = $parentId or ../../configItem/name = $parentId )]">
+ <xsl:sort select="name"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="configItem">
+ <xsl:value-of select="./name"/><xsl:text>
+</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/xorg-server/xkeyboard-config/tests/listCIs.xsl b/xorg-server/xkeyboard-config/tests/listCIs.xsl new file mode 100644 index 000000000..87e5bd9de --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/listCIs.xsl @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+<xsl:output method="text"/>
+
+ <xsl:param name="type"/>
+
+ <xsl:template match="xkbConfigRegistry">
+ <xsl:apply-templates select=".//configItem[name(..) = $type]">
+ <xsl:sort select="name"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="configItem">
+ <xsl:value-of select="./name"/><xsl:text>
+</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/xorg-server/xkeyboard-config/tests/mxkbledpanel/Imakefile b/xorg-server/xkeyboard-config/tests/mxkbledpanel/Imakefile new file mode 100644 index 000000000..3fd46021e --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/mxkbledpanel/Imakefile @@ -0,0 +1,8 @@ +LOCAL_LIBRARIES1 = -lXm
+ SRCS1 = mxkbledpanel.c
+ OBJS1 = mxkbledpanel.o
+
+PROGRAMS=mxkbledpanel
+
+ComplexProgramTarget_1(mxkbledpanel,$(LOCAL_LIBRARIES1),)
+
diff --git a/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.c b/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.c new file mode 100644 index 000000000..5d52c52c1 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.c @@ -0,0 +1,605 @@ +#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/XKBlib.h>
+#include <Xm/MainW.h>
+#include <Xm/RowColumn.h>
+#include <Xm/ToggleB.h>
+
+Display *theDisplay;
+XtAppContext appContext;
+int xkbEventBase;
+Widget topLevel;
+Widget leds[XkbNumIndicators];
+Atom ledAtoms[XkbNumIndicators];
+XmString ledNames[XkbNumIndicators];
+XkbDescPtr xkb_desc;
+
+void valueChangedProc(Widget,XtPointer,XmToggleButtonCallbackStruct *);
+XtCallbackRec valueChangedCB[2]={(XtCallbackProc)valueChangedProc,NULL};
+
+/************************************************************************/
+/* */
+/* Application Resources */
+/* */
+/************************************************************************/
+#define YES 1
+#define NO 0
+#define DONT_CARE -1
+
+typedef struct
+{
+ int wanted;
+ int wantAutomatic;
+ int wantExplicit;
+ int wantNamed;
+ int wantReal;
+ int wantVirtual;
+ int useUnion;
+} OptionsRec;
+
+OptionsRec options;
+
+#define Offset(field) XtOffsetOf(OptionsRec,field)
+XtResource resources[] =
+{
+ {"wanted", "Wanted", XtRInt, sizeof(int),
+ Offset(wanted), XtRImmediate, (XtPointer) DONT_CARE },
+ {"wantAutomatic", "WantAutomatic", XtRInt, sizeof(int),
+ Offset(wantAutomatic), XtRImmediate, (XtPointer) DONT_CARE},
+ {"wantExplicit", "WantExplicit", XtRInt, sizeof(int),
+ Offset(wantExplicit), XtRImmediate, (XtPointer) DONT_CARE},
+ {"wantNamed", "WantNamed", XtRInt, sizeof(int),
+ Offset(wantNamed), XtRImmediate, (XtPointer) DONT_CARE},
+ {"wantReal", "WantReal", XtRInt, sizeof(int),
+ Offset(wantReal), XtRImmediate, (XtPointer) DONT_CARE},
+ {"wantVirtual", "WantVirtual", XtRInt, sizeof(int),
+ Offset(wantVirtual), XtRImmediate, (XtPointer) DONT_CARE},
+ {"useUnion", "UseUnion", XtRInt, sizeof(int),
+ Offset(useUnion), XtRImmediate, (XtPointer) YES},
+ NULL
+};
+#undef Offset
+
+String fallbackResources[] =
+{
+ "*mainWindow.width: 100",
+ "*mainWindow.height: 50",
+ NULL
+};
+
+XrmOptionDescRec optionDesc[] =
+{
+ {"-watch", "*wanted", XrmoptionSepArg, (XtPointer) "0"},
+ {"-automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "0"},
+ {"+automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "1"},
+ {"-explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "0"},
+ {"+explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "1"},
+ {"-named", "*wantNamed", XrmoptionNoArg, (XtPointer) "0"},
+ {"+named", "*wantNamed", XrmoptionNoArg, (XtPointer) "1"},
+ {"-real", "*wantReal", XrmoptionNoArg, (XtPointer) "0"},
+ {"+real", "*wantReal", XrmoptionNoArg, (XtPointer) "1"},
+ {"-virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "0"},
+ {"+virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "1"},
+ {"-intersection", "*useUnion", XrmoptionNoArg, (XtPointer) "0"},
+ {"-union", "*useUnion", XrmoptionNoArg, (XtPointer) "1"}
+};
+
+/************************************************************************/
+/* */
+/* usage */
+/* */
+/************************************************************************/
+void usage(char *program)
+{
+ printf("Usage: %s <options>\n",program);
+ printf("Legal options include the usual X toolkit options plus:\n");
+ printf(" -help Print this message\n");
+ printf(" -indpy <name> Name of display to watch\n");
+ printf(" -watch <leds> Mask of LEDs to watch\n");
+ printf(" [-+]automatic (Don't) watch automatic LEDs\n");
+ printf(" [-+]explicit (Don't) watch explicit LEDs\n");
+ printf(" [-+]named (Don't) watch named LEDs\n");
+ printf(" [-+]real (Don't) watch real LEDs\n");
+ printf(" [-+]virtual (Don't) watch virtual LEDs\n");
+ printf(" -intersection Watch only LEDs in all desired sets\n");
+ printf(" -union Watch LEDs in any desired sets\n");
+ printf("The default set of LEDs is -intersection +named +virtual\n");
+ return;
+}
+/************************************************************************/
+/* */
+/* XkbEventHandler */
+/* */
+/* DESCRIPTION: */
+/* */
+/* Handles events generated by the Xkb server extension. */
+/* */
+/************************************************************************/
+Boolean XkbEventHandler(XEvent *event)
+{
+ XkbEvent *xkbEv = (XkbEvent *) event;
+
+ if (xkbEv->any.xkb_type==XkbIndicatorStateNotify) {
+ register int i;
+ register unsigned bit;
+ for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
+ if ((xkbEv->indicators.changed&bit)&&(leds[i]))
+ {
+ if (xkbEv->indicators.state&bit)
+ XmToggleButtonSetState(leds[i],True,False);
+ else
+ XmToggleButtonSetState(leds[i],False,False);
+ }
+ }
+ else if (xkbEv->any.xkb_type==XkbIndicatorMapNotify) {
+ unsigned change= xkbEv->indicators.changed;
+
+ if (XkbGetIndicatorMap(theDisplay,change,xkb_desc)!=Success)
+ fprintf(stderr,"Couldn't get changed indicator maps\n");
+ }
+
+ return True;
+
+} /* XkbEventHandler */
+
+/************************************************************************/
+/* */
+/* InitXkb */
+/* */
+/************************************************************************/
+Boolean InitXkb(Display *theDisplay)
+{
+ int i,opcode,errorBase,major,minor;
+ XkbDescPtr xkb;
+ unsigned int bit;
+ unsigned int real,virtual,named,explicit,automatic;
+ char *name;
+
+ if (!XkbQueryExtension(theDisplay,
+ &opcode,
+ &xkbEventBase,
+ &errorBase,
+ &major,
+ &minor))
+ return False;
+
+ if (!XkbUseExtension(theDisplay,&major,&minor))
+ return False;
+
+ XkbSelectEvents(theDisplay,
+ XkbUseCoreKbd,
+ XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask,
+ XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask);
+
+ XtSetEventDispatcher(theDisplay,
+ xkbEventBase+XkbEventCode,
+ XkbEventHandler);
+
+ xkb=XkbGetMap(theDisplay,0,XkbUseCoreKbd);
+ real=virtual=named=explicit=automatic=0;
+
+ if (!xkb)
+ {
+ fprintf(stderr,"Couldn't get keymap\n");
+ return False;
+ }
+ if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
+ {
+ fprintf(stderr,"Couldn't read indicator map\n");
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return False;
+ }
+ real=virtual=named=explicit=automatic=0;
+
+ if (XkbGetNames(theDisplay,XkbIndicatorNamesMask,xkb)!=Success)
+ {
+ fprintf(stderr,"Couldn't read indicator names\n");
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return False;
+ }
+ real=virtual=named=explicit=automatic=0;
+
+ for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
+ {
+ XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+ name = NULL;
+ if (xkb->names->indicators[i]!=None)
+ {
+ named|= bit;
+ name = XGetAtomName(theDisplay,xkb->names->indicators[i]);
+ }
+ if (name != NULL)
+ {
+ ledAtoms[i] = xkb->names->indicators[i];
+ ledNames[i] = XmStringCreate(name,XmSTRING_DEFAULT_CHARSET);
+ }
+ else
+ {
+ char temp[12];
+ sprintf(temp,"led%d\0",i+1);
+ ledAtoms[i] = None;
+ ledNames[i] = XmStringCreate(temp,XmSTRING_DEFAULT_CHARSET);
+ }
+ if (xkb->indicators->phys_indicators&bit)
+ real|= bit;
+ if ((((map->which_groups!=0)&&(map->groups!=0))||
+ ((map->which_mods!=0)&&
+ ((map->mods.real_mods!=0)||(map->mods.vmods!=0)))||
+ (map->ctrls!=0))&&
+ ((map->flags&XkbIM_NoAutomatic)==0)) {
+ automatic|= bit;
+ }
+ else explicit|= bit;
+ }
+
+ virtual = ~real;
+
+ if (options.useUnion)
+ {
+ if ((options.wantReal==NO) || (options.wantReal==DONT_CARE))
+ real = 0;
+ if ((options.wantVirtual==NO) || (options.wantVirtual==DONT_CARE))
+ virtual = 0;
+ if ((options.wantNamed==NO) || (options.wantNamed==DONT_CARE))
+ named = 0;
+ if ((options.wantAutomatic==NO) || (options.wantAutomatic==DONT_CARE))
+ automatic = 0;
+ if ((options.wantExplicit==NO) || (options.wantExplicit==DONT_CARE))
+ explicit = 0;
+
+ options.wanted |= real|virtual|named|automatic|explicit;
+ }
+ else
+ {
+ if (options.wanted == DONT_CARE)
+ options.wanted = ~0;
+
+ if (options.wantReal==NO)
+ real = ~real;
+ else if (options.wantReal==DONT_CARE)
+ real = ~0;
+
+ if (options.wantVirtual==NO)
+ virtual = ~virtual;
+ else if (options.wantVirtual==DONT_CARE)
+ virtual = ~0;
+
+ if (options.wantNamed==NO)
+ named = ~named;
+ else if (options.wantNamed==DONT_CARE)
+ named = ~0;
+
+ if (options.wantAutomatic==NO)
+ automatic = ~automatic;
+ else if (options.wantAutomatic==DONT_CARE)
+ automatic = ~0;
+
+ if (options.wantExplicit==NO)
+ explicit = ~explicit;
+ else if (options.wantExplicit==DONT_CARE)
+ explicit = ~0;
+
+ options.wanted &= real&virtual&named&automatic&explicit;
+ }
+
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return True;
+
+} /* InitXkb */
+
+/************************************************************************/
+/* */
+/* valueChangedProc - called when a toggle button is pressed. */
+/* */
+/************************************************************************/
+void valueChangedProc(Widget w,
+ XtPointer clientData,
+ XmToggleButtonCallbackStruct *callbackData)
+{
+ int led = (int) clientData;
+ XkbDescPtr xkb;
+
+ xkb = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
+ if (!xkb)
+ {
+ fprintf(stderr,"XkbGetMap failed\n");
+ return;
+ }
+
+ if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
+ {
+ fprintf(stderr,"GetIndicatorMap failed\n");
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return;
+ }
+
+ /* The 'flags' field tells whether this indicator is automatic
+ * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40),
+ * or neither (both - 0xC0).
+ *
+ * If NoAutomatic is set, the server ignores the rest of the
+ * fields in the indicator map (i.e. it disables automatic control
+ * of the LED). If NoExplicit is set, the server prevents clients
+ * from explicitly changing the value of the LED (using the core
+ * protocol *or* XKB). If NoAutomatic *and* NoExplicit are set,
+ * the LED cannot be changed (unless you change the map first).
+ * If neither NoAutomatic nor NoExplicit are set, the server will
+ * change the LED according to the indicator map, but clients can
+ * override that (until the next automatic change) using the core
+ * protocol or XKB.
+ */
+ switch (xkb->indicators->maps[led].flags &
+ (XkbIM_NoExplicit|XkbIM_NoAutomatic))
+ {
+ case XkbIM_NoExplicit|XkbIM_NoAutomatic:
+ {
+ XmToggleButtonSetState(w,!callbackData->set,FALSE);
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return;
+ }
+
+ case XkbIM_NoAutomatic:
+ {
+ if (ledAtoms[led] != None)
+ XkbSetNamedIndicator(theDisplay,XkbUseCoreKbd,
+ ledAtoms[led],callbackData->set,
+ FALSE,NULL);
+ else
+ {
+ XKeyboardControl xkc;
+ xkc.led= led;
+ if (callbackData->set)
+ xkc.led_mode= LedModeOn;
+ else xkc.led_mode= LedModeOff;
+ XChangeKeyboardControl(theDisplay,KBLed|KBLedMode,&xkc);
+ XSync(theDisplay,0);
+ }
+
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return;
+ }
+
+ case XkbIM_NoExplicit:
+ break;
+ }
+
+ /* The 'ctrls' field tells what controls tell this indicator to
+ * to turn on: RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4),
+ * StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20),
+ * TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100),
+ * Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800),
+ * InternalMods (0x1000), IgnoreLockMods (0x2000),
+ * PerKeyRepeat (0x3000), or ControlsEnabled (0x4000)
+ */
+ if (xkb->indicators->maps[led].ctrls)
+ {
+ unsigned long which = xkb->indicators->maps[led].ctrls;
+
+ XkbGetControls(theDisplay,XkbAllControlsMask,xkb);
+ if (callbackData->set)
+ xkb->ctrls->enabled_ctrls |= which;
+ else
+ xkb->ctrls->enabled_ctrls &= ~which;
+ XkbSetControls(theDisplay,which|XkbControlsEnabledMask,xkb);
+ }
+
+ /* The 'which_groups' field tells when this indicator turns on
+ * for the 'groups' field: base (0x1), latched (0x2), locked (0x4),
+ * or effective (0x8).
+ */
+ if (xkb->indicators->maps[led].groups)
+ {
+ int i;
+ unsigned int group = 1;
+
+ /* Turning on a group indicator is kind of tricky. For
+ * now, we will just Latch or Lock the first group we find
+ * if that is what this indicator does. Otherwise, we're
+ * just going to punt and get out of here.
+ */
+ if (callbackData->set)
+ {
+ for (i = XkbNumKbdGroups-1; i >= 0; i--)
+ if ((1 << i) &
+ xkb->indicators->maps[led].groups)
+ group = i;
+ if (xkb->indicators->maps[led].which_groups &
+ (XkbIM_UseLocked | XkbIM_UseEffective))
+ XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
+ else if (xkb->indicators->maps[led].which_groups&XkbIM_UseLatched)
+ XkbLatchGroup(theDisplay,XkbUseCoreKbd,group);
+ else
+ {
+ XmToggleButtonSetState(w,!callbackData->set,FALSE);
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return;
+ }
+ }
+ /* Turning off a group indicator will mean that we just
+ * Lock the first group that this indicator doesn't watch.
+ */
+ else
+ {
+ for (i = XkbNumKbdGroups-1; i >= 0; i--)
+ if (!((1 << i) &
+ xkb->indicators->maps[led].groups))
+ group = i;
+ XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
+ }
+ }
+
+ /* The 'which_mods' field tells when this indicator turns on
+ * for the modifiers: base (0x1), latched (0x2), locked (0x4),
+ * or effective (0x8).
+ *
+ * The 'real_mods' field tells whether this turns on when one of
+ * the real X modifiers is set: Shift (0x1), Lock (0x2), Control (0x4),
+ * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80).
+ *
+ * The 'virtual_mods' field tells whether this turns on when one of
+ * the virtual modifiers is set.
+ *
+ * The 'mask' field tells what real X modifiers the virtual_modifiers
+ * map to?
+ */
+ if (xkb->indicators->maps[led].mods.real_mods ||
+ xkb->indicators->maps[led].mods.mask)
+ {
+ XkbStateRec state;
+ unsigned int affect,mods;
+
+ affect = (xkb->indicators->maps[led].mods.real_mods |
+ xkb->indicators->maps[led].mods.mask);
+
+ if (callbackData->set)
+ mods = affect;
+ else
+ mods = 0;
+
+ if (xkb->indicators->maps[led].which_mods &
+ (XkbIM_UseLocked | XkbIM_UseEffective))
+ XkbLockModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
+ else if (xkb->indicators->maps[led].which_mods &
+ XkbIM_UseLatched)
+ XkbLatchModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
+ else
+ {
+ XmToggleButtonSetState(w,!callbackData->set,FALSE);
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+ return;
+ }
+ }
+
+ XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+
+} /* valueChangedProc */
+
+/************************************************************************/
+/* */
+/* InitializeUI */
+/* */
+/************************************************************************/
+void InitializeUI(Widget topLevel)
+{
+ Arg argList[3];
+ char buf[256];
+ int i;
+ unsigned int bit,n;
+ Widget mainWindow,rowColumn;
+ XmString tempString;
+
+ mainWindow = (Widget) XmCreateMainWindow(topLevel,"mainWindow",NULL,0);
+ XtManageChild(mainWindow);
+ rowColumn = (Widget) XmCreateRowColumn(mainWindow,"rowColumn",NULL,0);
+ XtManageChild(rowColumn);
+
+ XkbGetIndicatorState(theDisplay,XkbUseCoreKbd,&n);
+ for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
+ {
+ if (options.wanted&bit)
+ {
+ /* [[[ WDW - If we wanted to be really fancy, we
+ * would look for a "*ledxx.labelString" value
+ * in the resource database so the I18N dudes
+ * can see localized strings. ]]]
+ */
+ XtSetArg(argList[0], XmNlabelString,ledNames[i]);
+ if (n&bit) XtSetArg(argList[1], XmNset, True);
+ else XtSetArg(argList[1], XmNset, False);
+ sprintf(buf,"led%d\0",i);
+ valueChangedCB[0].closure = (XtPointer) i;
+ XtSetArg(argList[2], XmNvalueChangedCallback, valueChangedCB);
+ leds[i]= XmCreateToggleButton(rowColumn,buf,argList,3);
+ XtManageChild(leds[i]);
+ }
+ else
+ leds[i]=0;
+ }
+
+} /* InitializeUI */
+
+/************************************************************************/
+/* */
+/* main */
+/* */
+/************************************************************************/
+#if NeedFunctionPrototypes
+int main(int argc,
+ char *argv[])
+#else
+int main(argc, argv)
+ int argc;
+ char *argv[];
+#endif
+{
+ /********************************************************************/
+ /* */
+ /* Initialize the toolkit */
+ /* */
+ /********************************************************************/
+ Arg argList[2];
+ topLevel = XtAppInitialize(&appContext, "xkbleds",
+ optionDesc, XtNumber(optionDesc),
+ &argc, argv,
+ fallbackResources,
+ NULL, 0);
+ XtSetArg(argList[0], XtNallowShellResize, TRUE);
+ XtSetValues(topLevel,argList,1);
+ XtGetApplicationResources(topLevel, (XtPointer)&options, resources,
+ XtNumber(resources), NULL, 0);
+
+ if (argc > 1)
+ {
+ usage(argv[0]);
+ exit(0);
+ }
+
+ /* Defaults
+ */
+ if ((options.wanted == DONT_CARE) &&
+ (options.wantReal == DONT_CARE) &&
+ (options.wantVirtual == DONT_CARE) &&
+ (options.wantNamed == DONT_CARE) &&
+ (options.wantAutomatic == DONT_CARE) &&
+ (options.wantExplicit == DONT_CARE) &&
+ (options.useUnion == YES))
+ {
+ options.wanted = 0;
+ options.wantReal = YES;
+ options.wantNamed = YES;
+ options.wantAutomatic = YES;
+ }
+
+ /********************************************************************/
+ /* */
+ /* See if the server has XKB. */
+ /* */
+ /********************************************************************/
+ theDisplay = XtDisplay(topLevel);
+ if (!InitXkb(theDisplay))
+ {
+ fprintf(stderr,"Could not initialize XKB extension.\n");
+ exit(0);
+ }
+
+ if (options.wanted == 0)
+ {
+ fprintf(stderr,"No LED's were selected.\n\n");
+ usage(argv[0]);
+ exit(0);
+ }
+
+ /********************************************************************/
+ /* */
+ /* Set up the UI and go. */
+ /* */
+ /********************************************************************/
+ XtRealizeWidget(topLevel);
+ InitializeUI(topLevel);
+ XtAppMainLoop(appContext);
+
+ /* NOT REACHED */
+ exit(0L);
+}
diff --git a/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.man b/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.man new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/mxkbledpanel/mxkbledpanel.man diff --git a/xorg-server/xkeyboard-config/tests/ruby/README b/xorg-server/xkeyboard-config/tests/ruby/README new file mode 100644 index 000000000..2ddf58a82 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/ruby/README @@ -0,0 +1,3 @@ +This is just some stuff to play with symbols/inet file, trying to analize it.
+Only maintainers might be interested. It is written in Ruby - but it will
+never be actually used in xkeyboard-config distribution.
diff --git a/xorg-server/xkeyboard-config/tests/ruby/find_fragments.rb b/xorg-server/xkeyboard-config/tests/ruby/find_fragments.rb new file mode 100644 index 000000000..f991ad0ab --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/ruby/find_fragments.rb @@ -0,0 +1,52 @@ +#!/usr/bin/ruby
+#
+# $Id$
+# The script finds the fragments
+#
+
+require "xkbparser.rb"
+
+baseDir = "../.."
+
+symbolsDir = "#{baseDir}/symbols"
+#symbolsDir = "."
+
+parser = Parser.new
+
+allSyms = parser.parse("#{symbolsDir}/inet")
+
+everything = allSyms.merge
+
+everything.filter(1)
+
+#numCombinations = 1
+
+#puts "everything:"
+
+#everything.find_all do | symName, keycodes |
+#puts "#{symName}, #{keycodes.length} mappings -> "
+# keycodes.find_all do | keycode, counter |
+# puts " #{keycode} -> #{counter} occurences"
+# end
+# numCombinations *= (keycodes.length + 1)
+#end
+
+#puts "Total mappings: #{everything.length}/#{everything.full_length()}, #{numCombinations} combinations"
+#
+
+numCombinations = 0
+allSyms.find_all do | symsName, symbols |
+ puts "n: #{symsName}"
+
+ # Counting only symbols which used more than once
+ numDupSymbols = symbols.keys.inject(0) do | rv, keycode |
+ c = everything.cardinality(keycode, symbols[keycode])
+ puts "#{keycode} -> #{symbols[keycode]}, #{c}"
+ (c > 0) ? rv : rv + 1
+ end
+
+ numCombinations += (1 << numDupSymbols)
+ puts "l: #{symbols.length} d: #{numDupSymbols} c: #{numCombinations}"
+end
+
+puts "numCombinations: #{numCombinations}"
diff --git a/xorg-server/xkeyboard-config/tests/ruby/find_match.rb b/xorg-server/xkeyboard-config/tests/ruby/find_match.rb new file mode 100644 index 000000000..43af93482 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/ruby/find_match.rb @@ -0,0 +1,42 @@ +#!/usr/bin/ruby
+#
+# $Id$
+# The script finds best matching xkb_symbols in symbols/in
+#
+# Parameters: $0 - the name of the file with new xkb_symbols
+# $1 - max number of non-matching mappings (0 by default)
+#
+
+require "xkbparser.rb"
+
+baseDir = "../.."
+
+symbolsDir = "#{baseDir}/symbols"
+#symbolsDir = "."
+
+parser = Parser.new
+
+allSyms = parser.parse("#{symbolsDir}/inet")
+
+newSyms = parser.parse(ARGV[0])
+limit = ARGV[1].to_i
+
+newSyms.find_all do | key, value |
+
+ if value.hidden?
+ next
+ end
+
+ puts "Existing xkb_symbols matching #{key}: "
+
+ sorted = allSyms.match_symbols(value,limit).sort_by do | symsName, diff |
+ sprintf "%03d_%s", diff.size, symsName
+ end
+
+ sorted.find_all do | symsName, diff |
+ puts " #{symsName}, up to #{allSyms[symsName].size} keys (difference #{diff.size})-> #{diff}"
+ end
+
+end
+
+
diff --git a/xorg-server/xkeyboard-config/tests/ruby/utils.rb b/xorg-server/xkeyboard-config/tests/ruby/utils.rb new file mode 100644 index 000000000..93ff0ee5e --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/ruby/utils.rb @@ -0,0 +1,64 @@ +#
+# $Id$
+#
+# Commont classes
+#
+
+#
+# The hash containing non-unique mappings
+# It can have a->b and a->c together
+# Also, for every mapping it counts the number of times this mapping was set
+#
+class NonuniqueCountingHash < Hash
+
+ alias get_original []
+ alias put_original []=
+
+ def []=(key, value)
+ own = self.get_original(key)
+ hash = get_original(key)
+ if hash.nil?
+ put_original(key, hash = Hash.new)
+ end
+ if hash.has_key?(value)
+ hash[value] += 1
+ else
+ hash[value] = 1
+ end
+ end
+
+ #
+ # Number of all mappings (a->b and a->c counted as 2 mappings)
+ #
+ def full_length()
+ values.inject(0) do | rv, hash |
+ rv + hash.length
+ end
+ end
+
+ def cardinality(key1, key2)
+ if has_key?(key1)
+ hash = get_original(key1)
+ if hash.has_key?(key2)
+ hash[key2]
+ else
+ 0
+ end
+ else
+ 0
+ end
+ end
+
+ def filter(limit)
+ find_all do | key, hash |
+ hash.find_all do | key1, counter |
+ if (counter <= limit)
+ hash.delete(key1)
+ end
+ end
+ if hash.empty?
+ delete(key)
+ end
+ end
+ end
+end
diff --git a/xorg-server/xkeyboard-config/tests/ruby/xkbparser.rb b/xorg-server/xkeyboard-config/tests/ruby/xkbparser.rb new file mode 100644 index 000000000..ecf246b6c --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/ruby/xkbparser.rb @@ -0,0 +1,185 @@ +#
+# $Id$
+#
+# Commont parsing classes for symbols/inet
+# The parsing is simplified, based on regex - it is NOT a real parser for very
+# complex XKB format
+#
+
+require "utils.rb"
+
+class Symbols < Hash
+
+ #
+ # Constructor
+ #
+ def initialize
+ @includedSyms = Array.new
+ end
+
+ # Write-only property, parent list of symbols definitions
+ def symbols_list=(symbolsList)
+ @symbolsList = symbolsList
+ end
+
+ # Whether this set of symbols is hidden or not
+ def hidden?
+ @hidden
+ end
+
+ def hidden=(h)
+ @hidden = h
+ end
+
+ #
+ # Add "dependency" - the symbols referenced using the "include" statement.
+ #
+ def add_included(other)
+ @includedSyms.push(other)
+ end
+
+ alias get_original []
+ alias keys_original keys
+
+ #
+ # Get the symbol, trying first own definitions, then walking through all
+ # dependenies
+ #
+ def [](symName)
+ own = self.get_original(symName)
+ if own.nil?
+ @includedSyms.find_all do | symsName |
+ syms = @symbolsList[symsName]
+ his = syms[symName]
+ if !his.nil?
+ own = his
+ break
+ end
+ end
+ end
+ own
+ end
+
+ #
+ # All keys - including the ones specified in the included sections
+ #
+ def keys()
+ @includedSyms.inject(keys_original) do | rv, symsName |
+ syms = @symbolsList[symsName]
+ rv | syms.keys
+ end
+ end
+
+ # Size of all keys
+ def length()
+ keys().length()
+ end
+
+ #
+ # Size - takes into account overlapping key definitions
+ #
+ def size()
+ keys.size()
+ end
+
+ #
+ # Create a hash including all elements of this hash which are not in the
+ # other hash, use symbols + and * for marking the elements which existed in
+ # the original hash (+ if not existed)
+ #
+ def -(other)
+ diff = self.class.new
+ self.find_all do | key, value |
+ existing = other[key]
+ if existing != value
+ diff[key] = [ value, existing.nil? ? '+' : '' ]
+ end
+ end
+ diff
+ end
+
+
+ def to_s
+ s = "{\n"
+ # First output included syms
+ @includedSyms.find_all do | symsName |
+ s += " include \"inet(#{symsName})\"\n"
+ end
+ # Then - own definitions
+ self.find_all do | key, value |
+ s += " key #{key} { [ #{value} ] };\n"
+ end
+ s + "}";
+ end
+
+end
+
+class SymbolsList < Hash
+
+ #
+ # Add new xkb_symbols
+ #
+ def add_symbols (symbolsName, hidden)
+ newSyms = Symbols.new
+ newSyms.symbols_list = self
+ newSyms.hidden = hidden
+ self[symbolsName] = newSyms
+ end
+
+ def to_s
+ s = "// Autogenerated\n\n"
+ self.find_all do | symbols, mapping |
+ s += "partial alphanumeric_keys\nxkb_symbols \"#{symbols}\" #{mapping};\n\n"
+ end
+ s
+ end
+
+ def match_symbols(new_symbols,limit)
+ matching = Hash.new
+ find_all do | symbols, mapping |
+ diff = new_symbols - mapping
+ if diff.size <= limit
+ matching[symbols] = diff
+ end
+ end
+ matching
+ end
+
+ def merge()
+ everything = NonuniqueCountingHash.new
+ find_all do | symsName, syms |
+ syms.find_all do | symName, keycode |
+ everything[symName] = keycode
+ end
+ end
+ everything
+ end
+
+end
+
+class Parser
+
+ def parse (fileName)
+ allSyms = SymbolsList.new;
+ currentSyms = nil
+ hidden = false
+ File.open(fileName) do | file |
+ file.each_line do | line |
+ line.scan(/xkb_symbols\s+"(\w+)"/) do | symsName |
+ currentSyms = allSyms.add_symbols(symsName[0], hidden)
+ end
+ line.scan(/^\s*key\s*<(\w+)>\s*\{\s*\[\s*(\w+)/) do | keycode, keysym |
+ currentSyms[keycode] = keysym
+ end
+ line.scan(/^partial\s+(hidden\s+)?alphanumeric_keys/) do | h |
+ hidden = !h[0].nil?
+ end
+ line.scan(/^\s*include\s+"inet\((\w+)\)"/) do | otherPart |
+ currentSyms.add_included(otherPart[0])
+ end
+ end
+ end
+ allSyms
+ end
+
+end
diff --git a/xorg-server/xkeyboard-config/tests/testLayouts.pl b/xorg-server/xkeyboard-config/tests/testLayouts.pl new file mode 100644 index 000000000..a1d43a395 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/testLayouts.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use xkbTestFunc;
+
+xkbTestFunc::backupXkbSettings();
+
+xkbTestFunc::dumpXkbSettingsBackup();
+
+xkbTestFunc::testLevel2( "layout", "variant", 2, "(", ")", 1, 1, 0 );
+
+sleep 2;
+
+xkbTestFunc::restoreXkbSettings();
+
+print "Done!\n";
diff --git a/xorg-server/xkeyboard-config/tests/testModels.pl b/xorg-server/xkeyboard-config/tests/testModels.pl new file mode 100644 index 000000000..ed4f99341 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/testModels.pl @@ -0,0 +1,15 @@ +#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use xkbTestFunc;
+
+xkbTestFunc::backupXkbSettings();
+
+xkbTestFunc::dumpXkbSettingsBackup();
+
+xkbTestFunc::testLevel1( "model", 1 );
+
+xkbTestFunc::restoreXkbSettings();
+
+print "Done!\n";
diff --git a/xorg-server/xkeyboard-config/tests/testOptions.pl b/xorg-server/xkeyboard-config/tests/testOptions.pl new file mode 100644 index 000000000..57ccc58d3 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/testOptions.pl @@ -0,0 +1,15 @@ +#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use xkbTestFunc;
+
+xkbTestFunc::backupXkbSettings();
+
+xkbTestFunc::dumpXkbSettingsBackup();
+
+xkbTestFunc::testLevel2( "group", "option", 4, ":", "", 0, 0, 1 );
+
+xkbTestFunc::restoreXkbSettings();
+
+print "Done!\n";
diff --git a/xorg-server/xkeyboard-config/tests/testShortDescriptions b/xorg-server/xkeyboard-config/tests/testShortDescriptions new file mode 100644 index 000000000..c05299e97 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/testShortDescriptions @@ -0,0 +1,6 @@ +#!/bin/sh
+
+awk '/shortDescr/{print toupper($0)}' ../rules/base.xml.in | sed 's/<[^>]*>//g;s/ //g' | sort | uniq > xml.sd
+awk '{print $1}' ../docs/iso3166-3.csv | sort > iso.sd
+diff -u iso.sd xml.sd | grep '+'
+
diff --git a/xorg-server/xkeyboard-config/tests/xkbTestFunc.pm b/xorg-server/xkeyboard-config/tests/xkbTestFunc.pm new file mode 100644 index 000000000..1d7881d23 --- /dev/null +++ b/xorg-server/xkeyboard-config/tests/xkbTestFunc.pm @@ -0,0 +1,164 @@ +package xkbTestFunc;
+
+use strict;
+use warnings;
+
+our $VERSION='1.00';
+
+our $origXkbRules;
+our $origXkbModel;
+our $origXkbLayouts;
+our $origXkbOptions;
+our $origXkbVariants;
+
+sub backupXkbSettings
+{
+ ( $origXkbRules, $origXkbModel, $origXkbLayouts, $origXkbVariants, $origXkbOptions ) = getXkbSettings();
+}
+
+sub getXkbSettings
+{
+ my ( $xkbRules, $xkbModel, $xkbLayouts, $xkbVariants, $xkbOptions );
+
+ open (XPROP, "xprop -root |") or die "Could not start xprop";
+ PROP: while (<XPROP>)
+ {
+ if (/_XKB_RULES_NAMES\(STRING\) = \"(.*)\", \"(.*)\", \"(.*)\", \"(.*)\", \"(.*)\"/)
+ {
+ ( $xkbRules, $xkbModel, $xkbLayouts, $xkbVariants, $xkbOptions ) =
+ ( $1, $2, $3, $4, $5 ) ;
+ last PROP;
+ }
+ }
+ close XPROP;
+
+ return ( $xkbRules, $xkbModel, $xkbLayouts, $xkbVariants, $xkbOptions );
+}
+
+sub setXkbSettings
+{
+ my ( $xkbRules, $xkbModel, $xkbLayouts, $xkbVariants, $xkbOptions ) = @_;
+ ( system ( "setxkbmap", "-synch",
+ "-rules", $xkbRules,
+ "-model", $xkbModel,
+ "-layout", $xkbLayouts,
+ "-variant", $xkbVariants,
+ "-option", $xkbOptions ) == 0 ) or die "Could not set xkb configuration";
+ sleep 1;
+}
+
+sub restoreXkbSettings
+{
+ setXkbSettings( $origXkbRules, $origXkbModel, $origXkbLayouts, $origXkbVariants, $origXkbOptions );
+}
+
+sub defaultXkbSettings
+{
+ return ( "base", "pc105", "us", "", "" );
+}
+
+sub dumpXkbSettings
+{
+ my ( $xkbRules, $xkbModel, $xkbLayouts, $xkbVariants, $xkbOptions ) = @_;
+ print "rules: [$xkbRules]\n" ;
+ print "model: [$xkbModel]\n" ;
+ print "layouts: [$xkbLayouts]\n" ;
+ print "variants: [$xkbVariants]\n" ;
+ print "options: [$xkbOptions]\n" ;
+}
+
+sub dumpXkbSettingsBackup
+{
+ dumpXkbSettings( $origXkbRules, $origXkbModel, $origXkbLayouts, $origXkbVariants, $origXkbOptions );
+}
+
+sub testLevel1
+{
+ my ( $type, $idx ) = @_;
+
+ open ( XSLTPROC, "xsltproc --stringparam type $type listCIs.xsl ../rules/base.xml.in |" ) or
+ die ( "Could not start xsltproc" );
+ while (<XSLTPROC>)
+ {
+ chomp();
+ if (/(\S+)/)
+ {
+ my $paramValue=$1;
+ print "--- setting $type: [$paramValue]\n";
+ my @params = defaultXkbSettings();
+ $params[$idx] = $paramValue;
+ dumpXkbSettings ( @params );
+ setXkbSettings ( @params );
+ #print "--- dump:\n";
+ #dumpXkbSettings( getXkbSettings() );
+ }
+ }
+ close XSLTPROC;
+}
+
+sub testLevel2
+{
+ my ( $type, $subtype, $idx, $delim1, $delim2, $ifCheckLevel1, $ifAddLevel1, $ifResetToDefault ) = @_;
+
+ open ( XSLTPROC, "xsltproc --stringparam type $type listCIs.xsl ../rules/base.xml.in |" ) or
+ die ( "Could not start xsltproc" );
+ while (<XSLTPROC>)
+ {
+ chomp();
+ if (/(\S+)/)
+ {
+ my $paramValue=$1;
+ print "--- scanning $type: [$paramValue]\n";
+
+ if ( $ifCheckLevel1 )
+ {
+ my @params = defaultXkbSettings();
+ if ( $ifResetToDefault )
+ {
+ setXkbSettings ( @params );
+ }
+ $params[$idx] = "$paramValue";
+ dumpXkbSettings ( @params );
+ setXkbSettings ( @params );
+ #print "--- dump:\n";
+ #dumpXkbSettings( getXkbSettings() );
+ }
+
+ open ( XSLTPROC2, "xsltproc --stringparam type $subtype --stringparam parentId $paramValue listCI2.xsl ../rules/base.xml.in |" ) or
+ die ( "Could not start xsltproc" );
+ while (<XSLTPROC2>)
+ {
+ chomp();
+ if (/(\S+)/)
+ {
+ my $paramValue2=$1;
+ print " --- $subtype: [$paramValue2]\n";
+ my @params = defaultXkbSettings();
+ if ( $ifResetToDefault )
+ {
+ setXkbSettings ( @params );
+ }
+ if ( $ifAddLevel1 )
+ {
+ $params[$idx] = "$paramValue$delim1$paramValue2$delim2";
+ }
+ else
+ {
+ $params[$idx] = "$paramValue2";
+ }
+ dumpXkbSettings ( @params );
+ setXkbSettings ( @params );
+ #print "--- dump:\n";
+ #dumpXkbSettings( getXkbSettings() );
+ }
+ }
+ close XSLTPROC2;
+ }
+ }
+ close XSLTPROC;
+}
+
+1;
+__END__
+
+No docs yet
diff --git a/xorg-server/xkeyboard-config/xslt/reg2ll.xsl b/xorg-server/xkeyboard-config/xslt/reg2ll.xsl new file mode 100644 index 000000000..5cb4c8bec --- /dev/null +++ b/xorg-server/xkeyboard-config/xslt/reg2ll.xsl @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+<xsl:output method="text"
+ encoding="UTF-8"
+ doctype-system="xkb.dtd"
+ indent="no"/>
+
+<xsl:template match="modelList|optionList|name|description|shortDescription|configItem"/>
+<xsl:strip-space elements="*"/>
+
+<xsl:template match="layoutList"><xsl:apply-templates select="./layout"/></xsl:template>
+
+<xsl:template match="variantList"><xsl:apply-templates select="./variant"/></xsl:template>
+
+<xsl:template match="layout"><xsl:text>
+</xsl:text><xsl:value-of select="./configItem/name"/>:"<xsl:value-of select="./configItem/description"/>"<xsl:apply-templates match="./variantList/variant"/></xsl:template>
+
+<xsl:template match="variant"><xsl:text>
+</xsl:text><xsl:value-of select="../../configItem/name"/>(<xsl:value-of select="./configItem/name"/>):"<xsl:value-of select="../../configItem/description"/> - <xsl:value-of select="./configItem/description"/>"</xsl:template>
+
+</xsl:stylesheet>
diff --git a/xorg-server/xkeyboard-config/xslt/xfree86.xsl b/xorg-server/xkeyboard-config/xslt/xfree86.xsl new file mode 100644 index 000000000..8b4e84976 --- /dev/null +++ b/xorg-server/xkeyboard-config/xslt/xfree86.xsl @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+<xsl:output method="xml"
+ encoding="UTF-8"
+ doctype-system="xkb.dtd"
+ indent="yes"/>
+
+ <!-- Transform all "simple" elements as they are -->
+ <xsl:template match="@*|xkbConfigRegistry|layout|layoutList|model|modelList|group|option|optionList|variant|variantList">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|*"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Tricky business: configItem -->
+ <xsl:template match="configItem">
+ <configItem xsl:space="preserve">
+ <name><xsl:value-of select="./name"/></name>
+ <!-- If there are some shortDescriptions -->
+ <xsl:if test="count(./shortDescription)!=0">
+ <!-- First, put the non-translated version -->
+ <shortDescription><xsl:value-of select="./shortDescription[not(@xml:lang)]"/></shortDescription>
+ <!-- For all translated versions ... -->
+ <xsl:for-each select="./shortDescription[@xml:lang]">
+ <!-- ... which are different from non-translated one ... -->
+ <xsl:if test="../shortDescription[not(@xml:lang)]/text() != ./text()">
+ <!-- ... - output! -->
+ <shortDescription xml:lang="{./@xml:lang}"><xsl:value-of select="./text()"/></shortDescription>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <!-- If there are some descriptions -->
+ <xsl:if test="count(./description)!=0">
+ <!-- First, put the non-translated version -->
+ <description><xsl:value-of select="./description[not(@xml:lang)]"/></description>
+ <!-- For all translated versions ... -->
+ <xsl:for-each select="./description[@xml:lang]">
+ <!-- ... which are different from non-translated one ... -->
+ <xsl:if test="../description[not(@xml:lang)]/text() != ./text()">
+ <!-- ... - output! -->
+ <description xml:lang="{./@xml:lang}"><xsl:value-of select="./text()"/></description>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ </configItem>
+ </xsl:template>
+
+</xsl:stylesheet>
|