/*=========================================================================
*
* EDTSubm.cpp :  popup menu
*
*
* Version			1.0
* Creation date
* Revision date
*
* FBF
*=======================================================================*/
#include "stdafx.h"
#include "acp_base.h"
#include "itf/customid.h"

#ifdef ACTIVE_EDITOR
#include "itf/CPAsubm.hpp"
#include "itf/CPADLLb.hpp"

///////////////////////////////////////////////////////////////////////////////
// MACROS
///////////////////////////////////////////////////////////////////////////////
#define M_Entry(p_oElement)     ( (EDT_SubMenuEntry*) p_oElement )
#define M_Menu(p_oElement)      ( (EDT_SubMenu*) p_oElement )

//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
// class EDT_SubMenuEntry
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// Description : constructor
// ----------------------------------------------------------------------------
EDT_SubMenuEntry::EDT_SubMenuEntry(CPA_EditorBase *pOwner, char *p_cText, UINT uiMsgID, UINT uiIntID, BOOL _bCheck /*=FALSE*/, BOOL _bEnable /*=TRUE*/)
                 :EDT_SubMenuElement(C_SMEEntry)
{
    ASSERT( p_cText );

    m_p_cText       = (char*)malloc(strlen(p_cText)+1);
    strcpy(m_p_cText, p_cText);

    m_pOwner        = pOwner;
    m_IDCmdMsg      = uiMsgID;
    m_uiID          = uiIntID;
    m_bChecked      = _bCheck;
    m_bEnabled      = _bEnable;
}

// ----------------------------------------------------------------------------
// Description : destructor
// ----------------------------------------------------------------------------
EDT_SubMenuEntry::~EDT_SubMenuEntry()
{
    if(m_p_cText)
        free(m_p_cText);
}

// ----------------------------------------------------------------------------
// Description : call handle function
// ----------------------------------------------------------------------------
UINT EDT_SubMenuEntry::SendCommand(EDT_SubMenu *_p_oSubMenu)
{
    if (m_pOwner)
        m_pOwner->_OnSubMenuCommand(_p_oSubMenu,m_IDCmdMsg);
    return NULL;
}


//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
// class EDT_SubMenu
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// Description : constructor
// ----------------------------------------------------------------------------
EDT_SubMenu::EDT_SubMenu(tde_SubMenu _eSubMenu,UINT _uiIDStart /*=C_CustomIDUserEnd*/)
            :EDT_SubMenuElement(C_SMEMenu)
{
    m_eSubMenu      = _eSubMenu;
    m_uiInternalID  = m_uiInternalIDStart = _uiIDStart;
    m_bHasFather    = FALSE;
    m_p_oFather     = NULL;
    m_szName        = NULL;
    RemoveAll();
}

// ----------------------------------------------------------------------------
// Description : destructor
// ----------------------------------------------------------------------------
EDT_SubMenu::~EDT_SubMenu()
{
    Clear();
    if(m_szName)
        free(m_szName);
}

// ----------------------------------------------------------------------------
// Description : clear SubMenu content
// ----------------------------------------------------------------------------
void EDT_SubMenu::Clear()
{
    POSITION stPos = GetHeadPosition();
    while(stPos)
    {
        EDT_SubMenuElement *p_oElement = GetNext( stPos );

        if( p_oElement -> mfn_eGetElementType() == C_SMEMenu )
        {
            // p_oElement is a SubMenu
            M_Menu(p_oElement) -> Clear();
        }
        delete p_oElement;
    }
    RemoveAll();
    m_uiInternalID = m_uiInternalIDStart;
}

// ----------------------------------------------------------------------------
// Description : return SubMenuType
// ----------------------------------------------------------------------------
tde_SubMenu EDT_SubMenu::GetSubMenuType()
{
    return m_eSubMenu;
}

// ----------------------------------------------------------------------------
// Description : set father of SubMenu
// ----------------------------------------------------------------------------
void EDT_SubMenu::fn_vSetFather(EDT_SubMenu *_p_oFather)
{
    ASSERT( _p_oFather );
    m_bHasFather = TRUE;
    m_p_oFather = _p_oFather;
}

// ----------------------------------------------------------------------------
// Description : set SubMenu name
// ----------------------------------------------------------------------------
void EDT_SubMenu::fn_vSetName(char *_szName)
{
    ASSERT( _szName );
    m_szName = (char*)malloc(strlen(_szName)+1);
    strcpy(m_szName, _szName);
}

