#include "Text.h"
#include <Tchar.h>
#include "../x/Version.h"
#include "../x/scolplugin.h"




BOOL _InitDBCS()
{
	CPINFO info;
	GetCPInfo(GetOEMCP(), &info);
	return info.MaxCharSize > 1;
}

const BOOL _DBCS = _InitDBCS();



////////////////////////////////////////////////////////////////////////////////////////////////////////
//							        CLASSE TEXTE												      //
////////////////////////////////////////////////////////////////////////////////////////////////////////
Text::Text(char *texte,int wrap,int cx)
{
	// texte wrappé
	TILwrap=wrap;
	TILcx=cx;

	// longeur du texte
	TILtexte=NULL;
	TILlen=0;

	// le tableau des Infos
	TILsubline=(InfoLine *)malloc(sizeof(InfoLine)*1);
	TILsize=1;
	TILmaxstringw=0;
	TILhtexte=0;

	TILsubline->first=0;
	TILsubline->nCount=0;
	TILsubline->ndx=0;
	TILsubline->stringw=0;
	TILsubline->stringh=0;		// sous ligne
	TILsubline->maxstringw=0;
	TILsubline->postop=0;
	TILsubline->posbaseline=0;
	
	SetText(texte,0);
}

Text::~Text()
{
	free(TILtexte);
	free(TILsubline);
	// on ne desalloue pas les layerfonts car il sont presents dans l'objets texte!!!
	// on ne stocke que les pointeurs
}

void Text::AssignValueToTab(unsigned int nIndexSubLine,
							unsigned int nIndex,
							unsigned int nCount,
							unsigned int nIndexLine,
							int width,
							int height,
							int posbaseline)
{
#if DEBUG_WRAP
	MMechostr(1,"Text::AssignValueToTab:%d %d\n",nIndexSubLine,height);
#endif

	if ((TILsize-1)<nIndexSubLine)
	{
		// besoin d'allouer une info supplementaire
		TILsubline=(InfoLine *)realloc(TILsubline,(nIndexSubLine+1)*sizeof(InfoLine));
		TILsize=nIndexSubLine+1;
	}
	TILsubline[nIndexSubLine].first=nIndex;
	TILsubline[nIndexSubLine].nCount=nCount;
	TILsubline[nIndexSubLine].ndx=nIndexLine;
	TILsubline[nIndexSubLine].stringw=width;
	TILsubline[nIndexSubLine].stringh=height;
	TILsubline[nIndexSubLine].postop=TILhtexte;
	TILsubline[nIndexSubLine].posbaseline=posbaseline;

	TILhtexte+=height;
	TILsubline[nIndexSubLine].maxstringw=TILmaxstringw=max(TILmaxstringw,width);
}


unsigned int Text::ClipLine(unsigned int nIndex,unsigned int nIndexEnd)
{
	// make an initial guess on the number of characters that will fit
	
	int cx = 0;
	int cy = 0;
	char * lpszStart = TILtexte + nIndex;
	char * lpszStop = TILtexte + nIndexEnd;
	char * lpsz = lpszStart;
	
	CObjLayerFont * font=GetLayerFont(nIndex);
	
	while (lpsz < lpszStop)
	{
		
		if (*lpsz == '\t')
			cx += font->CLFtabStop - (cx % font->CLFtabStop);
		else
		{
#ifdef _UNICODE
			if (*lpsz <= 0xFF)
				cx += font->CLFcharWidths[(BYTE)*lpsz];
			else
				cx += font->CLFaverageCharWidth;
#else //_UNICODE
			if (_DBCS && _istlead(*lpsz))
			{
				++lpsz;
				cx += font->CLFaverageCharWidth;
			}
			else
				cx += font->CLFcharWidths[(BYTE)*lpsz];
#endif //!_UNICODE
		}
		++lpsz;
		font=GetLayerFont(nIndex+(lpsz-lpszStart));
		if (cx > TILcx)
			break;
	}

	// adjust for errors in the guess
	GetStringWidthHeight(nIndex,lpsz-lpszStart,1,&cx,&cy);
	if (cx > TILcx)
	{
		// remove characters until it fits
		do
		{
			if (_DBCS)
				lpsz = _tcsdec(lpszStart, lpsz);
			else
				--lpsz;
			GetStringWidthHeight(nIndex, lpsz-lpszStart,1,&cx,&cy);
		} while (cx > TILcx);
	}
	else if (cx < TILcx)
	{
		// add characters until it doesn't fit
		while (lpsz < lpszStop)
		{
			lpsz = _tcsinc(lpsz);
			GetStringWidthHeight(nIndex, lpsz-lpszStart,1,&cx,&cy);
			if (cx > TILcx)
			{
				if (_DBCS)
					lpsz = _tcsdec(lpszStart, lpsz);
				else
					--lpsz;
				break;
			}
		}
	}
	
	// return index of character just past the last that would fit
	return lpsz - TILtexte;

}

