/*********************************************************************************************/
/*                                                                                           */
/*      File Fred_Ini.c                                                                      */
/*                                                                                           */
/*      Chargement des packages de l'interface 2D                                            */
/*                                                                                           */
/*********************************************************************************************/


//
// Modifications History
//
//$ LB (13/06/2002) : D2BITMAP : changed the destroy bitmap callback, according to the new ObjBitmap structure
//
//$LB (16/12/2003) : simulate window transparency (ScolPaintEvent, ScolEventSizeWindow, SColEventMoveWindow)
//
//$LB (27/02/2004) : SCOLprocessScroll : hack in order to make the scrollbar arrows work
//


#define _WIN32_WINNT 0x0400


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

#include "objstr.h"

#include "objects/listbox.h"
#include "objects/win_events.h"

#include "x/Version.h"

#include "x/scolplugin.h"


int SCOLEventSizeWindow ( mmachine m , HWND h , int TailleW , int TailleH );
extern void SCOLremakeScroll ( HWND child ) ;
int SCOLPaintEvent(mmachine m, HWND h);

void SCOLprocessMinMaxInfo ( mmachine m , HWND hw , MINMAXINFO * mmi );
void SCOLprocessScroll ( mmachine m , HWND hw , LPARAM l , WPARAM w , char mode ) ;
int SCOLHandleNotifyMessage ( mmachine m , NMHDR * p ) ;

int mouse_x = -1 ;
int mouse_y = -1 ;
extern int TESTCURSORMOVE ;





/*****************************************************************************/ 
/*                                                                           */ 
/*      Processing de la gestion des tailles minimales et maximales des      */ 
/*      fenetres.                                                            */ 
/*                                                                           */ 
/*****************************************************************************/ 

void SCOLprocessMinMaxInfo ( mmachine m , HWND hw , MINMAXINFO * mmi )
{
    int k ;
    PtrObjVoid O ;
    PtrObjWindow W ;
    
    if (hw == (HWND)SCgetExtra("hscol") ) return ;
    if (!m->tape ) return ;
    
    k = OBJfindTH(m,OBJTYPWINDOW,(int)(hw));   
    if ( k == NIL ) return ;
    k = MMfetch(m,k,OFFOBJMAG);
    O=(PtrObjVoid) MMstart(m,(k>>1));
    W=(PtrObjWindow) MMstart(m,(O->Buffer>>1));
    if ( W->MinW > 0 ) mmi->ptMinTrackSize.x = W->MinW ;
    if ( W->MinH > 0 ) mmi->ptMinTrackSize.y = W->MinH ;
    if ( W->MaxW > 0 ) mmi->ptMaxTrackSize.x = W->MaxW ;
    if ( W->MaxH > 0 ) mmi->ptMaxTrackSize.y = W->MaxH ;
}


/*****************************************************************************/ 
/*                                                                           */ 
/*       gestion des evenements de type notify                               */ 
/*                                                                           */ 
/*****************************************************************************/ 

