#ifndef CODE_HTMLTEXTBOX_CXX
#define CODE_HTMLTEXTBOX_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: htmltextbox.cxx,v 1.1.1.1 1998/07/16 19:29:29 cvs Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include <string.h>
#include <ctype.h>
#include "types.h"
#include <Xclasses/htmltextbox.h>
#include "include/htmltextbox_p.h"

#define min(a,b)	(a<b?a:b)
#define max(a,b)	(a>b?a:b)

htmltextbox::htmltextbox(): textbox()
{
	while (!(p=new phtmltextbox))
	{
		outOfMemory("htmltextbox");
	}
	p->o=this;
	Name("htmltextbox");
}
htmltextbox::~htmltextbox()
{
	if (win) Free();
	if (p) delete p;
}
phtmltextbox::phtmltextbox()
{
	size=MEMBLOCKSIZE;
	if (text=(char*)malloc(size))
		*text=0;
	else
		size=0;

	used=0;
	old_w=0;
}
phtmltextbox::~phtmltextbox()
{
	if (text)
	{
		used=0;
		size=0;
		::free(text);
	}
}
void phtmltextbox::RemoveAll(void)
{
	if (text)
	{
		*text=0; used=0;
		if (size>MEMBLOCKSIZE)
		{
			if (text=(char*)realloc(text,MEMBLOCKSIZE))
				size=MEMBLOCKSIZE;
			else
				size=0;
		}
	}
}

void htmltextbox::AppendText(char *t)
{
	int l=strlen(t);
	while (p->used+l>=p->size)
	{
		p->text=(char*)realloc(p->text,p->size+MEMBLOCKSIZE*(l/MEMBLOCKSIZE+1));
		if (!p->text) 
		{
			p->size=0;
			p->used=0;
			return;
		}
		p->size+=MEMBLOCKSIZE*(l/MEMBLOCKSIZE+1);
	}
	strcat(p->text+p->used,t);
	p->used+=l;
	p->calcText();
}
void htmltextbox::ReplaceText(char *t)
{
	if (p->text)
	{
		p->used=0;
		*p->text=0;
	}
	AppendText(t);
	p->checkMem();
	p->calcText();
}
void phtmltextbox::checkMem(void)
{
	if (size-used>(MEMBLOCKSIZE+MEMBLOCKSIZE/2))
	{
		int f=(used/MEMBLOCKSIZE+1)*MEMBLOCKSIZE;

		text=(char*)realloc(text,f);
		if (!text) 
		{
			size=0;
			used=0;
			return;
		}
		size=f;
	}
}

int htmltextbox::Create(void)
{ 
	ReadOnly();
    if (textbox::Create())
    {
    	p->calcText();
		return 1;
    } 
    return 0;
}
void htmltextbox::Free(void)
{
	textbox::Free();
}

