#include <X11/Wc/COPY>

/*
* SCCS_data: %Z% %M%    %I% %E% %U%
*
* Widget Creation Library - WcActCB.c - Actions and Callbacks
*
* Wcl provides equivalent callbacks and actions for many typical application
* behaviors.  These callbacks and actions take string arguments.  If the
* arguments consist as whitespace or comma separated words, then it is
* easier to implement the behavior as an XtActionProc.  If the arguments
* need to be parsed according to more complex rules, then they are implemented
* as callbacks.
*
*******************************************************************************
*/

#ifdef WC_HAS_dlopen_AND_dlsym
#include <dlfcn.h>
#endif

#include <X11/IntrinsicP.h>

#ifdef sun
#include <X11/ObjectP.h>	/* why don't they just use X from mit!?! */
#include <X11/RectObjP.h>
#endif

#include <X11/ShellP.h>
#include <X11/Wc/WcCreateP.h>
#include <X11/StringDefs.h>

/*
*******************************************************************************
* Actions Utilities
*******************************************************************************
*/

/*  -- Invoke XtFunctions using params as widget names
*******************************************************************************
    Many actions are simple wrappers around Xt functions.  These utilities
    make writing such wrapper actions trivial.
*/

#define CAN_BE_GADGET  0
#define MUST_BE_WIDGET 1
#define MUST_BE_SHELL  2

typedef void (*PFVWidget) _((Widget));

static void WcxActProcWidget( reqType, caller, w, params, num_params, Proc )
    int		reqType;	/* some things only work for widgets	*/
    char*	caller;		/* action invoked by translation mgr	*/
    Widget	w;		/* action invoked on this widget	*/
    char**	params;		/* action arguments			*/
    Cardinal*	num_params;	/* count of params			*/
    PFVWidget	Proc;		/* the procedure to be invoked		*/
{
    int		i;
    for ( i = 0 ; i < *num_params ; i++ )
    {
	Widget target = WcFullNameToWidget( w, params[i] );
	if ( target )
	{
	    if (   reqType == CAN_BE_GADGET
	      || ( reqType == MUST_BE_WIDGET && XtIsWidget(target) )
	      || ( reqType == MUST_BE_SHELL  && XtIsShell( target) ) )
	    {
		Proc( target );
	    }
	    else
	    {
		if ( reqType == MUST_BE_WIDGET )
		{
		    WcWARN2( w, caller, "mustBeWidget",
			    "Wcl Warning: %s(%s) - Must be a Widget",
			    caller, params[i] );
		}
		else
		{
		     WcWARN2( w, caller, "mustBeShell",
			     "Wcl Warning: %s(%s) - Must be a Shell widget",
			     caller, params[i] );
		}
	    }
	}
	else
	{
	    WcWARN2( w, caller, "notFound", 
		   "Wcl Warning: %s(%s) - Widget not found",
		    caller, params[i] );
	}
    }
}

/*  -- For invoking XtSomething( widget, int )
*******************************************************************************
    For example, XtPopup, XtSetSensitive, ...
*/

typedef void (*PFVWidInt) _((Widget,int));

static void WcxActProcWidgetInt( reqType, caller, w, params, num_params,
				 Proc, arg )
    int		reqType;
    char*	caller;
    Widget	w;
    char**	params;
    Cardinal*	num_params;
    PFVWidInt	Proc;
    int		arg;		/* arg reqd by Proc */
{
    int		i;
    for ( i = 0 ; i < *num_params ; i++ )
    {
	Widget target = WcFullNameToWidget( w, params[i] );
	if ( target  )
	{
	    if (   reqType == CAN_BE_GADGET
	      || ( reqType == MUST_BE_WIDGET && XtIsWidget(target) )
	      || ( reqType == MUST_BE_SHELL  && XtIsShell( target) ) )
	    {
		Proc( target, arg );
	    }
	    else
	    {
		if ( reqType == MUST_BE_WIDGET )
		{
		    WcWARN2( w, caller, "mustBeWidget",
			    "Wcl Warning: %s(%s) - Must be a Widget",
			    caller, params[i] );
		}
		else
		{
		    WcWARN2( w, caller, "mustBeShell",
			    "Wcl Warning: %s(%s) - Must be a Shell widget",
			    caller, params[i] );
		}
	    }
	}
	else
	{
	    WcWARN2( w, caller, "notFound", 
		   "Wcl Warning: %s(%s) - Widget not found",
		   caller, params[i] );
	}
    }
}

/*
*******************************************************************************
* Actions which actually do something (equivalent CB invokes the ACT)
*******************************************************************************
*/

#define ACTION_DECL(name)			\
void name( w, unused, params, num_params )	\
    Widget	w;				\
    XEvent*	unused;				\
    char**	params;				\
    Cardinal*	num_params;


/*  --	Manage or Unmanage Widgets
*******************************************************************************
	WcManage( widget [, widget] ... )
	WcUnmanage( widget [, widget] ... )
*/
#ifdef XtManageChild
#undef XtManageChild
#endif

/*ARGSUSED*/
ACTION_DECL( WcManageACT )
{
    WcxActProcWidget( CAN_BE_GADGET, "WcManage", w, params, num_params,
		      XtManageChild );
}

#ifdef XtUnmanageChild
#undef XtUnmanageChild
#endif

/*ARGSUSED*/
ACTION_DECL( WcUnmanageACT )
{
    WcxActProcWidget( CAN_BE_GADGET, "WcUnmanage", w, params, num_params,
		      XtUnmanageChild );
}

/*  --	Manage or unamange named children
******************************************************************************* 
	WcManageChildren( parent, child [, child] ... )
	WcUnmanageChildren( parent, child [, child] ... )
*/

typedef void (*PFVWidsCard) _((WidgetList,Cardinal));

static void WcxChgMan( caller, Proc, w, params, num_params )
    char*	caller;
    PFVWidsCard	Proc;
    Widget	w;
    char**	params;
    Cardinal*	num_params;
{
    Widget	parent;
    Widget	children[MAX_CHILDREN];
    int    	i;

    if (*num_params < 2)
    {
	WcWARN1( w, caller, "usage", 
		"Wcl Usage: %s( parent, child [, child] ... )", caller );
	return;
    }

    if ( NULL == (parent = WcFullNameToWidget( w, *params )) )
    {
	WcWARN2( w, caller, "parentNotFound",
		"Wcl Warning: %s( %s, ... ) - parent not found",
		caller, *params );
	return;
    }

    for ( i = 1 ; i < *num_params ; i++ )
    {
	if ( NULL == (children[i-1] = WcChildNameToWidget( parent, params[i] )))
	{
	    WcWARN2( w, caller, "childNotFound",
		"Wcl Warning: %s() - child %s not found", caller, params[i] );
	    return;
	}
    }
    Proc( children, *num_params-1 );
}

