#ifndef CODE_INPUT_CXX
#define CODE_INPUT_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: input.cxx,v 1.8 2003/02/26 14:07:45 schmitzj 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.
 *-----------------------------------------------------------------------
 */

//  UNIX Key bindings:
//         Ctrl-A - Move to beginning of line
//         Ctrl-E - Move to end of line
//         Ctrl-B - Move backwards
//         Ctrl-F - Move forwards
//         Ctrl-U - Erase line
//         Ctrl-D - Delete character
//         Ctrl-C - Copy to X clipboard
//         Ctrl-V - Paste from X clipboard


#include <time.h>
#include <string.h>
#include <ctype.h>
#include "types.h"
#include "../include/extra_keysym.h"
#include "../include/defaults.h"
#include <Xclasses/gadget.h>
#include <Xclasses/gfx_text.h>
#include <Xclasses/Xcolors.h>
#include <Xclasses/Ddraw.h>
#include <Xclasses/input.h>
#include "include/input_p.h"

input::input(): gadget(), Ddraw(this)
{
	while (!(p=new pinput))
	{
		outOfMemory("input");
	}
	p->o=this;
	Name("input"); p->tgg.Name("inputfield");
	p->tgg.ParentClass(this);
}
input::~input()
{
	if (win) Free();
	if (p) delete p;
}
pinput::pinput() : tgg()
{
	text=NULL;
	textwidth=0;
	cpos=0;
	spos=0;
	blink=0;
	maxchars=64;
	ak=0;
	integer=0;
	invisible=0;
	notabove=0;
	l=0;
	mpos=0;
	mend=-1;
	xx=0;

	if (data=new char[maxchars+1])
	{
		*data=0;
	}
	else
	{
		maxchars=0;
	}
	if (cutdata=new char[maxchars+1])
	{
		*cutdata=0;
	}
	start=data;
}
pinput::~pinput()
{
	if (data) delete data;
	if (cutdata) delete cutdata;
}
void input::Text(char *t)
{
    p->text=t;
    ApplyKey(gfx_text::ShortCut(t));
}
void input::AlwaysMode(void)
{
	if (defaults.inputmode==0)
		p->notabove=1;
}
void input::IntegerMode(void)
{
	p->integer=1;
}
void input::InvisibleMode(void)
{
	p->invisible=1;
}

int input::MaxChars(int m)
{
	char *z;
	if (m!=p->maxchars)
	{
		if (z=new char[m+1])
		{
			if (p->data)
			{
				strncpy(z,p->data,m);
				delete p->data;
			}
			z[m]=0;
			p->data=z;
			p->maxchars=m;
		}
		if (z=new char[m+1])
		{
			*z=0;
			if (p->cutdata)
			{
				delete p->cutdata;
			}
			p->cutdata=z;
		}
	}
	p->start=p->data;
	return p->maxchars;
}
void input::Default(char *t)
{
	if (p->data)
	{
		strncpy(p->data,t,p->maxchars);
		p->start=p->data;
		p->spos=0;
		if (p->cpos>strlen(p->data)) p->cpos=strlen(p->data);
		p->mend=-1;
		if (win) p->taus(0);
	}
}
void input::Input(char *t)
{
	if (p->data) strcpy(t,p->data); else *t=0;
}
void input::Cursor(int c)
{
	if (c>strlen(p->data)) c=strlen(p->data);
	if (c>=0 && c<=p->maxchars)
	{
		if (win) p->taus(3);
		p->cpos=c;
		if (win) p->taus(0);
	}
}
int input::Cursor(void)
{
	return p->cpos;
}
void input::MarkTo(int c)
{
	p->mpos=p->cpos;
	Cursor(c);
	p->mend=p->cpos;

	if (win) p->cutpaste(NULL);
	if (win) p->taus(0);
}
int input::MarkSize(void)
{
	if (p->mend>=0)
		return abs(p->mend-p->mpos);
	else
		return 0;
}
void input::MarkedText(char *c)
{
	strcpy(c,p->cutdata);
}
void input::ReplaceMarkedText(char *c)
{
	if (p->mend=!-1)
	{
		int size=strlen(c);
		for(int i=0;i<size;i++)
		{
			if (p->l<p->maxchars && ((unsigned char)c[i])>=(unsigned char)32)
				p->zeichen_einfuegen(c[i]);
		}
		if (win) p->taus(0);
	}
}

