[alt.sources] EzMenu - Menu widgets with a resource manager interface, Part02/02

ferguson@cs.rochester.edu (George Ferguson) (11/15/90)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  EzMEP.h EzMenu.c EzMenu.h
# Wrapped by ferguson@swan.cs.rochester.edu on Mon Nov 12 14:07:38 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'EzMEP.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'EzMEP.h'\"
else
echo shar: Extracting \"'EzMEP.h'\" \(3061 characters\)
sed "s/^X//" >'EzMEP.h' <<'END_OF_FILE'
X/*
X * $XConsortium: SmeP.h,v 1.4 89/12/11 15:20:22 kit Exp $
X *
X * Copyright 1989 Massachusetts Institute of Technology
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of M.I.T. not be used in advertising or
X * publicity pertaining to distribution of the software without specific,
X * written prior permission.  M.I.T. makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X *
X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X */
X
X/*
X * SmeP.h - Private Header file for Sme object.
X *
X * This is the private header file for the Athena EzME object.
X * This object is intended to be used with the simple menu widget.  
X *
X * Date:    April 3, 1989
X *
X * By:      Chris D. Peterson
X *          MIT X Consortium 
X *          kit@expo.lcs.mit.edu
X */
X
X#ifndef _XawEzMEP_h
X#define _XawEzMEP_h
X
X/***********************************************************************
X *
X * EzME Widget Private Data
X *
X ***********************************************************************/
X
X#include <X11/RectObjP.h>
X#include <X11/Xaw/SmeP.h>
X#include <X11/Xaw/SmeBSBP.h>
X#include "EzME.h"
X
X/************************************************************
X *
X * New fields for the EzME widget class record.
X *
X ************************************************************/
X
Xtypedef struct _EzMEClassPart {
X  void (*highlight)();
X  void (*unhighlight)();
X  void (*notify)();	
X  XtPointer extension;
X} EzMEClassPart;
X
X/* Full class record declaration */
Xtypedef struct _EzMEClassRec {
X    RectObjClassPart    rect_class;
X    SmeClassPart	sme_class;
X    SmeBSBClassPart  sme_bsb_class;
X    EzMEClassPart	ezme_class;
X} EzMEClassRec;
X
Xextern EzMEClassRec ezmeClassRec;
X
X/* New fields for the EzME widget record */
Xtypedef struct {
X    /* resources */
X    char *action;
X    Widget toPopUp;
X} EzMEPart;
X
X/****************************************************************
X *
X * Full instance record declaration
X *
X ****************************************************************/
X
Xtypedef struct _EzMERec {
X  ObjectPart     object;
X  RectObjPart    rectangle;
X  SmePart	 sme;
X  SmeBSBPart   sme_bsb;
X  EzMEPart	 ezme;
X} EzMERec;
X
X/************************************************************
X *
X * Private declarations.
X *
X ************************************************************/
X#endif /* _XawEzMEP_h */
END_OF_FILE
if test 3061 -ne `wc -c <'EzMEP.h'`; then
    echo shar: \"'EzMEP.h'\" unpacked with wrong size!