#ifdef XtManageChildren
#undef XtManageChildren
#endif

/*ARGSUSED*/
ACTION_DECL( WcManageChildrenACT )
{
    WcxChgMan( "WcManageChildren", XtManageChildren, w, params, num_params );
}

#ifdef XtUnmanageChildren
#undef XtUnmanageChildren
#endif

/*ARGSUSED*/
ACTION_DECL( WcUnmanageChildrenACT )
{
    WcxChgMan( "WcUnmanageChildren", XtUnmanageChildren, w, params, num_params);
}

/*  -- Destroy named children
*******************************************************************************
    WcDestroy( name [, name] ... )
*/

#ifdef XtDestroyWidget
#undef XtDestroyWidget
#endif

/*ARGSUSED*/
ACTION_DECL( WcDestroyACT )
{
    WcxActProcWidget( CAN_BE_GADGET, "WcDestroy", w, params, num_params,
		      XtDestroyWidget );
}

/* -- Change sensitivity of widgets
*******************************************************************************
    WcSetSensitive( name [, name] ... )
    WcSetInsensitive( name [, name] ... )
*/

#ifdef XtSetSensitive
#undef XtSetSensitive
#endif

/*ARGSUSED*/
ACTION_DECL( WcSetSensitiveACT )
{
 WcxActProcWidgetInt( MUST_BE_WIDGET, "WcSetSensitive", w, params, num_params,
		      XtSetSensitive, TRUE );
}

/*ARGSUSED*/
ACTION_DECL( WcSetInsensitiveACT )
{
 WcxActProcWidgetInt( MUST_BE_WIDGET, "WcSetInsensitive", w, params, num_params,
		      XtSetSensitive, FALSE );
}

/* -- Popup and Popdown widgets
*******************************************************************************
    WcPopup( name [, name] ... )		uses XtGrabNone
    WcPopupGrab( name [, name] ... )		uses XtGrabExclusive
    WcPopdown( name [, name] ... )
*/
#ifdef XtPopup
#undef XtPopup
#endif

/*ARGSUSED*/
ACTION_DECL( WcPopupACT )
{
    WcxActProcWidgetInt( MUST_BE_SHELL, "WcPopup", w, params, num_params, 
			 XtPopup, XtGrabNone );
}

/*ARGSUSED*/
ACTION_DECL( WcPopupGrabACT )
{
    WcxActProcWidgetInt( MUST_BE_SHELL, "WcPopupGrab", w, params, num_params,
			 XtPopup, XtGrabExclusive );
}

#ifdef XtPopdown
#undef XtPopdown
#endif

/*ARGSUSED*/
ACTION_DECL( WcPopdownACT )
{
    WcxActProcWidget( MUST_BE_SHELL, "WcPopdown", w, params, num_params,
		      XtPopdown );
}


/*  -- Map or Unmap widgets
*******************************************************************************
    Some old Xt versions do not provide declarations for XtMapWidget()
    and XtUnmapWidget(), they may only be declared as macros.  Wcl provides
    the functions if they do not exist.

    WcMap( name [, name] ... )
    WcUnmap( name [, name] ... )
*/
#ifdef XtMapWidget
#undef XtMapWidget
#endif
#ifdef XtUnmapWidget
#undef XtUnmapWidget
#endif

extern void XtMapWidget _(( Widget ));
extern void XtUnmapWidget _(( Widget ));

/*ARGSUSED*/
ACTION_DECL( WcMapACT )
{
    WcxActProcWidget( MUST_BE_WIDGET, "WcMap", w, params, num_params,
		      XtMapWidget );
}

/*ARGSUSED*/
ACTION_DECL( WcUnmapACT )
{
    WcxActProcWidget( MUST_BE_WIDGET, "WcUnmap", w, params, num_params,
		      XtUnmapWidget );
}

/*  -- Install Accelerators
*******************************************************************************
    Invokes XtInstallAcclerators aand XtInstallAllAccelerators.

    dest - widget that can activate accelerators,
    src  - widget which provides functionality,
	   and defines the accel translation.
*/

/*ARGSUSED*/
ACTION_DECL( WcInstallAcceleratorsACT )
{
    int i;
    Widget dest, src;
    static char* usage = 
"Wcl Usage: WcInstallAccelerators( dest, src [, src] ... )\n\
\tdest - (root of tree) widget that can activate accelerators,\n\
\tsrc  - widget which provides functionality, \n\
\t       and defines the accel translation (accelerators resource)." ;

    if ( *num_params < 2 )
    {
	WcWARN( w, "WcInstallAccelerators", "usage", usage );
	return;
    }
    if ( NULL == (dest = WcFullNameToWidget( w, params[0] )) )
    {
	WcWARN1( w, "WcInstallAccelerators", "destNotFound",
		"Wcl Warning: Destination widget %s not found.", params[0] );
	WcWARN( w, "WcInstallAccelerators", "usage", usage );
	return;
    }
    for ( i = 1 ; i < *num_params ; i++ )
    {
	if ( NULL == (src = WcFullNameToWidget( w, params[i] )) )
	{
	    WcWARN1( w, "WcInstallAccelerators", "srcNotFound",
		    "Wcl Warning: Source widget %s not found.", params[i] );
	    WcWARN( w, "WcInstallAccelerators", "usage", usage );
	}
	else
	{
	    XtInstallAccelerators( dest, src );
	}
    }
}

/*ARGSUSED*/
ACTION_DECL( WcInstallAllAcceleratorsACT )
{
    Widget dest, src;
    static char* usage = 
"Wcl Usage: WcInstallAllAccelerators( dest, src )\n\
\tdest - (root of tree) widget that can activate accelerators,\n\
\tsrc  - root of widget tree, each child widget can provide functionality, \n\
\t       and can define a accel translation (accelerators resource)." ;

    if ( *num_params != 2 )
    {
	WcWARN( w, "WcInstallAllAccelerators", "usage", usage );
	return;
    }

    if ( NULL == (dest = WcFullNameToWidget( w, params[0] )) )
    {
	WcWARN1( w, "WcInstallAllAccelerators", "destNotFound",
		"Wcl Warning: Destination widget %s not found.", params[0] );
	WcWARN( w, "WcInstallAllAccelerators", "usage", usage );
	return;
    }

    if ( NULL == (src = WcFullNameToWidget( w, params[1] )) )
    {
	WcWARN1( w, "WcInstallAccelerators", "srcNotFound",
		"Wcl Warning: Source widget %s not found.", params[1] );
	WcWARN( w, "WcInstallAllAccelerators", "usage", usage );
	return;
    }

    XtInstallAllAccelerators( dest, src );
}