int SCOLHandleNotifyMessage ( mmachine m,NMHDR *p)
{
    int k , hp , state , pi  ;
    NM_TREEVIEW * t ;
    NM_LISTVIEW * v ;
    PtrObjVoid O ;
    PtrObjTree Tree ;
    HIMAGELIST L ;  
    TV_ITEM tvi ;  
    LV_HITTESTINFO lvi ;
    POINT P ;
    RECT R ;

    if (p->code == TVN_ITEMEXPANDED ) 
    {
        k=OBJbeginreflex(m,OBJTYPTREE,(int)p->hwndFrom,RFLTREE_EXPAND);
        if (k==0) 
        {
            t = ( NM_TREEVIEW * ) p ;
            hp = ( int ) t->itemNew.hItem ;
            if ( t->itemNew.state & TVIS_EXPANDED ) state = 1 ; else state = 0 ;
            if (MMpush(m,hp<<1))              return MERRMEM ;
            if (MMpush(m,state<<1))           return MERRMEM ;
            return OBJcallreflex(m,2);
        }        
        return 0 ;
    }

    if ( p->code == TVN_SELCHANGED )
    {
        t = ( NM_TREEVIEW * ) p ;
        hp = ( int ) t->itemNew.hItem ;
        k=OBJbeginreflex(m,OBJTYPTREE,(int)p->hwndFrom,RFLTREE_SELECT);
        if(k==0)
        {   

            if (MMpush(m,hp<<1)) return MERRMEM ;
            return OBJcallreflex(m,1);
        }
        return 0 ;
    }
    
    if ( p->code == TVN_BEGINDRAG )
    {
       pi = OBJfindTH(m,OBJTYPTREE,(int)(p->hwndFrom));   
       pi = MMfetch(m,pi,OFFOBJMAG);
       O=(PtrObjVoid) MMstart(m,(pi>>1));
       Tree=(PtrObjTree) MMstart(m,(O->Buffer>>1));       
       t = ( NM_TREEVIEW * ) p ;
       L = TreeView_GetImageList (Tree->WHandler , TVSIL_NORMAL) ;
       if ( L==NULL ) MMechostr(MSKDEBUG,"(TREE) Drag&Drop ImageList NULL\n");
       Tree->Dragged = t->itemNew.hItem ;
       hp = ( int ) t->itemNew.hItem ; 
       tvi.hItem = t->itemNew.hItem ;
       tvi.mask = TVIF_SELECTEDIMAGE ;
       TreeView_GetItem ( Tree->WHandler ,  &tvi ) ;
     
       if (!ImageList_BeginDrag ( L , tvi.iSelectedImage , 0, 0))  
            MMechostr(MSKDEBUG,"(TREE) Drag&Drop failed for an unknow reason. IDX = %d\n",tvi.iSelectedImage);     
       GetCursorPos ( &P ) ;
       GetWindowRect ( Tree->WHandler , &R ) ;
       P.x -= R.left ;
       P.y -= R.top ;
       UpdateWindow ( Tree->WHandler ) ;
       
       ImageList_DragEnter ( Tree->WHandler,P.x,P.y);       
       
       return 0 ;
    }

    if (p->code == LVN_COLUMNCLICK )
    {
        k=OBJbeginreflex(m,OBJTYPLISTTAB,(int)p->hwndFrom,RFLLISTTAB_COLUMN);
        if(k==0)
        {
            v = ( NM_LISTVIEW * ) p ;
            if(MMpush(m,v->iSubItem<<1)) return MERRMEM; 
            return OBJcallreflex(m,1);

        }
        return 0 ;
    }

    
    if ( p->code == NM_DBLCLK )
    {
        k=OBJbeginreflex(m,OBJTYPLISTTAB,(int)p->hwndFrom,RFLLISTTAB_DCLICK);
        if(k==0)
        {
            GetCursorPos ( &(lvi.pt) ) ;
            ScreenToClient ( p->hwndFrom , &(lvi.pt) ) ;
            lvi.flags = LVHT_ONITEM ;
            ListView_HitTest ( p->hwndFrom, &lvi ) ;

            if (MMpush(m,lvi.iItem<<1)) return MERRMEM ;
            if(MMpush(m,0)) return MERRMEM; 
            return OBJcallreflex(m,2);

        }
        return 0 ;
    } ;

    if ((p->code == NM_CLICK)||(p->code == NM_RCLICK))
    {
        if (p->code==NM_CLICK) k=OBJbeginreflex(m,OBJTYPLISTTAB,(int)p->hwndFrom,RFLLISTTAB_SELECT);
		else k=OBJbeginreflex(m,OBJTYPLISTTAB,(int)p->hwndFrom,RFLLISTTAB_RSELECT);
        if(k==0)
        {
            
            GetCursorPos ( &(lvi.pt) ) ;
            ScreenToClient ( p->hwndFrom , &(lvi.pt) ) ;
            lvi.flags = LVHT_ONITEM  ;
            ListView_HitTest ( p->hwndFrom, &lvi ) ;
            MMechostr(MSKDEBUG,"Item found = %d\n",lvi.iItem);

            if (MMpush(m,lvi.iItem<<1)) return MERRMEM ;         
            return OBJcallreflex(m,1);

        }
        return 0 ;
    }

    if (p->code == LVN_BEGINDRAG )
    {
        MMechostr(MSKDEBUG,"Set BEGINDRAG\n");
    }
    else 
    if (p->code == LVN_GETDISPINFO )
    {
        MMechostr(MSKDEBUG,"Get DISP info\n");
    }
    //else MMechostr (1,"LV Code %d\n",p->code);
	return 0;
}


/****************************************************************************/ 
/*                                                                          */ 
/*  void SCOLprocessScroll ( mmachine m , HWND hw , LPARAM l ,              */ 
/*          WPARAM w , char mode ) ;                                        */ 
/*                                                                          */ 
/*  gere les scroll bars des fenetres scols                                 */ 
/*                                                                          */ 
/****************************************************************************/ 


void SCOLprocessScroll ( mmachine m , HWND hw , LPARAM l , WPARAM w , char mode ) 
{
    int code = LOWORD ( w ) ;
    int pos = HIWORD ( w ) ;
    RECT r; 
    int k ;
    PtrObjVoid O ; 
    PtrObjWindow W ;

    if (code == 8 ) return ;
	
	//$LB (27/02/2004) : hack in order to make the scrollbar arrows work
	if (mode == 1 && code == 1) pos = GetScrollPos (hw, SB_VERT)+1;
	if (mode == 1 && code == 0) pos = GetScrollPos (hw, SB_VERT)-1;
	if (mode == 0 && code == 1) pos = GetScrollPos (hw, SB_HORZ)+1;
	if (mode == 0 && code == 0) pos = GetScrollPos (hw, SB_HORZ)-1;


    SetScrollPos ( hw , mode==0?SB_HORZ:SB_VERT,pos,TRUE);
	
    /* trouver la fenetre fille */ 
    k = OBJfindTH(m,OBJTYPWINDOW,(int)(hw));   
    if ( k == NIL ) return ;
    k = MMfetch(m,k,OFFOBJMAG);
    O=(PtrObjVoid) MMstart(m,(k>>1));
    W=(PtrObjWindow) MMstart(m,(O->Buffer>>1));
    if ( W->Child )
    {
        GetClientRect (W->Child , &r ) ;    
        MoveWindow ( W->Child , - GetScrollPos ( hw , SB_HORZ ), 
                - GetScrollPos ( hw , SB_VERT ) , r.right , r.bottom , TRUE ) ;
    }
}

/****************************************************************************/
/*  void SCOLremakeScroll ( HWND child)                                     */
/*   repositionne les scroll a taille child - taille parent                 */
/*  si taille parent > taille child, scroll desactive                       */
/****************************************************************************/

