/******************************************************************************************/
/*                                                                                        */
/*          Implementation des fonctions du package menu                                  */
/*                                                                                        */
/******************************************************************************************/


//
// Modifications History
//
//$ LB (13/06/2002) : changed objbitmap access, according to the new objbitmap structure
//



#include "x/Version.h"
#include "x/scolplugin.h"

#include <stdio.h>
#include <string.h>

#include "objstr.h"
#include "objects/bitmap.h"

int CounterMenuItem = 100 ;    





/*************************************************************************************/
/*                                                                                   */
/*  void GRCheckHiddenWindow ( PtrObjWindow W )                                      */
/*                                                                                   */
/*************************************************************************************/

int GRCheckHiddenWindow (mmachine m,HWND h )
{

  int p , res ;
  PtrObjVoid O ;
  PtrObjWindow W ;


    res=0;   
    p = OBJfindTH(m,OBJTYPWINDOW,(int)h);   
    
    if ( p != NIL )
    {
        p = MMfetch(m,p,OFFOBJMAG);
        
        O = ( PtrObjVoid ) (MMstart(m,(p>>1))) ;
        if ( O->Type == ( OBJ_TYPE_WINDOW << 1))
        {
            W = ( PtrObjWindow ) (MMstart(m,(O->Buffer>>1)));
            res = (W->Flags & WN_HIDE) ;

        }
    }
 
    return res ;
}



/****************************************************************************************/
/*                                                                                      */
/*  HMENU CreateMenu ( ) ;                                                              */
/*                                                                                      */
/*  cree un nouveau menu                                                                */
/*                                                                                      */
/****************************************************************************************/

HMENU NewObjMenu ( )
{
    return CreateMenu () ;
} 




/*************************************************************************/
/*                                                                       */
/*  int GRAppendMenuBitmap                                               */
/*                                                                       */
/*  correspond a la fonction magma Obj _append_menu_bitmap               */
/* ( ObjMenu,ObjBitmap)                                                  */
/*                                                                       */
/*************************************************************************/

