146185892Smrg#include <stdio.h>
246185892Smrg#include <stdlib.h>
346185892Smrg#include <X11/Xlib.h>
446185892Smrg#include <X11/Intrinsic.h>
546185892Smrg#include <X11/XKBlib.h>
646185892Smrg#include <Xm/MainW.h>
746185892Smrg#include <Xm/RowColumn.h>
846185892Smrg#include <Xm/ToggleB.h>
946185892Smrg
1046185892SmrgDisplay         *theDisplay;
1146185892SmrgXtAppContext    appContext;
1246185892Smrgint		xkbEventBase;
1346185892SmrgWidget		topLevel;
1446185892SmrgWidget		leds[XkbNumIndicators];
1546185892SmrgAtom		ledAtoms[XkbNumIndicators];
1646185892SmrgXmString	ledNames[XkbNumIndicators];
1746185892SmrgXkbDescPtr	xkb_desc;
1846185892Smrg
1946185892Smrgvoid            valueChangedProc(Widget,XtPointer,XmToggleButtonCallbackStruct *);
2046185892SmrgXtCallbackRec   valueChangedCB[2]={(XtCallbackProc)valueChangedProc,NULL};
2146185892Smrg
2246185892Smrg/************************************************************************/
2346185892Smrg/*									*/
2446185892Smrg/* Application Resources						*/
2546185892Smrg/*									*/
2646185892Smrg/************************************************************************/
2746185892Smrg#define	YES		1
2846185892Smrg#define	NO		0
2946185892Smrg#define	DONT_CARE	-1
3046185892Smrg
3146185892Smrgtypedef struct
3246185892Smrg{
3346185892Smrg    int		wanted;
3446185892Smrg    int		wantAutomatic;
3546185892Smrg    int		wantExplicit;
3646185892Smrg    int		wantNamed;
3746185892Smrg    int		wantReal;
3846185892Smrg    int		wantVirtual;
3946185892Smrg    int		useUnion;
4046185892Smrg} OptionsRec;
4146185892Smrg
4246185892SmrgOptionsRec options;
4346185892Smrg
4446185892Smrg#define Offset(field) XtOffsetOf(OptionsRec,field)
4546185892SmrgXtResource resources[] =
4646185892Smrg{
4746185892Smrg    {"wanted", "Wanted", XtRInt, sizeof(int),
4846185892Smrg     Offset(wanted), XtRImmediate, (XtPointer) DONT_CARE },
4946185892Smrg    {"wantAutomatic", "WantAutomatic", XtRInt, sizeof(int),
5046185892Smrg     Offset(wantAutomatic), XtRImmediate, (XtPointer)   DONT_CARE},
5146185892Smrg    {"wantExplicit", "WantExplicit", XtRInt, sizeof(int),
5246185892Smrg     Offset(wantExplicit), XtRImmediate, (XtPointer)    DONT_CARE},
5346185892Smrg    {"wantNamed", "WantNamed", XtRInt, sizeof(int),
5446185892Smrg     Offset(wantNamed), XtRImmediate, (XtPointer)       DONT_CARE},
5546185892Smrg    {"wantReal", "WantReal", XtRInt, sizeof(int),
5646185892Smrg     Offset(wantReal), XtRImmediate, (XtPointer)        DONT_CARE},
5746185892Smrg    {"wantVirtual", "WantVirtual", XtRInt, sizeof(int),
5846185892Smrg     Offset(wantVirtual), XtRImmediate, (XtPointer)     DONT_CARE},
5946185892Smrg    {"useUnion", "UseUnion", XtRInt, sizeof(int),
6046185892Smrg     Offset(useUnion), XtRImmediate, (XtPointer)        YES},
6146185892Smrg    NULL
6246185892Smrg};
6346185892Smrg#undef Offset
6446185892Smrg
6546185892SmrgString fallbackResources[] =
6646185892Smrg{
6746185892Smrg    "*mainWindow.width: 100",
6846185892Smrg    "*mainWindow.height: 50",
6946185892Smrg    NULL
7046185892Smrg};
7146185892Smrg
7246185892SmrgXrmOptionDescRec optionDesc[] =
7346185892Smrg{
7446185892Smrg    {"-watch", "*wanted", XrmoptionSepArg, (XtPointer) "0"},
7546185892Smrg    {"-automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "0"},
7646185892Smrg    {"+automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "1"},
7746185892Smrg    {"-explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "0"},
7846185892Smrg    {"+explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "1"},
7946185892Smrg    {"-named", "*wantNamed", XrmoptionNoArg, (XtPointer) "0"},
8046185892Smrg    {"+named", "*wantNamed", XrmoptionNoArg, (XtPointer) "1"},
8146185892Smrg    {"-real", "*wantReal", XrmoptionNoArg, (XtPointer) "0"},
8246185892Smrg    {"+real", "*wantReal", XrmoptionNoArg, (XtPointer) "1"},
8346185892Smrg    {"-virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "0"},
8446185892Smrg    {"+virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "1"},
8546185892Smrg    {"-intersection", "*useUnion", XrmoptionNoArg, (XtPointer) "0"},
8646185892Smrg    {"-union", "*useUnion", XrmoptionNoArg, (XtPointer) "1"}
8746185892Smrg};
8846185892Smrg
8946185892Smrg/************************************************************************/
9046185892Smrg/*									*/
9146185892Smrg/* usage								*/
9246185892Smrg/*									*/
9346185892Smrg/************************************************************************/
9446185892Smrgvoid usage(char *program)
9546185892Smrg{
9646185892Smrg    printf("Usage: %s <options>\n",program);
9746185892Smrg    printf("Legal options include the usual X toolkit options plus:\n");
9846185892Smrg    printf("  -help           Print this message\n");
9946185892Smrg    printf("  -indpy <name>   Name of display to watch\n");
10046185892Smrg    printf("  -watch <leds>   Mask of LEDs to watch\n");
10146185892Smrg    printf("  [-+]automatic   (Don't) watch automatic LEDs\n");
10246185892Smrg    printf("  [-+]explicit    (Don't) watch explicit LEDs\n");
10346185892Smrg    printf("  [-+]named       (Don't) watch named LEDs\n");
10446185892Smrg    printf("  [-+]real        (Don't) watch real LEDs\n");
10546185892Smrg    printf("  [-+]virtual     (Don't) watch virtual LEDs\n");
10646185892Smrg    printf("  -intersection   Watch only LEDs in all desired sets\n");
10746185892Smrg    printf("  -union          Watch LEDs in any desired sets\n");
10846185892Smrg    printf("The default set of LEDs is -intersection +named +virtual\n");
10946185892Smrg    return;
11046185892Smrg}
11146185892Smrg/************************************************************************/
11246185892Smrg/*									*/
11346185892Smrg/*  XkbEventHandler	 						*/
11446185892Smrg/*									*/
11546185892Smrg/*  DESCRIPTION:							*/
11646185892Smrg/*									*/
11746185892Smrg/*      Handles events generated by the Xkb server extension.		*/
11846185892Smrg/*									*/
11946185892Smrg/************************************************************************/
12046185892SmrgBoolean XkbEventHandler(XEvent *event)
12146185892Smrg{
12246185892Smrg    XkbEvent 		*xkbEv = (XkbEvent *) event;
12346185892Smrg
12446185892Smrg    if (xkbEv->any.xkb_type==XkbIndicatorStateNotify)  {
12546185892Smrg	register int 		i;
12646185892Smrg	register unsigned	bit;
12746185892Smrg	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
12846185892Smrg	    if ((xkbEv->indicators.changed&bit)&&(leds[i]))
12946185892Smrg	    {
13046185892Smrg		if (xkbEv->indicators.state&bit)
13146185892Smrg		    XmToggleButtonSetState(leds[i],True,False);
13246185892Smrg		else
13346185892Smrg		    XmToggleButtonSetState(leds[i],False,False);
13446185892Smrg	    }
13546185892Smrg    }
13646185892Smrg    else if (xkbEv->any.xkb_type==XkbIndicatorMapNotify) {
13746185892Smrg	    unsigned change= xkbEv->indicators.changed;
13846185892Smrg
13946185892Smrg	    if (XkbGetIndicatorMap(theDisplay,change,xkb_desc)!=Success)
14046185892Smrg		fprintf(stderr,"Couldn't get changed indicator maps\n");
14146185892Smrg    }
14246185892Smrg
14346185892Smrg    return True;
14446185892Smrg
14546185892Smrg} /* XkbEventHandler */
14646185892Smrg
14746185892Smrg/************************************************************************/
14846185892Smrg/*									*/
14946185892Smrg/* InitXkb								*/
15046185892Smrg/*									*/
15146185892Smrg/************************************************************************/
15246185892SmrgBoolean InitXkb(Display *theDisplay)
15346185892Smrg{
15446185892Smrg    int			i,opcode,errorBase,major,minor;
15546185892Smrg    XkbDescPtr 		xkb;
15646185892Smrg    unsigned int	bit;
15746185892Smrg    unsigned int	real,virtual,named,explicit,automatic;
15846185892Smrg    char 		*name;
15946185892Smrg
16046185892Smrg    if (!XkbQueryExtension(theDisplay,
16146185892Smrg			   &opcode,
16246185892Smrg			   &xkbEventBase,
16346185892Smrg			   &errorBase,
16446185892Smrg			   &major,
16546185892Smrg			   &minor))
16646185892Smrg	return False;
16746185892Smrg
16846185892Smrg    if (!XkbUseExtension(theDisplay,&major,&minor))
16946185892Smrg	return False;
17046185892Smrg
17146185892Smrg    XkbSelectEvents(theDisplay,
17246185892Smrg		    XkbUseCoreKbd,
17346185892Smrg		    XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask,
17446185892Smrg		    XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask);
17546185892Smrg
17646185892Smrg    XtSetEventDispatcher(theDisplay,
17746185892Smrg			 xkbEventBase+XkbEventCode,
17846185892Smrg			 XkbEventHandler);
17946185892Smrg
18046185892Smrg    xkb=XkbGetMap(theDisplay,0,XkbUseCoreKbd);
18146185892Smrg    real=virtual=named=explicit=automatic=0;
18246185892Smrg
18346185892Smrg    if (!xkb)
18446185892Smrg    {
18546185892Smrg	fprintf(stderr,"Couldn't get keymap\n");
18646185892Smrg	return False;
18746185892Smrg    }
18846185892Smrg    if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
18946185892Smrg    {
19046185892Smrg	fprintf(stderr,"Couldn't read indicator map\n");
19146185892Smrg	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
19246185892Smrg	return False;
19346185892Smrg    }
19446185892Smrg    real=virtual=named=explicit=automatic=0;
19546185892Smrg
19646185892Smrg    if (XkbGetNames(theDisplay,XkbIndicatorNamesMask,xkb)!=Success)
19746185892Smrg    {
19846185892Smrg	fprintf(stderr,"Couldn't read indicator names\n");
19946185892Smrg	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
20046185892Smrg	return False;
20146185892Smrg    }
20246185892Smrg    real=virtual=named=explicit=automatic=0;
20346185892Smrg
20446185892Smrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
20546185892Smrg    {
20646185892Smrg	XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
20746185892Smrg	name = NULL;
20846185892Smrg	if (xkb->names->indicators[i]!=None)
20946185892Smrg	{
21046185892Smrg	    named|= bit;
21146185892Smrg	    name = XGetAtomName(theDisplay,xkb->names->indicators[i]);
21246185892Smrg	}
21346185892Smrg	if (name != NULL)
21446185892Smrg        {
21546185892Smrg	    ledAtoms[i] = xkb->names->indicators[i];
21646185892Smrg	    ledNames[i] = XmStringCreate(name,XmSTRING_DEFAULT_CHARSET);
21746185892Smrg	}
21846185892Smrg	else
21946185892Smrg	{
22046185892Smrg	    char temp[12];
22146185892Smrg	    sprintf(temp,"led%d\0",i+1);
22246185892Smrg	    ledAtoms[i] = None;
22346185892Smrg	    ledNames[i] = XmStringCreate(temp,XmSTRING_DEFAULT_CHARSET);
22446185892Smrg	}
22546185892Smrg	if (xkb->indicators->phys_indicators&bit)
22646185892Smrg	    real|= bit;
22746185892Smrg	if ((((map->which_groups!=0)&&(map->groups!=0))||
22846185892Smrg	     ((map->which_mods!=0)&&
22946185892Smrg			((map->mods.real_mods!=0)||(map->mods.vmods!=0)))||
23046185892Smrg	     (map->ctrls!=0))&&
23146185892Smrg	    ((map->flags&XkbIM_NoAutomatic)==0)) {
23246185892Smrg	    automatic|= bit;
23346185892Smrg	}
23446185892Smrg	else explicit|= bit;
23546185892Smrg    }
23646185892Smrg
23746185892Smrg    virtual = ~real;
23846185892Smrg
23946185892Smrg    if (options.useUnion)
24046185892Smrg    {
24146185892Smrg        if ((options.wantReal==NO)      || (options.wantReal==DONT_CARE))
24246185892Smrg	    real = 0;
24346185892Smrg        if ((options.wantVirtual==NO)   || (options.wantVirtual==DONT_CARE))
24446185892Smrg	    virtual = 0;
24546185892Smrg        if ((options.wantNamed==NO)     || (options.wantNamed==DONT_CARE))
24646185892Smrg	    named = 0;
24746185892Smrg        if ((options.wantAutomatic==NO) || (options.wantAutomatic==DONT_CARE))
24846185892Smrg	    automatic = 0;
24946185892Smrg        if ((options.wantExplicit==NO)  || (options.wantExplicit==DONT_CARE))
25046185892Smrg	    explicit = 0;
25146185892Smrg
25246185892Smrg	options.wanted |= real|virtual|named|automatic|explicit;
25346185892Smrg    }
25446185892Smrg    else
25546185892Smrg    {
25646185892Smrg	if (options.wanted == DONT_CARE)
25746185892Smrg	    options.wanted = ~0;
25846185892Smrg
25946185892Smrg        if (options.wantReal==NO)
26046185892Smrg	    real = ~real;
26146185892Smrg	else if (options.wantReal==DONT_CARE)
26246185892Smrg	    real = ~0;
26346185892Smrg
26446185892Smrg        if (options.wantVirtual==NO)
26546185892Smrg	    virtual = ~virtual;
26646185892Smrg        else if (options.wantVirtual==DONT_CARE)
26746185892Smrg	    virtual = ~0;
26846185892Smrg
26946185892Smrg        if (options.wantNamed==NO)
27046185892Smrg	    named = ~named;
27146185892Smrg        else if (options.wantNamed==DONT_CARE)
27246185892Smrg	    named = ~0;
27346185892Smrg
27446185892Smrg        if (options.wantAutomatic==NO)
27546185892Smrg	    automatic = ~automatic;
27646185892Smrg        else if (options.wantAutomatic==DONT_CARE)
27746185892Smrg	    automatic = ~0;
27846185892Smrg
27946185892Smrg        if (options.wantExplicit==NO)
28046185892Smrg	    explicit = ~explicit;
28146185892Smrg        else if (options.wantExplicit==DONT_CARE)
28246185892Smrg	    explicit = ~0;
28346185892Smrg
28446185892Smrg        options.wanted &= real&virtual&named&automatic&explicit;
28546185892Smrg    }
28646185892Smrg
28746185892Smrg    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
28846185892Smrg    return True;
28946185892Smrg
29046185892Smrg} /* InitXkb */
29146185892Smrg
29246185892Smrg/************************************************************************/
29346185892Smrg/*                                                                      */
29446185892Smrg/* valueChangedProc - called when a toggle button is pressed.           */
29546185892Smrg/*                                                                      */
29646185892Smrg/************************************************************************/
29746185892Smrgvoid valueChangedProc(Widget                    	w,
29846185892Smrg                      XtPointer                 	clientData,
29946185892Smrg                      XmToggleButtonCallbackStruct      *callbackData)
30046185892Smrg{
30146185892Smrg    int         	led = (int) clientData;
30246185892Smrg    XkbDescPtr		xkb;
30346185892Smrg
30446185892Smrg    xkb = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
30546185892Smrg    if (!xkb)
30646185892Smrg    {
30746185892Smrg	fprintf(stderr,"XkbGetMap failed\n");
30846185892Smrg        return;
30946185892Smrg    }
31046185892Smrg
31146185892Smrg    if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
31246185892Smrg    {
31346185892Smrg	fprintf(stderr,"GetIndicatorMap failed\n");
31446185892Smrg	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
31546185892Smrg	return;
31646185892Smrg    }
31746185892Smrg
31846185892Smrg    /* The 'flags' field tells whether this indicator is automatic
31946185892Smrg     * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40),
32046185892Smrg     * or neither (both - 0xC0).
32146185892Smrg     *
32246185892Smrg     * If NoAutomatic is set, the server ignores the rest of the
32346185892Smrg     * fields in the indicator map (i.e. it disables automatic control
32446185892Smrg     * of the LED).   If NoExplicit is set, the server prevents clients
32546185892Smrg     * from explicitly changing the value of the LED (using the core
32646185892Smrg     * protocol *or* XKB).   If NoAutomatic *and* NoExplicit are set,
32746185892Smrg     * the LED cannot be changed (unless you change the map first).
32846185892Smrg     * If neither NoAutomatic nor NoExplicit are set, the server will
32946185892Smrg     * change the LED according to the indicator map, but clients can
33046185892Smrg     * override that (until the next automatic change) using the core
33146185892Smrg     * protocol or XKB.
33246185892Smrg     */
33346185892Smrg    switch (xkb->indicators->maps[led].flags &
33446185892Smrg	    (XkbIM_NoExplicit|XkbIM_NoAutomatic))
33546185892Smrg    {
33646185892Smrg	case XkbIM_NoExplicit|XkbIM_NoAutomatic:
33746185892Smrg	{
33846185892Smrg	    XmToggleButtonSetState(w,!callbackData->set,FALSE);
33946185892Smrg	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
34046185892Smrg	    return;
34146185892Smrg	}
34246185892Smrg
34346185892Smrg	case XkbIM_NoAutomatic:
34446185892Smrg	{
34546185892Smrg	    if (ledAtoms[led] != None)
34646185892Smrg		XkbSetNamedIndicator(theDisplay,XkbUseCoreKbd,
34746185892Smrg				     ledAtoms[led],callbackData->set,
34846185892Smrg				     FALSE,NULL);
34946185892Smrg	    else
35046185892Smrg	    {
35146185892Smrg		XKeyboardControl	xkc;
35246185892Smrg		xkc.led= led;
35346185892Smrg		if (callbackData->set)
35446185892Smrg		     xkc.led_mode= LedModeOn;
35546185892Smrg		else xkc.led_mode= LedModeOff;
35646185892Smrg		XChangeKeyboardControl(theDisplay,KBLed|KBLedMode,&xkc);
35746185892Smrg		XSync(theDisplay,0);
35846185892Smrg	    }
35946185892Smrg
36046185892Smrg	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
36146185892Smrg	    return;
36246185892Smrg	}
36346185892Smrg
36446185892Smrg	case XkbIM_NoExplicit:
36546185892Smrg	break;
36646185892Smrg    }
36746185892Smrg
36846185892Smrg    /* The 'ctrls' field tells what controls tell this indicator to
36946185892Smrg     * to turn on:  RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4),
37046185892Smrg     *              StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20),
37146185892Smrg     *		    TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100),
37246185892Smrg     *		    Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800),
37346185892Smrg     *		    InternalMods (0x1000), IgnoreLockMods (0x2000),
37446185892Smrg     *		    PerKeyRepeat (0x3000), or ControlsEnabled (0x4000)
37546185892Smrg     */
37646185892Smrg    if (xkb->indicators->maps[led].ctrls)
37746185892Smrg    {
37846185892Smrg	unsigned long which = xkb->indicators->maps[led].ctrls;
37946185892Smrg
38046185892Smrg	XkbGetControls(theDisplay,XkbAllControlsMask,xkb);
38146185892Smrg	if (callbackData->set)
38246185892Smrg	    xkb->ctrls->enabled_ctrls |= which;
38346185892Smrg	else
38446185892Smrg	    xkb->ctrls->enabled_ctrls &= ~which;
38546185892Smrg	XkbSetControls(theDisplay,which|XkbControlsEnabledMask,xkb);
38646185892Smrg    }
38746185892Smrg
38846185892Smrg    /* The 'which_groups' field tells when this indicator turns on
38946185892Smrg     * for the 'groups' field:  base (0x1), latched (0x2), locked (0x4),
39046185892Smrg     *                          or effective (0x8).
39146185892Smrg     */
39246185892Smrg    if (xkb->indicators->maps[led].groups)
39346185892Smrg    {
39446185892Smrg	int		i;
39546185892Smrg       	unsigned int	group = 1;
39646185892Smrg
39746185892Smrg	/* Turning on a group indicator is kind of tricky.  For
39846185892Smrg	 * now, we will just Latch or Lock the first group we find
39946185892Smrg	 * if that is what this indicator does.  Otherwise, we're
40046185892Smrg	 * just going to punt and get out of here.
40146185892Smrg	 */
40246185892Smrg	if (callbackData->set)
40346185892Smrg	{
40446185892Smrg	    for (i = XkbNumKbdGroups-1; i >= 0; i--)
40546185892Smrg		if ((1 << i) &
40646185892Smrg		    xkb->indicators->maps[led].groups)
40746185892Smrg		    group = i;
40846185892Smrg	    if (xkb->indicators->maps[led].which_groups &
40946185892Smrg		(XkbIM_UseLocked | XkbIM_UseEffective))
41046185892Smrg		XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
41146185892Smrg	    else if (xkb->indicators->maps[led].which_groups&XkbIM_UseLatched)
41246185892Smrg		XkbLatchGroup(theDisplay,XkbUseCoreKbd,group);
41346185892Smrg	    else
41446185892Smrg	    {
41546185892Smrg		XmToggleButtonSetState(w,!callbackData->set,FALSE);
41646185892Smrg		XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
41746185892Smrg		return;
41846185892Smrg	    }
41946185892Smrg	}
42046185892Smrg	/* Turning off a group indicator will mean that we just
42146185892Smrg	 * Lock the first group that this indicator doesn't watch.
42246185892Smrg	 */
42346185892Smrg	else
42446185892Smrg	{
42546185892Smrg	    for (i = XkbNumKbdGroups-1; i >= 0; i--)
42646185892Smrg		if (!((1 << i) &
42746185892Smrg		      xkb->indicators->maps[led].groups))
42846185892Smrg		    group = i;
42946185892Smrg	    XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
43046185892Smrg	}
43146185892Smrg    }
43246185892Smrg
43346185892Smrg    /* The 'which_mods' field tells when this indicator turns on
43446185892Smrg     * for the modifiers:  base (0x1), latched (0x2), locked (0x4),
43546185892Smrg     *                     or effective (0x8).
43646185892Smrg     *
43746185892Smrg     * The 'real_mods' field tells whether this turns on when one of
43846185892Smrg     * the real X modifiers is set:  Shift (0x1), Lock (0x2), Control (0x4),
43946185892Smrg     * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80).
44046185892Smrg     *
44146185892Smrg     * The 'virtual_mods' field tells whether this turns on when one of
44246185892Smrg     * the virtual modifiers is set.
44346185892Smrg     *
44446185892Smrg     * The 'mask' field tells what real X modifiers the virtual_modifiers
44546185892Smrg     * map to?
44646185892Smrg     */
44746185892Smrg    if (xkb->indicators->maps[led].mods.real_mods ||
44846185892Smrg	xkb->indicators->maps[led].mods.mask)
44946185892Smrg    {
45046185892Smrg	XkbStateRec 	state;
45146185892Smrg	unsigned int	affect,mods;
45246185892Smrg
45346185892Smrg	affect = (xkb->indicators->maps[led].mods.real_mods |
45446185892Smrg		  xkb->indicators->maps[led].mods.mask);
45546185892Smrg
45646185892Smrg	if (callbackData->set)
45746185892Smrg	    mods = affect;
45846185892Smrg	else
45946185892Smrg	    mods = 0;
46046185892Smrg
46146185892Smrg	if (xkb->indicators->maps[led].which_mods &
46246185892Smrg	    (XkbIM_UseLocked | XkbIM_UseEffective))
46346185892Smrg	    XkbLockModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
46446185892Smrg	else if (xkb->indicators->maps[led].which_mods &
46546185892Smrg		 XkbIM_UseLatched)
46646185892Smrg	    XkbLatchModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
46746185892Smrg	else
46846185892Smrg	{
46946185892Smrg	    XmToggleButtonSetState(w,!callbackData->set,FALSE);
47046185892Smrg	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
47146185892Smrg	    return;
47246185892Smrg	}
47346185892Smrg    }
47446185892Smrg
47546185892Smrg    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
47646185892Smrg
47746185892Smrg} /* valueChangedProc */
47846185892Smrg
47946185892Smrg/************************************************************************/
48046185892Smrg/*									*/
48146185892Smrg/* InitializeUI								*/
48246185892Smrg/*									*/
48346185892Smrg/************************************************************************/
48446185892Smrgvoid InitializeUI(Widget topLevel)
48546185892Smrg{
48646185892Smrg    Arg 		argList[3];
48746185892Smrg    char 		buf[256];
48846185892Smrg    int 		i;
48946185892Smrg    unsigned int	bit,n;
49046185892Smrg    Widget 		mainWindow,rowColumn;
49146185892Smrg    XmString		tempString;
49246185892Smrg
49346185892Smrg    mainWindow = (Widget) XmCreateMainWindow(topLevel,"mainWindow",NULL,0);
49446185892Smrg    XtManageChild(mainWindow);
49546185892Smrg    rowColumn  = (Widget) XmCreateRowColumn(mainWindow,"rowColumn",NULL,0);
49646185892Smrg    XtManageChild(rowColumn);
49746185892Smrg
49846185892Smrg    XkbGetIndicatorState(theDisplay,XkbUseCoreKbd,&n);
49946185892Smrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
50046185892Smrg    {
50146185892Smrg	if (options.wanted&bit)
50246185892Smrg	{
50346185892Smrg            /* [[[ WDW - If we wanted to be really fancy, we
50446185892Smrg	     *     would look for a "*ledxx.labelString" value
50546185892Smrg	     *     in the resource database so the I18N dudes
50646185892Smrg	     *	   can see localized strings. ]]]
50746185892Smrg	     */
50846185892Smrg	    XtSetArg(argList[0], XmNlabelString,ledNames[i]);
50946185892Smrg	    if (n&bit) XtSetArg(argList[1], XmNset, True);
51046185892Smrg	    else       XtSetArg(argList[1], XmNset, False);
51146185892Smrg	    sprintf(buf,"led%d\0",i);
51246185892Smrg            valueChangedCB[0].closure = (XtPointer) i;
51346185892Smrg	    XtSetArg(argList[2], XmNvalueChangedCallback, valueChangedCB);
51446185892Smrg	    leds[i]= XmCreateToggleButton(rowColumn,buf,argList,3);
51546185892Smrg	    XtManageChild(leds[i]);
51646185892Smrg	}
51746185892Smrg	else
51846185892Smrg	    leds[i]=0;
51946185892Smrg    }
52046185892Smrg
52146185892Smrg} /* InitializeUI */
52246185892Smrg
52346185892Smrg/************************************************************************/
52446185892Smrg/*									*/
52546185892Smrg/* main									*/
52646185892Smrg/*									*/
52746185892Smrg/************************************************************************/
52846185892Smrg#if NeedFunctionPrototypes
52946185892Smrgint main(int	argc,
53046185892Smrg	  char	*argv[])
53146185892Smrg#else
53246185892Smrgint main(argc, argv)
53346185892Smrg    int		argc;
53446185892Smrg    char	*argv[];
53546185892Smrg#endif
53646185892Smrg{
53746185892Smrg    /********************************************************************/
53846185892Smrg    /*									*/
53946185892Smrg    /* Initialize the toolkit 						*/
54046185892Smrg    /*									*/
54146185892Smrg    /********************************************************************/
54246185892Smrg    Arg argList[2];
54346185892Smrg    topLevel = XtAppInitialize(&appContext, "xkbleds",
54446185892Smrg			       optionDesc, XtNumber(optionDesc),
54546185892Smrg			       &argc, argv,
54646185892Smrg			       fallbackResources,
54746185892Smrg			       NULL, 0);
54846185892Smrg    XtSetArg(argList[0], XtNallowShellResize, TRUE);
54946185892Smrg    XtSetValues(topLevel,argList,1);
55046185892Smrg    XtGetApplicationResources(topLevel, (XtPointer)&options, resources,
55146185892Smrg			      XtNumber(resources), NULL, 0);
55246185892Smrg
55346185892Smrg    if (argc > 1)
55446185892Smrg    {
55546185892Smrg	usage(argv[0]);
55646185892Smrg	exit(0);
55746185892Smrg    }
55846185892Smrg
55946185892Smrg    /* Defaults
56046185892Smrg     */
56146185892Smrg    if ((options.wanted == DONT_CARE) &&
56246185892Smrg	(options.wantReal == DONT_CARE) &&
56346185892Smrg	(options.wantVirtual == DONT_CARE) &&
56446185892Smrg	(options.wantNamed == DONT_CARE) &&
56546185892Smrg	(options.wantAutomatic == DONT_CARE) &&
56646185892Smrg	(options.wantExplicit == DONT_CARE) &&
56746185892Smrg	(options.useUnion == YES))
56846185892Smrg    {
56946185892Smrg	options.wanted 		= 0;
57046185892Smrg	options.wantReal	= YES;
57146185892Smrg	options.wantNamed 	= YES;
57246185892Smrg	options.wantAutomatic	= YES;
57346185892Smrg    }
57446185892Smrg
57546185892Smrg    /********************************************************************/
57646185892Smrg    /*									*/
57746185892Smrg    /* See if the server has XKB.					*/
57846185892Smrg    /*									*/
57946185892Smrg    /********************************************************************/
58046185892Smrg    theDisplay = XtDisplay(topLevel);
58146185892Smrg    if (!InitXkb(theDisplay))
58246185892Smrg    {
58346185892Smrg	fprintf(stderr,"Could not initialize XKB extension.\n");
58446185892Smrg	exit(0);
58546185892Smrg    }
58646185892Smrg
58746185892Smrg    if (options.wanted == 0)
58846185892Smrg    {
58946185892Smrg	fprintf(stderr,"No LED's were selected.\n\n");
59046185892Smrg	usage(argv[0]);
59146185892Smrg	exit(0);
59246185892Smrg    }
59346185892Smrg
59446185892Smrg    /********************************************************************/
59546185892Smrg    /*									*/
59646185892Smrg    /* Set up the UI and go.						*/
59746185892Smrg    /*									*/
59846185892Smrg    /********************************************************************/
59946185892Smrg    XtRealizeWidget(topLevel);
60046185892Smrg    InitializeUI(topLevel);
60146185892Smrg    XtAppMainLoop(appContext);
60246185892Smrg
60346185892Smrg    /* NOT REACHED */
60446185892Smrg    exit(0L);
60546185892Smrg}
606