#include <libraries/zbbs.h>
#include "protos.h"
#include "globals.c"

VOID ChatRequest(VOID);
struct Protocol *GetProtocol(LONG);
BOOL AddMask(struct List *masklist, STRPTR prompt, STRPTR string, LONG *value, struct List *list, LONG xpos, LONG ypos, LONG len, LONG level);
VOID MaskEditor(struct List *list);

VOID Zeilen()
{
	LONG i;

	ClrScr();
	color(WHITE);

	i = 50;
	while(i > 2)	MyPrintf("%ld\r\n", --i);

	Ask("Welche Zahl siehst Du am oberen Bildschirmrand ? : ", NULL, -1, TRUE);
	if(!connected && !login)	return;

	if(wait_buffer[0])	User.lines = atol(wait_buffer);
}

VOID Zone()
{
	STRPTR buffer, buf, ptr;
	LONG i, size;
	char file[256];

	SPrintf(file, "%lsZoneData", Config.system);
	if(!(buffer = GetFile(file, &size)))
		SendError("Zone", "Konnte ZoneData nicht öffnen.");
	else
	{
		i = 0;
		buf = buffer;
		while(buf < buffer + size)
		{
			if(ptr = strchr(buf, '\n'))
			{
				*ptr = 0;
				MyPrintf("[%ld] %ls\r\n", ++i, buf);
				buf = ptr + 1;
			}
			if(ptr = strchr(buf, '\n'))	buf = ptr + 1;
			if(ptr = strchr(buf, '\n'))	buf = ptr + 1;
			else buf = buffer + size;
		}
		FreeVec(buffer);

		Ask("Zone : ", NULL, -1, TRUE);
		if(!connected && !login)	return;

		if(atol(wait_buffer) > 0 && atol(wait_buffer) <= i)
			User.zone = atol(wait_buffer);
	}
}

