/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* gos720 src/gos/2d/XTOP/extras/accessx/accessx.c 1.1                    */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2005                   */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* $Xorg: accessx.c,v 1.2 2001/01/29 20:04:07 coskrey Exp $ */
/***************************************************************************/
/*                                                                         */
/* Copyright (c) 2000 Compaq Computer Corporation                          */
/*                                                                         */
/* The software (contained on this media) is proprietary to and embodies   */
/* the confidential technology of Compaq Computer Corporation.             */
/* Possession use, duplication or disseminationof the software and media   */
/* in source and binary forms, with or without modification, is authorized,*/
/* provided that the following conditions are met:                         */
/*                                                                         */
/* 1.  Redistribution of source code must retain the above copyright       */
/* notice, this list of conditions, and the following disclaimer in the    */
/* documentation and/or other materials provided with the distribution.    */
/*                                                                         */
/* 2.  Redistribution of binary forms must reproduce the above copyright   */
/* notice, this list of conditions, and the following disclaimer in the    */
/* documentation and/or othe rmatierals provided with the distribution.    */
/*                                                                         */
/* 3.  The name of the Corporation may not be used to endorse or promote   */
/* products derived from this sfotware without specific prior written      */
/* permission from Compaq Computer Corporation.                            */
/*                                                                         */
/* THE SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
/* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY */
/* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL */
/* THE CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,*/
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT LIMITED TO,      */
/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR      */
/* PROFITS; OR BUSINESS INTERRUPTION), HOWEVER CAUSED AND ON ANY THEORY OF */
/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING    */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS      */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.            */
/*                                                                         */
/***************************************************************************/

/************************************************************************/
/*                                                                      */
/*         Copyright 1993 Sun Microsystems, Inc. All Rights Reserved.   */
/*                                                                      */
/*      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 */
/*      Sun Microsystems, Inc. (SMI) not be used in advertising or      */
/*      publicity pertaining to distribution of the software without    */
/*      specific, written prior permission.                             */
/*                                                                      */
/*                                                                      */
/*      SMI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,      */
/*      INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND         */
/*      FITNESS, IN NO EVENT SHALL SMI 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.                                               */
/*                                                                      */
/************************************************************************/

/************************************************************************/
/*									*/
/* AccessX	   						        */
/* 									*/
/* 	This module is intended to provide access features for people	*/
/*	with physical disabilities.  This is a Motif client that	*/
/*	communicates with the XKB server extension and allows us to	*/
/*	get visual feedback regarding the state of the AccessX features.*/
/*									*/
/************************************************************************/

/************************************************************************/
/*                                                                      */
/* Include Files                                                        */
/*                                                                      */
/************************************************************************/
#include <stdio.h>
#include <sys/param.h>
#include <stdlib.h>

#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Intrinsic.h>
#include <X11/XKBlib.h>

#include <Xm/Form.h>
#include <Mrm/MrmAppl.h>
#include "accessx.xbm"

/************************************************************************/
/*									*/
/* X11, Xt, and Other Global Variables					*/
/*									*/
/************************************************************************/
/* X11, Xt and General Widgets Global Variables 
 */
Widget		topLevel;
XtAppContext    appContext;
XrmDatabase  	settingsWindowDatabase = NULL;

Display         *theDisplay;
int		xkbEventBase;

Widget		settingsDialog;
Widget		statusTopLevel = NULL;
Widget 		statusDialog; 
Widget		helpDialog;
Widget		saveDoneDialog,saveErrDialog;
Widget		loadDoneDialog,loadErrDialog;

XmString 	emptyString,noneString,plusString;
XmString 	shiftString, lockString, controlString, 
                mod1String, mod2String, mod3String, mod4String, mod5String;
XmString 	mb1String, mb2String, mb3String, mb4String, mb5String;

#ifdef __osf__
XmString	helpText = NULL;
XmString	generalHelp = NULL;
XmString	stickyHelp = NULL;
XmString	mouseHelp = NULL;
XmString	toggleHelp = NULL;
XmString	repeatHelp = NULL;
XmString	slowHelp = NULL;
XmString	bounceHelp = NULL;
XmString	allHelp	= NULL;
#else
char		*helpText = NULL;
char		*generalHelp = NULL;
char		*stickyHelp = NULL;
char		*mouseHelp = NULL;
char		*toggleHelp = NULL;
char		*repeatHelp = NULL;
char		*slowHelp = NULL;
char		*bounceHelp = NULL;
char		*allHelp = NULL;
#endif

/************************************************************************/
/*									*/
/* Mrm Global Variables							*/
/*									*/
/************************************************************************/
void CreateProc(Widget, int *, unsigned long);
void ActivateProc(Widget, int *, XmAnyCallbackStruct *);
void ChangeControlProc(Widget, int *, XmToggleButtonCallbackStruct *);

MrmHierarchy	mrmHierarchy;	
MrmCode         dummyClass;

char *dbFilenameVec[] = {"accessx"};
int dbFilenameNum = (sizeof dbFilenameVec / sizeof dbFilenameVec [0]);

static MrmRegisterArg regList [] = 
{ 
    {"CreateProc", (caddr_t)CreateProc},
    {"ActivateProc", (caddr_t)ActivateProc},
    {"ChangeControlProc", (caddr_t)ChangeControlProc}
};
int regListNum = (sizeof regList / sizeof regList[0]);

/************************************************************************/
/*									*/
/* Constant Declarations						*/
/*									*/
/************************************************************************/
/*************** TOGGLE WIDGETS ***********************/
#define ENABLE_ACCESSX_TGL			1
#define ONOFF_SOUND_TGL				2
#define TIME_OUT_TGL				3
#define SHOW_STATUS_TGL				4

#define STICKY_KEYS_TGL				5
#define MOUSE_KEYS_TGL				6
#define TOGGLE_KEYS_TGL				7
#define REPEAT_KEYS_TGL				8
#define SLOW_KEYS_TGL				9
#define BOUNCE_KEYS_TGL				10

#define STICKY_MOD_SOUND_TGL			11
#define STICKY_TWO_KEYS_TGL			12
#define KRG_PRESS_SOUND_TGL			13
#define KRG_ACCEPT_SOUND_TGL			14

#define MAIN_TOGGLE_WIDGETS_MIN			ENABLE_ACCESSX_TGL
#define MAIN_TOGGLE_WIDGETS_MAX			BOUNCE_KEYS_TGL
#define SETTINGS_TOGGLE_WIDGETS_MIN 		STICKY_MOD_SOUND_TGL
#define SETTINGS_TOGGLE_WIDGETS_MAX 		KRG_ACCEPT_SOUND_TGL
#define TOGGLE_WIDGETS_MIN			ENABLE_ACCESSX_TGL
#define TOGGLE_WIDGETS_MAX			KRG_ACCEPT_SOUND_TGL

/************** SCALE WIDGETS *************************/
#define TIME_OUT_SCL				15

#define MOUSE_MAX_SPEED_SCL			16
#define MOUSE_ACCEL_SCL				17
#define MOUSE_DELAY_SCL				18

#define KRG_REPEAT_DELAY_SCL			19
#define KRG_REPEAT_RATE_SCL			20
#define KRG_SLOW_DELAY_SCL			21
#define KRG_DEBOUNCE_SCL			22

#define SCALE_WIDGETS_MIN			TIME_OUT_SCL
#define SCALE_WIDGETS_MAX			KRG_DEBOUNCE_SCL

/************** MAIN MENU ITEMS ***********************/
#define LOAD_BTN				23
#define SAVE_BTN				24
#define EXIT_BTN				25

#define ALL_BTN					26
#define STICKYKEYS_BTN				27
#define MOUSEKEYS_BTN				28
#define KRG_BTN					29

#define GENERAL_HELP_BTN			30
#define STICKY_HELP_BTN				31
#define MOUSE_HELP_BTN				32
#define TOGGLE_HELP_BTN				33
#define REPEAT_HELP_BTN				34
#define SLOW_HELP_BTN				35
#define BOUNCE_HELP_BTN				36

/*************** HELP WIDGETS *************************/
#define HELP_TEXT				37
#define CLOSE_HELP_BTN				38

/*************** SETTINGS WINDOW **********************/
#define SETTINGS_OK_BTN				39
#define SETTINGS_RESET_BTN			40
#define SETTINGS_DEFAULTS_BTN			41
#define SETTINGS_CANCEL_BTN			42
#define SETTINGS_HELP_BTN			43

/*************** STATUS *************************/
#define STATUS_FRAME                            44
#define DEFAULT_BUTTON_MENU			45
#define MB1_BTN					46
#define MB2_BTN					47
#define MB3_BTN					48
#define MB4_BTN					49
#define MB5_BTN					50

/*************** LOAD-SAVE WIDGETS *******************/
#define SAVE_DONE_CANCEL_BTN			51
#define SAVE_DONE_OK_BTN			52
#define SAVE_DONE_HELP_BTN			53

#define SAVE_ERR_CANCEL_BTN			54
#define SAVE_ERR_OK_BTN				55
#define SAVE_ERR_HELP_BTN			56

#define LOAD_DONE_CANCEL_BTN			57
#define LOAD_DONE_OK_BTN			58
#define LOAD_DONE_HELP_BTN			59

#define LOAD_ERR_CANCEL_BTN			60
#define LOAD_ERR_OK_BTN				61
#define LOAD_ERR_HELP_BTN			62

#define HELP_ERR_CANCEL_BTN			63
#define HELP_ERR_OK_BTN				64
#define HELP_ERR_HELP_BTN			65

