//////////////////////////////////////////////////////////////////////
// container.cpp: implementation of the container class.
//
//////////////////////////////////////////////////////////////////////


//
// Modifications History
//
//$LB (20/12/2002) : 16bits to 24bits
//
//$LB (11/11/2003) : add _SETcontainerCursor
//
//$LB (16/12/2003) : add _SETcontainerTransparency (in container_trans.cpp)
//
//$LB (16/12/2003) : add _SIMULATEcontainerTransparency  (int container_trans.cpp)
//



#include "../x/Version.h"
#include "../x/scolplugin.h"

#include <Commctrl.h>

#include "Macro.h"
#include "../x/Objstr.h"
#include "container.h"
#include "CObjBufferWindows.h"
#include "CObjBufferDirectX.h"
#include "lib2Dconf.h"
#include "utils.h"
#include "colors.h"
extern "C" 
{
  #include "osversion.h"
}
#include "bitmap.h"

#define TME_IN  (1<<1)
#define TME_OUT (1<<2)
#define TME_RANGE 100

extern HINSTANCE hinst;
extern mmachine mm;
extern int OBJCONTAINER;
extern int OBJNODE;


static	int	TypeBlit;








BOOL	InitContainer(HINSTANCE hInst)
{
	TypeBlit=DetectBlitType();

  //$BLG: v4.6a5 - Add
  //arrowCursor = LoadCursor( hInst, IDC_ARROW );

	return TRUE;
}

BOOL	UnLoadContainer()
{
	//$BLG: v4.6a5 - Add
	//DestroyCursor(arrowCursor);	
	//DeleteObject(arrowCursor);
	
	return TRUE;
}



// recupere le container a partir du descripteur scol
container * RetrievePtrContainer(mmachine m,int pdesc)
{
	int p_cont;
	if ((p_cont=MMfetch(m,pdesc,1)) == NIL) 
		return NULL;
	else
		return (container *) MMfetch(m,MTOP(p_cont),0);
}

/* recupere le container à partir de son handleur systeme */
container * RetrieveContainerFromHdlSys(int hdlsys)
{
	int p;
	if ((p = OBJfindTH( mm, OBJCONTAINER,hdlsys ))==NIL) return NULL;
	return  RetrievePtrContainer(mm,MTOP(MMfetch(mm,p,OFFOBJMAG ) ));
}

/* recupere le tuple correspondant au container */
int RetrieveMContainer(int hdlsys)
{
	int p;
	if ((p = OBJfindTH(mm, OBJCONTAINER,hdlsys ))==NIL) return NIL;
	return  MTOP(MMfetch(mm,p,OFFOBJMAG));
}

		//////////////////////////////////////////////////////////////////////
		//                 Container associé à une fenetre                  //
		//////////////////////////////////////////////////////////////////////

// constructeur du container
container::container(Window *win,int w,int h,int BckColor)
{	
	if (DEBUG_CONTAINER) MMechostr(MSKTRACE,"Starting container creation\n");
	
	CoCursorPosX=-1;
	CoCursorPosY=-1;

	//$BLG
	//MMechostr(0,"$BLG: container - BG - %i\n", BckColor);
	CoBackgroundColor=BckColor;
	CoXsize=w;
	CoYsize=h;
	CoWin=win;
	CoEnabled=1;

	// creation de l'objet d'affichage
	switch (TypeBlit)
	{
#ifdef USE_DIRECTX
		case BLIT_DIRECTX:
			CoBuffer=new CObjBufferDirectX(NULL); 
			break;
#endif
#ifdef USE_OPENGL
		case BLIT_OPENGL :
			break;
#endif
#ifdef USE_WINDOWS
		case BLIT_WINDOWS:
#endif
		default:
			 CoBuffer=new CObjBufferWindows(CoXsize,CoYsize);
			break;
	}
	
	CoTabStopSize=0;
	CoTabStopObjects=NULL;
	CoHandledObject=NULL;
  CoFocusedObject=NULL;
	CoActiveObject=NULL;
	CoActiveToolTipObject=NULL;
	CoNewHandledObject=NULL;

	CoOutPushedAlreadySent=0;
	CoInPushedAlreadySent=0;
	CoCurrentKeyFlags=0;

	// mise en place du service de timers
	CoTimerService = new CObjTimer();
	CoTMEtimer=NO_TIMER;
	if (CoWin!=NULL)
	{
		// demarrage du track mouse event
		Point2D pt =win->GetCursorPosScreen();
		Rect2D rect=win->GetClientInScreen();
		CoTMEcursorInContainer=(IsPointInRectangle(pt,rect)|| win->IsPointInWindow(pt));
		StartTME(TME_IN|TME_OUT);
	}

	if (DEBUG_CONTAINER) 
		MMechostr(MSKTRACE,"Container created succefully\n");
}

container::~container()
{
	// destruction du timer tooltip
	if (CoActiveToolTipObject!=NULL)
	{	 
		CoActiveToolTipObject->ObjToolTip->Disarm();
		CoActiveToolTipObject=NULL;
	}

	mt_del(CoTMEtimer);
	
	// destruction du service timer
	delete(CoTimerService);
	CoTimerService = NULL;

	// destruction recursives des objnodes
	OBJdelTH( mm,OBJNODE,(int)CoRoot);	
	
	// destruction du buffer offscreen 
	delete(CoBuffer);

	if (CoTabStopObjects!=NULL)
		free(CoTabStopObjects);

	// destrution de la fenetre
	if (CoWin!=NULL)
		delete(CoWin);
	
if (DEBUG_CONTAINER) 
		MMechostr(MSKTRACE,"Destruction container\n");
}

int container::posTabStop(PtrObjectBase obj)
{
	if (obj && CoTabStopObjects)
	{
		int i=0;
		while (i<CoTabStopSize)
		{
			if (CoTabStopObjects[i]==obj)
				return i;
			i++;
		}
	}
	return -1;
}

// fonction d'ajout d'un objet dans la liste des objets en tabstop
int container::addTabStopObjects(PtrObjectBase obj)
{
	if (obj)
	{
		obj->setFlags(obj->getFlags()|OBJ_TABSTOP);
		CoTabStopObjects=CoTabStopObjects==NULL?
						 (CObjectBase**)malloc(sizeof(CObjectBase*)):
						 (CObjectBase**)realloc(CoTabStopObjects,sizeof(CObjectBase*)*(CoTabStopSize+1));
		CoTabStopObjects[CoTabStopSize]=obj;
		return CoTabStopSize++;
	}
	return -1;
}

int container::remTabStopObjects(PtrObjectBase obj)
{
	int pos;
	if (obj)
		obj->setFlags(obj->getFlags()&(~OBJ_TABSTOP));
	if (obj && 
		CoTabStopObjects && 
		(pos=posTabStop(obj))!=-1
	   )
	{
		// on a trouvé l'objet, on le supprime
		CObjectBase** tmp=(CObjectBase**)malloc(sizeof(CObjectBase*)*(CoTabStopSize-1));
		memcpy(tmp,CoTabStopObjects,sizeof(CObjectBase*)*pos);
		if (pos+1<CoTabStopSize)
			memcpy(tmp+pos,CoTabStopObjects+pos+1,sizeof(CObjectBase*)*(CoTabStopSize-pos));
		free(CoTabStopObjects);
		CoTabStopObjects=tmp;
		CoTabStopSize--;
		
		/* si plus aucun element on vire la reference */
		if (CoTabStopSize==0)
		{
			free(CoTabStopObjects);
			CoTabStopObjects=NULL;
		}
		return pos;
	}
	return -1;
}

PtrObjectBase container::nextTabStop(PtrObjectBase obj)
{
	int pos;
	if ((pos=posTabStop(obj))!=-1 &&
		(pos!=(CoTabStopSize-1))
	   )
		return CoTabStopObjects[pos+1];
	else if (obj==NULL && CoTabStopObjects!=NULL)
		return CoTabStopObjects[0];
	return NULL;
}

PtrObjectBase container::prevTabStop(PtrObjectBase obj)
{
	int pos;
	if ((pos=posTabStop(obj))!=-1 &&
		(pos!=0)
	   )
		return CoTabStopObjects[pos-1];
	else if (obj==NULL && CoTabStopObjects!=NULL)
		return CoTabStopObjects[CoTabStopSize-1];
	return NULL;
}