/*  -- Create New Widget Heirarchy
*******************************************************************************
    WcCreateRoot( shell [on: display] [shell [on: display]] ... )
*/

/*ARGSUSED*/
ACTION_DECL( WcCreateRootACT )
{
    int i = 0;
    static char* usage =
"Wcl Usage: WcCreateRoot( shell [on: display] [shell [on: display]] ... )";

    while(*num_params)	/* must have args or give usage message */
    {

	if (WcStrEq(params[i], "on:"))
	    break;			/* give usage message */

	if ( i+2 < *num_params && WcStrEq(params[i+1], "on:") )
	{
	    XtAppContext	app   = XtWidgetToApplicationContext( w );
	    char*		class = WcAppNameToAppClass( params[i] );
#if defined(XtSpecificationRelease) && XtSpecificationRelease > 4
	    int			zero  = 0;
#else
	    Cardinal		zero  = 0;
#endif
	    char*		empty = "";
	    Display* dpy;

	    dpy = XtOpenDisplay( app, 
		params[i+2],		/* display name			*/
		params[i], class,	/* shell name and class		*/
		NULL, 0,		/* no options			*/
		&zero, &empty );	/* no argv - XtOpenDisplay	*/

	    XtFree(class);

	    if ( dpy == NULL)
	    {
		WcWARN1( w, "WcCreateRoot", "openDisplayFailed",
			"Wcl Warning: WcCreateRoot() could not open display %s",
			params[i+2]);
		return;
	    }
	    (void)WcCreateRoot( dpy, params[i] );
	    i+=3;	/* used 3 arguments */
	}
	else
	{
	    (void)WcCreateRoot( XtDisplay(w), params[i] );
	    ++i;
	}
	if (i == *num_params)
	    return;
    }

    /* Something went wrong
    */
    WcWARN( w, "WcCreateRoot", "usage", usage );
}

/*  -- Fork and exec
*******************************************************************************
    WcSpawn( cmd line )
*/

/*ARGSUSED*/
ACTION_DECL( WcSpawnACT )
{
    int    pid;
    int    i;
    char** argv = (char**)XtCalloc(*num_params + 1, sizeof(char*));

    for (i = 0 ; i < *num_params ; i++)
	argv[i] = params[i];

    if ( 0 == (pid = fork()) )
    {
	/* subprocess */
	execvp( params[0], argv );
	fprintf( stderr, 
		"Wcl Error in Subprocess: WcSpawn(%s ...) - Could not execvp.",
		params[0] );
	exit(1);
    }
    if (pid == -1)
    {
	WcWARN1( w, "WcSpawn", "forkFailed", 
		"Wcl Warning: WcSpawn(%s ...) Failed - Could not fork.",
		params[0] );
    }
}

/*  -- Load Resource File into Resource Database
*******************************************************************************
    WcLoadResourceFile( file [, file] )
*/

/*ARGSUSED*/
ACTION_DECL( WcLoadResourceFileACT )
{
    int		i;

    for ( i = 0 ; i < *num_params ; i++ )
	(void)WcLoadResourceFile( w, params[i] );
}

/*  -- Print Tree of named widgets
*******************************************************************************
    WcPrintTree( name [, name] )
*/

/*ARGSUSED*/
ACTION_DECL( WcPrintTreeACT )
{
    if (*num_params == 0)
	WcPrintTree(w);
    else
	WcxActProcWidget( CAN_BE_GADGET, "WcPrintTree", w, params, num_params,
			  WcPrintTree );
}

/*  -- Print resources under a widget instance
*******************************************************************************
    WcDumpResources( name [, name] )
*/

/*ARGSUSED*/
ACTION_DECL( WcDumpResourcesACT )
{
    if (*num_params == 0)
	WcPostCreateDumpResources( w, stderr );
    else
    {
	int i;
	for ( i = 0 ; i < *num_params ; i++ )
	{
	    Widget target = WcFullNameToWidget( w, params[i] );
	    if ( target  )
	    {
		WcPostCreateDumpResources( target, stderr );
	    }
	    else
	    {
		WcWARN1( w, "WcDumpResources", "notFound", 
		   "Wcl Warning: WcDumpResources(%s) - Widget not found",
		    params[i] );
	    }
	}
    }
}

/*  -- Make two or more widgets the same (max) size
*******************************************************************************
    WcSameSize( child, child [,child] ... )
*/

/*ARGSUSED*/
ACTION_DECL( WcSameSizeACT )
{
#define MAX_SAME (BUFSIZ/sizeof(Widget))
    Widget	sameWidgets[MAX_SAME];
    int		i, numWidgets;
    Dimension	maxBorder, maxHeight, maxWidth;
    Arg		arg[10];
    int		argc;

    if ( *num_params < 2 )
    {
	WcWARN1( w, "WcSameSize", "needTwoOrMore",
		"Wcl Warning: WcSameSize(%s) - Need at least two widgets",
		params[0] );
	return;
    }

    for ( i = numWidgets = 0 ; i < *num_params && numWidgets < MAX_SAME ; i++ )
    {
	char*  name   = (char*)params[i];
	Widget widget = WcFullNameToWidget( w, name );

	if ( (Widget)0 != widget )
	{
	    sameWidgets[numWidgets++] = widget;
	}
	else
	{
	    char* thisName = WcWidgetToFullName( w );
	    WcWARN2( w, "WcSameSize", "notFound",
		"Wcl Warning: WcSameSize cannot find widget %s from %s\n",
		name, thisName );
	    XtFree( thisName );
	}
    }

#define MAX_DIM(a,b) ((a)>(b)?(a):(b))
    for ( maxBorder = maxHeight = maxWidth = i = 0  ;  i < numWidgets  ;  i++ )
    {
	maxBorder = MAX_DIM( maxBorder, sameWidgets[i]->core.border_width );
	maxHeight = MAX_DIM( maxHeight, sameWidgets[i]->core.height );
	maxWidth  = MAX_DIM( maxWidth,  sameWidgets[i]->core.width );
    }

    argc = 0;
    XtSetArg( arg[argc], XtNborderWidth, (XtArgVal)maxBorder ); ++argc;
    XtSetArg( arg[argc], XtNheight,      (XtArgVal)maxHeight ); ++argc;
    XtSetArg( arg[argc], XtNwidth,       (XtArgVal)maxWidth  ); ++argc;

    for ( i = 0  ;  i < numWidgets  ;  i++ )
    {
	XtSetValues( sameWidgets[i], arg, argc );
    }

#undef MAX_DIM
#undef MAX_SAME
}

