/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */

/*****************************************************************
 ***                                                           ***
 ***              Misc Items for popupmenu                     ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_WIDGET_MENU_ITEMS_C_

#include <ctype.h>
#include "EZ_Widget.h"

/*********************************************************************
 * 
 *  Functions implemented in this file:
 */
EZ_Widget        *EZ_CreateMenuSeparator MY_ANSIARGS((EZ_Widget *parent));
void             EZ_DrawWidgetMenuSeparator MY_ANSIARGS((EZ_Widget *widget));
void             EZ_ComputeWidgetMenuSeparatorSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));

EZ_Widget        *EZ_CreateMenuSubMenu MY_ANSIARGS((EZ_Widget *parent, char *lab, int udl));
void             EZ_DrawWidgetMenuSubMenu MY_ANSIARGS((EZ_Widget *widget));
void             EZ_ComputeWidgetMenuSubMenuSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));
void             EZ_FreeWidgetMenuSubMenuData MY_ANSIARGS((EZ_Widget *widget));
void             EZ_MenuSubMenuEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

EZ_Widget        *EZ_CreateMenuNormalButton MY_ANSIARGS((EZ_Widget *parent, char *lab, int udl, int ret));
void             EZ_MenuNormalButtonEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

EZ_Widget        *EZ_CreateMenuCheckButton MY_ANSIARGS((EZ_Widget *parent, char *lab, int udl, 
							int onv, int offv, int onoff, int ret));

void             EZ_MenuCheckButtonEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

EZ_Widget        *EZ_CreateMenuRadioButton MY_ANSIARGS((EZ_Widget *parent, char *lab, int udl,
							int gid, int val, int ret));
void             EZ_MenuRadioButtonEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

void             EZ_SetSubMenuMenu MY_ANSIARGS((EZ_Widget *widget, EZ_Widget *menu));

void             EZ_MenuSeparatorEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

EZ_Widget        *EZ_GetMenuItemCompaion MY_ANSIARGS((EZ_Widget *widget));
/*********************************************************************
 * 
 *  Local Variables.
 */
static EZ_WidgetHandle EZ_MenuSeparatorHandle =
{
  EZ_ComputeWidgetMenuSeparatorSize,
  EZ_DrawWidgetMenuSeparator,
  EZ_FreeUnknownData,
  EZ_MenuSeparatorEventHandle,    /* response only to Expose */
};

static EZ_WidgetHandle EZ_MenuSubmenuHandle =
{                  
  EZ_ComputeWidgetMenuSubMenuSize,
  EZ_DrawWidgetMenuSubMenu,
  EZ_FreeWidgetMenuSubMenuData,
  EZ_MenuSubMenuEventHandle,
};

static EZ_WidgetHandle EZ_MenuNormalButtonHandle =
{    
  EZ_ComputeWidgetButtonSize,
  EZ_DrawWidgetButton,
  EZ_FreeWidgetNButtonData,
  EZ_MenuNormalButtonEventHandle,
};

static EZ_WidgetHandle EZ_MenuCheckButtonHandle =
{  
  EZ_ComputeWidgetCButtonSize,    
  EZ_DrawWidgetCheckButton,
  EZ_FreeWidgetCButtonData,
  EZ_MenuCheckButtonEventHandle,
};

static EZ_WidgetHandle EZ_MenuRadioButtonHandle =
{
  EZ_ComputeWidgetRButtonSize,
  EZ_DrawWidgetRadioButton,
  EZ_FreeWidgetRButtonData,
  EZ_MenuRadioButtonEventHandle,
};


/*********************************************************************
 ***                                                               ***
 ***                    Menu item:  separator                      ***
 ***                                                               ***
 *********************************************************************/

EZ_Widget  *EZ_CreateMenuSeparator(parent)
     EZ_Widget  *parent;     /* parent widget    */
{
  EZ_Widget  *wptr;

  wptr = EZ_CreateNewWidget(parent);
  /*--------------------------------------------------
   * Register the handling functions for CButton.
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_MENU_SEPARATOR] = &EZ_MenuSeparatorHandle;

  EZ_SetWidgetTypeAndNames(wptr,EZ_WIDGET_MENU_SEPARATOR);
  EZ_WidgetBorderStyle(wptr)  = EZ_BORDER_NONE;
  EZ_WidgetBorderWidth(wptr)  = 0;
  EZ_WidgetWidth(wptr)  = 10;    /* default size */
  EZ_WidgetHeight(wptr) = 3;

  EZ_MenuSeparatorCopy(wptr)   = NULL;

  return(wptr);
}

/*
 *  Figure out the dimension of a menu separator
 */
