// --------------------------------------------------------------------------
// Citadel: UserOut.CPP
//
// This is a collection of routines that give output to the user.

#include "ctdl.h"
#pragma hdrstop

#include "room.h"
#include "log.h"
#include "group.h"
#include "hall.h"
#include "events.h"
#include "term.h"


// --------------------------------------------------------------------------
// Contents
//
// GiveRoomPrompt() 	Gives the usual "THISROOM>" prompt.
// SetOutOK()			Sets for usual output.

void UserOutputControl::Reset(void)
	{
	ResetCanFlags();
	CanR = cfg.twitrev;

	OutFlag = OUTOK;
	Continuous = FALSE;
	}


// --------------------------------------------------------------------------
// GiveRoomPrompt(): Gives the usual "THISROOM>" prompt.

void GiveRoomPrompt(void)
	{
	static int roomCounter;
	label rn, gn, np, ex, hn;
	char rd[81];
	char tm[128], dt[128];
	int i;

	TI()SerialPort.Flush();

	TI()UserControl.Reset();

	TI()OC.Echo = BOTH;
	setio();

	TI()OC.ansiattr = cfg.attr;

	doEvent(EVT_ROOMPROMPT);

	if (TI()CurrentUser->IsYouAreHere())
		{
		youAreHere();
		}

	TI()UserControl.SetOutFlag(IMPERVIOUS);

	doCR();
	TI()OC.Formatting = FALSE;

	roomCounter++;

	strcpy(rn, GetRoomName(TI()thisRoom));

	gn[0] = 0;
	if (IsRoomGroupOnly(TI()thisRoom))
		{
		if (IsRoomMultiGroup(TI()thisRoom))
			{
			strcpy(gn, getmsg(1305));
			}
		else
			{
			strcpy(gn, GroupData->GetEntry(GetRoomGroupNumber(TI()thisRoom))->
					GetName());
			}
		}

	np[0] = 0;
	if (IsRoomShared(TI()thisRoom))
		{
		strcpy(np, TI()loggedIn ? TI()CurrentUser->GetNetPrefix() : cfg.netPrefix);
		}


	ex[0] = 0;
	i = 0;
	if (IsRoomDirectory(TI()thisRoom))
		{
		if (TI()CurrentUser->IsIBMRoom() && TI()CurrentUser->IsIBMGraph())
			{
			ex[i++] = roomCounter == 6969 ? '\xcc' : '\xb9';
			}
		else
			{
			ex[i++] = roomCounter == 6969 ? '[' : ']';
			}
		}

	if (IsRoomGroupOnly(TI()thisRoom))
		{
		if (TI()CurrentUser->IsIBMRoom() && TI()CurrentUser->IsIBMGraph())
			{
			ex[i++] = roomCounter == 6969 ? '\xba' : '\xb3';
			}
		else
			{
			ex[i++] = roomCounter == 6969 ? ';' : ':';
			}
		}

	if (IsRoomHidden(TI()thisRoom))
		{
		ex[i++] = roomCounter == 6969 ? '(' : ')';
		}
	if (IsRoomBIO(TI()thisRoom))
		{
		ex[i++] = roomCounter == 6969 ? '{' : '}';
		}
	else if (!IsRoomGroupOnly(TI()thisRoom) &&
			!IsRoomDirectory(TI()thisRoom) &&
			!IsRoomHidden(TI()thisRoom))
		{
		if (!(iswindow(TI()thisRoom) && TI()CurrentUser->IsIBMRoom() && TI()CurrentUser->IsIBMGraph()))
			{
			ex[i++] = roomCounter == 6969 ? '<' : '>';
			}
		}

	if (iswindow(TI()thisRoom))
		{
		if (TI()CurrentUser->IsIBMRoom() && TI()CurrentUser->IsIBMGraph())
			{
			ex[i++] = roomCounter == 6969 ? '\xae' : '\xaf';
			}
		else
			{
			ex[i++] = roomCounter == 6969 ? '<' : '>';
			}
		}
	ex[i] = 0;

	strcpy(hn, HallData->GetEntry(TI()thisHall)->GetName());

	strcpy(rd, GetCurrentRoomDescription());

	strftime(tm, 127, (TI()loggedIn) ?
			special_deansi(TI()CurrentUser->GetDateStamp(), TERM_TIME) :
			special_deansi(cfg.datestamp, TERM_TIME), 0l);

	strftime(dt, 127, (TI()loggedIn) ?
			special_deansi(TI()CurrentUser->GetVerboseDateStamp(), TERM_DATE) :
			special_deansi(cfg.vdatestamp, TERM_DATE), 0l);

	Andy(TI()loggedIn ? TI()CurrentUser->GetPromptFormat() : cfg.prompt,
			getmsg(848), rn, gn, np, ex, hn, rd, tm, dt);

	TI()OC.Formatting = TRUE;
	ansi(14);
	TI()OC.MCI_goto = FALSE;

	termCap(TERM_NORMAL);
	mPrintf(spc);

	TI()UserControl.SetOutFlag(OUTOK);

	if (roomCounter == 6969)
		{
		roomCounter = 0;
		}
	}