VOID Join()
{
	BPTR FH;
	LONG time_used;
	BOOL again;
	char buffer[200], file[256];

	Location("Join");

	if(!Compare(User.alias, "GAST"))
	{
		color(YELLOW);
		MyPrintf("Du bist bereits ein eingetragener User...\r\n");
		return;
	}

	ClrScr();
	ShowFile("%lsJoin.txt", Config.text);
	if(!connected && !login)	return;

	time_used = User.time_used;

	do
	{
		again = FALSE;

		Ask("Box Name (ALIAS) : ", NULL, 40, TRUE);
		if(!wait_buffer[0] || (!connected && !login))	goto exit;

		SPrintf(file, "%lsUserliste", Config.user);
		if(CheckUser(file, wait_buffer, NULL))
		{
			again = TRUE;
			color(RED);
			MyPrintf("Dieses Alias ist nicht mehr frei.\r\n");
		}

		if(strchr(wait_buffer, ' '))
		{
			again = TRUE;
			color(RED);
			MyPrintf("Keine Leerzeichen erlaubt.\r\n");
		}
	}	while(again);
	strcpy(User.alias, wait_buffer);

	do
	{
		again = FALSE;

		Ask("Vorname          : ", NULL, 40, TRUE);
		if(!wait_buffer[0] || (!connected && !login))	goto exit;
		strcpy(User.first_name, wait_buffer);

		Ask("Nachname         : ", NULL, 40, TRUE);
		if(!wait_buffer[0] || (!connected && !login))	goto exit;
		strcpy(User.name, wait_buffer);

		SPrintf(buffer, "%ls %ls", User.first_name, User.name);
		SPrintf(file, "%lsUserliste", Config.user);
		if(CheckUser(file, buffer, NULL))
		{
			again = TRUE;
			color(RED);
			MyPrintf("Dieser Name ist nicht mehr frei...\r\n");
		}
	}	while(again);

	do
	{
		again = FALSE;

		Ask("Passwort         : ", NULL, 40, TRUE);
		if(!wait_buffer[0] || (!connected && !login))	goto exit;
		strcpy(buffer, wait_buffer);

		Ask("Passwort (check) : ", NULL, 40, TRUE);
		if(!wait_buffer[0] || (!connected && !login))	goto exit;

		if(!Compare(buffer, wait_buffer))
		{
			again = TRUE;
			color(RED);
			MyPrintf("Die Passwoerter muessen uebereinstimmen...\r\n");
		}
	}	while(again);
	strcpy(User.password, buffer);

	Ask("Strasse + Nr.    : ", NULL, 40, TRUE);
	if(!wait_buffer[0] || (!connected && !login))	goto exit;
	strcpy(User.street, wait_buffer);

	Ask("PLZ Ort          : ", NULL, 40, TRUE);
	if(!wait_buffer[0] || (!connected && !login))	goto exit;
	strcpy(User.place, wait_buffer);

	Ask("Telefon          : ", NULL, 40, TRUE);
	if(!wait_buffer[0] || (!connected && !login))	goto exit;
	strcpy(User.phone, wait_buffer);

	Ask("Geburtsdatum     : ", NULL, 40, TRUE);
	if(!wait_buffer[0] || (!connected && !login))	goto exit;
	strcpy(User.birthday, wait_buffer);

	Ask("Computertyp      : ", NULL, 40, TRUE);
	if(!wait_buffer[0] || (!connected && !login))	goto exit;
	strcpy(User.terminal, wait_buffer);

	Ask("Hotkeys [y/N]    : ", "N", 2, TRUE);
	if(!connected && !login)	goto exit;
	User.hotkeys = (toupper(wait_buffer[0]) == 'Y');

	Ask("Ansi [y/n/Auto]  : ", "A", 2, TRUE);
	if(!connected && !login)	goto exit;
	if(toupper(wait_buffer[0]) != 'Y' && toupper(wait_buffer[0]) != 'N')
		User.ansi = 2;
	else
		User.ansi = (toupper(wait_buffer[0]) == 'Y' ? 1 : 0);
	if(User.ansi == 1)	ansi = 2;

	Ask("Bildschirm loeschen  [Y/n] : ", "Y", 2, TRUE);
	if(!connected && !login)	goto exit;
	User.screenblank = !(toupper(wait_buffer[0]) == 'N');

	Ask("Partielles Scrolling [Y/n] : ", "Y", 2, TRUE);
	if(!connected && !login)	goto exit;
	User.partial_scroll = !(toupper(wait_buffer[0]) == 'N');

	Ask("Font  [0=IBM/1=Amiga(ISO)] : ", "1", 2, TRUE);
	if(!connected && !login)	goto exit;
	User.amiga = (atol(wait_buffer) > 0);

	Zone();

	User.protocol = AskProtocol();

	Zeilen();

	Ask("Willst Du den Eintrag mit diesen Angaben [Y/n] : ", "Y", 2, TRUE);
	if(!connected && !login)	goto exit;
	if(toupper(wait_buffer[0]) != 'N')
	{
		MyPrintf("Einen Moment...\r\n");

		SPrintf(User.time_joined, "%ls %ls", date, time);
		strcpy(User.time_last, User.time_joined);
		User.level				= 20;
		User.time				= 3600;
		User.time_used			= time_used;
		User.time_on			=
		User.calls				= 1;
		strcpy(User.ud_ratio, "1:5");
		User.b_ratio			= TRUE;

		FindFreeFile(file, Config.user);
		strcpy(User.number, &file[strlen(Config.user)]);

		color(WHITE);
		MyPrintf("\r\nDu hast die Usernummer %ls\r\nFalls die Einstellungen nicht stimmen, kannst Du sie mit (S)etup\r\nändern oder dem Sysop eine Message schicken.\r\n\r\n", User.number);

		SPrintf(file, "%lsUserListe", Config.user);
		if(!(FH = COpen(file)))
			SendError("Join", "Konnte UserListe nicht (er)öffnen !");
		else
		{
			Seek(FH, 0L, OFFSET_END);
			FPrintf(FH, "%ls\n%ls\n%ls\n%ls\n", User.alias, User.first_name, User.name, User.number);
			Close(FH);

			SPrintf(file, "%ls%ls", Config.user, User.number);
			RefreshUser(file, &User);

			Status.users++;
			Status.users_new++;
			SPrintf(file, "%lsStatus", Config.system);
			RefreshStatus(file, &Status);

			SPrintf(Log.user, "%ls %ls", User.first_name, User.name);
			Log.new_user = TRUE;

			SPrintf(file, "Neuer User : %ls %ls [%ls]", User.first_name, User.name, User.alias);
			Location(file);

			ShowUser();
		}
		return;
	}

	exit:
	if(connected || login)
	{
		color(WHITE);
		MyPrintf("<Abbruch>\r\n\r\n");
	}

	SPrintf(file, "%lsUserliste", Config.user);
	CheckUser(file, "GAST", &User);
	SPrintf(file, "%ls%ls", Config.user, User.number);
	LoadUser(file, &User);
	ShowUser();

	User.time_used = time_used;
}

BOOL Access(LONG arealevel)
{
	if(User.level < arealevel)
	{
		color(RED);
		MyPrintf("kein Zugriff...\r\n");
		Beep();
		return(FALSE);
	}
	else return(TRUE);
}