int container::testTabStop(int vk)
{
	if (vk==9)
	{
		if (OBJ_VALIDITY(CoActiveObject) && !CoActiveObject->IsObjectTabStop())
			return 0;

		// perte de focus de l'objet actif
		if (CoActiveObject!=NULL)
			CoActiveObject->KillFocus (GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
		
		// on recupere l'objet actif au cas ou il a ete detruit
		OBJ_VALIDITY(CoActiveObject);
		
		// search for the next tabstop
		int shift=(int)(GetKeyState(VK_SHIFT)>>8)&1;
		do 	
			CoActiveObject=(shift?prevTabStop(CoActiveObject):nextTabStop(CoActiveObject));
		while (!((CoActiveObject==NULL) 
			     ||(CoActiveObject!=NULL 
					&& CoActiveObject->CanBeActiveObject() 
					&& CoActiveObject->IsObjectEnabled()
				   )
				)
			  );

		// changement de focus du nouvel objet actif
		if (CoActiveObject!=NULL)
			CoActiveObject->SetFocus(1,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
		else
			CoFocusedObject=CoActiveObject=NULL;
		return 1;
	}
	return 0;
}

int container::resetTabStop()
{
	int i;
	for (i=0;i<CoTabStopSize;i++)
		CoTabStopObjects[i]->setFlags(CoTabStopObjects[i]->getFlags()&(~OBJ_TABSTOP));
	free(CoTabStopObjects);
	CoTabStopObjects=NULL;
	CoTabStopSize=0;
	return 0;
}	

int container::SetFocus(PtrObjectBase obj)
{
	if (obj!=NULL)
	{
		if (CoActiveObject!=NULL)
			CoActiveObject->KillFocus(GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
		CoActiveObject=obj;
		CoActiveObject->SetFocus(1,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
		// $BLG: v5.01 - Add
		// If application changes Focus, for example to an ObjWin, the container's object Focus was lost
		CoFocusedObject = obj;
	}
	//$BLG - v5.01: Add
	else
	{
		if (CoActiveObject != NULL)
			CoActiveObject->KillFocus(GetTab(mm, FindObjNodeFromHdlSys(mm, (int)CoActiveObject)), 1);
		CoActiveObject = NULL;
		CoFocusedObject = NULL;
	}
	
	return 0;
}

/* Creation dans la pile Scol de l'Objet Container
   ObjContainer <-> [root container objbitmap win channel]
   id = (int)cont
*/
int	container::ConstructScolContainer(mmachine m)
{
	int p_res,tmp_res;

	// etat de la pile: channel parent x y w h Flags name pour un container-fenetre
	//					channel pour un container virtuel
	
	// creation de la fenetre
	CHECK(CoWin!=NULL?CoWin->ConstructWindow():MMpush(m,NIL));
	INVERT(m,0,1);

	// etat de la pile: win channel
	PtrObjectBase root =new CObjectContainer(this,NULL,0, 0, 0, 0, OBJ_ENABLE|OBJ_VISIBLE, 0, NO_TRANSPARENCY );
	CHECK( CrRoot( m, root ,0) );
	SetRoot(root);
	
	
	// etat de la pile: win channel root
	// creation de l'objet
	if (( p_res= MMmalloc(mm,1,TYPEBUF) )<0) return p_res;
	MMstore(m,p_res,0,(int)this);
	CHECK(MMpush(m,PTOM(p_res)));
	
	// etat de la pile: win channel root container
	
	// on cree l'ObjBitmap pour le buffer
	CHECK(CoBuffer->CreateScolBuffer(mm,2,(int)this));

	// etat de la pile: win channel root container objbitmap
	CHECK(MMpush(m,MMget(m,4)));

	// etat de la pile: win channel root container objbitmap win
	CHECK(MMpush(m,MMget(m,4)));

	// etat de la pile: win channel root container objbitmap win channel
	CHECK(MMpush(m, ITOM(5) ));
	CHECK(MBdeftab(m));

	// etat de la pile:win channel [root container ObjBitmap win channel]

	// creation de l'objet -> [Root (Buff)*container ObjBitmap win channel] 
	// d'identifiant le pointeur du container
	CHECK( OBJcreate(m,OBJCONTAINER,(int)this,-1,0) );
	
	// etat de la pile:win cont=[root container ObjBitmap win channel]
	INVERT(m,0,1);

	//etat de la pile:cont win
	if (CoWin!=NULL)
	{
		CHECK(CoWin->SetReflexes());	//Creation des Reflexes			
		CHECK(CoWin->Show());
	}
	MMpull(m);
	return 0;
}

int	container::DestructScolContainer(mmachine m,int p_obj)
{
	MMstore(m,p_obj,0,NIL);
	
	MMstore(m,p_obj,1,NIL);

	// l'ObjBitmap est detruite automatiquement par destruction du container
	MMstore(m,p_obj,2,NIL);
	
	// destruction de la fenetre
	if (CoWin!=NULL)
		CoWin->DestructWindow(MMfetch(m,p_obj,3));
	MMstore(m,p_obj,3,NIL);
	return 0;
}


		//////////////////////////////////////////////////////////////////////
		//          Le traitement des messages dans le container            //
		//////////////////////////////////////////////////////////////////////


int container::HdlPreDestroy(int id)
{
	int k;
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_PREDESTROY);
	if (k>0) return 1; 
	if (k==0) OBJcallreflex(mm,0);
	return 0L;
}

int container::HdlDestroy(int id)
{

	int k;
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_DESTROY);
	if (k>0) return 1; 
	if (k==0) OBJcallreflex(mm,0); 
	return 0L;

	// la fenetre vient d'etre detruite, mais le container par contre ne l'est pas
	OBJdelTH(mm,OBJCONTAINER,(int)this);	
}

int container::HdlPaint(int id)
{
	if (!IsEnabled()) return 0;

	// on redessine que la zone
	if (CoWin!=NULL)
	{
		Rect2D rect=CoWin->GetUpdatableRect();

		CoWin->BlitBuffer((CObjBufferWindows*)CoBuffer, CoBuffer->GetId(),
						  TypeBlit,
						  rect.RctHG.iptX,
						  rect.RctHG.iptY,
						  rect.RctBD.iptX,
						  rect.RctBD.iptY,
						  rect.RctHG.iptX,
						  rect.RctHG.iptY
						 );
	}
	// execution du reflexe de paint
	int k;
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_PAINT);
	if (k>0) return 1; 
	if (k==0) return OBJcallreflex(mm,0);
	return 0;
}

int i=0;

int container::HdlSize(int id,UINT state, int cx, int cy)
{
	if (!IsEnabled()) return 0;
	
	if (!(cx==0 || cy==0))
	{	
		// si non minimisée
		// redimmensionnement de tous les nodes Attention possibilité de destruction
		// du container ou autre
		ApplyOnTree(1,mm,GetSon(mm,FindObjNodeFromHdlSys(mm,(int)CoRoot)),&ComputeResize,cx,cy);
		
		/* prevent from destruction of container in user callback during resizing of objnodes*/
		if (RetrieveContainerFromHdlSys((int)this)==NULL) 
			return 0;

		// mise à jour de la taille du container
		
		CoXsize=cx;
		CoYsize=cy;
		
		// mise à jour du buffer du container
		delete(CoBuffer);
		switch (TypeBlit)
		{
#ifdef USE_DIRECTX
			case BLIT_DIRECTX:
				CoBuffer=new CObjBufferDirectX(NULL); 
				break;
#endif
#ifdef USE_OPENGL
			case BLIT_OPENGL :
				break;
#endif
#ifdef USE_WINDOWS
			case BLIT_WINDOWS:
#endif
			default:
				 CoBuffer=new CObjBufferWindows(CoXsize,CoYsize);
				break;
		}

		
		// creation du nouveau objbitmap
		int p,tmp_res;
		if ((p = RetrieveMContainer(id))!=NIL)
		{
			// empile le canal
			CHECK(MMpush(mm,MMfetch(mm,p,4)));
			CHECK(CoBuffer->CreateScolBuffer(mm,0,id));
			int bmp=MMpull(mm);
			// depile le canal
			MMpull(mm);

			// remplacement de l'ancien par le nouveau dans 
			// le pointeur scol du container
			if ((p = RetrieveMContainer(id))!=NIL)
				MMstore(mm,p,2,bmp);

		}
		Redraw(1);
	}
	int k,tmp_res;	
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_SIZE);
	if (k>0) return 1; 
	if (k==0) 
	{
		CHECK(MMpush(mm,ITOM(state&(CONTAINER_HIDDEN|
									CONTAINER_UNHIDDEN|
									CONTAINER_MAXIMIZED|
									CONTAINER_MINIMIZED|
									CONTAINER_RESTORED
								   )
						    )));
      	CHECK(MMpush(mm,ITOM(cx)));
		CHECK(MMpush(mm,ITOM(cy)));
		return OBJcallreflex(mm,3);
	}
	return 0;
}

int container::HdlMove(int id,int x, int y)
{
	if (!IsEnabled()) return 0;

	int k,tmp_res;
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_MOVE);
	if (k>0) return 1; 
	if (k==0)
	{
	  CHECK(MMpush(mm,ITOM(x)));
      CHECK(MMpush(mm,ITOM(y)));
      return OBJcallreflex(mm,2);
	}
	return 0;
}

int container::HdlSetFocus(int id)
{
	if (CoActiveObject!=NULL)
		CoActiveObject->SetFocus(0,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
	
	int k;
 	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_SETFOCUS);
	if (k>0) return 1; 
	if (k==0) return OBJcallreflex(mm,0);
	return 0;

}