/*************** LABEL WIDGETS FOR SCALES *******************/
#define TIME_OUT_LBL				66
#define MOUSE_MAX_SPEED_LBL			67
#define MOUSE_ACCEL_LBL				68
#define MOUSE_DELAY_LBL				69
#define KRG_REPEAT_RATE_LBL			70
#define KRG_REPEAT_DELAY_LBL			71
#define KRG_SLOW_DELAY_LBL			72
#define KRG_DEBOUNCE_LBL			73
#define KRG_SOUND_WHEN_LBL			74

#define STICKYKEYS_FRAME			75
#define MOUSEKEYS_FRAME				76
#define REPEATKEYS_FRAME			77
#define SLOWKEYS_FRAME				78
#define BOUNCEKEYS_FRAME			79
#define TEST_FRAME				80
#define SETTINGS_OK_FORM			81

#define MODIFIERS_LBL				82

#define LABEL_WIDGETS_MIN			MOUSE_MAX_SPEED_LBL
#define LABEL_WIDGETS_MAX			KRG_SOUND_WHEN_LBL
#define NUM_WIDGETS				MODIFIERS_LBL + 1
#define NUM_RES_WIDGETS				SCALE_WIDGETS_MAX + 1

Widget widgets[NUM_WIDGETS];


/* Application Class String 
 */
#define ACCESSX_CLASS		"AccessX"

char resStrings[NUM_RES_WIDGETS][256] = {
	"",
	"*EnableAccessXToggle.set",
	"*SoundOnOffToggle.set",
	"*TimeOutToggle.set",
	"*ShowStatusToggle.set",
	"*StickyKeysToggle.set",
	"*MouseKeysToggle.set",
	"*ToggleKeysToggle.set",
	"*RepeatKeysToggle.set",
	"*SlowKeysToggle.set",
	"*BounceKeysToggle.set",
	"*StickyModSoundToggle.set",
	"*StickyTwoKeysToggle.set",
	"*SlowKeysOnPressToggle.set",
	"*SlowKeysOnAcceptToggle.set",
	"*TimeOutScale",
	"*MouseMaxSpeedScale",
	"*MouseAccelScale",
	"*MouseDelayScale",
	"*KRGRepeatDelayScale",
	"*KRGRepeatRateScale",
	"*KRGSlowKeysDelayScale",
	"*KRGDebounceScale" };

char classStrings[NUM_RES_WIDGETS][80] = {
	"",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
	"AccessX*ToggleButtonGadget.XmCSet",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale",
        "AccessX*XmScale" };

/************************************************************************/
/*									*/
/* Application Resources						*/
/*									*/
/************************************************************************/
typedef struct 
{
    Boolean	showStatus;		/* Show status box on startup   */
    Boolean	useServer;		/* Use server settings		*/
    Boolean	useVmods;		/* Use virtual modifier names   */
                                        /*  in the status window	*/
} OptionsRec;

OptionsRec options;

#define Offset(field) XtOffsetOf(OptionsRec,field)
XtResource resources[] = 
{
    {"showStatus", "showStatus", XtRBoolean, sizeof(Boolean),
     Offset(showStatus), XtRImmediate, (XtPointer)      False},
    {"useServer", "UseServer", XtRBoolean, sizeof(Boolean),
     Offset(useServer), XtRImmediate, (XtPointer)      False},
    {"useVmods", "UseVmods", XtRBoolean, sizeof(Boolean),
     Offset(useVmods), XtRImmediate, (XtPointer)       False}
};
#undef Offset

XrmOptionDescRec optionDesc[] = {
    {"-status", "*showStatus", XrmoptionNoArg, (XtPointer) "true"},
    {"-server", "*useServer", XrmoptionNoArg, (XtPointer) "true"},
    {"-client", "*useServer", XrmoptionNoArg, (XtPointer) "false"},
    {"-vmods", "*useVmods", XrmoptionNoArg, (XtPointer) "true"}
};

/* The fallback resources are used to define the default values for
 * interface items such as the range/detail of the scales.
 */
String fallbackResources[] = { 
    "*EnableAccessXToggle.set: True",
    "*SoundOnOffToggle.set: True",
    "*ShowStatusToggle.set: False",
    "*TimeOutToggle.set: False",
    "*TimeOutScale.minimum: 1",
    "*TimeOutScale.maximum: 10",
    "*TimeOutScale.decimalPoints: 0",
    "*TimeOutScale.value: 2",
    "*StickyKeysToggle.set: False",
    "*MouseKeysToggle.set: False",
    "*ToggleKeysToggle.set: False",
    "*RepeatKeysToggle.set: True",
    "*SlowKeysToggle.set: False",
    "*BounceKeysToggle.set: False",
    "*StickyTwoKeysToggle.set: True",
    "*StickyModSoundToggle.set: True",
    "*MouseMaxSpeedScale.minimum: 1",
    "*MouseMaxSpeedScale.maximum: 500",
    "*MouseMaxSpeedScale.decimalPoints: 0",
    "*MouseMaxSpeedScale.value: 300",
    "*MouseAccelScale.minimum: 1",
    "*MouseAccelScale.maximum: 40",
    "*MouseAccelScale.decimalPoints: 1",
    "*MouseAccelScale.value: 20",
    "*MouseDelayScale.minimum: 1",
    "*MouseDelayScale.maximum: 40",
    "*MouseDelayScale.decimalPoints: 1",
    "*MouseDelayScale.value: 3",
    "*KRGRepeatRateScale.minimum: 1",
    "*KRGRepeatRateScale.maximum: 400",
    "*KRGRepeatRateScale.decimalPoints: 2",
    "*KRGRepeatRateScale.value: 5",
    "*KRGRepeatDelayScale.minimum: 1",
    "*KRGRepeatDelayScale.maximum: 400",
    "*KRGRepeatDelayScale.decimalPoints: 2",
    "*KRGRepeatDelayScale.value: 66",
    "*SlowKeysOnPressToggle.set: True",
    "*SlowKeysOnAcceptToggle.set: True",
    "*KRGSlowKeysDelayScale.minimum: 1",
    "*KRGSlowKeysDelayScale.maximum: 40",
    "*KRGSlowKeysDelayScale.decimalPoints: 1",
    "*KRGSlowKeysDelayScale.value: 3",
    "*KRGDebounceScale.minimum: 1",
    "*KRGDebounceScale.maximum: 40",
    "*KRGDebounceScale.decimalPoints: 1",
    "*KRGDebounceScale.value: 3",
    NULL
};

#define SECSTOMILLIS(x) (int)((float)x * (float)1000)
#define MILLISTOSECS(x) (float)((float)x / (float)1000)
#define NOZEROS(x) if (x <= 0) x = 1;

/************************************************************************/
/*                                                                      */
/* UpdateWidgetSensitivity                                              */
/*                                                                      */
/************************************************************************/
void UpdateWidgetSensitivity(void)
{
   int i;
   Arg argList[2];

   /* If the enable toggle is turned off then grey out everything */
   if (XmToggleButtonGadgetGetState(widgets[ENABLE_ACCESSX_TGL])) {
     XtSetArg(argList[0], XmNsensitive, True);
   }
   else {
     XtSetArg(argList[0], XmNsensitive, False);
   }

   for (i = TOGGLE_WIDGETS_MIN; i <= TOGGLE_WIDGETS_MAX; i++) {
      if (i != ENABLE_ACCESSX_TGL) {
         XtSetValues(widgets[i], argList, 1);
      }
   }

   for (i = SCALE_WIDGETS_MIN; i <= SCALE_WIDGETS_MAX; i++) {
      XtSetValues(widgets[i], argList, 1);
   }

   for (i = LABEL_WIDGETS_MIN; i <= LABEL_WIDGETS_MAX; i++) {
      XtSetValues(widgets[i], argList, 1);
   }
       
   /* Toggle Sensitivity of TimeOut Scale based upon ENABLE_ACCESS
    * as well as the TimeOut Toggle.
    */
   if (XmToggleButtonGadgetGetState(widgets[TIME_OUT_TGL]) &&
       XmToggleButtonGadgetGetState(widgets[ENABLE_ACCESSX_TGL]))
       XtSetArg(argList[0], XmNsensitive, True);
   else
       XtSetArg(argList[0], XmNsensitive, False);

   XtSetValues(widgets[TIME_OUT_LBL],argList,1);
   XtSetValues(widgets[TIME_OUT_SCL],argList,1);

} /* UpdateWidgetSensitivity */

/************************************************************************/
/*                                                                      */
/* ConvertScaleValueToUnits                                             */
/*                                                                      */
/*	Take a scale reading and a decimal point reading and returns    */
/* 	a floating point number which is the value the scale really     */
/*	represents. The purpose of this function is to easily convert   */
/*	between both representations independent of what the value      */
/*	actually represents.                                            */
/*                                                                      */
/************************************************************************/
float ConvertScaleValueToUnits(int value, short decimalPoints)
{
    int i, j;

    j = 1;
    for (i = 0; i < decimalPoints; i++) 
    {
	j *= 10;
    }

    return ((float)value / (float)j);
}

/************************************************************************/
/*                                                                      */
/* ConvertUnitsToScaleValue                                             */
/*                                                                      */
/*	Take a floating point value and a decimal points reading and    */
/*	returns an adjusted integer value which may be used as a value  */
/*      for a scale widget. The purpose of this function is to easily   */
/*      convert between both representation independent of what the     */
/*      value actually represents.                                      */
/*                                                                      */
/************************************************************************/
int ConvertUnitsToScaleValue(float value, short decimalPoints)
{
    int i, j;

    j = 1;
    for (i = 0; i < decimalPoints; i++) 
    {
	j *= 10;
    }
    
    return ((int)(value * (float)j));
}

