Blame tests/Performance/DND/menu.c

Packit b099d7
/* $XConsortium: menu.c /main/5 1995/07/15 21:01:38 drk $ */
Packit b099d7
/*
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
 */
Packit b099d7
/*
Packit b099d7
 * HISTORY
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
#include <stdio.h>
Packit b099d7
#include <string.h>
Packit b099d7
#include <Xm/Xm.h>
Packit b099d7
#include <Xm/LabelG.h>
Packit b099d7
#include <Xm/RowColumn.h>
Packit b099d7
#include <Xm/SeparatoG.h>
Packit b099d7
#include <Xm/PushBG.h>
Packit b099d7
#include <Xm/CascadeB.h>
Packit b099d7
#include "toolchest.h"
Packit b099d7
Packit b099d7
Packit b099d7
static struct menu *menus;
Packit b099d7
Packit b099d7
/* allocate a new menu entry */
Packit b099d7
struct menuEntry *
Packit b099d7
NewMenuEntry(char *label, enum menuEntryType type)
Packit b099d7
{
Packit b099d7
    register struct menuEntry *ret;
Packit b099d7
    ret = (struct menuEntry *)tcMalloc(sizeof (struct menuEntry));
Packit b099d7
    ret->label = label;
Packit b099d7
    ret->type = type;
Packit b099d7
    ret->sensitive = TRUE;
Packit b099d7
    ret->removed = FALSE;
Packit b099d7
    ret->empty = FALSE;
Packit b099d7
#ifdef TCEDIT
Packit b099d7
    ret->menuName = "";
Packit b099d7
    ret->execString = "";
Packit b099d7
    ret->exprString = "";
Packit b099d7
#endif
Packit b099d7
    return (ret);
Packit b099d7
}
Packit b099d7
Packit b099d7
/* look up a menu by name and return it.  If it is not found and mallocIt is
Packit b099d7
 * true, allocate a new one.
Packit b099d7
 */