int Text::WordWrap(unsigned int nIndexSubStart,unsigned int nIndexStop)
{
	int w,h,baseline;
	unsigned int ndxSubLine=nIndexSubStart;
	unsigned int ndxLine=TILsubline[ndxSubLine].ndx;
	unsigned int ndxFirst,nIndex;
	ndxFirst=nIndex=TILsubline[ndxSubLine].first;


#if DEBUG_WRAP
	MMechostr(MSKTRACE,"***********************> WordWrap <***************************\nIndexStart:%d %d\n",nIndex,ndxSubLine);
#endif

	
	if (nIndex>(unsigned int)TILlen)
	{
		TILsize=0;
		return TILlen;
	}

	if (nIndexStop>(unsigned int)TILlen) nIndexStop=TILlen;
	
	if (TILlen==0) TILsubline[0].nCount=0;
	
	if (nIndexSubStart==0)
	{
		TILmaxstringw=0;
		TILhtexte=0;
	}
	else
	{
		TILmaxstringw=TILsubline[ndxSubLine-1].maxstringw;
		TILhtexte=TILsubline[ndxSubLine-1].postop+TILsubline[ndxSubLine-1].stringh;
	}

	do
	{
		unsigned int nIndexEnd = EndOfLine(TILtexte, nIndexStop, nIndex);
#if DEBUG_WRAP
		MMechostr(1,"nIndex %d,nIndexEnd %d\n",nIndex,nIndexEnd);
#endif
		if (nIndex == nIndexEnd)
		{
			
#if DEBUG_WRAP
			MMechostr(1,"nIndex==nIndexEnd:%d\n",nIndex);
#endif
			baseline=GetStringWidthHeight(nIndex,1,1,&w,&h);
			AssignValueToTab(ndxSubLine,nIndex,0,ndxLine,0,h,baseline);
			ndxSubLine++;
		}
		else if(TILwrap) 
		{
#if DEBUG_WRAP
			MMechostr(1,"Wrap\n");
#endif
			do
			{
				unsigned int nIndexWrap = ClipLine(nIndex, nIndexEnd); 
				unsigned int nIndexWord = nIndexWrap;
				if (nIndexWord != nIndexEnd)
				{
					while (nIndexWord > nIndex &&
					  !_istspace(TILtexte[nIndexWord]))
					{
						nIndexWord--;
					}
					if (nIndexWord == nIndex)
						nIndexWord = nIndexWrap;
				}
				baseline=GetStringWidthHeight(nIndex,nIndexWord-nIndex,1,&w,&h);
				AssignValueToTab(ndxSubLine,nIndex,nIndexWord-nIndex,ndxLine,w,h,baseline);
				ndxSubLine++;
				nIndex = nIndexWord;
				
				while (nIndex < nIndexEnd && _istspace(TILtexte[nIndex]) && nIndex<nIndexWrap)
					nIndex++;
				
			} while (nIndex < nIndexEnd);
			nIndexEnd = nIndex;
		}
		else
		{
#if DEBUG_WRAP
			MMechostr(1,"No Wrap\n");
#endif
			baseline=GetStringWidthHeight(nIndex,nIndexEnd-nIndex,1,&w,&h);
			AssignValueToTab(ndxSubLine,nIndex,nIndexEnd-nIndex,ndxLine,w,h,baseline);
			ndxSubLine++;
			nIndex = nIndexEnd;
		}
		nIndex++;
		//nIndex = NextLine(string, nIndexStop, nIndexEnd);
		ndxLine++;		
	}while (nIndex < nIndexStop);
#if DEBUG_WRAP
	MMechostr(1,"ndxSubLine:%d\n",ndxSubLine);
#endif

	// on ajoute les characters de retour chariot en fin de chaine
	unsigned int i=TILsubline[ndxSubLine-1].first+TILsubline[ndxSubLine-1].nCount;
	while (i<nIndexStop)
	{
#if DEBUG_WRAP
		MMechostr(1,"%d\n",i);
#endif
		if (i==0 || (i!=0 && *(TILtexte+i) =='\r'))
		{
			baseline=GetStringWidthHeight(i,1,1,&w,&h);
			AssignValueToTab(ndxSubLine,i+1,0,ndxLine,0,h,baseline);
			ndxSubLine++;
			ndxLine++;
		}
		i++;
	}
	
	// on remet le tableau à la bonne taille
	if ((ndxSubLine>0)&&(ndxSubLine<TILsize))
	{
#if DEBUG_WRAP	
		MMechostr(1,"Realloc descendante\n");
#endif
		TILsubline=(InfoLine *)realloc(TILsubline,ndxSubLine*sizeof(InfoLine));
		TILsize=ndxSubLine;
	}
	Print();
	return 0;
}

unsigned int Text::SearchSubLineInTab(unsigned int nIndexStart)
{
	unsigned int i=-1;
	do	i++;
	while ((i<TILsize)&&(TILsubline[i].first<=nIndexStart));
	return i-1;
}


unsigned int Text::SearchIndexInTab(int xpos,int nIndex,int nIndexEnd)
{
	int cx=0;
	int cy;
	char * lpsz=TILtexte+nIndex;
	char * lpszStop = TILtexte + nIndexEnd;
	char * lpszStart= lpsz;
	CObjLayerFont * font=GetLayerFont(nIndex);
	
	if (xpos<0) return nIndex;

#if DEBUG_WRAP
	MMechostr(1,"Text::SearchIndexInTab:xpos:%d IndexStart:%d IndexEnd:%d\n",xpos,nIndex,nIndexEnd);
#endif

	while (lpsz<lpszStop)
	{
		if (*lpsz == '\t')
			cx += font->CLFtabStop - (cx % font->CLFtabStop);
		else
		{
#ifdef _UNICODE
			if (*lpsz <= 0xFF)
				cx += font->CLFcharWidths[(BYTE)*lpsz];
			else
				cx += font->CLFaverageCharWidth;
#else //_UNICODE
			if (_DBCS && _istlead(*lpsz))
			{
				++lpsz;
				cx += font->CLFaverageCharWidth;
			}
			else
				cx += font->CLFcharWidths[(BYTE)*lpsz];
#endif //!_UNICODE
		}
		++lpsz;
		font=GetLayerFont(nIndex+(lpsz-lpszStart));
		if (cx > xpos)
			break;
	}

	// adjust for errors in the guess
	GetStringWidthHeight(nIndex,lpsz-lpszStart,1,&cx,&cy);
	if (cx > xpos)
	{
		// remove characters until it fits
		do
		{
			if (_DBCS)
				lpsz = _tcsdec(lpszStart, lpsz);
			else
				--lpsz;
			GetStringWidthHeight(nIndex, lpsz-lpszStart,1,&cx,&cy);
		} while (cx > xpos);
	
		GetStringWidthHeight(nIndex,lpsz-lpszStart,1,&cx,&cy);
		if (xpos>cx+GetLayerFont(nIndex+(_tcsinc(lpsz)-lpszStart))->CLFcharWidths[(BYTE)*lpsz]/2)
		{
			if (_DBCS)
				lpsz=_tcsinc(lpsz);
			else
				lpsz++;
		}
	}
	
#if DEBUG_WRAP
	MMechostr(1,"End Text::SearchIndexInTab:res:%d\n",lpsz-TILtexte);
#endif

	return lpsz-TILtexte;
}

