// --------------------------------------------------------------------------
// Citadel: Log3.CPP
//
// .Enter Configuration and .Sysop Userlog edit

#include "ctdl.h"
#pragma hdrstop

#include "log.h"
#include "net.h"
#include "hall.h"
#include "room.h"
#include "maillist.h"
#include "filecmd.h"
#include "tallybuf.h"
#include "blurbs.h"
#include "miscovl.h"
#include "term.h"


// --------------------------------------------------------------------------
// Contents
//
// configure()	sets user configuration via menu
// newPW()		is menu-level routine to change password & initials


// --------------------------------------------------------------------------
// newPW(): Menu-level routine to change password & initials.
//
// Input:
//	Bool check: TRUE to check if user knows old in;pw; FALSE to not
//
// Return value:
//	None.

void newPW(Bool check)
	{
	char InitPw[LABELSIZE*2+2];
	char passWord[LABELSIZE*2+2];
	char Initials[LABELSIZE*2+2];
	char oldPw[LABELSIZE*2+2];
	char oldIn[LABELSIZE*2+2];
	char *semicolon;
	int goodpw;

	SetDoWhat(ENTERPW);

	if (check)
		{
		if (!getYesNo(getmsg(62), 0))
			{
			return;
			}

		getNormStr(getmsg(1116), InitPw, 40, NO_ECHO);

		semicolon = strchr(InitPw, ';');

		if (semicolon)
			{
			normalizepw(InitPw, Initials, passWord);
			}
		else
			{
			strcpy(Initials, InitPw);

			getNormStr(getmsg(1117), passWord, LABELSIZE, NO_ECHO);
			}

		if (!SameString(Initials, TI()CurrentUser->GetInitials()) ||
				!SameString(passWord, TI()CurrentUser->GetPassword()))
			{
			CRmPrintfCR(getmsg(1118));
			return;
			}
		}

	dospCR();
	dospCR();

	strcpy(oldIn, TI()CurrentUser->GetInitials());
	strcpy(oldPw, TI()CurrentUser->GetPassword());

	do
		{
		getNormStr(getmsg(603), InitPw, 61, NO_ECHO);
		dospCR();

		semicolon = strchr(InitPw, ';');

		if (semicolon)
			{
			normalizepw(InitPw, Initials, passWord);
			}
		else
			{
			strcpy(Initials, InitPw);
			}

		// do not allow anything over LABELSIZE characters
		Initials[LABELSIZE] = '\0';

		if (!semicolon)
			{
			getNormStr(getmsg(604), passWord, LABELSIZE, NO_ECHO);
			dospCR();
			}

		goodpw = (((FindPwInHashInTable(Initials, passWord) == CERROR) &&
				strlen(passWord) >= 2) ||
				(SameString(Initials, oldIn) && SameString(passWord, oldPw)));

		if (!goodpw)
			{
			CRmPrintfCR(getmsg(605));
			}
		} while (!goodpw && HaveConnectionToUser());

	// insure against loss of carrier
	if (HaveConnectionToUser())
		{
		TI()CurrentUser->SetInitials(Initials);
		TI()CurrentUser->SetPassword(passWord);
		TI()CurrentUser->SetPasswordChangeTime(time(NULL));

		storeLog();

		displaypw(TI()CurrentUser->GetName(), TI()CurrentUser->GetInitials(),
				TI()CurrentUser->GetPassword());

		trap(getmsg(606), T_PASSWORD);
		}
	}



// --------------------------------------------------------------------------
// Everything from here down is for the .EC and .SU commands


// --------------------------------------------------------------------------
// forwardaddr(): Sets up forwarding address for mail.
//
// Input:
//	LogEntry *EditLog is a pointer to the user to edit.

static void forwardaddr(LogEntry *EditLog)
	{
	char str[LABELSIZE+LABELSIZE+2];

	doCR();
	getNormStr(getecmsg(5), str, LABELSIZE + LABELSIZE + 1, ECHO);
	doCR();

	if (!*str)
		{
		EditLog->SetForwardToNode(FALSE);
		EditLog->SetForwardAddr(ns);
		EditLog->SetForwardAddrNode(ns);
		EditLog->SetForwardAddrRegion(ns);

		mPrintfCR(getecmsg(6), cfg.Lmsgs_nym);
		}
	else
		{
		label ruser;
		label rnode;
		label rregion;
		label raddress;

		parseNetAddress(str, ruser, rnode, rregion, raddress);

		if (!*rnode)		// if not forwarding to a node
			{
			const l_slot logslot = FindPersonByPartialName(str);

			if (logslot == CERROR)
				{
				mPrintfCR(getmsg(595), str);
				}
			else
				{
				EditLog->SetForwardToNode(FALSE);
				EditLog->SetForwardAddr(LogTab->GetEntry(logslot)->GetName());
				EditLog->SetForwardAddrNode(ns);
				EditLog->SetForwardAddrRegion(ns);

				mPrintfCR(getecmsg(7), cfg.Lmsgs_nym, EditLog->GetForwardAddr());
				}
			}
		else			// if forwarding to node
			{
			EditLog->SetForwardToNode(TRUE);
			EditLog->SetForwardAddr(ruser);
			EditLog->SetForwardAddrNode(rnode);
			EditLog->SetForwardAddrRegion(rregion);

			mPrintfCR(getecmsg(8), cfg.Lmsgs_nym, EditLog->GetForwardAddr(),
					EditLog->GetForwardAddrNode());
			}
		}
	}


// --------------------------------------------------------------------------
// defaulthall(): Edits default hall for a log entry.
//
// Input:
//	LogEntry *EditLog: The log entry to edit.
//	Bool UserlogEdit: TRUE if from .SU, FALSE if from .EC.

static void defaulthall(LogEntry *EditLog, Bool UserlogEdit)
	{
	doCR();

	if (!UserlogEdit && EditLog->IsDefaultHallLocked())
		{
		CRmPrintfCR(getecmsg(9), cfg.Lhall_nym);
		}
	else
		{
		label hallname;

		do
			{
			if (!getString(cfg.Lhall_nym, hallname, LABELSIZE, TRUE, ECHO,
					EditLog->GetDefaultHall()))
				{
				return;
				}

			if (*hallname == '?')
				{
				ListHalls(TRUE);
				}
			} while (*hallname == '?');

		if (SameString(hallname, EditLog->GetDefaultHall()))
			{
			// no change.
			}
		else if (SameString(hallname, spc))
			{
			// Single space: use this hall.
			EditLog->SetDefaultHall(HallData->GetEntry(TI()thisHall)->GetName());
			}
		else if (SameString(hallname, spcspc))
			{
			// Double space: back to Root.
			EditLog->SetDefaultHall(HallData->GetEntry(0)->GetName());
			}
		else
			{
			normalizeString(hallname);

			if (*hallname)
				{
				h_slot slot = partialhall(hallname);

				if ((slot == CERROR) || !accesshall(slot))
					{
					CRmPrintfCR(getmsg(611), cfg.Lhall_nym);
					}
				else
					{
					EditLog->SetDefaultHall(HallData->GetEntry(slot)->
							GetName());
					}
				}
			}

		CRmPrintfCR(getecmsg(11), cfg.Lhall_nym, EditLog->GetDefaultHall());
		}
	}


// --------------------------------------------------------------------------
// doColumn(): Used to columnize menus
//
// Input:
//	Bool *Col: TRUE if in the second column; FALSE if in first
//
// Output:
//	Bool *Col: Modified to new status

static void doColumn(Bool *Col)
	{
	if (!*Col)
		{
		mPrintf(getecmsg(1));
		}
	else
		{
		doCR();
		}

	*Col = !*Col;
	}


// --------------------------------------------------------------------------

static void listExcl(const strList *theList, const char *Pmsg, const char *Pmsgs)
	{
	if (theList)
		{
		CRmPrintfCR(getecmsg(18), Pmsg);

		prtList(LIST_START);
		for (const strList *theStr = theList; theStr;
				theStr = (const strList *) getNextLL(theStr))
			{
			prtList(theStr->string);
			}

		prtList(LIST_END);
		}
	else
		{
		CRmPrintfCR(getecmsg(19), Pmsgs);
		}
	}


static Bool FinishUpMenu(void)
	{
	CRmPrintfCR(getecmsg(16));
	return (!TI()CurrentUser->IsExpert());
	}

// --------------------------------------------------------------------------
// editIt(): Edits one of the message exclusion types.
//
// Input:
//	strList **theList: Pointer to base of list being edited
//	const char *Pmsg: What the list is called (singular)
//	const char *Pmsgs: What the list is called (plural)
//
// Output:
//	strList **theList: New, edited, list.