/*  -- Exit the application
*******************************************************************************
    WcExit( [exitVal] )
*/

/*ARGSUSED*/
ACTION_DECL( WcExitACT )
{
    if (*num_params)
	exit( atoi(*params) );
    else
	exit(0);
}

/*
*******************************************************************************
* Callbacks Which Actually Do Something
*******************************************************************************
*/

/*  -- Create Dynamically Created Children from Xrm Database
*******************************************************************************
    WcCreateChildren( parent, child [,child] ... )
    WcCreatePopups(   parent, child [,child] ... )
*/

typedef void (*PVFWidStr) _((Widget,char*));

static void WcxCreateKids ( w, parent_children, caller, CreateFunc )
    Widget	w;
    char*	parent_children;	/* parent + list of named children */
    char*	caller;			/* name of calling CB func 	   */
    PVFWidStr	CreateFunc;
{
    char*	children;
    Widget	parent;
    char	parentName[MAX_XRMSTRING];

    if ( *parent_children == NUL ) 
    {
	WcWARN1( w, caller, "noNames",
		"Wcl Warning: %s( ) - No widget names provided.", caller );
	return;
    }

    children = WcCleanName( parent_children, parentName );

    children = WcSkipWhitespace_Comma( children );

    if ((Widget)NULL == (parent = WcFullNameToWidget( w, parentName )) )
    {
	WcWARN2( w, caller, "parentNotFound",
		"Wcl Warning: %s( %s ...) - Parent widget not found.",
		caller, parentName );
	return;
    }

    if (*children == NUL)
    {
        WcWARN2( w, caller, "noChildNames",
		"Wcl Warning: %s(%s) - No child names provided.",
		caller, parentName );
        return;
    }

    CreateFunc( parent, children );
}

/*ARGSUSED*/
void WcCreateChildrenCB ( w, mom_children, unused )
    Widget	w;
    XtPointer	mom_children;	/* parent + list of named children */
    XtPointer	unused;
{
    WcxCreateKids(w, (char*)mom_children,
			"WcCreateChildren", WcCreateNamedChildren);
}

/*ARGSUSED*/
void WcCreatePopupsCB ( w, mom_children, unused )
    Widget	w;
    XtPointer	mom_children;	/* parent + list of named children */
    XtPointer	unused;
{
    WcxCreateKids(w, (char*)mom_children,
			"WcCreatePopups", WcCreateNamedPopups );
}

/* -- Position a TransientShell in middle of parent widget
*******************************************************************************
    This callback is useful as a popupCallback for transient widgets.
    WcPositionTransient()
*/

/*ARGSUSED*/
void WcPositionTransientCB( w, ignored, unused )
    Widget	w;
    XtPointer	ignored;
    XtPointer	unused;
{
    Widget		 child, transientFor;
    XtWidgetGeometry	 request;

#ifndef XtSpecificationRelease
    ShellWidget		 shell = (ShellWidget)w;
#else
    TransientShellWidget shell = (TransientShellWidget)w;

    if ( XtIsSubclass((Widget)shell,transientShellWidgetClass) )
	transientFor = shell->transient.transient_for;
    else
#endif
	transientFor = XtParent(w);

    if ( !XtIsSubclass((Widget)shell,shellWidgetClass)
      || (NULL == transientFor)
      || (NULL == ( child = shell->composite.children[0] )) )
	return;

    request.x = (Position)(transientFor->core.width  - child->core.width) / 2;
    request.y = (Position)(transientFor->core.height - child->core.height)/ 2;

    if (XtIsRealized (transientFor))
	XtTranslateCoords( transientFor, request.x,  request.y,
					&request.x, &request.y );

    request.request_mode  = ( request.x != shell->core.x ? CWX : 0 );
    request.request_mode |= ( request.y != shell->core.y ? CWY : 0 );

    if ( request.request_mode )
	(void)XtMakeGeometryRequest( (Widget)shell, &request, NULL );
}

/*  -- Set Resource Value on Widget
*******************************************************************************
    The client data argument consists of one or more resource specifications
    in this syntax:

	client_data	::=	res_spec
			|	res_spec_list

	res_spec	::=	targetName.resName: resValue
			|	targetName.resName(resType): resValue

	res_spec_list	::=	(res_spec)
			|	res_spec_list (res_spec)

*/

/*ARGSUSED*/
void WcSetValueCB ( w, name_res_resType_resVal, unused )
    Widget	w;  
    XtPointer	name_res_resType_resVal;
    XtPointer	unused;
{
    WcSetValue( w, (char*)name_res_resType_resVal );
}

/*  -- WcTraceCB
*******************************************************************************
    Prints out the wiget pathname of the invoking wiget, and an optional
    annotation on stderr.
*/

/*ARGSUSED*/
void WcTraceCB ( w, annotation, unused )
    Widget	w;
    XtPointer	annotation;	/* client data, traceback annotation */
    XtPointer	unused;
{
    char* name = WcWidgetToFullName( w );

    WcPrint( "Wcl Trace for ", name, ": ", (char*)annotation, NULL );

    XtFree( name );
}

/*  -- Invoke shell command
*******************************************************************************
    Call system().
*/

/*ARGSUSED*/
void WcSystemCB ( w, shellCmdString, unused )
    Widget	w;
    XtPointer	shellCmdString;
    XtPointer	unused;
{
    system( (char*)shellCmdString );
}

/*  -- Add and Remove Callbacks
*******************************************************************************
    WcAddCallbacks(    widget callbackName CallbackProc( args ) ... )
    WcRemoveCallbacks( widget callbackName CallbackProc( args ) ... )

    Invokes XtAddCallbacks and XtRemoveCallbacks, as callbacks should not just
    be trashed using XtSetValues, since other things besides the application
    code may express intrest in callbacks.  Especially true for popup, map,
    and destroy callbacks
*/

typedef void (*AddOrRemoveProc) _(( Widget, char*, XtCallbackRec* ));

static void WcxAddOrRemoveCallbacks ( w, string, caller, AddOrRemove )
    Widget		w;
    char*		string;
    char*		caller;
    AddOrRemoveProc	AddOrRemove;
{
    char                name[MAX_XRMSTRING];
    XtCallbackRec*      callbacks;
    Widget		target;

    string = WcCleanName( string, name );	/* name of a widget */
    string = WcSkipWhitespace_Comma( string );

    if ( NULL == (target = WcFullNameToWidget( w, name )) )
    {
	WcWARN2( w, caller, "destNotFound",
		"Wcl Warning: %s(%s) - Widget not found.", caller, name );
	return;
    }

    string = WcCleanName( string, name );	/* name now callback name */
    string = WcSkipWhitespace_Comma( string );

    if ( NULL != (callbacks = WcStringToCallbackList( w, string ) ) )
    {
	AddOrRemove( target, name, callbacks );
	WcFreeCallbackList( callbacks );
    }
}