unsigned int Text::GetCharWidth(int nIndex)
{
	return GetLayerFont(nIndex)->CLFcharWidths[(BYTE)*(TILtexte+nIndex)];
}

// Renvoie l'index du charactere suivant
unsigned int Text::NextIndex(unsigned int nIndex)
{
	unsigned int res=nIndex;
#ifdef _UNICODE
	return ++res;
#else //_UNICODE
	if (_DBCS)
		res=_tcsinc(TILtexte+nIndex)-TILtexte;
	else
		res++;
	return res;
#endif //!_UNICODE
}

// Renvoie l'index du charactere precedant
unsigned int Text::PreviousIndex(unsigned int nIndex)
{
	unsigned int res=nIndex;
#ifdef _UNICODE
	return --res;	
#else //_UNICODE
	if (_DBCS)
		res=_tcsdec(TILtexte,TILtexte+nIndex)-TILtexte;
	else
		res--;
	return res;
#endif //!_UNICODE
}

// Renvoie le nombre de characters visibles dans la sous-ligne
// a laquelle appartient nIndex
int Text::NumberCharacterVisible(unsigned int ndxSubLine,unsigned int nIndex)
{
	int res=0;
	unsigned int first=TILsubline[ndxSubLine].first;
	unsigned int i=first;
	while (i<nIndex)
	{
		i=NextIndex(i);
		res++;
	}
	return res;
}

// Renvoie l'index pour lequel on a nbchars visible dans la sous-ligne ndxSubLine
unsigned int Text::IndexFromCharacterVisible(unsigned int ndxSubLine,int nbchars)
{
	int nb=0;
	unsigned int first=TILsubline[ndxSubLine].first;
	unsigned int end=first+TILsubline[ndxSubLine].nCount;
	unsigned int i=first;
	while (i<end && nb<nbchars)
	{
		i=NextIndex(i);
		nb++;
	}
	return i;
}

void Text::ChangeWrapSize(int newcx)
{
	TILcx=newcx;
	WordWrap(0,TILlen);
}

char *Text::getRealText()
{
	return TILtexte;
}

// Change le texte
void Text::SetText(char *newtext,int execwordwrap)
{
	if (TILtexte)
		free(TILtexte);
	TILtexte=ReplaceRnByR(newtext);
	TILlen=strlen(TILtexte);
	
	if (execwordwrap) WordWrap(0,TILlen);
}

// Ajoute du texte en fin de chaine Rem:le nouveau texte ne dois posseder aucun \n
void Text::AddText(char *newtext,int execwordwrap)
{
	int lennew=strlen(newtext);
	int len=TILlen;

	TILtexte=(char *)realloc(TILtexte,sizeof(char)*(len+lennew+1));
	memcpy(TILtexte+len,newtext,sizeof(char)*lennew);
	TILtexte[len+lennew]=0;
	TILlen=strlen(TILtexte);
	
	if (execwordwrap) WordWrap(0,TILlen);
}


// Coupe le texte au premier retour chariot trouve
int Text::CrunchText(int testclip)
{
	unsigned int end;
	if ((
			testclip
			&&
			(end=(int)ClipLine(0,TILlen))!=TILlen
		)||
		(end=EndOfLine(TILtexte,TILlen,0))!=TILlen
	   )
	{
#if DEBUG_OBJTEXT
		MMechostr(1,"Text::CrunchText:%d\n",end);
#endif
		TILtexte=(char *)realloc(TILtexte,sizeof(char)*(end+1));
		TILtexte[end]=0;
		TILlen=end;
		WordWrap(0,TILlen);
		return 1;
	}
	return 0;
}

// Insere le charactere vk à la position nIndex
void Text::InsertChar(int vk,int nIndex,int execwordwrap)
{

	// character insertion
	char *tmp=(char *)malloc(sizeof(char)*(TILlen+2));
	if (nIndex)
		memcpy(tmp,TILtexte,(sizeof(char)*(nIndex)));
	
	tmp[nIndex]=vk;
	
	memcpy(tmp+nIndex+1,TILtexte+nIndex,(sizeof(char)*(TILlen-nIndex+1)));
	
	free(TILtexte);
	TILtexte=tmp;
	
	TILlen=strlen(TILtexte);

	// on redecoupe le texte
	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen);
}

