// --------------------------------------------------------------------------
// Citadel: Chat.CPP
//
// Chat stuff.

#include "ctdl.h"
#pragma hdrstop

#include "infilt.h"
#include "account.h"
#include "log.h"
#include "blurbs.h"
#include "miscovl.h"
#include "term.h"


// --------------------------------------------------------------------------
// Contents
//
// chat 		This is the chat mode
// ringSysop	ring the sysop


// --------------------------------------------------------------------------
// chat(): This is the chat mode.

void chat(void)
	{
	int c, from, lastfrom = 2, wsize = 0, i;
	char word[50];

	TI()chatkey = FALSE;
	TI()chatReq = FALSE;

	if (!SerialPort.HaveCarrier())
		{
		dial_out();
		return;
		}

	SetDoWhat(DOCHAT);

	cometochat();

	TI()UserControl.SetOutFlag(IMPERVIOUS);

	do
		{
		c = 0;

		if (KBReady())
			{
			c = ciChar();
			from = 0;
			}

		if (TI()SerialPort.IsInputReady())
			{
			if (!onConsole)
				{
				c = TI()SerialPort.Input();
				from = 1;
				}
			else
				{
				TI()SerialPort.Input();
				}
			}

		if (c < 128)
			{
			c = filt_in[c];
			}

		if (c && c != 26)	// Control+Z
			{
			if (from != lastfrom)
				{
				if (from)
					{
					termCap(TERM_NORMAL);
					TI()OC.ansiattr = cfg.attr;
					}
				else
					{
					termCap(TERM_BOLD);
					TI()OC.ansiattr = cfg.cattr;
					}
				lastfrom = from;
				}

			if (c == '\r' || c == '\n' || c == ' ' || c == '\t' || wsize == 50)
				{
				wsize = 0;
				}
			else
				{
				if (TI()OC.CrtColumn >= TI()CurrentUser->GetWidth() - 1)
					{
					if (wsize)
						{
						for (i = 0; i < wsize; i++)
							{
							doBS();
							}
						doCR();
						for (i = 0; i < wsize; i++)
							{
							echocharacter(word[i]);
							}
						}
					else
						{
						doCR();
						}

					wsize = 0;
					}
				else
					{
					// fix from maven

					if (c == '\b')
						{
						wsize--;
						}
					else
						{
						word[wsize] = (char)c;
						wsize++;
						}
					}
				}

			echocharacter((char)c);
			}
		} while ((c != 26) && SerialPort.HaveCarrier());	// Control+Z

	// don't account chat.
	if (cfg.accounting)
		{
		TI()CurrentUserAccount->SetLastTimeAccounted(time(NULL));
		}

	termCap(TERM_NORMAL);
	TI()OC.ansiattr = cfg.attr;
	time(&TI()LastActiveTime);

	doCR();
	}


// --------------------------------------------------------------------------
// ringSysop(): Ring the sysop.

#define RINGLIMIT 30
Bool ringSysop(Bool ring, Bool internalChat)
	{
	Bool answered = FALSE;
	static const char shave[] = { 10, 5, 5, 10, 20, 10, 75 };
	int j = 0;
	int special = 0;
	Bool oldnobells = cfg.noBells;

	CRmPrintf(getmsg(778));

	if (!ring)
		{
		cfg.noBells = TRUE;
		}
	else
		{
		if (cfg.noBells == 1)
			{
			cfg.noBells = 0;
			}
		}

	answered = FALSE;

	int i;
	for (i = 0; (i < RINGLIMIT) && !answered && (HaveConnectionToUser()); i++)
		{
		if (cfg.LocalChatLen && !cfg.noBells)
			{
			int Freq = 1024;
			int Cur;

			for (Cur = 0; Cur < cfg.LocalChatLen && !answered; Cur++)
				{
				int TimeLeft = 0;

				if (cfg.LocalChat[Cur] > 0)
					{
					Freq = cfg.LocalChat[Cur];
					}
				else if (cfg.LocalChat[Cur] == INT_MIN)
					{
					TI()SerialPort.Output(BELL);
					}
				else if (cfg.LocalChat[Cur] == INT_MIN + 1)
					{
					outCon(BELL);
					}
				else if (cfg.LocalChat[Cur] == INT_MIN + 2)
					{
					oChar(BELL);
					}
				else if (cfg.LocalChat[Cur] < -5000)
					{
					// pause
					TimeLeft = -1 * (cfg.LocalChat[Cur] + 5000);
					}
				else
					{
					// duration
					TimeLeft = -cfg.LocalChat[Cur];
					sound(Freq);
					}

				while (TimeLeft && !answered)
					{
					delay(10);
					TimeLeft -= 10;

					if (BBSCharReady() || KBReady())
						{
						answered = TRUE;
						}

					if (TimeLeft < 0)
						{
						TimeLeft = 0;
						}
					}

				nosound();
				}
			}
		else
			{
			oChar(BELL);

			for (int k = 0; k < shave[j] && !answered; k++, special++)
				{
				if (BBSCharReady() || KBReady())
					{
					answered = TRUE;
					}

				twirlypause(1);
				if (cfg.chatflash && !(special % cfg.chatflash) )
					{
					setborder(special / cfg.chatflash);
					}
				}

			j++;
			if (j == 7)
				{
				j = 0;
				}
			}

		if (BBSCharReady() || KBReady())
			{
			answered = TRUE;
			}
		}

	cfg.noBells = oldnobells;

	if (cfg.chatflash)
		{
		setborder(cfg.battr);
		}

	if (KBReady())
		{
		iCharNE();

		if (internalChat)
			{
			chat();
			}

		return (TRUE);
		}
	else if (i >= RINGLIMIT)
		{
		dispBlb(B_NOANSWER);

		return (FALSE);
		}
	else
		{
		iCharNE();

		return (FALSE);
		}
	}