int container::HdlKillFocus(int id)
{
	int k;	
	
	if (CoFocusedObject!=NULL && CoFocusedObject!=CoHandledObject)
			CoFocusedObject->ClickOut(0,0,0,0,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
	if (CoActiveObject!=NULL)
		CoActiveObject->KillFocus(GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
/*
	if (CoActiveObject!=NULL && CoActiveObject!=CoFocusedObject)
			CoActiveObject->ClickOut(0,0,0,0,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
*/
	CoFocusedObject=NULL;
	//CoActiveObject=NULL;
	k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_KILLFOCUS);
	if (k>0) return 1; 
	if (k==0) return OBJcallreflex(mm,0);
	
	return 0;
}


int container::HdlKeyDown(int id,UINT vk,BOOL keysys, int cRepeat, UINT flags)
{
	if (!IsEnabled()) return 0;

	int k,tmp_res;
	int ContainerKeyDownAllowed=1;
	
	if (CoActiveObject!=NULL)
	{
		ContainerKeyDownAllowed=CoActiveObject->TransmitToContainer(OBJ_CONTAINER_KEYDOWN);
		
		// le tooltip
		if (CoActiveObject==CoActiveToolTipObject && CoActiveToolTipObject->ObjToolTip!=NULL)
		{
			CoActiveToolTipObject->ObjToolTip->Disarm();
			CoActiveToolTipObject=NULL;
		}

		// to prevent object destruction in user callback
		if (!testTabStop(vk) && OBJ_VALIDITY(CoActiveObject))
			CoActiveObject->KeyDown(vk,keysys,cRepeat,flags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)));
	}
	else
	{
		// no prevent from destruction cause no user callback before
		if (!testTabStop(vk) && OBJ_VALIDITY(CoFocusedObject) && CoFocusedObject->IsObjectEnabled())
		{
			ContainerKeyDownAllowed=CoFocusedObject->TransmitToContainer(OBJ_CONTAINER_KEYDOWN);
			CoFocusedObject->KeyDown(vk,keysys,cRepeat,flags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)));
		}
	}
			
	if (ContainerKeyDownAllowed)
	{
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_KEYDOWN);
		if (k>0) return 1; 
		if (k==0)
		{
			CHECK(MMpush(mm,ITOM(flags)));
			CHECK(MMpush(mm,ITOM(vk)));
			return OBJcallreflex(mm,2);
		}			
	}
	
	return 0;	
}

int container::HdlKeyUp(int id,UINT vk, int cRepeat, UINT flags)
{
	if (!IsEnabled()) return 0;

	int k,tmp_res;
	int ContainerKeyUpAllowed=1;
	if (CoActiveObject!=NULL)
	{
		ContainerKeyUpAllowed=CoActiveObject->TransmitToContainer(OBJ_CONTAINER_KEYUP);
		CoActiveObject->KeyUp(vk,cRepeat,flags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)));
	}
	
	else
	{
		if (CoFocusedObject!=NULL && CoFocusedObject->IsObjectEnabled())
		{
			ContainerKeyUpAllowed=CoFocusedObject->TransmitToContainer(OBJ_CONTAINER_KEYUP);
			CoFocusedObject->KeyUp(vk,cRepeat,flags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)));
			
		}
	}
	
	if (ContainerKeyUpAllowed)
	{
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_KEYUP);
		if (k>0) return 1; 
		if (k==0)
		{
			CHECK(MMpush(mm,ITOM(flags)));
			return OBJcallreflex(mm,1);
		}		
	}		
	return 0;
}

int	container::HdlClick(int id,int typebouton, int x, int y, UINT keyFlags)
{
	if (!IsEnabled()) return 0;
	
	if (CoWin!=NULL) CoWin->SetFocus();

	int k,tmp_res,mask;

	CoCursorPosX=x;
	CoCursorPosY=y;

	CoCurrentKeyFlags=keyFlags;

	int UserClickAllowed=1;
	int p_root=FindObjNodeFromHdlSys(mm,(int)CoRoot);
	int p_objectundermouse=Search_ObjNode_Under_Mouse(mm,p_root,x,y);
	CObjectBase * objectundermouse=(p_objectundermouse==NIL?NULL:GetObjectBase(mm,p_objectundermouse));
	 
	
	
	/* Look if object under mouse is the focused object */
	if (objectundermouse!=CoFocusedObject || objectundermouse!=CoActiveObject)
	{
		/* mouse is out of focused object */
		if (CoFocusedObject!=NULL && !CoFocusedObject->isLinkedTo(objectundermouse))
			CoFocusedObject->ClickOut(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
		
		// to prevent object destruction in user callback
		if (OBJ_VALIDITY(CoActiveObject) && !CoActiveObject->isLinkedTo(objectundermouse) && CoFocusedObject!=CoActiveObject)
			CoActiveObject->ClickOut(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);
		
		if (OBJ_VALIDITY(objectundermouse))
			CoInPushedAlreadySent=1;
	}
	
	if (objectundermouse!=NULL && !OBJ_VALIDITY(CoHandledObject))
	{
		CoNewHandledObject=CoHandledObject=objectundermouse;
		CoHandledObject->CursorMoveIn(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoHandledObject)),1);
		OBJ_VALIDITY(objectundermouse);
	}

	if (objectundermouse!=NULL) /*objectundermouse valid */ 
	{
		UserClickAllowed = objectundermouse->TransmitToContainer(OBJ_CONTAINER_CLICK);
		
		if (objectundermouse->CanBeActiveObject() && objectundermouse->IsObjectEnabled())
			CoActiveObject=objectundermouse;
		else
		{
			if (!objectundermouse->isLinkedTo(CoActiveObject))
				CoActiveObject=NULL;
		}

		// tooltip
		if ( objectundermouse->ObjToolTip != NULL )
		{
			objectundermouse->ObjToolTip->Disarm();
			CoActiveToolTipObject=NULL;
		}

		// to prevent object destruction in user callback
		if (OBJ_VALIDITY(objectundermouse) && objectundermouse->IsObjectEnabled() )
		{
			/* sets the new focused object */
			CoFocusedObject = objectundermouse;	
			// to prevent object destruction in user callback
			CoFocusedObject->ClickIn(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
		}
	}

	if (UserClickAllowed)
	{
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_CLICK);
		if (k>0) return 1L; 
		if (k==0)
		{
			mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
			CHECK(MMpush(mm,ITOM(x)));
			CHECK(MMpush(mm,ITOM(y)));
			CHECK(MMpush(mm,ITOM(typebouton)));
			CHECK(MMpush(mm,ITOM(mask)));
			return OBJcallreflex(mm,4);
		}			
	}

	return 0L;
}

int	container::HdlUnClick(int id,int typebouton, int x, int y, UINT keyFlags)
{
	if (!IsEnabled()) return 0;

	int k,tmp_res,mask;
	
	CoCursorPosX=x;
	CoCursorPosY=y;

	CoCurrentKeyFlags=keyFlags;	
		
	int UserUnClickAllowed=1;
	int p_root=FindObjNodeFromHdlSys(mm,(int)CoRoot);
	int p_objectundermouse=Search_ObjNode_Under_Mouse(mm,p_root,x,y);
	CObjectBase * objectundermouse=(p_objectundermouse==NIL?NULL:GetObjectBase(mm,p_objectundermouse));
	
	if (objectundermouse!=NULL)
		UserUnClickAllowed = objectundermouse->TransmitToContainer(OBJ_CONTAINER_UNCLICK);

	if (CoFocusedObject!=objectundermouse)
	{
		/* Look if the new mouse position should be handled */
		CoHandledObject=objectundermouse;
		
		/* lost focus of the focused object */
		if ((CoFocusedObject!=NULL)&&(CoFocusedObject->IsObjectEnabled()))
			CoFocusedObject->UnClickOut(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
		
		/* handle of new mouse position and prevent object from destruction during preceding reflex*/
		if (OBJ_VALIDITY(CoHandledObject)&&(CoHandledObject->IsObjectEnabled()))
			CoHandledObject->CursorMoveIn(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoHandledObject)),1);

		CoOutPushedAlreadySent=0;
		CoInPushedAlreadySent=0;
	}
	else
	{
		if ((CoFocusedObject!=NULL)&&(CoFocusedObject->IsObjectEnabled()))
			CoFocusedObject->UnClickIn(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
	}

	if (UserUnClickAllowed)
	{	// execution du reflexe container
  		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_UNCLICK);
		if (k>0) return 1L; 
		if (k==0)
		{
			mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
			CHECK(MMpush(mm,ITOM(x)));
			CHECK(MMpush(mm,ITOM(y)));
			CHECK(MMpush(mm,ITOM(typebouton)));
			CHECK(MMpush(mm,ITOM(mask)));
			return OBJcallreflex(mm,4);
		}
	}

	return 0L;
}

