/*********************************************************************************************************/
/*                                           CONTAINER WINDOW									         */
/*********************************************************************************************************/ 

#include "Macro.h"
#include "window.h"
#include "container.h"
#include "container_trans.h"
#include "bitmap.h"


Window::Window(int x,int y,int w,int h,int flags,char *name)
{
	Wx=x;
	Wy=y;
	WxSize=x;
	WySize=y;
	WFlags=flags;
};

Window::~Window()
{
}

void Window::ReplaceFlags(int oldflag,int newflag)
{
	WFlags&=(0xFFFF-oldflag);
	WFlags|=newflag;
}

int Window::UpdateSate(int newstate)
{
	int style=0;
	switch(newstate)
	{
		case CONTAINER_MINIMIZED:
			if (WFlags&CO_MINIMIZE) return 0;
			ReplaceFlags(CO_MAXIMIZE,CO_MINIMIZE);
			style=WINDOW_MINIMIZED;
			break;
		case CONTAINER_MAXIMIZED:
			if (WFlags&CO_MAXIMIZE) return 0;
			ReplaceFlags(CO_MINIMIZE,CO_MAXIMIZE);
			style=WINDOW_MAXIMIZED;
			break;
		case CONTAINER_RESTORED:
			ReplaceFlags(CO_MAXIMIZE|CO_MINIMIZE,0);
			style=WINDOW_RESTORED;
			break;
		case CONTAINER_HIDDEN:
			if (WFlags&CO_HIDE) return 0;
			ReplaceFlags(0,CO_HIDE);
			style=WINDOW_HIDDEN;
			break;
		case CONTAINER_UNHIDDEN: // cas aussi du CONTAINER_NORMAL
			//if (!(WFlags&CO_HIDE)) return 0;
			ReplaceFlags(CO_HIDE|CO_MAXIMIZE|CO_MINIMIZE,0);
			style=WINDOW_UNHIDDEN;
			break;
		default:
		{
			if (WFlags&CO_HIDE) return 0;
			style=WINDOW_UNHIDDEN;			
			break;
		}
	}
	return style;
}

#ifdef SCOL	// fenetre scol avec traitement externe des evenements

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

extern HINSTANCE hinst;
extern mmachine mm;
extern int OBJCONTAINER;
extern int OBJNODE;

// Constructeur-Destructeur
WindowScol::WindowScol(int parent,int x,int y,int w,int h,int flags,char *name):Window(x,y,w,h,flags,name)
{
	Wid=-1;
}

WindowScol::~WindowScol()
{
}



// construction d'une fenetre en utilisant Scol
// dans la pile avant channel winparent x y w h flags name
// dans la pile apres channel win
int WindowScol::ConstructWindow()
{
	// on insere le canal devant winparent pour ne pas le perdre pour la suite
	int tmp_res,i;

	

	if ((tmp_res=MMpush(mm,NIL))<0)
	{
		mm->pp+=7;
		MMset(mm,0,NIL);
		return tmp_res;
	}
	for (i=0;i<8;i++)
		MMset(mm,i,MMget(mm,i+1));
	
	
	// etat de la pile:channel channel winparent x y w h Flags name
	
	// evaluation des flags de creation de la fenetre scol
	int Style=WN_HIDE;							// par defaut la fenetre est cachée
	int Flags=WFlags=MTOI(MMget(mm,1));
	if (MMget(mm,6)!=NIL && Flags & CO_CHILDINSIDE)
		Style |= WN_CHILD;
	if (Flags & CO_NOCLIPCHILDREN)		
		Style |= WN_NOCLIPCHILDREN ;
	if ( Flags & CO_MENU )						
		Style |= WN_MENU;
	if (Flags & CO_NOBORDER)			
		Style |= WN_NOBORDER;
    if (Flags & CO_NOCAPTION)			
		Style |= WN_NOCAPTION; 
    if ( Flags & CO_MINIMIZE )
		Style |= WN_MINIMIZE ;                
    if ( Flags & CO_MINBOX )					
		Style |= WN_MINBOX ;
    if ( Flags & CO_MAXBOX )					
		Style |= WN_MAXBOX ;
    if ( Flags & CO_SIZEBOX )					
		Style |= WN_SIZEBOX;
    if ( Flags & CO_3DBORDER )					
		Style |= WN_DOWN;
	
	Style |= WN_NOBACKGROUND;

	MMset(mm,1,ITOM(Style)); 

	if ((tmp_res=MMpush(mm,Msearchinsyspak(mm,"_CRwindow")))<0)
	{
		mm->pp+=7; 
		MMset(mm,0,NIL);
		return tmp_res;
	}
	// etat de la pile:channel channel winparent x y w h Flags name "_CRwindow"
	Minterpreter(mm);	
	// etat de la pile:channel win
	return 0;
}