/************************************************************************/
/*                                                                      */
/* SpaceAndSizeButtons		                                        */
/*                                                                      */
/************************************************************************/
void SpaceAndSizeButtons(Widget		*widgets,
			 int		numWidgets)
{
    Arg argList[5];
    int i;
    int widest = 0;
    Widget currentWidget;
    
    /* Find the widest button.
     */
    for (i = 0; i < numWidgets; i++) 
    {
        if (XtWidth(widgets[i]) > widest)
            widest = XtWidth(widgets[i]);
    }

    /*  Equally space the buttons.
     */
    XtSetArg(argList[0], XmNwidth, widest);
    XtSetArg(argList[1], XmNleftOffset, 0);
    XtSetArg(argList[2], XmNleftAttachment, XmATTACH_POSITION);
    XtSetArg(argList[3], XmNleftPosition, 0);
    for (i = 0; i < numWidgets; i++) 
    {
	argList[1].value = widest * (i - numWidgets) / (numWidgets + 1);
        argList[3].value = 100 * (i + 1) / (numWidgets + 1);
	XtSetValues (widgets[i], argList, 4);
    }

} /* SpaceAndSizeButtons */

/************************************************************************/
/*   									*/
/* ConcatModifiersString						*/
/*									*/
/************************************************************************/
void ConcatModifiersString(XmString *modifiersString,
			   XmString newString,
			   Boolean  locked)
{
    XmString tempString,leftBracket,rightBracket;
    
    if (*modifiersString != NULL)
    {
	tempString = XmStringConcat(*modifiersString,plusString);
	XmStringFree(*modifiersString);
    }
    else
	tempString = XmStringCreate("",XmSTRING_DEFAULT_CHARSET);

    if (locked)
    {
	leftBracket = XmStringCreate("[",XmSTRING_DEFAULT_CHARSET);
	rightBracket = XmStringCreate("]",XmSTRING_DEFAULT_CHARSET);
    }
    else
    {
	leftBracket = XmStringCreate("",XmSTRING_DEFAULT_CHARSET);
	rightBracket = XmStringCreate("",XmSTRING_DEFAULT_CHARSET);
    }

    *modifiersString = XmStringConcat(tempString,leftBracket);
    XmStringFree(tempString);
    tempString = XmStringConcat(*modifiersString,newString);
    XmStringFree(*modifiersString);
    *modifiersString = XmStringConcat(tempString,rightBracket);
    XmStringFree(tempString);
    XmStringFree(leftBracket);
    XmStringFree(rightBracket);    
}

/************************************************************************/
/*                                                                      */
/* UnmapStatusWindow							*/
/*									*/
/************************************************************************/
void UnmapStatusWindow(Widget 	     widget,
		       int    	     *dummy,
		       unsigned long reason)
{
    if (widget == statusTopLevel)
    {
	statusTopLevel = NULL;
	XmToggleButtonSetState(widgets[SHOW_STATUS_TGL],False,False);
    }
    else
	exit(0);
}

