//
// Modifications History
//
//$LB (20/12/2002) : 16bits to 24bits
//

#include "Macro.h"
#include "CObjectText.h"
#include "CObjectLabel.h"
#include "CObjectEditText.h"
#include "CObjectLabelSelect.h"
#include "../x/Objstr.h"
#include "utils.h"
#include "container.h"
#include "CObjectSlideBar.h"
#include "CObjMessageResize.h"			//pour la classe CObjMessageResize et les directions prédéfinies
#include "CObjMessageMove.h"			//pour la classe CObjMessageMove et les directions prédéfinies

extern int OBJNODE;
extern mmachine mm;

#define FONT	0
#define SLIDE_V 1
#define SLIDE_H 2



CObjectText::CObjectText(container * cont,
						 Layer *layer,
						 int x,int y,int w,int h,
						 int flags,int contflags,
						 int textcolor,
						 int textshadowflag,
						 int textshadowcolor,
						 int transp,
						 int coeff_transp_text,
						 int p_font,
						 char * texte,const char *forbiddenchar)
						 :CObjectBase(cont,layer,x,y,w,h,flags,contflags,transp)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::CObjectText");
#endif
//***********************************

	if (!( ObjFlags&(CT_LEFT|CT_RIGHT|CT_CENTER) )) ObjFlags|=CT_LEFT;
	
	TEXTtransp=transp;
	TEXTtexttransp=coeff_transp_text;
	
	TEXTwordwrap=ObjFlags&CT_WORDWRAP;
	TEXTmultifont=ObjFlags&CT_MULTIFONT;
	TEXTclickvalidation=0;
	
	TEXTforbiddenchar=(char *)malloc(sizeof(char)*(strlen(forbiddenchar)+1));
	strcpy(TEXTforbiddenchar,forbiddenchar);
	
	TEXTauthorizedChars=NULL;

	TEXTrefFont=Lib2dFontService.getLayerFont(GET_PTR_OBJ_FONT(p_font));
	
	if (TEXTmultifont)
		TEXTtexte=new TextMultiFont(texte,
									TEXTrefFont,
									textcolor,
									textshadowflag,
									textshadowcolor,
									coeff_transp_text,
									TEXTwordwrap,
									ObjW
									);
	else if (ObjFlags&CT_PASSWORD)
		TEXTtexte=new TextPassword( texte,
									TEXTrefFont,
									textcolor,
									textshadowflag,
									textshadowcolor,
									coeff_transp_text,
									TEXTwordwrap,
									ObjW
								  );
	else
		TEXTtexte=new TextMonoFont( texte,
									TEXTrefFont,
									textcolor,
									textshadowflag,
									textshadowcolor,
									coeff_transp_text,
									TEXTwordwrap,
									ObjW
								  );

	TEXTFirstVisibleSubLine=0;

	// pour les scrolls
	TEXTnbVerticalScrollBarPos=0;
	TEXTVerticalScrollBarIndex=0;

	TEXTnbHorizontalScrollBarPos=0;	// le nombre total de colonnes
	TEXTHorizontalScrollBarIndex=0;	// la position du ScrollBar horizontal
	 
	nbScrollEvent=0;

	int b1,b2,b3,b4;
	TEXTcyChar=TEXTtexte->RetrieveCharParam(0,&b1,&b2,&b3,&b4)->CLFaverageCharHeight;
	TEXTnbVisibleSubLines=ObjH/TEXTcyChar;

	if (ObjLayer!=NULL && coeff_transp_text!=255 && ObjLayer->AlphaBitmap!=NULL)
		ObjLayer->fillAlphaLayer (coeff_transp_text);
	

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::CObjectText end");
#endif
//***********************************
}


CObjectText::~CObjectText()
{	
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::~CObjectText");
#endif
//***********************************

	free(TEXTforbiddenchar);

	if (TEXTauthorizedChars!=NULL)
		free(TEXTauthorizedChars);

	delete(TEXTtexte);

    // dereferencement de la fonte !!!! Attention une seule fonte est referencée et non pas
    // plusieurs meme dans le cas d'un multifont
    Lib2dFontService.delLayerFont(TEXTrefFont);
}


int CObjectText::send_notification_change_nblines(int nblignes,int redrawobject)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::send_notification_change_nblines");
#endif
//***********************************

	//instancie la classe CObjMessageResize
	CObjMessageResize* msg = new CObjMessageResize(DIR_VERTICAL, 0, nblignes, redrawobject);

	//propage le message aux objects liés
	this->notify(msg);
	delete msg;

	return 0;
}


// envoie une notification de changement de nombre de position du scrollbar horizontal
int CObjectText::send_notification_change_nbcolones(int nbcolonnes,int redrawobject)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::send_notification_change_nbcolones");
#endif
//***********************************
	
	//instancie la classe CObjMessageResize
	CObjMessageResize* msg = new CObjMessageResize(DIR_HORIZONTAL, 0, nbcolonnes, redrawobject);

	//propage le message aux objects liés
	this->notify(msg);
	delete msg;

	return 0;
}
	

int CObjectText::send_notification_scrollpos(int direction,int orientation,int diffscrollpos,int redrawobject)
{

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::send_notification_scrollpos");
#endif
//***********************************

	//instancie la classe CObjMessageMove
	CObjMessageMove* msg = new CObjMessageMove(direction*orientation, diffscrollpos, redrawobject);

	//propage le message aux objects liés
	this->notify(msg);
	delete msg;

	return 0;
}


int CObjectText::GoDown(int nbligne,int p_tab,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GoDown");
#endif
//***********************************

//	int p_font=MTOP(MMfetch(mm,p_tab,FONT));
	TEXTFirstVisibleSubLine+=nbligne;
	SetScrollPositionVertical(nbligne,1,notifylinks);
	ClearAllText(p_tab);
	DrawObjectText(TEXTFirstVisibleSubLine);
	return TEXTFirstVisibleSubLine;
}


int CObjectText::GoUp(int nbligne,int p_tab,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GoUp");
#endif
//***********************************
//	int p_font=MTOP(MMfetch(mm,p_tab,FONT));
	TEXTFirstVisibleSubLine-=nbligne;
	if (TEXTFirstVisibleSubLine<TEXTnbVerticalScrollBarPos) 
		SetScrollPositionVertical(nbligne,-1,notifylinks);
	ClearAllText(p_tab);
	DrawObjectText(TEXTFirstVisibleSubLine);
	return TEXTFirstVisibleSubLine;
}


// scroll de nbchar characteres sur la droite
int CObjectText::GoRight(int nbpixels,int p_tab,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GoRight");
#endif
//***********************************	
	TEXTHorizontalScrollBarIndex+=nbpixels;
	SetScrollPositionHorizontal(nbpixels,1,notifylinks);
	ClearAllText(p_tab);
	DrawObjectText(TEXTFirstVisibleSubLine);
	return TEXTHorizontalScrollBarIndex;
}