// Supprime le charactere à la position nIndex
void Text::DeleteChar(int nIndex,int execwordwrap)
{
	char *tmp=(char *)malloc(sizeof(char)*TILlen);
	
	// le texte
	memcpy(tmp,TILtexte,(sizeof(char)*nIndex));
	
	// les subchars
	memcpy(tmp+nIndex,TILtexte+nIndex+1,(sizeof(char)*(TILlen-nIndex)));
	
	free(TILtexte);
	TILtexte=tmp;
	TILlen=strlen(TILtexte);

	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen);
}

// Insere la sous-chaine à la posiiton nIndex
void Text::InsertSubString(char *string,int nIndex,int execwordwrap)
{
	int size=strlen(string);
			
			
	char *tmp=(char *)malloc(sizeof(char)*(TILlen+size+1));
	
	if (nIndex)
		memcpy(tmp,TILtexte,(sizeof(char)*nIndex));
	memcpy(tmp+nIndex,string,(sizeof(char)*size));
	
	memcpy(tmp+nIndex+size,TILtexte+nIndex,(sizeof(char)*(TILlen-nIndex+1)));

	free(TILtexte);
	TILtexte=tmp;
	TILlen=strlen(TILtexte);

	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen);
}

// Supprime la sous-chaine commencant à l'index nIndexStart comportant nCount characteres
int Text::DeleteSubString(int nIndexStart,int nIndexEnd,int execwordwrap)
{
	int len,res;
	if ((len=nIndexEnd-nIndexStart)>0)
	{
		char *tmp=(char *)malloc(sizeof(char)*(TILlen-len+1));
		if (nIndexStart)
			memcpy(tmp,TILtexte,(sizeof(char)*nIndexStart));
		memcpy(tmp+nIndexStart,TILtexte+nIndexEnd,(sizeof(char)*(TILlen-nIndexEnd+1)));
		
		free(TILtexte);
		TILtexte=tmp;
		TILlen=strlen(TILtexte);

		res=nIndexStart;

		if (execwordwrap)
			WordWrap(SearchSubLineInTab(nIndexStart),TILlen);
	}
	else
		res=-1;

	return res;
}

#if DEBUG_WRAP
void Text::Print()
{
	int i=0;
	MMechostr(1,"TEXTNORMAL-------------------------------------\nTabSize:%d MaxStringSize:%d\n",TILsize,TILmaxstringw);
	while (i<(int)(TILsize))
	{
		int first=TILsubline[i].first;
		int nCount=TILsubline[i].nCount;
		char *tmp;
		tmp=(char *)malloc(sizeof(char)*(nCount+1));
		memcpy(tmp,TILtexte+first,sizeof(char)*(nCount));
		tmp[nCount]='\0';
		MMechostr(MSKTRACE,"First et Ndx Sous Chaine[%d]:f:%d-c:%d-index:%d-w:%d-h:%d-maxw%d-htexte:%d\nChaine:%s*\n"
				  ,i,
				  TILsubline[i].first,
				  TILsubline[i].nCount,
				  TILsubline[i].ndx,
				  TILsubline[i].stringw,
				  TILsubline[i].stringh,
				  TILsubline[i].maxstringw,
				  TILsubline[i].postop,
				  tmp);
		free(tmp);
		i++;
	}
}
#else
void Text::Print()
{
}
#endif







////////////////////////////////////////////////////////////////////////////////////////////////////////
//							        CLASSE TEXTE MONO FONT											  //
////////////////////////////////////////////////////////////////////////////////////////////////////////

TextMonoFont::TextMonoFont(char *texte,
						   CObjLayerFont *layerfont,
						   int textcolor,
						   int shadowflag,
						   int shadowcolor,
						   int coefftransp,
						   int wrap,
						   int cx)
						   :Text(texte,wrap,cx)

{
	TMOFfont=layerfont;
	TMOFtextcolor=textcolor;
	TMOFcoefftransp=coefftransp;
	TMOFshadowflag=shadowflag;
	TMOFshadowcolor=shadowcolor;

	WordWrap(0,TILlen);
}

TextMonoFont::~TextMonoFont()
{
	//Lib2dFontService.delLayerFont(TMOFfont);
}

int TextMonoFont::GetStringWidthHeight(int nStart,int nCount,int usetab,int *w,int *h)
{
	*w=TMOFfont->GetStringWidth(TILtexte+nStart,nCount,usetab);
	*h=TMOFfont->CLFaverageCharHeight;
	return TMOFfont->CLFascent;
}

CObjLayerFont * TextMonoFont::GetLayerFont(int nIndex)
{
	return TMOFfont;
}

int TextMonoFont::DrawSubString(Layer *layer,int x,int y,int Flags,int IndexSubString)
{
	int first=TILsubline[IndexSubString].first;
	int count=TILsubline[IndexSubString].nCount;
	
	//MMechostr(1,"Redessine sous-ligne[%d]:x:%d y:%d\n",IndexSubString,x,y);
	if (TMOFshadowflag>0 && TMOFcoefftransp==255)
		TMOFfont->CopyStringOnLayer(layer,x+TMOFshadowflag,y+TMOFshadowflag,TILtexte+first,count,TMOFshadowcolor,0,1,0);
	TMOFfont->CopyStringOnLayer(layer,x,y,TILtexte+first,count,TMOFtextcolor,0,1,0);
	
	return TMOFfont->CLFaverageCharHeight;
}

int	TextMonoFont::GetTextColor(int nIndex)
{
	return TMOFtextcolor;
}

CObjLayerFont * TextMonoFont::RetrieveCharParam(int nIndex,int *textcolor,int *coefftransp,int *shadowflag,int *shadowcolor)
{
	*textcolor=TMOFtextcolor;
	*coefftransp=TMOFcoefftransp;
	*shadowflag=TMOFshadowflag;
	*shadowcolor=TMOFshadowcolor;

	return TMOFfont;
}