// ----------------------------------------------------------------------------
// Description : return next internal ID
// ----------------------------------------------------------------------------
UINT EDT_SubMenu::mfn_vGetNextInternalID()
{
    if( m_bHasFather )
        return m_p_oFather -> mfn_vGetNextInternalID();
    else
        return m_uiInternalID++;
}

// ----------------------------------------------------------------------------
// Description : build SubMenu
// ----------------------------------------------------------------------------
void EDT_SubMenu::Build(CMenu *pPopupMenu /*=NULL*/)
{
    if(pPopupMenu)
    {	
        EDT_SubMenuElement	*p_oElement;
        CMenu				*p_oMenu;
		UINT				uiFlags;

        // delete SubMenu
        DeleteEntirePopupMenu(pPopupMenu);
        // if last entry is a separator, remove it
		if (!IsEmpty())
		{
			// check last element
			p_oElement = GetTail();
			if (p_oElement->mfn_eGetElementType() == C_SMESeparator)
				RemoveTail();
		}

		// add all entries
        POSITION stPos = GetHeadPosition();
        while(stPos)
        {
            p_oElement = GetNext(stPos);
            // add entry
            switch ( p_oElement -> mfn_eGetElementType() )
            {
            case C_SMESeparator:    // add a separator
                pPopupMenu -> AppendMenu(MF_SEPARATOR);
                break;
            case C_SMEEntry:        // add an item
                uiFlags = MF_STRING | (M_Entry(p_oElement)->GetCheck()  ? MF_CHECKED : MF_UNCHECKED )
                                    | (M_Entry(p_oElement)->GetEnable() ? MF_ENABLED : MF_GRAYED    );
                pPopupMenu -> AppendMenu(uiFlags, M_Entry(p_oElement)->GetInternalID(), M_Entry(p_oElement)->GetText());
                break;
            case C_SMEMenu:         // add a SubMenu
                // create SubMenu
                p_oMenu = new CMenu();
                p_oMenu -> CreatePopupMenu();
                // fill it
                M_Menu(p_oElement) -> Build( p_oMenu );
                // add to current SubMenu
                pPopupMenu -> AppendMenu ( MF_STRING|MF_POPUP|MF_ENABLED , (UINT)p_oMenu -> Detach() , M_Menu(p_oElement) -> m_szName ) ;
                delete p_oMenu;
                break;
            }
        }
    }
}

// ----------------------------------------------------------------------------
// Description : delete CMenu content
// ----------------------------------------------------------------------------
void EDT_SubMenu::DeleteEntirePopupMenu(CMenu* pPopupMenu)
{
    while(pPopupMenu->GetMenuItemCount() > 0)
    {
        UINT uiState = pPopupMenu->GetMenuState(0,MF_BYPOSITION);
        if(HIWORD(uiState) != 0)
        {
            // first item is a SubMenu
            DeleteEntirePopupMenu(pPopupMenu->GetSubMenu(0));
        }
        pPopupMenu->DeleteMenu(0,MF_BYPOSITION);
    }
}

// ----------------------------------------------------------------------------
// Description : get a new SubMenu (must uses it as sub menu of 'this')
// ----------------------------------------------------------------------------
EDT_SubMenu *EDT_SubMenu::fn_p_oGetNewSubMenu(char *_szName, tde_SubMenu _eMenuType /*=C_SubSubMenu*/)
{
    ASSERT( _szName );

    EDT_SubMenu *p_oResult = new EDT_SubMenu( _eMenuType == C_SubSubMenu ? GetSubMenuType() : _eMenuType );

    p_oResult -> fn_vSetName( _szName );
    p_oResult -> fn_vSetFather( this );

    return p_oResult;
}

// ----------------------------------------------------------------------------
// Description : add a separator
// ----------------------------------------------------------------------------
void EDT_SubMenu::AddASeparator()
{
    AddTail(new EDT_SubMenuSeparator());
}

// ----------------------------------------------------------------------------
// Description : add an entry from DLL
// ----------------------------------------------------------------------------
void EDT_SubMenu::AddAnEntry(CPA_EditorBase *p_oOwner, char *p_cText, UINT uiEntryID, BOOL _bCheck /*=FALSE*/, BOOL _bEnable /*=TRUE*/)
{
    AddTail(new EDT_SubMenuEntry(p_oOwner, p_cText, uiEntryID, mfn_vGetNextInternalID(), _bCheck, _bEnable));
}

// ----------------------------------------------------------------------------
// Description : add a SubMenu
// ----------------------------------------------------------------------------
void EDT_SubMenu::AddASubMenu(EDT_SubMenu *_p_oSubMenu)
{
    ASSERT( _p_oSubMenu );
    // SubMenu must be child of current SubMenu
    ASSERT( _p_oSubMenu -> m_p_oFather == this );
    // add SubMenu
    AddTail( (EDT_SubMenuElement*)_p_oSubMenu );
}

