
/* MenuMgr_utils.c */

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

#include "MenuMgr.h"

extern int	mm_debug;
#define DEBUG( s,n )	if(mm_debug <= n) printf s

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

ItemPtr
mm_GetItemHandle( mp, item )

	MenuPtr		mp;
	int		item;
{
ItemPtr		ip;
int		i;	

	for(	i=1, ip = (ItemPtr) mp->menuItems;
		ip && i!=item;
		ip->itemNumber=i, ip=ip->itemNext, i++ );

	if( ip && item==i )
		return ip;
	else
		return NULL;
}

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

int
mm_CountMItems( mp )

	MenuPtr		mp;
{
int 		i;
ItemPtr		ip;

	for( 	i=0, ip=(ItemPtr)mp->menuItems;
		ip; 
		ip->itemNumber = i+1, ip = ip->itemNext, i++ );

	mp->menuItemCount = i;
	return i;
}

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

int
mm_CountMenus( mbp )

	MenuBarPtr	mbp;
{
MenuPtr	mp;
int	i;

	for( 	i=0, mp=mbp->mbarMList; 
		mp;
		mp = mp->menuNext, i++ );
	mbp->mbarMenuCount = i;
	return i;
}

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

MenuPtr
mm_GetMHandle( mbp, id )

	MenuBarPtr	mbp;
	int		id;
{
MenuPtr		mp;
	
	for( 	mp=mbp->mbarMList; 
		mp && mp->menuID != id; 
		mp=mp->menuNext );
	return mp;
}

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

int
mm_SetMenuBarName( mbp, s )

	MenuBarPtr	mbp;
	char *		s;
{
char *calloc();

	if( mbp->mbarName )
		free( (char *) mbp->mbarName );
	mbp->mbarName = calloc( 1, strlen(s)+1 );
	strcpy( mbp->mbarName, s );
	mm_DrawNameBar( mbp );
	return 0;
}

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

int
mm_SetItemLabel( ip, str )

	ItemPtr		ip;
	char *		str;
{
char *		calloc();
char *		p;

	if( !ip )
		return -1;
	if( ip->itemLabel )
		free( (char *) ip->itemLabel );
	p = calloc( 1, strlen(str)+1 );
	strcpy( p, str );
	ip->itemLabel = p;
	return 0;
}

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

char *
mm_GetItemLabel( ip )

	ItemPtr		ip;
{
	if( !ip )
		return NULL;
	return ip->itemLabel;
}

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

int
mm_SetItemCheck( ip, on )

	ItemPtr		ip;
	int		on;
{
TextDataPtr	tdp;

	if( !ip )
		return -1;
	tdp = (TextDataPtr) ip->itemData;
	if( tdp && tdp->tdMagic == TEXT_MAGIC )
		tdp->tdMarked = on;
	else
		return -1;
	return 0;
}

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

int
mm_GetItemCheck( ip )

	ItemPtr	ip;
{
TextDataPtr	tdp;

	if( !ip )
		return -1;
	tdp = (TextDataPtr) ip->itemData;
	if( !tdp || tdp->tdMagic != TEXT_MAGIC )
		return -1;
	return tdp->tdMarked;
}

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

int
mm_GetItemEquiv( ip )

	ItemPtr	ip;
{
TextDataPtr	tdp;

	if( !ip )
		return -1;
	tdp = (TextDataPtr) ip->itemData;
	if( !tdp || tdp->tdMagic != TEXT_MAGIC )
		return -1;
	return tdp->tdEquiv;
}

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

int
mm_SetItemEquiv( ip, code )

ItemPtr		ip;
{
TextDataPtr	tdp;

	if( !ip )
		return -1;
	tdp = (TextDataPtr) ip->itemData;
	if( !tdp || tdp->tdMagic != TEXT_MAGIC )
		return -1;
	tdp->tdEquiv = code;
	return 0;
}

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

/* removes a menu from a menu bar */