int CObjectText::GoLeft(int nbpixels,int p_tab,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GoLeft");
#endif
//***********************************

	TEXTHorizontalScrollBarIndex-=nbpixels;		
	if (TEXTHorizontalScrollBarIndex<TEXTnbHorizontalScrollBarPos)
		SetScrollPositionHorizontal(nbpixels,-1,notifylinks);
	ClearAllText(p_tab);
	DrawObjectText(TEXTFirstVisibleSubLine);
	return TEXTHorizontalScrollBarIndex;
}


void CObjectText::ClearAllText(int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::ClearAllText");
#endif
//***********************************

	if (ObjLayer!=NULL)
		ObjLayer->fillPartLayer( ObjTransparency,Rect2D(0,0,ObjW,ObjH) );
}


void CObjectText::WordWrapFromStartIndex(int IndexStart,int p_font)
{

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::WordWrapFromStartIndex");
#endif
//***********************************

	TEXTtexte->WordWrap(TEXTtexte->SearchSubLineInTab(IndexStart),TEXTtexte->getLen());
}

	
void CObjectText::SetScrollPositionVertical(int nblignes,int dir,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetScrollPositionVertical");
#endif
//***********************************
	
	if (nblignes)
	{
		TEXTVerticalScrollBarIndex+=dir*nblignes;
		if (notifylinks)
		{
			send_notification_scrollpos(dir,DIR_VERTICAL,nblignes,0);
			nbScrollEvent++;
		}
	}
}


void CObjectText::SetScrollPositionHorizontal(int nbcolonnes,int dir,int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetScrollPositionHorizontal");
#endif
//***********************************
	
	if (nbcolonnes)
	{
		if (notifylinks)
		{
			send_notification_scrollpos(dir,DIR_HORIZONTAL,nbcolonnes,0);
			nbScrollEvent++;
		}
	}
}


void CObjectText::SetScrollNbLines(int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetScrollNbLines");
#endif
//***********************************
	
	int diff=(int)TEXTtexte->getNbLines()-(int)TEXTnbVisibleSubLines;
	
	if (diff<0) diff=0;
	if (TEXTnbVerticalScrollBarPos!=(unsigned int)diff)
	{
		if (notifylinks)
		{
			send_notification_change_nblines((int)diff-(int)TEXTnbVerticalScrollBarPos,0);
			nbScrollEvent++;
		}
		TEXTnbVerticalScrollBarPos=diff;
	}
}


// evalue le nombre de position du scrollbar horizontal
void CObjectText::SetScrollNbColonnes(int notifylinks)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetScrollNbColonnes");
#endif
//***********************************
	
	int diff=TEXTtexte->getMaxWidth()-ObjW;
	
	if (diff<0) diff=0;
	if (TEXTnbHorizontalScrollBarPos!=(unsigned int)diff)
	{
		if (notifylinks)
		{
			send_notification_change_nbcolones(diff-(int)TEXTnbHorizontalScrollBarPos,0);
			nbScrollEvent++;
		}
		TEXTnbHorizontalScrollBarPos=diff;
	}
}


void CObjectText::RepaintLinkedScroll()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::RepaintLinkedScroll");
#endif
//***********************************
	
	if (nbScrollEvent)
		this->repaint(nbScrollEvent);
	nbScrollEvent=0;
}


void CObjectText::InitLinkedScrollBar(int ndxLine)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::InitLinkedScrollBar");
#endif
//***********************************
	
	SetScrollNbLines(1);
	SetScrollNbColonnes(1);
	
	if (ObjFlags&CT_RIGHT)
		TEXTHorizontalScrollBarIndex=TEXTnbHorizontalScrollBarPos;
	else if (ObjFlags&CT_CENTER)
		TEXTHorizontalScrollBarIndex=max(0,(TEXTtexte->getMaxWidth()-ObjW)/2);
	SetScrollPositionHorizontal(TEXTHorizontalScrollBarIndex,1,1);

	nbScrollEvent=0;
	DrawObjectText(ndxLine);
	
}


int CObjectText::EvalDecalageFlags(int SubLine)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::EvalDecalageFlags");
#endif
//***********************************
	
	int res=0;
	if (TEXTwordwrap || 
		(!TEXTwordwrap && TEXTtexte->getMaxWidth()<ObjW)
	   )
	{
		// la plus longue des sous-ligne est <ObjW
		// calcul de l'alignement
//		if (ObjFlags&CT_LEFT)
//			res=0;
		
		if (ObjFlags&CT_RIGHT)
			res=ObjW-TEXTtexte->getInfoLine(SubLine).stringw;
		
		if (ObjFlags&CT_CENTER)
			res=(ObjW-TEXTtexte->getInfoLine(SubLine).stringw)/2;

	}
	else
	{	
		// calcul de l'alignement
		if (ObjFlags&CT_LEFT)
			res=-(int)TEXTHorizontalScrollBarIndex;

		if (ObjFlags&CT_RIGHT)
			res=TEXTtexte->getMaxWidth()-(int)TEXTHorizontalScrollBarIndex-TEXTtexte->getInfoLine(SubLine).stringw;

		if (ObjFlags&CT_CENTER)
			res=(TEXTtexte->getMaxWidth()-TEXTtexte->getInfoLine(SubLine).stringw)/2-(int)TEXTHorizontalScrollBarIndex;
	}
#if DEBUG_OBJTEXT
	MMechostr(1,"Decalage:%d %d\n",res,TEXTtexte->getInfoLine(SubLine).stringw);
#endif
	return res;
}

// Evalue le nombre de sous-lignes visibles à
// partir de la sous-ligne d'index ndxSubLine
int CObjectText::EvalNbVisibleSubLine(int ndxSubLine)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::EvalNbVisibleSubLine");
#endif
//***********************************
	
	int nb=0;
	if (TEXTmultifont)
	{
		int i=ndxSubLine+1;
		while ( i<(int)TEXTtexte->getNbLines()-1 && 
			    TEXTtexte->getInfoLine(i).postop-TEXTtexte->getInfoLine(ndxSubLine).postop<ObjH
			  ) 
			  i++;
		nb=i-ndxSubLine;
	}
	else
	{
		int b1,b2,b3,b4;
		nb=ObjH/TEXTtexte->RetrieveCharParam(0,&b1,&b2,&b3,&b4)->CLFaverageCharHeight;
	}
#if DEBUG_OBJTEXT
	MMechostr(1,"Nbre de Ligne visibles à partir de [%d]:%d\n",ndxSubLine,nb);
#endif
	return nb;
}


