

/* MenuMgr_draw.c */

#include <stdio.h>
#include <sys/types.h>
#include <X10/Xlib.h>

#include "MenuMgr.h"

extern int		mm_debug;
extern FontFamily	mm_Fonts;
extern XAssocTable *	mm_AssocTable;
extern Cursor		mm_Cursor;
extern Defaults		mm_Defs;

#define DEBUG( s,n )	if(mm_debug <= n) printf s
#define max(a,b)	((a)>(b) ? (a) : (b))

/* ---------------------------------------------------------------------- */

int
mm_AttachMenuBar( mbp, pw )

	MenuBarPtr	mbp;		/* menu bar to attach */
	Window		pw;		/* parent window */

{
static char *funcname = "mm_AttachMenuBar";
WindowInfo	wi;
WindowInfo	mbwi;	/* for menu bar */
MenuPtr		mp;
TransparentFrame *tf = NULL;
int		x,y;
int		ax,ay;
int		extra;
int		i;
DefsPtr		d = &mm_Defs;

	if( !XQueryWindow(pw,&wi) ) {
		fprintf(stderr,
		"%s: can't query parent window.\n",funcname);
		return -1;
		}

	/* create the menu and title bars */

	if( (mbp->mbarMenuWindow = XCreateWindow( pw,
		-(d->extMborder),
		(mm_Fonts.fi[mm_Fonts.tallest]->height)+(2*d->intNborder)+
			(2*d->extNborder),
		wi.width+1,
		(mm_Fonts.fi[mm_Fonts.tallest]->height)+(2*d->intMborder),
		d->extMborder, d->fgpixmap, d->bgpixmap )) == 0 )
	{
		fprintf(stderr,
			"%s: XCreateWindow() failed on menuwindow\n",funcname);
		return -1;
	}
	else
		XMakeAssoc( mm_AssocTable, mbp->mbarMenuWindow,(caddr_t)mbp );

	
	if( (mbp->mbarNameWindow = XCreateWindow( pw, 0,0, 
		wi.width-(2*d->extNborder),
		(mm_Fonts.fi[mm_Fonts.tallest]->height)+(2*d->intNborder), 
		d->extNborder, d->bgpixmap, d->fgpixmap )) == 0 )
	{
		fprintf(stderr,
			"%s: XCreateWindow() failed on namewindow\n",funcname);
		return -1;
	}
	else
		XMakeAssoc( mm_AssocTable, mbp->mbarNameWindow,(caddr_t)mbp );

	/* remember bottom of menu bar */
	/* NOTE: BottomEdge is first pixel of border below menu strip */

	XQueryWindow(mbp->mbarNameWindow,&mbwi);
	mbp->mbarBottomEdge = mbwi.y + mm_MBarsHeight(d,mm_Fonts)-1;

	/* now create the command button windows */

	mm_CountMenus(mbp);
	tf = (TransparentFrame *) 
		malloc( sizeof(TransparentFrame) * mbp->mbarMenuCount );

	x=0;
	y=0;
	extra = mm_Fonts.fi[mm_Fonts.widest]->width*2;
	
	for( 	i=0,mp=mbp->mbarMList; 
		mp;
		mp=mp->menuNext,i++ ) 
	{
		mp->menuTitleOffWidth = XStringWidth( mp->menuTitle, 
			mm_Fonts.fi[d->offstyle], 0,0 );
		mp->menuTitleOnWidth = XStringWidth( mp->menuTitle, 
			mm_Fonts.fi[d->onstyle], 0,0 );
		tf[i].x = x;
		tf[i].y = y;
		tf[i].width = max(mp->menuTitleOffWidth,mp->menuTitleOnWidth) 
			+ extra + 2*d->intMborder;
		tf[i].height = mm_Fonts.fi[mm_Fonts.tallest]->height +
			2*d->intMborder;
		x += tf[i].width;
	}

	XCreateTransparencies( mbp->mbarMenuWindow, tf, mbp->mbarMenuCount );

	for( 	i=0,mp=mbp->mbarMList; 
		mp; 
		mp=mp->menuNext,i++ )
	{
		mp->menuTitleWindow = tf[i].self;
		XSelectInput( mp->menuTitleWindow, mm_MenuTitleEvents );
		XMakeAssoc( mm_AssocTable, tf[i].self, (caddr_t)mp );
		mp->menuLeftEdge = tf[i].x;
	}
	
	if( tf )
		free( (char *) tf );
	mbp->mbarParentWindow = pw;
	XMakeAssoc( mm_AssocTable, pw, (caddr_t)mbp );

	/* define cursors for menu bar(s) */
	XDefineCursor( mbp->mbarParentWindow, mm_Cursor );

	/* make the move-hack window */
	Get_Absolute_Coords( mbp->mbarNameWindow, 0,0, &ax, &ay );
	mbp->mbarMoveHackWindow = 
		XCreateWindow(RootWindow,ax,ay,1,1,0,d->fgpixmap,d->fgpixmap);
	
	/* set the events to look for relative to menu bar */
	XSelectInput(mbp->mbarParentWindow,mm_MBarParentEvents);
	XSelectInput(mbp->mbarNameWindow,mm_MBarNameEvents);
	XSelectInput(mbp->mbarMenuWindow,mm_MBarMenuEvents);

	return 0;
}
/* ---------------------------------------------------------------------- */