void SCOLremakeScrollChild ( HWND child )
{

HWND parent = GetParent ( child ) ;
SCROLLINFO si ;
RECT rchild ;
RECT rparent ;
int rh , rw ;
int k  ;
PtrObjVoid O ;
PtrObjWindow W ;
RECT r ;

//    MMechostr ( 1 , "Passage SCOLremakeScroll\n" ) ;
    if ( parent == NULL ) return ;

    k = OBJfindTH(mm,OBJTYPWINDOW,(int)(parent));
    if ( k == NIL ) return ;
    k = MMfetch(mm,k,OFFOBJMAG);
    O=(PtrObjVoid) MMstart(mm,(k>>1));
    W=(PtrObjWindow) MMstart(mm,(O->Buffer>>1));

    if (( W->Flags & ( WN_HSCROLL | WN_VSCROLL )) == 0 ) return ;

    GetClientRect ( child , &rchild ) ;
    GetClientRect ( parent , &rparent ) ;

    rh = rchild.bottom - rparent.bottom ;
    rw = rchild.right - rparent.right ;

    MMechostr ( 1 , "Passage rh = %d rw = %d\n",rh,rw ) ;

    if ( W->Flags & WN_VSCROLL )
    {
        if ( rh > 0 )
        {
            si.cbSize = sizeof ( SCROLLINFO ) ;
            si.fMask = SIF_RANGE ;
            si.nMin = 0 ;
            si.nMax = rh ;
            SetScrollInfo ( parent , SB_VERT , &si , TRUE ) ;
            if ( GetScrollPos ( parent , SB_VERT ) > rh )
                SetScrollPos ( parent , SB_VERT , ((rh - 1)>0?rh-1:0) ,TRUE ) ;

            ShowScrollBar ( parent , SB_VERT , TRUE ) ;
        } else
        {
            ShowScrollBar ( parent , SB_VERT , FALSE ) ;
            SetScrollPos ( parent , SB_VERT , 0 , FALSE ) ;
        }
    }

    if ( W->Flags & WN_HSCROLL )
    {
        if ( rw > 0 )
        {
            si.cbSize = sizeof ( SCROLLINFO ) ;
            si.fMask = SIF_RANGE ;
            si.nMin = 0 ;
            si.nMax = rw ;
            SetScrollInfo ( parent , SB_HORZ , &si , TRUE ) ;
            if ( GetScrollPos ( parent , SB_HORZ ) > rw )
                SetScrollPos ( parent , SB_HORZ , ((rw-1)>0?rw-1:0),TRUE) ;
            ShowScrollBar ( parent , SB_HORZ , TRUE ) ;
        } else
        {
            ShowScrollBar ( parent , SB_HORZ , FALSE ) ;
            SetScrollPos ( parent , SB_HORZ , 0 , FALSE ) ;
        }
    }

    GetClientRect (child , &r ) ;
    MoveWindow ( child , - GetScrollPos ( parent , SB_HORZ ),
                - GetScrollPos ( parent , SB_VERT ) , r.right , r.bottom, TRUE ) ;
}

void SCOLremakeScroll( HWND Child )
{
int k ;
PtrObjVoid O ;
PtrObjWindow W ;

    SCOLremakeScrollChild ( Child ) ;
    k = OBJfindTH(mm,OBJTYPWINDOW,(int)(Child));
    if ( k == NIL ) return ;
    k = MMfetch(mm,k,OFFOBJMAG);
    O=(PtrObjVoid) MMstart(mm,(k>>1));
    W=(PtrObjWindow) MMstart(mm,(O->Buffer>>1));
    if ( W->Child ) SCOLremakeScrollChild (W->Child ) ;

}




int SCOLDropFiles ( mmachine m , HWND hwin , HDROP h , int TypeObjet , int ReflexNum )
{
    int C , L , res , k ;
    char Files [ 2048 ] ;
    POINT P ;

    k = OBJbeginreflex(m,TypeObjet,(int)hwin,ReflexNum);

    if (k==0)
    {
        C = DragQueryFile ( h , 0xFFFFFFFF , NULL , 0 ) ;
        if ( C > 0 )
        {
            DragQueryPoint(h,&P);
            if (MMpush(m,P.x<<1)) return MERRMEM ;
            if (MMpush(m,P.y<<1)) return MERRMEM ;
            MMpush(m,NIL) ; /* empile la queue de liste */         
            
            while ( C )
            {
                C -- ;
                L=DragQueryFile (h,C,Files,2048);
                Files[L]=0;         
                /* cree le doublet [S r1] */ 
                if (Mpushstrbloc(m,Files)) return MERRMEM ;

                /* inverse pour bien avoir la queue en dernier */ 
                res = MMget(m,1);
                MMset(m,1,MMget(m,0));
                MMset(m,0,res);

                if (MMpush(m,4)) return MERRMEM ;
                MBdeftab(m);             

            }          
            return OBJcallreflex(m,3);
        }
        return 0 ;
    }
	return 1;
}