void CObjectText::DrawObjectText(int IndexSubLine)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::DrawObjectText");
#endif
//***********************************
	
	int t=(((IndexSubLine-TEXTFirstVisibleSubLine)>0)?1:0);
	int	i=(IndexSubLine-t);
	int y=TEXTtexte->getInfoLine(i).postop-TEXTtexte->getInfoLine(TEXTFirstVisibleSubLine).postop;
	do
	{
#if DEBUG_OBJTEXT
		MMechostr(1,"Redessine ligne[%d]\n",i);
#endif
//MMechostr(1,"Redessine ligne[%d]\n",i);
		y+=TEXTtexte->DrawSubString(ObjLayer,EvalDecalageFlags(i),y,ObjFlags,i);
		i++;
	}while ((y<ObjH)&&(i<(int)TEXTtexte->getNbLines()));
}


void CObjectText::ScrollPositionAfterChangingText(int scrolltype,int suppress,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::ScrollPositionAfterChangingText");
#endif
//***********************************


//	int p_font=MTOP(MMfetch(mm,p_tab,FONT));

	SetScrollNbLines(1);
	SetScrollNbColonnes(1);
	
	// on positionne le curseur et le scrollbar si necessaire
	SetPositionCursorAndScroll(scrolltype,suppress,p_tab);
	RepaintLinkedScroll();
}


void CObjectText::SetText(char *newtxt,PtrObjFont font,int textcolor,int coeff,int shadowflag,int shadowcolor,int scrolltype,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetText");
#endif
//***********************************
	
	unsigned int oldlen=TEXTtexte->getLen();
	if (TEXTmultifont)
	{
		InfoChar info;
	
		info.color=textcolor;
		info.coefftransparancy=coeff;
		info.shadowflag=shadowflag;
		info.shadowcolor=shadowcolor;
		//info.font=Lib2dFontService.getLayerFont(font);
        
        /*if ((int)font->WHandler!=TEXTrefFont->CLFid)
        {
            Lib2dFontService.delLayerFont(TEXTrefFont);
            TEXTrefFont=Lib2dFontService.getLayerFont(font);
        }*/
        info.font=TEXTrefFont;
        
		(static_cast <TextMultiFont *> (TEXTtexte))->SetText(newtxt,&info,1);
	}
	else
		(static_cast <TextMonoFont *> (TEXTtexte))->SetText(newtxt,1);
	
	if (ObjFlags&CT_EDITLINE)
		TEXTtexte->CrunchText(TEXTwordwrap);
	
	ScrollPositionAfterChangingText(scrolltype,oldlen>TEXTtexte->getLen(),p_tab);
}


void CObjectText::AddText(char *newtxt,PtrObjFont font,int textcolor,int coeff,int shadowflag,int shadowcolor,int scrolltype,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::AddText");
#endif
//***********************************
	
	if (TEXTmultifont)
	{
		InfoChar info;
	
		info.color=textcolor;
		info.coefftransparancy=coeff;
		info.shadowflag=shadowflag;
		info.shadowcolor=shadowcolor;
		info.font=//Lib2dFontService.getLayerFont(font);
                  TEXTrefFont;
		(static_cast <TextMultiFont *> (TEXTtexte))->AddText(newtxt,&info,1);
	}
	else
		(static_cast <TextMonoFont *> (TEXTtexte))->AddText(newtxt,1);
	
	
	if (ObjFlags&CT_EDITLINE)
		TEXTtexte->CrunchText(TEXTwordwrap);
	
	ScrollPositionAfterChangingText(scrolltype,0,p_tab);
}


char * CObjectText::GetLine(int Line)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GetLine");
#endif
//***********************************
	
	if (Line<0) return NULL;
	
	int i=0;
	char *res=(char *)malloc(sizeof(char));
	while ((unsigned int)i<TEXTtexte->getNbLines() && TEXTtexte->getInfoLine(i).ndx<(unsigned int)Line) i++;
	if ((unsigned int)i==TEXTtexte->getNbLines())
	{
		free(res);
		return NULL;
	}
	else
	{
		int lenres=0;
		int len=0;
		while ((unsigned int)i<TEXTtexte->getNbLines() && TEXTtexte->getInfoLine(i).ndx==(unsigned int)Line)
		{
			lenres+=TEXTtexte->getInfoLine(i).nCount;
			res=(char *)realloc(res,sizeof(char)*(lenres+1));
			memcpy(res+len,TEXTtexte->getRealText()+TEXTtexte->getInfoLine(i).first,sizeof(char)*TEXTtexte->getInfoLine(i).nCount);
			res[lenres]=0;
			len=lenres;
			i++;
		}
		if (*res=='\r')
		{
			// on supprime le dernier retour chariot s'il y a lieu
			res=(char *)realloc(res,sizeof(char)*lenres);
			res[lenres-1]=0;
		}
	}

	return res;
}


int	CObjectText::GetLineCount()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GetLineCount");
#endif
//***********************************
	
	int nb=1;
	unsigned int currentsubline=0;
	int i=0;
	while ((unsigned int)i<TEXTtexte->getNbLines())
	{
		if (currentsubline!=TEXTtexte->getInfoLine(i).ndx)
		{ 
			currentsubline=TEXTtexte->getInfoLine(i).ndx;
			nb++;
		}
		i++;
	}
	return nb;
}


void CObjectText::SetFirstVisibleLine(int line,int p_tab,int redraw)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetFirstVisibleLine");
#endif
//***********************************
	
	if (line<0) return;
	int diff=(int)TEXTtexte->getNbLines()-(int)TEXTnbVisibleSubLines;

	if (diff<0) diff=0;
	if (line>diff) line=diff;
	
	int delta=line-(int)TEXTFirstVisibleSubLine;
	if (delta<0)
		GoUp(-delta,p_tab,1);
	else if (delta>0)
		GoDown(delta,p_tab,1);
	
	if (redraw)
	{
		Redraw();
		RepaintLinkedScroll();
	}
}


void CObjectText::DelLine(int scrolltype,int line,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::DelLine");
#endif
//***********************************
	
	if (line<0) return;
	
	int first=0;
	int count=0;
	int i=0;
	
	while ((unsigned int)i<TEXTtexte->getNbLines() && TEXTtexte->getInfoLine(i).ndx<(unsigned int)line) i++;
	
	if ((unsigned int)i!=TEXTtexte->getNbLines())
	{
		first=TEXTtexte->getInfoLine(i).first;
		while((unsigned int)i<TEXTtexte->getNbLines() && TEXTtexte->getInfoLine(i).ndx==(unsigned int)line)
		{
			count+=TEXTtexte->getInfoLine(i).nCount;
			i++;
		}
		
		if (first+count<(int)TEXTtexte->getLen()) count++;
		TEXTtexte->DeleteSubString(first,first+count,1);
		ScrollPositionAfterChangingText(scrolltype,1,p_tab);
	}
}


