// --------------------------------------------------------------------------
// Citadel: DoRead.CPP
//
// Handles the .Read... commands

#include "ctdl.h"
#pragma hdrstop

#include "room.h"
#include "readinfo.h"
#include "filecmd.h"
#include "viewlog.h"
#include "log.h"
#include "msg.h"
#include "hall.h"
#include "boolexpr.h"
#include "group.h"
#include "menus.h"
#include "miscovl.h"


// --------------------------------------------------------------------------
// Contents
//
//
// doRead() 		handles R(ead) command


// --------------------------------------------------------------------------
// doRead(): Handles R(ead) command.

void doRead(Bool moreYet, char first)
// moreYet: TRUE to accept following parameters
// first:	first parameter if TRUE
	{
	Bool abort;
	OldNewPick whichMess;
	Bool revOrder;
	Bool textverbose = FALSE;
	Bool read_forward_userlog = FALSE;
	long howMany = 0;
	Bool lastNum = FALSE;

	ClearMsgReadOptions(&TI()MRO);

	SetDoWhat(DOREAD);

	if (moreYet)
		{
		first = 0;
		}

	mPrintf(getmsg(290));

	abort = FALSE;
	revOrder = FALSE;
	whichMess = WhoKnows;

	resetMsgfilter(FALSE);

	if (!TI()loggedIn && !cfg.unlogReadOk)
		{
		CRmPrintfCR(getmsg(291));
		return;
		}

	int OptionCounter = 0;

	do
		{
		int ich;
		const int letter = toupper(first ? (int) first : (ich = iCharNE()));

		if (++OptionCounter == 69)
			{
			mPrintf(pctss, getmsg(69));
			OptionCounter = 0;
			}

		if (isdigit(letter))
			{
			if (!lastNum)
				{
				howMany = 0;
				}

			lastNum = TRUE;

			mPrintf(pctc, letter);

			howMany *= 10;
			howMany += letter - '0';
			}
		else
			{
			if (lastNum)
				{
				mPrintf(spc);
				}
			lastNum = FALSE;

			switch (letter)
				{
				case 'A':
					{
					if (cfg.readall == 0 ||
							(cfg.readall == 1 && TI()CurrentUser->IsAide()) ||

							(cfg.readall == 2 && TI()CurrentUser->IsSysop()))
						{
						mPrintf(getmsg(292));

						TI()MRO.All = TRUE;
						}

					break;
					}

				case 'B':
					{
					mPrintf(getmsg(298), cfg.Luser_nym);
					TI()rf.User = TRUE;
					break;
					}

				case 'C':
					{
					mPrintf(getmsg(299));
					showconfig(0, FALSE);
					abort = TRUE;
					break;
					}

				case 'D':
					{
					mPrintf(getmsg(300));

					if (CheckDirectoryRoom())
						{
						if (whichMess == WhoKnows)
							{
							whichMess = OldAndNew;
							}

						readdirectory(whichMess);
						}

					abort = TRUE;
					TI()MRO.Reverse = FALSE;
					break;
					}

				case 'E':
					{
					mPrintf(getmsg(230), ns);
					TI()rf.Mail = TRUE;
					break;
					}

				case 'F':
					{
					mPrintf(getmsg(303));
					revOrder = FALSE;
					whichMess = OldAndNew;
					read_forward_userlog = TRUE;
					break;
					}

				case 'G':
					{
					mPrintf(getmsg(236), cfg.Ugroup_nym);
					TI()rf.Group = TRUE;
					break;
					}

				case 'H':
					{
					mPrintfCR(pcts, cfg.Uhalls_nym);
					readhalls();
					abort = TRUE;
					break;
					}

				case 'I':
					{
					mPrintf(getmsg(301));

					if (CheckDirectoryRoom())
						{
						if (whichMess == WhoKnows)
							{
							whichMess = OldAndNew;
							}

						ReadInfoFile(TRUE, whichMess);
						}

					abort = TRUE;
					TI()MRO.Reverse = FALSE;
					break;
					}

				case 'K':
				case '*':
					{
					mPrintf(getmsg(297));
					TI()rf.Text = TRUE;
					break;
					}

				case 'L':
					{
					mPrintf(getmsg(272));
					TI()rf.Local = TRUE;
					break;
					}

				case '\n':
				case '\r':
				case 'M':
					{
					mPrintf(pcts, cfg.Umsgs_nym);
					moreYet = FALSE;
					break;
					}

				case 'N':
					{
					mPrintf(getmsg(305));
					whichMess = NewOnly;
					break;
					}

				case 'O':
					{
					mPrintf(getmsg(237));
					revOrder = TRUE;
					read_forward_userlog = FALSE;
					whichMess = OldOnly;
					break;
					}

				case 'P':
					{
					mPrintf(getmsg(307));
					TI()rf.Public = TRUE;
					break;
					}

				case 'R':
					{
					mPrintf(getmsg(308));
					revOrder = TRUE;
					read_forward_userlog = TRUE;
					TI()MRO.Reverse = TRUE;
					whichMess = OldAndNew;
					break;
					}

				case 'S':
					{
					mPrintfCR(getmsg(309));
					ShowSystemStatus();
					abort = TRUE;
					break;
					}

				case 'T':
					{
					mPrintf(getmsg(310));
					TI()MRO.Verbose = textverbose;

					if (!CheckDirectoryRoom())
						{
						return;
						}

					if (!TI()CurrentUser->IsDownload())
						{
						CRmPrintfCR(getmsg(364), getmsg(366));
						return;
						}

					// handle uponly flag
					if (IsRoomUploadOnly(TI()thisRoom) &&
							!TI()CurrentUser->HasRoomPrivileges(TI()thisRoom))
						{
						CRmPrintfCR(getmsg(214), cfg.Uroom_nym);
						return;
						}

					if (whichMess == WhoKnows)
						{
						whichMess = OldAndNew;
						}

					readtextfile(whichMess);
					abort = TRUE;
					break;
					}

				case 'U':
					{
					mPrintfCR(getmsg(311), cfg.Uuser_nym);
					Readlog(read_forward_userlog, whichMess, howMany);
					abort = TRUE;
					break;
					}

				case 'V':
					{
					mPrintf(getmsg(279));
					TI()MRO.Verbose = TRUE;
					textverbose = TRUE;
					break;
					}

				case 'W':
					{
					mPrintf(getmsg(312));
					if (!CheckDirectoryRoom())
						{
						return;
						}

					if (!TI()CurrentUser->IsDownload())
						{
						CRmPrintfCR(getmsg(364), getmsg(366));
						return;
						}

					// handle uponly flag
					if (IsRoomUploadOnly(TI()thisRoom) &&
							!TI()CurrentUser->HasRoomPrivileges(TI()thisRoom))
						{
						CRmPrintfCR(getmsg(214), cfg.Uroom_nym);
						return;
						}

					readwc();
					abort = TRUE;
					break;
					}

				case 'Z':
					{
					mPrintf(getmsg(313));

					if (CheckDirectoryRoom())
						{
						if (whichMess == WhoKnows)
							{
							whichMess = OldAndNew;
							}

						readArchive(whichMess);
						}

					abort = TRUE;
					break;
					}

				case '#':
					{
					mPrintf(getmsg(294), cfg.Lmsg_nym);
					TI()MRO.Number = TRUE;
					break;
					}

				case '&':
					{
					mPrintf(getmsg(295));
					TI()MRO.Date = TRUE;
					break;
					}

				case '!':
					{
					mPrintf(getmsg(296));
					TI()MRO.Headerscan = TRUE;
					break;
					}

				case ESC:
					{
					abort = TRUE;
					break;
					}

				default:
					{
					oChar(ich);
					mPrintf(sqst);
					abort = TRUE;
					if (TI()CurrentUser->IsExpert())
						{
						break;
						}
					}

				case '?':
					{
					if (letter == '?')
						{
						oChar('?');
						}

					SetDoWhat(READMENU);

					showMenu(M_READOPT);
					abort = TRUE;
					break;
					}
				}
			}

		first = 0;
		} while (moreYet && !abort);

	if (abort)
		{
		return;
		}

	// no by-user read in anon rooms unless read all
	if (IsRoomAnonymous(TI()thisRoom) && TI()rf.User && !TI()MRO.All)
		{
		CRCRmPrintfCR(getmsg(314), cfg.Lrooms_nym);
		return;
		}

	if (whichMess == WhoKnows)
		{
		whichMess = NewOnly;
		}

	doCR();
	showMessages(whichMess, revOrder, howMany);
	}