int SCOLEventMoveText ( mmachine m , HWND h , short PosX , short PosY )
{
  int k;

  /* move fenetre window */
//  MMechostr ( 1 , "Event Move\n" ) ;
  k=OBJbeginreflex(m,OBJTYPTEXT,(int)h,RFLTEXT_MOVE);
  if (k==0)
    {
      if (MMpush(m,PosX<<1))              return MERRMEM ;
      if (MMpush(m,PosY<<1))              return MERRMEM ;
      return OBJcallreflex(m,2);
    }
  if (k<0) return 0;
  return 1 ;
}
    
int SCOLEventSizeText ( mmachine m , HWND h , int TailleW , int TailleH )
{
  int k;
  RECT rect ;

  /* size fenetre window */
//  MMechostr ( 1 , "Event Size\n" ) ;
  k=OBJbeginreflex(m,OBJTYPTEXT,(int)h,RFLTEXT_SIZE);
  if (k==0)
    {
//      MMechostr ( 1 , "execute reflex size window\n" ) ;
      GetClientRect ( h , &rect ) ;
      if (MMpush(m,rect.right <<1 ))              return MERRMEM ;
      if (MMpush(m,rect.bottom <<1 ))              return MERRMEM ;
      return OBJcallreflex(m,2);
    }
  if (k<0) return 0;
  return 1 ;
}




int SCOLEventMoveWindow ( mmachine m , HWND h , short PosX , short PosY )
{
  int k,s;
  PtrObjVoid O;
  PtrObjWindow W;

  /* move fenetre window */
  k=OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_MOVE);


  //$LB (16/12/2003) : if window transparency and Win95,98,ME,NT 
  //                   then repaint and simulate transparency
  if (k!=1)
  {

	  s=MMget(m,0);
	  O=(PtrObjVoid) MMstart(m,(s>>1));
      W=(PtrObjWindow) MMstart(m,(O->Buffer>>1));
	  if ((W != NULL) && (W->tSimulated))
	  {
         SCOLPaintEvent(m, h); 
	  }
  }

  if (k==0)
    {
      if (MMpush(m,PosX<<1))              return MERRMEM ;
      if (MMpush(m,PosY<<1))              return MERRMEM ;
      return OBJcallreflex(m,2);
    }



  if (k<0) return 0;
  return 1 ;
}
    



int SCOLEventSizeWindow ( mmachine m , HWND h , int TailleW , int TailleH )
{
  int k,s;
  PtrObjVoid O;
  PtrObjWindow W;
  RECT rect ;
  

  /* size fenetre window */ 
  k=OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_SIZE);

  




  //$LB (16/12/2003) : if window transparency and Win95,98,ME,NT 
  //                   then repaint and simulate transparency
  if (k!=1)
  {
	  s=MMget(m,0);
	  O=(PtrObjVoid) MMstart(m,(s>>1));
      W=(PtrObjWindow) MMstart(m,(O->Buffer>>1));
	  if ((W != NULL) && (W->tSimulated))
	  {
	    SCOLPaintEvent(m, h); 
	  }
  }


  if (k==0)
    {

      SCOLremakeScroll ( h ) ;
//      MMechostr ( 1 , "execute reflex size window\n" ) ;
      GetClientRect ( h , &rect ) ;
      if (MMpush(m,rect.right <<1 ))              return MERRMEM ;
      if (MMpush(m,rect.bottom <<1 ))              return MERRMEM ;
      return OBJcallreflex(m,2);
    }
  if (k<0) return 0;
  return 1 ;
}

int SCOLEventClickMouse(mmachine m, HWND h, short X, short Y, int B,int type,int reflexe)
{
  int k,p;
  PtrObjWindow W;
  PtrObjVoid O;

  if (type==OBJTYPWINDOW)
  {
       p = OBJfindTH(m,OBJTYPWINDOW,(int)h);
      if (p==NIL) 
      {
           return 1;
      }
      p = MMfetch(m,p,OFFOBJMAG);

      O=(PtrObjVoid) MMstart(m,p>>1);
      W=(PtrObjWindow) MMstart(m,O->Buffer>>1);
      if ( W->Flags & WN_NOCURSOR) return 0;
  }
  k=OBJbeginreflex(m,type,(int)h,reflexe);
  if(k==0)
    {
     

      if ( MMpush(m,X<<1))        return MERRMEM ;
      if ( MMpush(m,Y<<1))        return MERRMEM ;
      if ( MMpush(m,B<<1))        return MERRMEM ;
      return OBJcallreflex(m,3);
    }
  if(k<0) return 0 ;
  return 1;
}

int SCOLEventUnClickMouse(mmachine m, HWND h, short X, short Y, int B,int type,int reflexe)
{
  int k,p;
  PtrObjVoid O;
  PtrObjWindow W;

  if (type==OBJTYPWINDOW)
  {
      p = OBJfindTH(m,OBJTYPWINDOW,(int)h);
      if (p==NIL) 
      {
           return 1;
      }
      p = MMfetch(m,p,OFFOBJMAG);
      O=(PtrObjVoid) MMstart(m,p>>1);
      W=(PtrObjWindow) MMstart(m,O->Buffer>>1);
      if ( W->Flags & WN_NOCURSOR) return 0;
  }

  k=OBJbeginreflex(m,type,(int)h,reflexe);
  if(k==0)
    {
 

      if ( MMpush(m,X<<1))        return MERRMEM ;
      if ( MMpush(m,Y<<1))        return MERRMEM ;
      if ( MMpush(m,B<<1))        return MERRMEM ;
      return OBJcallreflex(m,3);
    }
  if(k<0) return 0 ;
  return 1;
}