// --------------------------------------------------------------------------
// SetOutOK(): Sets for usual output.

void SetOutOK(void)
	{
	TI()UserControl.SetOutFlag(OUTOK);
	}


// --------------------------------------------------------------------------
// UserOutputControl::CheckInput(): Returns TRUE if the user has aborted
//	typeout

Bool UserOutputControl::CheckInput(Bool Pause)
	{
	Bool toReturn = FALSE;

	if (Continuous)
		{
		Pause = FALSE;
		}

	// Cannot abort IMPERVIOUS
	if (GetOutFlag() == IMPERVIOUS)
		{
		// for screenblanker
		KBReady();
		return (FALSE);
		}

	// Carrier loss and not on Console
	if (!HaveConnectionToUser())
		{
		SetOutFlag(OUTSKIP);

		return (TRUE);
		}

	// Check for keypress
	if (BBSCharReady() || Pause)
		{
		int c;

		if (!Pause)
			{
			c = toupper(iCharNE());
			}

		if (Pause || c == 'P' || c == 19)   // P or ^S (XOFF) - Pause
			{
			if (Pause)
				{
				if (!outSpeech(TRUE, TI()loggedIn ? TI()CurrentUser->GetMorePrompt() : cfg.moreprompt))
					{
					putWord((uchar *) (TI()loggedIn ? TI()CurrentUser->GetMorePrompt() : cfg.moreprompt));
					}
				}

			do
				{
				// wait to resume
				c = toupper(iCharNE());
				} while (!TI()CurrentUser->IsPUnPauses() &&
						(c == 'P' || c == 19));

			if (Pause)
				{
				int i, backspace = strlen(TI()loggedIn ? TI()CurrentUser->GetMorePrompt() : cfg.moreprompt);

				for (i = 0; i < backspace; i++)
					{
					doBS();
					}
				}
			}

		if (GetOutFlag() == NOSTOP)
			{
			return (FALSE);
			}

		const Bool WasFormatting = TI()OC.Formatting;
		TI()OC.Formatting = TRUE;

		switch (c)
			{
			case '9':
				{
				if (TI()hitSix)
					{
					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (!outSpeech(TRUE, getmsg(69)))
						{
						putWord((uchar *) getmsg(69));
						}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					doCR();
					}

				break;
				}

			case 'J':                               // jump paragraph
				{
				doCR();

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1477));

				termCap(TERM_BOLD);
				if (!outSpeech(TRUE, getmsg(1227)))
					{
					putWord((uchar *) getmsg(1227));
					}

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1478));

				doCR();

				SetOutFlag(OUTPARAGRAPH);

				break;
				}

			case 'K':                               // kill
				{
				if (CanK)
					{
					TI()MRO.DotoMessage = PULL_IT;

					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (!outSpeech(TRUE, getmsg(1228)))
						{
						putWord((uchar *) getmsg(1228));
						}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					SetOutFlag(OUTNEXT);

					toReturn = TRUE;
					}

				break;
				}

			case 'M':                               // mark
				{
				if (CanM)
					{
					TI()MRO.DotoMessage = MARK_IT;

					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (!outSpeech(TRUE, getmsg(1229)))
							{
							putWord((uchar *) getmsg(1229));
							}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					SetOutFlag(OUTNEXT);

					toReturn = TRUE;
					}

				break;
				}

			case '*':                               // censor
				{
				if (CanStar)
					{
					TI()MRO.DotoMessage = CENSOR_IT;

					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (!outSpeech(TRUE, getmsg(1230)))
						{
						putWord((uchar *) getmsg(1230));
						}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					SetOutFlag(OUTNEXT);

					toReturn = TRUE;
					}

				break;
				}

			case 'N':                               // next
				{
				doCR();

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1477));

				termCap(TERM_BOLD);
				if (!outSpeech(TRUE, getmsg(1231)))
						{
						putWord((uchar *) getmsg(1231));
						}

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1478));

				doCR();
				SetOutFlag(OUTNEXT);

				toReturn = TRUE;
				break;
				}

			case 'S':                               // stop
				{
				TI()numLines = 0;	// Don't pause for stop!

				doCR();

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1477));

				termCap(TERM_BOLD);
				if (!outSpeech(TRUE, getmsg(1232)))
					{
					putWord((uchar *) getmsg(1232));
					}

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1478));

				doCR();
				SetOutFlag(OUTSKIP);

				toReturn = TRUE;
				break;
				}

			case 'C':                               // continuous
				{
				doCR();

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1477));

				termCap(TERM_BOLD);
				if (!Continuous)
					{
					if (!outSpeech(TRUE, getmsg(1233)))
						{
						putWord((uchar *) getmsg(1233));
						}
					}
				else
					{
					if (!outSpeech(TRUE, getmsg(1234)))
						{
						putWord((uchar *) getmsg(1234));
						}
					}

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1478));

				Continuous = !Continuous;

				doCR();

				break;
				}

			case 'R':
				{
				if (CanR)
					{
					TI()MRO.DotoMessage = REVERSE_READ;
					SetOutFlag(OUTNEXT);
					}

				break;
				}

			case 'V':
				{
				TI()MRO.Verbose = !TI()MRO.Verbose;

				doCR();

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1477));

				termCap(TERM_BOLD);
				if (TI()MRO.Verbose)
					{
					if (!outSpeech(TRUE, getmsg(1235)))
						{
						putWord((uchar *) getmsg(1235));
						}
					}
				else
					{
					if (!outSpeech(TRUE, getmsg(1236)))
						{
						putWord((uchar *) getmsg(1236));
						}
					}

				termCap(TERM_NORMAL);
				putWord((const uchar *) getmsg(1478));

				doCR();

				break;
				}

			case '!':
				{
				if (CanBang)
					{
					TI()MRO.Headerscan = !TI()MRO.Headerscan;

					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (TI()MRO.Headerscan)
						{
						if (!outSpeech(TRUE, getmsg(1237)))
							{
							putWord((uchar *) getmsg(1237));
							}
						}
					else
						{
						if (!outSpeech(TRUE, getmsg(1238)))
							{
							putWord((uchar *) getmsg(1238));
							}
						}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					doCR();
					}

				break;
				}

			case '@':
				{
				if (CanAt)
					{
					TI()MRO.DotoMessage = REPLY;

					doCR();

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1477));

					termCap(TERM_BOLD);
					if (!outSpeech(TRUE, getmsg(1306)))
						{
						putWord((uchar *) getmsg(1306));
						}

					termCap(TERM_NORMAL);
					putWord((const uchar *) getmsg(1478));

					doCR();
					}

				break;
				}
			}

		TI()OC.Formatting = WasFormatting;

		if (c == '6')
			{
			TI()hitSix = TRUE;
			}
		else
			{
			TI()hitSix = FALSE;
			}
		}

	return (toReturn);
	}