void EZ_ComputeWidgetMenuSeparatorSize(widget, w, h)
    EZ_Widget *widget;
     int             *w, *h;
{
  EZ_SetWidgetSizeComputedFlag(widget);

  *w = EZ_WidgetWidth(widget);
  *h = EZ_WidgetHeight(widget);
}

/*
 *  Draw a Menu separator
 */

void  EZ_DrawWidgetMenuSeparator(wptr)
     EZ_Widget *wptr;
{
  int             w, h,y;
  Pixmap          pixmap;
  Window          win;
  GC              gc, gc1, junkgc;
  unsigned long   bgpv;

  win = EZ_WidgetWindow(wptr);
  w   = EZ_WidgetWidth(wptr);
  h   = EZ_WidgetHeight(wptr);

  /*-----------------------------------------------------------
   *  Create a pixmap, draw into this pixmap in background and
   *  copy to the button window when finished.
   *----------------------------------------------------------*/
  pixmap = XCreatePixmap(EZ_DisplayForWidgets, win, w, h, EZ_DepthForWidgets);   
  /*----------------------------------------------------------
   *       Fill the background 
   *---------------------------------------------------------*/
  EZ_GetBackgroundGC(wptr, &gc, &bgpv, 0, 0);  
  XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, 0,0, w, h); 
  EZ_GetDarkBrightNormalBDGC(wptr, &gc, &gc1, &junkgc); /* dark, bright */
  y = (h>>1) - 1;
  XDrawLine(EZ_DisplayForWidgets,pixmap, gc,  0, y,   w, y);
  y = (h>>1) + 1;
  XDrawLine(EZ_DisplayForWidgets,pixmap, gc1,  0, y,   w, y);

  XCopyArea(EZ_DisplayForWidgets,pixmap,win, EZ_WRITABLEGC,0,0,w,h,0,0); 
  XFreePixmap(EZ_DisplayForWidgets, pixmap);                             
}

void EZ_MenuSeparatorEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  if(widget == (EZ_Widget *)NULL)   return;

  if(event->type == Expose)   EZ_DrawWidget(widget);      
  else  if(event->type == KeyPress || (event->type == ButtonPress &&
				       event->xbutton.button == EZ_Btn1))
    EZ_HandleToplevelMenuEvents(widget, event); 
}



/*********************************************************************
 ***                                                               ***
 ***                   Menu item:  submenu                         ***
 ***                                                               ***
 *********************************************************************/