Packit b099d7
struct menu *
Packit b099d7
FindMenu(char *name, Boolean mallocIt)
Packit b099d7
{
Packit b099d7
    struct menu *menu = menus;
Packit b099d7
Packit b099d7
    /* look for the menu */
Packit b099d7
    while (menu)
Packit b099d7
    {
Packit b099d7
	if (strcmp(menu->name, name) == 0)
Packit b099d7
	    return (menu);
Packit b099d7
	menu = menu->next;
Packit b099d7
    };
Packit b099d7
    /* malloc a new one if appropriate */
Packit b099d7
    if (mallocIt)
Packit b099d7
    {
Packit b099d7
	menu = tcMalloc(sizeof(struct menu));
Packit b099d7
	menu->next = menus;
Packit b099d7
	menus = menu;
Packit b099d7
	menu->name = name;
Packit b099d7
	menu->firstMenuEntry = NULL;
Packit b099d7
	menu->lastMenuEntry = NULL;
Packit b099d7
	menu->referenced = FALSE;
Packit b099d7
#ifdef TCMENU
Packit b099d7
	menu->activeEntry = NULL;
Packit b099d7
	menu->menuWidget = NULL;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
	return (NULL);
Packit b099d7
}
Packit b099d7
Packit b099d7
/* remove itemName from menu menu.  Return TRUE if it was found */
Packit b099d7
static Boolean
Packit b099d7
removeItemFromMenu (char *itemName, struct menu *menu)
Packit b099d7
{
Packit b099d7
    struct menuEntry *entry = menu->firstMenuEntry;
Packit b099d7
    struct menuEntry *prev, *next;
Packit b099d7
Packit b099d7
    while (entry)
Packit b099d7
    {
Packit b099d7
	if (strcmp (itemName, entry->label) == 0 && !entry->removed)
Packit b099d7
	{
Packit b099d7
	    entry->removed = TRUE;
Packit b099d7
	    return (TRUE);
Packit b099d7
	}
Packit b099d7
	entry = entry->next;
Packit b099d7
    }
Packit b099d7
    return (FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
/* remove item name from menu named menuName.  If menuName is NULL, remove
Packit b099d7
 * it from any menu
Packit b099d7
 */
Packit b099d7
void
Packit b099d7
RemoveMenuEntry(char *name, char *menuName)
Packit b099d7
{
Packit b099d7
    register struct menu *menu;
Packit b099d7
Packit b099d7
    if (menuName == NULL)
Packit b099d7
    {
Packit b099d7
	Boolean found = FALSE;
Packit b099d7
Packit b099d7
	for (menu = menus; menu; menu = menu->next)
Packit b099d7
	{
Packit b099d7
	    if (removeItemFromMenu(name, menu))
Packit b099d7
	    {
Packit b099d7
		if (found)
Packit b099d7
		    FileError ("Item %s removed from more than one menu", name);
Packit b099d7
		else found = TRUE;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
	if (!found)
Packit b099d7
	    FileError ("Can't find %s for removal\n", name);
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
    {
Packit b099d7
	menu = FindMenu(menuName, FALSE);
Packit b099d7
	if (menu == NULL)
Packit b099d7
	    FileError("Cannot find menu %s for removal\n", menuName);
Packit b099d7
	else if (!removeItemFromMenu(name, menu))
Packit b099d7
	    FileError("Item %s not found in menu %s\n", name, menuName);
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
#ifndef TCEDIT
Packit b099d7
/* recursively build a menu, based on info previously read.  name is the
Packit b099d7
 * name of the menu, parent is the parent pane, and isMenuBar is true of
Packit b099d7
 * the menu is a menu bar.
Packit b099d7
 */
Packit b099d7
static void
Packit b099d7
buildMenu(struct menu *menu, Widget parent, Boolean isMenuBar)
Packit b099d7
{
Packit b099d7
    register struct menuEntry *entry;
Packit b099d7
    Arg wargs[10];
Packit b099d7
    int n;
Packit b099d7
    Widget w;
Packit b099d7
    XmString xmstr;
Packit b099d7
    enum menuEntryType lastType = ME_NONE;
Packit b099d7
    Boolean thisEntryRemoved = FALSE;
Packit b099d7
    Boolean lastEntryRemoved;
Packit b099d7
Packit b099d7
    if (menu->referenced)
Packit b099d7
    {
Packit b099d7
	fprintf (stderr,
Packit b099d7
		 "WARNING:  menu %s referenced more than once, extra reference ignored\n",
Packit b099d7
		 menu->name);
Packit b099d7
	return;
Packit b099d7
    }
Packit b099d7
    menu->referenced = TRUE;
Packit b099d7
    for (entry = menu->firstMenuEntry; entry; entry = entry->next)
Packit b099d7
    {
Packit b099d7
	lastEntryRemoved = thisEntryRemoved;
Packit b099d7
	if (entry->removed)
Packit b099d7
	{
Packit b099d7
	    thisEntryRemoved = TRUE;
Packit b099d7
	}
Packit b099d7
	else
Packit b099d7
	{
Packit b099d7
	    thisEntryRemoved = FALSE;
Packit b099d7
	    xmstr = XmStringCreateSimple(entry->label);
Packit b099d7
	    switch (entry->type)
Packit b099d7
	    {
Packit b099d7
	    case ME_EXEC:
Packit b099d7
	    case ME_CHECKEXEC:
Packit b099d7
	    case ME_CHECKEXPR:
Packit b099d7
		if (entry->type == ME_CHECKEXEC)
Packit b099d7
		    entry->sensitive = CheckExec(entry->execString);
Packit b099d7
		else if (entry->type == ME_CHECKEXPR)
Packit b099d7
		    entry->sensitive = CheckExpr(entry->exprString);
Packit b099d7
		else
Packit b099d7
		    entry->sensitive = TRUE;
Packit b099d7
		n = 0;
Packit b099d7
		XtSetArg (wargs[n], XmNlabelString, xmstr);n++;
Packit b099d7
		XtSetArg (wargs[n], XmNalignment, XmALIGNMENT_CENTER); n++; 
Packit b099d7
		XtSetArg (wargs[n], XmNsensitive, entry->sensitive); n++; 
Packit b099d7
		/* In the menu bar we must create a cascade button instead of
Packit b099d7
		 * a push button.  (Note that since menu pixmaps are only in
Packit b099d7
		 * the widget, we create a widget rather than a gadget
Packit b099d7
		 * for the cascade button
Packit b099d7
		 */
Packit b099d7
		w = XtCreateManagedWidget(entry->label,
Packit b099d7
					  isMenuBar?
Packit b099d7
				              xmCascadeButtonWidgetClass: 
Packit b099d7
					      xmPushButtonGadgetClass,
Packit b099d7
					  parent, wargs, n);
Packit b099d7
		XtAddCallback(w, XmNactivateCallback, ExecCallback,
Packit b099d7
			      (caddr_t)entry);
Packit b099d7
		break;
Packit b099d7
		
Packit b099d7
	    case ME_SEPARATOR:
Packit b099d7
		/* if we removed the last entry and the last non
Packit b099d7
		 * removed entry was a separator, a title, or the start,
Packit b099d7
		 * remove this entry.  However, don't set thisEntryRemoved
Packit b099d7
		 * so that if another separator immediatly follows, it is
Packit b099d7
		 * drawn.
Packit b099d7
		 */
Packit b099d7
		if (!(lastEntryRemoved &&
Packit b099d7
		    (lastType == ME_SEPARATOR ||
Packit b099d7
		     lastType == ME_TITLE ||
Packit b099d7
		     lastType == ME_NONE)))
Packit b099d7
		{
Packit b099d7
		    n = 0;
Packit b099d7
		    w = XmCreateSeparatorGadget (parent, entry->label,
Packit b099d7
						 wargs, n);
Packit b099d7
		    XtManageChild(w);
Packit b099d7
		}
Packit b099d7
		break;
Packit b099d7
		
Packit b099d7
	    case ME_TITLE:
Packit b099d7
		n = 0;
Packit b099d7
		XtSetArg (wargs[n], XmNlabelString, xmstr);n++;
Packit b099d7
		XtSetArg (wargs[n], XmNalignment, XmALIGNMENT_CENTER); n++; 
Packit b099d7
		w = XmCreateLabelGadget(parent, entry->label,
Packit b099d7
					NULL, 0); n++;
Packit b099d7
		XtManageChild(w);
Packit b099d7
		n = 0;
Packit b099d7
		XtSetArg (wargs[n], XmNseparatorType, XmDOUBLE_LINE); n++;
Packit b099d7
		w = XmCreateSeparatorGadget (parent, "separator",
Packit b099d7
					     wargs, n);
Packit b099d7
		XtManageChild(w);
Packit b099d7
		
Packit b099d7
	    case ME_LABEL:
Packit b099d7
		n = 0;
Packit b099d7
		XtSetArg (wargs[n], XmNlabelString, xmstr);n++;
Packit b099d7
		XtSetArg (wargs[n], XmNalignment, XmALIGNMENT_CENTER); n++; 
Packit b099d7
		w = XmCreateLabelGadget(parent, entry->label,
Packit b099d7
					NULL, 0);
Packit b099d7
		XtManageChild(w);
Packit b099d7
		break;
Packit b099d7
		
Packit b099d7
	    case ME_MENU:
Packit b099d7
		{
Packit b099d7
		    struct menu *submenu;
Packit b099d7
		    Widget pane;
Packit b099d7
		    
Packit b099d7
		    submenu = FindMenu(entry->menuName, FALSE);
Packit b099d7
		    if (submenu)
Packit b099d7
		    {
Packit b099d7
			n = 0;
Packit b099d7
			if (menuVisualStatus != SG_VISUAL_DEFAULT)
Packit b099d7
			{
Packit b099d7
			    XtSetArg (wargs[n], XmNdepth,
Packit b099d7
				      menuVisualDepth); n++;
Packit b099d7
			    XtSetArg (wargs[n], XmNcolormap, 
Packit b099d7
				      menuVisualColormap); n++;
Packit b099d7
			    XtSetArg (wargs[n], XmNvisual, menuVisual); n++;
Packit b099d7
			}
Packit b099d7
			pane = XmCreatePulldownMenu(parent, entry->menuName,
Packit b099d7
						    wargs, n);
Packit b099d7
			wm_windows[0] = XtWindow(pane);
Packit b099d7
			
Packit b099d7
			n = 0;
Packit b099d7
			XtSetArg(wargs[n], XmNsubMenuId, pane);n++;
Packit b099d7
			XtSetArg(wargs[n], XmNlabelString, xmstr);n++;
Packit b099d7
			if (isMenuBar && showDecal)
Packit b099d7
			{
Packit b099d7
			    XtSetArg(wargs[n], XmNmenuBarPixmap,
Packit b099d7
				     decalPixmap); n++;
Packit b099d7
			}
Packit b099d7
			w = XmCreateCascadeButton(parent, submenu->name,
Packit b099d7
						  wargs, n);
Packit b099d7
			XtManageChild(w);
Packit b099d7
			
Packit b099d7
			buildMenu (submenu, pane, FALSE);
Packit b099d7
		    }
Packit b099d7
		    else
Packit b099d7
		    {
Packit b099d7
			/* menu wasn't found.  Mark it so */
Packit b099d7
			entry->empty = TRUE;
Packit b099d7
			thisEntryRemoved = TRUE;
Packit b099d7
		    }
Packit b099d7
		}
Packit b099d7
		break;
Packit b099d7
		
Packit b099d7
	    default:
Packit b099d7
		XtError ("Unknown menu item type");
Packit b099d7
	    }
Packit b099d7
	    XmStringFree(xmstr);
Packit b099d7
	    if (!thisEntryRemoved)
Packit b099d7
		lastType = entry->type;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
	    
Packit b099d7
/* build the top level menu.  The flag isMenuBar indicates whether it
Packit b099d7
 * is in a menu bar
Packit b099d7
 */
Packit b099d7
void
Packit b099d7
BuildTopMenu(Widget parent, Boolean isMenuBar)
Packit b099d7
{
Packit b099d7
    struct menu *topMenu;
Packit b099d7
Packit b099d7
    if ((topMenu = FindMenu(TOP_MENU_NAME, FALSE)) == NULL)
Packit b099d7
    {
Packit b099d7
	char buf[100];
Packit b099d7
	sprintf(buf, 
Packit b099d7
		"Menu specification: menu '%s' referenced but not found\n",
Packit b099d7
		TOP_MENU_NAME);
Packit b099d7
	XtError(buf);
Packit b099d7
    }
Packit b099d7
    buildMenu(topMenu, parent, isMenuBar);
Packit b099d7
}
Packit b099d7
#endif