#if DEBUG_WRAP
void TextMonoFont::Print()
{
	int i=0;
	MMechostr(1,"MONOFONT-------------------------------------\nTabSize:%d MaxStringSize:%d LayerFont:%d\n",TILsize,TILmaxstringw,TMOFfont);
	while (i<(int)(TILsize))
	{
		int first=TILsubline[i].first;
		int nCount=TILsubline[i].nCount;
		char *tmp;
		tmp=(char *)malloc(sizeof(char)*(nCount+1));
		memcpy(tmp,TILtexte+first,sizeof(char)*(nCount));
		tmp[nCount]='\0';
		MMechostr(MSKTRACE,"First et Ndx Sous Chaine[%d]:f:%d-c:%d-index:%d-w:%d-h:%d-maxw%d-htexte:%d\nChaine:%s*\n"
				  ,i,
				  TILsubline[i].first,
				  TILsubline[i].nCount,
				  TILsubline[i].ndx,
				  TILsubline[i].stringw,
				  TILsubline[i].stringh,
				  TILsubline[i].maxstringw,
				  TILsubline[i].postop,
				  tmp);
		free(tmp);
		i++;
	}
	MMechostr(1,"-------------------------------------\n");
}
#else
void TextMonoFont::Print()
{
}
#endif




////////////////////////////////////////////////////////////////////////////////////////////////////////
//                             LA CLASSE DE TEXTE PASSWORD                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////
TextPassword::TextPassword(char *texte,
						   CObjLayerFont *layerfont,
						   int textcolor,
						   int shadowflag,
						   int shadowcolor,
						   int coefftransp,
						   int wrap,
						   int cx)
						   :TextMonoFont("",layerfont,textcolor,shadowflag,shadowcolor,coefftransp,wrap,cx)
{
	TTPtexte=NULL;
	SetText(texte,1);
}

TextPassword::~TextPassword()
{
	free(TTPtexte);
}

char * TextPassword::replaceByStar(char * old)
{
	int len=strlen(old);
	int i=0;
	char *visi=(char *)malloc(sizeof(char)*(len+1));
	while (i<len)
		*(visi+(i++))='*';
	*(visi+i)='\0';
	return visi;
}

void TextPassword::SetText(char *newtext,int execwordwrap)
{
	// texte réel
	if (TTPtexte)
		free(TTPtexte);
	char *temp=(char *)malloc(sizeof(char)*(strlen(newtext)+1));
	strcpy(temp,newtext);
	TTPtexte=ReplaceRnByR(temp);
	free(temp);
	
	// texte visible
	char *visi=replaceByStar(TTPtexte);
	TextMonoFont::SetText(visi,execwordwrap);
	free(visi);
}

// Ajoute du texte en fin de chaine Rem:le nouveau texte ne dois posseder aucun \n
void TextPassword::AddText(char *newtext,int execwordwrap)
{
	// texte reel
	int lennew=strlen(newtext);
	int len=strlen(TTPtexte);
	TTPtexte=(char *)realloc(TTPtexte,sizeof(char)*(len+lennew+1));
	memcpy(TTPtexte+len,newtext,sizeof(char)*lennew);
	TTPtexte[len+lennew]=0;
	
	// texte visible
	char *visi=replaceByStar(newtext);
	TextMonoFont::AddText(visi,execwordwrap);
	free(visi);
}

int TextPassword::CrunchText(int testclip)
{
	return 0;
}

void TextPassword::InsertChar(int vk,int nIndex,int execwordwrap)
{
	// character insertion in real text
	int len=strlen(TTPtexte);
	char *tmp=(char *)malloc(sizeof(char)*(len+2));
	
	if (nIndex)
		memcpy(tmp,TTPtexte,(sizeof(char)*(nIndex)));	
	tmp[nIndex]=vk;
	memcpy(tmp+nIndex+1,TTPtexte+nIndex,(sizeof(char)*(len-nIndex+1)));

	free(TTPtexte);
	TTPtexte=tmp;
	
	// character insertion in visible text
	TextMonoFont::InsertChar(42,nIndex,execwordwrap);
	0;
}

void TextPassword::DeleteChar(int nIndex,int execwordwrap)
{
	// delete char in real text
	int len=strlen(TTPtexte);
	char *tmp=(char *)malloc(sizeof(char)*len);	
	memcpy(tmp,TTPtexte,(sizeof(char)*nIndex));
	memcpy(tmp+nIndex,TTPtexte+nIndex+1,(sizeof(char)*(len-nIndex)));
	free(TTPtexte);
	TILtexte=tmp;

	// delete char in visible text
	TextMonoFont::DeleteChar(nIndex,execwordwrap);
}


void TextPassword::InsertSubString(char *string,int nIndex,int execwordwrap)
{
	// insert substring in real text
	int size=strlen(string);
	int len=strlen(TTPtexte);
	
	char *tmp=(char *)malloc(sizeof(char)*(len+size+1));
	
	if (nIndex)
		memcpy(tmp,TTPtexte,(sizeof(char)*nIndex));
	memcpy(tmp+nIndex,string,(sizeof(char)*size));
	memcpy(tmp+nIndex+size,TTPtexte+nIndex,(sizeof(char)*(len-nIndex+1)));
	free(TTPtexte);
	TTPtexte=tmp;
	
	char *visi=replaceByStar(string);
	TextMonoFont::InsertSubString(visi,nIndex,execwordwrap);
	free(visi);
}