EZ_Widget  *EZ_CreateMenuSubMenu(parent,label, underline)
     EZ_Widget  *parent;     /* parent widget    */
     char       *label;
     int        underline;
{
  EZ_Widget  *wptr;

  wptr = EZ_CreateNewWidget(parent);
  /*--------------------------------------------------
   * Register the handling functions for ...
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_MENU_SUBMENU] = &EZ_MenuSubmenuHandle;

  EZ_SetWidgetTypeAndNames(wptr,EZ_WIDGET_MENU_SUBMENU);
  EZ_WidgetBorderStyle(wptr)  = EZ_BORDER_NONE;
  EZ_WidgetLabelPosition(wptr) = EZ_LEFT;
  EZ_WidgetBorderWidth(wptr)  = 2;
  EZ_WidgetPadY(wptr) = 1;
  EZ_WidgetPadB(wptr) = 0;

  EZ_WidgetSepX(wptr) = EZ_WIDGET_DEFAULT_PADX;
  EZ_WidgetSepY(wptr) = EZ_WIDGET_DEFAULT_PADY;

  EZ_SubMenuLabel(wptr) = EZ_AllocCopyString(label);
  EZ_SubMenuLabelLength(wptr) = (label == (char *)NULL? 1 : strlen(label));
  EZ_SubMenuPixmap(wptr) = (EZ_Bitmap *)NULL;
  EZ_SubMenuFont(wptr)  = EZ_GetFontFromId(EZ_MENU_FONT);

  EZ_SubMenuTWidth(wptr) = 0;
  EZ_SubMenuTHeight(wptr) = 0;
  EZ_SubMenuFontAscent(wptr) = 0;
  EZ_SubMenuArrowSize(wptr) = 8;
  EZ_SubMenuArrowBWidth(wptr) = 1;

  EZ_SubMenuLineLength(wptr) = EZ_DEFAULT_LABEL_LINE_LENGTH;
  EZ_SubMenuNLines(wptr)  = 1;

  EZ_SubMenuLabel2(wptr) = (char *)NULL;
  EZ_SubMenuLabel2Length(wptr) = 0;
  EZ_SubMenuLabel2Width(wptr) = 0;

  if(label && underline >= 0 && underline < EZ_SubMenuLabelLength(wptr) && isprint(label[underline]))
    {
      EZ_SubMenuUnderLine(wptr) = underline;
      EZ_SubMenuModifiers(wptr) = Mod1Mask;
      EZ_SubMenuShortcut(wptr)  = (EZ_SubMenuLabel(wptr) + underline);
      EZ_InsertGlobalKeyPressEvent(wptr, Mod1Mask, (label+underline));
    }
  else
    {
      EZ_SubMenuUnderLine(wptr) = -1;
      EZ_SubMenuModifiers(wptr) = 0;
      EZ_SubMenuShortcut(wptr)  = (char *)NULL;
    }

  EZ_SubMenuTheMenu(wptr) = (EZ_Widget *)NULL;
  EZ_SubMenuCopy(wptr) = (EZ_Widget *)NULL;

  EZ_SetWidgetFocusableFlag(wptr);

  return(wptr);
}

/*
 *  Free private data for a submenu
 */
void  EZ_FreeWidgetMenuSubMenuData(widget)
     EZ_Widget *widget;
{
  if(EZ_SubMenuLabel(widget) != (char *)NULL)
    (void) my_free ((char *)EZ_SubMenuLabel(widget));
  if(EZ_SubMenuLabel2(widget) != (char *)NULL)
    (void) my_free ((char *)EZ_SubMenuLabel2(widget));
  if(EZ_SubMenuPixmap(widget) != (EZ_Bitmap *)NULL)
    EZ_FreeBitmap(EZ_SubMenuPixmap(widget));
}

/*
 *  Figure out the dimension of a submenu
 */
void EZ_ComputeWidgetMenuSubMenuSize(widget, w, h)
    EZ_Widget *widget;
     int             *w, *h;
{
  int length, height, cw, ch;;

  if(!(EZ_GetWidgetSizeComputedFlag(widget)))
    { 
      if( EZ_SubMenuPixmap(widget) == (EZ_Bitmap *)NULL)
	{
	  int nlines, twidth;

	  EZ_FigureLabelExtent(EZ_SubMenuFont(widget),
			       EZ_SubMenuLabel(widget),
			       (int)EZ_SubMenuLabelLength(widget),
			       (int)EZ_SubMenuLineLength(widget),
			       &nlines, &twidth);
	  EZ_SubMenuTWidth(widget) = twidth;
	  EZ_SubMenuNLines(widget) = nlines;

	  EZ_SubMenuTHeight(widget) = EZ_SubMenuFont(widget)->ascent +
	    EZ_SubMenuFont(widget)->descent;
	  EZ_SubMenuFontAscent(widget) = EZ_SubMenuFont(widget)->ascent;

	  EZ_SubMenuArrowSize(widget) = 
	    ((EZ_SubMenuTHeight(widget) *  EZ_SubMenuNLines(widget))<<1)/3;

	  if(EZ_SubMenuLabel2Length(widget) != 0)
	    {
	      EZ_SubMenuLabel2Width(widget) = EZ_LABEL_SEPARATION +
		XTextWidth(EZ_SubMenuFont(widget), 
			   EZ_SubMenuLabel2(widget),
			   EZ_SubMenuLabel2Length(widget));
	    }
	}
      else
	{
	  EZ_Bitmap *tmp = EZ_SubMenuPixmap(widget);
	  EZ_SubMenuNLines(widget) = 1;
	  EZ_SubMenuTWidth(widget) = tmp->width;
	  EZ_SubMenuTHeight(widget) = tmp->height;
	}
      EZ_SetWidgetSizeComputedFlag(widget);
    }

  EZ_WidgetAuxXRight(widget) = EZ_SubMenuLabel2Width(widget) +
    EZ_SubMenuArrowSize(widget) + (EZ_SubMenuArrowBWidth(widget)<<1) + 8;
  length = EZ_SubMenuTWidth(widget) + EZ_WidgetAuxXRight(widget);
    
  height = MAXV(EZ_SubMenuTHeight(widget)* EZ_SubMenuNLines(widget),
		EZ_SubMenuArrowSize(widget) + (EZ_SubMenuArrowBWidth(widget)<<1));

  cw = EZ_WidgetPadX(widget) + EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  ch = EZ_WidgetPadY(widget) + EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);

  cw = cw + cw + length;  /* extra space between label and arrow */
  ch = ch + ch + height;

  *w = cw;
  *h = ch;
}

/*
 *
 *  Draw a SubMenu item. (not the menu !)
 */