fi
# end of 'EzMEP.h'
fi
if test -f 'EzMenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'EzMenu.c'\"
else
echo shar: Extracting \"'EzMenu.c'\" \(11025 characters\)
sed "s/^X//" >'EzMenu.c' <<'END_OF_FILE'
X#if ( !defined(lint) && !defined(SABER) )
Xstatic char Xrcsid[] = "$XConsortium: SimpleMenu.c,v 1.32 89/12/11 15:01:50 kit Exp $";
X#endif 
X
X/*
X * Copyright 1989 Massachusetts Institute of Technology
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of M.I.T. not be used in advertising or
X * publicity pertaining to distribution of the software without specific,
X * written prior permission.  M.I.T. makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X *
X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X */
X
X#include <stdio.h>
X#include <X11/Xlib.h>
X#include <X11/Xos.h>  
X#include <X11/Intrinsic.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X
X#include "EzMenuP.h"
X#include <X11/Xaw/SimpleMenu.h>
X#include <X11/Xaw/Sme.h>
X#include "EzME.h"
X#include <X11/Xaw/SmeBSB.h>
X#include <X11/Xaw/SmeLine.h>
X
X#include <X11/Xaw/Cardinals.h>
X
X#include <ctype.h>
X
X#define offset(field) XtOffset(EzMenuWidget, ez_menu.field)
X
Xstatic XtResource resources[] = { 
X  {XtNmenu,  XtCMenu, XtRString, sizeof(String),
X     offset(menu), XtRString, NULL},
X};  
X#undef offset
X
X
X/*
X * Semi Public function definitions. 
X */
X
Xstatic void Initialize();
Xstatic void Destroy();
Xstatic void Realize();
Xstatic Boolean SetValues();
X
X#define superclass (&simpleMenuClassRec)
X    
XEzMenuClassRec ezMenuClassRec = {
X  {
X    /* superclass         */    (WidgetClass) superclass,
X    /* class_name         */    "EzMenu",
X    /* size               */    sizeof(EzMenuRec),
X    /* class_initialize   */	NULL,
X    /* class_part_initialize*/	NULL,
X    /* Class init'ed      */	FALSE,
X    /* initialize         */    Initialize,
X    /* initialize_hook    */	NULL,
X    /* realize            */    Realize,
X    /* actions            */    NULL,
X    /* num_actions        */    0,
X    /* resources          */    resources,
X    /* resource_count     */	XtNumber(resources),
X    /* xrm_class          */    NULLQUARK,
X    /* compress_motion    */    TRUE, 
X    /* compress_exposure  */    TRUE,
X    /* compress_enterleave*/ 	TRUE,
X    /* visible_interest   */    FALSE,
X    /* destroy            */    Destroy,
X    /* resize             */    XtInheritResize,
X    /* expose             */    XtInheritExpose,
X    /* set_values         */    SetValues,
X    /* set_values_hook    */	NULL,
X    /* set_values_almost  */	XtInheritSetValuesAlmost,  
X    /* get_values_hook    */	NULL,			
X    /* accept_focus       */    NULL,
X    /* intrinsics version */	XtVersion,
X    /* callback offsets   */    NULL,
X    /* tm_table		  */    XtInheritTranslations,
X    /* query_geometry	  */    XtInheritQueryGeometry,
X    /* display_accelerator*/    XtInheritDisplayAccelerator,
X    /* extension	  */    NULL
X  },{
X    /* geometry_manager   */    XtInheritGeometryManager,
X    /* change_managed     */    XtInheritChangeManaged,
X    /* insert_child	  */	XtInheritInsertChild,
X    /* delete_child	  */	XtInheritDeleteChild,
X    /* extension	  */    NULL
X  },{
X    /* Shell extension	  */    NULL
X  },{
X    /* Override extension */    NULL
X  },{
X    /* Simple Menu extension*/  NULL
X  },{
X    /* Ez Menu extension*/  NULL
X  }
X};
X
XWidgetClass ezMenuWidgetClass = (WidgetClass)&ezMenuClassRec;
X
X/************************************************************
X *
X * Semi-Public Functions.
X *
X ************************************************************/
X
X/*
X * routines to process menus
X */
X
X#define QUOTE '\"'
X#define BACKSLASH '\\'
X
X#define SKIPWHITE(cp) while (cp && *cp && isspace(*cp)) cp++
X#define FINDPAREN(cp) while (cp && *cp && *cp != '(') cp++
X#define FINDQUOTE(cp) while (cp && *cp && *cp != QUOTE) cp++
X#define KEY_LEN 32
X#define NAME_LEN 256
X#define LABEL_LEN 128
X
X/*
X * Parse a main level menu decl. and add all children to that parent
X */
X
Xchar *
XEzMenuParseString(from, to, maxlen)
Xchar *from;
Xchar *to;
Xint maxlen;
X{
X  char *oldto = to;
X  SKIPWHITE(from);
X  if ( from && *from == QUOTE ) {
X    maxlen--;
X    from++;
X    while (*from && *from != QUOTE && maxlen > 1) {
X      if ( *from == BACKSLASH) {
X	from++;
X      }
X      *to++ = *from++;
X      maxlen--;
X    }
X    if ( *from == QUOTE ) {
X      from++;
X    }
X  }
X  *to = 0;
X  return(from);
X}  
X
Xchar *
XEzMenuParseMenu(parent,menu,subMenuOk)
XWidget parent;
Xchar *menu;
XBool subMenuOk;
X{
X  char *thisWidgetName[NAME_LEN];
X  char *thisWidgetLabel[LABEL_LEN];
X
X  *thisWidgetName = 0;
X  *thisWidgetLabel = 0;
X  while(menu && *menu) {
X    SKIPWHITE(menu);
X
X    if (!menu || *menu != '(') {
X      return( menu );
X    }
X    else {
X      menu++;
X    }
X
X    SKIPWHITE(menu);
X
X    if (isalpha(*menu)) {
X      char key[KEY_LEN+1];
X      char *p = key;
X      int keylen = 0;
X
X      while(isalpha(*menu) && keylen < KEY_LEN) {
X	*p++ = *menu++;
X	keylen++;
X      }
X      *p = 0;
X
X      if (strcmp(key, "action") == 0 ) {
X	char name[NAME_LEN];
X	Arg arglist[1];
X	Cardinal num_args = 0;
X
X	menu = EzMenuParseString(menu, name, NAME_LEN);
X
X	XtSetArg(arglist[num_args], XtNaction, name); num_args++;
X	XtSetValues(parent, arglist, num_args);
X      }
X      else if (strcmp(key, "blank") == 0 ) {
X	char name[NAME_LEN];
X	Widget entry;
X
X	*name = 0;
X	menu = EzMenuParseString(menu, name, NAME_LEN);
X	if ( *name == 0 ) {
X	  static int counter = 0;
X	  sprintf(name, "blank%d", counter);
X	}
X	entry = XtCreateManagedWidget(name, smeObjectClass,
X				      parent, NULL, ZERO);
X      }
X      else if (strcmp(key, "line") == 0 ) {
X	char name[NAME_LEN];
X	Widget entry;
X
X	*name = 0;
X	menu = EzMenuParseString(menu, name, NAME_LEN);
X	if ( *name == 0 ) {
X	  static int counter = 0;
X	  sprintf(name, "line%d", counter);
X	}
X	entry = XtCreateManagedWidget(name, smeLineObjectClass, parent,
X				      NULL, ZERO);
X      }
X      else if (strcmp(key, "item") == 0 || strcmp(key, "menu") == 0 ) {
X	char name[NAME_LEN];
X	char label[LABEL_LEN];
X	Widget entry;
X	Bool isMenu;
X	extern void MenuSelect();
X	Arg arglist[10];
X	Cardinal num_args = 0;
X
X
X	isMenu = (strcmp(key, "menu") == 0);
X	*name = 0;
X
X	menu = EzMenuParseString(menu, label, LABEL_LEN);
X	menu = EzMenuParseString(menu, name, NAME_LEN);
X
X	if ( *name == 0 ) {
X	  static int counter = 0;
X	  sprintf(name, "%s%d", key, counter);
X	}
X
X	if ( *label == 0 ) {
X	  strcpy(label, name);
X	}
X
X	if ( isMenu ) {
X	  char menu_name[NAME_LEN];
X	  Widget menu_entry;
X
X	  sprintf(menu_name,"%s-menu", name);
X
X	  XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
X
X	  menu_entry = XtCreatePopupShell(menu_name, ezMenuWidgetClass,
X			     parent, arglist, num_args);
X
X	  /* now, parse their menu entry. This is gross, but beats
X	   scanning ahead to find the stupid balanced parens */
X	  menu = EzMenuParseMenu(menu_entry, menu, True);
X
X	  num_args = 0;
X	  XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
X	  XtSetArg(arglist[num_args], XtNmenu, menu_entry); num_args++;
X	  entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
X					arglist, num_args);
X	}
X	else {
X	  num_args = 0;
X	  XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
X	  XtSetArg(arglist[num_args], XtNmenu, 0); num_args++;
X	  entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
X					arglist, num_args);
X	}
X
X	menu = EzMenuParseMenu(entry, menu, isMenu);
X      }
X
X      SKIPWHITE(menu);
X      if (*menu != ')') {
X	char buffer[2048];
X	XtAppContext context = 
X	  XtWidgetToApplicationContext( parent );
X
X	sprintf(buffer, "unbalanced parens or bogus format: %s\n", menu);
X
X	XtAppError(context, buffer);
X	exit(1);
X      }
X      menu++;
X    }
X  }
X  return(menu);
X}
X
X/*      Function Name: Initialize
X *      Description: Initializes the simple menu widget
X *      Arguments: request - the widget requested by the argument list.
X *                 new     - the new widget with both resource and non
X *                           resource values.
X *      Returns: none.
X */
X
X/* ARGSUSED */
Xstatic void
XInitialize(request, new)
XWidget request, new;
X{
X  EzMenuWidget newez = (EzMenuWidget) new;
X  EzMenuWidget requestez = (EzMenuWidget) request;
X
X#ifdef DEBUG
X  fprintf(stderr,"Initialize %s\n",
X	  XtWidgetName(request);
X#endif
X
X  /* just copy the string that will be used to initialize the menu */
X  
X  newez -> ez_menu.menu = 0;
X
X  if (requestez -> ez_menu.menu ) {
X    int len = strlen(requestez -> ez_menu.menu);
X    newez -> ez_menu.menu = XtMalloc( len + 1 );
X    strcpy( newez -> ez_menu.menu, requestez -> ez_menu.menu);
X  }
X
X  if ( newez -> ez_menu.menu ) {
X    EzMenuParseMenu( newez, newez -> ez_menu.menu, True );
X  }
X}
X
X/*      Function Name: Realize
X *      Description: Realizes the widget.
X *      Arguments: w - the simple menu widget.
X *                 mask - value mask for the window to create.
X *                 attrs - attributes for the window to create.
X *      Returns: none
X */
X
Xstatic void
XRealize(w, mask, attrs)
XWidget w;
XXtValueMask * mask;
XXSetWindowAttributes * attrs;
X{
X  EzMenuWidget newez = (EzMenuWidget) w;
X  (*superclass->core_class.realize) (w, mask, attrs);
X}
X
X
X/*      Function Name: SetValues
X *      Description: Relayout the menu when one of the resources is changed.
X *      Arguments: current - current state of the widget.
X *                 request - what was requested.
X *                 new - what the widget will become.
X *      Returns: none
X */
X
X/* ARGSUSED */
Xstatic Boolean
XSetValues(current, request, new)
X     Widget current, request, new;
X{
X  EzMenuWidget ez_old = (EzMenuWidget) current;
X  EzMenuWidget ez_want = (EzMenuWidget) request;
X  EzMenuWidget ez_new = (EzMenuWidget) new;
X  Boolean ret_val = FALSE;
X  if (
X
X      /* no old menu, want one now */
X
X      ( !ez_old -> ez_menu.menu && ez_want -> ez_menu.menu )
X      ||
X
X      /* old menu, new one is different */
X
X      (ez_want -> ez_menu.menu
X       && ez_old -> ez_menu.menu
X       && ( strcmp( ez_old -> ez_menu.menu,
X		   ez_want -> ez_menu.menu) != 0 ))
X      ) {
X
X    int len = strlen(ez_old -> ez_menu.menu);
X
X    ez_new -> ez_menu.menu = XtMalloc( len + 1 );
X    strcpy( ez_new -> ez_menu.menu,
X	   ez_old -> ez_menu.menu);
X    
X    if ( XtIsRealized(ez_old) ) {
X      SimpleMenuWidget smw = (SimpleMenuWidget) ez_old;
X      SmeObject *entry;
X      
X      ForAllChildren(smw, entry) {
X	XtDestroyWidget(entry);
X      }
X
X      EzMenuParseMenu(ez_new, ez_new -> ez_menu.menu, True);
X      ret_val = TRUE;
X    }
X  }
X  return(ret_val);
X}
X
Xstatic void
XDestroy(who)
XEzMenuWidget who;
X{
X  XtFree( who -> ez_menu.menu );
X}
X
END_OF_FILE
if test 11025 -ne `wc -c <'EzMenu.c'`; then
    echo shar: \"'EzMenu.c'\" unpacked with wrong size!
fi
# end of 'EzMenu.c'
fi
if test -f 'EzMenu.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'EzMenu.h'\"
else
echo shar: Extracting \"'EzMenu.h'\" \(3452 characters\)
sed "s/^X//" >'EzMenu.h' <<'END_OF_FILE'
X/*
X * $XConsortium: EzMenu.h,v 1.17 89/12/11 15:01:55 kit Exp $
X *
X * Copyright 1989 Massachusetts Institute of Technology
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of M.I.T. not be used in advertising or
X * publicity pertaining to distribution of the software without specific,
X * written prior permission.  M.I.T. makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X *
X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Chris D. Peterson, MIT X Consortium
X */
X
X/*
X * EzMenu.h - Public Header file for EzMenu widget.
X *
X * This is the public header file for the Athena EzMenu widget.
X * It is intended to provide one pane pulldown and popup menus within
X * the framework of the X Toolkit.  As the name implies it is a first and
X * by no means complete implementation of menu code. It does not attempt to
X * fill the needs of all applications, but does allow a resource oriented
X * interface to menus.
X *
X * Date:    April 3, 1989
X *
X * By:      Chris D. Peterson
X *          MIT X Consortium 
X *          kit@expo.lcs.mit.edu
X */
X
X#ifndef _EzMenu_h
X#define _EzMenu_h
X
X#include <X11/Shell.h>
X#include <X11/Xmu/Converters.h>
X#include <X11/Xaw/SimpleMenu.h>
X
X/****************************************************************
X *
X * EzMenu widget
X *
X ****************************************************************/
X
X/* EzMenu Resources:
X
X Name		     Class		RepType		Default Value
X ----		     -----		-------		-------------
X background	     Background		Pixel		XtDefaultBackground
X backgroundPixmap    BackgroundPixmap	Pixmap          None
X borderColor	     BorderColor	Pixel		XtDefaultForeground
X borderPixmap	     BorderPixmap	Pixmap		None
X borderWidth	     BorderWidth	Dimension	1
X bottomMargin        VerticalMargins    Dimension       VerticalSpace
X columnWidth         ColumnWidth        Dimension       Width of widest text
X cursor              Cursor             Cursor          None
X destroyCallback     Callback		Pointer		NULL
X height		     Height		Dimension	0
X label               Label              String          NULL (No label)
X labelClass          LabelClass         Pointer         smeBSBObjectClass
X mappedWhenManaged   MappedWhenManaged	Boolean		True
X rowHeight           RowHeight          Dimension       Height of Font
X sensitive	     Sensitive		Boolean		True
X topMargin           VerticalMargins    Dimension       VerticalSpace
X width		     Width		Dimension	0
X x		     Position		Position	0n
X y		     Position		Position	0
X
X*/
X
Xtypedef struct _EzMenuClassRec*	EzMenuWidgetClass;
Xtypedef struct _EzMenuRec*		EzMenuWidget;
X
X#define XtNmenu "menu"
X#define XtCMenu "Menu"
X
Xextern WidgetClass ezMenuWidgetClass;
X
X#endif /* _EzMenu_h */
END_OF_FILE
if test 3452 -ne `wc -c <'EzMenu.h'`; then
    echo shar: \"'EzMenu.h'\" unpacked with wrong size!
fi
# end of 'EzMenu.h'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
George Ferguson			ARPA: ferguson@cs.rochester.edu
University of Rochester		UUCP: {decvax,rutgers}!rochester!ferguson
Rochester  NY  14627		VOX:  (716) 275-2527