void CObjectText::SetForbiddenChar(char *newfor)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetForbiddenChar");
#endif
//***********************************
	
	free(TEXTforbiddenchar);
	TEXTforbiddenchar=(char *)malloc(sizeof(char)*(strlen(newfor)+1));
	strcpy(TEXTforbiddenchar,newfor);

	if (ObjFlags&CT_EDITLINE)
	{
		int len=strlen(TEXTforbiddenchar);
		TEXTforbiddenchar=(char *)realloc(TEXTforbiddenchar,sizeof(char)*(len+2));
		TEXTforbiddenchar[len]='\r';
		TEXTforbiddenchar[len+1]=0;
	}
}


void CObjectText::SetAuthorizedChars(char* newau)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::SetAuthorizedChars");
#endif
//***********************************
	
	if (TEXTauthorizedChars!=NULL)
		free(TEXTauthorizedChars);

	if (newau==NULL)
		TEXTauthorizedChars=NULL;
	else
	{
		TEXTauthorizedChars=(char *)malloc(sizeof(char)*(strlen(newau)+1));
		strcpy(TEXTauthorizedChars,newau);
	}
}


void CObjectText::SetClickValidation(int val)
{
	TEXTclickvalidation=val;
}


void CObjectText::SetPositionCursorAndScroll(int scrolltype,int suppress,int p_tab)
{
	0;
}


int CObjectText::IsMouseOnObject(int x,int y, int p_tab)
{
	return 1;
}


int CObjectText::CursorMove(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}