void  EZ_DrawWidgetMenuSubMenu(wptr)
     EZ_Widget *wptr;
{
  int             w, h,x,y, xx, yy, fillx, filly, padb, padb2, offset, offseta = 0, filled = 0;
  Pixmap          pixmap;
  Window          win;
  GC              gc;
  int             arrow_style;
  unsigned long   bgpv, bgpva;

  win = EZ_WidgetWindow(wptr);
  w   = EZ_WidgetWidth(wptr);
  h   = EZ_WidgetHeight(wptr);
  padb = EZ_WidgetPadB(wptr);
  padb2 = padb + padb;

  EZ_GetWidgetLabelPosition(wptr, &fillx, &filly);

  /*-----------------------------------------------------------
   *  Create a pixmap, draw into this pixmap in background and
   *  copy to the SubMenu window when finished.
   *----------------------------------------------------------*/
  pixmap = XCreatePixmap(EZ_DisplayForWidgets, win, w, h, EZ_DepthForWidgets);    
  if(padb > 0)
    {
      EZ_GetParentBgGCN(wptr, &gc,&bgpva);
      XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, 0,0, w, h); 
      filled = 1;
    }
  else bgpva = 0;  
  EZ_GetBackgroundGC(wptr, &gc, &bgpv, 1,0);
  if(filled == 0 || bgpv != bgpva)
    XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, padb,padb, w-padb2, h-padb2); 

  /*--------------------------------------------------------
   *  Draw the label.
   *-------------------------------------------------------*/
  xx = EZ_WidgetXOffset(wptr) + fillx;
  yy = EZ_WidgetYOffset(wptr) + filly;

  if(EZ_OffsetEnabled && EZ_WidgetBorderStyle(wptr) == EZ_BORDER_DOWN)  offseta = 1;
  offset = padb + offseta;
  x = xx + EZ_WidgetPadX(wptr) + EZ_WidgetBorderWidth(wptr) + offset;
  y = yy + EZ_SubMenuFontAscent(wptr) + EZ_WidgetBorderWidth(wptr) + EZ_WidgetPadY(wptr) + offset;
  
  if(EZ_SubMenuPixmap(wptr) == (EZ_Bitmap *)NULL)
    {
      if( EZ_GetWidgetDisabledFlag(wptr) )
	{
	  GC  bgc, lgc, ngc;
	  EZ_GetDarkBrightNormalBDGC(wptr, &bgc, &lgc, &ngc);
	  XSetFont(EZ_DisplayForWidgets, bgc, EZ_WidgetFont(wptr)->fid);
	  XSetFont(EZ_DisplayForWidgets, lgc, EZ_WidgetFont(wptr)->fid);
	  XSetFont(EZ_DisplayForWidgets, ngc, EZ_WidgetFont(wptr)->fid);

	  EZ_RenderLabelTextDisabled(pixmap, lgc, bgc, ngc, x, y, 
				     (int)EZ_SubMenuTHeight(wptr), EZ_SubMenuLabel(wptr),
				     (int)EZ_SubMenuLabelLength(wptr), (int)EZ_SubMenuLineLength(wptr),
				     (int)EZ_SubMenuNLines(wptr),
				     (int)EZ_SubMenuTWidth(wptr),
				     (int)EZ_WidgetJustification(wptr),
				     EZ_SubMenuFont(wptr));
	}
      else
	{
	  if(EZ_SubMenuForeground(wptr) != EZ_DefaultForeground || 
	     EZ_SubMenuFont(wptr) != EZ_GetFontFromId(EZ_MENU_FONT))
	    {
	      XSetFont(EZ_DisplayForWidgets, EZ_WRITABLEGC, EZ_SubMenuFont(wptr)->fid);
	      XSetForeground(EZ_DisplayForWidgets, EZ_WRITABLEGC, EZ_SubMenuForeground(wptr));	
	      gc = EZ_WRITABLEGC;
	    }
	  else  gc = EZ_MENU_TEXTGC;
	  
	  EZ_RenderLabelText(pixmap, gc, x, y, (int)EZ_SubMenuTHeight(wptr), EZ_SubMenuLabel(wptr),
			     (int)EZ_SubMenuLabelLength(wptr), (int)EZ_SubMenuLineLength(wptr),
			     (int)EZ_SubMenuNLines(wptr),
			     (int)EZ_SubMenuTWidth(wptr),
			     (int)EZ_WidgetJustification(wptr),
			     EZ_SubMenuFont(wptr));

	  if(EZ_SubMenuLabel2Length(wptr) != 0)
	    {
	      int tmpx =  w - (EZ_WidgetPadX(wptr) + EZ_WidgetBorderWidth(wptr) + padb +
			       EZ_WidgetAuxXRight(wptr)) + offseta + EZ_LABEL_SEPARATION;
	      XDrawString(EZ_DisplayForWidgets, 
			  pixmap,  gc,
			  tmpx, ((h+EZ_SubMenuFontAscent(wptr))>>1) + offseta, 
			  EZ_SubMenuLabel2(wptr),
			  EZ_SubMenuLabel2Length(wptr));
	    }
	  else if(EZ_SubMenuUnderLine(wptr) >= 0 && 
		  EZ_SubMenuUnderLine(wptr) < ((int)EZ_SubMenuLineLength(wptr)>>1))
	    {
	      int tlen = XTextWidth(EZ_SubMenuFont(wptr),EZ_SubMenuLabel(wptr),
				    EZ_SubMenuUnderLine(wptr));
	      int tlen1 = tlen + XTextWidth(EZ_SubMenuFont(wptr),
					    EZ_SubMenuLabel(wptr)+EZ_SubMenuUnderLine(wptr), 1);
	      int base = y + EZ_SubMenuTHeight(wptr) - EZ_SubMenuFontAscent(wptr)-1;
	      int boldfont;

	      if(EZ_SubMenuFont(wptr) != EZ_GetFontFromId(EZ_MENU_FONT))
		boldfont = (EZ_GetWidgetThinFontFlag(wptr) == 0);
	      else boldfont = EZ_LabelFontIsBold; 	  
	      
	      XDrawLine(EZ_DisplayForWidgets, pixmap, gc,
			x+tlen, base, x+tlen1, base);
	      if(boldfont)
		XDrawLine(EZ_DisplayForWidgets, pixmap, gc,
			  x+tlen, base+1, x+tlen1, base+1);
	    }

	}
    }
  else    /* copy the pixmap */
    {
      EZ_Bitmap *tmp = EZ_SubMenuPixmap(wptr);
      EZ_RenderPixmapLabel(wptr, tmp, pixmap, x, y - (int)( EZ_SubMenuFontAscent(wptr)));
    }
  arrow_style = EZ_BORDER_UP;
  if(EZ_WidgetBorderStyle(wptr) == EZ_BORDER_UP)
    arrow_style = EZ_BORDER_DOWN;

  /*--------------------------------------------------------
   *  Draw the little arrow.
   *-------------------------------------------------------*/  
  x = w - (EZ_WidgetPadX(wptr) + EZ_WidgetBorderWidth(wptr) + padb +
	   EZ_SubMenuArrowSize(wptr) + ( EZ_SubMenuArrowBWidth(wptr)<<1) );
  y =  ((h - EZ_SubMenuArrowSize(wptr))>>1) -  EZ_SubMenuArrowBWidth(wptr);
    
  EZ_DrawHRArrow(wptr,pixmap,x,y,
		 EZ_SubMenuArrowSize(wptr) + (EZ_SubMenuArrowBWidth(wptr)<<1),
		 arrow_style, 
		 EZ_SubMenuArrowBWidth(wptr),
		 EZ_GetWidgetHighlightFlag(wptr));

  /*============================================================
   *for complex button with  NW labels 
   */
  {
    EZ_Widget *children = EZ_WidgetChildren(wptr);
    if(children && EZ_WidgetType(children) == EZ_WIDGET_NW_LABEL)
      {
	EZ_DisplayNWLabel(children, pixmap, EZ_WidgetForeground(wptr), bgpv,
			  EZ_GetWidgetDisabledFlag(wptr), EZ_GetWidgetHighlightFlag(wptr),
			  0, 0, offset,1);
      }
  }
  /*============================================================*/  

  
  EZ_DrawRectBorder(wptr, pixmap);
  XCopyArea(EZ_DisplayForWidgets,pixmap,win, EZ_WRITABLEGC,0,0,w,h,0,0); 
  XFreePixmap(EZ_DisplayForWidgets, pixmap);                             
}


