#ifndef CODE_AUTOTEXTBOX_CXX
#define CODE_AUTOTEXTBOX_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: autotextbox.cxx,v 1.4 1998/10/07 17:55:52 beckerr 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/autotextbox.h>
#include "include/autotextbox_p.h"
#include "../include/strbuf.h"

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

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

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

void autotextbox::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->old_w=0;
	p->calcText();
}
void autotextbox::ReplaceText(char *t)
{
	if (p->text)
	{
		p->used=0;
		*p->text=0;
	}
	AppendText(t);
	p->checkMem();
}
void pautotextbox::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 autotextbox::Create(void)
{
	ReadOnly();
    if (textbox::Create())
    {
		p->old_w=0;
    	p->calcText();
		return 1;
    } 
    return 0;
}
void autotextbox::Free(void)
{
	textbox::Free();
}

void autotextbox::Resize(int w,int h)
{
	textbox::Resize(w,h);
	p->calcText();
}

#define TABSIZE 4

void pautotextbox::calcText(void)
{
	int w=o->visible_cols();
	int t=o->TopLine();

	if (w<4 || old_w==w) return;
	
	char *line=new char[w+2];
	if (!line) return;
		
	Xcl_strbuf btext;

	o->textbox::ReplaceText("");

	char *d=line;
	char *s=text;
	line[0]=0;

	while (*s)
	{
		if (*s=='\t')
		{
			int n=TABSIZE-(int)(d-line)%TABSIZE;
			if (d+n<line+w)
			{
				for (;n>0;n--)
					strcpy(d++," ");
			}
			else
			{
				*d=0;
				btext+=line;
				line[0]=0;
				d=line;
			}
			s++;
		}
		else
		if (*s=='\n')
		{
			*(d++)=*(s++);
			*d=0;
			btext+=line;
			line[0]=0;
			d=line;
		}
		else
		if (d<line+w)
		{
			*(d++)=*(s++);
		}
		else
		{
			*d=0;
			char *sp;
			for (sp=d; sp>line; sp--)
			{
				if (*sp==' ')
				{
					*sp=0;
					break;
				}
			}
			btext+=line;
			btext+="\n";
			if (sp>line)
			{
				strcpy(line,sp+1);
				d=strchr(line,0);
			}
			else
			{
				line[0]=0;
				d=line;
			}
		}
		if (!line[0])
		{
			XFlush(o->display());
			XEvent myevent;
			int j=1;
			while (j && XCheckMaskEvent(o->display(),ExposureMask|StructureNotifyMask,&myevent))
			{
				if (o->HandleEvent(&myevent)!=-1)
				{
					XPutBackEvent(o->display(),&myevent);
					j=0;
				}
			}
		}
	}
	if (line[0])
	{
		*d=0;
		btext+=line;
	}
	o->textbox::AppendText(btext());
	o->TopLine(t);
	o->CursorTo(0,t);
	delete[] line;
}
#endif
