#ifdef MOTIF
/****************************************************************************
 *         This example code is from the book:
 *
 *         The X Window System Programming and Applications with Xt,
 *           OSF/Motif, second edition
 *         by
 *           Douglas Young
 *
 *         Copyright 1993, 1994 by Prentice Hall
 *         All Rights Reserved
 *
 *  Permission to use, copy, modify, and distribute this software for
 *  any purpose except publication and without fee is hereby granted, provided
 *  that the above copyright notice appear in all copies of the software.
 **************************************************************************/

#include <Xm/Xm.h>
#include <Xm/SeparatoG.h>
#include <Xm/PushBG.h>
#include <Xm/CascadeBG.h>
#include <Xm/RowColumn.h>
#include <Xm/LabelG.h>
#include <Xm/ToggleBG.h>
#include "MenuSupport.h"

static void postMenuHandler (Widget w, XtPointer clientData, XEvent
*event, Boolean *flag);
static void attachPopup(Widget parent, Widget menu);
static void createMenuChildren(Widget parent, MenuDescription *desc,
XtPointer defaultClientData);


Widget createMenu(MenuType menuType, char *name, Widget parent,
MenuDescription *desc, XtPointer defaultClientData)
{
    Widget w;

    switch(menuType)
    {
    case POPUP:

	w = XmCreatePopupMenu(parent, name, NULL, 0);

	attachPopup(parent, w);;

	createMenuChildren(w, desc, defaultClientData);

	return w;

    case MENUBAR:

	w = XmCreateMenuBar(parent, name, NULL, 0);

	XtManageChild(w);

	createMenuChildren(w, desc, defaultClientData);

	return w;

    case OPTION:
    {
	Widget option = XmCreateOptionMenu(parent, name, NULL, 0);

	w = XmCreatePulldownMenu(parent, name, NULL, 0);

	XtVaSetValues(option, XmNsubMenuId, w, NULL);

	createMenuChildren(w, desc, defaultClientData);

	XtManageChild(option);

	return option;

    }

    default:
	XtError("Invalid Menu Type");
	return NULL;
    }
}

static void createMenuChildren(Widget parent, MenuDescription *desc,
XtPointer defaultClientData)
{
    Widget  w;
    int     i;

    /*
     * Create an entry for each item in the menu.
     */

    for(i=0; desc[i].type != NULL ;i++)
    {
      switch(desc[i].type)
	{
	case LABEL:

	    w = XtCreateManagedWidget(desc[i].name,
				      xmLabelGadgetClass,
				      parent, NULL, 0);

	    break;

	case BUTTON:

	    w = XtCreateManagedWidget(desc[i].name,
				      xmPushButtonGadgetClass,
				      parent, NULL, 0);
	    XtAddCallback(w,
			  XmNactivateCallback,
			  desc[i].func,
			  desc[i].data ? desc[i].data :
defaultClientData);
	    break;

	case TOGGLE:

	    w = XtCreateManagedWidget(desc[i].name,
				      xmToggleButtonGadgetClass,
				      parent, NULL, 0);
	    XtAddCallback(w,
			  XmNvalueChangedCallback,
			  desc[i].func,
			  desc[i].data ? desc[i].data :
defaultClientData);
	    break;


	case SEPARATOR:

	    XtCreateManagedWidget("separator",
				  xmSeparatorGadgetClass,
				  parent, NULL, 0);
	    break;

	case PULLDOWN:
	{
	    Widget pulldown;

	    pulldown = XmCreatePulldownMenu(parent,
					    desc[i].name,
					    NULL, 0);

	    w = XtVaCreateManagedWidget(desc[i].name,
					xmCascadeButtonGadgetClass,
					parent,
					XmNsubMenuId, pulldown,
					NULL);

	    createMenuChildren(pulldown, desc[i].subMenu,
defaultClientData);

	    break;

	}
	case RADIOPULLDOWN:
	{
	    Widget pulldown;

	    pulldown = XmCreatePulldownMenu(parent,
					    desc[i].name,
					    NULL, 0);

	    XtVaSetValues(pulldown, XmNradioBehavior, TRUE, NULL);

	    w = XtVaCreateManagedWidget(desc[i].name,
					xmCascadeButtonGadgetClass,
					parent,
					XmNsubMenuId, pulldown,
					NULL);

	    createMenuChildren(pulldown, desc[i].subMenu,
defaultClientData);

	}
	}
    }
}


static void attachPopup(Widget parent, Widget menu)
{
    XtAddEventHandler(parent, ButtonPressMask, FALSE,
		      postMenuHandler, menu);
}


static void postMenuHandler (Widget w, XtPointer clientData,
			     XEvent *event, Boolean *flag)
{
    int button;
    Widget menu = (Widget) clientData;

    /*
     * Make sure the button that caused this event was the one
     * the menupane uses for menu item selection.
     */

    XtVaGetValues(menu,  XmNwhichButton, &button, NULL);

    if (event->type == ButtonPress &&
	event->xbutton.button == button )
    {
	/*
	 * Position the menu over the sprite and post the menu.
	 */

	XmMenuPosition(menu, (XButtonPressedEvent *) event);
	XtManageChild(menu);
    }
}


#endif /* MOTIF */