int	container::HdlDblClick(int id,int typebouton, int x, int y, UINT keyFlags)
{
	if (!IsEnabled()) return 0;

	if (CoWin!=NULL) CoWin->SetFocus();

	int k,tmp_res,mask;
	
	CoCursorPosX=x;
	CoCursorPosY=y;

	CoCurrentKeyFlags=keyFlags;
		
	int UserDblClickAllowed=1;
	int p_root=FindObjNodeFromHdlSys(mm,(int)CoRoot);
	int p_objectundermouse=Search_ObjNode_Under_Mouse(mm,p_root,x,y);
	CObjectBase * objectundermouse=(p_objectundermouse==NIL?NULL:GetObjectBase(mm,p_objectundermouse));

	if (objectundermouse!=NULL)
		UserDblClickAllowed=objectundermouse->TransmitToContainer(OBJ_CONTAINER_DBLCLICK);
	
	/* Look if object under the mouse is the focused object */
	if (objectundermouse!=CoFocusedObject)
	{
		if (CoFocusedObject!=NULL && !CoFocusedObject->isLinkedTo(objectundermouse))
			CoFocusedObject->ClickOut(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);

		/* prevent object from destruction during preceding reflex */
		if (OBJ_VALIDITY(CoActiveObject) && !CoActiveObject->isLinkedTo(objectundermouse) && CoFocusedObject!=CoActiveObject)
			CoActiveObject->ClickOut(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoActiveObject)),1);

		/* prevent object from destruction during preceding reflex */
		if (OBJ_VALIDITY(objectundermouse))
			CoInPushedAlreadySent=1;
	}
	
	if (objectundermouse!=NULL)
	{
		if (objectundermouse->CanBeActiveObject() && objectundermouse->IsObjectEnabled())
			CoActiveObject=objectundermouse;
		else
		{
			if (!objectundermouse->isLinkedTo(CoActiveObject))
			CoActiveObject=NULL;
		}
		// tooltip
		if (objectundermouse->ObjToolTip!=NULL)
		{
			objectundermouse->ObjToolTip->Disarm();
			CoActiveToolTipObject=NULL;
		}
	}

	/* prevent object from destruction during preceding reflex */
	if (OBJ_VALIDITY(objectundermouse)&&(objectundermouse->IsObjectEnabled()))
	{
		CoFocusedObject=objectundermouse;
		CoFocusedObject->DblClickIn(x,y,typebouton,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
	}

	if (UserDblClickAllowed)
	{
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_DBLCLICK);
		if (k>0) return 1L; 
		if (k==0)
		{
			mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
			CHECK(MMpush(mm,ITOM(x)));
			CHECK(MMpush(mm,ITOM(y)));
			CHECK(MMpush(mm,ITOM(typebouton)));
			CHECK(MMpush(mm,ITOM(mask)));
			return OBJcallreflex(mm,4);
		}	
	}

	return 0L;
}

int	container::HdlMouseWheel(int id,int delta, int x, int y, UINT keyFlags)
{		
	if (!IsEnabled()) return 0;

	CoCursorPosX=x;
	CoCursorPosY=y;

	int ContainerMouseWheelAllowed=1;
	int p_root=FindObjNodeFromHdlSys(mm,(int)CoRoot);
	int p_newhandled=Search_ObjNode_Under_Mouse(mm,p_root,x,y);
	CObjectBase * obj_newhandled=(p_newhandled==NIL?NULL:GetObjectBase(mm,p_newhandled));
	
	if (obj_newhandled!=NULL && obj_newhandled->IsObjectEnabled())
	{
		ContainerMouseWheelAllowed=obj_newhandled->TransmitToContainer(OBJ_CONTAINER_MOUSEWHEEL);
		obj_newhandled->MouseWheel(delta,x,y,keyFlags,GetTab(mm,p_newhandled),1);
	}

			
	if (ContainerMouseWheelAllowed)
	{
		int k,tmp_res,mask;
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_MOUSEWHEEL);
		if (k>0) return 1L; 
		if (k==0)
		{
			mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
			CHECK(MMpush(mm,ITOM(x)));
			CHECK(MMpush(mm,ITOM(y)));
			CHECK(MMpush(mm,ITOM(delta)));
			CHECK(MMpush(mm,ITOM(mask)));
			return OBJcallreflex(mm,4);
		}						
	}
	
	return 0L;
}

int	container::HdlMouseHover(int id)
{
	int k;	
	if (IsEnabled())
	{
		StartTME(TME_OUT); 
	
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_MOUSEHOVER);
		if (k>0) return 1L; 
		if (k==0) return OBJcallreflex(mm,0);
	}
	return 0L;
}

int	container::HdlMouseLeave(int id)
{
	if (!IsEnabled()) return 0;

	// on desactive l'objet courant
	if (CoHandledObject!=NULL)
	{
		Point2D p=GetCursorPosClient();

		// tooltip
		if (CoHandledObject->ObjToolTip!=NULL)
		{
			CoHandledObject->ObjToolTip->Disarm();
			CoActiveToolTipObject=NULL;
		}

		// to prevent object destruction in user callback
		if (OBJ_VALIDITY(CoHandledObject))
			CoHandledObject->CursorMoveOut(p.iptX,p.iptY,0,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoHandledObject)),1);
		
		CoHandledObject=NULL;
	}
	
	StartTME(TME_IN);

	int k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_MOUSELEAVE);
	if (k>0) return 1L; 
	if (k==0) return OBJcallreflex(mm,0);
	return 0L;

}

int	container::HdlMouseMove(int id,int x, int y, UINT keyFlags)
{
	if (!IsEnabled()) return 0;
	if ( x == CoCursorPosX && y == CoCursorPosY ) return 0L;
	
	int mask,tmp_res,k;
	
	CoCursorPosX=x;
	CoCursorPosY=y;
	
	int UserMouseMoveAllowed=1;
	int p_root=FindObjNodeFromHdlSys(mm,(int)CoRoot);
	int p_newhandled=Search_ObjNode_Under_Mouse(mm,p_root,x,y);
	CoNewHandledObject=(p_newhandled==NIL?NULL:GetObjectBase(mm,p_newhandled));
	
	/* Cursor going out of the handled object ? */
	int OutOfHandledObject=((CoHandledObject!=NULL)&&(CoHandledObject != CoNewHandledObject));
	/* Cursor going into a new object ? */
	int IntoMouseObject=((CoNewHandledObject != NULL) && (CoNewHandledObject != CoHandledObject));
	/* test du bouton presse */
	int BtnNotPushed=(keyFlags&(MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))==0;

	if ((!IntoMouseObject) && 
		(!OutOfHandledObject) && 
		((CoHandledObject!=NULL))
	   )
	{
		// le tooltip
		if (CoHandledObject->ObjToolTip!=NULL && BtnNotPushed)
			CoHandledObject->ObjToolTip->Reset(x,y);
		
		// to prevent object destruction in user callback
		if (OBJ_VALIDITY(CoHandledObject) && CoHandledObject->IsObjectEnabled())
			CoHandledObject->CursorMove(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoHandledObject)),1);
	}
	// on bouge le curseur avec le bouton appuyé dans l'objet actif
	
	if (OutOfHandledObject)
  	{
		// tooltip
		if (OBJ_VALIDITY(CoHandledObject) && CoHandledObject->ObjToolTip!=NULL)
		{
			CoHandledObject->ObjToolTip->Disarm();
			CoActiveToolTipObject=NULL;
		}
		
		if (BtnNotPushed)
		{
			if (OBJ_VALIDITY(CoHandledObject))// && CoHandledObject->IsObjectEnabled()) //CoHandledObject valid 
				CoHandledObject->CursorMoveOut(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoHandledObject)),1);
		}
		else
		{
			if (OBJ_VALIDITY(CoFocusedObject) && !CoOutPushedAlreadySent)
			{
				CoOutPushedAlreadySent = 1;
  				CoInPushedAlreadySent = 0;
				//if (CoFocusedObject->IsObjectEnabled())
				CoFocusedObject->CursorMoveOutWithBtnPushed(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
			}
		}
		CoHandledObject=NULL;
	}

	if (IntoMouseObject)
  	{
		if (BtnNotPushed)
		{
			// tooltip
			// to prevent object destruction in user callback
			if (OBJ_VALIDITY(CoNewHandledObject) && CoNewHandledObject->ObjToolTip!=NULL)
			{
				CoNewHandledObject->ObjToolTip->Arm(x,y);
				CoActiveToolTipObject=CoNewHandledObject;	
			}

			// to prevent object destruction in user callback
			if (OBJ_VALIDITY(CoNewHandledObject))// && CoNewHandledObject->IsObjectEnabled())
				CoNewHandledObject->CursorMoveIn(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoNewHandledObject)),1);
		}
		else
  		{
			if (OBJ_VALIDITY(CoFocusedObject)&&(CoFocusedObject==CoNewHandledObject))
			{
  				CoOutPushedAlreadySent = 0;
  				CoInPushedAlreadySent = 1;
				//if (CoFocusedObject->IsObjectEnabled())
				CoFocusedObject->CursorMoveInWithBtnPushed(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);
			}
		}
		CoHandledObject=CoNewHandledObject;
	}
	
	// to prevent object destruction in user callback
	OBJ_VALIDITY(CoNewHandledObject);
	if ((keyFlags&MK_LBUTTON) !=0 && OBJ_VALIDITY(CoFocusedObject) && CoNewHandledObject!=CoFocusedObject)//&& CoFocusedObject->IsObjectEnabled())
		CoFocusedObject->CursorMoveOutsideWithBtnPushed(x,y,keyFlags,GetTab(mm,FindObjNodeFromHdlSys(mm,(int)CoFocusedObject)),1);

	if (OBJ_VALIDITY(CoNewHandledObject))
		UserMouseMoveAllowed = CoNewHandledObject->TransmitToContainer(OBJ_CONTAINER_MOVE);
	
	if (UserMouseMoveAllowed)
	{
		k=OBJbeginreflex(mm,OBJCONTAINER,id,RFLCONTAINER_CURSORMOVE);
		if (k>0) return 1L; 
		if (k==0)
		{
			mask=keyFlags&(MK_CONTROL|MK_LBUTTON|MK_MBUTTON|MK_RBUTTON|MK_SHIFT);
			CHECK(MMpush(mm,ITOM(x)));
			CHECK(MMpush(mm,ITOM(y)));
			CHECK(MMpush(mm,ITOM(mask)));
			return OBJcallreflex(mm,3);
		}
	}
	
	return 0L;
}