int WindowScol::DestructWindow(int p)
{
	// destruction de la fenetre on aurait pu utiliser la fonction _DSwindow
	// mais ca oblige a faire des MMpush -> garbage!!! (dangereux)
	return OBJdelTM(mm,OBJtypebyname ("OBJTYPWINDOW"),p);
	
}

// Renvoie le pointeur Magma de la fenetre
int	WindowScol::RetrieveMWin()
{
	int p;
	if ((p=OBJfindTH( mm,OBJtypebyname("OBJTYPWINDOW"), Wid ))==NIL) return NIL;
	return MMfetch( mm,p, OFFOBJMAG );
}

int	WindowScol::SetReflexes()
{
	int tmp_res;

	// etat de la pile:cont win
	// click
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Click")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinClick")));
	Minterpreter(mm);
	// etat de la pile:cont win

	// unclick
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer UnClick")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinUnclick")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// dblclick
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer DblClick")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinDClick")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// keydown
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer KeyDown")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinKeydown")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// focus
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer KeyUp")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinKeyup")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// focus
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Focus")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinFocus")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// killfocus
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer KillFocus")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinKillFocus")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// move
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Move")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinMove")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// size
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Size")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinSize")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// close
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Close")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinClose")));
	Minterpreter(mm);

	// etat de la pile:cont win

	//destroy
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Destroy")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinDestroy")));
	Minterpreter(mm);

	// etat de la pile:cont win

	//cursormove
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer CursorMove")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBcursorMove")));
	Minterpreter(mm);

	// etat de la pile:cont win

	// paint
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer Paint")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinPaint")));
	Minterpreter(mm);

	// mousewheel
	CHECK(MMpush(mm,Msearchinsyspak(mm,"RFL wincontainer MouseWheel")));
	CHECK(MMpush(mm,MMget(mm,2)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_CBwinWheel")));
	Minterpreter(mm);
	
	return 0;
}



int	WindowScol::Move(int x,int y)
{ 
	// dans le pile cont x y
	// on insere win devant x
	int i,tmp_res;
	CHECK(MMpush(mm,NIL));
	for (i=0;i<2;i++)
		MMset(mm,i,MMget(mm,i+1));
	MMset(mm,2,MMfetch(mm,MTOP(MMget(mm,3)),3));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_MVwindow")));
	Minterpreter(mm);
	MMpull(mm);
	return 0;
}

int	WindowScol::Size(int x,int y,int w,int h,int ext)
{ 
	// dans le pile cont x y w h
	// on insere win devant x
	int i,tmp_res;
	CHECK(MMpush(mm,NIL));
	for (i=0;i<4;i++)
		MMset(mm,i,MMget(mm,i+1));
	MMset(mm,4,MMfetch(mm,MTOP(MMget(mm,5)),3));
	INVERT(mm,0,2);
	INVERT(mm,1,3);
	// dans le pile cont win w h x y
	CHECK(MMpush(mm,Msearchinsyspak(mm,ext?"_SIZEwindowEx":"_SIZEwindow")));
	Minterpreter(mm);
	MMpull(mm);
	return 0;
}



int	WindowScol::SetName(char *name)
{ 
	int tmp_res,p;
	char *p_c;
	
	// on empile la fenetre
	CHECK(MMpush(mm,RetrieveMWin()));
	
	//on empile le texte
	int len=strlen(name);
	if ((p=MMmalloc(mm,STR_SIZE(len),TYPEBUF))<0) return p;
	MMstore(mm,p,0,len);
	p_c=MMstartstr(mm,p);
	memcpy(p_c,name,len);
	p_c[len]=0;
	CHECK(MMpush(mm,PTOM(p)));
	
	// on empile la fonction
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_SETwindowName")));
	Minterpreter(mm);
	MMpull(mm);
	
	
	return 0;
}


int	WindowScol::Show(int newstate)
{ 
	int tmp_res,wndstate;
	if ((wndstate=UpdateSate(newstate)))
	{
		// on empile win 
		CHECK(MMpush(mm,RetrieveMWin()));
		CHECK(MMpush(mm,ITOM(wndstate)));
		CHECK(MMpush(mm,Msearchinsyspak(mm,"_SHOWwindow")));
		Minterpreter(mm);
		
		// on depile win
		MMpull(mm); 
	}
	return 0;
}

int	WindowScol::Top()
{ 
	int tmp_res;
	CHECK(MMpush(mm,RetrieveMWin()));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_TOPwindow")));
	Minterpreter(mm);
	MMpull(mm);
	return 0;
}

int	WindowScol::Enable(int etat)
{ 
	int tmp_res;
	CHECK(MMpush(mm,RetrieveMWin()));
	CHECK(MMpush(mm,ITOM(etat)));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_ENwindow")));
	Minterpreter(mm);
	MMpull(mm);
	return 0;
}

int	WindowScol::SetFocus()
{ 
	int tmp_res;
	CHECK(MMpush(mm,RetrieveMWin()));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_SETfocus")));
	Minterpreter(mm);
	MMpull(mm);
	return 0;
}

int	WindowScol::GetSize(int *x,int *y,int *w,int *h,int ext)
{ 
	int tmp_res;
	CHECK(MMpush(mm,RetrieveMWin()));
	CHECK(MMpush(mm,Msearchinsyspak(mm,ext?"_GETwindowExPositionSize":"_GETwindowPositionSize")));
	Minterpreter(mm);
	int p=MTOP(MMget(mm,0));
	*x=MTOI(MMfetch(mm,p,0));
	*y=MTOI(MMfetch(mm,p,1));
	*w=MTOI(MMfetch(mm,p,2));
	*h=MTOI(MMfetch(mm,p,3));
	return 0;
}

// fonctions de gestions du curseur
int	WindowScol::CrCursor(const char * Cursor){return 0;}
int	WindowScol::DsCursor(int Cursor){return 0;}
int	WindowScol::ChangeCursor(int Cursor){return 0;}



WindowScolWin::WindowScolWin(mmachine m, int parent,int x,int y,int w,int h,int flags,char *name):WindowScol(parent,x,y,w,h,flags,name)
{
PtrObjVoid O;
PtrObjWindow wparent;

	Whwnd=NULL;

	//$LB (16/12/2003) : store the window scol parent datas (will be used in Blit process)
	O = ( PtrObjVoid ) MMstart(m, (parent) ) ;
	wparent = ( PtrObjWindow ) MMstart(m, (O->Buffer>>1) ) ;
	if (wparent != NULL)
	{
	RECT screen;

	  this->parent = (PtrObjWindow) malloc (sizeof (ObjWindow));

  	  GetWindowRect ( GetDesktopWindow () , &screen) ;

	  // LIB2D transparency bitmap background
	  if (LIB2DtransBkg == NULL) 
	  { 
		LIB2DtransBkg = (PtrObjBitmap) malloc (sizeof(struct ObjBitmap));
		LIB2DtransBkg->TailleW = screen.right - screen.left;
		LIB2DtransBkg->TailleH = screen.bottom - screen.top;
		LIB2DtransBkg->BPP = 24;
		LIB2DtransBkg->BytesPP = 3;
		ObjBitmap_NewDIBSection (LIB2DtransBkg, NULL);
	  }
	  CaptureScreen (LIB2DtransBkg, 0, 0, LIB2DtransBkg->TailleW, LIB2DtransBkg->TailleH);
	  this->parent->tBkg = (PtrObjBitmap) LIB2DtransBkg;
			

	  // window transparency buffer
	  if (this->parent->tBuf == NULL)
	  {
    	this->parent->tBuf = (PtrObjBitmap) malloc (sizeof(struct ObjBitmap));
		this->parent->tBuf->TailleW = this->parent->TailleW;
		this->parent->tBuf->TailleH = this->parent->TailleH;
		this->parent->tBuf->BPP = 24;
		this->parent->tBuf->BytesPP = 3;
		this->parent->tX = this->parent->PosX;
		this->parent->tY = this->parent->PosY;
		ObjBitmap_NewDIBSection (this->parent->tBuf, NULL);
	  } 



      this->parent->PosX       = wparent->PosX;
	  this->parent->PosY       = wparent->PosY;
	  this->parent->TailleW    = wparent->TailleW;
	  this->parent->TailleH    = wparent->TailleH;
	  this->parent->Flags      = wparent->Flags;
	  this->parent->WHandler   = wparent->WHandler;
      this->parent->tSimulated = wparent->tSimulated; 
	  this->parent->tBuf       = wparent->tBuf; 
	  this->parent->tBkg       = LIB2DtransBkg;//wparent->tBkg; 
	  this->parent->tX         = wparent->tX;
	  this->parent->tY         = wparent->tY;
	  this->parent->tColorB    = wparent->tColorB; 
      this->parent->tColorG    = wparent->tColorG;
      this->parent->tColorR    = wparent->tColorR; 
      this->parent->tfactor    = wparent->tfactor; 
      this->parent->tflags     = wparent->tflags;

	}
}

WindowScolWin::~WindowScolWin()
{
	Whwnd=NULL;
}

// construction d'une fenetre en utilisant Scol
// dans la pile avant channel winparent x y w h flags name
// dans la pile apres channel win
int WindowScolWin::ConstructWindow()
{
	int tmp_res;
	CHECK(WindowScol::ConstructWindow());
	
	PtrObjWindow win;
	if ((win=GET_PTR_OBJ_WINDOW(MTOP(MMget(mm,0))))!=NULL)
	{
		Whwnd=GET_PTR_OBJ_WINDOW(MTOP(MMget(mm,0)))->WHandler;
		Wid=(int)Whwnd;
		return 0;
	}
	else
		return MERRRET;
}

int WindowScolWin::Show(int newstate)
{
	int res=WindowScol::Show(newstate);
	// on positionne la fenetre en premiere position
	if (!(WFlags & CO_HIDE))
	{
		SetForegroundWindow(Whwnd);
		BringWindowToTop(Whwnd);
	}
	return res;
}










//$LB (16/12/2003)
//
// WindowScolWin::TransparentBlitBuffer is stored in container_trans.cpp
//







int	WindowScolWin::BlitBuffer(CObjBufferWindows* CoBuffer,int buff,int typeblit,int dx,int dy,int dw,int dh,int sx,int sy)
{
	switch(typeblit)
	{
		case BLIT_WINDOWS:
		{
			if (this->parent != NULL)
			if (this->parent->tSimulated == 0)
			{

			HDC Dcb,Dcw;
			HBITMAP OldBitmap;

			Dcw = GetDC ( Whwnd ) ;       
			Dcb = CreateCompatibleDC ( Dcw ) ;
			OldBitmap =(HBITMAP) SelectObject ( Dcb , (HBITMAP)buff ) ;
			BitBlt ( Dcw , dx , dy , dw , dh , Dcb , sx , sy , SRCCOPY ) ;
			SelectObject( Dcb , OldBitmap );
			DeleteDC( Dcb );
			ReleaseDC(Whwnd,Dcw);
			}
			else this->TransparentBlitBuffer (CoBuffer, buff, dx, dy, dw, dh, sx, sy);
				
			break;
		}
		default:
			break;
	}
	return 0;
}

Rect2D WindowScolWin::GetUpdatableRect()
{
	RECT rect;
	GetUpdateRect(Whwnd,&rect,TRUE);
	return Rect2D(rect.left,rect.top,rect.right,rect.bottom);
}

int	WindowScolWin::CrCursor(const char * Cursor)
{
	return (int)(HCURSOR)LoadCursor(NULL,Cursor);
}
int	WindowScolWin::DsCursor(int Cursor)
{
	return (int)DestroyCursor((HCURSOR)Cursor);
}
int	WindowScolWin::ChangeCursor(int Cursor)
{
	HCURSOR res=NULL;
	if (Cursor!=0)
	{
		HCURSOR hCursor=(HCURSOR)Cursor;
		PtrObjWindow OW;
		// On recupere le PtrObjWindow pour pouvoir mettre le curseur
		// au nouveau curseur car sinon des qu'on bouge la souris il
		// le remet en etat arrow
		if ((OW=GET_PTR_OBJ_WINDOW(MTOP(RetrieveMWin())))!=NULL)
		{
			OW->Cursor=hCursor;
			if ( hCursor != (res=( HCURSOR ) GetClassLong ( Whwnd , GCL_HCURSOR )))
			{
					SetClassLong ( Whwnd , GCL_HCURSOR , (long)hCursor ) ;
					if (GetCapture ( ) == Whwnd ) SetCursor ( hCursor ) ;
			}
		}
	}
	return (int)res;
}

int	WindowScolWin::GetWindowState()
{
	WINDOWPLACEMENT wnd ;
	wnd.length = sizeof ( WINDOWPLACEMENT ) ;
	GetWindowPlacement(Whwnd,&wnd);
	return	(wnd.showCmd&(		
									CONTAINER_HIDDEN|
									CONTAINER_UNHIDDEN|
									CONTAINER_MAXIMIZED|
									CONTAINER_MINIMIZED|
									CONTAINER_RESTORED|
									CONTAINER_NORMAL
					   )
			);
}

Point2D	WindowScolWin::GetCursorPosClient()
{
	POINT P;	
	GetCursorPos (&P);
	ScreenToClient(Whwnd,&P);
	return Point2D(P.x,P.y);
}

Point2D	WindowScolWin::GetCursorPosScreen()
{
	POINT P;	
	GetCursorPos (&P);
	return Point2D(P.x,P.y);
}

Rect2D	WindowScolWin::GetClientInScreen()
{
	if (Whwnd==NULL)
		return Rect2D(0,0,0,0);
	RECT rect;
	GetClientRect(Whwnd,&rect);
	MapWindowPoints(Whwnd,NULL,(LPPOINT)&rect,2);
	return Rect2D(rect.left,rect.top,rect.right,rect.bottom);
}

int	WindowScolWin::IsPointInWindow(Point2D p)
{
	POINT pt;
	pt.x=p.iptX;
	pt.y=p.iptY;
	return ((WindowFromPoint(pt) == Whwnd));
}

int	WindowScolWin::CopyToClipBoard(char *txt)
{
	int len=strlen(txt);
	HANDLE hdata;
	char * lpdata;

	if (!(hdata = GlobalAlloc(GMEM_DDESHARE, sizeof(char)*(len+1)))) 
		return 1;
	if (!(lpdata = (char *)GlobalLock (hdata))) 
		return 1;
	memcpy(lpdata,txt,sizeof(char)*(len+1));
	GlobalUnlock(hdata);

    /* Clear the current contents of the clipboard, and set
     * the data handle to the new string.
     */

    if (OpenClipboard(Whwnd))
	{
        EmptyClipboard();
        SetClipboardData(CF_TEXT, hdata);
        CloseClipboard();
    }    
	hdata = NULL;
	return 0;
}

char *WindowScolWin::GetFromClipBoard()
{
	char *res=NULL;
	if (OpenClipboard(Whwnd)) 
	{
		if (IsClipboardFormatAvailable(CF_TEXT) || IsClipboardFormatAvailable(CF_OEMTEXT))
		{
			HANDLE hdata;
			char * lpdata;
			
			if (!(hdata = GetClipboardData(CF_TEXT))) 
			{
				CloseClipboard();
				return NULL;
            }
			if (!(lpdata = (char *)GlobalLock(hdata))) 
			{
                CloseClipboard();
				return NULL;
            }
			
			res=(char *)malloc(sizeof(char)*(strlen(lpdata)+1));
			strcpy(res,lpdata);

			GlobalUnlock(hdata);
			CloseClipboard();
			//free(lpdata);
		}
		else
		{
			CloseClipboard();
			return NULL;
		}
	}
	return res;

}
#else		// fenetre non scol avec traitement interne des evenements

#endif		//SCOL