/*
 * Submenu Event handle.
 */

void EZ_MenuSubMenuEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  if(widget == (EZ_Widget *)NULL)   return;

  if(EZ_GetWidgetDisabledFlag(widget))
    {
      if(event->type == Expose)	EZ_DrawWidget(widget);      
      else if(event->type == EnterNotify)
	EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      else  if(event->type == KeyPress || (event->type == ButtonPress &&
					   event->xbutton.button == EZ_Btn1))
	EZ_HandleToplevelMenuEvents(widget, event); 
      return;
    }

  switch(event->type)
    {
    case Expose:
      EZ_DrawWidget(widget);      
      break;
    case ButtonPress:
      if(!event->xbutton.send_event)
	{
	  EZ_WidgetBorderStyle(widget) = EZ_BORDER_DOWN;
	  EZ_DrawWidget(widget);
	}
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	{
	  EZ_DisplayPopupSubMenuOf(widget);
	  EZ_HandleToplevelMenuEvents(widget, event); 
	}
      break;
    case ButtonRelease:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_DrawWidget(widget);
      break;
    case EnterNotify:
    case FocusIn:
      EZ_SetWidgetHighlightFlag(widget);
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_DrawWidget(widget);
      if(EZ_CurrentPopupMenu != (EZ_Widget *)NULL)  /* 1-7-97 */
	EZ_DisplayPopupSubMenuOf(widget);
      break;
    case LeaveNotify:
      if(event->xcrossing.mode == NotifyGrab  ||
	 event->xcrossing.mode == NotifyUngrab)
	break;
    case FocusOut:
      EZ_ClearWidgetHighlightFlag(widget);
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      EZ_DrawWidget(widget);      
      break;
    case KeyPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    default:
      break;
    }
}