int	container::ExecuteReflexRender(mmachine m,int rflrender,Rect2D r)
{
	int k=OBJbeginreflex(mm,OBJCONTAINER,(int)this,rflrender);
	if (k>0) return 1L; 
	if (k==0)
	{
			int tmp_res;
			CHECK(MMpush(mm,ITOM(r.RctHG.iptX)));
			CHECK(MMpush(mm,ITOM(r.RctHG.iptY)));
			CHECK(MMpush(mm,ITOM(r.RctBD.iptX)));
			CHECK(MMpush(mm,ITOM(r.RctBD.iptY)));
			CHECK(MMpush(mm,ITOM(4)));
			CHECK(MBdeftab(mm));
			return OBJcallreflex(mm,1);
	}
	return -1;
}



void container::Redraw(int RepaintFlag)
{
	if ( RepaintFlag )
	{
		// execution du reflexe prerender
		//if (!ExecuteReflexRender(mm,RFLCONTAINER_PRERENDER,Rect2D(0,0,CoXsize,CoYsize)))
		//	return;

		
		if (ExecuteReflexRender(mm,RFLCONTAINER_PRERENDER,Rect2D(0,0,CoXsize,CoYsize)))
			// on clear le buffer s'il n'y a pas de prerender
			CoBuffer->Clear( 0, 0, CoXsize, CoYsize, CoBackgroundColor );
		
		
		/* prevent from destruction of container in user callback */
		if (RetrieveContainerFromHdlSys((int)this)==NULL) return ;

		int FirstObjNode=GetSon(mm,FindObjNodeFromHdlSys(mm,(int)CoRoot));
		PaintObjNodes(mm,CoBuffer,FirstObjNode);
		PaintToolTip(CoActiveToolTipObject,CoBuffer);

		// execution du reflexe postrender
		ExecuteReflexRender(mm,RFLCONTAINER_POSTRENDER,Rect2D(0,0,CoXsize,CoYsize));
		
		/* prevent from destruction of container in user callback */
		if (RetrieveContainerFromHdlSys((int)this)==NULL) return ;

		if (CoWin!=NULL)
				CoWin->BlitBuffer((CObjBufferWindows*)CoBuffer, CoBuffer->GetId(),TypeBlit,0,0,CoXsize,CoYsize,0,0);
	}
}

void container::RedrawArea(Rect2D area2redraw,int RepaintFlag)
{
	if ( RepaintFlag )
	{
		// execution du reflexe prerender
		//if (!ExecuteReflexRender(mm,RFLCONTAINER_PRERENDER,area2redraw))
		//	return;

		if (ExecuteReflexRender(mm,RFLCONTAINER_PRERENDER,area2redraw))
			// on clear le buffer s'il n'y a pas de prerender
			CoBuffer->Clear( area2redraw.RctHG.iptX, area2redraw.RctHG.iptY, area2redraw.RctBD.iptX, area2redraw.RctBD.iptY, CoBackgroundColor );
		
		/* prevent from destruction of container in user callback */
		if (RetrieveContainerFromHdlSys((int)this)==NULL) return ;

		int FirstObjNode=GetSon(mm,FindObjNodeFromHdlSys(mm,(int)CoRoot));
		PaintPartObjNodes(mm,CoBuffer,FirstObjNode,area2redraw);
		PaintToolTip(CoActiveToolTipObject,CoBuffer);
		
		// execution du reflexe postrender
		ExecuteReflexRender(mm,RFLCONTAINER_POSTRENDER,area2redraw);
		
		/* prevent from destruction in user callback */
		if (RetrieveContainerFromHdlSys((int)this)==NULL) return ;
		
		if (CoWin!=NULL)
				CoWin->BlitBuffer((CObjBufferWindows*)CoBuffer, CoBuffer->GetId(),
								  TypeBlit,
								  area2redraw.RctHG.iptX, 
								  area2redraw.RctHG.iptY, 
								  area2redraw.RctBD.iptX, 
								  area2redraw.RctBD.iptY, 
								  area2redraw.RctHG.iptX, 
								  area2redraw.RctHG.iptY
								 );
	}
}

int  TrackMouseEventTimerCallback(int idEvent,int param)
{
	bool in_or_out=false;
    container * cont=(container *)param;
	Window * win=cont->GetPtrWindow();
	if (win!=NULL)
	{
		Point2D pt =win->GetCursorPosScreen();
		Rect2D rect=win->GetClientInScreen();
		if ((cont->CoTMEflags&TME_OUT)&&(cont->CoTMEcursorInContainer))
		{
			if (!IsPointInRectangle(pt,rect) || !win->IsPointInWindow(pt)) 
			{
				in_or_out=true;
                mt_del(idEvent);
				cont->CoTMEcursorInContainer=FALSE;
				cont->HdlMouseLeave((int)cont);
			}
		}
		if ((cont->CoTMEflags&TME_IN)&&(!cont->CoTMEcursorInContainer))
		{
			if (IsPointInRectangle(pt,rect) && win->IsPointInWindow(pt))
			{
				in_or_out=true;
                mt_del(idEvent);
				cont->CoTMEcursorInContainer=TRUE;
				cont->HdlMouseHover((int)cont);
			}
		}

        if (!in_or_out && !cont->CoTMEcursorInContainer && cont->CoHandledObject!=NULL )
        {   // cas ou le curseur est tjs dehors mais est rentré
            // subrepticement dans le container et le timer ne
            // s'en est pas rendu compte donc il faut quand meme
            // desactiver les objets en cours de selection
            mt_del(idEvent);
			cont->CoTMEcursorInContainer=FALSE;
			cont->HdlMouseLeave((int)cont);
        }
	}
	return 0;
}

int container::StartTME(int Flags)
{
	if (CoWin!=NULL)
	{
		CoTMEflags=Flags;
		return (CoTMEtimer=mt_start(TME_RANGE,(int)this,TrackMouseEventTimerCallback));
	}
	return 0;
}

int container::Register( int delay, CObjectBase *object )
{
	if ( this->CoTimerService != NULL )
		return( this->CoTimerService->Register( delay, object ) );
	else
		return -1;
}

int container::Unregister( int id )
{
	if ( this->CoTimerService != NULL )
		return( this->CoTimerService->Unregister( id ) );
	else
		return -1;
}

Point2D	container::GetCursorPosClient()
{
	if (CoWin!=NULL)
		return CoWin->GetCursorPosClient();
	else
		return Point2D(CoCursorPosX,CoCursorPosY);
}

Point2D	container::GetCursorPosScreen()
{
	if (CoWin!=NULL)
		return CoWin->GetCursorPosScreen();
	else
		return Point2D(CoCursorPosX,CoCursorPosY);
}

// Enable or Disable container
int	container::Enable(int etat)
{
	int tmp_res;
	CoEnabled=etat;
	if (CoWin!=NULL)
		CHECK(CoWin->Enable(etat));	
	return 0;
}

int	container::GetSize(int *x,int *y,int *w,int *h,int ext)
{
	int tmp_res;
	if (CoWin!=NULL)
	{
		CHECK(CoWin->GetSize(x,y,w,h,ext));
	}
	else
	{
		// container virtuel
		CHECK(MMpush(mm,ITOM(*x=0)));
		CHECK(MMpush(mm,ITOM(*y=0)));
		CHECK(MMpush(mm,ITOM(*w=CoXsize)));
		CHECK(MMpush(mm,ITOM(*h=CoYsize)));
		CHECK(MMpush(mm,ITOM(4)));
		CHECK(MMpush(mm,MBdeftab(mm)));
	}
	return 0;
}