/************************************************************************/
/*                                                                      */
/* CreateAndMapStatusWindow	                                        */
/*                                                                      */
/************************************************************************/
void CreateAndMapStatusWindow(void)
{
    XkbDescRec 		*desc;
    char		*modName;
    unsigned char 	mapReturn[5];
    int			i,numButtons;
    Arg 	        argList[1];
    
    if (statusTopLevel == NULL) 
    { 
	statusTopLevel = XtAppCreateShell(NULL,ACCESSX_CLASS,
					  topLevelShellWidgetClass,
					  theDisplay,NULL,0);
 	XtSetArg(argList[0], XtNallowShellResize, TRUE);
        XtSetValues(statusTopLevel,argList,1);

        XmAddProtocolCallback(statusTopLevel,
                              XmInternAtom(XtDisplay(statusTopLevel), 
                                           "WM_PROTOCOLS",0),
                              XmInternAtom(XtDisplay(statusTopLevel), 
					   "WM_DELETE_WINDOW",0),
                              UnmapStatusWindow,NULL);

	MrmFetchWidget(mrmHierarchy, "StatusDialog", statusTopLevel,
		       &statusDialog, &dummyClass);
	
	XtManageChild(statusDialog);

	/* Unmanage rows for buttons that don't exist 
	 */
	numButtons = XGetPointerMapping(theDisplay,mapReturn,5);
	for (i = numButtons; i < 5; i++)
	    XtUnmanageChild(widgets[MB1_BTN + i]);


	if (options.useVmods)
	{
	    desc = XkbGetMap(theDisplay,XkbVirtualModsMask,XkbUseCoreKbd);
	    XkbGetNames(theDisplay,XkbVirtualModNamesMask,desc);

	    for (i=0; i < XkbNumVirtualMods; i++) 
	    {
		if (desc->names->vmods[i]!=None)
		{
		    modName = XGetAtomName(theDisplay,desc->names->vmods[i]);
		    switch(desc->server->vmods[i])
		    {
			case ShiftMapIndex:
			{
			    shiftString = XmStringCreate(modName, 
							 XmSTRING_DEFAULT_CHARSET);
			    break;
			}

			case LockMapIndex:
			{
			    lockString = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}

			case ControlMapIndex:
			{
			    controlString = XmStringCreate(modName, 
							   XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			case Mod1MapIndex:
			{
			    mod1String = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			case Mod2MapIndex:
			{
			    mod2String = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			case Mod3MapIndex:
			{
			    mod3String = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			case Mod4MapIndex:
			{
			    mod4String = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			case Mod5MapIndex:
			{
			    mod5String = XmStringCreate(modName, 
							XmSTRING_DEFAULT_CHARSET);
			    break;
			}
		    
			default:	break;
		    }
		    
		    XFree(modName);
		}
	    }
	}
	XtRealizeWidget(statusTopLevel);
   }

   XtMapWidget(statusTopLevel);
   
} /* CreateAndMapStatusWindow */

/************************************************************************/
/*   									*/
/* SetStatusFromState							*/
/*									*/
/************************************************************************/
void SetStatusFromState(void)
{
    Arg         argList[10];
    XkbStateRec	state;
    XkbDescRec 	*desc;
    XmString	modifiersString;
    
    modifiersString = NULL;

    if (!XmToggleButtonGadgetGetState(widgets[SHOW_STATUS_TGL]))
    {
        if (statusTopLevel)
	    XtUnmapWidget(statusTopLevel);
	return;
    }

    CreateAndMapStatusWindow();

    /* Set the current mouse button
     */
    desc = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
    XkbGetControls(theDisplay,XkbAllControlsMask,desc);

    XtSetArg(argList[0], XmNmenuHistory, 
	     widgets[MB1_BTN - 1 + desc->ctrls->mk_dflt_btn]);
    XtSetValues(widgets[DEFAULT_BUTTON_MENU], argList, 1);

    /* Now set the modifiers+buttons label.
     */
    XkbGetState(theDisplay,XkbUseCoreKbd,&state);

    if ((state.base_mods & ShiftMask) || (state.latched_mods & ShiftMask))
	ConcatModifiersString(&modifiersString,shiftString,FALSE);
    else if (state.locked_mods & ShiftMask) 
	ConcatModifiersString(&modifiersString,shiftString,TRUE);

    if ((state.base_mods & LockMask) || (state.latched_mods & LockMask))
	ConcatModifiersString(&modifiersString,lockString,FALSE);
    else if (state.locked_mods & LockMask) 
	ConcatModifiersString(&modifiersString,lockString,TRUE);

    if ((state.base_mods & ControlMask) || (state.latched_mods & ControlMask))
	ConcatModifiersString(&modifiersString,controlString,FALSE);
    else if (state.locked_mods & ControlMask) 
	ConcatModifiersString(&modifiersString,controlString,TRUE);

    if ((state.base_mods & Mod1Mask) || (state.latched_mods & Mod1Mask))
	ConcatModifiersString(&modifiersString,mod1String,FALSE);
    else if (state.locked_mods & Mod1Mask) 
	ConcatModifiersString(&modifiersString,mod1String,TRUE);

    if ((state.base_mods & Mod2Mask) || (state.latched_mods & Mod2Mask))
	ConcatModifiersString(&modifiersString,mod2String,FALSE);
    else if (state.locked_mods & Mod2Mask) 
	ConcatModifiersString(&modifiersString,mod2String,TRUE);

    if ((state.base_mods & Mod3Mask) || (state.latched_mods & Mod3Mask))
	ConcatModifiersString(&modifiersString,mod3String,FALSE);
    else if (state.locked_mods & Mod3Mask) 
	ConcatModifiersString(&modifiersString,mod3String,TRUE);

    if ((state.base_mods & Mod4Mask) || (state.latched_mods & Mod4Mask))
	ConcatModifiersString(&modifiersString,mod4String,FALSE);
    else if (state.locked_mods & Mod4Mask) 
	ConcatModifiersString(&modifiersString,mod4String,TRUE);

    if ((state.base_mods & Mod5Mask) || (state.latched_mods & Mod5Mask))
	ConcatModifiersString(&modifiersString,mod5String,FALSE);
    else if (state.locked_mods & Mod5Mask) 
	ConcatModifiersString(&modifiersString,mod5String,TRUE);

    if (state.ptr_buttons & Button1Mask) 
	ConcatModifiersString(&modifiersString,mb1String,FALSE);

    if (state.ptr_buttons & Button2Mask) 
	ConcatModifiersString(&modifiersString,mb2String,FALSE);

    if (state.ptr_buttons & Button3Mask) 
	ConcatModifiersString(&modifiersString,mb3String,FALSE);

    if (state.ptr_buttons & Button4Mask) 
	ConcatModifiersString(&modifiersString,mb4String,FALSE);

    if (state.ptr_buttons & Button5Mask) 
	ConcatModifiersString(&modifiersString,mb5String,FALSE);

    if (modifiersString != NULL)
    {
	XtSetArg(argList[0],XmNlabelString,modifiersString);
	XtSetValues(widgets[MODIFIERS_LBL],argList,1);
	XmStringFree(modifiersString);
    }
    else
    {
	XtSetArg(argList[0],XmNlabelString,noneString);
	XtSetValues(widgets[MODIFIERS_LBL],argList,1);
    }
    
    if (XmToggleButtonGadgetGetState(widgets[MOUSE_KEYS_TGL]) &&
        !XtIsManaged(widgets[DEFAULT_BUTTON_MENU]))
    {
        XtManageChild(widgets[DEFAULT_BUTTON_MENU]);
        XtSetArg(argList[0],XmNbottomAttachment,XmATTACH_FORM);
	XtSetValues(widgets[DEFAULT_BUTTON_MENU],argList,1);
        XtSetArg(argList[0],XmNleftAttachment,XmATTACH_WIDGET);
	XtSetArg(argList[1],XmNleftWidget,widgets[DEFAULT_BUTTON_MENU]);
	XtSetValues(widgets[STATUS_FRAME],argList,2);
    }
    else if (!XmToggleButtonGadgetGetState(widgets[MOUSE_KEYS_TGL]) &&
	     XtIsManaged(widgets[DEFAULT_BUTTON_MENU]))
    {
        XtSetArg(argList[0],XmNleftAttachment,XmATTACH_FORM);
        XtSetArg(argList[1],XmNbottomAttachment,XmATTACH_FORM);
	XtSetValues(widgets[STATUS_FRAME],argList,2);
        XtUnmanageChild(widgets[DEFAULT_BUTTON_MENU]);
    }

} /* SetStatusFromState */

/************************************************************************/
/*									*/
/* SetControlsFromState							*/
/*									*/
/*	Sets the user interface state from the state of the extension.	*/
/*									*/
/************************************************************************/
void SetControlsFromState(void)
{
    XkbDescRec 	*desc;
    int i,minimum,maximum,scaleVal;
    short decimalPoints;
    Arg argList[3];

    desc = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
    XkbGetControls(theDisplay,XkbAllControlsMask,desc);

    /********************************************************************/
    /*									*/
    /* Global values:  Enable AccessX, Beep on Feature Use, TimeOut	*/
    /*							 		*/
    /********************************************************************/
    if (desc->ctrls->enabled_ctrls&XkbAccessXKeysMask)
	XmToggleButtonSetState(widgets[ENABLE_ACCESSX_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[ENABLE_ACCESSX_TGL], False, False);

    if (XkbAX_NeedFeedback(desc->ctrls,XkbAX_FeatureFBMask))
	XmToggleButtonSetState(widgets[ONOFF_SOUND_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[ONOFF_SOUND_TGL], False, False);

    if (desc->ctrls->enabled_ctrls&XkbAccessXTimeoutMask)
    {
	XtSetArg(argList[0], XmNsensitive, True);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);	
	XmToggleButtonSetState(widgets[TIME_OUT_TGL], True, False);
    }
    else
    {
	XtSetArg(argList[0], XmNsensitive, False);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);	
	XmToggleButtonSetState(widgets[TIME_OUT_TGL], False, False);
    }
    
    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[TIME_OUT_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(desc->ctrls->ax_timeout/60, 
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);
    }
    XmScaleSetValue(widgets[TIME_OUT_SCL],scaleVal);
    
    /********************************************************************/
    /*									*/
    /* Keyboard Control: StickyKeys, MouseKeys, ToggleKeys		*/
    /*							 		*/
    /********************************************************************/
    if (desc->ctrls->enabled_ctrls&XkbStickyKeysMask)
	XmToggleButtonSetState(widgets[STICKY_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[STICKY_KEYS_TGL], False, False);
    
    if (desc->ctrls->enabled_ctrls&XkbMouseKeysMask)
	XmToggleButtonSetState(widgets[MOUSE_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[MOUSE_KEYS_TGL], False, False);

    if (XkbAX_NeedFeedback(desc->ctrls,XkbAX_IndicatorFBMask))
	XmToggleButtonSetState(widgets[TOGGLE_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[TOGGLE_KEYS_TGL], False, False);
    
    /********************************************************************/
    /*									*/
    /* Keyboard Response: RepeatKeys, SlowKeys, BounceKeys		*/
    /*							 		*/
    /********************************************************************/
    if (desc->ctrls->enabled_ctrls&XkbRepeatKeysMask)
	XmToggleButtonSetState(widgets[REPEAT_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[REPEAT_KEYS_TGL], False, False);
    
    if (desc->ctrls->enabled_ctrls&XkbSlowKeysMask)
	XmToggleButtonSetState(widgets[SLOW_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[SLOW_KEYS_TGL], False, False);
    
    if (desc->ctrls->enabled_ctrls&XkbBounceKeysMask)
	XmToggleButtonSetState(widgets[BOUNCE_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[BOUNCE_KEYS_TGL], False, False);

    /********************************************************************/
    /*									*/
    /* StickyKeys Settings:  Auto Off, Modifiers Beep			*/
    /*							 		*/
    /********************************************************************/
    if (XkbAX_NeedOption(desc->ctrls,XkbAX_TwoKeysMask))
	XmToggleButtonSetState(widgets[STICKY_TWO_KEYS_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[STICKY_TWO_KEYS_TGL], False, False);
    
    if (XkbAX_NeedFeedback(desc->ctrls,XkbAX_StickyKeysFBMask))
	XmToggleButtonSetState(widgets[STICKY_MOD_SOUND_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[STICKY_MOD_SOUND_TGL], False, False);
        
    /********************************************************************/
    /*									*/
    /* MouseKeys Settings:  Max Speed, Acceleration, Delay		*/
    /*							 		*/
    /********************************************************************/
    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[MOUSE_MAX_SPEED_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(desc->ctrls->mk_max_speed,
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[MOUSE_MAX_SPEED_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[MOUSE_MAX_SPEED_SCL],argList,1);
    }
    XmScaleSetValue(widgets[MOUSE_MAX_SPEED_SCL],scaleVal);

    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[MOUSE_ACCEL_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(MILLISTOSECS(desc->ctrls->mk_time_to_max),
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[MOUSE_ACCEL_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[MOUSE_ACCEL_SCL],argList,1);
    }
    XmScaleSetValue(widgets[MOUSE_ACCEL_SCL],scaleVal);

    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[MOUSE_DELAY_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(MILLISTOSECS(desc->ctrls->mk_delay),
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[MOUSE_DELAY_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[MOUSE_DELAY_SCL],argList,1);
    }
    XmScaleSetValue(widgets[MOUSE_DELAY_SCL],scaleVal);

    /********************************************************************/
    /*									*/
    /* RepeatKeys Settings:  Delay, Rate				*/
    /*							 		*/
    /********************************************************************/
    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[KRG_REPEAT_RATE_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue((float) MILLISTOSECS(desc->ctrls->repeat_interval), 
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[KRG_REPEAT_RATE_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[KRG_REPEAT_RATE_SCL],argList,1);
    }
    XmScaleSetValue(widgets[KRG_REPEAT_RATE_SCL],scaleVal);

    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[KRG_REPEAT_DELAY_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(MILLISTOSECS(desc->ctrls->repeat_delay), 
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[KRG_REPEAT_DELAY_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[KRG_REPEAT_DELAY_SCL],argList,1);
    }
    XmScaleSetValue(widgets[KRG_REPEAT_DELAY_SCL],scaleVal);

    /********************************************************************/
    /*									*/
    /* SlowKeys Settings:  Beep On Press, Beep on Accept, Delay		*/
    /*							 		*/
    /********************************************************************/
    if (XkbAX_NeedFeedback(desc->ctrls,XkbAX_SKPressFBMask))
	XmToggleButtonSetState(widgets[KRG_PRESS_SOUND_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[KRG_PRESS_SOUND_TGL], False, False);

    if (XkbAX_NeedFeedback(desc->ctrls,XkbAX_SKAcceptFBMask))
	XmToggleButtonSetState(widgets[KRG_ACCEPT_SOUND_TGL], True, False);
    else
	XmToggleButtonSetState(widgets[KRG_ACCEPT_SOUND_TGL], False, False);

    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[KRG_SLOW_DELAY_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(MILLISTOSECS(desc->ctrls->slow_keys_delay), 
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[KRG_SLOW_DELAY_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[KRG_SLOW_DELAY_SCL],argList,1);
    }
    XmScaleSetValue(widgets[KRG_SLOW_DELAY_SCL],scaleVal);
    
    /********************************************************************/
    /*									*/
    /* BounceKeys Settings:  Delay					*/
    /*							 		*/
    /********************************************************************/
    XtSetArg(argList[0], XmNdecimalPoints,&decimalPoints);
    XtSetArg(argList[1], XmNminimum, &minimum);
    XtSetArg(argList[2], XmNmaximum, &maximum);
    XtGetValues(widgets[KRG_DEBOUNCE_SCL],argList,3);
    scaleVal = ConvertUnitsToScaleValue(MILLISTOSECS(desc->ctrls->debounce_delay), 
					decimalPoints);

    if (scaleVal > maximum)
    {
	XtSetArg(argList[0], XmNmaximum, scaleVal);
	XtSetValues(widgets[KRG_DEBOUNCE_SCL],argList,1);
    }
    else if (scaleVal < minimum)
    {
	XtSetArg(argList[0], XmNminimum, scaleVal);
	XtSetValues(widgets[KRG_DEBOUNCE_SCL],argList,1);
    }
    XmScaleSetValue(widgets[KRG_DEBOUNCE_SCL],scaleVal);

    SetStatusFromState();
    UpdateWidgetSensitivity();
        
} /* SetControlsFromState */

/************************************************************************/
/*									*/
/* SetDefaults					  		        */
/*									*/
/*	Sets the default state of the extension.                        */
/*									*/
/************************************************************************/
void SetDefaults(void)
{
    unsigned long	which;
    CARD32 		enabled,changeEnabled;
    XkbDescRec 		*desc;
    
    desc = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
    XkbGetControls(theDisplay,XkbAllControlsMask,desc);

    which = XkbAccessXKeysMask | XkbMouseKeysAccelMask | XkbRepeatKeysMask | 
            XkbSlowKeysMask | XkbBounceKeysMask;

    desc->ctrls->ax_options |= XkbAX_TwoKeysMask|XkbAX_StickyKeysFBMask|
	                       XkbAX_SKPressFBMask|XkbAX_SKAcceptFBMask;

    desc->ctrls->mk_interval = 10;
    desc->ctrls->mk_curve = 50;
    desc->ctrls->mk_max_speed = 300;
    desc->ctrls->mk_time_to_max = 2000;
    desc->ctrls->mk_delay = 300;
    desc->ctrls->repeat_interval = 40;
    desc->ctrls->repeat_delay = 660;
    desc->ctrls->slow_keys_delay = 300;
    desc->ctrls->debounce_delay = 300;
    XkbSetControls(theDisplay,which,desc);
    SetControlsFromState();
    
} /* SetDefaults */

/************************************************************************/
/*									*/
/* SetStateFromControls							*/
/*									*/
/*	Sets the state of the extension according to the state of the	*/
/*	widgets in the interface.					*/
/*									*/
/************************************************************************/
void SetStateFromControls(void)
{
    unsigned long	which;
    CARD32 		enabled,changeEnabled;
    XkbDescRec 		*desc;
    Arg 		argList[2];
    int 		scaleValue;
    short 		decimalPoints;
    Widget		defaultButton;
    unsigned char	button;
    
    which = XkbAccessXKeysMask | XkbAccessXTimeoutMask |
	    XkbControlsEnabledMask |
	    XkbMouseKeysAccelMask |
	    XkbRepeatKeysMask | XkbSlowKeysMask | XkbBounceKeysMask;

    changeEnabled = XkbAccessXKeysMask |
	            XkbAccessXFeedbackMask |
	            XkbStickyKeysMask | XkbMouseKeysMask | 
		    XkbRepeatKeysMask | XkbSlowKeysMask | XkbBounceKeysMask;

    enabled = XkbAccessXFeedbackMask;
    
    desc = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
    XkbGetControls(theDisplay,XkbAllControlsMask,desc);

    desc->ctrls->ax_options = XkbAX_LatchToLockMask;
    
    /********************************************************************/
    /*									*/
    /* Global values:  Enable AccessX, Beep on Feature Use, TimeOut	*/
    /*							 		*/
    /********************************************************************/
    if (XmToggleButtonGadgetGetState(widgets[ENABLE_ACCESSX_TGL]))
	enabled |= XkbAccessXKeysMask;

    if (XmToggleButtonGadgetGetState(widgets[ONOFF_SOUND_TGL]))
	desc->ctrls->ax_options |= XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask;
    
    if (XmToggleButtonGadgetGetState(widgets[TIME_OUT_TGL]))
    {
	XtSetArg(argList[0], XmNsensitive, True);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);
	enabled |= XkbAccessXTimeoutMask;
    }	    
    else
    {
	XtSetArg(argList[0], XmNsensitive, False);
	XtSetValues(widgets[TIME_OUT_SCL],argList,1);	
    }
    
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[TIME_OUT_SCL],argList,2);
    desc->ctrls->ax_timeout = 60 * ConvertScaleValueToUnits(scaleValue,
							    decimalPoints);
    NOZEROS(desc->ctrls->ax_timeout);
    
    /********************************************************************/
    /*									*/
    /* Keyboard Control: StickyKeys, MouseKeys, ToggleKeys		*/
    /*							 		*/
    /********************************************************************/
    if (XmToggleButtonGadgetGetState(widgets[STICKY_KEYS_TGL]))
    {
	enabled |= XkbStickyKeysMask;
    }
    
    if (XmToggleButtonGadgetGetState(widgets[MOUSE_KEYS_TGL]))
    {
	enabled |= XkbMouseKeysMask;
    }
    
    if (XmToggleButtonGadgetGetState(widgets[TOGGLE_KEYS_TGL]))
	desc->ctrls->ax_options |= XkbAX_IndicatorFBMask;
    
    /********************************************************************/
    /*									*/
    /* Keyboard Response: RepeatKeys, SlowKeys, BounceKeys		*/
    /*							 		*/
    /********************************************************************/
    if (XmToggleButtonGadgetGetState(widgets[REPEAT_KEYS_TGL]))
	enabled |= XkbRepeatKeysMask;

    if (XmToggleButtonGadgetGetState(widgets[SLOW_KEYS_TGL]))
	enabled |= XkbSlowKeysMask;

    if (XmToggleButtonGadgetGetState(widgets[BOUNCE_KEYS_TGL]))
	enabled |= XkbBounceKeysMask;

    /********************************************************************/
    /*									*/
    /* StickyKeys Settings:  Auto Off, Modifiers Beep			*/
    /*							 		*/
    /********************************************************************/
    if (XmToggleButtonGadgetGetState(widgets[STICKY_TWO_KEYS_TGL]))
	desc->ctrls->ax_options |= XkbAX_TwoKeysMask;
    
    if (XmToggleButtonGadgetGetState(widgets[STICKY_MOD_SOUND_TGL]))
	desc->ctrls->ax_options |= XkbAX_StickyKeysFBMask;
        
    /********************************************************************/
    /*									*/
    /* MouseKeys Settings:  Speed Delay, Max Speed			*/
    /*							 		*/
    /********************************************************************/
    desc->ctrls->mk_interval = 10;
    desc->ctrls->mk_curve = 50;

    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[MOUSE_MAX_SPEED_SCL],argList,2);
    desc->ctrls->mk_max_speed = 
	ConvertScaleValueToUnits(scaleValue,decimalPoints);
    NOZEROS(desc->ctrls->mk_max_speed);
    
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[MOUSE_ACCEL_SCL],argList,2);
    desc->ctrls->mk_time_to_max = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->mk_time_to_max);
    
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[MOUSE_DELAY_SCL],argList,2);
    desc->ctrls->mk_delay = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->mk_delay);
    
    /********************************************************************/
    /*									*/
    /* RepeatKeys Settings:  Delay, Rate				*/
    /*							 		*/
    /********************************************************************/
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[KRG_REPEAT_RATE_SCL],argList,2);
    desc->ctrls->repeat_interval = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->repeat_interval);
    
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[KRG_REPEAT_DELAY_SCL],argList,2);
    desc->ctrls->repeat_delay = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->repeat_delay);

    /********************************************************************/
    /*									*/
    /* SlowKeys Settings:  Beep On Press, Beep on Accept, Delay		*/
    /*							 		*/
    /********************************************************************/
    if (XmToggleButtonGadgetGetState(widgets[KRG_PRESS_SOUND_TGL]))
	desc->ctrls->ax_options |= XkbAX_SKPressFBMask;

    if (XmToggleButtonGadgetGetState(widgets[KRG_ACCEPT_SOUND_TGL]))
	desc->ctrls->ax_options |= XkbAX_SKAcceptFBMask;

    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[KRG_SLOW_DELAY_SCL],argList,2);
    desc->ctrls->slow_keys_delay = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->slow_keys_delay);

    /********************************************************************/
    /*									*/
    /* BounceKeys Settings:  Delay					*/
    /*							 		*/
    /********************************************************************/
    XtSetArg(argList[0],XmNvalue,&scaleValue);
    XtSetArg(argList[1],XmNdecimalPoints,&decimalPoints);
    XtGetValues(widgets[KRG_DEBOUNCE_SCL],argList,2);
    desc->ctrls->debounce_delay = 
	SECSTOMILLIS(ConvertScaleValueToUnits(scaleValue,decimalPoints));
    NOZEROS(desc->ctrls->debounce_delay);

    /********************************************************************/
    /*									*/
    /* Default Mouse Button						*/
    /*									*/
    /********************************************************************/
    if (widgets[DEFAULT_BUTTON_MENU])
    {
	XtSetArg(argList[0],XmNmenuHistory,&defaultButton);
	XtGetValues(widgets[DEFAULT_BUTTON_MENU],argList,1);
	for (button = MB1_BTN; button <= MB5_BTN; button++)
	    if (widgets[button] == defaultButton)
	    {
		which |= XkbMouseKeysMask;
		desc->ctrls->mk_dflt_btn = button - MB1_BTN + 1;
		break;
	    }
    }

    /********************************************************************/
    /*									*/
    /* Set the values.							*/
    /*									*/
    /********************************************************************/
    desc->ctrls->enabled_ctrls &= ~changeEnabled;
    desc->ctrls->enabled_ctrls |= (changeEnabled & enabled);
    XkbSetControls(theDisplay,which,desc);

    SetStatusFromState();
    UpdateWidgetSensitivity();
    
} /* SetStateFromControls */

/************************************************************************/
/*									*/
/* SetHelpText								*/
/*									*/
/************************************************************************/
Bool SetHelpText(int id)
{
    int i;

    if (!generalHelp)
    {
	XmString	tempText;
	MrmFetchLiteral(mrmHierarchy, "GeneralHelpString", theDisplay,
			(XtPointer *)&generalHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "StickyHelpString", theDisplay,
			(XtPointer *)&stickyHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "MouseHelpString", theDisplay,
			(XtPointer *)&mouseHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "ToggleHelpString", theDisplay,
			(XtPointer *)&toggleHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "RepeatHelpString", theDisplay,
			(XtPointer *)&repeatHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "SlowHelpString", theDisplay,
			(XtPointer *)&slowHelp, &dummyClass);
	MrmFetchLiteral(mrmHierarchy, "BounceHelpString", theDisplay,
			(XtPointer *)&bounceHelp, &dummyClass);

#ifdef __osf__
	allHelp = XmStringCopy(stickyHelp);
	tempText = XmStringConcat(allHelp,mouseHelp);
	XmStringFree(allHelp);
	allHelp = XmStringConcat(tempText,repeatHelp);
	XmStringFree(tempText);
	tempText = XmStringConcat(allHelp,slowHelp);
	XmStringFree(allHelp);
	allHelp = XmStringConcat(tempText,bounceHelp);
	XmStringFree(tempText);
#else
	allHelp = malloc(strlen(stickyHelp) + strlen(mouseHelp) + 
		strlen(repeatHelp) + strlen(slowHelp) + strlen(bounceHelp));
	if(!allHelp)
	    allHelp = "Please use the Help Menu button to view help topics";
	else
	    sprintf(allHelp, "%s%s%s%s%s", stickyHelp, mouseHelp, repeatHelp,
		slowHelp, bounceHelp);
#endif
    }
    
    switch (id)
    {
	case STICKY_HELP_BTN:
	{
	    helpText = stickyHelp;
	    break;
	}

	case MOUSE_HELP_BTN:
	{
	    helpText = mouseHelp;
	    break;
	}

	case TOGGLE_HELP_BTN:
	{
	    helpText = toggleHelp;
	    break;
	}

	case REPEAT_HELP_BTN:
	{
	    helpText = repeatHelp;
	    break;
	}

	case SLOW_HELP_BTN:
	{
	    helpText = slowHelp;
	    break;
	}

	case BOUNCE_HELP_BTN:
	{
	    helpText = bounceHelp;
	    break;
	}

	case SETTINGS_HELP_BTN:
	{
	    helpText = allHelp;
	    break;
	}

	case GENERAL_HELP_BTN:
	{
	    helpText = generalHelp;
	    break;
	}

	default:	break;
    }

    if (helpText)
    {
	XtUnmanageChild(widgets[HELP_TEXT]);
#ifdef __osf__
	DXmCSTextSetString(widgets[HELP_TEXT],emptyString);
	DXmCSTextSetString(widgets[HELP_TEXT],helpText);
#else
	XmTextSetString(widgets[HELP_TEXT],"");
	XmTextSetString(widgets[HELP_TEXT],helpText);
#endif

	helpText = NULL;
	XtManageChild(widgets[HELP_TEXT]);    
    }
    
    return(True);

} /* SetHelpText */

/************************************************************************/
/*                                                                      */
/* ResolveResourceFileName                                              */
/*                                                                      */
/************************************************************************/
char *ResolveResourceFileName(void)
{
    static char fullPath[MAXPATHLEN];
#ifdef VMS
    sprintf(fullPath, "SYS$LOGIN:%s.DAT", ACCESSX_CLASS);
#else
    char *homeDirectory;

    homeDirectory = getenv("HOME");
    
    if (!homeDirectory)
	return(NULL);

    sprintf(fullPath, "%s/%s", homeDirectory, ACCESSX_CLASS);
#endif

    return(fullPath);

} /* ResolveResourceFileName */

/************************************************************************/
/*                                                                      */
/* LoadSettingsFromFile                                                 */
/*                                                                      */
/************************************************************************/
void LoadSettingsFromFile(void)
{
    int i, value;
    short decimalPoints;
    XrmDatabase accessXDatabase;
    char *res, classValueString[256], classDecimalPointsString[256];
    XrmValue resourceValue;
    char decimalPointsClass[256], valueClass[256];
    Arg argList[2];

    accessXDatabase = XrmGetFileDatabase(ResolveResourceFileName());
    if (!accessXDatabase) 
    {
	XtManageChild(loadErrDialog);
	return;
    }
    
    for (i = TOGGLE_WIDGETS_MIN; i <= TOGGLE_WIDGETS_MAX; i++) 
    {
	XrmGetResource(accessXDatabase, 
		       resStrings[i], classStrings[i],
		       &res, &resourceValue);

	if (strcmp(resourceValue.addr, "True") == 0)
	    XmToggleButtonGadgetSetState(widgets[i], True, False);
	else 
	    XmToggleButtonGadgetSetState(widgets[i], False, False);
    }

    for (i = SCALE_WIDGETS_MIN; i <= SCALE_WIDGETS_MAX; i++)  
    {
	sprintf(classValueString, "%s.value", resStrings[i]);
	sprintf(classDecimalPointsString, "%s.decimalPoints", resStrings[i]);

	XrmGetResource(accessXDatabase, 
		       classValueString, classStrings[i],
		       &res, &resourceValue); 
	value = atoi(resourceValue.addr);

	XrmGetResource(accessXDatabase,
		       classDecimalPointsString, classStrings[i],
		       &res, &resourceValue);

	decimalPoints = atoi(resourceValue.addr);

	XtSetArg(argList[0], XmNvalue, value);
	XtSetArg(argList[1], XmNdecimalPoints, decimalPoints);
	XtSetValues(widgets[i], argList, 2);
    }
      
    SetStateFromControls();
    XtManageChild(loadDoneDialog);

} /* LoadSettingsFromFile */

/************************************************************************/
/*                                                                      */
/* SaveSettingsToFile                                                   */
/*                                                                      */
/************************************************************************/
void SaveSettingsToFile(void)
{
    int i, scaleValue;
    short decimalPoints;
    Arg argList[2];
    char scaleValueString[32], decimalPointsString[32];
    char scaleValueRes[256], decimalPointsRes[256];
    char *fname;
    XrmDatabase accessXDatabase = NULL, fileDatabase;

    for (i = TOGGLE_WIDGETS_MIN; i <= TOGGLE_WIDGETS_MAX; i++) 
    {
	if (XmToggleButtonGadgetGetState(widgets[i]))
	    XrmPutStringResource(&accessXDatabase, resStrings[i], "True");
	else
	    XrmPutStringResource(&accessXDatabase, resStrings[i], "False");
    }

    for (i = SCALE_WIDGETS_MIN; i <= SCALE_WIDGETS_MAX; i++) 
    {
	XtSetArg(argList[0], XmNvalue, &scaleValue);
	XtSetArg(argList[1], XmNdecimalPoints, &decimalPoints);
	XtGetValues(widgets[i], argList, 2);

	sprintf(scaleValueString, "%d", scaleValue);
	sprintf(decimalPointsString, "%d", decimalPoints);

	sprintf(scaleValueRes, "%s.%s", resStrings[i], "value");
	sprintf(decimalPointsRes, "%s.%s", resStrings[i], "decimalPoints");

	XrmPutStringResource(&accessXDatabase, 
			     scaleValueRes, scaleValueString);
	XrmPutStringResource(&accessXDatabase, decimalPointsRes, 
			     decimalPointsString);
    }

    fname = ResolveResourceFileName();
    if (!fname) 
    {
	XtManageChild(saveErrDialog);
	return;
    }
    fileDatabase = XrmGetFileDatabase(fname);

    XrmCombineDatabase(accessXDatabase, &fileDatabase, True);
    XrmPutFileDatabase(fileDatabase, fname);

    XtManageChild(saveDoneDialog);

} /* SaveSettingsToFile */

/************************************************************************/
/*									*/
/* StoreSettingsWindowToDatabase					*/
/*									*/
/************************************************************************/
void StoreSettingsWindowToDatabase(void)
{
    int i, scaleValue;
    short decimalPoints;
    Arg argList[2];
    char scaleValueString[32], decimalPointsString[32];
    char scaleValueRes[256], decimalPointsRes[256];
   
    settingsWindowDatabase = NULL;

    for (i = SETTINGS_TOGGLE_WIDGETS_MIN; i<=SETTINGS_TOGGLE_WIDGETS_MAX; i++)
    {	
	if (XmToggleButtonGadgetGetState(widgets[i]))
	    XrmPutStringResource(&settingsWindowDatabase, 
				 resStrings[i], "True");
       else
	   XrmPutStringResource(&settingsWindowDatabase, 
				resStrings[i], "False");
    }

    for (i = SCALE_WIDGETS_MIN; i <= SCALE_WIDGETS_MAX; i++) 
    {
	if (i == TIME_OUT_SCL)
	    continue;

	XtSetArg(argList[0], XmNvalue, &scaleValue);
	XtSetArg(argList[1], XmNdecimalPoints, &decimalPoints);
	XtGetValues(widgets[i], argList, 2);

	sprintf(scaleValueString, "%d", scaleValue);
	sprintf(decimalPointsString, "%d", decimalPoints);

	sprintf(scaleValueRes, "%s.%s", resStrings[i], "value");
	sprintf(decimalPointsRes, "%s.%s", resStrings[i], "decimalPoints");

	XrmPutStringResource(&settingsWindowDatabase, 
			     scaleValueRes,scaleValueString);
	XrmPutStringResource(&settingsWindowDatabase, 
			     decimalPointsRes,decimalPointsString);
    }

} /* StoreSettingsWindowToDatabase */

/************************************************************************/
/*									*/
/* RestoreSettingsWindowFromDatabase					*/
/*									*/
/************************************************************************/
void RestoreSettingsWindowFromDatabase(void)
{
    int i, value;
    short decimalPoints;
    char *res, classValueString[256], classDecimalPointsString[256];
    XrmValue resourceValue;
    char decimalPointsClass[256], valueClass[256];
    Arg argList[2];

    for (i = SETTINGS_TOGGLE_WIDGETS_MIN; i<=SETTINGS_TOGGLE_WIDGETS_MAX; i++)
    {
	XrmGetResource(settingsWindowDatabase, 
		       resStrings[i], classStrings[i],
		       &res, &resourceValue);

	if (strcmp(resourceValue.addr, "True") == 0)
	    XmToggleButtonGadgetSetState(widgets[i], True, False);
	else
	    XmToggleButtonGadgetSetState(widgets[i], False, False);
    }

    for (i = SCALE_WIDGETS_MIN; i <= SCALE_WIDGETS_MAX; i++)
    {
	if (i == TIME_OUT_SCL)
	    continue;

	sprintf(classValueString, "%s.value", resStrings[i]);
	sprintf(classDecimalPointsString, "%s.decimalPoints", resStrings[i]);

	XrmGetResource(settingsWindowDatabase, 
		       classValueString, classStrings[i],
		       &res, &resourceValue);

	value = atoi(resourceValue.addr);
	XrmGetResource(settingsWindowDatabase,
		       classDecimalPointsString,
		       classStrings[i], &res, &resourceValue);

	decimalPoints = atoi(resourceValue.addr);

	XtSetArg(argList[0], XmNvalue, value);
	XtSetArg(argList[1], XmNdecimalPoints, decimalPoints);
	XtSetValues(widgets[i], argList, 2);
    }

} /* RestoreSettingsWindowFromDatabase */

/************************************************************************/
/*									*/
/* CreateProc								*/
/*									*/
/*	Procedure called when a widget is fetched from Mrm.		*/
/*									*/
/************************************************************************/
void CreateProc(Widget 		widget, 
		int		*id, 
		unsigned long	reason)
{
    widgets[*id] = widget;

} /* CreateProc */

/************************************************************************/
/*									*/
/* ActivateProc								*/
/*									*/
/*	Procedure called when a widget is activated. 			*/
/*									*/
/************************************************************************/
void ActivateProc(Widget 		widget, 
		  int			*id, 
		  XmAnyCallbackStruct	*callbackData)
{
    Arg argList[10];

    switch (*id) 
    {
	case EXIT_BTN:
	{
	    exit(0);
	}
	
	case LOAD_BTN:
	{
	    LoadSettingsFromFile();
	    break;
	}

	case SAVE_BTN:
	{
	    SaveSettingsToFile();
	    break;
	}

	case ALL_BTN:
	{
	    StoreSettingsWindowToDatabase();
	    
	    XtUnmanageChild(widgets[STICKYKEYS_FRAME]);
	    XtUnmanageChild(widgets[MOUSEKEYS_FRAME]);
	    XtUnmanageChild(widgets[REPEATKEYS_FRAME]);
	    XtUnmanageChild(widgets[SLOWKEYS_FRAME]);
	    XtUnmanageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtUnmanageChild(widgets[TEST_FRAME]);       

	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_FORM);
	    XtSetValues(widgets[STICKYKEYS_FRAME],argList,1);

	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[STICKYKEYS_FRAME]);
	    XtSetValues(widgets[MOUSEKEYS_FRAME],argList,2);

	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[MOUSEKEYS_FRAME]);
	    XtSetValues(widgets[REPEATKEYS_FRAME],argList,2);

	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[REPEATKEYS_FRAME]);
	    XtSetValues(widgets[SLOWKEYS_FRAME],argList,2);

	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[SLOWKEYS_FRAME]);
	    XtSetValues(widgets[BOUNCEKEYS_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[BOUNCEKEYS_FRAME]);
	    XtSetValues(widgets[TEST_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[TEST_FRAME]);
	    XtSetValues(widgets[SETTINGS_OK_FORM],argList,2);
	    
	    XtManageChild(widgets[STICKYKEYS_FRAME]);
	    XtManageChild(widgets[MOUSEKEYS_FRAME]);
	    XtManageChild(widgets[REPEATKEYS_FRAME]);
	    XtManageChild(widgets[SLOWKEYS_FRAME]);
	    XtManageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtManageChild(widgets[TEST_FRAME]);       
	    XtManageChild(settingsDialog);
	    break;
	}
	
	case STICKYKEYS_BTN:
	{
	    StoreSettingsWindowToDatabase();

	    XtUnmanageChild(widgets[STICKYKEYS_FRAME]);
	    XtUnmanageChild(widgets[MOUSEKEYS_FRAME]);
	    XtUnmanageChild(widgets[REPEATKEYS_FRAME]);
	    XtUnmanageChild(widgets[SLOWKEYS_FRAME]);
	    XtUnmanageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtUnmanageChild(widgets[TEST_FRAME]);       
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_FORM);
	    XtSetValues(widgets[STICKYKEYS_FRAME],argList,1);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[STICKYKEYS_FRAME]);
	    XtSetValues(widgets[TEST_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[TEST_FRAME]);
	    XtSetValues(widgets[SETTINGS_OK_FORM],argList,2);
	    
	    XtManageChild(widgets[STICKYKEYS_FRAME]);
	    XtManageChild(widgets[TEST_FRAME]);       
	    XtManageChild(settingsDialog);
	    break;
	}
	
	case MOUSEKEYS_BTN:
	{
	    StoreSettingsWindowToDatabase();

	    XtUnmanageChild(widgets[STICKYKEYS_FRAME]);
	    XtUnmanageChild(widgets[MOUSEKEYS_FRAME]);
	    XtUnmanageChild(widgets[REPEATKEYS_FRAME]);
	    XtUnmanageChild(widgets[SLOWKEYS_FRAME]);
	    XtUnmanageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtUnmanageChild(widgets[TEST_FRAME]);       
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_FORM);
	    XtSetValues(widgets[MOUSEKEYS_FRAME],argList,1);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[MOUSEKEYS_FRAME]);
	    XtSetValues(widgets[SETTINGS_OK_FORM],argList,2);
	    
	    XtManageChild(widgets[MOUSEKEYS_FRAME]);    
	    XtManageChild(settingsDialog);
	    break;
	}
	
	case KRG_BTN:
	{
	    StoreSettingsWindowToDatabase();

	    XtUnmanageChild(widgets[STICKYKEYS_FRAME]);
	    XtUnmanageChild(widgets[MOUSEKEYS_FRAME]);
	    XtUnmanageChild(widgets[REPEATKEYS_FRAME]);
	    XtUnmanageChild(widgets[SLOWKEYS_FRAME]);
	    XtUnmanageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtUnmanageChild(widgets[TEST_FRAME]);       
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_FORM);
	    XtSetValues(widgets[REPEATKEYS_FRAME],argList,1);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[REPEATKEYS_FRAME]);
	    XtSetValues(widgets[SLOWKEYS_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[SLOWKEYS_FRAME]);
	    XtSetValues(widgets[BOUNCEKEYS_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[BOUNCEKEYS_FRAME]);
	    XtSetValues(widgets[TEST_FRAME],argList,2);
	    
	    XtSetArg(argList[0],XmNtopAttachment,XmATTACH_WIDGET);
	    XtSetArg(argList[1],XmNtopWidget,widgets[TEST_FRAME]);
	    XtSetValues(widgets[SETTINGS_OK_FORM],argList,2);
	    
	    XtManageChild(widgets[REPEATKEYS_FRAME]);
	    XtManageChild(widgets[SLOWKEYS_FRAME]);
	    XtManageChild(widgets[BOUNCEKEYS_FRAME]);
	    XtManageChild(widgets[TEST_FRAME]);
	    XtManageChild(settingsDialog);
	    break;
	}

	case SETTINGS_OK_BTN:
	{
	    XtUnmanageChild(settingsDialog);
	    break;
	}
	
	case SETTINGS_RESET_BTN:
	{
	    RestoreSettingsWindowFromDatabase();
	    SetStateFromControls();
	    break;
	}
	
	case SETTINGS_DEFAULTS_BTN:
	{
	    SetDefaults();
	    break;
	}
	
	case SETTINGS_CANCEL_BTN:
	{
	    RestoreSettingsWindowFromDatabase();
	    SetStateFromControls();
	    XtUnmanageChild(settingsDialog);
	    break;
	}

	case MB1_BTN:
	case MB2_BTN:
	case MB3_BTN:
	case MB4_BTN:
	case MB5_BTN:
	{
	    SetStateFromControls();
	    break;
	}
	
	case SAVE_DONE_OK_BTN:
	case SAVE_DONE_CANCEL_BTN:
	{
	    XtUnmanageChild(saveDoneDialog);
	    break;
	}

	case SAVE_ERR_OK_BTN:
	case SAVE_ERR_CANCEL_BTN:
	{
	    XtUnmanageChild(saveErrDialog);
	    break;
	}

	case LOAD_DONE_OK_BTN:
	case LOAD_DONE_CANCEL_BTN:
	{
	    XtUnmanageChild(loadDoneDialog);
	    break;
	}
	
	case LOAD_ERR_OK_BTN:
	case LOAD_ERR_CANCEL_BTN:
	{
	    XtUnmanageChild(loadErrDialog);
	    break;
	}
	
	case CLOSE_HELP_BTN:
	{
	    XtUnmanageChild(helpDialog);
	    break;
	}
	
	case GENERAL_HELP_BTN:
	case STICKY_HELP_BTN:
	case MOUSE_HELP_BTN:
	case TOGGLE_HELP_BTN:
	case REPEAT_HELP_BTN:
	case SLOW_HELP_BTN:
	case BOUNCE_HELP_BTN:
	case SETTINGS_HELP_BTN:
	{
	    XtManageChild(helpDialog);
	    SetHelpText(*id);
	    break;
	}
	
	case SHOW_STATUS_TGL:
	{
	    SetStatusFromState();
	    break;
	}
	
	default: break;
    }

} /* ActivateProc */

/************************************************************************/
/*									*/
/* ChangeControlProc							*/
/*									*/
/*	Procedure called when one of the widgets indicating the AccessX	*/
/*	state is activated.						*/
/*									*/
/************************************************************************/
void ChangeControlProc(Widget 				widget, 
		       int				*id, 
		       XmToggleButtonCallbackStruct	*callbackData)
{
    SetStateFromControls();
    
} /* ChangeControlProc */

/************************************************************************/
/*									*/
/* FetchUIStrings							*/
/*									*/
/*	Fetch user interface strings from the UID file.			*/
/*									*/
/************************************************************************/
void FetchUIStrings(void)
{
    MrmFetchLiteral(mrmHierarchy, "EmptyString", theDisplay,
                    (XtPointer *)&emptyString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "NoneString", theDisplay,
                    (XtPointer *)&noneString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "PlusString", theDisplay,
                    (XtPointer *)&plusString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "ShiftString", theDisplay,
		    (XtPointer *)&shiftString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "LockString", theDisplay,
		    (XtPointer *)&lockString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "ControlString", theDisplay,
                    (XtPointer *)&controlString, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "Mod1String", theDisplay,
                    (XtPointer *)&mod1String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "Mod2String", theDisplay,
                    (XtPointer *)&mod2String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "Mod3String", theDisplay,
                    (XtPointer *)&mod3String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "Mod4String", theDisplay,
                    (XtPointer *)&mod4String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "Mod5String", theDisplay,
                    (XtPointer *)&mod5String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "MB1String", theDisplay,
                    (XtPointer *)&mb1String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "MB2String", theDisplay,
                    (XtPointer *)&mb2String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "MB3String", theDisplay,
                    (XtPointer *)&mb3String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "MB4String", theDisplay,
                    (XtPointer *)&mb4String, &dummyClass);

    MrmFetchLiteral(mrmHierarchy, "MB5String", theDisplay,
                    (XtPointer *)&mb5String, &dummyClass);

}  /* FetchUIStrings */

/************************************************************************/
/*									*/
/* InitializeUI								*/
/*									*/
/************************************************************************/
void InitializeUI(Widget topLevel)
{
    Arg 	argList[3];
    int 	i;
    Widget 	mainWindow;
    Pixmap      bitmap;
    
    /* Initialize widget array to all NULLS 
     */
    for (i = 0; i < NUM_WIDGETS; i++)
	widgets[i] = NULL;
    
    /* Set the accessx bitmap for the icon
     */
    bitmap = XCreatePixmapFromBitmapData(XtDisplay(topLevel),
					 RootWindowOfScreen(XtScreen(topLevel)),
					 (char *)accessXIcon_bits,
					 accessXIcon_width,
					 accessXIcon_height,
					 1, 0, 1);

    XtSetArg(argList[0], XmNallowShellResize, True);
    XtSetArg(argList[1], XmNiconPixmap, bitmap);
    XtSetValues(topLevel,argList,2);
    
    /* Open up the UID database and fetch/manage the main window 
     */
    if (MrmOpenHierarchyPerDisplay(XtDisplay(topLevel), dbFilenameNum, 
	dbFilenameVec, NULL, &mrmHierarchy) !=MrmSUCCESS) {
	printf("Could not open hierarchy.\n");
	exit(1);
    }
    
    FetchUIStrings();
    
    MrmRegisterNames(regList, regListNum);
    MrmFetchWidget(mrmHierarchy, "AccessXMainWindow", topLevel,
		&mainWindow, &dummyClass);
    XtManageChild(mainWindow);

    MrmFetchWidget(mrmHierarchy, "SettingsDialog", topLevel, &settingsDialog,
                   &dummyClass);
    SpaceAndSizeButtons(&widgets[SETTINGS_OK_BTN],5);
    
    MrmFetchWidget(mrmHierarchy, "SaveDoneDialog", topLevel, &saveDoneDialog,
                   &dummyClass);
    XtUnmanageChild((Widget)XmMessageBoxGetChild(saveDoneDialog,
						 XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild((Widget)XmMessageBoxGetChild(saveDoneDialog,
						 XmDIALOG_HELP_BUTTON));

    MrmFetchWidget(mrmHierarchy, "SaveErrorDialog", topLevel, &saveErrDialog,
                   &dummyClass);
    XtUnmanageChild((Widget)XmMessageBoxGetChild(saveErrDialog,
						 XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild((Widget)XmMessageBoxGetChild(saveErrDialog,
						 XmDIALOG_HELP_BUTTON));

    MrmFetchWidget(mrmHierarchy, "LoadDoneDialog", topLevel, &loadDoneDialog,
                   &dummyClass);
    XtUnmanageChild((Widget)XmMessageBoxGetChild(loadDoneDialog,
						 XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild((Widget)XmMessageBoxGetChild(loadDoneDialog,
						 XmDIALOG_HELP_BUTTON));

    MrmFetchWidget(mrmHierarchy, "LoadErrorDialog", topLevel, &loadErrDialog,
                   &dummyClass);
    XtUnmanageChild((Widget)XmMessageBoxGetChild(loadErrDialog,
						 XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild((Widget)XmMessageBoxGetChild(loadErrDialog,
						 XmDIALOG_HELP_BUTTON));

    MrmFetchWidget(mrmHierarchy, "HelpDialog", topLevel, &helpDialog,
		   &dummyClass);
    SpaceAndSizeButtons(&widgets[CLOSE_HELP_BTN],1);

    if (options.showStatus)
        XmToggleButtonGadgetSetState(widgets[SHOW_STATUS_TGL],True,False);

    if (options.useServer)
        SetControlsFromState();
    else
        SetStateFromControls();

    XtRealizeWidget(topLevel);

} /* InitializeUI */

/************************************************************************/
/*									*/
/*  XkbEventHandler	 						*/
/*									*/
/*  DESCRIPTION:							*/
/*									*/
/*      Handles events generated by the Xkb server extension.		*/
/*									*/
/************************************************************************/
Boolean XkbEventHandler(XEvent *event)
{
    XkbEvent *xkbEv = (XkbEvent *) event;
    
    switch(xkbEv->any.xkb_type)
    {
	case XkbStateNotify:
	{
	    SetStatusFromState();
	    break;
	}
	
	case XkbControlsNotify:
	{
	    SetControlsFromState();
	    break;
	}
	
	default: break;
    }

    return True;
    
} /* XkbEventHandler */

/************************************************************************/
/*									*/
/* InitXkb								*/
/*									*/
/************************************************************************/
Boolean InitXkb(Display *theDisplay)
{
    int	opcode,errorBase,major,minor;
    
    if (!XkbQueryExtension(theDisplay,
			   &opcode,
			   &xkbEventBase,
			   &errorBase,
			   &major,
			   &minor))
	return False;

    if (!XkbUseExtension(theDisplay,&major,&minor))
	return False;

    XkbSelectEvents(theDisplay,
		    XkbUseCoreKbd,
		    XkbAllEventsMask,
		    XkbAllEventsMask);

    XtSetEventDispatcher(theDisplay,
			 xkbEventBase+XkbEventCode,
			 XkbEventHandler);

    return True;
    
} /* InitXkb */

/************************************************************************/
/*									*/
/* main									*/
/*									*/
/************************************************************************/
#if NeedFunctionPrototypes
int main(int	argc, 
		  char	*argv[])
#else
int main(argc, argv)
    int		argc;
    char	*argv[];
#endif
{
    /********************************************************************/
    /*									*/
    /* Initialize the toolkit and Mrm					*/
    /*									*/
    /********************************************************************/
    MrmInitialize();
#ifdef __osf__
    DXmInitialize();
#endif
    topLevel = XtAppInitialize(&appContext, ACCESSX_CLASS, 
			       optionDesc, XtNumber(optionDesc), 
			       &argc, argv, 
			       fallbackResources,
			       NULL, 0);
    
    XtGetApplicationResources(topLevel, (XtPointer)&options, resources,
			      XtNumber(resources), NULL, 0);

    /********************************************************************/
    /*									*/
    /* See if the server has XKB.					*/
    /*									*/
    /********************************************************************/
    theDisplay = XtDisplay(topLevel);
    if (!InitXkb(theDisplay))
    {
	fprintf(stderr,"Could not initialize XKB extension.\n");
	exit(0);
    }

    /********************************************************************/
    /*									*/
    /* Set up the UI and go.						*/
    /*									*/
    /********************************************************************/
    InitializeUI(topLevel);
    XtAppMainLoop(appContext);
    
    /* NOT REACHED */
    exit(0L);
}