/*********************************************************************
 *
 *  Check whether the menu hierarchy contains a loop.
 *  return 1 if a loop is found.
 */
static int check_loop_in_popup(m1, m)
     EZ_Widget *m1,*m;
{
  EZ_Widget *children;
  EZ_Widget *tmp;

  tmp = m1;
  if(tmp != (EZ_Widget *)NULL)
    {
      children = EZ_WidgetChildren(tmp);
      while(children != (EZ_Widget *)NULL)
	{
	  if(EZ_WidgetType(children) == EZ_WIDGET_MENU_SUBMENU)
	    {
	      if(EZ_SubMenuTheMenu(children) == m) return(1);
	      else if(check_loop_in_popup(EZ_SubMenuTheMenu(children), m)) return(1);
	    }
	  children = EZ_WidgetSibling(children);
	}
    }
  return(0);
}
/*********************************************************************
 *
 *   Set the menu for a submenu.
 */
void EZ_SetSubMenuMenu(subm, m)
     EZ_Widget *subm, *m;
{
  if(subm != (EZ_Widget *)NULL &&
     EZ_WidgetType(subm) == EZ_WIDGET_MENU_SUBMENU)
    {
      if(m != (EZ_Widget *)NULL)
	{
	  if(EZ_WidgetType(m) == EZ_WIDGET_POPUP_MENU)
	    {
	      EZ_SubMenuTheMenu(subm) = m;
	      if(check_loop_in_popup(m,m) == 1)
		{
		  (void)fprintf(stderr, "Error: Loop detected in a menu hierarchy!\n\
       Operation 'EZ_SetSubMenuMenu' is ignored.\n\
       SubMenu item=%lx, Menu=%lx\n",(unsigned long)subm,(unsigned long)m);
		  EZ_SubMenuTheMenu(subm) = (EZ_Widget *)NULL;
		}
	    }
	}
      else
	EZ_SubMenuTheMenu(subm) = m;
    }
}

/*********************************************************************
 ***                                                               ***
 ***                    Menu item:  normal button                  ***
 ***                                                               ***
 *********************************************************************/

EZ_Widget  *EZ_CreateMenuNormalButton(parent, label, underline, ret_value)
     EZ_Widget *parent;
     char            *label;
     int             ret_value, underline;
{
  EZ_Widget *tmp;

  tmp = EZ_CreateButton(parent,label, underline);
  /*--------------------------------------------------
   * Register the handling functions for ...
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_MENU_NORMAL_BUTTON] = &EZ_MenuNormalButtonHandle;

  EZ_SetWidgetTypeAndNames(tmp,EZ_WIDGET_MENU_NORMAL_BUTTON);
  EZ_WidgetBorderStyle(tmp) = EZ_BORDER_NONE;  
  EZ_WidgetLabelPosition(tmp) = EZ_LEFT_2_RIGHT;
  EZ_WidgetPadY(tmp) = 1;
  EZ_WidgetPadB(tmp) = 0;
  EZ_WidgetRetData(tmp) = ret_value;

  /* EZ_ClearWidgetFocusableFlag(tmp);   */

  return(tmp);
}
/*
 *   event handle
 */