int	container::OwnsObject(CObjectBase *obj)
{
	return (obj==NULL || (obj!=NULL && obj->Container()==this));
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                      FONCTIONS SCOL DU CONTAINER FENETRE										   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int CreateWindowContainer( mmachine m, char *fun)
{
	int p_name,tmp_res;
	int x,y,w,h,bckcolor,flags;
	char name[400];
  
  //retrieve the parent (position 7 in stack)
  int parent = MTOP(MMget(m,7));

	if (MMget(m,8)==NIL)
	{
		MMechostr(MSKTRACE,"%s: channel is nil\n",fun);
		m->pp += 8;
		MMset(m,0,NIL);
		return 0;
	}
	else if (MTOI(MMget(m,3))<=0)
	{
		MMechostr(MSKTRACE,"%s: Creation failed : h<=0 or nil\n",fun);
		m->pp += 8;
		MMset(m,0,NIL);
		return 0;
	}
	else if (MTOI(MMget(m,4))<=0)
	{
		MMechostr(MSKTRACE,"%s: Creation failed : w<=0 or nil\n",fun);
		m->pp += 8;
		MMset(m,0,NIL);
		return 0;
	}

  //$BLG - v4.6a4
  //Moved and modified below
	//if ((p_name=MTOP(MMget(m,0)))==NIL)
	//	strcpy (name , "(SCOL)" );
	//else
	//	sprintf (name , "(SCOL)%s" , MMstartstr(m, p_name) );
	
	if ((bckcolor = MTOI(MMget(m,1))) == NIL) bckcolor = 0; // noir par defaut
	//$BLG
	//MMechostr(0,"$BLG: CreateWindowContainer - BG - %i\n", bckcolor);
	
	flags=MTOI(MMget(m,2));

  //$BLG - v4.6a4
	if ((p_name = MTOP(MMget(m, 0))) == NIL)
	  if (flags & CO_NOSCOL)
	    strcpy(name, "" );
	  else
		  strcpy (name , "(SCOL)" );
	else
	  if (flags & CO_NOSCOL)
		  sprintf (name , "%s" , MMstartstr(m, p_name) );	
    else
		  sprintf (name , "(SCOL)%s" , MMstartstr(m, p_name) );	

	h=MTOI(MMget(m,3));
	w=MTOI(MMget(m,4));
	if ((y=MTOI(MMget(m,5)))==NIL) y=CW_USEDEFAULT;
	if ((x=MTOI(MMget(m,6)))==NIL) x=CW_USEDEFAULT;

	// on depile le background
	INVERT(m,0,1);
	MMpull(m);
	
	// etat pile channel parent x y w h flags name
	// creation du pointeur du container
	Window *win = NULL;
#ifdef SCOL
	// SCOL is defined as preprocessor
	win=new WindowScolWin(m,parent,x,y,w,h,flags,name);
#else
#endif
	container *cont=new container(win,w,h, bckcolor);
	CHECK(cont->ConstructScolContainer(m));
	//$BLG - v4.6a5: Add (Apply parameters, like background color, just after creation)
	//cont->Redraw(1);
	return 0;
}


int _CRcontainerFromObjCont(mmachine m)
{
	int	p_parent;
	// recuperation de la fenetre parente
	if ((p_parent = MTOP(MMget(m, 7))) != NIL)
	{
		container * co;
		if ((co = RetrievePtrContainer(m, p_parent)) == NULL)
		{
			MMechostr(MSKTRACE,"_CRcontainerFromObjCont: parent container already destroyed\n"); 
			m->pp+=7;
			MMset(m,0,NIL);
			return 0;
		}
		else
    // retrieve the window
			MMset(m, 7, MMfetch(m, p_parent, 3));
	}
	return CreateWindowContainer(m,"_CRcontainerFromObjCont");
}


int _CRcontainerFromObjWin(mmachine m)
{
	return CreateWindowContainer(m,"_CRcontainerFromObjWin");
}

int _SHOWcontainer(mmachine m)
{
	int etat,p;
	container * cont;
	etat=MTOI(MMpull(m));
	if ((p=MMget(m,0))==NIL)
		return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p)))==NULL)
	{
		MMechostr(MSKTRACE,"_SHOWcontainer: container already destroyed\n");
		return 0;
	}
	else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_SHOWcontainer: this method cannot be applied to a virtual  container\n");
		return 0;
	}
 	return cont->GetPtrWindow()->Show(etat);
}

int _MOVEcontainer(mmachine m)
{
	int x,y,p;
	container * cont;

	// on ne depile aucun parametre , ils seront depilés dans
	// la fonctions du container
	y=MTOI(MMget(m,0));
	x=MTOI(MMget(m,1));
	if ((p=MMget(m,2))==NIL) 
		return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p)))==NULL)
	{
		MMechostr(MSKTRACE,"_MOVEcontainer: container already destroyed\n");
		m->pp+=2;
		return 0;
	}
    else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_MOVEcontainer: this method cannot be applied to a virtual container\n");
		m->pp+=2;
		return 0;
	}
	return cont->GetPtrWindow()->Move(x,y);
}

int _SETcontainerName(mmachine m)
{
	int p_cont,p_name;
	container * cont;

	p_name=MTOP(MMpull(m));
	if ((p_cont=MMget(m,0))==NIL) return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_SETcontainerName: container already destroyed\n");
		return 0;
	}
	else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_SETcontainerName: this method cannot be applied to a virtual container\n");
		return 0;
	}
	return cont->GetPtrWindow()->SetName(MMstartstr(m, p_name));
}

int _SIZEcontainer(mmachine m)
{
	int w , h , x , y , p_cont;
	container *cont;
	
	// on ne depile aucun parametre , ils seront depilés dans
	// la fonctions du container
	
	h = MTOI(MMget(m,0));
    w = MTOI(MMget(m,1));
    y = MTOI(MMget(m,2));
    x = MTOI(MMget(m,3));
	if ((p_cont=MMget(m,4))==NIL)
	{
		m->pp+=4;
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_SIZEcontainer: container already destroyed\n");
		m->pp+=4;
		return 0;
	}
	else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_SIZEcontainer: this method cannot be applied to a virtual container\n");
		m->pp+=4;
		return 0;
	}
	cont->GetPtrWindow()->Size(x,y,w,h,0);
	return 0;
}

int _SIZEEXcontainer(mmachine m)
{
	int w , h , x , y , p_cont;
	container *cont;
	
	// on ne depile aucun parametre , ils seront depilés dans
	// la fonctions du container

	h = MTOI(MMget(m,0));
    w = MTOI(MMget(m,1));
    y = MTOI(MMget(m,2));
    x = MTOI(MMget(m,3));
	if ((p_cont=MMget(m,4))==NIL) 
	{
		m->pp+=4;
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_SIZEEXcontainer: container already destroyed\n");
		m->pp+=4;
		return 0;
	}
	else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_SIZEEXcontainer: this method cannot be applied to a virtual container\n");
		m->pp+=4;
		return 0;
	}
	cont->GetPtrWindow()->Size(x,y,w,h,1);
	return 0;
}

int _TOPcontainer(mmachine m)
{
	int p_cont;
	container * cont;

	if ((p_cont=MMget(m,0))== NIL ) return 0;
	
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_TOPcontainer: container already destroyed\n");
		return 0;
	}
    else if (cont->GetPtrWindow()==NULL)
	{
		//$BLG: v4.6a7 - Modif
		//MMechostr(MSKTRACE,"_SIZEEXcontainer: this method cannot be applied to a virtual container\n");
		MMechostr(MSKTRACE,"_TOPcontainer: this method cannot be applied to a virtual container\n");
		return 0;
	}
	return cont->GetPtrWindow()->Top();
}

//$BLG: 4.6a7 - Add
//Source code from _TOPcontainer
int _TOPMOSTcontainer(mmachine m)
{
	int p_cont;
	container * cont;
	
	int fcs; 		// Focus
	int lvl;		// Display level

	fcs = MMpull(m)>>1;
	lvl = MMpull(m)>>1;	
	p_cont = MMget(m,0);

	if ((p_cont == NIL) || (lvl < 0) || (lvl > 3) || (fcs < 0) || (fcs > 1))
		return 0;

	if ((cont = RetrievePtrContainer(m, MTOP(p_cont))) == NULL)
	{
		MMechostr(MSKTRACE, "_TOPMOSTcontainer: container already destroyed\n");
		return 0;
	}
  else if (cont->GetPtrWindow() == NULL)
	{
		MMechostr(MSKTRACE, "_TOPMOSTcontainer: this method cannot be applied to a virtual container\n");
		return 0;
	}

	return cont->GetPtrWindow()->TopMost(lvl, fcs);
}


//$BLG - v5.11: Add
int _SETcontainerBackgroundColor(mmachine m)
{
	int p_cont;
	container *cont;
	int bckcolor;
	int repaint;
	
	repaint = MMpull(m)>>1;
	bckcolor = MMpull(m);
	p_cont = MMget(m, 0);
	
	if ((p_cont == NIL) || (bckcolor == NIL))
		return 0;
	
	bckcolor >>= 1;
	if ((bckcolor < 0x000000) || (bckcolor > 0xffffff))
		return 0;
	
	if ((cont = RetrievePtrContainer(m, MTOP(p_cont))) == NULL)
	{
		MMechostr(MSKTRACE, "_SETcontainerBackgroundColor: container already destroyed\n");
		return 0;
	}
	
	cont->SetBackgroundColor(bckcolor);
	
	if (repaint == 1) cont->Redraw(1);
	
	return 0;
}