/*ARGSUSED*/
void WcAddCallbacksCB ( w,  callbackString, unused )
    Widget      w;
    XtPointer   callbackString;
    XtPointer   unused;
{
    WcxAddOrRemoveCallbacks( w, (char*)callbackString,
				"WcAddCallbacks", XtAddCallbacks );
}

/*ARGSUSED*/
void WcRemoveCallbacksCB ( w,  callbackString, unused )
    Widget      w;
    XtPointer   callbackString;
    XtPointer   unused;
{
    WcxAddOrRemoveCallbacks( w, (char*)callbackString,
				"WcRemoveCallbacks", XtRemoveCallbacks );
}

/*  -- Invoke Callback Once Only
*******************************************************************************
    WcOnceOnly( name, callback(clientData) [callback(clientData) ...] )

    I sure wish we did not need to pass the callback name, but we must...
    We don't know which callback list name (i.e., activateCallback,
    destroyCallback, wcAfterChildren etc) is being invoked.  We can't get it
    at conversion time, as the converter does not have enough information.
*/

void WcOnceOnlyCB ( w, name_callbackString, passedAlong )
    Widget	w;
    XtPointer	name_callbackString;
    XtPointer	passedAlong;
{
    static char* usage = 
"Wcl Usage: WcOnceOnly( name, callback(clientData) [callback(clientData) ...] )\n\
\tname - callback name (i.e., activateCallback, destroyCallback, etc)\n\
\t\tCallbacks are each invoked with the client data,\n\
\t\tthen this callback is removed.";
    XtCallbackRec*	cb;
    XtCallbackRec*	callbackRecs;   
    char		name[MAX_XRMSTRING];
    char*		callbacks = (char*)name_callbackString;

    callbacks = WcCleanName( callbacks, name );
    callbacks = WcSkipWhitespace_Comma( callbacks );

    if ( NULL != ( callbackRecs = WcStringToCallbackList( w, callbacks ) ) )
    {
	for ( cb = callbackRecs  ;  cb->callback != 0  ;  cb++ )
	{
	    cb->callback( w, cb->closure, passedAlong );
	}
	/* This does nothing if WcOnceOnlyCB is called via the late binder:
	*/
	XtRemoveCallback( w, name, WcOnceOnlyCB, name_callbackString );

	/* This does nothing if WcOnceOnlyCB was bound via C
	*/
	WcLateBinder_RemoveCallback( name );

	XtFree( (char*)callbackRecs );
    }
    else
    {
	char* fullName = WcWidgetToFullName(w);

	WcWARN2( w, "WcOnceOnly", "noSuchCallbackList",
		"Wcl Warning: Widget %s does not have callback list named %s.",
		fullName, name );
	WcWARN( w, "WcOnceOnly", "usage", usage );
	XtFree( fullName );
    }
}

/*  -- Augment or override translations
*******************************************************************************
    WcTranslations( widget translationString )
*/

/*ARGSUSED*/
void WcTranslationsCB ( w, name_trans, unused )
    Widget	w;
    XtPointer	name_trans;
    XtPointer	unused;
{
    char	name[MAX_XRMSTRING];
    char*	translations	= (String)name_trans;
    Widget	target;

    translations = WcCleanName( (char*)name_trans, name );
    translations = WcSkipWhitespace_Comma( translations );
    if ( NULL == (target = WcFullNameToWidget( w, name ) ) )
    {
	WcWARN1( w, "WcTranslations", "notFound",
		"Wcl Warning: WcTranslations(%s ... ) - Widget not found.",
		name );
	return;
    }
    WcSetTranslations( target, translations );
}