void input::Free(void)
{
	if (XGetSelectionOwner(display(),XA_PRIMARY)==win)
	{
		XSetSelectionOwner(display(),XA_PRIMARY,None,time(NULL));
	}
	p->tgg.Free();
	gadget::Free();
}
int input::Create(void)
{ 
	Background(col_background());
	BorderSize(2);
	KeyBorder();

	if (defaults.inputmode==1)
		p->notabove=1;
	else if (defaults.inputmode==2)
		p->notabove=0;
	
    if (gadget::Create())
    {
		if (!setlimit)
		{
			p->textwidth=textlength(this,p->text);
			if (p->text) before_x=p->textwidth+5+2;
		}
    	Mode(GM_ONEEXPOSE|GM_KEY|GM_CUTPASTE);
    	if (p->text)
    		p->tgg.Dimensions(win,before_x+2+RealSize(),1+RealSize(),width-before_x-RealSize()-5-RealSize(),height-RealSize()-RealSize()-1);
    	else
	    	p->tgg.Dimensions(win,2+RealSize(),1+RealSize(),width-before_x-5-RealSize(),height-RealSize()-RealSize()-1);
		unsigned int dummy=p->backcol();
    	p->tgg.Background(dummy);
    	p->tgg.CopyFont(this);
    	if (p->tgg.Create())
    	{
            if (p->notabove)
            {
	            p->tgg.MCursor(XC_top_left_arrow);
	        	p->tgg.Mode(GM_BUTTON1|GM_BUTTON2|GM_ABOVE|GM_MOUSEMOVE|GM_ONEEXPOSE|GM_KEY|GM_KEYTICK|GM_ACTIVETICK|GM_MINIMALMOVE);
            }
            else
            {
	            p->tgg.MCursor(XC_xterm);
	        	p->tgg.Mode(GM_BUTTON1|GM_BUTTON2|GM_ABOVE|GM_MOUSEMOVE|GM_ONEEXPOSE|GM_KEY|GM_KEYTICK|GM_ACTIVETICK);
	        }
        	p->tgg.SendEventTo(this);
	        return 1;
		}
		else
		{
			gadget::Free();
		}
    } 
    return 0;
}
void input::Resize(int w,int h)
{
	gadget::Resize(w,h);
	if (p->text)
		p->tgg.Resize(w-before_x-5-RealSize()-RealSize(),h-RealSize()-RealSize()-1);
	else
		p->tgg.Resize(w-5-RealSize()-RealSize(),h-RealSize()-RealSize()-1);
}
void input::Lock(void)
{
	gadget::Lock();
	p->tgg.Lock();
}
void input::Unlock(void)
{
	gadget::Unlock();
	p->tgg.Unlock();
}
void input::Block(int b)
{
	gadget::Block(b);
	p->tgg.Block(b);
}
void input::Unblock(int b)
{
	gadget::Unblock(b);
	p->tgg.Unblock(b);
}
void pinput::taus(int f)
{
// f: 0 - Clear, alles neu
//    1 - blinken
//    2 - Cursor neu
//    3 - Cursor neu, nicht deaktiv zeichnen

	int w,dhint,fasc,fdec;
	XCharStruct cs;

	if (cpos<=spos)
	{
		spos=cpos;
		start=&data[spos];
		if (cpos-spos)
		{
			w=XTextWidth(tgg.gg_font(),start,cpos-spos);
		}
		else
		{
			w=0;
		}
	}
	else
	{
		while ((w=XTextWidth(tgg.gg_font(),start,cpos-spos))>tgg._width())
		{
			spos++;
			start=&data[spos];
		}
//		w++;
	}

	int ln=strlen(start);
	char vstart[ln+1];
	if (!invisible)
	{
		strcpy(vstart,start);
	}
	else
	{
		for(int i=0;i<ln;i++) vstart[i]='*';
		vstart[ln]=0;
		w=XTextWidth(tgg.gg_font(),vstart,cpos-spos);
	}

	if (!f)
	{
		tgg.Background(backcol());
		XClearWindow(o->display(),tgg._win());
		blink=0;
	}
	else
	{
		blink++;
		if (blink==6 || f==2 || f==3)
		{
//			if (invisible) w=0;
			XSetForeground(o->display(),tgg._gc(),backcol());
			XDrawLine(o->display(),tgg._win(),tgg._gc(),w,1,w,tgg._height()-1);
		}
		if (blink>10) blink=0;
	}
	XTextExtents(tgg.gg_font(),data,strlen(data),&dhint,&fasc,&fdec,&cs);
	XSetForeground(o->display(),tgg._gc(),tgg.col_text());
	XDrawString(o->display(),tgg._win(),tgg._gc(),0,fasc+(tgg._height()-fasc-fdec)/2,vstart,ln);
	if (mend!=-1 && mpos!=mend)
	{
		int s,e;
		int ws=0; //,we=0;
		if (mpos>mend)
		{
			s=mend;
			e=mpos;
		}
		else
		{
			s=mpos;
			e=mend;
		}
		if (s>spos) ws=XTextWidth(tgg.gg_font(),vstart,s-spos); else s=spos;
//		if (e>spos) we=XTextWidth(tgg.gg_font(),vstart,e-spos);
		XSetBackground(o->display(),tgg._gc(),tgg.col_text());
		XSetForeground(o->display(),tgg._gc(),backcol());
//		XDrawImageString(o->display(),tgg._win(),tgg._gc(),ws,fasc+(tgg._height()-fasc-fdec)/2,&data[s],e-s);
		XDrawImageString(o->display(),tgg._win(),tgg._gc(),ws,fasc+(tgg._height()-fasc-fdec)/2,&vstart[s-spos],e-s);
		XSetBackground(o->display(),tgg._gc(),backcol());
	}

	if (!blink && f!=3)
	{
		char dot[]={1,2};
//		if (invisible) w=0;
		if (!ak)
		{
			XSetDashes(o->display(),tgg._gc(),0,dot,2);
			XSetLineAttributes(o->display(),tgg._gc(),0,LineOnOffDash,CapButt,JoinRound);
		}
		XSetForeground(o->display(),tgg._gc(),tgg.col_black());
		XDrawLine(o->display(),tgg._win(),tgg._gc(),w,1,w,tgg._height()-1);
		if (!ak)
		{
			XSetLineAttributes(o->display(),tgg._gc(),0,LineSolid,CapButt,JoinRound);
		}
		blink++;
	}
	if (o->locked)
	{
		o->borderlocked(&tgg,0,0,tgg._width(),tgg._height(),LOCK_NOBORDER);
	}
}
void pinput::zeichen_loeschen(int n)
{
	if (mend!=-1)
	{
		for(int i=0;(i+mend)<=l;i++)
		{
			data[mpos+i]=data[mend+i];
		}
		l-=mend-mpos;
		if (cpos!=mpos)
		{
			cpos-=mend-mpos;
			if (cpos<0) cpos=0;
		}
		if (cpos>l) cpos=l;
		mend=-1;
	}
	else
	{
		for(int i=n;i<=l;i++)
		{
			data[i]=data[i+1];
		}
		l--;
	}
}
void pinput::zeichen_einfuegen(char z)
{
	if (!integer || isdigit(z))
	{
		if (mend!=-1)
		{
			zeichen_loeschen(cpos);
			cpos=mpos;
		}
		for(int i=l;i>cpos;i--)
		{
			data[i]=data[i-1];
		}
		data[cpos++]=z;
		data[++l]=0;
	}
}
void pinput::cutpaste(XEvent *event)
{ // event obsolete
	if (!invisible)
	{
		if (mend!=-1)
		{
			if (mpos!=mend)
			{
				int s,e;
				if (mend<mpos)
				{
					s=mend;
					e=mpos;
				}
				else
				{
					s=mpos;
					e=mend;
				}
				mpos=s;
				mend=e;
				strncpy(cutdata,&data[s],e-s);
				cutdata[e-s]=0;
				o->ClipTo(cutdata,strlen(cutdata));
			}
			else
			{
				mend=-1;
			}
		}
	}
	else
	{
		mend=-1;
	}
}