extern HCURSOR   arrowCursor;

int SCOLEventMoveMouse(mmachine m, HWND h, short X, short Y, int S)
{
  int k,p;
  PtrObjVoid O;
  PtrObjWindow W;
  HCURSOR newcursor;

  p = OBJfindTH(m,OBJTYPWINDOW,(int)h);
  if (p==NIL) 
  {
	  return 1;
  }
  p = MMfetch(m,p,OFFOBJMAG);
  O=(PtrObjVoid) MMstart(m,p>>1);
  W=(PtrObjWindow) MMstart(m,O->Buffer>>1);
  if ( W->Flags & WN_NOCURSOR) return 0;

  if (W->Cursor) newcursor=W->Cursor;
  else newcursor=arrowCursor;

  if (newcursor != ( HCURSOR ) GetClassLong ( h , GCL_HCURSOR ))
  {
	  SetClassLong ( h , GCL_HCURSOR , (long) newcursor ) ;
	  SetCursor (newcursor);
  }

  k=OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_MOVEMOUSE);
  if(k==0)
    {

      if ( MMpush(m,X<<1))        return MERRMEM ;
      if ( MMpush(m,Y<<1))        return MERRMEM ;
      if ( MMpush(m,S<<1))        return MERRMEM ;
      return OBJcallreflex(m,3);
    }
  if(k<0) return 0 ;
  return 1;
}

int SCOLEventDClickMouse ( mmachine m , HWND h , short X , short Y , int B )
{
  int k,p;
  PtrObjVoid O;
  PtrObjWindow W;

  p = OBJfindTH(m,OBJTYPWINDOW,(int)h);
  if (p==NIL) 
  {
	  return 0;
  }
  p = MMfetch(m,p,OFFOBJMAG);
  O=(PtrObjVoid) MMstart(m,p>>1);
  W=(PtrObjWindow) MMstart(m,O->Buffer>>1);
  if ( W->Flags & WN_NOCURSOR) return 0;
  k=OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_DCLICK);
  if(k==0)
    {

      if ( MMpush(m,X<<1))        return MERRMEM ;
      if ( MMpush(m,Y<<1))        return MERRMEM ;
      if ( MMpush(m,B<<1))        return MERRMEM ;
      return OBJcallreflex(m,3);
    }
  if(k<0) return 0 ;
  return 1;
}


int SCOLKeyDownEvent(mmachine m,HWND h, int scancode, int KeyData)
{
  int k ;

  /***************** reflex pour les fenetres windows *******************/
  k = OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_KEYDOWN) ;
  if(k==0)
    {
      if(MMpush(m,scancode<<1)) return MERRMEM ;
      if(MMpush(m,KeyData<<1)) return MERRMEM ;
      return OBJcallreflex(m,2) ;
    }
  if(k<0) return 0 ;
  return 1;
}

int SCOLKeyUpEvent(mmachine m, HWND h, int Key) 
{
  int k;

  /* reflex pour les fenetres windows */
  k = OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_KEYUP) ;
  if(k==0)
    {
      if (MMpush(m,Key<<1)) return MERRMEM ;
      return OBJcallreflex(m,1) ;
    }
  if (k<0) return 0 ;
  return 1;
}

HWND HErase=NULL;



int SCOLPaintEvent(mmachine m, HWND h)
{
  int k;
  RECT r;



  k=OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_PAINT);

  if (k<=0) 
  {
	GetUpdateRect (h,&r,TRUE);
    if (k==0) OBJcallreflex(m,0);  

    ValidateRect(h,NULL);
	return 0;
  }


  return 1;

}

    
/* gestion de l'evenement  WM_COMMAND */