int _ENcontainer(mmachine m)
{
	int p_cont,etat;
	container * cont;

	etat=MTOP(MMpull(m));
	if ((p_cont=MMget(m,0))==NIL) return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_ENcontainer: container already destroyed\n");
		return 0;
	}
	return cont->Enable(etat);
}

int _GETcontainerPositionSize(mmachine m)
{
	int p_cont;
	int x,y,w,h;
	container * cont;

	if ((p_cont=MMpull(m))==NIL) return MMpush(m,NIL);
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcontainerPositionSize: container already destroyed\n");
		return MMpush(m,NIL);
	}
	return cont->GetSize(&x,&y,&w,&h,0);
}

int _GETcontainerExPositionSize(mmachine m)
{
	int p_cont;
	int x,y,w,h;
	container * cont;

	if ((p_cont=MMpull(m))==NIL) return MMpush(m,NIL);
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcontainerExPositionSize: container already destroyed\n");
		return MMpush(m,NIL);
	}
	return cont->GetSize(&x,&y,&w,&h,1); 
}

int _SETfocusContainer(mmachine m)
{
	int p_cont;
	container *cont;

	if ((p_cont=MMget(m,0))==NIL) return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_SETfocusContainer: container already destroyed\n");
		return 0;
	}
	else if (cont->GetPtrWindow()==NULL)
	{
		MMechostr(MSKTRACE,"_SETfocusContainer: this method cannot be applied to a virtual container\n");
		return 0;
	}

	return cont->GetPtrWindow()->SetFocus();
}


//
// fonctions reflexes par defaut de la fenetre associée au container
//
#define CALLMETHOD(m,s) {																				\
	_METHODcontainer##s(m);																				\
	MMpull(m);																							\
	return 0;}

int RFLwincontainerClick(mmachine m)		CALLMETHOD(m,Click)

int RFLwincontainerUnClick(mmachine m)		CALLMETHOD(m,UnClick)

int RFLwincontainerDblClick(mmachine m)		CALLMETHOD(m,DblClick)

int RFLwincontainerKeyDown(mmachine m)		CALLMETHOD(m,KeyDown)

int RFLwincontainerKeyUp(mmachine m)		CALLMETHOD(m,KeyUp)

int RFLwincontainerFocus(mmachine m)		CALLMETHOD(m,Focus)

int RFLwincontainerKillFocus(mmachine m)	CALLMETHOD(m,KillFocus)

int RFLwincontainerMove(mmachine m)			CALLMETHOD(m,Move)

int RFLwincontainerSize(mmachine m)			CALLMETHOD(m,Size)

int RFLwincontainerClose(mmachine m)		CALLMETHOD(m,PreDestroy)

int RFLwincontainerDestroy(mmachine m)		CALLMETHOD(m,Destroy)

int RFLwincontainerCursorMove(mmachine m)	CALLMETHOD(m,MouseMove)

int RFLwincontainerMouseWheel(mmachine m)	CALLMETHOD(m,MouseWheel)

int RFLwincontainerPaint(mmachine m)		CALLMETHOD(m,Paint)


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                      FONCTIONS SCOL DU CONTAINER	VIRTUEL 									   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int _CRcontainer(mmachine m)
{
	int bckcolor,w,h;

	if ((bckcolor=MTOI(MMpull(m)))==NIL) bckcolor=0;
	h=MTOI(MMpull(m));
    w=MTOI(MMpull(m));
    if (h==NIL || h<=0)
    {
        MMechostr(MSKTRACE,"_CRcontainer: Creation failed : h<=0 or nil\n");
		MMset(m,0,NIL);
        return 0;
    }

    if (w==NIL || w<=0)
    {
        MMechostr(MSKTRACE,"_CRcontainer: Creation failed : w<=0 or nil\n");
		MMset(m,0,NIL);    
        return 0;
    }

	
	container *cont=new container(NULL,w,h,bckcolor);
	return cont->ConstructScolContainer(m);
}

int _DScontainer(mmachine m)
{
	int p,tmp_res;
	container *co;

	if ((p=MTOP(MMpull(m)))==NIL) return MMpush(m,NIL);
	if ((co=RetrievePtrContainer(m,p))!=NULL)
	{
		OBJdelTH(m,OBJCONTAINER,(int)co);
		CHECK(MMpush(m,ITOM(0)));
	}
	else
	{
		MMechostr(MSKTRACE,"_DScontainer: container already destroyed\n");
		CHECK(MMpush(m,ITOM(1)));
	}
	return 0;
}

//AAAAAAAAAAAAAAAAAAAAAARRRRRRRRRFFFFFFFFFFFF!!! ca c'est de la macro
#define SPL_METHOD(s) {																					\
	int p_cont;																							\
	container * cont;																					\
	if ((p_cont=MMget(m,0))==NIL) return 0;																\
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))!=NULL)												\
		cont->Hdl##s((int)cont);																		\
	return 0;}
	 


int _METHODcontainerPreDestroy(mmachine m)	SPL_METHOD(PreDestroy)

int _METHODcontainerDestroy(mmachine m)		SPL_METHOD(Destroy)

int _METHODcontainerFocus(mmachine m)		SPL_METHOD(SetFocus)

int _METHODcontainerKillFocus(mmachine m)	SPL_METHOD(KillFocus)

int _METHODcontainerMouseHover(mmachine m)	SPL_METHOD(MouseHover)

int _METHODcontainerMouseLeave(mmachine m)	SPL_METHOD(MouseLeave)

int _METHODcontainerPaint(mmachine m)		SPL_METHOD(Paint)

int _METHODcontainerSize(mmachine m)
{
	int p_cont,w,h;
	container * cont;
	if ((p_cont=MMget(m,2))==NIL)
	{
		m->pp += 2;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 2;
		MMset(m,0,p_cont);
		return 0;
	}
	h=MTOI(MMpull(m));
	w=MTOI(MMpull(m));
	
	//on recupere le window state
	int state=cont->GetPtrWindow()!=NULL?cont->GetPtrWindow()->GetWindowState():CONTAINER_HIDDEN;
	if (cont->GetPtrWindow()!=NULL)
		cont->GetPtrWindow()->UpdateSate(state);	
	
	return cont->HdlSize((int)cont,state,w,h);
}

int _METHODcontainerMove(mmachine m)
{
	int p_cont,x,y;
	container * cont;
	if ((p_cont=MMget(m,2))==NIL)
	{
		m->pp += 2;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 2;
		MMset(m,0,p_cont);
		return 0;
	}
	
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));
	
	cont->HdlMove((int)cont,x,y);
	return 0;
}

int _METHODcontainerKeyDown(mmachine m)
{
	int p_cont,key,vcode;
	container * cont;
	if ((p_cont=MMget(m,2))==NIL)
	{
		m->pp += 2;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 2;
		MMset(m,0,p_cont);
		return 0;
	}
	
	key=MTOI(MMpull(m));
	vcode=MTOI(MMpull(m));
	
	cont->HdlKeyDown((int)cont,key,false,false,vcode);
	return 0;
}

int _METHODcontainerKeyUp(mmachine m)
{
	int p_cont,key;
	container * cont;
	if ((p_cont=MMget(m,1))==NIL)
	{
		m->pp += 1;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 1;
		MMset(m,0,p_cont);
		return 0;
	}
	
	key=MTOI(MMpull(m));
	
	cont->HdlKeyUp((int)cont,key,false,key);
	return 0;
}

int _METHODcontainerClick(mmachine m)
{
	int p_cont,btn,x,y,flags;
	container * cont;
	
	if ((p_cont=MMget(m,3))==NIL)
	{
		m->pp += 3;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 3;
		MMset(m,0,p_cont);
		return 0;
	}
	
	btn=MTOI(MMpull(m));
	
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));
	
	flags=((int)(GetKeyState(VK_SHIFT)>>8)&1?MK_SHIFT:0)|
		  ((int)(GetKeyState(VK_CONTROL)>>8)&1?MK_CONTROL:0)|
		  ((int)(GetKeyState(VK_LBUTTON)>>8)&1?MK_LBUTTON:0)|
		  ((int)(GetKeyState(VK_RBUTTON)>>8)&1?MK_RBUTTON:0)|
		  ((int)(GetKeyState(VK_MBUTTON)>>8)&1?MK_MBUTTON:0);

	cont->HdlClick((int)cont,btn,x,y,flags);
	return 0;
}