// ----------------------------------------------------------------------------
// Description : handle selected item
// ----------------------------------------------------------------------------
UINT EDT_SubMenu::_OnCommand(UINT uiInternalID)
{
	POSITION stPos;
    EDT_SubMenuElement *p_oElement;

    stPos = GetHeadPosition();
	while(stPos)
	{
        p_oElement = GetNext(stPos);

        if( (p_oElement -> mfn_eGetElementType() == C_SMEEntry) && (M_Entry(p_oElement) -> GetInternalID() == uiInternalID) )
        {
            // entry found!, launch command on owner
            return M_Entry(p_oElement) -> SendCommand(this);
        }
        else if( (p_oElement -> mfn_eGetElementType() == C_SMEMenu) )
        {
            // search on submenu
            UINT uiResult = M_Menu(p_oElement) -> _OnCommand( uiInternalID );
            if( uiResult )
                // entry found
                return uiResult;
        }
	}
	return NULL;
}

// ----------------------------------------------------------------------------
// Description : handle selected item
// ----------------------------------------------------------------------------
BOOL EDT_SubMenu::fn_bFindCmdID (UINT uiInternalID, CPA_EditorBase **pOwner, UINT *CmdID)
{
    EDT_SubMenuElement	*pElem;
	POSITION			pos;

    pos = GetHeadPosition();
	while(pos)
	{
        pElem = GetNext(pos);

        if ((pElem->mfn_eGetElementType() == C_SMEEntry) && (M_Entry(pElem)->GetInternalID() == uiInternalID))
        {
            // entry found
            *CmdID = M_Entry(pElem)->GetCmdID();
			if (pOwner)
				*pOwner = M_Entry(pElem)->GetOwner();
			return TRUE;
        }
        else if ((pElem->mfn_eGetElementType() == C_SMEMenu))
        {
            // search on submenu
            if (M_Menu(pElem)->fn_bFindCmdID(uiInternalID,pOwner,CmdID))
				return TRUE;
        }
	}
	// entry not found
	return FALSE;
}
// JMD
char EDT_SubMenu::fn_cGrayedItem (CMenu *pPopupMenu, char *szItem) {
	char cFinish = 0 ;
	if(pPopupMenu) {	
		EDT_SubMenuElement	*p_oElement;
		int iID ;
		LPCTSTR szText ;
		// add all entries
    POSITION stPos = GetHeadPosition();
    while(stPos && !cFinish) {
			p_oElement = GetNext(stPos);
      // add entry
      switch ( p_oElement -> mfn_eGetElementType() ) {
      case C_SMEEntry:        // add an item
				iID = M_Entry(p_oElement)->GetInternalID();
				szText = M_Entry(p_oElement)->GetText();
				if ( !stricmp (szItem, szText) ) {
					pPopupMenu->EnableMenuItem ( iID, MF_GRAYED | MF_BYCOMMAND ) ;
					cFinish = 1 ;
				}
        break;
      case C_SMEMenu:         // add a SubMenu
				iID = M_Menu(p_oElement)->m_uiInternalID;
				szText = M_Menu(p_oElement)->m_szName ;
				if ( !stricmp (szItem, szText) ) {
					//pPopupMenu->EnableMenuItem ( iID, MF_BYCOMMAND ) ;
					M_Menu(p_oElement)->fn_vGrayedAllMenuItem( pPopupMenu );
					cFinish = 1 ;
				}
				else
					cFinish = M_Menu(p_oElement)->fn_cGrayedItem( pPopupMenu, szItem );
        break;
      }
		}
	}
	return (cFinish) ;
}
void EDT_SubMenu::fn_vGrayedAllMenuItem ( CMenu *pPopupMenu ){
	EDT_SubMenuElement	*p_oElement;
	int iID ;

	// add all entries
	POSITION stPos = GetHeadPosition();
	while(stPos) {
		p_oElement = GetNext(stPos);
		// add entry
		switch ( p_oElement -> mfn_eGetElementType() ) {
		case C_SMEEntry:        // add an item
			iID = M_Entry(p_oElement)->GetInternalID();
			pPopupMenu->EnableMenuItem ( iID, MF_GRAYED | MF_BYCOMMAND ) ;
			break;
		case C_SMEMenu:         // add a SubMenu
				M_Menu(p_oElement)->fn_vGrayedAllMenuItem( pPopupMenu );
			break;
		}
	}
}

#endif  //ACTIVE_EDITOR