int
mm_DetachMenuBar( mbp )

	MenuBarPtr	mbp;		/* menu bar to detach */
{
static char *funcname = "mm_DetachMenuBar";
MenuPtr		mp;

	XDeleteAssoc( mm_AssocTable, mbp->mbarMenuWindow );
	XDeleteAssoc( mm_AssocTable, mbp->mbarNameWindow );
	XDeleteAssoc( mm_AssocTable, mbp->mbarParentWindow );

	XDestroyWindow( mbp->mbarNameWindow );
	XDestroyWindow( mbp->mbarMoveHackWindow );

	mbp->mbarParentWindow = 0;
	mbp->mbarNameWindow = 0;
	mbp->mbarMoveHackWindow = 0;

	mbp->mbarBottomEdge = 0;

	for( 	mp=mbp->mbarMList; 
		mp; 
		mp=mp->menuNext )
	{
		mp->menuLeftEdge = 0;
		XDeleteAssoc( mm_AssocTable, mp->menuTitleWindow );
		XDestroyWindow( mp->menuTitleWindow );
		mp->menuTitleWindow = 0;
	}

	XDestroyWindow( mbp->mbarMenuWindow );
	mbp->mbarMenuWindow = 0;
	
	return 0;
}

/* ---------------------------------------------------------------------- */

int
mm_DrawMenuBar( mbp )

	MenuBarPtr	mbp;
{
WindowInfo	wi;
MenuPtr		mp;
DefsPtr d = &mm_Defs;

	XMapWindow( mbp->mbarMenuWindow );
	XMapSubwindows( mbp->mbarMenuWindow );

	XClear( mbp->mbarMenuWindow );

	/* now update BottomEdge and LeftEdge vars */
	XQueryWindow(mbp->mbarNameWindow,&wi);
	mbp->mbarBottomEdge = wi.y + mm_MBarsHeight(d,mm_Fonts)-1;

	for( 	mp=mbp->mbarMList; 
		mp; 
		mp=mp->menuNext )
	{
		XQueryWindow( mp->menuTitleWindow, &wi );
		mp->menuLeftEdge = wi.x;
		mm_LabelMenu( mp, mm_Defs.fgcolor );
/*		(*mp->menuProc)
			(msgCalcSize,mp,0,0); */
	}
	
	return 0;
}

/* ---------------------------------------------------------------------- */

	/* this shouldn't be necessary, but if a window manager has moved
	   us, we won't know about it; clever hack makes this get called
	   after every move */

int
mm_SetNewMenuBarPos( mbp )

	MenuBarPtr	mbp;
{
WindowInfo	wi;
MenuPtr		mp;
int		ax, ay;
DefsPtr		d = &mm_Defs;

	Get_Absolute_Coords( mbp->mbarNameWindow, 0,0, &ax, &ay );
	XMoveWindow( mbp->mbarMoveHackWindow, ax, ay );

	/* now reset these guys to x,y loc of NameBar */
	ax -= d->extMborder;
	ay -= d->extMborder;

	for( 	mp=mbp->mbarMList; 
		mp; 
		mp=mp->menuNext )
	{
		if( !mp->menuWindow )
			(*mp->menuProc)
				(msgCalcSize,mp,0,0);
		else
		{
			XMoveWindow( mp->menuShadow,
				ax+mp->menuLeftEdge+d->xoff, 
				ay+mbp->mbarBottomEdge+d->yoff );
			XMoveWindow( mp->menuWindow, 
				ax+mp->menuLeftEdge, ay+mbp->mbarBottomEdge );
		}
	}
	
	return 0;
}

/* ---------------------------------------------------------------------- */