int GRAppendMenuBitmap ( mmachine m )
{
    int s , sb , res , l , s2 , Flag, TFlag ;    
    PtrObjVoid O , OB ;
    PtrObjMenu Me ;   
    PtrObjBitmap Bi ;
    PtrObjMenuItem M ;
    HMENU Hm ;
    HWND Hw ;
    RECT rect , rect2 ; 
    WINDOWPLACEMENT wnd ;

    /***************************** DEBUG 2D ******************************/
    #ifdef TRACE2D
        MMechostr ( 1 , " DBG _append_menu_bitmap\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**********************************************************************/

    sb = MMpull(m) ;
    Flag = MMpull(m)>>1;
    s = MMpull(m) ;
    TFlag = MF_BITMAP | MF_BYCOMMAND ;
        
    if ( Flag & ME_CHECKED ) TFlag |= MF_CHECKED ;
    if ( Flag & ME_UNCHECKED ) TFlag |= MF_UNCHECKED ;
    if ( Flag & ME_ENABLED ) TFlag |= MF_ENABLED ;
    if ( Flag & ME_DISABLED ) TFlag |= MF_GRAYED ;
    if ( Flag & ME_SEPARATOR ) TFlag |= MF_SEPARATOR ;

    if (( s == NIL ) || ( sb == NIL )) { MMset(m,0,NIL) ;  return 0 ; }
    O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;    
    Me = ( PtrObjMenu ) MMstart(m,(O->Buffer>>1) ) ;
    OB = ( PtrObjVoid ) MMstart(m,(sb>>1) ) ;
    Bi = ( PtrObjBitmap ) MMstart(m,(OB->Buffer>>1) ) ;

	//$ LB (13/06/2002) : create DIBSection from bitmap buffer
	if (!Bi->DIBhandler) ObjBitmap_CreateDIBSection (Bi);

    Hm = Me->WHandler ; 
    Hw = Me->Handler ;
    GetClientRect ( Hw , &rect ) ;
    if ( AppendMenu ( Hm , TFlag , CounterMenuItem ,(LPCTSTR) Bi->DIBhandler ) == FALSE )  
    {
        MMechostr ( 1 , "_append_menu_bitmap : Fail to create the item\n" ) ;
        MMset(m,0,NIL) ; /* depile le channel */
        return 0 ;
    }
   

    if ( Hw != NULL ) 
    {
        GetClientRect ( Hw , &rect2 ) ;
        while ( rect.bottom != rect2.bottom )
        {
            wnd.length = sizeof ( WINDOWPLACEMENT ) ;
            GetWindowPlacement ( Hw , &wnd ) ;
            wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
            res=GRCheckHiddenWindow(m,Hw);
            if ( res ) wnd.showCmd = SW_HIDE ;               
            SetWindowPlacement ( Hw , &wnd ) ;
            if(res)ShowWindow(Hw,SW_HIDE);
            UpdateWindow ( Hw ) ;
            GetClientRect ( Hw , &rect2 ) ;
        }
    }
	MMpush(m,sb);
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL ) return MERRMEM ;
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    l = ( sizeof ( struct ObjMenuItem ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL ) return MERRMEM ;
    s = MMpull(m) ;
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    M = ( PtrObjMenuItem ) MMstart(m, s2 ) ;
    O->Type = OBJ_TYPE_MENU << 1 ;  
    O->Buffer = ( s2 << 1 ) + 1 ;
    O->Tab = MMpull(m) ;
    O->Father = NIL ;              
    M->Handler = CounterMenuItem ++ ;
    M->Type = OBJ_MENU_ITEM_BITMAP ;
    M->WHandler = Hm ;
    M->HWindow = Hw ; 
	MMpush(m,s);
    res = OBJcreate(m,OBJTYPMENUITEM,M->Handler,OBJTYPMENU,(int)Hm);
    

    /************************** DEBUG 2D **************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _append_menu_bitmap done\n" ) ;
    #endif
    /******************************************************************/

    return res ;
}

/****************************************************************************/
/*                                                                          */
/*  int GRAppendPopupBitmap ( mmachine m )                                  */
/*                                                                          */
/* correspond Obj _append_popup_menu ( Obj MenuPere , Obj MenuFils , I MH   */
/* I HBitmap )                                                              */
/*                                                                          */
/****************************************************************************/

int GRAppendPopupBitmap ( mmachine m )
{
    int s , sb , res , l , s2 ;    
    PtrObjVoid O , OB ;
    PtrObjMenu Me ;   
    PtrObjBitmap Bi ;
    PtrObjMenu M ;
    HWND Hw ;
    HBITMAP Hb ;
    HMENU Hm ;
    RECT rect , rect2 ; 
    WINDOWPLACEMENT wnd ;

    /***************************** DEBUG 2D ******************************/
    #ifdef TRACE2D
        MMechostr ( 1 , " DBG _append_popup_bitmap\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**********************************************************************/

    sb = MMpull(m) ; 
    s = MMpull(m) ;

    if (( s == NIL ) || ( sb == NIL )) { MMset(m,0,NIL) ;  return 0 ; }
    O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;    
    Me = ( PtrObjMenu ) MMstart(m,(O->Buffer>>1) ) ;
    OB = ( PtrObjVoid ) MMstart(m,(sb>>1) ) ;
    Bi = ( PtrObjBitmap ) MMstart(m,(OB->Buffer>>1) ) ;

	//$ LB (13/06/2002) : create DIBSection from bitmap buffer
	if (!Bi->DIBhandler) ObjBitmap_CreateDIBSection (Bi);

    Hw = Me->Handler ; 
    Hb = Bi->DIBhandler ;
    Hm = Me->WHandler ;
    
	MMpush(m,sb);
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL ) return MERRMEM ;
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    l = ( sizeof ( struct ObjMenu ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL ) return MERRMEM ;
    s = MMpull(m) ;
    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    M = ( PtrObjMenu ) MMstart(m, s2 ) ;
    O->Type = OBJ_TYPE_MENU << 1 ;  
    O->Buffer = ( s2 << 1 ) + 1 ;
    O->Tab = MMpull(m) ;
    O->Father = NIL ;              
    M->Handler = Hw ;  
    M->WHandler = NewObjMenu () ;
    M->HParent = Hm ;
	MMpush(m,s);
    res = OBJcreate(m,OBJTYPMENU,(int)M->WHandler,OBJTYPMENU,(int)Hm);

    GetClientRect ( Hw, &rect ) ;
    if ( AppendMenu ( Hm , MF_POPUP | MF_BITMAP , ( UINT ) M->WHandler , ( LPCTSTR ) Bi->DIBhandler ) == FALSE )              
                MMechostr ( 1 , "_append_popup_bitmap : Fail to create the item\n" ) ; 
    if ( Hw != NULL )
    {
        GetClientRect ( Hw , &rect2 ) ;
        while ( rect.bottom != rect2.bottom )
        {
            wnd.length = sizeof ( WINDOWPLACEMENT ) ;
            GetWindowPlacement ( Hw , &wnd ) ;
            wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
            l=GRCheckHiddenWindow(m,Hw);
            if (l) wnd.showCmd = SW_HIDE ;               
            SetWindowPlacement ( Hw , &wnd ) ;
            if(l)ShowWindow(Hw,SW_HIDE);
            UpdateWindow ( Hw ) ;
            GetClientRect ( Hw , &rect2 ) ;
        }
    }

    /************************** DEBUG 2D **************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _append_menu_bitmap done\n" ) ;
    #endif
    /******************************************************************/

    return res ;
}

/*****************************************************************************/
/*                                                                           */
/*  int GRAppendPopup ( mmachine m )                                         */
/*                                                                           */
/*  correspond a la fonction magma                                           */
/*  ObjMenu _append_popup (ObjMenu S ) ;                                     */
/*  qui ajoute un sous menu a un menu                                        */
/*                                                                           */
/*****************************************************************************/

int GRAppendPopup ( mmachine m )
{
        PtrObjVoid OP , OC ;
        PtrObjMenu MP , MC ;
        int  s , s2 , res , l ,sc ;
        char Libelle [ 128 ];
        HMENU HParent ;
        HWND HW ;
        RECT rect , rect2 ; 
        WINDOWPLACEMENT wnd ;

        /********************* DEBUG 2D ***************************************/
        #ifdef TRACE2D
            MMechostr ( 1 , "DBG _append_popup\n" ) ;
            FDebug2D ( m ) ;
        #endif
        /**********************************************************************/

        s = MMpull(m) ;
        if ( s == NIL ) strcpy ( Libelle , "" ) ;
        else strcpy ( Libelle , ( char * ) MMstart(m, ( s >> 1 ) + 1) );      
        s = MMpull(m) ;        
        if ( s == NIL )
        {
            MMechostr (1 , "AppendPopup : Parent Parameter is NIL\n" ) ;
            return MMpush(m,NIL) ;
        }
        OP = ( PtrObjVoid ) MMstart(m, ( s >> 1 ) ) ;
        MP = ( PtrObjMenu ) MMstart(m, ( OP->Buffer >> 1 ) ) ;              
        HParent = MP->WHandler ;
        HW = MP->Handler ;

        /* creation d'un autre menu */
        l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
        sc = MMmallocCLR (m,l,TYPETAB) ;
        if ( sc == NIL ) return MERRMEM ;
        if ( MMpush(m,(sc<<1)+1)) return MERRMEM ;
        l = ( sizeof ( struct ObjMenu ) + 3 ) >> 2 ;
        s2 = MMmalloc ( m,l,TYPEBUF ) ;
        if ( s2 == NIL ) return MERRMEM ;
        sc = MMget(m,0) ;

        OC = ( PtrObjVoid ) MMstart(m, (sc>>1) ) ;
        MC = ( PtrObjMenu ) MMstart(m, s2 ) ;
        OC->Type = OBJ_TYPE_MENU << 1 ;  
        OC->Buffer = ( s2 << 1 ) + 1 ;
        OC->Tab = NIL ;
        OC->Father = s ;
        MC->WHandler = NewObjMenu () ;          
        MC->Handler = HW ;
        MC->HParent = HParent ;

        GetClientRect ( HW , &rect ) ;
        AppendMenu ( HParent , MF_POPUP | MF_STRING , ( UINT ) MC->WHandler , ( LPCTSTR )  Libelle ) ;          
        res= OBJcreate(m,OBJTYPMENU,(int)MC->WHandler,OBJTYPMENU,(int)HParent);

        #ifdef TRACE2D
            MMechostr(MSKDEBUG,"(DBG) apprendMenu %d parent %d",MC->WHandler,MC->HParent);
        #endif
        if ( HW != NULL ) 
        {
            DrawMenuBar ( HW ) ;    
            UpdateWindow ( HW ) ;
            GetClientRect ( HW , &rect2 ) ;
            while ( rect.bottom != rect2.bottom )
            {
                wnd.length = sizeof ( WINDOWPLACEMENT ) ;
                GetWindowPlacement ( HW , &wnd ) ;
                wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
                l=GRCheckHiddenWindow(m,HW);
                if (l) wnd.showCmd = SW_HIDE ;               
                SetWindowPlacement ( HW , &wnd ) ;
                if(l)ShowWindow(HW,SW_HIDE);
                UpdateWindow ( HW ) ;
                GetClientRect ( HW , &rect2 ) ;
            }
        }

        /************************ DEBUG 2D **************************************/
        #ifdef TRACE2D
            FDebug2D ( m ) ;
            MMechostr ( 1 , "DBG _append_popup done\n" ) ;
        #endif
        /*************************************************************************/

        return res ;
}

/*****************************************************************************/
/*                                                                           */
/*  int GREnableMenuItem ( mmachine m )                                      */
/*                                                                           */
/*  correspond a la fonction magma Obj _enable_menu_item(Obj Menu, I Handle) */
/*  qui rend actif un des menu items du menu objet                           */
/*                                                                           */
/*****************************************************************************/

int GREnableMenuItem ( mmachine m )
{
        PtrObjVoid O ;
        PtrObjMenuItem M ;
        int s  ;

        /******************************** DEBUG 2D ****************************/
        #ifdef TRACE2D
            MMechostr( 1 , "DBG _enable_menu_item\n" ) ;
            FDebug2D ( m ) ;
        #endif
        /**********************************************************************/
      
        s = MMpull(m) ;
        if ( s == NIL ) MMechostr (1,"EnableMenuItem : Menu parameter is NIL\n" ) ;
        else
        {
            O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;       
            M = ( PtrObjMenuItem ) MMstart(m, ( O->Buffer>>1) ) ;
            EnableMenuItem ( M->WHandler , M->Handler , MF_ENABLED ) ;
        }
        s = MMpush(m,s);
    
        /****************************** DEBUG 2D *******************************/
        #ifdef TRACE2D
            MMechostr ( 1 , "DBG _enable_menu_item Done\n" ) ;
            FDebug2D ( m ) ;
        #endif
        /***********************************************************************/

        return s ;

}

/*****************************************************************************/
/*                                                                           */
/*  int GRDisableMenuItem ( mmachine m ) ;                                   */
/*                                                                           */
/* correspond a la fonction magma _disable_menu_item(Obj M,I Handle)         */
/* laquelle rend inactif un des choix du menu                                */
/*                                                                           */
/*****************************************************************************/

int GRDisableMenuItem ( mmachine m )
{
        PtrObjVoid O ;
        PtrObjMenuItem M ;
        int s ;

        /********************** DEBUG 2D ********************************/
        #ifdef TRACE2D
            MMechostr ( 1 , "DBG _disable_menu_item\n" ) ;
            FDebug2D ( m ) ;
        #endif
        /****************************************************************/

        s = MMpull(m) ;
        if ( s == NIL ) MMechostr ( 1 , "DisableMenuItem : Menu parameter is NIL\n" ) ;
        else
        {
            O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
            M = ( PtrObjMenuItem ) MMstart(m, (O->Buffer>>1) ) ;        
            EnableMenuItem ( M->WHandler , M->Handler , MF_DISABLED | MF_GRAYED ) ;
        }
        s = MMpush(m,s) ;

        /************************** DEBUG 2D ******************************/
        #ifdef TRACE2D
            FDebug2D ( m ) ;
            MMechostr ( 1 , "DBG _disable_menu_item done\n" ) ;
        #endif
        /******************************************************************/
            
        return s ;
}


/*****************************************************************************/
/*                                                                           */
/*   fonction int GRCreatePopupMenu ( mmachine m ) ;                         */
/*                                                                           */
/*  correspond a la fonction ObjMenu _CRpopupMenu ' Chn ) ;                  */
/*  qui cree un menu contextuel vide                                         */
/*                                                                           */
/*****************************************************************************/

int GRCreatePopupMenu ( mmachine m ) 
{
    int s , s2 , l , res ;
    PtrObjVoid O ;
    PtrObjMenu M ;

    /***************** DEBUG 2D **********************************************/
    #ifdef DEBUG2D
        MMechostr ( 1 , "DBG _CRpopupMenu\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /*************************************************************************/

    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL ) return MERRMEM ;
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    l = ( sizeof ( struct ObjMenu ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL ) return MERRMEM ;
    s = MMget(m,0) ;

       O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    M = ( PtrObjMenu ) MMstart(m, s2 ) ;
    O->Type = OBJ_TYPE_MENU << 1 ;  
    O->Buffer = ( s2 << 1 ) + 1 ;
    O->Tab = NIL ;
    O->Father = NIL ;
    M->WHandler = CreatePopupMenu () ;      
    M->Handler = NULL ;  
    M->HParent = NULL ;
    MMechostr(MSKDEBUG,"(DBG) _CRpopupMenu : Menu %d\n",M->WHandler);
    
    res = OBJcreate(m,OBJTYPMENU,(int)M->WHandler,OBJTYPWINDOW,(int)NULL);

    /**************************** DEBUG 2D ************************************/
    #ifdef TRACE2D
        FDebug2D ( m );
        MMechostr ( 1, "DBG _CRpopupMenu done\n" ) ;
    #endif
    /***************************************************************************/

    return res ;
}

/*****************************************************************************/
/*                                                                           */
/*      fonction int GRDrawMenu ( mmachine m ) ;                             */
/*                                                                           */
/*  correspond a la fonction scol ObjWin _DRAWmenu(ObjMenu,ObjWin,X,Y,Flag)  */
/*                                                                           */
/*****************************************************************************/

int flagmen=0;


typedef struct
{
    int _x;
    int _y;
    HWND  _hwnd;
    HMENU _menu;
    int   _flags;
} MenuParam;

MenuParam params;

int SCOLInternaldrawMenu(mmachine m,HWND hwnd,unsigned int msg,UINT wParam, LONG lParam,int *ret)
{
    TrackPopupMenu (params._menu,params._flags,params._x,params._y,0,params._hwnd,NULL);
    return 1;
}

extern int WM_SCOLDRAWMENU;

int GRDrawMenu ( mmachine m)
{
    int f , x , y , s , sw , res , flag ;
    PtrObjVoid OM , OW ;
    PtrObjMenu M ;
    HWND W ;
    POINT p ;
    /******************************************* DEBUG 2D *******************/
#ifdef TRACE2D
	MMechostr (1,"DBG _DRAWmenu\n")  ;
	FDebug2D ( m ) ; 
#endif
    /************************************************************************/
	
    f = MMpull(m)>>1;
    y = MMpull(m)>>1;
    x = MMpull(m)>>1;
	
    s = MMpull(m);
    sw = MMpull(m);   
	
    if (s != NIL )
    {
		if (sw==NIL)
		{
			W=(HWND)SCgetExtra("hscol");
		}
		else
		{
			OW = ( PtrObjVoid ) MMstart(m,(sw>>1)) ;
			switch (OW->Type>>1)
			{
			case OBJ_TYPE_WINDOW :
				W = (( PtrObjWindow ) MMstart(m,(OW->Buffer>>1)))->WHandler;
				break ;
			case OBJ_TYPE_TREE :
				W = (( PtrObjTree ) MMstart(m,(OW->Buffer>>1)))->WHandler;
				break ;
			}
		}
		
        OM = ( PtrObjVoid ) MMstart(m,(s>>1)) ;
        M = ( PtrObjMenu ) MMstart(m,(OM->Buffer>>1));
		
        //flag = TPM_NONOTIFY;
        flag = TPM_RIGHTBUTTON ;
        if ( f & PM_HCENTER_ALIGN ) flag |= TPM_CENTERALIGN ;
        else if ( f & PM_LEFT_ALIGN ) flag |= TPM_LEFTALIGN ;
        else if ( f & PM_RIGHT_ALIGN ) flag |= TPM_RIGHTALIGN ;
        else flag |= TPM_CENTERALIGN ;
		
        if ( f & PM_BOTTOM_ALIGN ) flag |= TPM_BOTTOMALIGN ;
        else if ( f & PM_TOP_ALIGN ) flag |= TPM_TOPALIGN ;
        else if ( f & PM_VCENTER_ALIGN ) flag |= TPM_VCENTERALIGN ;
        else flag |= TPM_VCENTERALIGN ;
		
		
        if ((f & PM_SCREEN) == 0 ) 
        {
            p.x = x ;
            p.y = y ;
			
            ClientToScreen ( W,&p);
            x = p.x ;
            y = p.y ;
            
        }
		if ((x==-1)&&(y==-1))
		{
			GetCursorPos(&p);
            x = p.x ;
            y = p.y ;
		}
		
        // Joss : 19/10/2001 correction du TrackPopupMenu bloquant pour Scol au niveau de la pile
        params._x=x;
        params._y=y;
        params._flags=flag;
        params._hwnd =W;
        params._menu =M->WHandler;


        PostMessage((HWND)SCgetExtra("hscol"),WM_SCOLDRAWMENU,0,0);

        //MMechostr(MSKDEBUG,"%d %d %d %d %d\n",DMx,DMy,DMflag,DMhw,DMhm);
		
		/*	if (sw==NIL)
		hThreadDM = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) ThreadDrawMenu,0,0,&dwThreadDMId);
		else if (!flagmen)
		*/
//		SetForegroundWindow(DMhw);
//		SetFocus(DMhw);
/*
        if (!flagmen)
		{
			flagmen=1;
			TrackPopupMenu (DMhm,DMflag,DMx,DMy,0,DMhw,NULL);
			flagmen=0;
		}*/
	}else MMechostr ( 1 , "_DRAWmenu Menu object is NIL\n" ) ;
	
    res = MMpush(m,sw);
	MMechostr(1,"******End DrawMenu\n");
    /************************ DEBUG 2D *************************************/
#ifdef TRACE2D
	FDebug2D ( m ) ;
	MMechostr ( 1,"DBG _DRAWmenu Done\n" );
#endif
    /***********************************************************************/
	
    return res ;
}



/*****************************************************************************/
/*                                                                           */
/* fonction int GRCreateMenu ( mmachine m ) ;                                */
/*                                                                           */
/* correspond a la fonction magma Obj _create_menu ( Chn, ObjWin , I         */
/* nota benet : Le parametre I ne sert que pour la version X                 */
/*  cree un menu vide                                                        */
/*                                                                           */
/*****************************************************************************/

int GRCreateMenu ( mmachine m )
{
    int l , s , s2 , res ;
    PtrObjVoid O ;
    PtrObjMenu M ;
    PtrObjWindow W ;    
    HWND H ;
    WINDOWPLACEMENT  wnd  ;
    RECT rect , rect2 ;
    /**************************DEBUG 2D **************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _create_menu\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**************************************************************************/
   
    s = MMpull(m) ;
    if ( s == NIL ) 
    { 
           MMset(m,0,NIL);
           return 0 ;
    }
   
    O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;
    W = ( PtrObjWindow ) MMstart(m, (O->Buffer>>1) ) ;
    H = W->WHandler ;
    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL ) return MERRMEM ;
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    l = ( sizeof ( struct ObjMenu ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL ) return MERRMEM ;
    s = MMget(m,0) ;

    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    M = ( PtrObjMenu ) MMstart(m, s2 ) ;
    O->Type = OBJ_TYPE_MENU << 1 ;  
    O->Buffer = ( s2 << 1 ) + 1 ;
    O->Tab = NIL ;
    O->Father = NIL ;
    M->WHandler = NewObjMenu () ;      
    M->Handler = H ;  
    M->HParent = NULL ;
    
    res = OBJcreate(m,OBJTYPMENU,(int)M->WHandler,OBJTYPWINDOW,(int)H);
    GetClientRect ( H , &rect ) ;
    SetMenu (H , M->WHandler ) ;    

    #ifdef TRACE2D
        MMechostr(MSKDEBUG,"(DBG) _CRmenu %d win %d\n",M->WHandler,H);
    #endif
    
    DrawMenuBar ( H);
    InvalidateRect ( H , NULL , FALSE ) ;
    UpdateWindow ( H ) ;
    GetClientRect ( H , &rect2 ) ;
    while ( rect.bottom != rect2.bottom )
    {
        wnd.length = sizeof ( WINDOWPLACEMENT ) ;
        GetWindowPlacement ( H , &wnd ) ;
        wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
        l=GRCheckHiddenWindow(m,H);
        if (l) wnd.showCmd = SW_HIDE ;               
        SetWindowPlacement ( H, &wnd ) ;
        if(l)ShowWindow(H,SW_HIDE);
        UpdateWindow ( H ) ;
        GetClientRect ( H , &rect2 ) ;  
    }
 
    /************** DEBUG 2D ******************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _create_menu done\n" ) ;
    #endif
    /********************************************************************/

    return res ;
    
}

/*************************************************************************************/
/*                                                                                   */
/*  int GRCreateMenuItemString ( mmachine m ) ;                                      */
/*                                                                                   */
/*  correspond a la fonction ObjMenuItem _append_menu_item_string (Chn,ObjMenu,S,I)  */
/* laquelle cree un element de menu                                                  */
/*                                                                                   */
/*************************************************************************************/


int GRCreateMenuItemString ( mmachine m )
{
    int s , l , s2 , Flag , res , TFlag ;
    char Name [33000] ;
    PtrObjVoid O , O2 ;
    PtrObjMenuItem M ;
    PtrObjMenu M2 ;
    RECT rect , rect2 ;
    WINDOWPLACEMENT wnd ;

    /****************** DEBUG 2D ***********************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _append_menu\n" ) ;
        FDebug2D ( m );
    #endif
    /*****************************************************************/
  
    s = MMpull(m) ;
    if ( s == NIL ) strcpy ( Name , "" ) ;
    else strcpy ( Name , ( char * ) MMstart(m,(s>>1) + 1 )) ;
      Flag = MMpull(m) >> 1 ;

    l = ( sizeof ( struct ObjVoid ) + 3 ) >> 2 ;
    s = MMmallocCLR (m,l,TYPETAB) ;
    if ( s == NIL ) return MERRMEM ;
    if ( MMpush(m,(s<<1)+1)) return MERRMEM ;
    l = ( sizeof ( struct ObjMenuItem ) + 3 ) >> 2 ;
    s2 = MMmalloc ( m,l,TYPEBUF ) ;
    if ( s2 == NIL ) return MERRMEM ;
    s = MMpull(m) ;

    O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
    M = ( PtrObjMenuItem ) MMstart(m, s2 ) ;
    O->Type = OBJ_TYPE_MENU << 1 ;  
    O->Buffer = ( s2 << 1 ) + 1 ;
    O->Tab = NIL ;
    O->Father = NIL ;  
    s2 = MMget(m,0) ;
    if ( s2 == NIL ) return 0 ;
    O2 = ( PtrObjVoid ) MMstart(m,(s2>>1) ) ;
    M2 = ( PtrObjMenu ) MMstart(m,(O2->Buffer>>1) ) ;
   
    M->Handler = CounterMenuItem ++ ;
    M->Type = OBJ_MENU_ITEM_STRING ;
    M->WHandler = M2->WHandler ;
    M->HWindow= M2->Handler ;
    TFlag = MF_STRING | MF_BYCOMMAND ;
        
    if ( Flag & ME_CHECKED ) TFlag |= MF_CHECKED ;
    if ( Flag & ME_UNCHECKED ) TFlag |= MF_UNCHECKED ;
    if ( Flag & ME_ENABLED ) TFlag |= MF_ENABLED ;
    if ( Flag & ME_DISABLED ) TFlag |= MF_GRAYED ;
    if ( Flag & ME_SEPARATOR ) TFlag |= MF_SEPARATOR ;

    GetClientRect ( M->HWindow , &rect ) ;        
    if ( AppendMenu ( M->WHandler , TFlag , M->Handler , Name ) == FALSE )
            MMechostr( 1 , "ERROR : _append_menu : Can't ADD a menu item\n" ) ;
    if ( M->HWindow != NULL ) 
    {
        DrawMenuBar ( M->HWindow ) ;
        UpdateWindow ( M->HWindow ) ; 
        GetClientRect ( M->HWindow , &rect2 ) ;
        while ( rect.bottom != rect2.bottom )
        {                
            wnd.length = sizeof ( WINDOWPLACEMENT ) ;
            GetWindowPlacement ( M->HWindow , &wnd ) ;
            wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
            res=GRCheckHiddenWindow(m,M->HWindow);
            if ( res ) wnd.showCmd = SW_HIDE ;               
            SetWindowPlacement ( M->HWindow , &wnd ) ;
            if(res)ShowWindow(M->HWindow,SW_HIDE);
            UpdateWindow ( M->HWindow ) ;
            GetClientRect ( M->HWindow , &rect2 ) ;
        }
   
    }

    MMset(m,0,s);
    res = OBJcreate(m,OBJTYPMENUITEM,M->Handler,OBJTYPMENU,(int)M->WHandler);

    /************** DEBUG 2D ******************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _append_menu done\n" ) ;
    #endif
    /********************************************************************/

    return res ;
    
}
/************************************************************************************/
/*                                                                                  */
/*  int GRReflexMenuSelect ( mmachine m );                                          */
/*                                                                                  */
/*  correspond a la fonction magma _ObjMenuItem _reflex_menu_select ( O,Fun,U0)     */
/* laquelle definit le callback d'un choix de menu                                  */
/*                                                                                  */
/************************************************************************************/

int GRReflexMenuSelect ( mmachine m )
{
    return OBJaddreflex(m,OBJTYPMENUITEM,RFLMENUITEM_SELECT) ;
}

/************************************************************************/
/*                                                                      */
/*  int GRCheckMenuItem ( mmachine m ) ;                                */
/*                                                                      */
/*  correspond a la focntion magma ObjMenuItem _check_menu_item         */
/* ( ObjMenuItem O , I etat )                                           */
/* laquelle si etat = 1 met le menu item en selectionne , 0 enleve le   */
/* check , et -1 -> check si unchecked et uncheck si checked            */
/*                                                                      */
/************************************************************************/

int GRCheckMenuItem ( mmachine m )
{
    int s , etat ;
    PtrObjVoid O ;
    PtrObjMenuItem M ;
    MENUITEMINFO Info ;

    /********************* DEBUG 2D *************************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _check_menu_item\n" ) ;
        FDebug2D ( m ); 
    #endif
    /********************************************************************/

   etat = MMpull(m) >> 1 ;
   s = MMpull(m) ;

   if ( s == NIL ) MMechostr(  1 , "_check_menu_item : Item is NIL\n" ) ;
   else 
   {
       O = ( PtrObjVoid ) MMstart(m, (s>>1) ) ;
       M = ( PtrObjMenuItem ) MMstart(m,(O->Buffer>>1) ) ;
       if ( etat == -1 )
       {
           Info.cbSize = sizeof ( MENUITEMINFO ) ;
           Info.fMask = MIIM_STATE ;
           GetMenuItemInfo ( M->WHandler , M->Handler , FALSE , & Info ) ;
               if ( Info.fState & MFS_CHECKED ) etat = 0 ; else etat = 1 ;
       }
       if ( etat == 0 ) CheckMenuItem ( M->WHandler , M->Handler , MF_BYCOMMAND | MF_UNCHECKED ) ;
       else if ( etat == 1 ) CheckMenuItem ( M->WHandler , M->Handler , MF_BYCOMMAND | MF_CHECKED ) ;
       else MMechostr(  1 , "_check_menu_item : Etat value unknox\n" ) ;
   }
   s = MMpush(m,s) ;

   /********************* DEBUG 2D ****************************************/
    #ifdef TRACE2D
        FDebug2D ( m );
        MMechostr( 1 , "DBG _check_menu_item done\n" ) ;
    #endif
    /*************************************************************************/

    return s ;
}

/********************************************************************************/
/*                                                                              */
/* int GRGetCheckMenuItem ( mmachine m )                                        */
/*                                                                              */
/* correspond a la fonction magma I _get_check_menu_item ( ObjMenuItem )        */
/* laquelle renvoi l'etat checked / unchecked d'un menu item                    */
/*                                                                              */
/********************************************************************************/

int GRGetCheckMenuItem ( mmachine m )
{
    int s ;
    PtrObjVoid O ;
    PtrObjMenuItem  M ;
    MENUITEMINFO Info ;

    /*********************** DEBUG 2D **************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _get_check_menu_item\n" ) ;
        FDebug2D ( m ); 
    #endif
    /***************************************************************/

    s = MMpull(m) ;
    if( s == NIL )
    {
        MMechostr( 1 , "_get_check_menu_item : Item is NIL\n" ) ;
        s = -1 ;
    }
    else
    {
        O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;
        M = ( PtrObjMenuItem ) MMstart(m,(O->Buffer>>1) );
        Info.cbSize = sizeof ( MENUITEMINFO ) ;
        Info.fMask = MIIM_STATE ;
        GetMenuItemInfo ( M->WHandler , M->Handler , FALSE , & Info ) ;
        if ( Info.fState & MFS_CHECKED ) s = 1 ; else s = 0 ;
    }

    /********************* DEBUG 2D *******************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr( 1 , "DBG _get_check_menu_item done\n" ) ;
    #endif
    /**************************************************************/

    return MMpush(m,s<<1) ;
}

/**************************************************************************/
/*                                                                        */
/*  int GRPaintObjMenu                                                    */
/*                                                                        */
/*  correspond a la fonction magma ObjMenu _paint_obj_menu                */
/* laquelle repeind un objet menuy                                        */
/*                                                                        */
/**************************************************************************/

int GRPaintObjMenu ( mmachine m )
{
    int s ;
    PtrObjVoid O ;
    PtrObjMenu M ;

    /******************* DEBUG 2D *****************************************/
    #ifdef TRACE2D
        MMechostr ( 1 , "DBG _paint_obj_menu\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /***********************************************************************/

    s = MMget(m,0) ;

    if( s != NIL )
    {
        O = ( PtrObjVoid ) MMstart(m, ( s>>1) ) ;
        M = ( PtrObjMenu ) MMstart(m,(O->Buffer>>1) ) ;
      
       if ( M->WHandler != NULL ) DrawMenuBar ( M->Handler ) ;
       InvalidateRect ((HWND) M->WHandler , NULL , TRUE ) ;
       SendMessage ( (HWND)M->WHandler , WM_PAINT , 0 , 0 ) ;     
       
    }

    /************* DEBUG 2D *************************************************/
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _paint_obj_menu done\n" ) ;
    #endif
    /*************************************************************************/

    return 0 ;
}



/*******************************************************************************/
/*                                                                             */
/* int GRDestroyMenuItem ( mmachine m )                                        */
/*                                                                             */
/* correspond a la fonction magma I _destroy_menu_item ( ObjMenuItem )         */
/* laquelle detruit un element de menu                                         */
/*                                                                             */
/*******************************************************************************/

int GRDestroyMenuItem ( mmachine m )
{
    int s ,res ;
    PtrObjVoid O ;
    PtrObjMenuItem M ;
    RECT rect , rect2 ;
    WINDOWPLACEMENT wnd ;

    /********************* DEBUG 2D *****************************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _destroy_menu_item\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**************************************************************************/

    s = MMget(m,0) ;
    if ( s == NIL ) return 0 ;

    O = ( PtrObjVoid ) MMstart(m,( s >> 1 ) ) ;
    M = ( PtrObjMenuItem ) MMstart(m,(O->Buffer >> 1 ) ) ;

    GetClientRect ( M->HWindow , &rect ) ;
    OBJdelTH(m,OBJTYPMENUITEM,M->Handler) ;
    if ( M->HWindow != NULL )
    {
        DrawMenuBar ( M->HWindow ) ;
        UpdateWindow ( M->HWindow ) ;
        GetClientRect ( M->HWindow , &rect2 ) ;
        while ( rect.bottom != rect2.bottom )
        {
            wnd.length = sizeof ( WINDOWPLACEMENT ) ;
            GetWindowPlacement ( M->HWindow , &wnd ) ;
            wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
            res=GRCheckHiddenWindow(m,M->HWindow);
            if ( res ) wnd.showCmd = SW_HIDE ;               
            SetWindowPlacement ( M->HWindow , &wnd ) ;
            if(res)ShowWindow(M->HWindow,SW_HIDE);
            UpdateWindow ( M->HWindow ) ;
            GetClientRect ( M->HWindow , &rect2 ) ;
        }
    }
  
    /*********************** DEBUG 2D ******************************************/
    #ifdef TRACE2d
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _destroy_menu_item done\n" ) ;
    #endif
    /****************************************************************************/

    return 0 ;
}

/**********************************************************************************/
/*                                                                                */
/*  int GRDestroyObjMenu ( mmachine m ) ;                                         */
/*                                                                                */
/*  correspond ala fonction magma I _destroy_obj_menu ( ObjMenu ) ;               */
/*                                                                                */
/**********************************************************************************/

int GRDestroyObjMenu ( mmachine m )
{

    int s , res ; 
    PtrObjVoid O ;
    PtrObjMenu M ;
    RECT rect , rect2 ;
    WINDOWPLACEMENT wnd ;

    /*********************** DEBUG 2D ****************************************/
    #ifdef TRACE2D
        MMechostr( 1 , "DBG _destroy_obj_menu\n" ) ;
        FDebug2D ( m ) ;
    #endif
    /**************************************************************************/

    s = MMget(m,0) ;
    if ( s == NIL ) 
    {
        MMset(m,0,0) ;
        return 0 ;
    }

    O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;
    M = ( PtrObjMenu ) MMstart(m,(O->Buffer>>1) ) ;  

    GetClientRect ( M->Handler , &rect ) ;
    OBJdelTH(m,OBJTYPMENU,(int)M->WHandler);
    if ( M->Handler != NULL )
    {
        DrawMenuBar (M->Handler ) ;
        ValidateRect (M->Handler,&rect);
        UpdateWindow (M->Handler) ;
        GetClientRect ( M->Handler, &rect2 ) ;
        while ( rect.bottom != rect2.bottom )
        {
            wnd.length = sizeof ( WINDOWPLACEMENT ) ;
            GetWindowPlacement ( M->Handler , &wnd ) ;
            wnd.rcNormalPosition.bottom += rect.bottom - rect2.bottom ;
            wnd.showCmd = SW_SHOW ;
            res=GRCheckHiddenWindow(m,M->Handler);
            if (res) wnd.showCmd = SW_HIDE;               
            SetWindowPlacement (M->Handler, &wnd );
            if(res)ShowWindow(M->Handler,SW_HIDE);
            UpdateWindow (M->Handler);
            GetClientRect (M->Handler,&rect2 );
        }     
    }

    /************************ DEBUG 2D *******************************************/ 
    #ifdef TRACE2D
        FDebug2D ( m ) ;
        MMechostr ( 1 , "DBG _destroy_obj_menu done\n" ) ;
    #endif
    /******************************************************************************/ 

    MMset(m,0,0) ;
    return 0 ;
}

/************************************************************************************/ 
/*                                                                                  */ 
/* int GRSetMenuItemBitmap ( mmachine m ) ;                                         */ 
/*                                                                                  */ 
/*  correspond a la fonction ObjMenuItem _SETmenuItemBitmap (OjbMenuItem,ObjBitmap) */ 
/*  laquelle affiche un bitmap ou change le bitmap d'un menu item                   */ 
/*                                                                                  */ 
/************************************************************************************/ 

int GRSetMenuItemBitmap ( mmachine m )
{
    int so, sb1,sb2,k ;
    HBITMAP HB1 , HB2 ;
    PtrObjVoid O ;
    PtrObjMenuItem M ;
    PtrObjBitmap B ;

    sb1 = MMget(m,0);//SH
    sb2 = MMget(m,1);//SH
    so = MMget(m,2);//SH

    if ( so != NIL )
    {
          O = ( PtrObjVoid ) MMstart(m,( so >> 1 ) ) ;
          M = ( PtrObjMenuItem ) MMstart(m,(O->Buffer >> 1 ) ) ;
          if ( sb1 != NIL ) 
          {
                O = ( PtrObjVoid ) MMstart(m,(sb1>>1));
                B = ( PtrObjBitmap ) MMstart(m,(O->Buffer>>1)) ;

				//$ LB (13/06/2002) : create DIBSection from bitmap buffer
				if (!B->DIBhandler) ObjBitmap_CreateDIBSection (B);

                HB1 = B->DIBhandler ;
          } else HB1 = NULL ;

          if (sb2 != NIL ) 
          {
              O = ( PtrObjVoid ) MMstart(m,(sb2>>1));
              B = (PtrObjBitmap ) MMstart(m,(O->Buffer>>1));

			  //$ LB (13/06/2002) : create DIBSection from bitmap buffer
			  if (!B->DIBhandler) ObjBitmap_CreateDIBSection (B);

              HB2 = B->DIBhandler ;
          } else HB2 = NULL ;
          SetMenuItemBitmaps ( M->WHandler , M->Handler , FALSE , HB1 , HB2 ) ;
		  if (MMpush(m,2*2)) return MERRMEM;//SH
		  if (k=MBdeftab(m)) return MERRMEM;//SH
		  so = MMget(m,1); //SH
		  O = ( PtrObjVoid ) MMstart(m,( so >> 1 ) ) ; //SH
		  O->Tab=MMpull(m);  //SH
    }
	else
	{
		MMpull(m);//SH
		MMpull(m);//SH
	}
    return 0;

}

/****************************************************************************/ 
/*                                                                          */ 
/*      int GRCheckMenu ( mmachine m ) ;                                    */ 
/*                                                                          */ 
/*      correspond a la fonction magma _CHKmenu (ObjMenu , I ) -> ObjMenu   */ 
/*      laquelle change l'etat checked / unchecked d'un menu                */ 
/*                                                                          */ 
/****************************************************************************/ 

int GRCheckMenu ( mmachine m )
{
    int s , etat , pos , i;
    PtrObjVoid O ;
    PtrObjMenu M ;
    MENUITEMINFO Info ;

    /************************** TRACE 2D ************************************/ 
    #ifdef TRACE2D
        MMechostr(MSKDEBUG,"(DBG) _CHKmenu\r\n");
        FDebug2D(m);
    #endif
    /************************************************************************/ 

    etat = MMpull(m)>>1 ;
    s = MMpull(m) ;

    MMechostr(MSKDEBUG,"Passage CHKpopup\r\n");

    if ( s != NIL )
    {
        O = ( PtrObjVoid ) MMstart(m,(s>>1) ) ;
        M = ( PtrObjMenu ) MMstart(m,(O->Buffer>>1) ) ;  

        /* rechercher la position du menu dans son menu parent */ 
        pos = NIL ;
        if ( M->HParent != NULL )
        for ( i = 0 ; i < GetMenuItemCount ( M->HParent ) ; i ++ )
        if ( GetSubMenu ( M->HParent , i ) == M->WHandler ) pos = i ;

        if ( pos != NIL ) 
        {           
            if ( etat == -1 )
            {
                Info.cbSize = sizeof ( MENUITEMINFO ) ;
                Info.fMask = MIIM_STATE ;
                GetMenuItemInfo ( M->HParent , pos , TRUE , & Info ) ;
                    if ( Info.fState & MFS_CHECKED ) etat = 0 ; else etat = 1 ;
            }
            if ( etat == 0 ) CheckMenuItem ( M->HParent , pos , MF_BYPOSITION | MF_UNCHECKED ) ;
            else if ( etat == 1 ) CheckMenuItem ( M->HParent , pos , MF_BYPOSITION | MF_CHECKED ) ;
        } else MMechostr(MSKDEBUG,"POS nil for menu\r\n",M->WHandler);
    }

    s = MMpush(m,s) ;

    /****************************** TRACE 2D ********************************/ 
    #ifdef TRACE2D
        FDebug2D(m ) ;
        MMechostr(MSKDEBUG,"(DBG) _CHKmenu done\r\n");
    #endif
    /************************************************************************/ 

    return s ;
}
