/*  GadTools layout toolkit
**
**  Copyright © 1993-1995 by Olaf `Olsen' Barthel
**  Freely distributable.
**
**  :ts=4
*/

#include "gtlayout_global.h"

#ifdef DO_MENUS

	/* LT_MenuControlTagList(struct Window *Window,struct Menu *Menu,struct TagItem *Tags):
	 *
	 *	Change the state of the menus and menu items.
	 */

VOID LIBENT
LT_MenuControlTagList(REG(a0) struct Window *Window,REG(a1) struct Menu *IntuitionMenu,REG(a2) struct TagItem *Tags)
{
	RootMenu		*Root = (RootMenu *)((ULONG)IntuitionMenu - offsetof(RootMenu,Menu));
	struct TagItem	*List,*Entry;
	ULONG			 ID;
	MenuNode		*Menu;
	ItemNode		*Item;
	BOOLEAN			 GotIt;
	BOOLEAN			 Disconnected = FALSE;

	if(!IntuitionMenu)
		return;

	List = Tags;

		// Make sure that if window and menu are provided,
		// the menu is attached to the window.

	if(Window && IntuitionMenu)
	{
		if(Window -> MenuStrip != IntuitionMenu)
			Window = NULL;
	}

	while(Entry = NextTagItem(&List))
	{
		switch(Entry -> ti_Tag)
		{
				// We start with a menu/item/subitem ID

			case LAMN_ID:

				GotIt = FALSE;

				ID = (ULONG)Entry -> ti_Data;

					// Check if it's on the menu list

				for(Menu = (MenuNode *)Root -> MenuList . mlh_Head ; Menu -> Node . mln_Succ ; Menu = (MenuNode *)Menu -> Node . mln_Succ)
				{
					if(Menu -> ID == ID)
					{
						GotIt = TRUE;

						Item = NULL;

						break;
					}
				}

					// If it isn't, check the item/subitem list

				if(!GotIt)
				{
					for(Item = (ItemNode *)Root -> ItemList . mlh_Head ; Item -> Node . mln_Succ ; Item = (ItemNode *)Item -> Node . mln_Succ)
					{
						if(Item -> ID == ID)
						{
							GotIt = TRUE;

							Menu = NULL;

							break;
						}
					}
				}

					// Do nothing if none is found

				if(!GotIt)
				{
					Menu = NULL;
					Item = NULL;
				}

				break;

				// Fiddle with the checkmark

			case LAMN_Checked:

				if(Item)
				{
						// Disconnect the window menu before we
						// change the states

					if(Window && !Disconnected)
					{
						ClearMenuStrip(Window);

						Disconnected = TRUE;
					}

					if(Entry -> ti_Data)
						Item -> Item . Flags |=  CHECKED;
					else
						Item -> Item . Flags &= ~CHECKED;

						// Now check for mutual exclusion

					if(Item -> Item . MutualExclude && Entry -> ti_Data)
					{
						ItemNode	*Node;
						ULONG		 Exclude;
						UWORD		 Result;
						BOOLEAN		 IsSub;

						Exclude = Item -> Item . MutualExclude;

							// Is the current item a submenu item?

						if(SUBNUM(Item -> MenuCode) == NOSUB)
							IsSub = FALSE;
						else
							IsSub = TRUE;

							// Walk the item list back to the first list entry
							// in this menu/submenu

						for(Node = Item ; Node -> Node . mln_Pred ; Node = (ItemNode *)Node -> Node . mln_Pred)
						{
								// Extract the item number

							if(IsSub)
								Result = SUBNUM(Node -> MenuCode);
							else
								Result = ITEMNUM(Node -> MenuCode);

								// Is this the first item?

							if(!Result)
							{
								UWORD i,Mask,Value;

									// Now build a mask to extract the data
									// that should remain constant for all
									// items in this list.

								if(IsSub)
									Mask = 0x07FF;	// menu-item + menu
								else
									Mask = 0x001F;	// menu

									// This is the constant value

								Value = Item -> MenuCode & Mask;

									// Now we walk down the list

								for(i = 0 ; Node -> Node . mln_Succ && i < 32 ; i++)
								{
										// Will this one be affected by the
										// mutual exclusion stuff?

									if(Node != Item && (Node -> Item . Flags & CHECKIT) && (Exclude & (1L << i)))
										Node -> Item . Flags &= ~CHECKED;

										// Move to the next item

									Node = (ItemNode *)Node -> Node . mln_Succ;

										// Is this still the same menu/submenu?

									if((Node -> MenuCode & Mask) != Value)
										break;
								}

								break;
							}
						}
					}
				}

				break;

				// Turn menus, submenus and items off or on

			case LAMN_Disabled:

				if(Window)
				{
					UWORD Code;

					if(Item)
						Code = Item -> MenuCode;
					else
						Code = Menu -> MenuCode;

					if(Entry -> ti_Data)
						OffMenu(Window,Code);
					else
						OnMenu(Window,Code);
				}
				else
				{
					UWORD *Flags;

					if(Item)
						Flags = &Item -> Item . Flags;
					else
						Flags = &Menu -> Menu . Flags;

					if(Entry -> ti_Data)
						*Flags &= ~ITEMENABLED;
					else
						*Flags |= ITEMENABLED;
				}

				break;
		}
	}

		// Reconnect the menu strip if necessary

	if(Disconnected)
		ResetMenuStrip(Window,IntuitionMenu);
}


/*****************************************************************************/


VOID __stdargs
LT_MenuControlTags(struct Window *Window,struct Menu *Menu,...)
{
	va_list VarArgs;

	va_start(VarArgs,Menu);
	LT_MenuControlTagList(Window,Menu,(struct TagItem *)VarArgs);
	va_end(VarArgs);
}

#endif	/* DO_MENUS */