int
mm_DrawNameBar( mbp )

	MenuBarPtr	mbp;
{
WindowInfo	wi;
int		strwidth;
int		style;
DefsPtr		d = &mm_Defs;

	XMapWindow( mbp->mbarNameWindow );
	XMapWindow( mbp->mbarMoveHackWindow );

	/* first, set to background color */
	XClear( mbp->mbarNameWindow );

	XQueryWindow( mbp->mbarNameWindow, &wi );
	if( mbp->mbarNameCallback )
		style = d->onstyle;
	else
		style = d->offstyle;

	strwidth = XStringWidth( mbp->mbarName,
		mm_Fonts.fi[style], 0,0 );

	XTextMask( mbp->mbarNameWindow,
		(wi.width - strwidth)/2,
		d->intNborder, mbp->mbarName, strlen(mbp->mbarName), 
		mm_Fonts.fi[style]->id, d->bgcolor );

	return 0;
}

/* ---------------------------------------------------------------------- */

int
mm_HiliteNameBar( mbp, on )

	MenuBarPtr	mbp;
	int		on;	/* hilite if true */
{
DefsPtr		d = &mm_Defs;
WindowInfo	wi;
Vertex		vlist[4];
int		strwidth;
int		style;
int		space;

	if( !mbp )
		return -1;

	XQueryWindow( mbp->mbarNameWindow, &wi );

	if( mbp->mbarNameCallback )
		style = d->onstyle;
	else
		return -1;	/* don't do it without function */

	strwidth = XStringWidth( mbp->mbarName,
		mm_Fonts.fi[style], 0,0 );
	space = XStringWidth( "M",
		mm_Fonts.fi[style], 0,0 );

	vlist[0].x = space;
	vlist[0].y = wi.height/2;
	vlist[1].x = (wi.width/2 - strwidth/2) - space;
	vlist[1].y = vlist[0].y;
	vlist[1].flags = VertexDrawLastPoint;
	vlist[2].x = wi.width/2 + strwidth/2 + space;
	vlist[2].y = vlist[0].y;
	vlist[2].flags = VertexDontDraw;
	vlist[3].x = wi.width - space;
	vlist[3].y = vlist[0].y;
	vlist[3].flags = VertexDrawLastPoint;

	XDraw( mbp->mbarNameWindow, vlist, 4, 1,2,
		(on ? d->bgcolor : d->fgcolor),
		GXcopy, AllPlanes );
	
	return 0;
}

/* ---------------------------------------------------------------------- */

static int
mm_LabelMenu( mp, color )

	MenuPtr		mp;
	int		color;			/* a pixel value */
{
static char *funcname = "mm_LabelMenu";
int	strwidth;
int	style;
int	twidth;
DefsPtr	d = &mm_Defs;

	if( MENU_IS_ENABLED(mp) && ANY_ITEMS_ENABLED(mp) )
	{
		style = d->onstyle;	/* indicate active */
		strwidth = mp->menuTitleOnWidth;
	}
	else
	{
		style = d->offstyle;	/* indicate inactive */
		strwidth = mp->menuTitleOffWidth;
	}

	twidth = max(mp->menuTitleOffWidth,mp->menuTitleOnWidth) + 
		2*mm_Fonts.fi[mm_Fonts.widest]->width +
		2*d->intMborder;

	XTextMask( mp->menuTitleWindow,
		(twidth-strwidth)/2,
		d->intMborder,
		mp->menuTitle,strlen(mp->menuTitle),
		mm_Fonts.fi[style]->id,color );

	return 0;
}

/* ---------------------------------------------------------------------- */

int
mm_HiliteMenu( mbp, menuID )

	MenuBarPtr	mbp;
	int		menuID;
{
MenuPtr		mp;

	/* if id is zero, clears them all */

	mp = mm_GetMHandle( mbp, menuID );
	mm_HiliteMenuPtr( mbp, mp );
	return 0;
}

/* ---------------------------------------------------------------------- */

int
mm_HiliteMenuPtr( mbp, mp )

	MenuBarPtr	mbp;
	MenuPtr		mp;
{
WindowInfo	wi;
MenuPtr		tmp;
DefsPtr		d = &mm_Defs;

	for(	tmp = mbp->mbarMList;
		tmp != NULL;
		tmp = tmp->menuNext )
	{

		/* turn off any other menus that are on */

		if( tmp->menuOn && tmp!=mp )
		{
			/* set to background color */
			XClear( tmp->menuTitleWindow );
			mm_LabelMenu( tmp, d->fgcolor );
			tmp->menuOn = 0;
		}
		else if( tmp==mp && !tmp->menuOn )
		{
			XQueryWindow( tmp->menuTitleWindow, &wi );
			XPixSet( tmp->menuTitleWindow, 0,0,
				wi.width,wi.height, d->fgcolor );
			mm_LabelMenu( tmp, d->bgcolor );
			tmp->menuOn = 1;
		}
	}

	return 0;
}