int SCOLCommandEvent(mmachine m,HWND Parent,int Code,int Control,HWND Child)
{
  int k,pos;  
  char Element [ 1024 ] ;
  
  
//  MMechostr( 1 , "Event : search for a reflex Parent%x Code %d Control %d Child %x\n" ,Parent, Code , Control , Child) ;

  /***********************************************************************************/
  /*          Reflex dans une combo box                                              */
  /***********************************************************************************/

  k=1;
  if ( Code == CBN_SELCHANGE ) 
  {
      k = OBJbeginreflex(m,OBJTYPCOMBOBOX,(int)Child,RFLCOMBOBOX_SELECT) ;
      if ( k == 0 )
      {
        pos = SendMessage(Child,CB_GETCURSEL,0,0) ;
        if ( pos == CB_ERR ) pos = -1 ;
        if ( MMpush(m,pos<<1)) return MERRMEM ;
        if ( pos != -1 ) pos = SendMessage(Child , CB_GETLBTEXT , pos , ( LPARAM ) Element ) ;
        if ( pos == CB_ERR || pos == -1 ) pos = MMpush(m,NIL) ;
        else if ( Mpushstrbloc(m,Element )) return MERRMEM ;
          return OBJcallreflex(m,2);
      }
      else if ( k < 0 ) return 0 ;

  }
  /***********************************************************************************/
  /*          Reflex selection dans un menu                                          */
  /***********************************************************************************/
  if (Child == 0 ) k=OBJbeginreflex(m,OBJTYPMENUITEM,Control,RFLMENUITEM_SELECT) ; else k = 1 ;
  if ( k == 0 )
    {
    #ifdef TRACE_EVENT
          MMechostr( 1 , "execute reflex event menu item\n" ) ;
    #endif
      OBJcallreflex(m,0) ;
      return 1;
    }
  if ( k < 0 ) return 1 ;

  /***********************************************************************************/
  /*              Reflex click sur push button = RFLBUTTON_EVENT                     */
  /***********************************************************************************/

  if (Child!=0) k=OBJbeginreflex(m,OBJTYPBUTTON,(int)Child,RFLBUTTON_EVENT) ; else k = 1 ;
  if (k==0)
    {
    #ifdef TRACE_EVENT
      MMechostr ( 1 , "execute reflex event bouton\n" ) ;
    #endif
      return OBJcallreflex(m,0);
    }
  if( k < 0 ) return 0 ;

  /***********************************************************************************/
  /*              Reflex coche/decoche une check box = RFLCHECK_EVENT                */
  /***********************************************************************************/

  if ( Child!=0) k=OBJbeginreflex(m,OBJTYPCHECK,(int)Child,RFLCHECK_EVENT) ;
  if(k==0)
    {
    #ifdef TRACE_EVENT
      MMechostr ( 1 , "execute reflex event check box\n" ) ;
    #endif
      if ( MMpush(m,SendMessage(Child,BM_GETCHECK,0,0) << 1)) return MERRMEM ;
      return OBJcallreflex(m,1);
    }
  if( k < 0 ) return 0 ;

  /**********************************************************************************/
  /*            Reflex d'ajout d'un caractere dans un objet texte = RFLTEXT_EVENT   */
  /**********************************************************************************/

  if((Child !=0) && (Code==768)) k=OBJbeginreflex(m,OBJTYPTEXT,(int)Child,RFLTEXT_EVENT) ; else k = 1 ;
  if(k==0)
    {
    #ifdef TRACE_EVENT          
      MMechostr ( 1 , "execute reflex event text\n" ) ;
    #endif
      return OBJcallreflex(m,0) ;
    }
  if(k<0) return 0 ;

  /************************************************************************************/
  /*        Reflex des list box                                                       */
  /************************************************************************************/

  if (Child && Code == LBN_SELCHANGE )
  {
      k = OBJbeginreflex ( m,OBJTYPLISTBOX,(int)Child,RFLLISTBOX_CLICK) ;
      if ( k == 0 )
      {
            #ifdef TRACE_EVENT
                MMechostr ( 1 , "Execute reflex list box click\n" ) ;
            #endif
            pos = SendMessage ( Child , LB_GETCURSEL , 0 , 0 ) ;
            if ( MMpush(m,pos<<1)) return MERRMEM ;
			GRpushListElement(m,Child,pos);
            return OBJcallreflex(m,2 ) ;
      }
      if ( k < 0 ) return 0 ;
  }

  if ( Child && Code == LBN_DBLCLK )
  {
      k = OBJbeginreflex ( m , OBJTYPLISTBOX,(int)Child,RFLLISTBOX_DCLICK ) ;
      if ( k == 0 )
      {
        #ifdef TRACE_EVENT
            MMechostr ( 1 , "Execute reflex list box dclick\n" ) ;
        #endif
        pos = SendMessage ( Child , LB_GETCURSEL , 0 , 0 ) ;
        MMpush(m,pos<<1) ;
		GRpushListElement(m,Child,pos);
        return OBJcallreflex(m,2) ;
      }
      if ( k < 0 ) return 0 ;      
  } 
  return 1;
}


int SCOLDestroyEvent(mmachine m,HWND h)
{
  int k,p;

  /*********** destruction d'une fenetre window ******/
  k = OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_DESTROY) ;
  if (k<=0)
  {
//	  MMechostr(MSKDEBUG,"destroyevent win %x\n",h);
	  p=OBJfindTH(m,OBJTYPWINDOW,(int)h);
      OBJdel(m,p,-1);
      if (k==0) return OBJcallreflex(m,0) ;
	  return 0;
  }
  return 1;
}


int SCOLCloseEvent(mmachine m,HWND h)
{
  int k;

  /*********** destruction d'une fenetre window ******/
  k = OBJbeginreflex(m,OBJTYPWINDOW,(int)h,RFLWINDOW_CLOSE) ;
  if (k==0) return OBJcallreflex(m,0) ;
  if (k<0) return 1 ;
  return 1;
}


#define WHEEL_DELTA 120

int SCOLEventMouseWheel(mmachine m,HWND hwnd, int delta, int x, int y, UINT keyFlags)
{
	int d=delta/WHEEL_DELTA;
	POINT P;
	int k,mask;
	
	P.x=x;
	P.y=y;
	
	// on recupere les coordonées de la souris par rapport à la zone client
	ScreenToClient(hwnd,&P);
	
	k=OBJbeginreflex(m,OBJTYPWINDOW,(int)hwnd,RFLWINDOW_WHEEL);
	if (k==0)
	{
		mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
		if (MMpush(m,2*(P.x))) return MERRMEM;
		if (MMpush(m,2*(P.y))) return MERRMEM;
		if (MMpush(m,2*(d))) return MERRMEM;
		if (MMpush(m,2*(mask))) return MERRMEM;
		return OBJcallreflex(m,4);
	}
	return 1;
}