Bool ProcessReadFilter(ReadFilter *rf, Bool AllowMetaGroups)
	{
	if (rf->User)
		{
		if (!getString(cfg.Luser_nym, rf->SearchUser, LABELSIZE, FALSE, ECHO,
				TI()rf2.SearchUser))
			{
			return (FALSE);
			}

		normalizeString(rf->SearchUser);
		stripansi(rf->SearchUser);

		if (!*(rf->SearchUser))
			{
			rf->User = FALSE;
			}
		}

	if (rf->Group)
		{
		char groupname[256];

		Bool GroupDone = FALSE;
		do
			{
			if (TI()rf2.SearchGroup[0] != BOOLEAN_END &&
					IsBooleanExpressionValid(TI()rf2.SearchGroup))
				{
				CRmPrintf(getmsg(553));
				ShowBooleanExpression(TI()rf2.SearchGroup, ShowGroupWithMeta);
				doCR();
				}

			if (!getString(cfg.Lgroup_nym, groupname, 255, TRUE, ECHO, ns))
				{
				return (FALSE);
				}

			stripansi(groupname);

			if (*groupname == '?')
				{
				ListGroups(TRUE);
				}
			else if (*groupname)
				{
				if (SameString(groupname, spc))
					{
					GroupDone = TRUE;
					rf->Group = FALSE;
					}
				else
					{
					BoolExpr Expression;

					if (!CreateBooleanExpression(groupname, AllowMetaGroups ?
							TestGroupOrMetaExists : TestGroupExists,
							Expression))
						{
						CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
						}
					else
						{
						memcpy(rf->SearchGroup, Expression, sizeof(BoolExpr));
						GroupDone = TRUE;
						}
					}
				}
			else
				{
				if (TI()rf2.SearchGroup[0] != BOOLEAN_END &&
						IsBooleanExpressionValid(TI()rf2.SearchGroup))
					{
					memcpy(rf->SearchGroup, TI()rf2.SearchGroup, sizeof(BoolExpr));
					}
				else
					{
					rf->Group = FALSE;
					}

				GroupDone = TRUE;
				}
			} while (!GroupDone);

		if (rf->Group)
			{
			CRmPrintf(getmsg(198));
			ShowBooleanExpression(rf->SearchGroup, ShowGroupWithMeta);
			mPrintfCR(getmsg(552));
			}
		}

	if (rf->Text)
		{
		if (!getString(getmsg(1015), rf->SearchText, LABELSIZE, FALSE, ECHO,
				TI()rf2.SearchText))
			{
			return (FALSE);
			}

		normalizeString(rf->SearchText);

		if (!*rf->SearchText)
			{
			rf->Text = FALSE;
			}
		}

	return (TRUE);
	}

void resetMsgfilter(int resetOld)
	{
	if (resetOld)
		{
		CopyStringToBuffer(TI()rf2.SearchUser, TI()CurrentUser->GetName(), LABELSIZE);
		stripansi(TI()rf2.SearchUser);
		TI()rf2.SearchGroup[0] = 0;
		TI()rf2.SearchGroup[1] = BOOLEAN_END;
		TI()rf2.SearchText[0] = 0;
		}
	else
		{
		if (*TI()rf.SearchUser)
			{
			CopyStringToBuffer(TI()rf2.SearchUser, TI()rf.SearchUser, LABELSIZE);
			}

		if (TI()rf.SearchGroup[0] != BOOLEAN_END)
			{
			memcpy(TI()rf2.SearchGroup, TI()rf.SearchGroup, sizeof(BoolExpr));
			}

		if (*TI()rf.SearchText)
			{
			CopyStringToBuffer(TI()rf2.SearchText, TI()rf.SearchText, LABELSIZE);
			}
		}

	memset(&TI()rf, 0, sizeof(ReadFilter));
	TI()rf.SearchGroup[0] = BOOLEAN_END;
	}