static void editIt(strList **theList, const char *Pmsg, const char *Pmsgs)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;
	strList *theStr;

	mPrintfCR(Pmsg);

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintfCR(getecmsg(12), Pmsg);
			CRmPrintf(getecmsg(13));
			CRmPrintf(getecmsg(14));
			CRmPrintfCR(getecmsg(15));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(17), Pmsg);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'L':
				{
				mPrintfCR(getmsg(340));

				listExcl(*theList, Pmsg, Pmsgs);

				break;
				}

			case 'A':
				{
				char ooga[70];

				mPrintfCR(getmsg(358));

				do
					{
					getString(getecmsg(20), ooga, 69 /* Dude! */, TRUE, ECHO,
							ns);

					if (*ooga == '?')
						{
						listExcl(*theList, Pmsg, Pmsgs);
						}
					} while (*ooga == '?');

				if (*ooga)
					{
					for (theStr = *theList; theStr; 
							theStr = (strList *) getNextLL(theStr))
						{
						if (SameString(theStr->string, ooga))
							{
							mPrintf(getecmsg(21));
							break;
							}
						}

					if (!theStr)
						{
						theStr = (strList *) addLL((void **) theList,
								sizeof(*theStr) + strlen(ooga));

						if (theStr)
							{
							strcpy(theStr->string, ooga);
							}
						}
					}

				break;
				}

			case 'R':
				{
				char ooga[70];

				mPrintfCR(getmsg(359));

				do
					{
					getString(getecmsg(22), ooga, 69 /* Dude! */, TRUE, ECHO,
							ns);

					if (*ooga == '?')
						{
						listExcl(*theList, Pmsg, Pmsgs);
						}
					} while (*ooga == '?');

				if (*ooga)
					{
					int i;
					for (i = 1, theStr = *theList; theStr;
							theStr = (strList *) getNextLL(theStr), i++)
						{
						if (SameString(theStr->string, ooga))
							{
							deleteLLNode((void **) theList, i);
							break;
							}
						}

					if (!theStr)
						{
						mPrintf(getecmsg(23));
						}
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}


// --------------------------------------------------------------------------

static void listAuthorTags(const LogEntry *EditLog, const char *Author)
	{
	Bool Started = FALSE;
	doCR();

	for (const pairedStrings *theTag = EditLog->GetTagUserPointer(); theTag;
			theTag = (pairedStrings *) getNextLL(theTag))
		{
		if (SameString(theTag->string1, Author))
			{
			if (!Started)
				{
				mPrintfCR(getecmsg(296), cfg.Luser_nym, Author);

				prtList(LIST_START);
				Started = TRUE;
				}

			prtList(theTag->string2);
			}
		}

	if (Started)
		{
		prtList(LIST_END);
		}
	else
		{
		mPrintfCR(getecmsg(297), cfg.Luser_nym, Author);
		}
	}


// --------------------------------------------------------------------------

static void listTaggedAuthors(const LogEntry *EditLog)
	{
	if (EditLog->GetTagUserPointer())
		{
		CRmPrintfCR(getecmsg(294), cfg.Lusers_nym);

		strList *beenShown = NULL;

		prtList(LIST_START);
		for (const pairedStrings *theTag = EditLog->GetTagUserPointer();
				theTag; theTag = (pairedStrings *) getNextLL(theTag))
			{
			for (strList *theList = beenShown; theList;
					theList = (strList *) getNextLL(theList))
				{
				if (SameString(theList->string, theTag->string1))
					{
					break;
					}
				}

			if (!theList)
				{
				prtList(theTag->string1);

				theList = (strList *) addLL((void **) beenShown,
						sizeof(strList) + strlen(theTag->string1));

				if (theList)
					{
					strcpy(theList->string, theTag->string1);
					}
				else
					{
					mPrintf(getmsg(188), getecmsg(322));
					}
				}
			}

		disposeLL((void **) &beenShown);

		prtList(LIST_END);
		}
	else
		{
		CRmPrintfCR(getecmsg(295), cfg.Luser_nym);
		}
	}


// --------------------------------------------------------------------------
// editTags(): Edits message author tags.
//
// Input:
//	LogEntry *EditLog: Log entry to edit.

static void editTags(LogEntry *EditLog)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	mPrintfCR(getecmsg(25), cfg.Umsg_nym);

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintfCR(getecmsg(25), cfg.Umsg_nym);
			CRmPrintf(getecmsg(13));
			CRmPrintf(getecmsg(14));
			CRmPrintfCR(getecmsg(15));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(26), cfg.Lmsg_nym);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'L':
				{
				mPrintfCR(getmsg(340));

				if (EditLog->GetTagUserPointer())
					{
					CRmPrintfCR(getecmsg(27), cfg.Lmsg_nym);

					TI()UserControl.SetOutFlag(OUTOK);

					for (const pairedStrings *theTag =
							EditLog->GetTagUserPointer(); theTag;
							theTag = (pairedStrings *) getNextLL(theTag))
						{
						mPrintfCR(getecmsg(2), theTag->string1,
								theTag->string2);
						}
					}
				else
					{
					CRmPrintfCR(getecmsg(28), cfg.Lmsg_nym);
					}

				break;
				}

			case 'A':
				{
				label ooga;

				mPrintfCR(getmsg(358));

				do
					{
					getString(getecmsg(29), ooga, LABELSIZE, TRUE, ECHO, ns);

					if (*ooga == '?')
						{
						listTaggedAuthors(EditLog);
						}
					} while (*ooga == '?');

				if (*ooga)
					{
					label ooga2;

					do
						{
						getString(getecmsg(30), ooga2, LABELSIZE, TRUE, ECHO,
								ns);

						if (*ooga2 == '?')
							{
							listAuthorTags(EditLog, ooga);
							}
						} while (*ooga2 == '?');

					if (*ooga2)
						{
						EditLog->AddTagUser(ooga, ooga2);
						}
					}

				break;
				}

			case 'R':
				{
				label ooga;

				mPrintfCR(getmsg(359));

				do
					{
					getString(getecmsg(31), ooga, LABELSIZE, TRUE, ECHO, ns);

					if (*ooga == '?')
						{
						listTaggedAuthors(EditLog);
						}
					} while (*ooga == '?');

				if (*ooga && !EditLog->RemoveUserTag(ooga))
					{
					mPrintf(getecmsg(32));
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

static void DisplayOnOffWithColumn(int Msg, Bool Value, Bool *Col)
	{
	displayOnOff(getecmsg(Msg), Value);
	doColumn(Col);
	}

static void DisplayYesNoWithColumn(int Msg, Bool Value, Bool *Col)
	{
	displayYesNo(getecmsg(Msg), Value);
	doColumn(Col);
	}

static void DisplayOnOffWithCR(int Msg, Bool Value)
	{
	displayOnOff(getecmsg(Msg), Value);
	doCR();
	}

// --------------------------------------------------------------------------
// editTerminal(): Edits terminal stuff.
//
// Input:
//	LogEntry1 *EditLog1: Log entry to edit
//
// Output:
//	LogEntry1 *EditLog1: Modified entry.

static void editTerminal(LogEntry1 *EditLog1)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			Bool Col = FALSE;

			doCR();

			if (cfg.ecColor)
				{
				DisplayOnOffWithColumn(33, EditLog1->IsIBMANSI(), &Col);
				DisplayOnOffWithColumn(34, EditLog1->IsIBMColor(), &Col);
				}

			DisplayOnOffWithColumn(35, EditLog1->IsIBMGraph(), &Col);

			mPrintf(getecmsg(36), EditLog1->GetWidth());
			doColumn(&Col);

			DisplayOnOffWithColumn(37, EditLog1->IsUpperOnly(), &Col);
			DisplayOnOffWithColumn(38, EditLog1->IsLinefeeds(), &Col);
			DisplayOnOffWithColumn(39, EditLog1->IsTabs(), &Col);

			mPrintf(getecmsg(40), EditLog1->GetNulls());
			doColumn(&Col);

			if (EditLog1->IsIBMGraph())
				{
				DisplayOnOffWithColumn(41, EditLog1->IsIBMRoom(), &Col);
				}

			if (cfg.music)
				{
				DisplayOnOffWithColumn(42, EditLog1->IsMusic(), &Col);
				}

			// from here down is not columnized...
			if (Col)
				{
				doCR();
				}

			label temp;
			mPrintfCR(getecmsg(43), EditLog1->GetLinesPerScreen() ?
					itoa(EditLog1->GetLinesPerScreen(), temp, 10) :
					getecmsg(44));

			mPrintfCR(getecmsg(291), EditLog1->GetMorePrompt());

			if (EditLog1->IsIBMANSI())
				{
				mPrintfCR(getecmsg(45));
				}

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(46), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'I':
				{
				EditLog1->SetIBMGraph(changeOnOff(getecmsg(47),
						EditLog1->IsIBMGraph()));

				setlogTerm();
				break;
				}

			case 'W':
				{
				mPrintfCR(getecmsg(48));

				const long value = GetNumberWithBlurb(getecmsg(49), 10l, 255l,
							(long) EditLog1->GetWidth(), B_WIDTH);

				if (HaveConnectionToUser())
					{
					EditLog1->SetWidth((int) value);
					}

				break;
				}

			case 'L':
				{
				mPrintfCR(getecmsg(50));

				long value;

				Bool ShowBlb;
				do
					{
					ShowBlb = FALSE;

					value = getNumber(getecmsg(51), 0L, INT_MAX,
							EditLog1->GetLinesPerScreen(), TRUE, &ShowBlb);

					if (ShowBlb || value == 1 || value == 2)
						{
						dispBlb(B_LENGTH);
						}
					} while (ShowBlb || value == 1 || value == 2);

				EditLog1->SetLinesPerScreen((int) value);

				break;
				}

			case 'N':
				{
				mPrintfCR(getecmsg(53));

				EditLog1->SetNulls((int) GetNumberWithBlurb(getecmsg(54), 0L,
						255L, EditLog1->GetNulls(), B_NULLS));

				break;
				}

			case 'U':
				{
				EditLog1->SetUpperOnly(changeOnOff(getecmsg(56),
						EditLog1->IsUpperOnly()));
				break;
				}

			case 'F':
				{
				EditLog1->SetLinefeeds(changeOnOff(getecmsg(57),
						EditLog1->IsLinefeeds()));
				break;
				}

			case 'T':
				{
				EditLog1->SetTabs(changeOnOff(getecmsg(58),
						EditLog1->IsTabs()));
				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			case 'R':
				{
				if (EditLog1->IsIBMANSI())
					{
					mPrintf(getecmsg(59));
					askAttributes(EditLog1);
					break;
					}
				}	// Fall through

			case 'A':
				{
				if (toupper(c) == 'A' && cfg.ecColor)
					{
					EditLog1->SetIBMANSI(changeOnOff(getecmsg(60),
							EditLog1->IsIBMANSI()));

					setdefaultcolors();
					setlogTerm();
					break;
					}
				}

			case 'C':
				{
				if (toupper(c) == 'C' && cfg.ecColor)
					{
					EditLog1->SetIBMColor(changeOnOff(getecmsg(61),
							EditLog1->IsIBMColor()));

					setdefaultcolors();
					setlogTerm();
					break;
					}
				}

			case 'O':
				{
				if (toupper(c) == 'O' && EditLog1->IsIBMGraph())
					{
					EditLog1->SetIBMRoom(changeOnOff(getecmsg(62),
							EditLog1->IsIBMRoom()));
					break;
					}
				}

			case 'M':
				{
				if (toupper(c) == 'M' && cfg.music)
					{
					EditLog1->SetMusic(changeOnOff(getecmsg(63),
							EditLog1->IsMusic()));
					break;
					}
				}

			case '>':
				{
				char stuff[80];

				mPrintfCR(getecmsg(292));

				if (GetStringWithBlurb(getecmsg(293), stuff, 79,
						EditLog1->GetMorePrompt(), B_MOREPRMP) && *stuff)
					{
					if (SameString(stuff, spc))
						{
						EditLog1->SetMorePrompt(cfg.moreprompt);
						}
					else 
						{
						stripansi(stuff);
						normalizeString(stuff);
						EditLog1->SetMorePrompt(stuff);
						}
					}

				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}


// --------------------------------------------------------------------------
// editPersonalInfo(): Edits personal stuff
//
// Input/Output:
//	LogEntry1 *EditLog1: Log entry to edit

static void editPersonalInfo(LogEntry1 *EditLog1)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintf(getecmsg(64), EditLog1->GetRealName());
			CRmPrintf(getecmsg(65), EditLog1->GetPhoneNumber());
			CRmPrintf(getecmsg(66), EditLog1->GetMailAddr1());
			CRmPrintf(getecmsg(67), EditLog1->GetMailAddr2());
			CRmPrintfCR(getecmsg(68), EditLog1->GetMailAddr3());

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(300), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'R':
				{
				label stuff;

				mPrintfCR(getecmsg(69));

				if (GetStringWithBlurb(getecmsg(70), stuff, LABELSIZE,
						EditLog1->GetRealName(), B_REALNAME) && *stuff)
					{
					normalizeString(stuff);
					EditLog1->SetRealName(stuff);
					}

				break;
				}

			case 'P':
				{
				label stuff;

				mPrintfCR(getecmsg(71));

				if (GetStringWithBlurb(getecmsg(72), stuff, LABELSIZE,
						EditLog1->GetPhoneNumber(), B_PHONENUM) && *stuff)
					{
					normalizeString(stuff);
					EditLog1->SetPhoneNumber(stuff);
					}

				break;
				}

			case '1':
				{
				label stuff;

				mPrintfCR(getecmsg(73));

				if (GetStringWithBlurb(getecmsg(74), stuff, LABELSIZE,
						EditLog1->GetMailAddr1(), B_ADDRESS) && *stuff)
					{
					normalizeString(stuff);
					EditLog1->SetMailAddr1(stuff);
					}

				break;
				}

			case '2':
				{
				label stuff;

				mPrintfCR(getecmsg(75));

				if (GetStringWithBlurb(getecmsg(76), stuff, LABELSIZE,
						EditLog1->GetMailAddr2(), B_ADDRESS) && *stuff)
					{
					normalizeString(stuff);
					EditLog1->SetMailAddr2(stuff);
					}

				break;
				}

			case '3':
				{
				label stuff;

				mPrintfCR(getecmsg(77));

				if (GetStringWithBlurb(getecmsg(78), stuff, LABELSIZE,
						EditLog1->GetMailAddr3(), B_ADDRESS) && *stuff)
					{
					normalizeString(stuff);
					EditLog1->SetMailAddr3(stuff);
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}


// --------------------------------------------------------------------------
// editFormatStrings(): Edits format strings
//
// Input/Output:
//	LogEntry1 *EditLog1: Log entry to edit

static void editFormatStrings(LogEntry1 *EditLog1)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintf(getecmsg(79), EditLog1->GetPromptFormat());
			CRmPrintf(getecmsg(80), EditLog1->GetDateStamp());
			CRmPrintf(getecmsg(81), EditLog1->GetVerboseDateStamp());
			CRmPrintfCR(getecmsg(82), EditLog1->GetNetPrefix());

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(301), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'P':
				{
				char stuff[64];

				mPrintfCR(getecmsg(83));

				if (GetStringWithBlurb(getecmsg(84), stuff, 63,
						EditLog1->GetPromptFormat(), B_PROMPT) && *stuff)
					{
					if (SameString(stuff, spc))
						{
						EditLog1->SetPromptFormat(cfg.prompt);
						}
					else
						{
						normalizeString(stuff);
						EditLog1->SetPromptFormat(stuff);
						}
					}

				break;
				}

			case 'N':
				{
				label stuff;

				mPrintfCR(getecmsg(85));

				if (GetStringWithBlurb(getecmsg(86), stuff, LABELSIZE,
						EditLog1->GetNetPrefix(), B_NETPREFX) && *stuff)
					{
					if (SameString(stuff, spc))
						{
						EditLog1->SetNetPrefix(cfg.netPrefix);
						}
					else
						{
						normalizeString(stuff);
						EditLog1->SetNetPrefix(stuff);
						}
					}

				break;
				}

			case 'T':
				{
				char stuff[64];

				mPrintfCR(getecmsg(87));

				if (GetStringWithBlurb(getecmsg(88), stuff, 63,
						EditLog1->GetDateStamp(), B_TIME) && *stuff)
					{
					if (SameString(stuff, spc))
						{
						EditLog1->SetDateStamp(cfg.datestamp);
						}
					else
						{
						normalizeString(stuff);
						EditLog1->SetDateStamp(stuff);
						}
					}

				if (GetStringWithBlurb(getecmsg(89), stuff, 63,
						EditLog1->GetVerboseDateStamp(), B_TIME) && *stuff)
					{
					if (SameString(stuff, spc))
						{
						EditLog1->SetVerboseDateStamp(cfg.vdatestamp);
						}
					else
						{
						normalizeString(stuff);
						EditLog1->SetVerboseDateStamp(stuff);
						}
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

/* -------------------------------------------------------------------- */
/*	messageEditOptions		Sets message editor options 				*/
/* -------------------------------------------------------------------- */
static void listDictionary(LogEntry *EditLog)
	{
	TI()UserControl.SetOutFlag(OUTOK);

	if (EditLog->GetDictionaryPointer())
		{
		CRmPrintfCR(getecmsg(110));

		prtList(LIST_START);
		for (const strList *theStr = EditLog->GetDictionaryPointer();
				theStr; theStr = (strList *) getNextLL(theStr))
			{
			prtList(theStr->string);
			}

		prtList(LIST_END);
		}
	else
		{
		CRmPrintfCR(getecmsg(111));
		}
	}

static void spellCheckerOptions(LogEntry *EditLog)
	{
	int prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintfCR(getecmsg(94),
				getecmsg(EditLog->GetSpellCheckMode() + 95));

			DisplayOnOffWithCR(99, EditLog->IsCheckApostropheS());
			DisplayOnOffWithCR(100, EditLog->IsCheckAllCaps());
			DisplayOnOffWithCR(101, EditLog->IsCheckDigits());

			mPrintfCR(getecmsg(102));
			mPrintfCR(getecmsg(103));
			mPrintfCR(getecmsg(104));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(304), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case 'S':
				{
				EditLog->SetCheckApostropheS(changeOnOff(getecmsg(106),
						EditLog->IsCheckApostropheS()));
				break;
				}

			case 'D':
				{
				EditLog->SetCheckDigits(changeOnOff(getecmsg(107),
						EditLog->IsCheckDigits()));
				break;
				}

			case 'C':
				{
				EditLog->SetCheckAllCaps(changeOnOff(getecmsg(109),
						EditLog->IsCheckAllCaps()));
				break;
				}

			case 'L':
				{
				mPrintfCR(getmsg(340));

				listDictionary(EditLog);

				break;
				}

			case 'P':
				{
				int m;

				mPrintf(getecmsg(112));

				const int ii = toupper(iCharNE());

				if (ii == 'V')
					{
					m = 95;
					EditLog->SetSpellCheckMode(0);
					}
				else if (ii == 'R')
					{
					m = 96;
					EditLog->SetSpellCheckMode(1);
					}
				else if (ii == 'T')
					{
					m = 97;
					EditLog->SetSpellCheckMode(2);
					}
				else if (ii == 'A')
					{
					m = 98;
					EditLog->SetSpellCheckMode(3);
					}
				else
					{
					m = 113;
					oChar((char) ii);
					if (ii != '?')
						{
						mPrintf(sqst);
						}

					doCR(2);
					}

				mPrintfCR(getecmsg(m));
				break;
				}

			case 'A':
				{
				char word[70];

				mPrintfCR(getmsg(358));

				do
					{
					getString(getecmsg(116), word, 69 /* Dude! */, TRUE, ECHO,
							ns);

					if (*word == '?')
						{
						listDictionary(EditLog);
						}
					} while (*word == '?');

				if (*word)
					{
					if (EditLog->IsWordInDictionary(word))
						{
						CRmPrintfCR(getecmsg(117));
						}
					else
						{
						if (!EditLog->AddWordToDictionary(word))
							{
							mPrintf(getmsg(188), getecmsg(52));
							}
						}
					}

				break;
				}

			case 'R':
				{
				char word[70];

				mPrintfCR(getmsg(359));

				do
					{
					getString(getecmsg(118), word, 69 /* Dude! */, TRUE, ECHO,
							ns);

					if (*word == '?')
						{
						listDictionary(EditLog);
						}
					} while (*word == '?');

				if (*word && !EditLog->RemoveWordFromDictionary(word))
					{
					CRmPrintfCR(getecmsg(119));
					}

				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

static void listReplacedText(const LogEntry *EditLog)
	{
	if (EditLog->GetReplacePointer())
		{
		CRmPrintfCR(getecmsg(315));

		prtList(LIST_START);
		for (const pairedStrings *theRepl = EditLog->GetReplacePointer();
				theRepl; theRepl = (pairedStrings *) getNextLL(theRepl))
			{
			prtList(theRepl->string1);
			}

		prtList(LIST_END);
		}
	else
		{
		CRmPrintfCR(getecmsg(316));
		}
	}

static void textReplacementOptions(LogEntry *EditLog)
	{
	int prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			CRmPrintfCR(getecmsg(13));
			mPrintfCR(getecmsg(14));
			mPrintfCR(getecmsg(15));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(307), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'L':
				{
				mPrintfCR(getmsg(340));

				if (EditLog->GetReplacePointer())
					{
					CRmPrintfCR(getecmsg(308));

					TI()UserControl.SetOutFlag(OUTOK);

					for (const pairedStrings *theRepl =
							EditLog->GetReplacePointer(); theRepl;
							theRepl = (pairedStrings *) getNextLL(theRepl))
						{
						mPrintfCR(getecmsg(309), theRepl->string1,
								theRepl->string2);
						}
					}
				else
					{
					CRmPrintfCR(getecmsg(310));
					}

				break;
				}

			case 'A':
				{
				label ooga;

				mPrintfCR(getmsg(358));

				do
					{
					getString(getecmsg(311), ooga, LABELSIZE, TRUE, ECHO, ns);

					if (*ooga == '?')
						{
						listReplacedText(EditLog);
						}
					} while (*ooga == '?');

				if (*ooga)
					{
					for (const pairedStrings *theRepl = EditLog->GetReplacePointer();
							theRepl; theRepl = (pairedStrings *) getNextLL(theRepl))
						{
						if (SameString(theRepl->string1, ooga))
							{
							break;
							}
						}

					if (theRepl)
						{
						CRmPrintfCR(getecmsg(317));
						}
					else
						{
						label ooga2;

						getString(getecmsg(312), ooga2, LABELSIZE, FALSE,
								ECHO, ns);

						if (*ooga2)
							{
							EditLog->AddReplace(ooga, ooga2);
							}
						}
					}

				break;
				}

			case 'R':
				{
				label ooga;

				mPrintfCR(getmsg(359));

				do
					{
					getString(getecmsg(313), ooga, LABELSIZE, TRUE, ECHO, ns);

					if (*ooga == '?')
						{
						listReplacedText(EditLog);
						}
					} while (*ooga == '?');

				if (*ooga && !EditLog->RemoveReplace(ooga))
					{
					CRmPrintfCR(getecmsg(314));
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

static void messageEditOptions(LogEntry *EditLog)
	{
	int prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			doCR();

			DisplayOnOffWithCR(90, EditLog->IsVerboseContinue());
			DisplayOnOffWithCR(91, EditLog->IsConfirmSave());
			DisplayOnOffWithCR(92, EditLog->IsConfirmAbort());
			DisplayOnOffWithCR(93, EditLog->IsConfirmNoEO());

			mPrintfCR(getecmsg(284));
			mPrintfCR(getecmsg(303));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(298), cfg.Lmsg_nym);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'A':
				{
				EditLog->SetConfirmAbort(changeOnOff(getecmsg(105),
						EditLog->IsConfirmAbort()));
				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case 'E':
				{
				EditLog->SetConfirmNoEO(changeOnOff(getecmsg(108),
						EditLog->IsConfirmNoEO()));
				break;
				}

			case 'P':
				{
				mPrintfCR(getecmsg(305));

				spellCheckerOptions(EditLog);
				break;
				}

			case 'R':
				{
				mPrintfCR(getecmsg(306));

				textReplacementOptions(EditLog);
				break;
				}

			case 'S':
				{
				EditLog->SetConfirmSave(changeOnOff(getecmsg(114),
						EditLog->IsConfirmSave()));
				break;
				}

			case 'V':
				{
				EditLog->SetVerboseContinue(changeOnOff(getecmsg(115),
						EditLog->IsVerboseContinue()));
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

/* -------------------------------------------------------------------- */
/*	editMsgOption		Edits message read options						*/
/* -------------------------------------------------------------------- */
static void editMsgOption(LogEntry *EditLog, Bool UserlogEdit, Bool *pedited_pointers)
	{
	Bool prtMsg = !TI()CurrentUser->IsExpert();
	Bool quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			doCR();

			if (cfg.censor || UserlogEdit || TI()CurrentUser->IsSysop())
				{
				DisplayOnOffWithCR(155, EditLog->IsViewCensoredMessages());
				}

			if (EditLog->IsIBMANSI())
				{
				DisplayOnOffWithCR((153),
						EditLog->IsClearScreenBetweenMessages());
				}

			DisplayOnOffWithCR(151, EditLog->IsPauseBetweenMessages());
			DisplayOnOffWithCR(150, EditLog->IsViewSubjects());
			DisplayOnOffWithCR(152, EditLog->IsViewSignatures());

			mPrintfCR(getecmsg(120));
			mPrintfCR(getecmsg(121));
			mPrintfCR(getecmsg(122));
			mPrintfCR(getecmsg(123));
			DisplayOnOffWithCR(124, EditLog->IsExcludeEncryptedMessages());
			DisplayOnOffWithCR(125, !EditLog->IsHideMessageExclusions());

			mPrintfCR(getecmsg(126));

			prtMsg = FinishUpMenu();
			}

		const int c = DoMenuPrompt(getecmsg(299), cfg.Lmsg_nym);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case '*':
				{
				if (cfg.censor || UserlogEdit || TI()CurrentUser->IsSysop())
					{
					char temp[128];
					sprintf(temp, getecmsg(178), cfg.Lmsgs_nym);

					EditLog->SetViewCensoredMessages(changeOnOff(temp,
							EditLog->IsViewCensoredMessages()));

					*pedited_pointers = TRUE;

					if (EditLog->IsViewCensoredMessages() && !UserlogEdit)
						{
						dispBlb(B_DISCLAIM);
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '@':
				{
				char temp[128];

				sprintf(temp, getecmsg(187), cfg.Lmsg_nym);
				EditLog->SetPauseBetweenMessages(changeOnOff(temp,
						EditLog->IsPauseBetweenMessages()));
				break;
				}

			case 'A':
				{
				editIt(EditLog->GetKillUserPointerPointer(),
						getecmsg(127), getecmsg(128));
				break;
				}

			case ESC:
			case 'B':
				{
				mPrintf(getecmsg(24));
				quit = TRUE;
				break;
				}

			case 'C':
				{
				if (EditLog->IsIBMANSI())
					{
					char temp[128];

					sprintf(temp, getecmsg(189), cfg.Lmsg_nym);
					EditLog->SetClearScreenBetweenMessages(changeOnOff(temp,
							EditLog->IsClearScreenBetweenMessages()));
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'E':
				{
				EditLog->SetExcludeEncryptedMessages(
						!EditLog->IsExcludeEncryptedMessages());

				DisplayOnOffWithCR(129,
						EditLog->IsExcludeEncryptedMessages());
				break;
				}

			case 'G':
				{
				EditLog->SetViewSignatures(!EditLog->IsViewSignatures());
				mPrintfCR(getecmsg(182), EditLog->IsViewSignatures() ?
						ns : getecmsg(180));
				break;
				}

			case 'J':
				{
				EditLog->SetViewSubjects(!EditLog->IsViewSubjects());
				mPrintfCR(getecmsg(181), EditLog->IsViewSubjects() ?
						ns : getecmsg(180));
				break;
				}

			case 'M':
				{
				editTags(EditLog);
				break;
				}

			case 'N':
				{
				editIt(EditLog->GetKillNodePointerPointer(),
						getecmsg(130), getecmsg(131));
				break;
				}

			case 'O':
				{
				EditLog->SetHideMessageExclusions(
						!EditLog->IsHideMessageExclusions());

				DisplayOnOffWithCR(132, !EditLog->IsHideMessageExclusions());
				break;
				}

			case 'R':
				{
				editIt(EditLog->GetKillRegionPointerPointer(),
						getecmsg(133), getecmsg(134));
				break;
				}

			case 'T':
				{
				editIt(EditLog->GetKillTextPointerPointer(),
						getecmsg(135), getecmsg(135));
				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);

	doCR();
	}

/* -------------------------------------------------------------------- */
/*	userPointers()	Manually reset userlog pointers.					*/
/* -------------------------------------------------------------------- */
static void userPointers(LogEntry *ToEdit, Bool fromEC)
	{
	Bool menu = !TI()CurrentUser->IsExpert();

	mPrintfCR(getecmsg(55));

	for (;;)
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (menu)
			{
			CRmPrintfCR(getecmsg(268));
			mPrintfCR(getecmsg(269));
			mPrintfCR(getecmsg(270));
			mPrintfCR(getecmsg(271));
			mPrintfCR(getecmsg(272));

			CRmPrintfCR(getecmsg(273));

			menu = !TI()CurrentUser->IsExpert();
			}

		label Oldest, Newest;
		strcpy(Oldest, ltoac(cfg.oldest));
		strcpy(Newest, ltoac(cfg.newest));
		CRmPrintfCR(getecmsg(274), ltoac(cfg.newest - cfg.oldest + 1), Oldest,
				Newest);

		const int c = DoMenuPrompt(getecmsg(275), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		switch (toupper(c))
			{
			case 'R':
				{
				label roomname;
				r_slot roomslot;

				mPrintfCR(getecmsg(276));

				do
					{
					getString(getmsg(1279), roomname, LABELSIZE, TRUE, ECHO,
							GetRoomName(TI()thisRoom));

					if (*roomname == '?')
						{
						ListAllRooms(FALSE, TRUE, FALSE);
						}
					} while (*roomname == '?');

				roomslot = RoomExists(roomname);

				if (roomslot == CERROR)
					{
					roomslot = PartialRoomExists(roomname, TI()thisRoom, TRUE);

					// no partial room name to get to hidden room
					if (roomslot != CERROR)
						{
						if (!ToEdit->IsInRoom(roomslot))
							{
							roomslot = CERROR;
							}
						}
					}

				// cannot get to BIO rooms or public rooms you have been
				// removed from.
				if (roomslot != CERROR)
					{
					if (IsRoomBIO(roomslot) || !IsRoomHidden(roomslot))
						{
						if (!ToEdit->IsInRoom(roomslot))
							{
							roomslot = CERROR;
							}
						}
					}

				if (roomslot == CERROR || !(*roomname) ||
						(fromEC && !(ToEdit->CanAccessRoom(roomslot, FALSE, FALSE) &&
						theAlgorithm(roomslot, TI()thisHall, FALSE))))
					{
					if (*roomname)
						{
						CRmPrintf(getmsg(157), cfg.Lroom_nym, roomname);
						}
					}
				else
					{
					char prompt[128];
					ulong msgnumber;

					ToEdit->SetInRoom(roomslot, TRUE);

					sprintf(prompt, getecmsg(277), GetRoomName(roomslot));

					msgnumber = getNumber(prompt, 0L, cfg.newest,
							ToEdit->GetRoomNewPointer(roomslot), FALSE, NULL);

					ToEdit->SetRoomNewPointer(roomslot, msgnumber);
					}

				break;
				}

			case 'D':
				{
				r_slot i;

				mPrintfCR(getecmsg(278));

				TI()UserControl.SetOutFlag(OUTOK);
				doCR();

				for (i = 0;
						i < cfg.maxrooms && (!TI()UserControl.CheckInput(FALSE));
						i++)
					{
					if (IsRoomInuse(i) &&
							(!fromEC || (ToEdit->CanAccessRoom(i, FALSE, FALSE) &&
							theAlgorithm(i, TI()thisHall, FALSE))))
						{
						mPrintfCR(getecmsg(279), deansi(GetRoomName(i)),
								ltoac(ToEdit->GetRoomNewPointer(i)));
						}
					}

				break;
				}

			case 'N':
				{
				mPrintfCR(getecmsg(280), cfg.Lmsgs_nym);

				for (r_slot i = 0; i < cfg.maxrooms; i++)
					{
					ToEdit->SetRoomNewPointer(i, cfg.oldest - 1);
					}

				break;
				}

			case 'O':
				{
				mPrintfCR(getecmsg(281), cfg.Lmsgs_nym);

				for (r_slot i = 0; i < cfg.maxrooms; i++)
					{
					ToEdit->SetRoomNewPointer(i, cfg.newest);
					}

				break;
				}

			case 'S':
				{
				char prompt[128];
				ulong msgnumber;

				mPrintfCR(getecmsg(282));

				sprintf(prompt, getecmsg(283), cfg.Lmsg_nym);

				msgnumber = getNumber(prompt, 0L, LONG_MAX, -1l, FALSE, NULL);

				if (msgnumber)
					{
					if (msgnumber > cfg.newest)
						{
						mPrintfCR(getmsg(1010));
						}
					else
						{
						r_slot i;

						for (i = 0; i < cfg.maxrooms; i++)
							{
							ToEdit->SetRoomNewPointer(i, msgnumber);
							}

						doCR();
						}
					}

				break;
				}

			case ESC:
			case 'B':
				{
				mPrintfCR(getecmsg(24));
				return;
				}

			default:
				{
				mPrintfCR(getmsg(351));
				menu = TRUE;
				break;
				}
			}
		}
	}

static void configure(LogEntry *EditLog, Bool newUser, Bool UserlogEdit);

static void PrivilegeEdit(LogEntry *EditLog, Bool UserlogEdit, l_index Index)
	{
	doCR();

	Bool prtMsg = !TI()CurrentUser->IsExpert(), quit = FALSE;

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMsg)
			{
			Bool Col = FALSE;

			doCR();

			DisplayYesNoWithColumn(213, EditLog->IsSurnameLocked(), &Col);
			DisplayYesNoWithColumn(214, EditLog->IsUserSignatureLocked(), &Col);

			if (onConsole || cfg.sysopOk || !UserlogEdit)
				{
				DisplayYesNoWithColumn(215, EditLog->IsSysop(), &Col);
				}

			DisplayYesNoWithColumn(216, EditLog->IsAide(), &Col);
			DisplayYesNoWithColumn(217, EditLog->IsNode(), &Col);
			DisplayYesNoWithColumn(218, EditLog->IsPermanent(), &Col);
			DisplayYesNoWithColumn(219, EditLog->IsNetUser(), &Col);
			DisplayYesNoWithColumn(220, EditLog->IsProblem(), &Col);
			DisplayYesNoWithColumn(221, EditLog->IsMail(), &Col);
			DisplayYesNoWithColumn(222, EditLog->IsVerified(), &Col);

			if (cfg.borders)
				{
				DisplayYesNoWithColumn(223, EditLog->IsEnterBorders(), &Col);
				}

			DisplayYesNoWithColumn(224, EditLog->IsDefaultHallLocked(), &Col);
			DisplayOnOffWithColumn(225, EditLog->IsChat(), &Col);
			DisplayOnOffWithColumn(226, EditLog->IsMakeRoom(), &Col);
			DisplayOnOffWithColumn(227, EditLog->IsOut300(), &Col);
			DisplayYesNoWithColumn(228, EditLog->IsPsycho(), &Col);
			DisplayOnOffWithColumn(229, EditLog->IsUpload(), &Col);
			DisplayOnOffWithColumn(230, EditLog->IsDownload(), &Col);
			DisplayOnOffWithColumn(231, EditLog->IsPrintFile(), &Col);

			// from here down is not columnized...
			if (Col)
				{
				doCR();
				}

			mPrintfCR(getecmsg(212), EditLog->GetName());

			label tmp;
			mPrintfCR(getecmsg(232), EditLog->GetCallLimit() ?
					itoa(EditLog->GetCallLimit(), tmp, 10) : getecmsg(233));

			if (cfg.accounting)
				{
				mPrintf(getecmsg(234));

				if (EditLog->IsAccounting())
					{
					mPrintfCR(pcts, ltoac(EditLog->GetCredits() / 60));
					}
				else
					{
					mPrintfCR(getecmsg(235));
					}
				}

			if (UserlogEdit)
				{
				mPrintfCR(getecmsg(318));
				}

			if (onConsole)
				{
				cPrintf(getecmsg(236), EditLog->GetInitials(),
						EditLog->GetPassword());
				doccr();
				}

			CRmPrintfCR(UserlogEdit ? getmsg(868) : getecmsg(16));

			prtMsg = !TI()CurrentUser->IsExpert();
			}

		int c = DoMenuPrompt(getecmsg(302), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		if (c == ESC)
			{
			c = (UserlogEdit ? 'A' : 'B');
			}

		switch (toupper(c))
			{
			case '.':
				{
				if (UserlogEdit)
					{
					mPrintf(getecmsg(319));
					configure(EditLog, FALSE, TRUE);
					doCR();
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '1':
				{
				EditLog->SetPsycho(changeOnOff(getecmsg(263),
						EditLog->IsPsycho()));
				break;
				}

			case '2':
				{
				mPrintfCR(getecmsg(264));
				EditLog->SetCallLimit((int) GetNumberWithBlurb(getecmsg(265),
						0, INT_MAX, EditLog->GetCallLimit(), B_CALLIMIT));
				break;
				}

			case '3':
				{
				EditLog->SetOut300(changeOnOff(getecmsg(266),
						EditLog->IsOut300()));
				break;
				}

			case '4':
				{
				if (cfg.borders)
					{
					EditLog->SetEnterBorders(changeYesNo(getecmsg(267),
							EditLog->IsEnterBorders()));
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'A':
				{
				if (UserlogEdit)
					{
					mPrintfCR(getmsg(653));

					if (getYesNo(getmsg(654), 1))
						{
						quit = TRUE;
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'B':
				{
				if (!UserlogEdit)
					{
					mPrintf(getecmsg(24));
					quit = TRUE;
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'C':
				{
				EditLog->SetChat(changeOnOff(getecmsg(238),
						EditLog->IsChat()));
				break;
				}

			case 'D':
				{
				if (EditLog->IsSysop())
					{
					mPrintfCR(getecmsg(287));
					CRmPrintfCR(getecmsg(288));
					}
				else
					{
					EditLog->SetAide(changeYesNo(getecmsg(243),
							EditLog->IsAide()));
					}

				break;
				}

			case '5':
				{
				EditLog->SetDownload(changeOnOff(getecmsg(239),
						EditLog->IsDownload()));
				break;
				}

			case 'E':
				{
				EditLog->SetNetUser(changeYesNo(getecmsg(240),
						EditLog->IsNetUser()));
				break;
				}

			case 'F':
				{
				EditLog->SetPrintFile(changeOnOff(getecmsg(241),
						EditLog->IsPrintFile()));
				break;
				}

			case 'H':
				{
				char Prompt[128];
				sprintf(Prompt, getecmsg(242), cfg.Lhall_nym);

				EditLog->SetDefaultHallLocked(changeYesNo(Prompt,
						EditLog->IsDefaultHallLocked()));
				break;
				}

			case 'I':
				{
				mPrintfCR(getecmsg(244));

				if (cfg.accounting)
					{
					EditLog->SetAccounting(!getYesNo(getecmsg(245),
							!EditLog->IsAccounting()));

					if (EditLog->IsAccounting())
						{
						char string[200];

						sprintf(string, getecmsg(246), cfg.Ucredits_nym);

						EditLog->SetCredits(getNumber(string, 0,
								LONG_MAX / 60, EditLog->GetCredits() / 60,
								FALSE, NULL) * 60);
						}
					}
				else
					{
					CRmPrintfCR(getecmsg(247));
					}

				break;
				}

			case 'K':
				{
				EditLog->SetUserSignatureLocked(changeOnOff(getecmsg(248),
						EditLog->IsUserSignatureLocked()));
				break;
				}

			case 'L':
				{
				EditLog->SetSurnameLocked(changeOnOff(getecmsg(249),
						EditLog->IsSurnameLocked()));
				break;
				}

			case 'M':
				{
				EditLog->SetMail(changeOnOff(getecmsg(250),
						EditLog->IsMail()));
				break;
				}

			case 'N':
				{
				mPrintfCR(getecmsg(251));

				label temp;

				do
					{
					getString(getecmsg(252), temp, LABELSIZE, TRUE, ECHO,
							EditLog->GetName());

					if (*temp == '?')
						{
						ListUsers(TI()CurrentUser->IsAide());
						}
					} while (*temp == '?');

				normalizeString(temp);

				l_slot NameSlot = FindPersonByName(temp);

				if (	// Didn't enter a name or...
						!*temp ||

						// name exists, and it is not us, or...
						(
							(NameSlot != CERROR) &&
							(LogTab->GetEntry(NameSlot)->GetLogIndex() != Index)
						) ||

						// it is the name of a mailing list
						IsMailingList(temp))
					{
					if (*temp)
						{
						CRmPrintfCR(getmsg(1257), temp);
						}
					}
				else
					{
					Bool Change = TRUE;

					if (SameString(temp, getmsg(1020)) ||
							SameString(temp, getmsg(1019)) ||
							SameString(temp, cfg.nodeTitle))
						{
						CRmPrintfCR(getecmsg(253), temp);

						if (!getYesNo(getecmsg(254), 0))
							{
							Change = FALSE;
							}
						}

					if (Change && inExternal(getmsg(353), temp))
						{
						CRmPrintf(getecmsg(255), temp);

						if (!getYesNo(getecmsg(254), 0))
							{
							Change = FALSE;
							}
						}

					if (Change)
						{
						EditLog->SetName(temp);
						}
					}

				break;
				}

			case 'O':
				{
				EditLog->SetNode(changeYesNo(getecmsg(256),
						EditLog->IsNode()));

				if (EditLog->IsNode() &&
						!*EditLog->GetAlias() && !*EditLog->GetLocID())
					{
					Bool Valid = FALSE;

					do
						{
						label string, temp;
						char tempalias[4], templocID[5];

						strcpy(temp, makeaddress(EditLog->GetAlias(),
								EditLog->GetLocID()));

						if (getString(getmsg(1124), string, 8, FALSE, ECHO,
								temp))
							{
							normalizeString(string);

							parse_address(string, tempalias, templocID, FALSE);

							if (	!isaddress(string) ||

									(
										(addressexists(string) != CERROR) &&

										!(
										SameString(tempalias, EditLog->GetAlias()) &&
										SameString(templocID, EditLog->GetLocID())
										)
									)

									||

									(
										SameString(tempalias, cfg.alias) &&
										SameString(templocID, cfg.locID)
									)

									||

									strlen(tempalias) < 2

									||

									strlen(templocID) < 3
								)
								{
								CRmPrintfCR(*string ? getmsg(1125) : getecmsg(321));
								}
							else
								{
								EditLog->SetAlias(tempalias);
								EditLog->SetLocID(templocID);

								Valid = TRUE;
								}
							}
						else
							{
							EditLog->SetNode(FALSE);
							CRmPrintfCR(getecmsg(320));
							Valid = TRUE;
							}
						} while (!Valid);
					}

				break;
				}

			case 'P':
				{
				EditLog->SetPermanent(changeYesNo(getecmsg(257),
						EditLog->IsPermanent()));
				break;
				}

			case 'R':
				{
				EditLog->SetMakeRoom(changeOnOff(getecmsg(258),
						EditLog->IsMakeRoom()));
				break;
				}

			case 'S':
				{
				if (UserlogEdit)
					{
					mPrintfCR(getmsg(652));

					if (getYesNo(getmsg(652), 1))
						{
						quit = TRUE;
						EditLog->Save(Index);
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'T':
				{
				if (EditLog->IsSysop())
					{
					mPrintfCR(getecmsg(289));
					CRmPrintf(getecmsg(290));
					}
				else
					{
					EditLog->SetProblem(changeYesNo(getecmsg(260),
							EditLog->IsProblem()));
					}

				break;
				}

			case 'U':
				{
				EditLog->SetUpload(changeOnOff(getecmsg(262),
						EditLog->IsUpload()));
				break;
				}

			case 'V':
				{
				EditLog->SetVerified(changeYesNo(getecmsg(261),
						EditLog->IsVerified()));
				break;
				}

			case 'Y':
				{
				if (onConsole || cfg.sysopOk || !UserlogEdit)
					{
					EditLog->SetSysop(changeYesNo(getecmsg(259),
							EditLog->IsSysop()));
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '?':
			case '\r':
			case '\n':
				{
				mPrintfCR(getmsg(351));
				prtMsg = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				break;
				}
			}
		} while (!quit);
	}

/* -------------------------------------------------------------------- */
/*	configure() 	sets user configuration via menu					*/
/* -------------------------------------------------------------------- */
static void configure(LogEntry *EditLog, Bool newUser, Bool UserlogEdit)
	{
	Bool prtMess = !TI()CurrentUser->IsExpert();
	Bool quit = FALSE;
	const Bool oldcensor = EditLog->IsViewCensoredMessages();
	Bool edited_pointers = FALSE;

	doCR();

	do
		{
		TI()UserControl.SetOutFlag(OUTOK);

		if (prtMess || newUser)
			{
			label dProtocol;

			Bool Col = FALSE;

			if (*EditLog->GetDefaultHall())
				{
				label dHall;
				*dHall = 0;

				for (h_slot i = 1; i < cfg.maxhalls; ++i)
					{
					if (HallData->GetEntry(i)->IsInuse() &&
							SameString(HallData->GetEntry(i)->GetName(),
							EditLog->GetDefaultHall()))
						{
						if (EditLog->CanAccessHall(i))
							{
							CopyStringToBuffer(dHall,
									HallData->GetEntry(i)->GetName(),
									LABELSIZE);
							}
						}
					}

				EditLog->SetDefaultHall(dHall);
				}
			else
				{
				// If user has no default hall defined, make it Root.
				EditLog->SetDefaultHall(HallData->GetEntry(0)->GetName());
				}

			if (EditLog->GetDefaultProtocol())
				{
				const protocols *theProt =
						GetProtocolByKey(EditLog->GetDefaultProtocol());

				if (theProt)
					{
					strcpy(dProtocol, theProt->name);
					}
				else
					{
					dProtocol[0] = 0;
					}
				}
			else
				{
				dProtocol[0] = 0;
				}

			doCR();

			DisplayOnOffWithColumn(136, EditLog->IsViewRoomDesc(), &Col);
			DisplayOnOffWithColumn(137, EditLog->IsViewHallDescription(), &Col);
			DisplayOnOffWithColumn(138, EditLog->IsViewRoomInfoLines(), &Col);
			DisplayOnOffWithColumn(139, EditLog->IsWideRoom(), &Col);
			DisplayOnOffWithColumn(140, EditLog->IsAutoNextHall(), &Col);

			if (cfg.ecTwirly)
				{
				DisplayOnOffWithColumn(141, EditLog->IsTwirly(), &Col);
				}

			DisplayOnOffWithColumn(142, EditLog->IsAutoVerbose(), &Col);

			if (!EditLog->IsAutoVerbose())
				{
				DisplayOnOffWithColumn(143, EditLog->IsVerboseLogOut(), &Col);
				}

			if (cfg.ecUserlog || UserlogEdit || TI()CurrentUser->IsSysop())
				{
				DisplayYesNoWithColumn(144, !EditLog->IsUnlisted(), &Col);
				}

			DisplayOnOffWithColumn(145, !EditLog->IsExpert(), &Col);
			DisplayOnOffWithColumn(146, EditLog->IsYouAreHere(), &Col);
			DisplayOnOffWithColumn(147, EditLog->IsOldToo(), &Col);
			DisplayOnOffWithColumn(148, EditLog->IsMinibin(), &Col);

			mPrintf(getecmsg(149), EditLog->GetNumUserShow());
			doColumn(&Col);

			if (cfg.surnames || cfg.netsurname || cfg.titles ||
					cfg.nettitles)
				{
				DisplayOnOffWithColumn(154, EditLog->IsViewTitleSurname(), &Col);
				}

			if (cfg.borders)
				{
				DisplayOnOffWithColumn(156, EditLog->IsViewBorders(), &Col);
				}

			DisplayYesNoWithColumn(157, EditLog->IsViewCommas(), &Col);
			DisplayYesNoWithColumn(286, EditLog->IsPUnPauses(), &Col);

			// from here down is not columnized...
			if (Col)
				{
				doCR();
				}

			mPrintfCR(getecmsg(158), EditLog->GetDefaultHall());

			mPrintfCR(getecmsg(159), dProtocol);

			if (cfg.titles && (cfg.entersur ||
					UserlogEdit || TI()CurrentUser->IsSysop()))
				{
				mPrintfCR(getecmsg(323), EditLog->GetTitle());
				}

			if (cfg.surnames && (cfg.entersur ||
					UserlogEdit || TI()CurrentUser->IsSysop()))
				{
				mPrintfCR(getecmsg(324), EditLog->GetSurname());
				}

			if (cfg.ecSignature || UserlogEdit || TI()CurrentUser->IsSysop())
				{
				mPrintfCR(getecmsg(160), EditLog->GetSignature());
				}

			mPrintf(getecmsg(161));
			if (!EditLog->IsForwardToNode())
				{
				mPrintfCR(getecmsg(4), EditLog->GetForwardAddr());
				}
			else
				{
				mPrintfCR(getecmsg(3), EditLog->GetForwardAddr(),
						EditLog->GetForwardAddrNode());
				}

			mPrintfCR(getecmsg(162), makeaddress(EditLog->GetAlias(),
					EditLog->GetLocID()));

			mPrintfCR(getecmsg(163), TI()CurrentUser->IsExpert() ?
					ns : getecmsg(164));

			mPrintfCR(getecmsg(165), TI()CurrentUser->IsExpert() ?
					ns : getecmsg(166));

			mPrintfCR(getecmsg(167), TI()CurrentUser->IsExpert() ?
					ns : getecmsg(168));

			mPrintfCR(getecmsg(169), cfg.Umsg_nym,
					TI()CurrentUser->IsExpert() ? ns : getecmsg(170));

			mPrintfCR(getecmsg(171), TI()CurrentUser->IsExpert() ?
					ns : getecmsg(172));

			mPrintfCR(getecmsg(173), cfg.Umsg_nym,
					TI()CurrentUser->IsExpert() ? ns : getecmsg(174));

			if (!UserlogEdit && TI()CurrentUser->IsSysop())
				{
				mPrintfCR(getecmsg(237));
				}

			if (!newUser)
				{
				CRmPrintfCR(UserlogEdit ? getecmsg(16) : getmsg(868));
				}

			prtMess = !TI()CurrentUser->IsExpert();
			}

		if (newUser)
			{
			if (getYesNo(getecmsg(175), 1))
				{
				quit = TRUE;
				continue;
				}

			newUser = FALSE;
			}

		int c = DoMenuPrompt(getmsg(616), NULL);

		if (!HaveConnectionToUser())
			{
			return;
			}

		if (c == ESC)
			{
			c = (UserlogEdit ? 'B' : 'A');
			}

		switch (toupper(c))
			{
			case ',':
				{
				EditLog->SetViewCommas(changeYesNo(getecmsg(176),
						EditLog->IsViewCommas()));
				break;
				}

			case '&':
				{
				label stuff;
				label Input;

				mPrintfCR(getmsg(1123));

				strcpy(stuff, makeaddress(EditLog->GetAlias(),
						EditLog->GetLocID()));

				if (getString(getmsg(1124), Input, 8, FALSE, ECHO, stuff))
					{
					normalizeString(Input);

					if (*Input)
						{
						char tempalias[4], templocID[5];

						parse_address(Input, tempalias, templocID, FALSE);

						if (	!isaddress(Input) ||

								(
									(addressexists(Input) != CERROR) &&

									!(
									SameString(tempalias, EditLog->GetAlias()) &&
									SameString(templocID, EditLog->GetLocID())
									)
								)

								||

								(
									SameString(tempalias, cfg.alias) &&
									SameString(templocID, cfg.locID)
								)

								||

								strlen(tempalias) < 2

								||

								strlen(templocID) < 3
							)
							{
							CRmPrintfCR(getmsg(1125));
							}
						else
							{
							EditLog->SetAlias(tempalias);
							EditLog->SetLocID(templocID);
							}
						}
					else
						{
						EditLog->SetAlias(ns);
						EditLog->SetLocID(ns);
						}
					}

				break;
				}

			case '>':
				{
				mPrintf(getecmsg(199), cfg.Lhall_nym);

				defaulthall(EditLog, UserlogEdit);
				break;
				}

			case '#':
				{
				mPrintfCR(getecmsg(185));
				EditLog->SetNumUserShow((int) GetNumberWithBlurb(getecmsg(186),
						0, INT_MAX, EditLog->GetNumUserShow(), B_NUMUSERS));
				break;
				}

			case '-':
				{
				char Prompt[128];
				sprintf(Prompt, getecmsg(195), cfg.Uhall_nym);

				EditLog->SetViewHallDescription(changeOnOff(Prompt,
						EditLog->IsViewHallDescription()));
				break;
				}

			case '+':
				{
				EditLog->SetViewRoomInfoLines(changeOnOff(getecmsg(196),
						EditLog->IsViewRoomInfoLines()));
				break;
				}

			case '_':
				{
				if ((cfg.ecSignature || UserlogEdit ||
						TI()CurrentUser->IsSysop()))
					{
					mPrintfCR(getmsg(17));

					if (!UserlogEdit && !EditLog->IsSysop() &&
							EditLog->IsUserSignatureLocked())
						{
						CRmPrintfCR(getecmsg(209));
						doCR();
						}
					else
						{
						char stuff[91];

						if (GetStringWithBlurb(getecmsg(210), stuff, 90,
								EditLog->GetSignature(), B_SIGNATUR) &&
								*stuff)
							{
							normalizeString(stuff);
							EditLog->SetSignature(stuff);
							}
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '.':
				{
				if (!UserlogEdit && TI()CurrentUser->IsSysop())
					{
					mPrintf(getecmsg(211));
					PrivilegeEdit(EditLog, FALSE, TI()ThisLog);
					doCR();
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '1':
				{
				EditLog->SetWideRoom(changeOnOff(getecmsg(198),
						EditLog->IsWideRoom()));
				break;
				}

			case '2':
				{
				if (cfg.borders)
					{
					EditLog->SetViewBorders(changeOnOff(getecmsg(183),
							EditLog->IsViewBorders()));
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '3':
				{
				if (cfg.titles && (cfg.entersur ||
						UserlogEdit || TI()CurrentUser->IsSysop()))
					{
					mPrintfCR(getecmsg(325));

					if (!UserlogEdit && !EditLog->IsSysop() &&
							EditLog->IsSurnameLocked())
						{
						CRmPrintfCR(getmsg(252));
						doCR();
						}
					else
						{
						label NewTitle;

						// Note: getmsg(253) also in doenter.cpp
						if (GetStringWithBlurb(getmsg(253), NewTitle,
								LABELSIZE, EditLog->GetTitle(), B_TITLESUR) &&
								*NewTitle)
							{
							normalizeString(NewTitle);
							EditLog->SetTitle(NewTitle);
							}
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '4':
				{
				if (cfg.surnames && (cfg.entersur ||
						UserlogEdit || TI()CurrentUser->IsSysop()))
					{
					mPrintfCR(getecmsg(326));

					if (!UserlogEdit && !EditLog->IsSysop() &&
							EditLog->IsSurnameLocked())
						{
						CRmPrintfCR(getmsg(252));
						doCR();
						}
					else
						{
						label NewSurname;

						// Note: getmsg(254) also in doenter.cpp
						if (GetStringWithBlurb(getmsg(254), NewSurname,
								LABELSIZE, EditLog->GetSurname(), B_TITLESUR) &&
								*NewSurname)
							{
							normalizeString(NewSurname);
							EditLog->SetSurname(NewSurname);
							}
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case '5':
				{
				mPrintfCR(getecmsg(188));

				editFormatStrings(EditLog);
				break;
				}

			case '6':
				{
				mPrintfCR(getecmsg(203));

				editPersonalInfo(EditLog);
				break;
				}

			case 'A':
				{
				if (!UserlogEdit)
					{
					mPrintfCR(getmsg(653));

					if (getYesNo(getmsg(654), 1))
						{
// DoEnterConfig() reloads the userlog entry anyway.
//						if (TI()loggedIn)
//							{
//							if (!EditLog->Load(TI()ThisLog))
//								{
//								mPrintfCR(getmsg(656));
//								}
//							}

						setlogTerm();

						quit = TRUE;
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'B':
				{
				if (UserlogEdit)
					{
					mPrintf(getecmsg(24));
					quit = TRUE;
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'D':
				{
				EditLog->SetViewRoomDesc(changeOnOff(getecmsg(194),
						EditLog->IsViewRoomDesc()));
				break;
				}

			case 'E':
				{
				mPrintfCR(getecmsg(205), cfg.Umsg_nym);

				messageEditOptions(EditLog);
				break;
				}

			case 'F':
				{
				mPrintf(getecmsg(200));
				forwardaddr(EditLog);
				break;
				}

			case 'H':
				{
				EditLog->SetExpert(!changeOnOff(getecmsg(191),
						!EditLog->IsExpert()));

				prtMess = !TI()CurrentUser->IsExpert();
				break;
				}

			case 'I':
				{
				if (!(cfg.surnames || cfg.netsurname || cfg.titles ||
						cfg.nettitles))
					{
					break;
					}

				EditLog->SetViewTitleSurname(!EditLog->IsViewTitleSurname());
				mPrintfCR(getecmsg(179), EditLog->IsViewTitleSurname() ?
						ns : getecmsg(180));
				break;
				}

			case 'L':
				{
				if (toupper(c) == 'L' && !EditLog->IsAutoVerbose())
					{
					EditLog->SetVerboseLogOut(changeOnOff(getecmsg(208),
							EditLog->IsVerboseLogOut()));
					}
				else
					{
					mPrintfCR(getecmsg(10));
					}

				break;
				}

			case 'M':
				{
				EditLog->SetMinibin(changeOnOff(getecmsg(190),
						EditLog->IsMinibin()));
				break;
				}

			case 'N':
				{
				EditLog->SetPUnPauses(changeYesNo(getecmsg(285),
						EditLog->IsPUnPauses()));
				break;
				}

			case 'O':
				{
				EditLog->SetOldToo(changeOnOff(getecmsg(193),
						EditLog->IsOldToo()));
				break;
				}

			case 'P':
				{
				int ich = 0;

				mPrintfCR(getecmsg(201));

				do
					{
					if (!TI()CurrentUser->IsExpert() || (ich == '?'))
						{
						if (ich == '?')
							{
							oChar(ich);
							doCR();
							}

						doCR();

						for (protocols *theProt = extProtList; theProt;
								theProt = (protocols *) getNextLL(theProt))
							{
							if (!theProt->NetOnly)
								{
								mPrintfCR(getmsg(1408), theProt->CommandKey,
										theProt->MenuName);
								}
							}
						}

					ich = DoMenuPrompt(getecmsg(202), NULL);
					} while (ich == '?');

				if (ich == ' ')
					{
					EditLog->SetDefaultProtocol(0);
					}
				else
					{
					const protocols *theProt = GetProtocolByKey(ich);

					if (theProt)
						{
						mPrintfCR(pcts, theProt->name);
						EditLog->SetDefaultProtocol(ich);
						}
					else
						{
						BadMenuSelection(ich);
						}
					}

				break;
				}

			case 'R':
				{
				mPrintfCR(getecmsg(204), cfg.Lmsg_nym);

				editMsgOption(EditLog, UserlogEdit, &edited_pointers);
				break;
				}

			case 'S':
				{
				if (!UserlogEdit)
					{
					mPrintfCR(getmsg(652));

					if (getYesNo(getmsg(652), 1))
						{
						quit = TRUE;
						storeLog();
						}

					if (	oldcensor != EditLog->IsViewCensoredMessages() ||
							edited_pointers
						)
						{
						roomtalley();
						}
					}
				else
					{
					BadMenuSelection(c);
					}

				break;
				}

			case 'T':
				{
				mPrintfCR(getecmsg(177));

				editTerminal(EditLog);
				break;
				}

			case 'U':
				{
				if (toupper(c) == 'U' && (cfg.ecUserlog || UserlogEdit ||
						TI()CurrentUser->IsSysop()))
					{
					EditLog->SetUnlisted(!changeYesNo(getecmsg(207),
							!EditLog->IsUnlisted()));
					break;
					}
				}

			case 'V':
				{
				EditLog->SetAutoVerbose(changeOnOff(getecmsg(184),
						EditLog->IsAutoVerbose()));
				break;
				}

			case 'W':
				{
				if (toupper(c) == 'W' && cfg.ecTwirly)
					{
					EditLog->SetTwirly(changeOnOff(getecmsg(206),
							EditLog->IsTwirly()));
					break;
					}
				}

			case 'X':
				{
				char Prompt[128];
				sprintf(Prompt, getecmsg(197), cfg.Lhall_nym);

				EditLog->SetAutoNextHall(changeOnOff(Prompt,
						EditLog->IsAutoNextHall()));
				break;
				}

			case 'Y':
				{
				EditLog->SetYouAreHere(changeOnOff(getecmsg(192),
						EditLog->IsYouAreHere()));
				break;
				}

			case 'Z':
				{
				userPointers(EditLog, !UserlogEdit);
				edited_pointers = TRUE;
				break;
				}

			case '\r':
			case '\n':
			case '?':
				{
				mPrintfCR(getmsg(351));
				prtMess = TRUE;
				break;
				}

			default:
				{
				BadMenuSelection(c);
				}
			}
		} while (!quit);
	}

void DoUserlogEdit(LogEntry *EditLog, l_index Index)
	{
	if (!read_ec_messages())
		{
		mPrintf(getmsg(188), getmsg(441));
		return;
		}

	PrivilegeEdit(EditLog, TRUE, Index);

	dump_ec_messages();
	}

void DoEnterConfiguration(Bool newUser)
	{
	SetDoWhat(ENTERCONFIG);

	if (!read_ec_messages())
		{
		mPrintf(getmsg(188), getmsg(428));
		return;
		}

	storeLog();

	configure(TI()CurrentUser, newUser, FALSE);

	dump_ec_messages();

	if (TI()loggedIn)
		{
		// load it back to compact memory - log extensions.
		TI()CurrentUser->Load(TI()ThisLog);
		}
	}