/*  -- Invoke Action or Callback in Dynamically Linked Libraries
*******************************************************************************
	WcDynamicAction(   sharedLibrary entryPointName([optArgs]) )
	WcDynamicCallback( sharedLibrary entryPointName([optArgs]) )

    Invokes named callback or action.

    Works only on machines which support dlopen() and dlsym(), in other
    words, SunOS and SVR4 machines.  The idea and proof of concept was
    provided by John Coyne (coyne@seismo.CSS.GOV).

    This has really been superceeded by the upgraded string-to-callback
    converter and WcLateBinder()
*/
/*ARGSUSED*/
void WcDynamicInvoke( w, clientData, callData, invokeAction, caller )
    Widget	w;
    XtPointer	clientData, callData;
    int		invokeAction;
    char*	caller;
{
#ifndef WC_HAS_dlopen_AND_dlsym

    /* Cannot do anything.
    */

    WcWARN( w, "WcDynamicInvoke", "notSupported",
	    "Wcl Warning: WcDynamicInvoke() requires dynamic linking via dlopen() and dlsym()" );
    return;

#else

    /* We can actually try to do the dynamic bind and invocation
    */

    static char usageAction[] =
"Wcl Usage: WcDynamicAction( sharedLibrary entryPointName([optArgs]) )\n\
  sharedLibrary  - path from / or ~, or name registered with WclDynamicLibs\n\
  entryPointName - name of XtActionProc\n\
  optArgs        - passed as string args to XtActionProc (do NOT free)";

    static char usageCallback[] =
"Wcl Usage: WcDynamicCallback( sharedLibrary entryPointName([optArgs]) )\n\
  sharedLibrary  - path from / or ~, or name registered with WclDynamicLibs\n\
  entryPointName - name of XtCallbackProc\n\
  optArgs        - passed as clientData string to XtCallbackProc (do NOT free)";

    static char unbalAction[] =
"Wcl Warning: WcDynamicAction( %s ) - Unbalanced parens.";

    static char unbalCallback[] =
"Wcl Warning: WcDynamicCallback( %s ) - Unbalanced parens.";

    static char unknownAction[] =
"Wcl Warning: WcDynamicAction( %s ... ) - library not registered.";

    static char unknownCallback[] =
"Wcl Warning: WcDynamicCallback( %s ... ) - library not registered.";

    static char tooLongAction[] =
"Wcl Warning: WcDynamicAction( %s ... ) - Expanded name too long: %s%s";

    static char tooLongCallback[] =
"Wcl Warning: WcDynamicCallback( %s ... ) - Expanded name too long: %s%s";

    static char dlopenAction[] =
"Wcl Warning: WcDynamicAction( %s ... ) Failed - %s";

    static char dlopenCallback[] =
"Wcl Warning: WcDynamicCallback( %s ... ) Failed - %s";

    char*	usage   = ( invokeAction? usageAction   : usageCallback );
    char*	unbal   = ( invokeAction? unbalAction   : unbalCallback );
    char*	unknown = ( invokeAction? unknownAction : unknownCallback );
    char*	tooLong = ( invokeAction? tooLongAction : tooLongCallback );
    char*	dlopenFailed = ( invokeAction? dlopenAction : dlopenCallback );
    char	librarySpec[ MAX_XRMSTRING ];
    char*	sharedLibrary;
    char	entryPoint[ MAX_XRMSTRING ];
    char	optArgs[ MAX_XRMSTRING ];
    char*	from;
    char*	to;
    void*	handle;

    /* First word is the shared library
    */
    from = WcCleanName( (char*)clientData, librarySpec );

    /* Get name of entry point
    */
    from = WcSkipWhitespace_Comma( from );
    for ( to = entryPoint  ;  *from && ' ' <= *from && *from != '('  ; )
	*to++ = *from++;
    *to = '\0';

    if ( '\0' == *entryPoint )
    {
	WcWARN(  w, caller, "usage", usage );
	return;
    }

    /* Get optional arguments, strip leading and trailing blanks
    */
    while ( *from && *from <= ' ' && *from != '(' )
	from++;

    if ( *from == '\0' )
    {
	/* No parens means no optional args
	*/
	*optArgs = '\0';
    }
    else if ( *from == '(' )
    {
	/* Get chars in parens, no leading or trailing whitespace
	*/
	char* firstNonWhitespace = (char*)0;
	char* lastNonWhitespace;
	int inParens = 0;
	while ( *from )
	{
	    if      ( '(' == *from ) inParens++;
	    else if ( ')' == *from ) inParens--;
	    else if ( ' ' <  *from )
	    {
		if ( firstNonWhitespace == (char*)0 )
		    firstNonWhitespace = from;
		lastNonWhitespace = from;
	    }
	    ++from;
	}
	if ( 0 != inParens )
	{
	    WcWARN1( w, caller, "unbalancedParens", unbal, (char*)clientData );
	    return;
	}

	to = optArgs;
	if ( firstNonWhitespace != (char*)0 )
	{
	    from = firstNonWhitespace;
	    while ( from <= lastNonWhitespace )
		*to++ = *from++;
	}
	*to = '\0';
    }
    else
    {
	/* Junk following entry point name
	*/
	WcWARN(  w, caller, "usage", usage );
	return;
    }

    if ( librarySpec[0] == '-' && librarySpec[1] == 'l' )
    {
	/* Library which should have been registered with Wcl
	*/
	XtAppContext app = XtWidgetToApplicationContext(w);
	sharedLibrary = WcMapDynLibFind( app, XrmStringToQuark(librarySpec) );

	if ( (char*)0 == sharedLibrary )
	{
	    WcWARN1( w, caller, "unknownLibrary", unknown, librarySpec );
	    return;
	}
    }
    else if ( librarySpec[0] == '~' )
    {
	char  user[ MAX_PATHNAME ];
	char  path[ MAX_PATHNAME ];
	char* homeDir;

	from = &librarySpec[1];		/* skip the tilda */
	to   = &user[0];

	while ( *from && *from != '/' )
	    *to++ = *from++;
	*to = '\0';

	homeDir = WcHomeDirectory( user );	/* homeDir is static storage */

	if( WcStrLen(homeDir) + WcStrLen(from) >= MAX_PATHNAME )
	{
	    WcWARN3( w, caller, "tooLongExpanded",
		     tooLong, librarySpec, homeDir, from );
	    return;
	}

	WcStrCpy( path, homeDir );
	WcStrCat( path, from );		/* from points at first '/' */

	sharedLibrary = path;
    }
    else
    {
	sharedLibrary = librarySpec; /* It must be a path name */
    }

    if ( NULL == (handle = dlopen( sharedLibrary, RTLD_LAZY )) )
    {
	WcWARN2( w, "WcDynamicCallback", "dlopenFailed",
		 dlopenFailed, sharedLibrary, dlerror() );
	return;
    }

    if ( invokeAction )
    {
	XtActionProc ActProc = (XtActionProc)dlsym( handle, entryPoint );

	if ( NULL != ActProc )
	    WcInvokeAction( ActProc, w, optArgs );
	else
	    WcWARN3( w, caller, "dlsymFailed",
		"Wcl Warning: WcDynamicAction( %s %s ) Failed - %s",
		sharedLibrary, entryPoint, dlerror() );
    }
    else
    {
	XtCallbackProc CbProc = (XtCallbackProc)dlsym( handle, entryPoint );

	if ( NULL != CbProc )
	    CbProc( w, (XtPointer)optArgs, callData );
	else
	    WcWARN3( w, "WcDynamicCallback", "dlsymFailed",
		"Wcl Warning: WcDynamicCallback( %s %s ) Failed - %s",
		sharedLibrary, entryPoint, dlerror() );
    }
#endif
}

/*ARGSUSED*/
void WcDynamicActionCB( w, clientData, callData )
    Widget	w;
    XtPointer	clientData, callData;
{
#ifdef WC_HAS_dlopen_AND_dlsym
    WcDynamicInvoke( w, clientData, callData, 1, "WcDynamicAction" );
#else
    WcWARN( w, "WcDynamicAction", "notSupported",
      "Wcl Warning: WcDynamicAction() requires dynamic linking via dlopen() and dlsym()" );
#endif
}

/*ARGSUSED*/
void WcDynamicCallbackCB( w, clientData, callData )
    Widget	w;
    XtPointer	clientData, callData;
{
#ifdef WC_HAS_dlopen_AND_dlsym
    WcDynamicInvoke( w, clientData, callData, 0, "WcDynamicCallback" );
#else
    WcWARN( w, "WcDynamicCallback", "notSupported",
      "Wcl Warning: WcDynamicCallback() requires dynamic linking via dlopen() and dlsym()" );
#endif
}

/*
*******************************************************************************
* Callbacks which simply invoke equivalent actions
*******************************************************************************
*/

#define CB_INVOKES_ACT( cb, act )		\
void    cb( w, client_data, unused )		\
    Widget	w;				\
    XtPointer	client_data;			\
    XtPointer	unused;				\
{						\
    WcInvokeAction( act, w, client_data );	\
}

