#include <curses.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>

void CharInsert(x,o)
char *x;
int o;
{
	int ct;
	x+=o;
	ct=strlen(x);
	while(ct>=0)
	{
		x[ct+1]=x[ct];
		ct--;
	}
}

void WaitFD(fd)
int fd;
{
	int rdw=(1<<fd);
	static struct timeval tlim={1,0};
	if(select(32,&rdw,NULL,&rdw,&tlim)==-1)
		Error("Select Failed");
}

WINDOW *top,*bottom;
int TopSize,BottomSize,Width;

Shutdown()
{
	endwin();
#ifndef NEW_CURSES
	KeyRestore();
#endif
	exit(1);
}

Error(x)
char *x;
{
	endwin();
	printf("%s\n",x);
#ifndef NEW_CURSES
	KeyRestore();
#endif
	exit(1);
}

SetUp()
{
	initscr();
	signal(SIGINT,Shutdown);
	Width=COLS;
	TopSize=LINES-7;
	BottomSize=7;
	top=newwin(TopSize,Width,0,0);
	bottom=newwin(BottomSize,Width,TopSize+1,0);
	if(top==NULL || bottom==NULL)
		Error("Window create failed.\n");
	wmove(top,TopSize,0);
}

char Input[514];
char YankBuffer[514];
char BackBuffer[514];
int InputPos=0;
char Prompt[256]="By what name shall I call you : ";
int GoAhead=1;
int Echo=1;
int State=0;
char Buffer[514];
int BufPtr=0;

void CursorCalc(pos,x,y)
int pos;
int *x,*y;
{
	pos+=strlen(Prompt);
	*x=pos%Width;
	*y=pos/Width;
}

DoEvent()
{
	Buffer[BufPtr]=0;
	BufPtr=0;
	if(*Buffer=='Q')
		Shutdown();
	if(*Buffer=='P')
	{
		strcpy(Prompt,Buffer+1);
		return;
	}
	if(*Buffer=='T')
	{
		strcpy(Input,Buffer+1);
		InputPos=strlen(Input);
		return;
	}
	if(*Buffer=='G')
	{
		werase(bottom);
/*		wprintw(top,"[GAH]\n");*/
		wrefresh(top);
		wprintw(bottom,"%s",Prompt);
		wmove(bottom,0,strlen(Prompt));
		wprintw(bottom,"%s",Input);
		wrefresh(bottom);
		GoAhead=1;
		return;
	}
	if(*Buffer=='S')
	{
		wprintw(top,"|%s",Buffer+1);
		return;
	}
	if(*Buffer=='E')
	{
		if(Buffer[1]=='Y')
			Echo=0;
		else
			Echo=1;
		return;
	}
}

#ifndef NEW_CURSES

struct termios TermDef;
int tty_set=0;

void KeyRestore()
{
	if(tty_set)
	{
		ioctl(0,TCSETS,&TermDef);
	}
}

void SetNoEcho()
{
	struct termios temp;
	if(tty_set)
		return;
	if(ioctl(0,TCGETS,&TermDef)==-1)
		return;
	temp=TermDef;
	temp.c_lflag&=~(ICANON|ECHO);
	temp.c_cc[VMIN]=0;
	temp.c_cc[VTIME]=1;
	tty_set=1;
	ioctl(0,TCSETS,&temp);
}

#endif