int
mm_DeleteMenu( mbp, mp )

	MenuBarPtr	mbp;
	MenuPtr		mp;
{
MenuPtr		cur, prev;

	if( !mbp || !mp )
		return -1;

	for( 	prev = NULL, cur = mbp->mbarMList;
		cur && cur!=mp;
		prev = cur, cur = cur->menuNext );

	if( !cur )
		return -1;	/* could not find: not deleted */

	if( prev == NULL )
		mbp->mbarMList = cur->menuNext;
	else
		prev->menuNext = cur->menuNext;
	mm_CountMenus( mbp );

	for( 	cur = mbp->mbarMList;
		cur;
		cur = cur->menuNext )
	{
		mm_CalcMenuSize( cur );
	}
	return 0;
}

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

int
mm_DeleteItem( mp, ip )

	MenuPtr		mp;
	ItemPtr		ip;
{
ItemPtr		cur, prev;
long		newmask = 0;	/* changed bits */
long		oldmask = 0;	/* unchanged bits */
int		i;

	if( !mp || !ip )
		return -1;

	for( 	prev = NULL, cur = mp->menuItems;
		cur && cur != ip;
		prev = cur, cur = cur->itemNext );

	if( !cur )
		return -1;

	if( prev == NULL )
		mp->menuItems = cur->itemNext;
	else
		prev->itemNext = cur->itemNext;
	ip->itemNext = NULL;
	
	/* need to shift right all bits to left of this one */

	newmask = mp->menuFlags;
	for( i=ip->itemNumber; i<mp->menuItemCount; i++ )   /* use old count */
		newmask |= (1<<i);
	for( i=ip->itemNumber-1; i>=0; i-- )	/* include menu bit */
		oldmask |= (1<<i);
	mp->menuFlags = (mp->menuFlags & oldmask) | 
		((mp->menuFlags>>1) & newmask);

	mm_CountMItems(mp);
	mm_CalcMenuSize(mp);
	return 0;
}

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

ItemPtr
mm_NewItem()

{
ItemPtr		ip;
TextDataPtr	tdp;
char *		calloc();

	ip = (ItemPtr) calloc( 1, sizeof(Item) );
	ip->itemMagic = ITEM_MAGIC;
	tdp = (TextDataPtr ) calloc( 1, sizeof(TextData) );
	tdp->tdMagic = TEXT_MAGIC;
	ip->itemData = (char *) tdp;
	ip->itemData = (char *) tdp;
	return ip;
}

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

int
mm_DisposeItem( ip )

	ItemPtr	ip;
{
	if( !ip )
		return -1;
	free( (char *) ip->itemData );
	free( (char *) ip->itemLabel );
	free( (char *) ip );
	return 0;
}


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

int
mm_InsertItem( mp, ip, beforeNumber )

	MenuPtr		mp;
	ItemPtr		ip;
	int		beforeNumber;
{
ItemPtr		cur, prev;
long		oldmask = 0;
long		newmask = 0;
int		i;

	if( !mp || !ip )
		return -1;

	mm_CountMItems(mp);

	for(	prev = NULL, cur = mp->menuItems;
		cur && cur->itemNumber != beforeNumber;
		prev = cur, cur = cur->itemNext );
	
	if( !cur )		/* not found; put item at tail */
	{
		if( !prev )	/* no previous; it's the first */
			mp->menuItems = ip;
		else
			prev->itemNext = ip;
		ip->itemNext = NULL;
	}
	else			/* we found it; put before cur */
	{
		if( !prev )
		{
			mp->menuItems = ip;
			ip->itemNext = cur;
		}
		else
		{
			prev->itemNext = ip;
			ip->itemNext = cur;
		}
	}

	ip->itemMenu = mp;
	mm_CountMItems( mp );

	/* need to shift left all bits to left of this one */

	newmask = mp->menuFlags;
	for( i=ip->itemNumber; i<=mp->menuItemCount; i++ ) /* use new count */
		newmask |= (1<<i);
	for( i=ip->itemNumber; i>=0; i-- )	/* include menu bit */
		oldmask |= (1<<i);
	mp->menuFlags = (mp->menuFlags & oldmask) | 
		((mp->menuFlags<<1) & newmask);
	mm_EnableItem( mp, ip->itemNumber );  /* must be explicitly disabled */

	mm_CalcMenuSize( mp );
	return 0;
}