void EZ_MenuNormalButtonEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  if(widget == (EZ_Widget *)NULL) return;

  if(EZ_GetWidgetDisabledFlag(widget))
    {
      if(event->type == Expose)	EZ_DrawWidget(widget);      
      else if(event->type == EnterNotify)
	EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      else  if(event->type == KeyPress || (event->type == ButtonPress &&
				       event->xbutton.button == EZ_Btn1))
	EZ_HandleToplevelMenuEvents(widget, event); 
      return;
    }

  switch(event->type)
    {
    case Expose:
      EZ_DrawWidget(widget);      
      break;
    case ButtonPress:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_DOWN;
      EZ_DrawWidget(widget);
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;

    case ButtonRelease:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_DrawWidget(widget);
      if(EZ_CurrentPopupMenu != (EZ_Widget *)NULL)
	{
	  EZ_WidgetRetData(EZ_CurrentPopupMenu) = EZ_WidgetRetData(widget); /* return value */
	  EZ_PopupLSItem(EZ_CurrentPopupMenu) = widget;   /* this is the selected item     */
	}
      break;
    case EnterNotify:
    case FocusIn:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_SetWidgetHighlightFlag(widget);
      EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      EZ_DrawWidget(widget);
      break;
    case LeaveNotify:
      if(event->xcrossing.mode == NotifyGrab  ||
	 event->xcrossing.mode == NotifyUngrab)
	break;
    case FocusOut:
      EZ_ClearWidgetHighlightFlag(widget);
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      EZ_DrawWidget(widget);      
      break;
    case KeyPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    default:
      break;
    }
}

/*********************************************************************
 ***                                                               ***
 ***                    Menu item:  check button                   ***
 ***                                                               ***
 *********************************************************************/

EZ_Widget  *EZ_CreateMenuCheckButton(parent, label, underline, onvalue, offvalue, onoff,ret_value)
     EZ_Widget  *parent;     /* parent widget    */
     char             *label;
     int              onvalue, offvalue, onoff;
     int              ret_value, underline;
{
  EZ_Widget *tmp;

  tmp = EZ_CreateCheckButton(parent, label, underline, onvalue,offvalue, onoff);
  /*--------------------------------------------------
   * Register the handling functions for ...
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_MENU_CHECK_BUTTON] = &EZ_MenuCheckButtonHandle;

  EZ_SetWidgetTypeAndNames(tmp,EZ_WIDGET_MENU_CHECK_BUTTON);
  EZ_WidgetBorderStyle(tmp) = EZ_BORDER_NONE;  
  EZ_WidgetLabelPosition(tmp) = EZ_LEFT_2_RIGHT;
  EZ_WidgetPadY(tmp) = 0;
  EZ_WidgetPadB(tmp) = 0;
  EZ_WidgetRetData(tmp) = ret_value;
  EZ_CButtonCheckSizeAdjust(tmp) = 3;

  /* EZ_ClearWidgetFocusableFlag(tmp);   */

  return(tmp);
}

/*
 *   event handle
 */
void EZ_MenuCheckButtonEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  if(widget == (EZ_Widget *)NULL) return;
  
  if(EZ_GetWidgetDisabledFlag(widget))
    {
      if(event->type == Expose)
	EZ_DrawWidget(widget);      
      else if(event->type == EnterNotify)
	EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      else  if(event->type == KeyPress || (event->type == ButtonPress &&
					   event->xbutton.button == EZ_Btn1))
	EZ_HandleToplevelMenuEvents(widget, event); 
      return;
    }

  switch(event->type)
    {
    case Expose:
      EZ_DrawWidget(widget);      
      break;
    case ButtonPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    case ButtonRelease:
      if( EZ_CButtonOn(widget) )
	{
	  EZ_CButtonSetOffValue(widget);
	}
      else
	{
	  EZ_CButtonSetOnValue(widget);
	}
      EZ_DrawWidget(widget);
      if(EZ_CurrentPopupMenu != (EZ_Widget *)NULL)
	{
	  EZ_WidgetRetData(EZ_CurrentPopupMenu) = EZ_WidgetRetData(widget);
	  EZ_PopupLSItem(EZ_CurrentPopupMenu) = widget;  /* this is the selected item     */
	}
      break;

    case EnterNotify:
    case FocusIn:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_SetWidgetHighlightFlag(widget);
      EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      EZ_DrawWidget(widget);
      break;
    case LeaveNotify:
      if(event->xcrossing.mode == NotifyGrab  ||
	 event->xcrossing.mode == NotifyUngrab)
	break;
    case FocusOut:
      EZ_ClearWidgetHighlightFlag(widget);
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      EZ_DrawWidget(widget);      
      break;
    case KeyPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    default:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      break;
    }
}


/*********************************************************************
 ***                                                               ***
 ***                    Menu item:  radio button                   ***
 ***                                                               ***
 *********************************************************************/