main(argc,argv)
int argc;
char *argv[];
{
	int fd;
	int txo;
	int x,y;
	if(argc!=3)
	{
		fprintf(stderr,"%s <host> <port>\n",argv[0]);
		exit(1);
	}
	fd=Make_Connection(atoi(argv[2]),argv[1]);
	if(fd==-1)
	{
		perror(argv[1]);
		exit(1);
	}
	SetUp();
	refresh();
	wprintw(top,"AberMUD 5.21BETA3, Client  Alan Cox 1991\n");
	scrollok(top,TRUE);
	idlok(top,TRUE);
	idlok(bottom,TRUE);
#ifdef NEW_CURSES
	keypad(stdscr,TRUE);
	halfdelay(1);
#endif
#ifdef NEW_CURSES
	noecho();
#else
	SetNoEcho();
#endif
	wrefresh(top);
	fcntl(fd,F_SETFL,O_NDELAY);
	while(1)
	{
		char buf[256];
		int l;
		txo=0;
		while((l=read(fd,buf,255))>0)
		{
			int ct=0;
			while(ct<l)
			{
				if(State==1&&buf[ct]!='\003')
					Buffer[BufPtr++]=buf[ct];
				else if (State==1)
				{
					State=0;
					DoEvent();
				}
				else
				{
					if(buf[ct]=='\002')
						State=1;
					else
					{
						if(buf[ct]=='\n')
						{
							scroll(top);
							wmove(top,TopSize,0);
							wclrtoeol(top);
							wmove(top,TopSize,0);
						}
						else
							waddch(top,buf[ct]);
/*						wrefresh(top);*/
					}
					txo=1;
				}
				ct++;
			}
		}
		if(l<=0&&errno!=EWOULDBLOCK&&errno!=0)
			Error("Remote Closed Connection\n");
		if(txo!=0&&GoAhead==1)
		{
			wrefresh(top);
			wrefresh(bottom);
			txo=0;
		}
		if(GoAhead==0)
		{
			WaitFD(fd);
			continue;
		}
#ifdef NEW_CURSES
		l=getch();
#else
		{
			char tc;
			if(read(0,&tc,1)!=1)
				l=ERR;
			else
				l=tc;
		}
#endif
		if(l!=ERR)
		{
			char c=l;
			if(l==8||l==127)
			{
				if(InputPos)
				{
					InputPos--;
					strcpy(Input+InputPos,Input+InputPos+1);
					CursorCalc(InputPos,&x,&y);
					wmove(bottom,y,x);
					wprintw(bottom,"%s ",Input+InputPos);
					wmove(bottom,y,x);
					wrefresh(bottom);
				}
				continue;
			}
#ifndef KEY_LEFT
#define KEY_LEFT	2
#define KEY_RIGHT	6
#endif
			if((l==KEY_LEFT||l==2)&&InputPos)
			{
				InputPos--;
				CursorCalc(InputPos,&x,&y);
				wmove(bottom,y,x);
				wrefresh(bottom);
				continue;
			}
			if((l==6||l==KEY_RIGHT)&&InputPos<strlen(Input))
			{
				InputPos++;
				CursorCalc(InputPos,&x,&y);
				wmove(bottom,y,x);
				wrefresh(bottom);
				continue;
			}
			if(c==1)
			{
				InputPos=0;
				CursorCalc(InputPos,&x,&y);
				wmove(bottom,y,x);
				wrefresh(bottom);
				continue;
			}
			if(c==5)
			{
				InputPos=strlen(Input);
				CursorCalc(InputPos,&x,&y);
				wmove(bottom,y,x);
				wrefresh(bottom);
				continue;
			}
			if(c==25)
			{
				werase(bottom);
				strcpy(Input,YankBuffer);
				InputPos=strlen(Input);
				wmove(bottom,0,0);
				wprintw(bottom,"%s",Prompt);
				wmove(bottom,0,strlen(Prompt));
				wprintw(bottom,"%s",Input);
				wrefresh(bottom);
				continue;
			}
			if(c=='R'-64)
			{
				werase(bottom);
				strcpy(Input,BackBuffer);
				InputPos=strlen(Input);
				wmove(bottom,0,0);
				wprintw(bottom,"%s",Prompt);
				wmove(bottom,0,strlen(Prompt));
				wprintw(bottom,"%s",Input);
				wrefresh(bottom);
				continue;
			}
			if(c=='K'-64)
			{
				strcpy(YankBuffer,Input);
				continue;
			}
			if(c==24)
			{
				InputPos=0;
				*Input=0;
				werase(bottom);
				wmove(bottom,0,0);
				wprintw(bottom,"%s",Prompt);
				wrefresh(bottom);
				continue;
			}
			if(c=='\r'||c=='\n')
			{
				c='\n';
				GoAhead=0;
				if(write(fd,Input,strlen(Input))!=strlen(Input))
					Error("Remote closed connection");
				if(write(fd,&c,1)==-1)
					Error("Remote closed connection");
/*				wprintw(top,"[SNT]\n");*/
				strcpy(BackBuffer,Input);
				InputPos=0;
				*Input=0;
				continue;
			}
			if(InputPos==511||c<32||c>127)
			{
#ifdef NEW_CURSES
				beep();
#endif
				continue;
			}
			CharInsert(Input,InputPos);
			Input[InputPos++]=c;
			if(Echo==1)
			{
				wprintw(bottom,"%s",Input+InputPos-1);
				CursorCalc(InputPos,&x,&y);
				wmove(bottom,y,x);
				wrefresh(bottom);
			}
		}
	}
	Shutdown();
}