/*ARGSUSED*/
CB_INVOKES_ACT( WcManageCB,			WcManageACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcUnmanageCB,			WcUnmanageACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcManageChildrenCB,		WcManageChildrenACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcUnmanageChildrenCB,		WcUnmanageChildrenACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcDestroyCB,			WcDestroyACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcSetSensitiveCB,		WcSetSensitiveACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcSetInsensitiveCB,		WcSetInsensitiveACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcPopupCB,			WcPopupACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcPopupGrabCB,			WcPopupGrabACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcPopdownCB,			WcPopdownACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcMapCB,			WcMapACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcUnmapCB,			WcUnmapACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcInstallAcceleratorsCB,	WcInstallAcceleratorsACT )
/*ARGSUSED*/
CB_INVOKES_ACT( WcInstallAllAcceleratorsCB,	WcInstallAllAcceleratorsACT )
/*ARGSUSED*/
CB_INVOKES_ACT( WcCreateRootCB,			WcCreateRootACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcSpawnCB,			WcSpawnACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcLoadResourceFileCB,		WcLoadResourceFileACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcPrintTreeCB,			WcPrintTreeACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcDumpResourcesCB,		WcDumpResourcesACT	)
/*ARGSUSED*/
CB_INVOKES_ACT( WcSameSizeCB,			WcSameSizeACT		)
/*ARGSUSED*/
CB_INVOKES_ACT( WcExitCB,			WcExitACT		)

/*  -- WcRegisterCreateCallbacks
*******************************************************************************
    Register all Wcl callbacks.  Called from WcInitialize, so applications
    normally never call this directly.
*/

void WcRegisterWcCallbacks ( app )
    XtAppContext app;
{
    ONCE_PER_XtAppContext( app );

#define RCALL( name, func ) WcRegisterCallback ( app, name, func, NULL );

  /* Actually implemented as XtActionProcs:
  */
  RCALL( "WcManage",			WcManageCB			)
  RCALL( "WcManageCB",			WcManageCB			)
  RCALL( "WcUnmanage",			WcUnmanageCB			)
  RCALL( "WcUnmanageCB",		WcUnmanageCB			)
  RCALL( "WcManageChildren",		WcManageChildrenCB		)
  RCALL( "WcManageChildrenCB",		WcManageChildrenCB		)
  RCALL( "WcUnmanageChildren",		WcUnmanageChildrenCB		)
  RCALL( "WcUnmanageChildrenCB",	WcUnmanageChildrenCB		)
  RCALL( "WcDestroy",			WcDestroyCB			)
  RCALL( "WcDestroyCB",			WcDestroyCB			)
  RCALL( "WcSetSensitive",		WcSetSensitiveCB		)
  RCALL( "WcSetSensitiveCB",		WcSetSensitiveCB		)
  RCALL( "WcSetInsensitive",		WcSetInsensitiveCB		)
  RCALL( "WcSetInsensitiveCB",		WcSetInsensitiveCB		)
  RCALL( "WcPopup",			WcPopupCB			)
  RCALL( "WcPopupCB",			WcPopupCB			)
  RCALL( "WcPopupGrab",			WcPopupGrabCB			)
  RCALL( "WcPopupGrabCB",		WcPopupGrabCB			)
  RCALL( "WcPopdown",			WcPopdownCB			)
  RCALL( "WcPopdownCB",			WcPopdownCB			)
  RCALL( "WcMap",			WcMapCB				)
  RCALL( "WcMapCB",			WcMapCB				)
  RCALL( "WcUnmap",			WcUnmapCB			)
  RCALL( "WcUnmapCB",			WcUnmapCB			)
  RCALL( "WcInstallAccelerators",	WcInstallAcceleratorsCB		)
  RCALL( "WcInstallAcceleratorsCB",	WcInstallAcceleratorsCB		)
  RCALL( "WcInstallAllAccelerators",	WcInstallAllAcceleratorsCB	)
  RCALL( "WcInstallAllAcceleratorsCB",	WcInstallAllAcceleratorsCB	)
  RCALL( "WcCreateRoot",		WcCreateRootCB			)
  RCALL( "WcCreateRootCB",		WcCreateRootCB			)
  RCALL( "WcSpawn",			WcSpawnCB			)
  RCALL( "WcSpawnCB",			WcSpawnCB			)
  RCALL( "WcLoadResourceFile",		WcLoadResourceFileCB		)
  RCALL( "WcLoadResourceFileCB",	WcLoadResourceFileCB		)
  RCALL( "WcPrintTree",			WcPrintTreeCB			)
  RCALL( "WcPrintTreeCB",		WcPrintTreeCB			)
  RCALL( "WcDumpResources",		WcDumpResourcesCB		)
  RCALL( "WcDumpResourcesCB",		WcDumpResourcesCB		)
  RCALL( "WcSameSize",			WcSameSizeCB			)
  RCALL( "WcSameSizeCB",		WcSameSizeCB			)
  RCALL( "WcExit",			WcExitCB			)
  RCALL( "WcExitCB",			WcExitCB			)

  /* Actually implemented as XtCallbackProcs:
  */
  RCALL( "WcCreateChildren",		WcCreateChildrenCB		)
  RCALL( "WcCreateChildrenCB",		WcCreateChildrenCB		)
  RCALL( "WcCreatePopups",		WcCreatePopupsCB		)
  RCALL( "WcCreatePopupsCB",		WcCreatePopupsCB		)
  RCALL( "WcPositionTransient",		WcPositionTransientCB		)
  RCALL( "WcPositionTransientCB",	WcPositionTransientCB		)
  RCALL( "WcSetValues",			WcSetValueCB			)
  RCALL( "WcSetValuesCB",		WcSetValueCB			)
  RCALL( "WcSetValue",			WcSetValueCB			)
  RCALL( "WcSetValueCB",		WcSetValueCB			)
  RCALL( "WcTrace",			WcTraceCB			)
  RCALL( "WcTraceCB",			WcTraceCB			)
  RCALL( "WcSystem",			WcSystemCB			)
  RCALL( "WcSystemCB",			WcSystemCB			)
  RCALL( "WcAddCallbacks",		WcAddCallbacksCB		)
  RCALL( "WcAddCallbacksCB",		WcAddCallbacksCB		)
  RCALL( "WcRemoveCallbacks",		WcRemoveCallbacksCB		)
  RCALL( "WcRemoveCallbacksCB",		WcRemoveCallbacksCB		)
  RCALL( "WcOnceOnly",			WcOnceOnlyCB			)
  RCALL( "WcOnceOnlyCB",		WcOnceOnlyCB			)
  RCALL( "WcTranslations",		WcTranslationsCB		)
  RCALL( "WcTranslationsCB",		WcTranslationsCB		)
  RCALL( "WcDynamicAction",		WcDynamicActionCB		)
  RCALL( "WcDynamicActionCB",		WcDynamicActionCB		)
  RCALL( "WcDynamicCallback",		WcDynamicCallbackCB		)
  RCALL( "WcDynamicCallbackCB",		WcDynamicCallbackCB		)
}