int SCOLEventPower(mmachine m,HWND hwnd, int val)
{
	int k,rfl;

	rfl=-1;
	if (val==PBT_APMSUSPEND) rfl=RFLWINDOW_SUSPEND;
	else if (val==PBT_APMRESUMESUSPEND) rfl=RFLWINDOW_RESUME;
	if (rfl==-1) return 1;
		
	k=OBJbeginreflex(m,OBJTYPWINDOW,(int)hwnd,rfl);
	if (k==0) OBJcallreflex(m,0);
	return 1;
}

#include "Keysymde.h"

int TabCodes[160]=
{
0,0,0,0,0,0,0,0, /*0.*/
0,0,0,0,0,0,0,0,
0,0,0,XK_Pause,XK_Caps_Lock,0,0,0,
0,0,0,XK_Escape,0,0,0,0,
0,XK_Prior,XK_Next,XK_End,XK_Home,XK_Left,XK_Up,XK_Right,
XK_Down,0,0,0,XK_Sys_Req,XK_Insert,XK_Delete,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, /*4.*/
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
XK_F1,XK_F2,XK_F3,XK_F4,XK_F5,XK_F6,XK_F7,XK_F8,
XK_F9,XK_F10,XK_F11,XK_F12,XK_F13,XK_F14,XK_F15,XK_F16,
0,0,0,0,0,0,0,0, /*8.*/
0,0,0,0,0,0,0,0,
XK_Num_Lock,XK_Scroll_Lock,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};

int convertvirtcode(int c)
{
    if ((c<0)||(c>=160)) return 0;
    return TabCodes[c];
}



int D2events(mmachine m,HWND hwnd,unsigned int msg,UINT wParam, LONG lParam,int *ret)
{
    int c,k,res;
	POINT P;
    NMHDR * pnmh ;
	MINMAXINFO * mmi ;

    res=1;
    switch( msg ) {
    case WM_HSCROLL :
		SCOLprocessScroll ( m , hwnd , lParam , wParam , 0 ) ;
		res=0;
        break ;
    case WM_VSCROLL :
		SCOLprocessScroll ( m , hwnd , lParam , wParam , 1 ) ;
		res=0;
        break ;
	case WM_GETMINMAXINFO :
		mmi = ( LPMINMAXINFO ) lParam ;
        SCOLprocessMinMaxInfo (  m , hwnd , (LPMINMAXINFO) lParam );
        res=0;
        break ;
	case WM_DROPFILES :
		SCOLDropFiles ( m,hwnd,(HANDLE)wParam,OBJTYPWINDOW,RFLWINDOW_DROPFILE);
        res=0;
        break; 
    case WM_NOTIFY :
		pnmh = (LPNMHDR) lParam ;
        SCOLHandleNotifyMessage (m, pnmh ) ;
		res=1;
        break ;
    case WM_SETFOCUS :
        SCOLFocusWindow ( m , ( HWND ) hwnd ) ;
		res=1;
        break ;
    case WM_KILLFOCUS :
        SCOLKillFocusWindow ( m , ( HWND ) hwnd ) ;
        res=1;
        break ;
    case WM_DESTROY:
        res=SCOLDestroyEvent(m,hwnd);
        break;
    case WM_CLOSE:
        res=SCOLCloseEvent(m,hwnd);
        break;
    case WM_CHAR:
        if ((int)wParam!=XK_Escape)
        res=SCOLKeyDownEvent(m,hwnd,(lParam>>16)&0x1ff,wParam);
        break;
    case WM_KEYDOWN:
        c=convertvirtcode((int)wParam);
        if (c==0) break;
        res=SCOLKeyDownEvent (m,hwnd,(lParam>>16)&0x1ff,c);
        break ;
    case WM_KEYUP:
        res=SCOLKeyUpEvent(m,hwnd,(lParam>>16)&0x1ff);
        break ;
    case WM_COMMAND :
        res=SCOLCommandEvent (m,hwnd,HIWORD(wParam),LOWORD(wParam),(HWND)lParam);
        break ;
    case WM_LBUTTONUP :
		if ((wParam & MK_RBUTTON)==0) ReleaseCapture();
        k=1;
        res=SCOLEventUnClickMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k,OBJTYPWINDOW,RFLWINDOW_UNCLICK);
        break ;
    case WM_RBUTTONUP :
		if ((wParam & MK_LBUTTON)==0) ReleaseCapture();
        k=2;
        res=SCOLEventUnClickMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k,OBJTYPWINDOW,RFLWINDOW_UNCLICK);
        break ;
    case WM_LBUTTONDOWN :
		SetCapture(hwnd);
        k=1;
        res=SCOLEventClickMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k,OBJTYPWINDOW,RFLWINDOW_CLICK);
        break ;
    case WM_RBUTTONDOWN :
		SetCapture(hwnd);
        k=2;
        res=SCOLEventClickMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k,OBJTYPWINDOW,RFLWINDOW_CLICK);
        break ;
    case WM_LBUTTONDBLCLK : 
        SetCapture(hwnd);
        k=1;
        res=SCOLEventDClickMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k);
        break;
    case WM_RBUTTONDBLCLK :
        SetCapture(hwnd);
        k=2 ;
        res=SCOLEventDClickMouse (m,hwnd,LOWORD(lParam),HIWORD(lParam),k);
        break ;
    case WM_MOUSEMOVE :
        if ( TESTCURSORMOVE )
        {
            TESTCURSORMOVE = 0 ;
            break;
        }
        GetCursorPos ( &P ) ;        
        if ( P.x == mouse_x && P.y == mouse_y )
        {
            #ifdef TRACE_MSG
                MMechostr(MSKDEBUG,"Message ignore\n");
            #endif            
            break ;
        }
        mouse_x = P.x ; mouse_y = P.y ;        
        
        k=wParam&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
		res=SCOLEventMoveMouse(m,hwnd,LOWORD(lParam),HIWORD(lParam),k);
        break ;
    case WM_PAINT:
        res=SCOLPaintEvent(m,hwnd);
        break;
        
    case WM_MOVE :
        res=SCOLEventMoveWindow ( m,hwnd,LOWORD(lParam),HIWORD(lParam)) ;
        break ;
    case WM_SIZE :
        res=SCOLEventSizeWindow ( m,hwnd,LOWORD(lParam),HIWORD(lParam )) ;
        break ;
	case WM_MOUSEWHEEL:
		res=SCOLEventMouseWheel(m,hwnd,
                               (int)(short)HIWORD(wParam), 
                               (int)(short)LOWORD(lParam),
                               (int)(short)HIWORD(lParam),
                               (int)(short)LOWORD(wParam));
	    break;
	case WM_POWERBROADCAST:
		res=SCOLEventPower(m,hwnd,wParam);
		break;
	}
	return res;
}