int input::GClipHandler(int why,char *data,int size)
{
	int r=0;
	switch (why)
	{
		case CH_DESELECT:
			p->mend=-1;
			p->taus(0);
			r=GCH_MESSAGE;
			break;
		case CH_REQUEST:
			r=GCH_MESSAGE;

			for(int i=0;i<size;i++)
			{
				if (p->l<p->maxchars && ((unsigned char)data[i])>=(unsigned char)32)
					p->zeichen_einfuegen(data[i]);
			}

			p->ak=1;
			p->blink=0;
			p->taus(0);
			p->tgg.ActivateKey();
			break;
	}
	return r;
}
void input::GExpose(XEvent *event)
{
	if (wasfor)
	{
		p->taus(0);
//		if (locked)
//		{
//			borderlocked(&p->tgg,0,0,p->tgg._width(),p->tgg._height(),LOCK_NOBORDER);
//		}
	}
	else
	{
		XSetForeground(display(),gc,p->backcol());
		if (p->text)
		{
			XFillRectangle(display(),win,gc,before_x+RealSize(),RealSize(),width-before_x-RealSize(),height-RealSize()/*-3*/);
			borderDown(this,before_x,0,width-before_x,height);
			if (p->ak) bordermark(this,before_x,0,width-before_x,height); else borderunmark(this,before_x,0,width-before_x,height);
			bordertext(this,0,0,before_x-TEXTDISTANCE,height,p->text,ADJUST_RIGHT|ADJUST_MIDDLE);
		}
		else
		{
			XFillRectangle(display(),win,gc,RealSize(),RealSize(),width-before_x-RealSize(),height-RealSize()/*-3*/);
			borderDown(this,0,0,width,height);
			if (p->ak) bordermark(this,0,0,width,height); else borderunmark(this,0,0,width,height);
		}
	}
}
int input::GActivate(XEvent *event,int why)
{
	if (why==GA_BUTTONPRESS)
	{
		if (!p->invisible) p->mpos=p->spos;
		p->l=strlen(p->data);
		while (p->mpos<p->l && XTextWidth(p->tgg.gg_font(),p->start,p->mpos-p->spos+1)<event->xbutton.x) p->mpos++;

		if (event->xbutton.button==2)
		{
			ClipRequest();
			return 0;
		}
		else
		{
			p->mend=-1;
			p->tgg.ActivateKey();
			if (!p->notabove || p->ak) p->cpos=p->mpos;
			p->ak=1;
			p->blink=0;
			p->taus(0);
		}
		if (!p->invisible) return GAR_ACTIVE; else return 0;
	}
	if (why==GA_ABOVE)
	{
		if (!locked && !p->notabove)
		{
			p->tgg.ActivateKey();
			return GAR_ACTIVE;
		}
		return 0;
	}
	if (why==GA_TICK)
	{
		if (p->mend!=-1)
		{
			if (p->xx<0)
			{
				if (p->cpos>0)
				{
					p->cpos--;
					p->mend=p->cpos;
					p->taus(0);
				}
			}
			if (p->xx>p->tgg.gg_width())
			{
				p->l=strlen(p->data);
				if (p->cpos<p->l)
				{
					p->cpos++;
					p->mend=p->cpos;
					p->taus(0);
				}
			}
		}
		else
		{
			p->taus(1);
		}
	}
	if (!p->ak) return 0;

	if (why==GA_KEY)
	{
		int c,ocpos=p->cpos,r=GAR_ACTIVE;
		int status;
		c=LookupString(event,p->taste,sizeof(p->taste),p->key,status);
		p->l=strlen(p->data);

		switch (p->key)
		{
			case XK_Left:
			case XK_KP_Left:
				if (p->cpos>0) p->cpos--;
				if (event->xkey.state & ShiftMask)
				{
					if (p->mpos==ocpos && p->mend!=-1)
					{
						p->mpos=p->cpos;
					}
					else
					{
						p->mpos=p->cpos;
						p->mend=ocpos;
					}
					p->cutpaste(event);
				}
				else
					p->mend=-1;
				break;
			case XK_Right:
			case XK_KP_Right:
				if (p->cpos<p->l) p->cpos++;
				if (event->xkey.state & ShiftMask)
				{
					if (p->mend==ocpos && p->mend!=-1)
					{
						p->mend=p->cpos;
					}
					else
					{
						p->mend=p->cpos;
						p->mpos=ocpos;
					}
					p->cutpaste(event);
				}
				else
					p->mend=-1;
				break;
			case XK_Home:
			case XK_KP_Home:
				p->cpos=0;
				if (event->xkey.state & ShiftMask)
				{
					if (p->mpos==ocpos && p->mend!=-1)
					{
						p->mpos=p->cpos;
					}
					else
					{
						p->mpos=p->cpos;
						p->mend=ocpos;
					}
					p->cutpaste(event);
				}
				else
					p->mend=-1;
				break;
			case XK_End:
			case XK_KP_End:
				p->cpos=p->l;
				if (event->xkey.state & ShiftMask)
				{
					if (p->mend==ocpos && p->mend!=-1)
					{
						p->mend=p->cpos;
					}
					else
					{
						p->mend=p->cpos;
						p->mpos=ocpos;
					}
					p->cutpaste(event);
				}
				else
					p->mend=-1;
				break;
			case XK_BackSpace:
				if (p->mend==-1)
				{
					if (p->cpos>0)
					{
						p->zeichen_loeschen(p->cpos-1);
						r|=GAR_MESSAGE;
						p->cpos--;
					}
					else
					{
						XBell(display(),-75);
					}
				}
				else
				{
					p->zeichen_loeschen(0);
					r|=GAR_MESSAGE;
				}
				break;
			case XK_Delete:
			case XK_KP_Delete:
				if (p->mend==-1)
				{
					if (p->l>p->cpos)
					{
						p->zeichen_loeschen(p->cpos);
						r|=GAR_MESSAGE;
					}
					else
					{
						XBell(display(),-75);
					}
				}
				else
				{
					p->zeichen_loeschen(0);
					r|=GAR_MESSAGE;
				}
				break;
			case XK_Return:
			case XK_KP_Enter:
				p->mend=-1;
				DefaultKeyHandler(event);
				break;
			case Sun_XK_Cut: // cut
			case 0xffd1:
				if (p->mend!=-1) p->zeichen_loeschen(0);
				break;
			case Sun_XK_Copy: // copy
			case 0xffcd:
				break;
			case Sun_XK_Paste: // paste
			case 0xffcf:
				ClipRequest();
				break;
			default:
				{
					if (c==1 && ((unsigned char)p->taste[0])>=32 && !(event->xkey.state & ControlMask)) // && !(event->xkey.state & Mod1Mask))
					{
						if (p->l<p->maxchars || p->mend!=-1)
						{
							p->zeichen_einfuegen(p->taste[0]);
							r|=GAR_MESSAGE;
						}
						else
						{
							XBell(display(),-75);
						}
					}
					else
					{
						int done=0;
						if ((event->xkey.state & ControlMask) && !(event->xkey.state & Mod1Mask))
						{
							switch (p->key)
							{
								case XK_x: // cut
									if (p->mend!=-1) p->zeichen_loeschen(0);
									done=1;
									break;
								case XK_c: // copy
									break;
								case XK_v: // paste
								case XK_Insert:
									ClipRequest();
									done=1;
									break;
								case XK_a:
									p->cpos=0;
									if (event->xkey.state & ShiftMask)
									{
										if (p->mpos==ocpos && p->mend!=-1)
										{
											p->mpos=p->cpos;
										}
										else
										{
											p->mpos=p->cpos;
											p->mend=ocpos;
										}
										p->cutpaste(event);
									}
									else
										p->mend=-1;
									done=1;
									break;
								case XK_e:
									p->cpos=p->l;
									if (event->xkey.state & ShiftMask)
									{
										if (p->mend==ocpos && p->mend!=-1)
										{
											p->mend=p->cpos;
										}
										else
										{
											p->mend=p->cpos;
											p->mpos=ocpos;
										}
										p->cutpaste(event);
									}
									else
										p->mend=-1;
									done=1;
									break;
								case XK_b:
									if (p->cpos>0) p->cpos--;
									if (event->xkey.state & ShiftMask)
									{
										if (p->mpos==ocpos && p->mend!=-1)
										{
											p->mpos=p->cpos;
										}
										else
										{
											p->mpos=p->cpos;
											p->mend=ocpos;
										}
										p->cutpaste(event);
									}
									else
										p->mend=-1;
									done=1;
									break;
								case XK_f:
									if (p->cpos<p->l) p->cpos++;
									if (event->xkey.state & ShiftMask)
									{
										if (p->mend==ocpos && p->mend!=-1)
										{
											p->mend=p->cpos;
										}
										else
										{
											p->mend=p->cpos;
											p->mpos=ocpos;
										}
										p->cutpaste(event);
									}
									else
										p->mend=-1;
									done=1;
									break;
								case XK_u:
									p->data[0]=0;
									p->cpos=0;
									p->mend=-1;
									done=1;
									break;
								case XK_d:
									if (p->mend==-1)
									{
										if (p->cpos>0)
										{
											p->zeichen_loeschen(p->cpos-1);
											r|=GAR_MESSAGE;
											p->cpos--;
										}
										else
										{
											XBell(display(),-75);
										}
									}
									else
									{
										p->zeichen_loeschen(0);
										r|=GAR_MESSAGE;
									}
									done=1;
									break;
							}
						}
						if ((event->xkey.state & ShiftMask))
						{
							switch (p->key)
							{
								case XK_Insert: // paste
									ClipRequest();
									done=1;
									break;
							}
						}

						if (!done)
						{
							int dk=0;
							if (c==1) event->xkey.state&=~Mod1Mask;
							dk=DefaultKeyHandler(event);
							if (dk==DKH_DEACTIVATED)
							{
								return 0;
							}
						}
					}
				}
				break;
		}

		p->taus(0);
		return r;
	}
	return 0;
}
int input::GSelected(XEvent *event,int why,int wasabove)
{
	if (why==GA_KEY)
	{
		if (p->key==XK_Return || p->key==XK_KP_Enter)
		{
			p->mend=-1;
//			p->ak=0;
//			p->blink=-1;
//			p->taus(2);
			p->tgg.DeactivateKey();
			return GSR_SELECTION;
		}
	}
	if (why==GA_ABOVE)
	{
//		if (!p->notabove)
//		{
//			p->ak=0;
//			p->blink=-1;
//			if (!(p->tgg._active() & GA_BUTTONPRESS))
//			{
//				p->tgg.DeactivateKey();
//				p->taus(2);
//			}
//		}
//		else
//		{
//			p->taus(1);
//		}
	}
	if (why==GA_BUTTONPRESS)
	{
		if (p->tgg._active()&GA_DCLICK)
		{
			p->mpos=0;
			p->mend=p->l;
		}

		p->cutpaste(event);
		
		if (!p->ak)
		{
			p->tgg.DeactivateKey(); 
		}
		if (p->tgg._active()&GA_DCLICK)
		{
			p->taus(0);
		}
	}
	return 0;
}
void input::GActionPress(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
	if (reason&GB_KEY)
	{
		if (wasfor)
		{
			if (p->text)
				bordermark(this,before_x,0,width-before_x,height);
			else
				bordermark(this,0,0,width,height);
			if (p->notabove) p->tgg.MCursor(XC_xterm);
			p->ak=1;
			p->blink=0;
			p->taus(0);
		}
		else
		{
			p->tgg.ActivateKey();
		}
	}
}
void input::GActionRelease(int mx,int my,int rx,int ry,unsigned int state,int button,int reason)
{
	if (reason&GB_KEY)
	{
		if (p->text)
			borderunmark(this,before_x,0,width-before_x,height);
		else
			borderunmark(this,0,0,width,height);
		p->ak=0;
		if (p->notabove) p->tgg.MCursor(XC_top_left_arrow);
		p->taus(0);
	}
}
int input::GMouseMove(int mx,int my,int rx,int ry,unsigned int state,int button)
{
	if (button==1)
	{
		p->mend=p->spos;
		p->xx=mx;
		if (mx<0) mx=0;
		if (mx>width) mx=width;
		p->l=strlen(p->data);
		while (p->mend<p->l && XTextWidth(p->tgg.gg_font(),p->start,p->mend-p->spos+1)<mx) p->mend++;
		p->cpos=p->mend;
		p->taus(0);
	}
	return 0;
}
void input::GSetLimits(void)
{
	p->textwidth=textlength(this,p->text);
	minwidth=p->textwidth+TEXTDISTANCE+8+(p->text && *p->text?p->textwidth/strlen(p->text)*5:textlength(this,"MM")/2*5);
	minheight=textheight(this,p->text)+10;
	maxheight=minheight;
	if (p->text) before_x=p->textwidth+5+TEXTDISTANCE;
	setlimit=1;
}

#endif