void htmltextbox::Resize(int w,int h)
{
	textbox::Resize(w,h);
	p->calcText();
}
int phtmltextbox::findMatch(char c,char *t)
{
	int p=0;
	while (*t && *t!=c)
	{
		t++;
		p++;
	}
	if (*t!=c) p=0;
	return p;
}
char *phtmltextbox::findSymbol(char *s1,int s2)
{
	static char ret[20]="\0";
	char sym[s2+1];
	
	sym[s2]=0;
	for(int i=0;i<s2;i++)
	{
		sym[i]=*s1;
		s1++;
	}
	if (!strcmp("auml",sym))
	{
		strcpy(ret,"ä");
	}
	else if (!strcmp("Auml",sym))
	{
		strcpy(ret,"Ä");
	}
	else if (!strcmp("ouml",sym))
	{
		strcpy(ret,"ö");
	}
	else if (!strcmp("Ouml",sym))
	{
		strcpy(ret,"Ö");
	}
	else if (!strcmp("uuml",sym))
	{
		strcpy(ret,"ü");
	}
	else if (!strcmp("Uuml",sym))
	{
		strcpy(ret,"Ü");
	}
	else if (!strcmp("szlig",sym))
	{
		strcpy(ret,"ß");
	}
	else if (!strcmp("gt",sym))
	{
		strcpy(ret,">");
	}
	else if (!strcmp("lt",sym))
	{
		strcpy(ret,"<");
	}
	if (ret[0])
		return ret;
	else
		return NULL;
}
char *phtmltextbox::findTag(char *s1,int s2)
{
	static char ret[20]="\0";
	char sym[s2+1];
	
	sym[s2]=0;
	for(int i=0;i<s2;i++)
	{
		sym[i]=*s1;
		s1++;
	}
	if (!strcasecmp("br",sym))
	{
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("p",sym))
	{
		strcpy(ret,"\n\n");
	}
	else if (!strcasecmp("dl",sym))
	{
		md_dl=1;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("/dl",sym))
	{
		md_dl=0;
		md_dt=0;
		md_dd=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("dt",sym))
	{
		md_dt=1;
		md_dd=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("dd",sym))
	{
		md_dd=1;
		md_dt=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("ol",sym))
	{
		md_ol=1;
		ol_counter=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("/ol",sym))
	{
		md_ol=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("ul",sym))
	{
		md_ul=1;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("/ul",sym))
	{
		md_ul=0;
		strcpy(ret,"\n");
	}
	else if (!strcasecmp("li",sym))
	{
		if (md_ol || md_ul)
		{
			md_li=1;
			strcpy(ret,"\n");
		}
	}

	if (ret[0])
		return ret;
	else
		return NULL;
}
void phtmltextbox::calcText(void)
{
	int w=o->visible_cols();
	int c=0,lstsp=0,lstspc=0,add;
	char line[w+2],l;

	if (w<4 || w==old_w) return;

	md_dl=0;
	md_ul=0;
	md_ol=0;
	md_li=0;
	md_dd=0;
	md_dt=0;
	ol_counter=0;
	old_w=w;

	int tl=o->TopLine();

	o->textbox::ReplaceText("");
	line[0]=0;
	for(int i=0;i<=used;i++)
	{
		l=*(text+i);
		if (l=='\n') l=' ';
		if (l==' ')
		{
			lstsp=i;
			lstspc=c;
		}
		if (c<w)
		{
			int end=0;
			add=1;
			switch (l)
			{
				case '&': // bekanntes Symbol ?
					if (end=findMatch(';',text+i))
					{
						char *ll=findSymbol(text+i+1,end-1);
						if (ll)
						{
							add=0;
							while (*ll)
							{
								line[c++]=*ll;
//								if (*ll==' ' || *ll=='\n')
//								{
//									lstspc=c-1;
//								}
								ll++;
							}
							i+=end;
						}
					}
					break;
				case '<': // bekannter Tag?
					if (end=findMatch('>',text+i))
					{
						add=0;
						char *ll=findTag(text+i+1,end-1);
						if (ll)
						{
							while (*ll)
							{
								line[c++]=*ll;
//								if (*ll==' ' || *ll=='\n')
//								{
//									lstspc=c-1;
//								}
								ll++;
							}
						}
						i+=end;
					}
					break;
			}
			if (add && (c>0 || l!=' ' || (c>0 && line[c-1]!=' ')))
			{
				line[c++]=l;
//				if (l==' ' || l=='\n')
//				{
//					lstspc=c-1;
//				}
			}
		}
		else
		{
			if (lstsp!=i && lstspc!=c)
			{ // Backtracing zur letzten Space
				if (lstspc>0)
				{
					c=lstspc;
					i=lstsp;
				}
				else
					i--;
			}
			line[c++]='\n';
		}
		if ((c-1)<=w && c>1 && (line[c-1]=='\n' || line[c-1]==0))
		{
			line[c]=0;
			o->textbox::AppendText(line);
			c=0;
			lstspc=c;
			lstsp=i;
			line[0]=0;
			if (md_li)
			{
				md_li=0;
				if (md_ol)
				{
					sprintf(line," %2d. ",++ol_counter);
					c+=strlen(line);
				}
				else if (md_ul)
				{
					strcat(line,"   - ");
					c+=strlen(line);
				}
			}
			else if (md_ol || md_ul || md_dd)
			{
				strcat(line,"     ");
				c+=strlen(line);
			}
			else if(md_dd)
			{
				strcat(line," ");
				c+=1;
			}
		}
	}
	if (c>0)
	{
		line[c]=0;
		o->textbox::AppendText(line);
	}
	o->TopLine(tl);
	o->CursorTo(0,tl);
}
#endif