VOID UserSetup()
{
	struct List MaskList, ZoneList, YesNoList, FontList, AnsiList, HelpList, EditorList;
	struct Protocol *protocol;
	struct Line *line, *line2;
	char file[256];

	if(protocol = AllocVec(sizeof(struct Protocol), MEMF_ANY | MEMF_CLEAR))
	{
		strcpy(protocol->name, "Auswahl");
		protocol->node.ln_Name = protocol->name;
		AddHead(&ProtocolList, protocol);
	}

	NewList(&ZoneList);
	SPrintf(file, "%lsZoneData", Config.system);
	GetLineList(file, &ZoneList);
	line = GetHead(&ZoneList);
	while(line)
	{
		if(line = GetSucc(line))
		{
			line2 = GetSucc(line);
			Remove(line);
			FreeVec(line);
			line = line2;
		}

		if(line)
		{
			line2 = GetSucc(line);
			Remove(line);
			FreeVec(line);
			line = line2;
		}
	}

	NewList(&YesNoList);
	if(line = GetLine())
	{
		strcpy(line->text, "No");
		AddTail(&YesNoList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Yes");
		AddTail(&YesNoList, line);
	}

	NewList(&FontList);
	if(line = GetLine())
	{
		strcpy(line->text, "IBM");
		AddTail(&FontList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Amiga [ISO]");
		AddTail(&FontList, line);
	}

	NewList(&AnsiList);
	if(line = GetLine())
	{
		strcpy(line->text, "Off");
		AddTail(&AnsiList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "On");
		AddTail(&AnsiList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Automatic");
		AddTail(&AnsiList, line);
	}

	NewList(&HelpList);
	if(line = GetLine())
	{
		strcpy(line->text, "Novice");
		AddTail(&HelpList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Intermediate");
		AddTail(&HelpList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Expert");
		AddTail(&HelpList, line);
	}

	NewList(&EditorList);
	if(line = GetLine())
	{
		strcpy(line->text, "Zeilen");
		AddTail(&EditorList, line);
	}
	if(line = GetLine())
	{
		strcpy(line->text, "Fullscreen");
		AddTail(&EditorList, line);
	}

	NewList(&MaskList);
	AddMask(&MaskList, "Vorname....:", User.first_name,	NULL, NULL, 3, 3, 40, 256);
	AddMask(&MaskList, "Nachname...:", User.name,			NULL, NULL, 3, 4, 40, 256);
	AddMask(&MaskList, "Strasse....:", User.street,			NULL, NULL, 3, 5, 40, 20);
	AddMask(&MaskList, "PLZ Ort....:", User.place,			NULL, NULL, 3, 6, 40, 20);
	AddMask(&MaskList, "Telefon....:", User.phone,			NULL, NULL, 3, 7, 40, 20);
	AddMask(&MaskList, "Passwort...:", User.password,		NULL, NULL, 3, 8, 40, 20);
	AddMask(&MaskList, "Geburtstag.:", User.birthday,		NULL, NULL, 3, 9, 40, 20);

	AddMask(&MaskList, "User Nummer:", User.number,			NULL, NULL, 37, 3, 40, 256);
	AddMask(&MaskList, "Alias......:", User.alias,			NULL, NULL, 37, 4, 40, 256);
	AddMask(&MaskList, "Vertreter..:", User.vertreter,		NULL, NULL, 37, 5, 40, 20);
	AddMask(&MaskList, "Computer...:", User.terminal,		NULL, NULL, 37, 6, 40, 20);
	AddMask(&MaskList, "Zone.......:", NULL, &User.zone, &ZoneList,	37, 7, 40, 0);
	AddMask(&MaskList, "Last Call..:", User.time_last,		NULL, NULL, 37, 8, 40, 256);
	AddMask(&MaskList, "First Call.:", User.time_joined,	NULL, NULL, 37, 9, 40, 256);


	AddMask(&MaskList, "Level......:", NULL, &User.level,			NULL, 3, 11, 40, 256);
	AddMask(&MaskList, "Anrufe.....:", NULL, &User.calls,			NULL, 3, 12, 40, 256);
	AddMask(&MaskList, "Time (sec).:", NULL, &User.time,			NULL, 3, 13, 40, 256);
	AddMask(&MaskList, "Time heute.:", NULL, &User.time_used,	NULL, 3, 14, 40, 256);
	AddMask(&MaskList, "Time total.:", NULL, &User.time_on,		NULL, 3, 15, 40, 256);
	AddMask(&MaskList, "Mails sent.:", NULL, &User.mails_sent,	NULL, 3, 16, 40, 256);
	AddMask(&MaskList, "Mails read.:", NULL, &User.mails_read,	NULL, 3, 17, 40, 256);
	AddMask(&MaskList, "Chat Req...:", NULL, &User.chat_requests,NULL, 3, 18, 40, 256);

	AddMask(&MaskList, "Uploads....:", NULL, &User.uploads,		NULL, 25, 11, 40, 256);
	AddMask(&MaskList, "Bytes Ul...:", NULL, &User.bytes_upload,NULL, 25, 12, 40, 256);
	AddMask(&MaskList, "Downloads..:", NULL, &User.downloads,	NULL, 25, 13, 40, 256);
	AddMask(&MaskList, "Bytes Dl...:", NULL, &User.bytes_download,NULL, 25, 14, 40, 256);
	AddMask(&MaskList, "U/D-Ratio..:", User.ud_ratio,		NULL, NULL, 25, 15, 40, 256);
	AddMask(&MaskList, "Byte Ratio.:", NULL, &User.b_ratio,		&YesNoList, 25, 16, 40, 256);
	AddMask(&MaskList, "Ul first...:", NULL, &User.ul_first,		&YesNoList, 25, 17, 40, 256);
	AddMask(&MaskList, "Ul heute...:", NULL, &User.ul_already,	&YesNoList, 25, 18, 40, 256);

	AddMask(&MaskList, "Hotkeys....:", NULL, &User.hotkeys,		&YesNoList, 47, 11, 40, 0);
	AddMask(&MaskList, "Font.......:", NULL, &User.amiga,			&FontList, 47, 12, 40, 0);
	AddMask(&MaskList, "Helplevel..:", NULL, &User.help_level,	&HelpList, 47, 13, 40, 0);
	AddMask(&MaskList, "Ansi.......:", NULL, &User.ansi,			&AnsiList, 47, 14, 40, 0);
	AddMask(&MaskList, "Protokoll..:", NULL, &User.protocol,		&ProtocolList, 47, 15, 40, 0);
	AddMask(&MaskList, "Editor.....:", NULL, &User.editor,		&EditorList, 47, 16, 40, 0);
	AddMask(&MaskList, "Zeilen.....:", NULL, &User.lines,			NULL, 47, 17, 40, 0);

	ClrScr();
	color(YELLOW);
	MyPrintf("             Userdaten ändern  (mit ESC ESC beenden)");

	MaskEditor(&MaskList);
	RemList(&MaskList);

	if(protocol)
	{
		Remove(protocol);
		FreeVec(protocol);
	}
	RemList(&ZoneList);
	RemList(&YesNoList);
	RemList(&FontList);
	RemList(&AnsiList);
	RemList(&HelpList);
	RemList(&EditorList);

	gotoxy(1, User.lines);

	switch(User.ansi)
	{
		case 0:
			ansi = 0;
			break;
		case 1:
			ansi = 2;
			break;
		default:
			User.ansi = 2;
			AnsiTest();
			break;
	}
}

VOID Chat()
{
	BOOL stop, last;
	char linebuffer1[81], linebuffer2[81];
	LONG linepos1, linepos2, i;

	Location("Starte Chat");

	SetDrMd(Win2->RPort, JAM1);
	SetAPen(Win2->RPort, 0);
	RectFill(Win2->RPort, 0, 49, Win2->Width, 50);

	Status.window	=
	keyboard			= TRUE;
	RefreshStrip();

	color(WHITE);
	MyPrintf("\r\nEntering Chat ...\r\n\n");
	if(ansi > 1)
	{
		MyPrintf("\33[1;1H\33[2J\33[1;1H");
		color(CYAN);
		MyPrintf("%ls\33[12;1H%ls", User.alias, Config.sysop_name);

		color(VIOLET);
		MyPrintf("\33[2;1H");
		i = strlen(User.alias);
		while(i--)	Char('-');

		MyPrintf("\33[13;1H");
		i = strlen(Config.sysop_name);
		while(i--)	Char('-');

		color(GREEN);
		MyPrintf("\33[11;1H==============================================================================\33[21;1H");
	}

	linepos1 =
	linepos2 = 0;
	stop	= FALSE;
	last	= TRUE;
	do
	{
		Wait((1L << Win1->UserPort->mp_SigBit) |
			(1L << Win2->UserPort->mp_SigBit) |
			(1L << ReadPortCON->mp_SigBit) |
			(1L << ReadPortSER->mp_SigBit) |
			(1L << DoTime->tr_node.io_Message.mn_ReplyPort->mp_SigBit));

		if(CheckIO((struct IORequest *)DoTime))
		{
			QueueTimer();
			Clock();
		}

		while(GetMsg(ReadPortCON))
		{
			stop = TRUE;
			if(keyboard)
			{
				if(!last)
				{
					if(ansi > 1)	MyPrintf("\33[21;%ldH", linepos1 + 1);
					color(GREEN);
					last = !last;
				}
				if((console_in[0] != BACK_SPACE) && (console_in[0] != '\r'))
				{
					Char(console_in[0]);
					linebuffer1[linepos1++] = console_in[0];
				}
				else
				{
					if(console_in[0] == BACK_SPACE)
					{
						if(linepos1 > 0)
						{
							linepos1--;
							Backspace();
						}
						else Beep();
					}
					if(console_in[0] == '\r')
					{
						Return();
						if(ansi > 1)	MyPrintf("\33[14;1H\33[1M\33[21;1H\33[1L");
						linepos1 = 0;
					}
				}
			}
			QueueConsole();
		}

		if(CheckIO((struct IORequest *)ReadSER))
		{
			stop = TRUE;
			WaitIO((struct IORequest *)ReadSER);
			if(ser_in)
			{
				if(last)
				{
					if(ansi > 1)	MyPrintf("\33[10;%ldH", linepos2 + 1);
					color(YELLOW);
					last = !last;
				}
				if(serial_in[0] == DEL)	serial_in[0] = BACK_SPACE;
				if((serial_in[0] != BACK_SPACE) && (serial_in[0] != '\r'))
				{
					Char(serial_in[0]);
					if(ansi > 1)	linebuffer2[linepos2++] = serial_in[0];
					else				linebuffer1[linepos1++] = serial_in[0];
				}
				else
				{
					if(serial_in[0] == BACK_SPACE)
					{
						if((ansi > 1 && linepos2 > 0) || (ansi < 1 && linepos1 > 0))
						{
							if(ansi > 1)	linepos2--;
							else				linepos1--;
							Backspace();
						}
						else	Beep();
					}
					if(serial_in[0]=='\r')
					{
						Return();
						if(ansi > 1)
						{
							MyPrintf("\33[3;1H\33[1M\33[10;1H\33[1L");
							linepos2 = 0;
						}
						else				linepos1 = 0;
					}
				}
			}
			SendIO((struct IORequest *)ReadSER);
		}

		if(linepos1 > 77)
		{
			linebuffer1[linepos1] = 0;
			if(strchr(linebuffer1, ' '))
			{
				if(ansi > 1)	MyPrintf("\33[21;%ldH", linepos1 + 1);
				while(linebuffer1[linepos1] != ' ' && linepos1 > 0)
				{
					linepos1--;
					Backspace();
				}
			}
			else	linepos1 = 0;
			Return();
			if(ansi > 1)	MyPrintf("\33[14;1H\33[1M\33[21;1H\33[1L");
			if(strchr(linebuffer1, ' '))
			{
				linepos1++;
				if(ansi > 1)	MyPrintf("\33[21;1H");
				color(GREEN);
				MyPrintf(&linebuffer1[linepos1]);
				strcpy(linebuffer1, &linebuffer1[linepos1]);
				linepos1 = strlen(linebuffer1);
			}
		}

		if(linepos2 > 77)
		{
			linebuffer2[linepos2] = 0;
			if(strchr(linebuffer2, ' '))
			{
				if(ansi > 1)	MyPrintf("\33[10;%ldH", linepos2 + 1);
				while(linebuffer2[linepos2] != ' ' && linepos2 > 0)
				{
					linepos2--;
					Backspace();
				}
			}
			else	linepos2 = 0;
			Return();
			if(ansi > 1)	MyPrintf("\33[3;1H\33[1M\33[10;1H\33[1L");
			if(strchr(linebuffer2, ' '))
			{
				linepos2++;
				if(ansi > 1)	MyPrintf("\33[10;1H");
				color(YELLOW);
				MyPrintf(&linebuffer2[linepos2]);
				strcpy(linebuffer2, &linebuffer2[linepos2]);
				linepos2 = strlen(linebuffer2);
			}
		}

		if(!CarrierSet() && connected)
		{
			ser_out = FALSE;
			HangUp();
		}
		if(!stop)	CheckMenu();
		stop = FALSE;

	}	while((connected || login) && chat);

	color(GREEN);
	if(ansi>1)	ClrScr();
	color(WHITE);
	MyPrintf("Leaving Chat\r\n");
	Location("Beende Chat");

	GetDate();
	Status.time_on	+= (time_now - time_last);
	Status.online_today += (time_now - time_last);
	Status.online += (time_now - time_last);
	User.time_already -= (time_now - time_last);
	time_last = time_now;
}



VOID ChatRequest()
{
	char file[256];
	LONG i;

	Location("***** Chat Request *****");

	SetDrMd(Win2->RPort, JAM1);
	SetAPen(Win2->RPort, 0);
	RectFill(Win2->RPort, 0, 49, Win2->Width, 50);

	SetDrMd(Win2->RPort, COMPLEMENT);
	SetAPen(Win2->RPort, 1);
	RectFill(Win2->RPort, 0, 49, Win2->Width, 50);

	Return();

	User.chat_requests++;
	Log.paged_sysop++;

	if(Status.sysop)
	{
		if(Config.screen_front)
		{
			ScreenToFront(Scr);
			ActivateWindow(Win1);
		}
		i = 15;
		while(i > 0)
		{
			color(RangeRand(7));
			MyPrintf("\rIch rufe den SYSOP; mit Taste abbrechen ... [%ld sec]", i);

			if(Config.bell)	Bell();
			else
			{
				Delay(30);
				DisplayBeep(NULL);
			}
			Delay(10);

			if(CheckIO((struct IORequest *)ReadSER))
			{
				i = 0;
				WaitIO((struct IORequest *)ReadSER);
				SendIO((struct IORequest *)ReadSER);
			}
			if(GetMsg(ReadPortCON))
			{
				QueueConsole();
				i = 0;
				chat = TRUE;
				Chat();
			}
			--i;
		}
		Return();
		Return();
	}
	else
	{
		ClrScr();
		SPrintf(file, "%lsChat.txt", Config.text);
		if(Exists(file))	ShowFile("%lsChat.txt", Config.text);
		else
		{
			color(YELLOW);
			MyPrintf("Der Sysop kann im Moment leider nicht erreicht werden.\r\n\n");
		}
	}
}



VOID Terminal()
{
	LONG actual;

	Status.window	=
	keyboard			= TRUE;
	ser_out			= FALSE;

	color(CYAN);
	MyPrintf("\r\nANSI - Terminal\r\n===============\r\n\n");
	color(WHITE);

	ser_out	=
	ser_in	=
	term		= TRUE;
	RefreshStrip();

	do
	{
		Wait((1L << Win1->UserPort->mp_SigBit) |
			(1L << Win2->UserPort->mp_SigBit) |
			(1L << ReadPortCON->mp_SigBit) |
			(1L << ReadPortSER->mp_SigBit) |
			(1L << DoTime->tr_node.io_Message.mn_ReplyPort->mp_SigBit));

		if(CheckIO((struct IORequest *)DoTime))
		{
			QueueTimer();
			Clock();
		}

		while(GetMsg(ReadPortCON))
		{
			if(keyboard)
			{
				if(ser_out)
				{
					WriteSER->IOSer.io_Command	=	CMD_WRITE;
					WriteSER->IOSer.io_Data		=	(APTR)console_in;
					WriteSER->IOSer.io_Length	=	1L;
					DoIO((struct IORequest *)WriteSER);
				}
				if(FH_Capture)	Write(FH_Capture, console_in, 1);
				if(FH_Printer)	Write(FH_Printer, console_in, 1);
			}
			QueueConsole();
		}
		if(CheckIO((struct IORequest *)ReadSER))
		{
			WaitIO((struct IORequest *)ReadSER);

			ReadSER->IOSer.io_Command = SDCMD_QUERY;
			DoIO((struct IORequest *)ReadSER);
			actual = (ULONG)ReadSER->IOSer.io_Actual;

			if(actual)
			{
				if(actual > Config.ser_read_size)	actual = Config.ser_read_size;

				ReadSER->IOSer.io_Length	= actual;
				ReadSER->IOSer.io_Command	= CMD_READ;
				ReadSER->IOSer.io_Data		= (APTR)&serial_in[1];
				DoIO((struct IORequest *)ReadSER);
			}
			actual++;	/* den ersten Char mitrechnen..!!!!! */

			ReadSER->IOSer.io_Length	= 1;
			ReadSER->IOSer.io_Command	= CMD_READ;
			ReadSER->IOSer.io_Data		= (APTR)serial_in;

			if(ser_in)
			{
				if(Status.window)
				{
					WriteCON->io_Command	=	CMD_WRITE;
					WriteCON->io_Data		=	(APTR)serial_in;
					WriteCON->io_Length	=	actual;
					DoIO(WriteCON);
				}
				if(FH_Capture)	Write(FH_Capture, serial_in, actual);
				if(FH_Printer)	Write(FH_Printer, serial_in, actual);
			}
			SendIO((struct IORequest *)ReadSER);
		}
		CheckMenu();
	}	while(term);

	keyboard	=
	ser_out	= FALSE;
	ser_in	= TRUE;
	RefreshStrip();

	color(NORMAL);
	color(CYAN);
	MyPrintf("Terminal Ende\r\n\n");
	color(WHITE);
}



VOID UserListe()
{
	BPTR FH;
	STRPTR ptr;
	LONG line, stop;
	BOOL more, ret;
	char file[256];

	Location("Userliste");

	SPrintf(file, "%lsuserliste", Config.user);
	if(!(FH =  Open(file, MODE_OLDFILE)))
		SendError("UserListe", "couldn't open userlist !");
	else
	{
		line	= 3;
		stop	=
		ret	= FALSE;
		ClrScr();
		color(BLUE);
		MyPrintf("Alias        Name                 #     Alias        Name                 #\r\n-----------------------------------------------------------------------------\r\n");
		do
		{
			more = FGets(FH, file, 80);
			if(ptr = strchr(file, '\n'))	*ptr = 0;
			color(YELLOW);
			if(more)	MyPrintf("%-12ls ", file);

			FGets(FH, file, 80);
			if(ptr = strchr(file, '\n'))	*ptr = 0;

			strcpy(&file[strlen(file)], " ");
			more = FGets(FH, &file[strlen(file)], 80);
			if(ptr = strchr(file, '\n'))	*ptr = 0;
			color(GREEN);
			if(more)	MyPrintf("%-20ls ", file);

			more = FGets(FH, file, 80);
			if(ptr = strchr(file, '\n'))	*ptr = 0;
			color(CYAN);
			if(more)	MyPrintf("%-3ls", file);

			if(ret)
			{
				line++;
				Return();
				ret = FALSE;
			}
			else
			{
				ret = TRUE;
				MyPrintf("   ");
			}

			if(GetMsg(ReadPortCON))
			{
				if(keyboard)	stop = TRUE;
				QueueConsole();
			}
			if(CheckIO((struct IORequest *)ReadSER))
			{
				if(ser_in)	stop = TRUE;
				WaitIO((struct IORequest *)ReadSER);
				SendIO((struct IORequest *)ReadSER);
			}
			if(!stop && (line > User.lines))	stop = TRUE;
			if(stop > 0)
			{
				stop	= FALSE;
				line	= 1;

				Ask("More [Y/n/c]", NULL, HOTKEY, FALSE);
				if(!connected && !login)	return;
				if(toupper(wait_buffer[0]) == 'N')	stop = TRUE;
				if(toupper(wait_buffer[0]) == 'C')	stop = -1;
			}
		}	while((connected || login) && more && !stop);

		Return();
		Close(FH);
	}
}

BOOL AddMask(struct List *masklist, STRPTR prompt, STRPTR string, LONG *value, struct List *list, LONG xpos, LONG ypos, LONG len, LONG level)
{
	struct Mask *mask;

	if(mask = AllocVec(sizeof(struct Mask), MEMF_ANY | MEMF_CLEAR))
	{
		mask->prompt	= prompt;
		mask->string	= string;
		mask->value		= value;
		mask->list		= list;
		mask->xpos		= xpos;
		mask->ypos		= ypos;
		mask->len		= len;
		mask->level		= level;

		AddTail(masklist, mask);
		return(TRUE);
	}
	else	return(FALSE);
}

VOID AllocMask(struct Mask *mask, STRPTR buffer)
{
	gotoxy(mask->xpos, mask->ypos);

	MyPrintf(Config.ansi_colors[UNDERSCORE]);
	color(GREEN);
	MyPrintf(mask->prompt);

	if(mask->list)
	{
		struct Node *entry;
		LONG i;

		i = 0;
		entry = GetHead(mask->list);
		while(i++ < *mask->value && entry)	entry = GetSucc(entry);

		if(!entry)
		{
			entry = GetHead(mask->list);
			*mask->value = 0;
		}
		strcpy(buffer, entry->ln_Name);

		MyPrintf(Config.ansi_colors[NORMAL]);
		color(CYAN);
		MyPrintf(" %ls%ls%ls", Config.ansi_colors[REVERSE], buffer, Config.ansi_colors[NORMAL]);
	}
	else
	{
		if(mask->string)	strcpy(buffer, mask->string);
		else	SPrintf(buffer, "%ld", *mask->value);

		MyPrintf(Config.ansi_colors[NORMAL]);
		color(CYAN);
		MyPrintf(" %ls", buffer);
	}
}

VOID ReleaseMask(struct Mask *mask, STRPTR buffer)
{
	gotoxy(mask->xpos, mask->ypos);

	color(GREEN);
	MyPrintf(mask->prompt);
	if(mask->list)
	{
		color(CYAN);
		MyPrintf(" %ls", buffer);
	}
	else
	{
		if(mask->string)	strcpy(mask->string, buffer);
		else	*mask->value = atol(buffer);
	}
}

VOID MaskEditor(struct List *list)
{
	struct Mask *mask;
	unsigned char buffer[81], c;

	MyPrintf(Config.ansi_colors[NORMAL]);
	mask = GetHead(list);
	while(mask)
	{
		gotoxy(mask->xpos, mask->ypos);

		color(GREEN);
		if(mask->level > User.level)	MyPrintf(Config.ansi_colors[BOLD]);
		MyPrintf(mask->prompt);
		if(mask->level > User.level)	MyPrintf(Config.ansi_colors[NORMAL]);

		if(mask->level > User.level)	color(WHITE);
		else	color(CYAN);
		if(mask->list)
		{
			struct Node *entry;
			LONG i;

			i = 0;
			entry = GetHead(mask->list);
			while(i++ < *mask->value && entry)	entry = GetSucc(entry);

			if(!entry)
			{
				entry = GetHead(mask->list);
				*mask->value = 0;
			}

			MyPrintf(" %ls", entry->ln_Name);
		}
		else
		{
			if(mask->string)	MyPrintf(" %ls", mask->string);
			else	MyPrintf(" %ld", *mask->value);
		}

		mask = GetSucc(mask);
	}

	mask = GetHead(list);
	while(mask && (mask->level > User.level))	mask = GetSucc(mask);
	if(!mask)	mask = GetTail(list);
	AllocMask(mask, buffer);
	do
	{
		In(1, 1);
		c = wait_buffer[0];
		switch(c)
		{
			case BACK_SPACE:
				if(!strlen(buffer) || mask->list)	Beep();
				else
				{
					Backspace();
					buffer[strlen(buffer) - 1] = 0;
				}
				break;

			case ESC:
				In(1, 1);
				c = wait_buffer[0];
				if(c == ESC)
				{
					ReleaseMask(mask, buffer);
					return;
				}
				if(c != '[')	continue;

			case CSI:
				In(1, 1);
				c = wait_buffer[0];
				switch(c)
				{
					case 'A': /* up */
						ReleaseMask(mask, buffer);
						if(GetPred(mask))	mask = GetPred(mask);
						else	mask = GetTail(list);
						while(mask && (mask->level > User.level))	mask = GetPred(mask);
						if(!mask)	mask = GetTail(list);
						AllocMask(mask, buffer);
						break;

					case 'B': /* down */
						ReleaseMask(mask, buffer);
						if(GetSucc(mask))	mask = GetSucc(mask);
						else	mask = GetHead(list);
						while(mask && (mask->level > User.level))	mask = GetSucc(mask);
						if(!mask)	mask = GetTail(list);
						AllocMask(mask, buffer);
						break;

					case 'C': /* right */
					{
						struct Mask *mask2;

						ReleaseMask(mask, buffer);
						mask2 = GetSucc(mask);
						while(mask2 && ((mask2->ypos != mask->ypos) || (mask2->level > User.level)))
							mask2 = GetSucc(mask2);
						if(mask2)	mask = mask2;
						else Beep();
						AllocMask(mask, buffer);
					}
						break;

					case 'D': /* left */
					{
						struct Mask *mask2;

						ReleaseMask(mask, buffer);
						mask2 = GetPred(mask);
						while(mask2 && ((mask2->ypos != mask->ypos) || (mask2->level > User.level)))
							mask2 = GetPred(mask2);
						if(mask2)	mask = mask2;
						else Beep();
						AllocMask(mask, buffer);
					}
						break;
				}
				break;

			case 0:
				ReleaseMask(mask, buffer);
				if(GetSucc(mask))	mask = GetSucc(mask);
				else	mask = GetHead(list);
				while(mask && (mask->level > User.level))	mask = GetSucc(mask);
				if(!mask)	mask = GetTail(list);
				AllocMask(mask, buffer);
				break;

			default:
				if(iscntrl(c))	Beep();
				else
				{
					if(mask->list)
					{
						RemLine(buffer);

						if(strcmp(mask->string, "BOOL"))	*mask->value += 1;
						else	*mask->value = !*mask->value;

						AllocMask(mask, buffer);
					}
					else
					{
						if(!mask->string && !isdigit(c))	Beep();
						else
						{
							if(strlen(buffer) < mask->len)
							{
								buffer[strlen(buffer) + 1] = 0;
								buffer[strlen(buffer)] = c;
								Char(c);
							}
							else Beep();
						}
					}
				}
				break;
		}
	}	while(connected || login);
}