EZ_Widget  *EZ_CreateMenuRadioButton(parent, label, underline, gid, value, ret_value)
     EZ_Widget  *parent;     /* parent widget    */
     char             *label;
     int              value, gid;
     int              ret_value, underline;
{
  EZ_Widget *tmp;

  tmp = EZ_CreateRadioButton(parent,label,underline, gid, value);
  /*--------------------------------------------------
   * Register the handling functions for ...
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_MENU_RADIO_BUTTON] = &EZ_MenuRadioButtonHandle;

  EZ_SetWidgetTypeAndNames(tmp,EZ_WIDGET_MENU_RADIO_BUTTON);
  EZ_WidgetBorderStyle(tmp) = EZ_BORDER_NONE;  
  EZ_WidgetLabelPosition(tmp) = EZ_LEFT_2_RIGHT;
  EZ_WidgetPadY(tmp) = 0;
  EZ_WidgetPadB(tmp) = 0;
  EZ_WidgetRetData(tmp) = ret_value;
  EZ_RButtonCheckSizeAdjust(tmp) = 3; 

  /* EZ_ClearWidgetFocusableFlag(tmp); */

  return(tmp);  
}

/*
 *   event handle
 */
void EZ_MenuRadioButtonEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  if(widget == (EZ_Widget *)NULL) return;
  
  if(EZ_GetWidgetDisabledFlag(widget))
    {
      if(event->type == Expose)	EZ_DrawWidget(widget);      
      else if(event->type == EnterNotify)
	EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      else  if(event->type == KeyPress || (event->type == ButtonPress &&
					   event->xbutton.button == EZ_Btn1))
	EZ_HandleToplevelMenuEvents(widget, event); 
      return;
    }

  switch(event->type)
    {
    case Expose:
	EZ_DrawWidget(widget);      
      break;
    case ButtonPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    case ButtonRelease:      
      if( !( EZ_RButtonOn(widget)) )
	{
	  EZ_RButtonList  *friends;
	  EZ_Widget *old = (EZ_Widget *)NULL;

	  friends = EZ_RButtonGroup(widget)->list;
	  while(friends)
	    {
	      if( EZ_RButtonOn( friends->rbutton) )
		{
		  old = friends->rbutton;  /* currently checked  */
		  break;
		}
	      friends = friends->next;
	    }
	  EZ_RButtonSetValue(widget);
	  EZ_DrawWidget(widget);
	  if(old && EZ_WidgetMapped(old)) EZ_DrawWidget(old);
	}
      if(EZ_CurrentPopupMenu != (EZ_Widget *)NULL)
	{
	  EZ_WidgetRetData(EZ_CurrentPopupMenu) = EZ_WidgetRetData(widget);
	  EZ_PopupLSItem(EZ_CurrentPopupMenu) = widget;  /* this is the selected item     */
	}
      break;
    case EnterNotify:
    case FocusIn:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
      EZ_SetWidgetHighlightFlag(widget);
      EZ_HideSubMenuOf(EZ_WidgetParent(widget));
      EZ_DrawWidget(widget);
      break;
    case LeaveNotify:
      if(event->xcrossing.mode == NotifyGrab  ||
	 event->xcrossing.mode == NotifyUngrab)
	break;
    case FocusOut:
      EZ_ClearWidgetHighlightFlag(widget);
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      EZ_DrawWidget(widget);      
      break;
    case KeyPress:
      if(EZ_CurrentPopupMenu == (EZ_Widget *)NULL)
	EZ_HandleToplevelMenuEvents(widget, event); 
      break;
    default:
      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NONE;
      break;
    }
}
/**************************************************************/
EZ_Widget *EZ_GetMenuItemCompaion(widget)
     EZ_Widget *widget;
{
  if(widget)
    {
      int WType = EZ_WidgetType(widget);
      EZ_Widget *clone;
      
      switch(WType)
	{
	case EZ_WIDGET_MENU_SEPARATOR:
	    clone = EZ_MenuSeparatorCopy(widget);
	      break;
	case EZ_WIDGET_MENU_SUBMENU:
	    clone = EZ_SubMenuCopy(widget);
	      break;
	case EZ_WIDGET_MENU_NORMAL_BUTTON:
	    clone = EZ_ButtonCopy(widget);
	      break;
	case EZ_WIDGET_MENU_CHECK_BUTTON:
	    clone = EZ_CButtonCopy(widget);
	      break;
	case EZ_WIDGET_MENU_RADIO_BUTTON:
	    clone = EZ_RButtonCopy(widget);
	      break;
	default:
	    clone = NULL;
	      break;
	}
      return(clone);
    }
  return(NULL);
}
/**************************************************************************************/
#undef _EZ_WIDGET_MENU_ITEMS_C_