int D2WINDOW(mmachine m,int handsys,int objm)
{
//	MMechostr(MSKDEBUG,"destroy window %x\n",handsys);
    DestroyWindow((HWND)handsys);
	return 0;
}
int D2BUTTON(mmachine m,int handsys,int objm)
{
    DestroyWindow((HWND)handsys);
	return 0;
}
int D2TEXT(mmachine m,int handsys,int objm)
{
    DestroyWindow((HWND)handsys);
	return 0;
}
int D2FONT(mmachine m,int handsys,int objm)
{
    DeleteObject((HFONT)handsys);
	return 0;
}
int D2CHECK(mmachine m,int handsys,int objm)
{
    DestroyWindow((HWND)handsys);
	return 0;
}
int D2MENU(mmachine m,int handsys,int objm)
{
	PtrObjVoid O ;
	PtrObjMenu Me ;
	O = ( PtrObjVoid ) MMstart(m,objm>>1);
	Me = ( PtrObjMenu ) MMstart(m,O->Buffer>>1);
	if ( Me->HParent ) RemoveMenu ( Me->HParent , ( int ) Me->WHandler , MF_BYCOMMAND ) ;
	DestroyMenu ( Me->WHandler ) ;          
	return 0;
}
int D2MENUITEM(mmachine m,int handsys,int objm)
{
	PtrObjVoid O ;
	PtrObjMenuItem MI ;
	O = ( PtrObjVoid ) MMstart(m,objm>>1);
	MI = ( PtrObjMenuItem ) MMstart(m,O->Buffer>>1);
	DeleteMenu (MI->WHandler,MI->Handler,MF_BYCOMMAND);
	return 0;
}
int D2COMBOBOX(mmachine m,int handsys,int objm)
{
	DestroyWindow ((HWND)handsys);
	return 0;
}



//$ LB (13/06/2002) : changed the destroy bitmap callback, according to the new ObjBitmap structure
int D2BITMAP(mmachine m,int handsys,int objm)
{
	PtrObjVoid O ;
	PtrObjBitmap B ;


	O = ( PtrObjVoid ) MMstart(m,objm>>1);
	B = ( PtrObjBitmap ) MMstart(m,O->Buffer>>1);
	/* debut rem */
/*      if (O->Tab==NIL) MMechostr(MSKDEBUG,"bitmap is _CRbitmap\n");
		  else  MMechostr(MSKDEBUG,"bitmap is _LDbitmap : %s\n",MMstartstr(m,O->Tab>>1));
	  MMechostr(MSKDEBUG,"deleting bitmap %x %d %d\n",handsys,B->TailleW,B->TailleH);
*/
/* fin rem */

	if (B->DIBhandler)
	{
		DeleteObject ( (HBITMAP ) B->DIBhandler ) ;
	}
	else
	{
		free (B->bits);
		if (B->table) free (B->table);
	}

	//don't set B->handler to NULL : it can be used to print some infos...
	B->DIBhandler = NULL;
	B->bits       = NULL;
	B->table      = NULL;

	return 0;
}



int D2CURSOR(mmachine m,int handsys,int objm)
{
	DestroyCursor ( (HCURSOR ) handsys ) ;
	return 0;
}
int D2LISTBOX(mmachine m,int handsys,int objm)
{
	DestroyWindow ((HWND)handsys);
	return 0;
}
int D2RICHTEXT(mmachine m,int handsys,int objm)
{
	DestroyWindow ((HWND)handsys);
	return 0;
}
int D2TREE(mmachine m,int handsys,int objm)
{
	DestroyWindow ((HWND)handsys);
	return 0;
}
int D2LISTBITMAP(mmachine m,int handsys,int objm)
{
    ImageList_Destroy ( (HIMAGELIST ) handsys ) ;
	return 0;
}
int D2LISTTAB(mmachine m,int handsys,int objm)
{
    DestroyWindow ( ( HWND ) handsys ) ;
	return 0;
}
int D2HEADER(mmachine m,int handsys,int objm)
{
    DestroyWindow ( ( HWND ) handsys ) ;
	return 0;
}