int _METHODcontainerUnClick(mmachine m)
{
	int p_cont,btn,x,y,flags;
	container * cont;
	
	if ((p_cont=MMget(m,3))==NIL)
	{
		m->pp += 3;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 3;
		MMset(m,0,p_cont);
		return 0;
	}

	btn=MTOI(MMpull(m));
		
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));
	
	flags=((int)(GetKeyState(VK_SHIFT)>>8)&1?MK_SHIFT:0)|
		  ((int)(GetKeyState(VK_CONTROL)>>8)&1?MK_CONTROL:0)|
		  ((int)(GetKeyState(VK_LBUTTON)>>8)&1?MK_LBUTTON:0)|
		  ((int)(GetKeyState(VK_RBUTTON)>>8)&1?MK_RBUTTON:0)|
		  ((int)(GetKeyState(VK_MBUTTON)>>8)&1?MK_MBUTTON:0);

	cont->HdlUnClick((int)cont,btn,x,y,flags);
	return 0;
}

int _METHODcontainerDblClick(mmachine m)
{
	int p_cont,btn,x,y,flags;
	container * cont;
	
	if ((p_cont=MMget(m,3))==NIL)
	{
		m->pp += 3;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 3;
		MMset(m,0,p_cont);
		return 0;
	}
	
	btn=MTOI(MMpull(m));
	
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));
	
	flags=((int)(GetKeyState(VK_SHIFT)>>8)&1?MK_SHIFT:0)|
		  ((int)(GetKeyState(VK_CONTROL)>>8)&1?MK_CONTROL:0)|
		  ((int)(GetKeyState(VK_LBUTTON)>>8)&1?MK_LBUTTON:0)|
		  ((int)(GetKeyState(VK_RBUTTON)>>8)&1?MK_RBUTTON:0)|
		  ((int)(GetKeyState(VK_MBUTTON)>>8)&1?MK_MBUTTON:0);

	cont->HdlDblClick((int)cont,btn,x,y,flags);
	return 0;
}

int _METHODcontainerMouseWheel(mmachine m)
{
	int p_cont,delta,x,y,flags;
	container * cont;
	
	if ((p_cont=MMget(m,4))==NIL)
	{
		m->pp += 4;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 4;
		MMset(m,0,p_cont);
		return 0;
	}
	
	flags=MTOI(MMpull(m));
	delta=MTOI(MMpull(m));
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));
	
	cont->HdlMouseWheel((int)cont,delta,x,y,flags);
	return 0;
}

int _METHODcontainerMouseMove(mmachine m)
{
	int p_cont,x,y,flags;
	container * cont;
	
	if ((p_cont=MMget(m,3))==NIL)
	{
		m->pp += 3;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		m->pp += 3;
		MMset(m,0,p_cont);
		return 0;
	}
	
	flags=MTOI(MMpull(m));
	y=MTOI(MMpull(m));
	x=MTOI(MMpull(m));

	cont->HdlMouseMove((int)cont,x,y,flags);
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                      FONCTIONS SCOL COMMUNES AU DEUX CONTAINERS								   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int _GETcontainerMap(mmachine m)
{
	int p_cont;
	container * cont;
	
	if ((p_cont=MTOP(MMpull(m)))==NIL)
	{
		MMpush(m,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,p_cont))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcontainerMap: container already destroyed\n");
		MMpush(m,NIL);
		return 0;
	}
	
	return MMpush(m,MMfetch(m,p_cont,2));
}


int DsContainer2(mmachine m,int handsys,int objm)
{
	int p_obj=MTOP(objm);
	container *co=RetrievePtrContainer(m,p_obj);
	
	co->DestructScolContainer(m,p_obj);
	delete(co);
	
	return 0;
}

int _PAINTcontainer(mmachine m)
{
	int p_cont;
	container * cont;

	if ((p_cont=MMget(m,0))==NIL) return 0;
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_PAINTcontainer: container already destroyed\n");
		return 0;
	}
	cont->Redraw(1);
	return 0;
}



int _PAINTcontainerArea(mmachine m)
{
	int p_cont,w,h;
	Rect2D rect;
	container * cont;
	
	if ((p_cont=MMget(m,4))==NIL)
	{
		m->pp += 4;
		MMset(m,0,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,MTOP(p_cont)))==NULL)
	{
		MMechostr(MSKTRACE,"_PAINTcontainer: container already destroyed\n");
		m->pp += 4;
		MMset(m,0,p_cont);
		return 0;
	}
	if ((h=MTOI(MMpull(m)))==NIL) h=0;
	if ((w=MTOI(MMpull(m)))==NIL) w=0;
	if ((rect.RctHG.iptY=MTOI(MMpull(m)))==NIL) rect.RctHG.iptY=0;
	if ((rect.RctHG.iptX=MTOI(MMpull(m)))==NIL) rect.RctHG.iptX=0;
	rect.RctBD.iptX=rect.RctHG.iptX+w;
	rect.RctBD.iptY=rect.RctHG.iptY+h;
	cont->RedrawArea(rect,1);
	return 0;
}



//$LB (11/11/2003)
/************************************************************************************************/
/*                                                                                              */
/*  int _SETcontainerCursor ( mmachine m ) ;                                                    */
/*                                                                                              */
/*  <=> _SETwinCursor mais pour une window de container
/*                                                                                              */
/************************************************************************************************/

int _SETcontainerCursor ( mmachine m )
{
  int s , res;
  PtrObjVoid O ;
  PtrObjCursor C ;
  HCURSOR Hc ;

	int p_cont;
	container * cont;
	

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "_SETcontainerCursor\n");
#endif
//***********************************

  s = MMpull( m ) ;

	if ((p_cont=MTOP(MMpull(m)))==NIL)
	{
		MMpush(m,NIL);
		return 0;
	}
	if ((cont=RetrievePtrContainer(m,p_cont))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcontainerMap: container already destroyed\n");
		MMpush(m,NIL);
		return 0;
	}

  if ( s != NIL ) 
  {
      //MMechostr(0,">PARAM\n");
      O = ( PtrObjVoid ) MMstart(m,(s>>1) );
      C = ( PtrObjCursor ) MMstart(m,(O->Buffer >> 1 ) ) ;
      Hc = C->HCursor ; 
   		cont->GetPtrWindow()->ChangeCursor ((int)Hc);
		 /*
        if ( Hc != ( HCURSOR ) GetClassLong ( H , GCL_HCURSOR ))
        {

                SetClassLong ( H , GCL_HCURSOR , (long) Hc ) ;
                if (GetCapture ( ) == H ) SetCursor ( Hc ) ;

         }
		 */
	}
	//$BLG: v4.6a5 - Added Else part
	else
	{
		//MMechostr(0,">NIL\n");
		Hc = arrowCursor;
		cont->GetPtrWindow()->ChangeCursor ((int)Hc);
	}

  res = MMpush ( m , s) ;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "_SETcontainerCursor end\n");
#endif
//***********************************

  return res ;
}




//$LB (31/10/2004)
/************************************************************************************************/
/*                                                                                              */
/*  int _GETcontainerCursorPos ( mmachine m ) ;                                                 */
/*                                                                                              */
/*  <=> renvoie les coordonées de la souris par rapport au container
/*                                                                                              */
/************************************************************************************************/

int _GETcontainerCursorPos ( mmachine m )
{
int s,p_cont;
container * cont;
POINT P,P2;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "_GETcontainerCursorPos\n");
#endif
//***********************************

	if ((p_cont=MTOP(MMpull(m)))==NIL)
	{
		MMpush(m,NIL);
		return 0;
	}

	if ((cont=RetrievePtrContainer(m,p_cont))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcontainerCursorPos: container already destroyed\n");
		MMpush(m,NIL);
		return 0;
	}

	GetCursorPos (&P ) ;

    P2.x = 0 ; P2.y = 0 ;

    ClientToScreen (cont->CoWin->parent->WHandler, &P2 ) ;
    P.x -= P2.x ;
    P.y -= P2.y ;
    if (MMpush(m,(P.x)<<1)) return MERRMEM ;
    if (MMpush(m,(P.y)<<1)) return MERRMEM ;
    if (MMpush(m,4)) return MERRMEM;
    s = MBdeftab (m);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "_GETcontainerCursorPos end\n");
#endif
//***********************************

	return s;
}


/*****************************************************************************/
/*                          Reflexes du container                            */
/*****************************************************************************/
int rflDestroyContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_DESTROY);
}


int rflPreDestroyContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_PREDESTROY);
}

int rflMoveContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_MOVE);
}

int rflSizeContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_SIZE);
}

int rflSetFocusContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_SETFOCUS);
}

int rflKillFocusContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_KILLFOCUS);
}

int rflPaintContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_PAINT);
}

int rflKeyUpContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_KEYUP);
}

int rflKeyDownContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_KEYDOWN);
}

int rflClickContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_CLICK);
}

int rflUnClickContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_UNCLICK);
}

int rflDblClickContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_DBLCLICK);
}

int rflMouseWheelContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_MOUSEWHEEL);
}

int rflMouseLeaveContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_MOUSELEAVE);
}

int rflMouseHoverContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_MOUSEHOVER);
}

int rflCursorMoveContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_CURSORMOVE);
}

int rflPreRenderContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_PRERENDER);
}

int rflPostRenderContainer(mmachine m)
{
  return OBJaddreflex(m,OBJCONTAINER,RFLCONTAINER_POSTRENDER);
}