/*
*******************************************************************************
* Actions which simply invoke equivalent callbacks
*******************************************************************************
*/

#define ACT_INVOKES_CB( act, cb )			\
void    act( w, unused, params, num_params )		\
    Widget	w;					\
    XEvent*	unused;					\
    char**	params;					\
    Cardinal*	num_params;				\
{							\
    WcInvokeCallback( cb, w, params, num_params );	\
}

/*ARGSUSED*/
ACT_INVOKES_CB( WcCreateChildrenACT,	WcCreateChildrenCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcCreatePopupsACT,	WcCreatePopupsCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcPositionTransientACT,	WcPositionTransientCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcSetValueACT,		WcSetValueCB		)
/*ARGSUSED*/
ACT_INVOKES_CB( WcTraceACT,		WcTraceCB		)
/*ARGSUSED*/
ACT_INVOKES_CB( WcSystemACT,		WcSystemCB		)
/*ARGSUSED*/
ACT_INVOKES_CB( WcAddCallbacksACT,	WcAddCallbacksCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcRemoveCallbacksACT,	WcRemoveCallbacksCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcOnceOnlyACT,		WcOnceOnlyCB		)
/*ARGSUSED*/
ACT_INVOKES_CB( WcTranslationsACT,	WcTranslationsCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcDynamicActionACT,	WcDynamicActionCB	)
/*ARGSUSED*/
ACT_INVOKES_CB( WcDynamicCallbackACT,	WcDynamicCallbackCB	)

/*  -- WcRegisterWcActions
*******************************************************************************
   Register all Wcl supplied actions.  Called from WcInitialize(), so 
   applications usually do not call this directly.
*/

void WcRegisterWcActions ( app )
XtAppContext app;
{
    static XtActionsRec WcActions[] = {

      {"WcManage",			WcManageACT			},
      {"WcManageACT",			WcManageACT			},
      {"WcUnmanage",			WcUnmanageACT			},
      {"WcUnmanageACT",			WcUnmanageACT			},
      {"WcManageChildren",		WcManageChildrenACT		},
      {"WcManageChildrenACT",		WcManageChildrenACT		},
      {"WcUnmanageChildren",		WcUnmanageChildrenACT		},
      {"WcUnmanageChildrenACT",		WcUnmanageChildrenACT		},
      {"WcDestroy",			WcDestroyACT			},
      {"WcDestroyACT",			WcDestroyACT			},
      {"WcSetSensitive",		WcSetSensitiveACT		},
      {"WcSetSensitiveACT",		WcSetSensitiveACT		},
      {"WcSetInsensitive",		WcSetInsensitiveACT		},
      {"WcSetInsensitiveACT",		WcSetInsensitiveACT		},
      {"WcPopup",			WcPopupACT			},
      {"WcPopupACT",			WcPopupACT			},
      {"WcPopupGrab",			WcPopupGrabACT			},
      {"WcPopupGrabACT",		WcPopupGrabACT			},
      {"WcPopdown",			WcPopdownACT			},
      {"WcPopdownACT",			WcPopdownACT			},
      {"WcMap",				WcMapACT			},
      {"WcMapACT",			WcMapACT			},
      {"WcUnmap",			WcUnmapACT			},
      {"WcUnmapACT",			WcUnmapACT			},
      {"WcInstallAccelerators",		WcInstallAcceleratorsACT	},
      {"WcInstallAcceleratorsACT",	WcInstallAcceleratorsACT	},
      {"WcInstallAllAccelerators",	WcInstallAllAcceleratorsACT	},
      {"WcInstallAllAcceleratorsACT",	WcInstallAllAcceleratorsACT	},
      {"WcCreateRoot",			WcCreateRootACT			},
      {"WcCreateRootACT",		WcCreateRootACT			},
      {"WcSpawn",			WcSpawnACT			},
      {"WcSpawnACT",			WcSpawnACT			},
      {"WcLoadResourceFile",		WcLoadResourceFileACT		},
      {"WcLoadResourceFileACT",		WcLoadResourceFileACT		},
      {"WcPrintTree",			WcPrintTreeACT			},
      {"WcPrintTreeACT",		WcPrintTreeACT			},
      {"WcDumpResources",		WcDumpResourcesACT		},
      {"WcDumpResourcesACT",		WcDumpResourcesACT		},
      {"WcSameSize",			WcSameSizeACT			},
      {"WcSameSizeACT",			WcSameSizeACT			},
      {"WcExit",			WcExitACT			},
      {"WcExitACT",			WcExitACT			},

      {"WcCreateChildren",		WcCreateChildrenACT		},
      {"WcCreateChildrenACT",		WcCreateChildrenACT		},
      {"WcCreatePopups",		WcCreatePopupsACT		},
      {"WcCreatePopupsACT",		WcCreatePopupsACT		},
      {"WcPositionTransient",		WcPositionTransientACT		},
      {"WcPositionTransientACT",	WcPositionTransientACT		},
      {"WcSetValues",			WcSetValueACT			},
      {"WcSetValuesACT",		WcSetValueACT			},
      {"WcSetValue",			WcSetValueACT			},
      {"WcSetValueACT",			WcSetValueACT			},
      {"WcTrace",			WcTraceACT			},
      {"WcTraceACT",			WcTraceACT			},
      {"WcSystem",			WcSystemACT			},
      {"WcSystemACT",			WcSystemACT			},
      {"WcAddCallbacks",		WcAddCallbacksACT		},
      {"WcAddCallbacksACT",		WcAddCallbacksACT		},
      {"WcRemoveCallbacks",		WcRemoveCallbacksACT		},
      {"WcRemoveCallbacksACT",		WcRemoveCallbacksACT		},
      {"WcOnceOnly",			WcOnceOnlyACT			},
      {"WcOnceOnlyACT",			WcOnceOnlyACT			},
      {"WcTranslations",		WcTranslationsACT		},
      {"WcTranslationsACT",		WcTranslationsACT		},
      {"WcDynamicAction",		WcDynamicActionACT		},
      {"WcDynamicActionACT",		WcDynamicActionACT		},
      {"WcDynamicCallback",		WcDynamicCallbackACT		},
      {"WcDynamicCallbackACT",		WcDynamicCallbackACT		},
    };

    ONCE_PER_XtAppContext( app );

    XtAppAddActions(app, WcActions, XtNumber(WcActions));
}