int CObjectText::CursorMoveIn(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::CursorMoveInWithBtnPushed(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::CursorMoveOut(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::CursorMoveOutWithBtnPushed(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::CursorMoveOutsideWithBtnPushed(int x,int y,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::ClickIn(int x,int y,int btn,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::UnClickIn(int x,int y,int btn,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}
	
int CObjectText::ClickOut(int x,int y,int btn,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::UnClickOut(int x,int y,int btn,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::DblClickIn(int x,int y,int btn,int keyFlags, int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::MouseWheel(int delta,int x,int y,int keyFlags,int p_tab,int redrawobject)
{
	return 0;
}

int CObjectText::KeyUp(UINT vk,int cRepeat, UINT flags, int p_tab)
{
	return 0;
}

int CObjectText::KeyDown(UINT vk,int keysys,int cRepeat, UINT flags, int p_tab)
{
	return 0;
}

int CObjectText::SetFocus(int reset,int p_tab,int redraw)
{
	return 0;
}

int CObjectText::KillFocus(int p_tab,int redraw)
{
	return 0;
}

int CObjectText::Timer( int timerID )
{
	return 0;
}


Layer *CObjectText::GetLayer(mmachine m,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GetLayer");
#endif
//***********************************

	if (ObjLayer==NULL) return NULL;
	
	ObjLayer->sourceRect = Rect2D(0,0,ObjW-1,ObjH-1);
	return ObjLayer;
}


Layer *CObjectText::GetLayerPart(mmachine m,Rect2D *paintrect,int p_tab)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::GetLayerPart");
#endif
//***********************************

	if (ObjLayer==NULL) return NULL;
	// on cherche quelle est la sous-bitmap de l'objet	
	ObjLayer->sourceRect = IntersectionRectangle(
									Rect2D	(
												0,
												0,
												ObjW,
												ObjH
											),
									*paintrect
								  );
	return ObjLayer;
}


int CObjectText::DestroyAllLayers()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::DestroyAllLayers");
#endif
//***********************************

	// on ne supprime que le layer principal
	if (ObjLayer!=NULL)	
	{
		ObjLayer->removeAllNext();
		delete(ObjLayer);
	}
	ObjLayer=NULL;
	return 0;
}


int CObjectText::ResizeLayer(int w,int h,int p_tab)
{	
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjectText::ResizeLayer");
#endif
//***********************************


	// check si il y a la place pour au moins un charactere
	int cw,ch;
	TEXTtexte->GetStringWidthHeight(0,1,1,&cw,&ch);
	if (cw>=w)
		return 0;

	// modification de la taille du texte
	TEXTtexte->ChangeWrapSize(w);
	ObjLayer=new Layer( w, h, TEXTtransp, TEXTtexttransp!=255 );
	if (ObjLayer!=NULL && TEXTtexttransp!=255 && ObjLayer->AlphaBitmap!=NULL)
		ObjLayer->fillAlphaLayer (TEXTtexttransp);

	// evaluation du nouveau nombre de lignes
	int oldvisible=TEXTnbVisibleSubLines;
	TEXTnbVisibleSubLines=h/TEXTcyChar;
	int diffcount=oldvisible-TEXTnbVisibleSubLines;
	
	// augmentation du nombre d'elts visible -> possibilité de
	// repositionnement de la premiere ligne visible
	if (diffcount<0 && TEXTtexte->getNbLines()>TEXTnbVisibleSubLines)
	{
		int diff=TEXTFirstVisibleSubLine+TEXTnbVisibleSubLines-TEXTtexte->getNbLines();
		if (diff>0)
			SetFirstVisibleLine(TEXTFirstVisibleSubLine-diff,p_tab,0);
	}
	InitLinkedScrollBar(TEXTFirstVisibleSubLine);
	return 0;
}


int CObjectText::CanBeActiveObject()
{
	return 1;
}


int ValidHeightForControl(int p_font,int h)
{
	int res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nValidHeightForControl");
#endif
//***********************************

	CObjLayerFont* layerfont=Lib2dFontService.getLayerFont(GET_PTR_OBJ_FONT(p_font));
	if (layerfont->CLFaverageCharHeight>h)
		res=0;
	else
		res=1;
	Lib2dFontService.delLayerFont(layerfont);
	return res;
}


// FONCTIONS SCOL
int _CRcompText(mmachine m)
{
	int shadowflag,shadowcolor,transparency,tmp_res,textcolor,textcoefftransp;
	int p_font,flags_creation,flags_handler,p_objpere,p_container,p_slidebarh;
	int p_coordinates,p_texte,x,y,w,h;
	int p_select,p_shadow;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_CRcompText");
#endif
//***********************************

	CObjectBase *obj_root,*obj_father,*new_object;

	container * co;
	char * texte;
	int select_color,coeff_transp;

	// les differents tests de non validité
	if ((MMget(m,13))==NIL)
	{
		MMechostr(MSKTRACE,"_CRcompText: channel is nil\n");
		m->pp += 13;
		MMset(m,0,NIL);
		return 0;	
	}
	if ((MMget(m,12))==NIL)
	{
		MMechostr(MSKTRACE,"_CRcompText: container is nil\n");
		m->pp += 13;
		MMset(m,0,NIL);
		return 0;
	}

#if DEBUG_OBJNODE
		MMechostr(MSKTRACE,"DEBUG_OBJNODE _CRcompText\n");
#endif

	// pile : Chn ObjContainer ObjNode Coordinates FlagsCreation FlagsHandler w h text ObjFont TextParam SelectParam AlphaV AlphaH
		
	// on inverse les infos de slidebar vertical et les flags de creation
	INVERT( m, 1, 9 );
	// on inverse les infos de slidebar horizontal et les coordonnees
	INVERT( m, 0, 10 );

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  FlagsHandler w h text ObjFont TextParam SelectParam FlagsCreation Coordinates
	// les coordonnées
	if ((p_coordinates=MTOP(MMpull(m)))==NIL)
	{
		x=0;
		y=0;
	}
	else
	{
		x=MTOI(MMfetch(m,p_coordinates,0));
		y=MTOI(MMfetch(m,p_coordinates,1));
	}

	if ((flags_creation=MTOI(MMpull(m)))==NIL) flags_creation=OBJ_ENABLE|OBJ_VISIBLE;

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  FlagsHandler w h text ObjFont TextParam SelectParam
	
	// la selection dans l'edit text
	if ((p_select=MTOP(MMpull(m)))==NIL)
	{
		coeff_transp=127;
		select_color=0+(0<<8)+(255<<16);
	}
	else
	{
		if ((select_color=MTOI(MMfetch( m, p_select, 0 )))==NIL) select_color=0+(0<<8)+(255<<16);
		
		if ((coeff_transp=MTOI(MMfetch( m, p_select, 1 )))==NIL) coeff_transp=50;
		if ( coeff_transp<0 || coeff_transp>100) 
		{
			MMechostr(MSKTRACE,"_CRcompText: Transparence coefficient for selection must be in [0;100] range\n");
			m->pp += 10;
			MMset(m,0,NIL);
			return 0;
		}
		else
			coeff_transp=255*(100-coeff_transp)/100;
		
	}
	
	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  FlagsHandler w h text ObjFont TextParam
	// l'ombre
	if ((p_shadow=MTOP(MMpull(m)))==NIL)
	{
		shadowcolor=0;
		shadowflag =0;
		textcoefftransp=255;
		textcolor  =255+(255<<8)+(255<<16);
	}
	else
	{
		if ((textcolor		=MTOI(MMfetch( m, p_shadow, 0 )))==NIL) textcolor  =0;
		if ((textcoefftransp=MTOI(MMfetch( m, p_shadow, 1 )))==NIL) textcoefftransp=0;
		if ( textcoefftransp<0 || textcoefftransp>100) 
		{
			MMechostr(MSKTRACE,"_CRcompText: Transparence coefficient for text color must be in [0;100] range\n");
			m->pp += 9;
			MMset(m,0,NIL);
			return 0;
		}
		else
			textcoefftransp=255*(100-textcoefftransp)/100;

		if ((shadowflag =MTOI(MMfetch( m, p_shadow, 2 )))==NIL) shadowflag =0;
		if ((shadowcolor=MTOI(MMfetch( m, p_shadow, 3 )))==NIL) shadowcolor=0;
	}

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  FlagsHandler w h text ObjFont
	// on inverse font et flags_handler
	INVERT( m, 0, 4 );

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  ObjFont w h text FlagsHandler
	if ((flags_handler=MTOI(MMpull(m)))==NIL)  flags_handler =0;

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  ObjFont w h text
	if ((p_texte=MTOP(MMpull(m)))==NIL)
	{
		//$BLG
		MMechostr(0,"STR EMPTY\n");
		texte=(char *)malloc(sizeof(char)*2);
		strcpy(texte,"");
	}
	else
	{
		int len=MMsizestr(m,p_texte);
		texte=(char *)malloc(sizeof(char)*(len+1));
		memcpy(texte,MMstartstr(m,p_texte),len+1);
		//$BLG
		MMechostr(0,"STR: %s\n",texte);
	}

	// pile : Chn ObjContainer ObjNode AlphaH AlphaV  ObjFont w h
	// on recupere la largeur et la hauteur 
	if ((h=MTOI(MMpull(m)))==NIL) h=0;
	if ((w=MTOI(MMpull(m)))==NIL) w=0;
	
	transparency = getDifferentColor(2, textcolor, shadowcolor );

	// pile: Chn ObjContainer ObjNode infos_slidebarh infos_slidebarv ObjFont

	// le Chn
	CHECK( MMpush( m, MMget( m, 5 ) ) );
	// on inverse Chn et ObjFont
	INVERT( m, 0, 1 );
	
	// pile: Chn ObjContainer ObjNode infos_slidebarh infos_slidebarv Chn ObjFont

	// le container et le pere
	p_objpere=MTOP(MMget(m,4));
	p_container=MTOP(MMget(m,5));
	p_font = MTOP( MMget( m, 0 ) );
	obj_father=GetObjectBase(m,p_objpere);
	if ((p_objpere!=NIL)&&(obj_father==NULL))
	{
		MMechostr(MSKTRACE,"_CRcompText: object father already destroyed\n");
		m->pp += 6;
		MMset(m,0,NIL);
	}
	else if ((co=RetrievePtrContainer(m,p_container))==NULL)
	{
		MMechostr(MSKTRACE,"_CRcompText: container already destroyed\n");
		m->pp += 6;
		MMset(m,0,NIL);
	}
	else if (!co->OwnsObject(obj_father))
	{
		MMechostr(MSKTRACE,"_CRcompText: father object was not created in this container!\n");
		m->pp += 6;
		MMset(m,0,NIL);
		return 0;
	}
	else if (!ValidHeightForControl(p_font,h))
	{
		MMechostr(MSKTRACE,"_CRcompText: creation failed :control texte height is not big enough for the font you choosed\n");
		m->pp += 6;
		MMset(m,0,NIL);
	}
	else
	{
		// evaluation de l'Image
		
		Layer *layer = new Layer( w, h, transparency, textcoefftransp!=255 );

		obj_root=co->Root();
		
		// creation du nouvel objet
		if (flags_creation&CT_MULTIEDITLINE)
			new_object=new CObjectEditText(co,layer,x,y,w,h,flags_creation,flags_handler,transparency,p_font,textcolor,textcoefftransp,shadowflag,shadowcolor,texte,"",select_color,coeff_transp);
		else if (flags_creation&CT_EDITLINE)
		{
			char *temp;
			temp=(char *)malloc(sizeof(char)*2);
			temp[0]='\r';
			temp[1]=0;
			new_object=new CObjectEditText(co,layer,x,y,w,h,flags_creation,flags_handler,transparency,p_font,textcolor,textcoefftransp,shadowflag,shadowcolor,texte,temp,select_color,coeff_transp);
			free(temp);
		}
		else if (flags_creation&CT_LABEL && flags_creation&CT_SELECT)
		{
			flags_creation-=CT_LABEL;
			flags_creation|=CT_MULTIEDITLINE;
			new_object=new CObjectLabelSelect(co,layer,x,y,w,h,flags_creation,flags_handler,transparency,p_font,textcolor,textcoefftransp,shadowflag,shadowcolor,texte,"",select_color,coeff_transp);
		}
		else
			new_object=new CObjectLabel(co,layer,x,y,w,h,flags_creation,flags_handler,transparency,p_font,textcolor,textcoefftransp,shadowflag,shadowcolor,texte,"");
		// ajout de l'objet et creation du nouvel OBJNODE
		
		// ajout de l'edit dans l'arbre
		CHECK( MMpush(m,NIL) );
		CHECK( MMpush(m,NIL) );
		CHECK( AddNode(m,obj_root,obj_father,(CObjectBase*)new_object,3) );

		// pile: Chn ObjContainer ObjNode infos_slidebarh infos_slidebarv new_object
		// on ecrase l'ancien ObjNode avec le nouveau
		MMset( m, 3, MMget( m, 0 ) );
		MMpull( m );

		// pile: Chn ObjContainer new_object infos_slidebarh infos_slidebarv

#if DEBUG_OBJNODE
	PrintTree(m,0,FindObjNodeFromHdlSys(m,(int)obj_root));
#endif
		// Construction du slide_bar vertical
		if ( MTOP( MMget( m, 0 ) ) != NIL ) 
		{
			CHECK(CreateLinkedScrollBar(m,4,flags_handler,SLB_VERTICAL,1));
			int p_tab=GetTab(m,MTOP(MMget(m,3)));
			MMstore(m,p_tab,SLIDE_V,MMpull(m));
		}
		
		// pile : Chn ObjContainer new_object infos_slidebarh infos_slidebarv
		MMpull(m);
		
		// pile: Chn ObjContainer new_object infos_slidebarh 
		
		// Construction du slide_bar horizontal
		if ( (p_slidebarh=MTOP( MMget( m, 0 ) )) != NIL && (flags_creation&CT_WORDWRAP) )
			MMechostr(MSKTRACE,"_CRcomptext: comptext is in wordwrap comportement and the horizontal slidebar is not nil => horizontal slidebar is not created\n");
		else if ( p_slidebarh != NIL && !(flags_creation&CT_WORDWRAP) )
		{
			CHECK(CreateLinkedScrollBar(m,3,flags_handler,SLB_HORIZONTAL,1));
			int p_tab=GetTab(m,MTOP(MMget(m,2)));
			MMstore(m,p_tab,SLIDE_H,MMpull(m));
		}
		// pile: Chn ObjContainer new_object infos_slidebarh 
		MMpull(m);
		
		// pile: Chn ObjContainer new_object
		
		INVERT( m, 0, 2 );
		MMpull( m );
		MMpull( m );
		
		(static_cast <CObjectText *> (new_object))->InitLinkedScrollBar(0);

	}
	free(texte);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_CRcompText end");
#endif
//***********************************

	return 0;
}


int _DScompText(mmachine m)
{
	int p,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_DScompText");
#endif
//***********************************

	if ((p=MTOP(MMpull(m)))!=NIL)
	{
		DsNode(m,p);
		CHECK(MMpush(m,MTOI(0)));		
	}
	else
		CHECK(MMpush(m,NIL));
	return 0;
}


int _CONVERTcompTextToObjNode(mmachine m)
{
	return 0;
}


int _SETcompText(mmachine m)
{
	char * texte;
	int p_texte,p_obj,p_char,p_font,scrolltype;
	int textcolor,coefftransp,shadowflag,shadowcolor;
	PtrObjFont  font;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_SETcompText");
#endif
//***********************************

	if ((scrolltype=MTOI(MMpull(m)))==NIL) scrolltype=CT_NOCHANGE;
	
	if ((p_char=MTOP(MMpull(m)))==NIL)
	{
		shadowcolor=0;
		shadowflag =0;
		coefftransp=0;
		textcolor=255+(255<<8)+(255<<16);
	}
	else
	{
		if ((textcolor	=MTOI(MMfetch( m, p_char, 0 )))==NIL) textcolor  =0;
		if ((coefftransp=MTOI(MMfetch( m, p_char, 1 )))==NIL) coefftransp=0;
		if ( coefftransp<0 || coefftransp>100) 
		{
			MMechostr(MSKTRACE,"_SETcompText: Transparence coefficient for text color must be in [0;100] range\n");
			m->pp += 9;
			MMset(m,0,NIL);
			return 0;
		}
		else
			coefftransp=255*(100-coefftransp)/100;

		if ((shadowflag =MTOI(MMfetch( m, p_char, 2 )))==NIL) shadowflag =0;
		if ((shadowcolor=MTOI(MMfetch( m, p_char, 3 )))==NIL) shadowcolor=0;
	}

	if ((p_font=MTOP(MMpull(m)))==NIL) font=NULL;
	else font=GET_PTR_OBJ_FONT(p_font);

	// on recupere le texte
    if ((p_texte=MTOP(MMpull(m)))==NIL)
	{
		texte=(char *)malloc(sizeof(char)*2);
		strcpy(texte,"");
	}
	else
	{
		int len=MMsizestr(m,p_texte);
		texte=(char *)malloc(sizeof(char)*(len+1));
		memcpy(texte,MMstartstr(m,p_texte),len+1);
	}

	if ((p_obj=MTOP(MMget(m,0)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_SETcompText: Object already destroyed.\n");
		else
		{
			int p_tab;	
			if ((p_tab=GetTab(m,p_obj))!=NIL)
				(static_cast <CObjectText *> (obj))->SetText(texte,font,textcolor,coefftransp,shadowflag,shadowcolor,scrolltype,p_tab);
		}
	}
	free(texte);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_SETcompText end");
#endif
//***********************************

	return 0;
		
}


int _ADDcompText(mmachine m)
{
	int p_texte;
	char * texte;
	int p_font,p_char,p_obj,scrolltype;
	int textcolor,coefftransp,shadowflag,shadowcolor;
	PtrObjFont  font;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_ADDcompText");
#endif
//***********************************

	if ((scrolltype=MTOI(MMpull(m)))==NIL) scrolltype=CT_NOCHANGE;
	

	if ((p_char=MTOP(MMpull(m)))==NIL)
	{
		shadowcolor=0;
		shadowflag =0;
		coefftransp=0;
		textcolor=255+(255<<8)+(255<<16);
	}
	else
	{
		if ((textcolor	=MTOI(MMfetch( m, p_char, 0 )))==NIL) textcolor  =0;
		if ((coefftransp=MTOI(MMfetch( m, p_char, 1 )))==NIL) coefftransp=0;
		if ( coefftransp<0 || coefftransp>100) 
		{
			MMechostr(MSKTRACE,"_SETcompText: Transparence coefficient for text color must be in [0;100] range\n");
			m->pp += 9;
			MMset(m,0,NIL);
			return 0;
		}
		else
			coefftransp=255*(100-coefftransp)/100;

		if ((shadowflag =MTOI(MMfetch( m, p_char, 2 )))==NIL) shadowflag =0;
		if ((shadowcolor=MTOI(MMfetch( m, p_char, 3 )))==NIL) shadowcolor=0;
	}

	if ((p_font=MTOP(MMpull(m)))==NIL) font=NULL;
	else font=GET_PTR_OBJ_FONT(p_font);


	// on recupere le texte
    if ((p_texte=MTOP(MMpull(m)))==NIL)
	{
		texte=(char *)malloc(sizeof(char)*2);
		strcpy(texte,"");
	}
	else
	{
		char * temp;
		int len=MMsizestr(m,p_texte);
		temp=(char *)malloc(sizeof(char)*(len+1));
		memcpy(temp,MMstartstr(m,p_texte),len+1);
		texte=ReplaceRnByR(temp);
		free(temp);
	}
	
	if ((p_obj=MTOP(MMget(m,0)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_SETcompText: Object already destroyed.\n");
		else
		{
			int p_tab;	
			if ((p_tab=GetTab(m,p_obj))!=NIL)
				(static_cast <CObjectText *> (obj))->AddText(texte,font,textcolor,coefftransp,shadowflag,shadowcolor,scrolltype,p_tab);
		}
	}
	free(texte);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_ADDcompText end");
#endif
//***********************************

	return 0;
}


int _GETcompText(mmachine m)
{
	int p_obj,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompText");
#endif
//***********************************

	if ((p_obj=MTOP(MMpull(m)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
		{
			MMechostr(MSKTRACE,"_GETcompText: Object already destroyed.\n");
			CHECK(MMpush(m,NIL));
		}
		else
		{
			int p;
			char *p_c;
			char *txt=ReplaceRByN((static_cast <CObjectText *> (obj))->GetText());
			int len=strlen(txt);
			if ((p=MMmalloc(m,STR_SIZE(len),TYPEBUF))<0) return p;
			MMstore(m,p,0,len);
			p_c=MMstartstr(m,p);
			memcpy(p_c,txt,len);
			p_c[len]=0;
			CHECK(MMpush(m,PTOM(p)));
			free(txt);
		}
	}
	else
	{
			MMechostr(MSKTRACE,"_GETcompText: CompText is nil.\n");
			CHECK(MMpush(m,NIL));
	}	

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompText");
#endif
//***********************************

	return 0;
}


int _GETcompTextLine(mmachine m)
{
	int p_obj,tmp_res;
	int ligne;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompTextLine");
#endif
//***********************************

	if ((p_obj=MTOP(MMget(m,1)))==NIL)
	{
		MMechostr(MSKTRACE,"_GETcompTextLine: CompText is nil.\n");
		m->pp += 1;
		MMset(m,0,NIL);
		return 0;	
	}
	
	if ((ligne=MTOI(MMpull(m)))==NIL) ligne=0;
	
	CObjectBase *obj;
	p_obj=MTOP(MMpull(m));
	
	// on recupere l'objet
	if ((obj=GetObjectBase(m,p_obj))==NULL)
	{
		MMechostr(MSKTRACE,"_GETcompTextLine: Object already destroyed.\n");
		CHECK(MMpush(m,NIL));
	}
	else
	{
		int p;
		char *p_c;
		char *txt_tmp,*txt;
		if ((txt_tmp=(static_cast <CObjectText *> (obj))->GetLine(ligne))!=NULL)
		{
			txt=ReplaceRByN(txt_tmp);
			free(txt_tmp);

			int len=strlen(txt);
			if ((p=MMmalloc(m,STR_SIZE(len),TYPEBUF))<0) return p;
			MMstore(m,p,0,len);
			p_c=MMstartstr(m,p);
			memcpy(p_c,txt,len);
			p_c[len]=0;
			CHECK(MMpush(m,PTOM(p)));
			free(txt);
		}
		else
			CHECK(MMpush(m,NIL));
	}

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompTextLine end");
#endif
//***********************************

	return 0;
}


int _GETcompTextLineCount(mmachine m)
{
	int p_obj,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompTextLineCount");
#endif
//***********************************

	if ((p_obj=MTOP(MMpull(m)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
		{
			MMechostr(MSKTRACE,"_GETcompTextLineCount: Object already destroyed.\n");
			CHECK(MMpush(m,NIL));
		}
		else
			CHECK(MMpush(m,ITOM((static_cast <CObjectText *> (obj))->GetLineCount())));
	}
	else
	{
			MMechostr(MSKTRACE,"_GETcompTextLineCount: CompText is nil.\n");
			CHECK(MMpush(m,NIL));
	}	
	return 0;
}


int _GETcompTextFirstLine(mmachine m)
{
	int p_obj,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_GETcompTextFirstLine");
#endif
//***********************************

	if ((p_obj=MTOP(MMpull(m)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
		{
			MMechostr(MSKTRACE,"_GETcompTextFirstLine: Object already destroyed.\n");
			CHECK(MMpush(m,NIL));
		}
		else
			CHECK(MMpush(m,ITOM((static_cast <CObjectText *> (obj))->GetFirstVisibleLine())));
	}
	else
	{
			MMechostr(MSKTRACE,"_GETcompTextFirstLine: CompText is nil.\n");
			CHECK(MMpush(m,NIL));
	}	
	return 0;
}


int _SETcompTextFirstLine(mmachine m)
{
	int p_obj,line;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_SETcompTextFirstLine");
#endif
//***********************************
	
	if ((line=MTOI(MMpull(m)))==NIL) line=0;

	if ((p_obj=MTOP(MMget(m,0)))!=NIL)
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_SETcompTextFirstLine: Object already destroyed.\n");
		else
		{
			int p_tab;	
			if ((p_tab=GetTab(m,p_obj))!=NIL)
				(static_cast <CObjectText *> (obj))->SetFirstVisibleLine(line,p_tab,1);
		}
	}
	else
		MMechostr(MSKTRACE,"_SETcompTextFirstLine: CompText is nil.\n");
	return 0;
}


int _DELcompTextLine(mmachine m)
{
	int p_obj;
	int ligne,scrolltype;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_DELcompTextLine");
#endif
//***********************************

	if ((scrolltype=MTOI(MMpull(m)))==NIL) scrolltype=CT_NOCHANGE;

	if ((ligne=MTOI(MMpull(m)))==NIL) ligne=0;
	
	if ((p_obj=MTOP(MMget(m,0)))==NIL)
		MMechostr(MSKTRACE,"_DELcompTextLine: CompText is nil.\n");
	else
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_DELcompTextLine: Object already destroyed.\n");
		else
		{
			int p_tab;	
			if ((p_tab=GetTab(m,p_obj))!=NIL)
				(static_cast <CObjectText *> (obj))->DelLine(scrolltype,ligne,p_tab);
		}
	}
	return 0;
}


int _SETcompTextForbiddenChar(mmachine m)
{
	int p_obj,p_forbiddenchar;
	char *forbiddenchar;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_SETcompTextForbiddenChar");
#endif
//***********************************

	if ((p_forbiddenchar=MTOP(MMpull(m)))==NIL)
	{
		forbiddenchar=(char *)malloc(sizeof(char)*2);
		strcpy(forbiddenchar,"");
	}
	else
	{
		int len=MMsizestr(m,p_forbiddenchar);
		forbiddenchar=(char *)malloc(sizeof(char)*(len+1));
		memcpy(forbiddenchar,MMstartstr(m,p_forbiddenchar),len+1);
	}
	
	if ((p_obj=MTOP(MMget(m,0)))==NIL)
		MMechostr(MSKTRACE,"_SETcompTextForbiddenChar: CompText is nil.\n");
	else
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_SETcompTextForbiddenChar: Object already destroyed.\n");
		else
			(static_cast <CObjectText *> (obj))->SetForbiddenChar(forbiddenchar);
	}
	free(forbiddenchar);
	return 0;
}


int _SETcompTextAuthorizedChar(mmachine m)
{
	int p_obj,p_auchar;
	char *auchar;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_SETcompTextAuthorizedChar");
#endif
//***********************************

	if ((p_auchar=MTOP(MMpull(m)))==NIL)
		auchar=NULL;
	else
	{
		int len=MMsizestr(m,p_auchar);
		auchar=(char *)malloc(sizeof(char)*(len+1));
		memcpy(auchar,MMstartstr(m,p_auchar),len+1);
	}
	
	if ((p_obj=MTOP(MMget(m,0)))==NIL)
		MMechostr(MSKTRACE,"_SETcompTextAuthorizedChar: CompText is nil.\n");
	else
	{
		CObjectBase *obj;
		// on recupere l'objet
		if ((obj=GetObjectBase(m,p_obj))==NULL)
			MMechostr(MSKTRACE,"_SETcompTextAuthorizedChar: Object already destroyed.\n");
		else
			(static_cast <CObjectText *> (obj))->SetAuthorizedChars(auchar);
	}
	if (auchar!=NULL)
		free(auchar);
	return 0;
}


// RFL


int rflcompTextChange(mmachine m)
{
	return OBJaddreflex(m,OBJNODE,RFLOBJNODE_CHANGE);
}


int rflcompTextValidation(mmachine m)
{
	int res,p_obj,validation; 
	CObjectBase *obj;
	res=0;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nrflcompTextValidation");
#endif
//***********************************

	if ( (validation=MTOI(MMpull(m)))!=NIL && (p_obj=MTOP(MMget(m,2)))!=NIL && (obj=GetObjectBase(m,p_obj))!=NULL)
	{
		(static_cast <CObjectText *> (obj))->SetClickValidation(validation);
		res=OBJaddreflex(m,OBJNODE,RFLOBJNODE_VALIDATION);
	}
	else
	{
		MMpull(m);
		MMpull(m);
		res=0;
	}
	return res;
}


int _CBcompTextResizeResource(mmachine m)
{
	int p_obj,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_CBcompTextResizeResource");
#endif
//***********************************

	if ((p_obj=MTOP(MMget(m,4)))==NIL)
	{
		MMechostr(1,"_CBcompTextResizeResource: CompText is nil\n");
		m->pp += 4;
		MMset(m,0,NIL);
	}
	else if (GetObjectBase(m,p_obj)==NULL)
	{
		MMechostr(1,"_CBcompTextResizeResource: CompText already destroyed\n");
		m->pp += 4;
		MMset(m,0,NIL);
	}
	else
	{
		// pile  CompText fun1 p1 fun2 p2
		int p_tab=GetTab(m,p_obj);
		CHECK(MMpush(m,MMfetch(m,p_tab,SLIDE_H)));
		INVERT(m,0,1);
		INVERT(m,1,2);
		// pile CompText fun1 p1 slb2 fun2 p2
		CHECK(_CBcompSlideBarResizeResource(m));
		MMpull(m);

		//pile CompText fun1 p1
		p_tab=GetTab(m,MTOP(MMget(m,2)));
		CHECK(MMpush(m,MMfetch(m,p_tab,SLIDE_V)));
		INVERT(m,0,1);
		INVERT(m,1,2);
		CHECK(_CBcompSlideBarResizeResource(m));
		MMpull(m);
		
		//pile CompText
	}
	return 0;
}


int _CBcompTextResize(mmachine m)
{
	int p_obj,tmp_res;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\n_CBcompTextResize");
#endif
//***********************************

	if ((p_obj=MTOP(MMget(m,6)))==NIL)
	{
		MMechostr(1,"_CBcompTextResize: CompText is nil\n");
		m->pp += 6;
		MMset(m,0,NIL);
	}
	else if (GetObjectBase(m,p_obj)==NULL)
	{
		MMechostr(1,"_CBcompTextResize: CompText already destroyed\n");
		m->pp += 6;
		MMset(m,0,NIL);
	}
	else
	{
		// pile  CompText fun1 p1 fun2 p2 fun3 u3
		int p_tab=GetTab(m,p_obj);
		CHECK(MMpush(m,MMfetch(m,p_tab,SLIDE_H)));
		INVERT(m,0,1);
		INVERT(m,1,2);
		
		// pile CompText fun1 p1 slb fun2 p2
		CHECK(_CBcompSlideBarResize(m));
		MMpull(m);
		
		//pile CompText fun1 p1 fun2 p2
		p_tab=GetTab(m,MTOP(MMget(m,4)));
		CHECK(MMpush(m,MMfetch(m,p_tab,SLIDE_V)));
		INVERT(m,0,1);
		INVERT(m,1,2);
		
		// pile CompText fun1 p1 slb fun2 p2
		CHECK(_CBcompSlideBarResize(m));
		MMpull(m);
		
		return OBJaddreflex(m,OBJNODE,RFLOBJNODE_RESIZE);
	}
	return 0;
}