int TextPassword::DeleteSubString(int nIndexStart,int nIndexEnd,int execwordwrap)
{
	int len;
	if ((len=nIndexEnd-nIndexStart)>0)
	{

		char *tmp=(char *)malloc(sizeof(char)*(strlen(TTPtexte)-len+1));
		if (nIndexStart)
			memcpy(tmp,TTPtexte,(sizeof(char)*nIndexStart));
		memcpy(tmp+nIndexStart,TTPtexte+nIndexEnd,(sizeof(char)*(strlen(TTPtexte)-nIndexEnd+1)));
		
		free(TTPtexte);
		TTPtexte=tmp;
	}
	return TextMonoFont::DeleteSubString(nIndexStart,nIndexEnd,execwordwrap);
}

char *TextPassword::getRealText()
{
	return TTPtexte;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//							        CLASSE TEXTE MONO FONT											  //
////////////////////////////////////////////////////////////////////////////////////////////////////////

TextMultiFont::TextMultiFont(char *texte,
						   CObjLayerFont *layerfont,
						   int textcolor,
						   int shadowflag,
						   int shadowcolor,
						   int coefftransp,
						   int wrap,
						   int cx)
						   :Text(texte,wrap,cx)

{
	//TILlistFont.push_back(layerfont);
	
	unsigned int i=0;
	TILsubchar=(InfoChar *)malloc(sizeof(InfoChar)*(TILlen+1));
	for (i=0;i<TILlen+1;i++)
	{
		TILsubchar[i].color=textcolor;
		TILsubchar[i].shadowflag=shadowflag;
		TILsubchar[i].shadowcolor=shadowcolor;
		TILsubchar[i].coefftransparancy=coefftransp;
		TILsubchar[i].font=layerfont;
	}
	
	WordWrap(0,TILlen);
}

TextMultiFont::~TextMultiFont()
{
	// destruction des fontes referencées par le MultiFont
	/*std::list<CObjLayerFont*>::iterator i = TILlistFont.begin();
	while(i!=TILlistFont.end())
	{
		delete(*i);
		i++;
	}*/
	// destruction de la structure d'infos
	free(TILsubchar);
}

// Renvoie le Layer font du nIndex Charactere
CObjLayerFont * TextMultiFont::GetLayerFont(int nIndex)
{
	return TILsubchar[nIndex].font;
}

int	TextMultiFont::GetTextColor(int nIndex)
{
	return TILsubchar[nIndex].color;
}

int TextMultiFont::GetStringWidthHeight(int nStart,int nCount,int usetab,int *w,int *h)
{
	int i,j,m;
	CObjLayerFont *font=TILsubchar[nStart].font;
	*w=0;
	*h=font->CLFaverageCharHeight;
	m=font->CLFascent;
    i=j=0;
	while (i<nCount && i<TILlen)
	{
		j=0;
		while (i+j<nCount && i+j<TILlen && TILsubchar[nStart+i+j].font==font) j++;
		*w+=font->GetStringWidth(TILtexte+i+nStart,j,usetab);
		*h=max(*h,font->CLFaverageCharHeight);
		i+=j;
		font=TILsubchar[i+nStart].font;
		m=max(m,font->CLFascent);
	}
	return m;
}

// Change le texte
void TextMultiFont::SetText(char *newtext,InfoChar * info,int execwordwrap)
{
	// ajout de la fonte dans la liste si necessaire
	/*std::list<CObjLayerFont*>::iterator o=TILlistFont.begin();
	while (o!=TILlistFont.end())
	{
		if ((*o)==info->font) break;
		o++;
	}
	if (*o!=info->font)
		TILlistFont.push_back(info->font);
	*/

	// mise à jour du contenu
	Text::SetText(newtext,0);

	// mise à jour des infos
	int i;
	TILsubchar=(InfoChar *)realloc(TILsubchar,sizeof(InfoChar)*(TILlen+1));
	for (i=0;i<(int)TILlen+1;i++)
	{
		TILsubchar[i].color=info->color;
		TILsubchar[i].shadowflag=info->shadowflag;
		TILsubchar[i].shadowcolor=info->shadowcolor;
		TILsubchar[i].coefftransparancy=info->coefftransparancy;
		TILsubchar[i].font=info->font;
	}
	if (execwordwrap)
		WordWrap(0,TILlen);
}

// Ajoute du texte en fin de chaine Rem:le nouveau texte ne dois posseder aucun \n
void TextMultiFont::AddText(char *newtext,InfoChar * info,int execwordwrap)
{
	int i;
	int oldlen=TILlen;
	
	// ajout de la fonte dans la liste si necessaire
	/*std::list<CObjLayerFont*>::iterator o=TILlistFont.begin();
	while (o!=TILlistFont.end())
	{
		if ((*o)==info->font) break;
		o++;
	}
	if (*o!=info->font)
		TILlistFont.push_back(info->font);
	*/	

	// mise à jour du contenu
	Text::AddText(newtext,0);
	
	// mise à jour des infos
	TILsubchar=(InfoChar *)realloc(TILsubchar,sizeof(InfoChar)*(TILlen+1));
	for (i=oldlen;i<(int)TILlen+1;i++)
	{
		TILsubchar[i].color=info->color;
		TILsubchar[i].shadowflag=info->shadowflag;
		TILsubchar[i].shadowcolor=info->shadowcolor;
		TILsubchar[i].coefftransparancy=info->coefftransparancy;
		TILsubchar[i].font=info->font;
	}
	if (execwordwrap)
		WordWrap(0,TILlen);
}


// Coupe le texte au premier retour chariot trouve
int TextMultiFont::CrunchText(int testclip)
{
	if (Text::CrunchText(testclip))
	{
		TILsubchar=(InfoChar *)realloc(TILsubchar,sizeof(InfoChar)*(TILlen+1));
		return 1;
	}
	return 0;
}

// Insere le charactere vk à la position nIndex
void TextMultiFont::InsertChar(int vk,int nIndex,int execwordwrap)
{
	int oldlen=TILlen;

	Text::InsertChar(vk,nIndex,0);

	// character insertion
	InfoChar *tmpchar=(InfoChar *)malloc(sizeof(InfoChar)*(oldlen+2));
	if (nIndex)
		memcpy(tmpchar,TILsubchar,(sizeof(InfoChar)*(nIndex)));
	
	tmpchar[nIndex].color=TILsubchar[nIndex].color;
	tmpchar[nIndex].shadowflag=TILsubchar[nIndex].shadowflag;
	tmpchar[nIndex].shadowcolor=TILsubchar[nIndex].shadowcolor;
	tmpchar[nIndex].coefftransparancy=TILsubchar[nIndex].coefftransparancy;
	tmpchar[nIndex].font=TILsubchar[nIndex].font;
	
	memcpy(tmpchar+nIndex+1,TILsubchar+nIndex,(sizeof(InfoChar)*(oldlen-nIndex+1)));
	
	free(TILsubchar);

	TILsubchar=tmpchar;

	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen);
	
}

// Supprime le charactere à la position nIndex
void TextMultiFont::DeleteChar(int nIndex,int execwordwrap)
{
	int oldlen=TILlen;

	Text::DeleteChar(nIndex,0);

	InfoChar *tmpchar=(InfoChar *)malloc(sizeof(InfoChar)*(oldlen));
	
	// les subchars
	memcpy(tmpchar,TILsubchar,(sizeof(InfoChar)*nIndex));
	memcpy(tmpchar+nIndex,TILsubchar+nIndex+1,(sizeof(InfoChar)*(oldlen-nIndex)));
	
	free(TILsubchar);
	TILsubchar=tmpchar;

	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen); 
}
// Insere la sous-chaine à la posiiton nIndex
void TextMultiFont::InsertSubString(char *string,int nIndex,int execwordwrap)
{
	int i;
	int oldlen=TILlen;
	int size=strlen(string);
	

	Text::InsertSubString(string,nIndex,0);

			
	InfoChar *tmpchar=(InfoChar *)malloc(sizeof(InfoChar)*(oldlen+size+1));
	
	if (nIndex)
		memcpy(tmpchar,TILsubchar,(sizeof(InfoChar)*nIndex));
	for (i=0;i<size;i++)
		memcpy(tmpchar+nIndex+i,TILsubchar+nIndex,sizeof(InfoChar));
	
	memcpy(tmpchar+nIndex+size,TILsubchar+nIndex,(sizeof(InfoChar)*(oldlen-nIndex+1)));

	free(TILsubchar);
	TILsubchar=tmpchar;

	if (execwordwrap) WordWrap(SearchSubLineInTab(nIndex),TILlen); 
}

// Supprime la sous-chaine commencant à l'index nIndexStart comportant nCount characteres
int TextMultiFont::DeleteSubString(int nIndexStart,int nIndexEnd,int execwordwrap)
{
	int len,res;
	int oldlen=TILlen;

	if ((res=Text::DeleteSubString(nIndexStart,nIndexEnd,execwordwrap))!=-1)
	{
		len=nIndexEnd-nIndexStart;
		InfoChar *tmpchar=(InfoChar *)malloc(sizeof(InfoChar)*(oldlen-len+1));
		if (nIndexStart>0)
			memcpy(tmpchar,TILsubchar,(sizeof(InfoChar)*nIndexStart));
		memcpy(tmpchar+nIndexStart,TILsubchar+nIndexEnd,(sizeof(InfoChar)*(oldlen-nIndexEnd+1)));
		
		free(TILsubchar);
		TILsubchar=tmpchar;
	}
	else
		res=-1;
	
	return res;

}

// Affiche une chaine dans le Layer
int TextMultiFont::DrawSubString(Layer *layer,int x,int y,int Flags,int IndexSubString)
{
	int first=TILsubline[IndexSubString].first;
	int count=TILsubline[IndexSubString].nCount;
	CObjLayerFont *font=TILsubchar[first].font;
	int baseline=y+TILsubline[IndexSubString].posbaseline;
	int color=TILsubchar[first].color;	
	int coefftransparancy=TILsubchar[first].coefftransparancy;	
    int shadowflag=TILsubchar[first].shadowflag;	
    int shadowcolor=TILsubchar[first].shadowcolor;
    int i=0;
	int w=0;
	int j,h;
	
	while (i<count)
	{
		j=i;
		// check identical font and color
        while (j<count && TILsubchar[first+j].font==font && 
               color==TILsubchar[first+j].color && 
               coefftransparancy==TILsubchar[first+j].coefftransparancy &&
               shadowflag==TILsubchar[first+j].shadowflag && 
               shadowcolor==TILsubchar[first+j].shadowcolor) j++; 
		
        // draw shadowed text
        if (shadowflag>0 && shadowcolor==255)
            font->CopyStringOnLayer(layer,x+shadowflag,y+shadowflag,TILtexte+first,count,shadowcolor,0,1,0);
        
        // draw text
        font->CopyStringOnLayer(layer,x,baseline,TILtexte+first+i,j-i,color,0,1,1);
		
        GetStringWidthHeight(first,j-i,1,&w,&h);

        // draw transparency
        layer->fillPartAlphaLayer(coefftransparancy,Rect2D(x,y,x+w,y+h));

		
		
		x+=w;
		i=j;
		font=TILsubchar[first+i].font;
		color=TILsubchar[first+i].color;
        coefftransparancy=TILsubchar[first+i].coefftransparancy;	
        shadowflag=TILsubchar[first+i].shadowflag;	
        shadowcolor=TILsubchar[first+i].shadowcolor;
	}
	return TILsubline[IndexSubString].stringh;

}

#if DEBUG_WRAP
void TextMultiFont::Print()
{
	int i=0;
	MMechostr(1,"MULTIFONT-------------------------------------\nTabSize:%d\n",TILsize);
	while (i<(int)(TILsize))
	{
		int first=TILsubline[i].first;
		int nCount=TILsubline[i].nCount;
		char *tmp;
		tmp=(char *)malloc(sizeof(char)*(nCount+1));
		memcpy(tmp,TILtexte+first,sizeof(char)*(nCount));
		tmp[nCount]='\0';
		MMechostr(MSKTRACE,"First et Ndx Sous Chaine[%d]:%d-%d-%d-%d-%d-%d-%d-%d\nChaine:%s*\n"
				  ,i,
				  TILsubline[i].first,
				  TILsubline[i].nCount,
				  TILsubline[i].ndx,
				  TILsubline[i].stringw,
				  TILsubline[i].stringh,
				  TILsubline[i].maxstringw,
				  TILsubline[i].postop,
				  TILsubline[i].posbaseline,
				  tmp);
		free(tmp);
		i++;
	}
	MMechostr(1,"-------------------------------------\n");
	
	i=0;
	while(i<(int)(TILlen+1))
	{
		MMechostr(MSKTRACE,"Subchar[%d]: color:%d font:%d\n",i,TILsubchar[i].color,TILsubchar[i].font);
		i++;
	}
	MMechostr(1,"-------------------------------------\n");
}
#else
void TextMultiFont::Print()
{
}
#endif


CObjLayerFont * TextMultiFont::RetrieveCharParam(int nIndex,int *textcolor,int *coefftransp,int *shadowflag,int *shadowcolor)
{
	
	*textcolor=TILsubchar[nIndex].color;
	*coefftransp=TILsubchar[nIndex].coefftransparancy;
	*shadowflag=TILsubchar[nIndex].shadowflag;
	*shadowcolor=TILsubchar[nIndex].shadowcolor;

	return TILsubchar[nIndex].font;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////
//						FONCTIONS COMMUNES SUR UNE CHAINES DE CHARACTERES							  //
////////////////////////////////////////////////////////////////////////////////////////////////////////

unsigned int NextWord(char* txt,int nIndex)
{
	int i=nIndex;
	if (_istspace(txt[i]))
		while (i<(int)strlen(txt) && _istspace(txt[i]) )
			i++;
	else
		while (i<(int)strlen(txt) && !_istspace(txt[i]) )
			i++;
	return (unsigned int)i;
}

unsigned int PreviousWord(char* txt,int nIndex)
{
	int i=nIndex;
	if (i)
	{
		if (_istspace(txt[i-1]))
			do i--;
			while (i>0  && _istspace(txt[i-1]) );
		else
			do i--;
			while (i>0 && !_istspace(txt[i-1]) );
	}
	return (unsigned int)i;
}

unsigned int EndOfLine(char * txt,unsigned int nLen,unsigned int nIndex)
{
	char * lpsz = txt + nIndex;
	char * lpszStop = txt + nLen;
	while (lpsz < lpszStop && *lpsz != '\r')
		++lpsz;
	return lpsz - txt;
}

char * ReplaceRnByR(char * txt)
{
	int len=strlen(txt);
	int i=0;
	int j=0;
	char *res;
	res=(char *)malloc(sizeof(char)*(len+1));
	while (i<len)
	{
		if (*(txt+i) =='\n')
		{
			if ( (i>0 && *(txt+i-1)!='\r') || i==0)
			{
				*(res+j)='\r';
				j++;
			}
			i++;
		}
		else
		{
			*(res+j)=*(txt+i);
			i++;
			j++;
		}
	}
	*(res+j)='\0';
	res=(char*)realloc(res,sizeof(char)*(j+1));
	return res;
}

char * ReplaceRByN(char * txt)
{
	int len=strlen(txt);
	char *res;
	int i=0;
	res=(char *)malloc(sizeof(char)*(len+1));
	while (i<len)
	{
		if (*(txt+i) =='\r')
			*(res+i)='\n';
		else
			*(res+i)=*(txt+i);
		i++;
	}
	*(res+i)='\0';
	return res;
}

char *ReplaceRByRn(char *txt,int nCount)
{
	char *res;
	int i=0;
	int j=0;
	int len=nCount+1;
	res=(char *)malloc(sizeof(char)*len);	
	while (i<nCount)
	{
		if (*(txt+i)=='\r')
		{
			len+=2;
			res=(char *)realloc(res,sizeof(char)*len);
			*(res+j)='\r';
			*(res+j+1)='\n';
			j+=2;
		}
		else
		{
			*(res+j)=*(txt+i);
			j++;
		}
		i++;
	}
	*(res+j)='\0';
	return res;
}


unsigned int NextLine(char * txt,unsigned int nLen,unsigned int nIndex)
{
	char * lpsz = txt + nIndex;
	char * lpszStop = txt + nLen;
	while (lpsz < lpszStop && *lpsz == '\r')
		++lpsz;
	if (lpsz < lpszStop && *lpsz == '\n')
		++lpsz;
	return lpsz - txt;
}
