// --------------------------------------------------------------------------
// Citadel: RoomEdit.CPP
//
// Room editing stuff.

#include "ctdl.h"
#pragma hdrstop

#include "room.h"
#include "roompriv.h"
#include "boolexpr.h"
#include "log.h"
#include "group.h"
#include "msg.h"
#include "hall.h"
#include "libovl.h"
#include "net.h"
#include "cfgfiles.h"
#include "miscovl.h"


// --------------------------------------------------------------------------
// Contents
//
// editRoom()			sysop special to rename rooms
// killempties()		deletes empty rooms
// killroom()			aide fn to kill current room


// --------------------------------------------------------------------------
// inExternal(): Returns wether an entry is in EXTERNAL.CIT.

Bool inExternal(const char *key, const char *str)
{
	FILE *fBuf;
	char line[90];
	char *words[256];
	char path[80];
	int len = strlen(key);

	sprintf(path, sbs, cfg.homepath, citfiles[C_EXTERNAL_CIT]);

if (
(
fBuf
							=
								fopen(
			path, FO_R)



				) ==



										NULL



																					)	/*
	{
								ASCII
	 }				 mode */
  { { {/*{*/{{{ {{{ {																																				{
  {{
  {{
   { {	{
  {{		  mPrintf(getmsg(																					 15)			,				   citfiles[C_EXTERNAL_CIT]    /*externalCit*/																						   /*"Cannot find external.cit!"*/);   return FALSE;} }
   }} }  }		  }} }
   }} }}} }}}  }}
   }

	while (fgets(line, 90, fBuf) != NULL)
	{
		if (line[0] != '#')
			{
			continue;
			}

		if (strnicmp(line, key, len) != SAMESTRING)
			{
			continue;
			}

		parse_it(words, line);

		if (SameString(words[0], key))
		{
			if (u_match(str, words[1]))
			{
				fclose(fBuf);
				return (TRUE);
			}
		}
	}
	fclose(fBuf);
	return (FALSE);
}


// --------------------------------------------------------------------------
// editRoom(): Is aide special fn.

Bool editRoom(void)
	{
	label roomname, oldname;
	Bool waspublic;
	Bool prtMess = !TI()CurrentUser->IsExpert();
	Bool quit = FALSE;
	r_slot	oldthisRoom;

	SetDoWhat(EDITROOM);

	oldthisRoom = TI()thisRoom;

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

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

		} while (*roomname == '?');

	TI()thisRoom = RoomExists(roomname);
	if (TI()thisRoom == CERROR)
		{
		TI()thisRoom = PartialRoomExists(roomname, oldthisRoom, TRUE);
		}

	if ((TI()thisRoom) == CERROR || !(*roomname))
		{
		if (*roomname)
			{
			CRmPrintfCR(getmsg(1066), cfg.Lroom_nym, roomname);
			}

		TI()thisRoom = oldthisRoom;
		return (FALSE);
		}

	getRoom(TI()thisRoom, roomBuf);

	CopyStringToBuffer(oldname, roomBuf->rbname, LABELSIZE);

	if (!roomBuf->rbflags.IsMsDOSdir())
		{
		*roomBuf->rbdirname = 0;
		}

	if (roomBuf->rbflags.IsPublic() && !roomBuf->rbflags.IsBIO())
		{
		waspublic = TRUE;
		}
	else
		{
		waspublic = FALSE;
		}

	do
		{
		if (prtMess)
			{
			doCR();
			TI()UserControl.SetOutFlag(OUTOK);
			mPrintfCR(getmsg(1152), roomBuf->rbname);

			mPrintfCR(getmsg(1153), roomBuf->descript);

			mPrintfCR(getmsg(1154), roomBuf->rbflags.IsMsDOSdir() ?
					roomBuf->rbdirname : getmsg(1173));

			mPrintfCR(getmsg(1155), roomBuf->rbflags.IsApplication() ?
					roomBuf->rbaplic : getmsg(1173));

			if (roomBuf->rbflags.IsApplication())
				{
				displayYesNo(getmsg(1156), roomBuf->AUTOAPP);
				doCR();
				}

			mPrintfCR(getmsg(1157), roomBuf->rbroomtell[0] ?
					roomBuf->rbroomtell : getmsg(1173));

			if (roomBuf->rbflags.IsGroupOnly() &&
					roomBuf->rbflags.IsBooleanGroup())
				{
				mPrintf(getmsg(1158), ns);
				ShowBooleanExpression(roomBuf->GroupExpression, ShowGroup);
				}
			else
				{
				mPrintf(getmsg(1158), roomBuf->rbflags.IsGroupOnly() ?
						GroupData->GetEntry(roomBuf->rbgrpno)->GetName() :
						getmsg(1173));
				}

			CRmPrintfCR(getmsg(1159), roomBuf->rbflags.IsPrivilegedGroup() ?
					GroupData->GetEntry(roomBuf->rbPgrpno)->GetName() : getmsg(1173));

			if (roomBuf->rbflags.IsPrivilegedGroup())
				{
				displayYesNo(getmsg(1160), roomBuf->rbflags.IsDownloadOnly());
				doCR();

				displayYesNo(getmsg(1161), roomBuf->rbflags.IsUploadOnly());
				doCR();

				displayYesNo(getmsg(1162), roomBuf->rbflags.IsReadOnly());
				doCR();

				displayYesNo(getmsg(1163), roomBuf->rbflags.IsGroupModerates());
				doCR();
				}

			displayYesNo(getmsg(1164), !roomBuf->rbflags.IsPublic());
			doCR();

			displayYesNo(getmsg(1165), roomBuf->rbflags.IsBIO());
			doCR();

			displayYesNo(getmsg(1166), roomBuf->rbflags.IsAnonymous());
			doCR();

			displayYesNo(getmsg(1167), roomBuf->rbflags.IsModerated());
			doCR();

			displayYesNo(getmsg(1168), roomBuf->rbflags.IsShared());
			doCR();

			if (roomBuf->rbflags.IsShared())
				{
				mPrintfCR(getmsg(1169), roomBuf->netID);
				}

			displayYesNo(getmsg(1170), roomBuf->rbflags.IsPermanent());
			doCR();

			displayYesNo(getmsg(1171), roomBuf->rbflags.IsSubject());
			doCR();

			displayYesNo(getmsg(1172), roomBuf->rbflags.IsArchive());
			doCR();

			displayYesNo(getmsg(6), roomBuf->NOEXCLUDE);
			doCR();

			mPrintfCR(getmsg(1151), roomBuf->dictionary);

			CRmPrintfCR(getmsg(868));

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

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

		if (!(HaveConnectionToUser()))
			{
			TI()thisRoom = oldthisRoom;
			getRoom(TI()thisRoom, roomBuf);
			return (FALSE);
			}

		switch (toupper(c))
			{
			case ESC:
			case 'A':
				{
				mPrintfCR(getmsg(653));

				if (getYesNo(getmsg(654), TRUE))
					{
					TI()thisRoom = oldthisRoom;
					getRoom(TI()thisRoom, roomBuf);
					return (FALSE);
					}

				break;
				}

			case 'B':
				{
				if ((TI()thisRoom > 2) || (TI()thisRoom >= 0 && TI()CurrentUser->IsSysop()))
					{
					char Prompt[128];
					sprintf(Prompt, getmsg(64), cfg.Lroom_nym);

					roomBuf->rbflags.SetBIO(changeYesNo(Prompt,
							roomBuf->rbflags.IsBIO()));
					}
				else
					{
					mPrintfCR(getmsg(1210), cfg.Lroom_nym);

					CRmPrintfCR(getmsg(1205), GetRoomName(LOBBY),
							GetRoomName(MAILROOM), GetRoomName(AIDEROOM),
							getmsg(1211));
					}

				break;
				}

			case 'C':
				{
				mPrintfCR(getmsg(980));

				if (TI()CurrentUser->IsSysop() && onConsole)
					{
					getNormStr(getmsg(981), roomBuf->dictionary, 12, ECHO);
					}
				else
					{
					mPrintfCR(getmsg(1176), getmsg(980));
					}

				break;
				}

			case 'D':
				{
				mPrintfCR(getmsg(1186));

				if (TI()CurrentUser->IsSysop())
					{
					Bool WasDirectory = roomBuf->rbflags.IsMsDOSdir();

					char Prompt[128];
					sprintf(Prompt, getmsg(1187), cfg.Lroom_nym);

					if (getYesNo(Prompt, WasDirectory))
						{
						char pathname[64];

						doCR();

						if (!*roomBuf->rbdirname)
							{
							mPrintfCR(getmsg(1188));
							}
						else
							{
							strupr(roomBuf->rbdirname);
							mPrintfCR(getmsg(1189), roomBuf->rbdirname);
							}

						getString(getmsg(1190), pathname, 63, FALSE, ECHO,
								*roomBuf->rbdirname ?
								roomBuf->rbdirname : cfg.dirpath);

						if (*pathname)
							{
							if (strncmp(pathname, getmsg(1461), 2) == SAMESTRING)
								{
								char Temp[64];

								strcpy(Temp, pathname + 1);

								strcpy(pathname, *roomBuf->rbdirname ?
										roomBuf->rbdirname : cfg.dirpath);

								strncat(pathname, Temp, 63 - strlen(pathname));
								}

							if (pathname[strlen(pathname) - 1] == '\\')
								{
								pathname[strlen(pathname) - 1] = 0;
								}

							strupr(pathname);

							doCR();

							if (!onConsole && inExternal(getmsg(1462),
									pathname))
								{
								securityViolation(pathname);
								TI()thisRoom = oldthisRoom;
								getRoom(TI()thisRoom, roomBuf);
								return (FALSE);
								}

							if (changedir(pathname))
								{
								roomBuf->rbflags.SetMsDOSdir(TRUE);
								CopyStringToBuffer(roomBuf->rbdirname,
										pathname,
										sizeof(roomBuf->rbdirname) - 1);

								mPrintfCR(getmsg(1189), roomBuf->rbdirname);
								}
							else
								{
								mPrintfCR(getmsg(1192), pathname);

								if (getYesNo(getmsg(1193), 0))
									{
									if (mkdir(pathname) == -1)
										{
										CRmPrintfCR(getmsg(1194), pathname);
										}
									else
										{
										CopyStringToBuffer(roomBuf->rbdirname,
												pathname,
												sizeof(roomBuf->rbdirname) - 1);
										roomBuf->rbflags.SetMsDOSdir(TRUE);

										CRmPrintfCR(getmsg(1189), roomBuf->rbdirname);
										}
									}
								}

							if (!WasDirectory &&
									roomBuf->rbflags.IsPrivilegedGroup() &&
									roomBuf->rbflags.IsMsDOSdir())
								{
								roomBuf->rbflags.SetDownloadOnly(
										getYesNo(getmsg(1195),
										roomBuf->rbflags.IsDownloadOnly()));

								if (!roomBuf->rbflags.IsDownloadOnly())
									{
									roomBuf->rbflags.SetUploadOnly(
											getYesNo(getmsg(1196),
											roomBuf->rbflags.IsUploadOnly()));
									}
								}
							}
						}
					else
						{
						roomBuf->rbflags.SetMsDOSdir(FALSE);
						roomBuf->rbflags.SetDownloadOnly(FALSE);
						roomBuf->rbflags.SetUploadOnly(FALSE);
						}

					changedir(cfg.homepath);
					}
				else
					{
					CRmPrintfCR(getmsg(1197));
					}

				break;
				}

			case 'E':
				{
				if (TI()CurrentUser->IsSysop())
					{
					char Prompt[128];
					sprintf(Prompt, getmsg(65), cfg.Lroom_nym);

					roomBuf->rbflags.SetShared(changeYesNo(Prompt,
							roomBuf->rbflags.IsShared()));

					if (roomBuf->rbflags.IsShared() && !*roomBuf->netID)
						{
						label NetID1, NetID2;

						CopyStringToBuffer(NetID1, roomBuf->rbname, LABELSIZE);
						normalizeString(NetID1);
						stripansi(NetID1);
						strip(NetID1, '"');

						r_slot roomslot = IdExists(NetID1, FALSE);

						if (roomslot != CERROR)
							{
							NetID1[0] = 0;
							}

						do
							{
							getString(getmsg(1185), NetID2, LABELSIZE, TRUE,
									ECHO, NetID1);

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

						normalizeString(NetID2);
						stripansi(NetID2);
						strip(NetID2, '"');

						roomslot = IdExists(NetID2, FALSE);

						if (roomslot != CERROR &&
								(roomslot != TI()thisRoom) && *NetID2)
							{
							mPrintfCR(getmsg(137), NetID2);
							}
						else
							{
							CopyStringToBuffer(roomBuf->netID, NetID2, LABELSIZE);
							}
						}
					}
				else
					{
					mPrintfCR(getmsg(1218), cfg.Lroom_nym);
					CRmPrintfCR(getmsg(1219), cfg.Lrooms_nym);
					}

				break;
				}

			case 'F':
				{
				mPrintfCR(getmsg(1198));

				if (TI()CurrentUser->IsSysop())
					{
					char Prompt[128];
					sprintf(Prompt, getmsg(1199), cfg.Lroom_nym);

					if (getYesNo(Prompt,
							roomBuf->rbroomtell[0] != '\0'))
						{
						char description[13];

						getString(getmsg(1200), description, 12,
								FALSE, ECHO, roomBuf->rbroomtell);

						CopyStringToBuffer(roomBuf->rbroomtell,
								description, sizeof(roomBuf->rbroomtell) - 1);
						}
					else
						{
						roomBuf->rbroomtell[0] = '\0';
						}
					}
				else
					{
					CRmPrintfCR(getmsg(1201));
					}

				break;
				}

			case 'G':
				{
				mPrintfCR(getmsg(1202), cfg.Lgroup_nym);

				if ((TI()thisRoom > 2) || (TI()thisRoom > 0 && TI()CurrentUser->IsSysop()))
					{
					if (roomBuf->rbflags.IsGroupOnly() &&
							roomBuf->rbflags.IsBooleanGroup())
						{
						CRmPrintf(getmsg(1368));
						ShowBooleanExpression(roomBuf->GroupExpression, ShowGroup);
						doCR();
						}

					char groupname[256], prompt[128];

					sprintf(prompt, getmsg(1203), cfg.Lgroup_nym,
							cfg.Lroom_nym);

					do
						{
						getString(prompt, groupname, 255, TRUE, ECHO,
								roomBuf->rbflags.IsGroupOnly() && !roomBuf->rbflags.IsBooleanGroup() ?
								GroupData->GetEntry(roomBuf->rbgrpno)->GetName() : ns);

						if (*groupname == '?')
							{
							ListGroups(TRUE);
							}
						} while (*groupname == '?');

					if (SameString(groupname, spc))
						{
						roomBuf->rbflags.SetGroupOnly(FALSE);
						roomBuf->rbflags.SetBooleanGroup(FALSE);
						}
					else
						{
						const g_slot groupslot =
								FindGroupByPartialName(groupname, FALSE);

						if (*groupname && (groupslot != CERROR))
							{
							roomBuf->rbflags.SetGroupOnly(TRUE);
							roomBuf->rbflags.SetBooleanGroup(FALSE);
							roomBuf->rbgrpno = groupslot;
							}
						else
							{
							if (*groupname)
								{
								BoolExpr Expression;

								if (!CreateBooleanExpression(groupname,
										TestGroupExists, Expression))
									{
									CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
									}
								else
									{
									memcpy(roomBuf->GroupExpression,
											Expression, sizeof(BoolExpr));

									roomBuf->rbflags.SetGroupOnly(TRUE);
									roomBuf->rbflags.SetBooleanGroup(TRUE);
									}
								}
							}
						}
					}
				else
					{
					if (TI()thisRoom > 0)
						{
						CRmPrintfCR(getmsg(1204), cfg.Lgroup_nym,
								GetRoomName(MAILROOM), GetRoomName(AIDEROOM));
						}
					else
						{
						CRmPrintfCR(getmsg(1206), GetRoomName(LOBBY),
								cfg.Lgroup_nym);
						}
					}

				break;
				}

			case 'H':
				{
				if ((TI()thisRoom > 2) || (TI()thisRoom >= 0 && TI()CurrentUser->IsSysop()))
					{
					char Prompt[128];
					sprintf(Prompt, getmsg(72), cfg.Lroom_nym);

					roomBuf->rbflags.SetPublic(!changeYesNo(Prompt,
							!roomBuf->rbflags.IsPublic()));
					}
				else
					{
					mPrintfCR(getmsg(1212), cfg.Lroom_nym);

					CRmPrintfCR(getmsg(1205), GetRoomName(LOBBY),
							GetRoomName(MAILROOM), GetRoomName(AIDEROOM),
							getmsg(1213));
					}

				break;
				}

			case 'I':
				{
				mPrintfCR(getmsg(1182));

				char Prompt[128];
				sprintf(Prompt, getmsg(1183), cfg.Lroom_nym);

				getNormStr(Prompt, roomBuf->descript, 79, ECHO);
				break;
				}

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

				if (TI()CurrentUser->IsSysop() && onConsole)
					{
					if (getYesNo(getmsg(1174), roomBuf->rbflags.IsApplication()))
						{
						char application[13];

						getString(getmsg(1175), application, 12,
								FALSE, ECHO, roomBuf->rbaplic);

						CopyStringToBuffer(roomBuf->rbaplic, application,
								sizeof(roomBuf->rbaplic) - 1);

						roomBuf->rbflags.SetApplication(TRUE);
						}
					else
						{
						roomBuf->rbaplic[0] = '\0';
						roomBuf->rbflags.SetApplication(FALSE);
						}
					}
				else
					{
					mPrintfCR(getmsg(1176), getmsg(1174));
					}

				break;
				}

			case 'M':
				{
				if (TI()CurrentUser->IsSysop())
					{
					roomBuf->rbflags.SetModerated(changeYesNo(getmsg(84),
							roomBuf->rbflags.IsModerated()));
					}
				else
					{
					mPrintfCR(getmsg(1216));
					CRmPrintfCR(getmsg(1217), cfg.Lrooms_nym);
					}

				break;
				}

			case 'N':
				{
				label roomname;

				mPrintfCR(getmsg(1180));

				char Prompt[128];
				sprintf(Prompt, getmsg(1181), cfg.Lroom_nym);

				do
					{
					getString(Prompt, roomname, LABELSIZE, TRUE, ECHO,
							roomBuf->rbname);

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

				normalizeString(roomname);
				r_slot roomslot = RoomExists(roomname);

				if (roomslot >= 0 && roomslot != TI()thisRoom)
					{
					mPrintf(getmsg(105), roomname, cfg.Lroom_nym);
					}
				else
					{
					// also in room itself
					CopyStringToBuffer(roomBuf->rbname, roomname, LABELSIZE);
					}

				break;
				}

			case 'O':
				{
				if (roomBuf->rbflags.IsApplication())
					{
					char Prompt[128];
					sprintf(Prompt, getmsg(103), cfg.Lroom_nym);

					roomBuf->AUTOAPP = changeYesNo(Prompt, roomBuf->AUTOAPP);
					}
				else
					{
					mPrintfCR(getmsg(1179), cfg.Lroom_nym);
					CRmPrintfCR(getmsg(109), cfg.Uroom_nym);
					}

				break;
				}

			case 'P':
				{
				if (TI()thisRoom > DUMP)
					{
					if (!roomBuf->rbflags.IsMsDOSdir())
						{
						roomBuf->rbflags.SetPermanent(changeYesNo(getmsg(158),
								roomBuf->rbflags.IsPermanent()));
						}
					else
						{
						roomBuf->rbflags.SetPermanent(TRUE);
						mPrintfCR(getmsg(1220));
						CRmPrintfCR(getmsg(1221), cfg.Lrooms_nym);
						}
					}
				else
					{
					mPrintfCR(getmsg(1220));

					roomBuf->rbflags.SetPermanent(TRUE);

					CRmPrintfCR(getmsg(1222), GetRoomName(LOBBY),
							GetRoomName(MAILROOM), GetRoomName(AIDEROOM),
							GetRoomName(DUMP));
					}

				break;
				}

			case 'R':
				{
				mPrintfCR(getmsg(1177));

				if (TI()CurrentUser->IsSysop() && onConsole)
					{
					if (getYesNo(getmsg(1177), roomBuf->rbflags.IsArchive()))
						{
						char archive[13];

						getString(getmsg(1178), archive, 12, FALSE,
								ECHO, roomBuf->archive);

						normalizeString(archive);

						CopyStringToBuffer(roomBuf->archive, archive,
								sizeof(roomBuf->archive) - 1);
						roomBuf->rbflags.SetArchive(roomBuf->archive[0]);
						}
					else
						{
						roomBuf->archive[0] = 0;
						roomBuf->rbflags.SetArchive(FALSE);
						}
					}
				else
					{
					CRmPrintfCR(getmsg(1176), getmsg(1177));
					}

				break;
				}

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

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

				break;
				}

			case 'U':
				{
				char Prompt[128];
				sprintf(Prompt, getmsg(1224), cfg.Lroom_nym);

				roomBuf->rbflags.SetSubject(changeYesNo(Prompt,
						roomBuf->rbflags.IsSubject()));
				break;
				}

			case 'V':
				{
				char prompt[128];
				label groupname;

				mPrintfCR(getmsg(1207), cfg.Lgroup_nym);

				sprintf(prompt, getmsg(1203), cfg.Lgroup_nym, cfg.Lroom_nym);

				do
					{
					getString(prompt, groupname, LABELSIZE, TRUE, ECHO,
							roomBuf->rbflags.IsPrivilegedGroup() ?
							GroupData->GetEntry(roomBuf->rbPgrpno)->GetName() : ns);

					if (*groupname == '?')
						{
						ListGroups(TRUE);
						}
					} while (*groupname == '?');

				if (SameString(groupname, spc))
					{
					roomBuf->rbflags.SetPrivilegedGroup(FALSE);
					roomBuf->rbflags.SetReadOnly(FALSE);
					roomBuf->rbflags.SetDownloadOnly(FALSE);
					roomBuf->rbflags.SetUploadOnly(FALSE);
					roomBuf->rbflags.SetGroupModerates(FALSE);
					}
				else
					{
					const g_slot groupslot =
							FindGroupByPartialName(groupname, FALSE);

					if (*groupname && (groupslot != CERROR))
						{
						roomBuf->rbflags.SetPrivilegedGroup(TRUE);
						roomBuf->rbPgrpno = (uchar) groupslot;

						roomBuf->rbflags.SetReadOnly(getYesNo(getmsg(1208),
								roomBuf->rbflags.IsReadOnly()));

						char prompt[128];

						sprintf(prompt, getmsg(1209), cfg.Ugroup_nym);

						roomBuf->rbflags.SetGroupModerates(getYesNo(prompt,
								roomBuf->rbflags.IsGroupModerates()));

						if (roomBuf->rbflags.IsMsDOSdir())
							{
							roomBuf->rbflags.SetDownloadOnly(getYesNo(
									getmsg(1195),
									roomBuf->rbflags.IsDownloadOnly()));

							if (!roomBuf->rbflags.IsDownloadOnly())
								{
								roomBuf->rbflags.SetUploadOnly(getYesNo(
										getmsg(1196),
										roomBuf->rbflags.IsUploadOnly()));
								}
							else
								{
								roomBuf->rbflags.SetUploadOnly(FALSE);
								}
							}
						}
					else
						{
						if (*groupname)
							{
							CRmPrintfCR(getmsg(947), cfg.Lgroup_nym);
							}
						}
					}

				break;
				}

			case 'W':
				{
				mPrintfCR(getmsg(1184));

				if (TI()CurrentUser->IsSysop())
					{
					label NetID;

					do
						{
						getString(getmsg(1185), NetID, LABELSIZE, TRUE, ECHO,
								roomBuf->netID);

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

					normalizeString(NetID);
					stripansi(NetID);
					strip(NetID, '"');

					r_slot roomslot = IdExists(NetID, FALSE);

					if (roomslot != CERROR && (roomslot != TI()thisRoom) && *NetID)
						{
						mPrintfCR(getmsg(137), NetID);
						}
					else
						{
						CopyStringToBuffer(roomBuf->netID, NetID, LABELSIZE);
						}
					}
				else
					{
					CRmPrintfCR(getmsg(1318));
					}

				break;
				}

			case 'X':
				{
				roomBuf->NOEXCLUDE = changeYesNo(getmsg(4),
						roomBuf->NOEXCLUDE);
				break;
				}

			case 'Y':
				{
				if ((TI()thisRoom > 2) || (TI()thisRoom >= 0 && TI()CurrentUser->IsSysop()))
					{
					roomBuf->rbflags.SetAnonymous(changeYesNo(getmsg(5),
							roomBuf->rbflags.IsAnonymous()));
					}
				else
					{
					mPrintfCR(getmsg(1214));

					CRmPrintfCR(getmsg(1205), GetRoomName(LOBBY),
							GetRoomName(MAILROOM), GetRoomName(AIDEROOM),
							getmsg(1215));
					}

				break;
				}

			case '\r':
			case '\n':
			case '?':
				{
				mPrintfCR(getmsg(351));

				prtMess = TRUE;
				break;
				}

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

	if (waspublic &&
			(!roomBuf->rbflags.IsPublic() || roomBuf->rbflags.IsBIO()))
		{
		cycleroom(TI()thisRoom, FALSE, FALSE);
		TI()CurrentUser->SetInRoom(TI()thisRoom, TRUE);
		}

	if (!waspublic &&
			(roomBuf->rbflags.IsPublic() && !roomBuf->rbflags.IsBIO()))
		{
		cycleroom(TI()thisRoom, TRUE, FALSE);
		}

	putRoom(TI()thisRoom, roomBuf);

	// trap it
	char TrapStr[80];
	sprintf(TrapStr, getmsg(1226),
			oldname, roomBuf->rbname, TI()CurrentUser->GetName());
	trap(TrapStr, T_AIDE);

	// Aide room
	Message *Msg = new Message;

	if (Msg)
		{
		char summary[500];

		CreateRoomSummary(summary, TI()thisRoom);
		Msg->SetTextWithFormat(getmsg(1463), TrapStr, bn, summary);

		if (roomBuf->rbflags.IsGroupOnly())
			{
			if (roomBuf->rbflags.IsBooleanGroup())
				{
				Msg->SetGroup(GroupData->GetEntry(1)->GetName());
				}
			else
				{
				Msg->SetGroup(GroupData->GetEntry(roomBuf->rbgrpno)->GetName());
				}
			}

		Msg->SetRoomNumber(AIDEROOM);

		systemMessage(Msg);

		delete Msg;
		}
	else
		{
		mPrintf(getmsg(188), getmsg(1319));
		}

	TI()thisRoom = oldthisRoom;
	getRoom(TI()thisRoom, roomBuf);

	return (TRUE);
	}


// --------------------------------------------------------------------------
// killempties(): Sysop fn to kill empty rooms.

void killempties(void)
	{
	Message *Msg = new Message;

	if (Msg)
		{
		label oldName;
		Bool didkill = FALSE;

		SetDoWhat(SYSKEMPTY);

		CopyStringToBuffer(oldName, roomBuf->rbname, LABELSIZE);

		Msg->SetTextWithFormat(getsysmsg(168), TI()CurrentUser->GetName());
		trap(Msg->GetText(), T_AIDE);

		r_slot slot;
		for (slot = DUMP + 1; slot < cfg.maxrooms; slot++)
			{
			if (IsRoomInuse(slot))
				{
				Bool goodRoom = FALSE;

				if (IsRoomPermanent(slot) || IsRoomDirectory(slot) ||
						IsRoomApplication(slot))
					{
					goodRoom = TRUE;
					}
				else
					{
					const m_slot t_size = sizetable();

					for (m_slot i = 0; i < t_size; ++i)
						{
						if (getRoomNum(i) == slot)
							{
							goodRoom = TRUE;
							break;
							}
						}
					}

				if (!goodRoom)
					{
					int i;
					aRoom rBuf;
					char text[LABELSIZE+10];

					getRoom(slot, &rBuf);

					sprintf(text, getmsg(377), rBuf.rbname);

					if ((i = getYesNo(text, 3)) == TRUE)
						{
						if (slot == TI()thisRoom)
							{
							getRoom(LOBBY, roomBuf);
							TI()thisRoom = LOBBY;
							}

						// Nuke the room
						Msg->AppendText(rBuf.rbname);
						Msg->AppendText(getmsg(1464));
						memset(&rBuf, 0, sizeof(aRoom));
						putRoom(slot, &rBuf);
						didkill = TRUE;
						}

					if (i == 2)
						{
						break;
						}
					}
				}
			}

		if (didkill)
			{
			Msg->SetRoomNumber(AIDEROOM);
			systemMessage(Msg);
			}

		delete Msg;
		}
	else
		{
		mPrintf(getmsg(188), getmsg(1320));
		}
	}


// --------------------------------------------------------------------------
// killroom(): Aide fn to kill specified room.

Bool killroom(const char *name)
	{
	aRoom rBuf;

	label roomname;
	r_slot roomslot;
	char string[256];

	if (name)
		{
		roomslot = RoomExists(name);

		if (roomslot == CERROR)
			{
			return (FALSE);
			}
		}
	else
		{
		Bool test;

		SetDoWhat(AIDEKILL);

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

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

			if (SameString(roomname, GetRoomName(TI()thisRoom)))
				{
				roomslot = TI()thisRoom;
				test = TRUE;
				}
			else
				{
				normalizeString(roomname);

				if (!*roomname)
					{
					return (FALSE);
					}

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

				test = TRUE;
				if (roomslot == CERROR)
					{
					CRmPrintfCR(getmsg(157), cfg.Lroom_nym, roomname);
					test = FALSE;
					}
				}
			} while (!test);
		}

	if (roomslot <= DUMP)
		{
		if (!name)
			{
			CRmPrintfCR(getmsg(379),
					GetRoomName(LOBBY), GetRoomName(MAILROOM),
					GetRoomName(AIDEROOM), GetRoomName(DUMP));
			}

		return (FALSE);
		}

	sprintf(string, getmsg(377), GetRoomName(roomslot));
	if (!name && !getYesNo(string, 0))
		{
		return (FALSE);
		}

	// Remove all messages from room.
	const m_slot t_size = sizetable();
	for (m_slot i = 0; i < t_size; i++)
		{
		if (getRoomNum(i) == roomslot)
			{
			if (getFlags(i)->IsMail())
				{
				changeheader((ulong) (cfg.mtoldest + i), MAILROOM, UCHAR_MAX);
				}
			else
				{
				changeheader((ulong) (cfg.mtoldest + i), DUMP, UCHAR_MAX);
				}
			}
		}

	// kill room from every hall and write it to disk
	for (h_slot j = 0; j < cfg.maxhalls; j++)
		{
		HallData->GetEntry(j)->SetRoomInHall(roomslot, FALSE);
		HallData->GetEntry(j)->SetWindowedIntoHall(roomslot, FALSE);
		}

	HallData->Save();

	// remove from all personal halls.
	TI()CurrentUser->SetRoomInPersonalHall(roomslot, FALSE);

	for (l_slot l = 0; l < cfg.MAXLOGTAB; l++)
		{
		LogEntry6 Log6(cfg.maxrooms);

		Log6.Load(l);
		Log6.SetRoomInPersonalHall(roomslot, FALSE);
		Log6.Save(l);
		}

	sprintf(string, getmsg(380), GetRoomName(roomslot),
			TI()CurrentUser->GetName());
	trap(string, T_AIDE);

	getRoom(roomslot, &rBuf);

	Message *Msg = new Message;

	if (Msg)
		{
		sprintf(string, getmsg(1379), cfg.Uroom_nym, GetRoomName(roomslot),
				TI()CurrentUser->GetName());
		Msg->SetText(string);

		if (rBuf.rbflags.IsGroupOnly())
			{
			if (rBuf.rbflags.IsBooleanGroup())
				{
				Msg->SetGroup(GroupData->GetEntry(1)->GetName());
				}
			else
				{
				Msg->SetGroup(GroupData->GetEntry(rBuf.rbgrpno)->GetName());
				}
			}

		Msg->SetRoomNumber(AIDEROOM);
		systemMessage(Msg);

		delete Msg;
		}
	else
		{
		mPrintf(getmsg(188), getmsg(1314));
		}

	if (rBuf.rbflags.IsShared() && *rBuf.netID && !IsNetIDInNetIDCit(rBuf.netID))
		{
		AddNetIDToNetIDCit(rBuf.netID, getmsg(1366));
		}

	rBuf.rbflags.SetInuse(FALSE);

	putRoom(roomslot, &rBuf);

	if (roomslot == TI()thisRoom)
		{
		CRmPrintf(getmsg(1367));
		stepRoom(0);
		}

	return (TRUE);
	}


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

Bool moveRoom(int offset, Bool inHall)
	{
	r_slot rp1, rp2;

	SetDoWhat(MOVEROOM);

	mPrintfCR(getmsg(383), cfg.Lroom_nym);
	doCR();

	rp1 = GetRoomPosInTable(TI()thisRoom);

	if	((rp1 > (LOBBY+1) || offset == 1) &&
			(rp1 < (cfg.maxrooms - 1) || offset == -1) &&
			(TI()thisRoom != LOBBY))
		{

		do
			{
			rp2 = rp1 + offset;

			roomPos[rp1] = RoomPosTableToRoom(rp2);
			roomPos[rp2] = TI()thisRoom;

			rp1 = rp2;
			} while (
					(rp1 > (LOBBY+1) || offset == 1) &&
					(rp1 < cfg.maxrooms - 1 || offset == -1) &&
					!(IsRoomInuse(RoomPosTableToRoom(rp1 - offset)) &&
					(!inHall || TI()CurrentUser->IsUsePersonalHall() ?
					TI()CurrentUser->IsRoomInPersonalHall(RoomPosTableToRoom(rp1 - offset)) :
					roominhall(RoomPosTableToRoom(rp1 - offset), TI()thisHall))));

		putRoomPos();

		if (!(IsRoomInuse(RoomPosTableToRoom(rp1 - offset)) &&
				(!inHall || TI()CurrentUser->IsUsePersonalHall() ?
				TI()CurrentUser->IsRoomInPersonalHall(RoomPosTableToRoom(rp1 - offset)) :
				roominhall(RoomPosTableToRoom(rp1 - offset), TI()thisHall))))
			{
			return (FALSE);
			}
		else
			{
			do
				{
				rp2--;
				} while (rp2 && !(IsRoomInuse(RoomPosTableToRoom(rp2)) &&
						(!inHall || TI()CurrentUser->IsUsePersonalHall() ?
						TI()CurrentUser->IsRoomInPersonalHall(RoomPosTableToRoom(rp1 - offset)) :
						roominhall(RoomPosTableToRoom(rp2), TI()thisHall))));

			mPrintfCR(getmsg(384), cfg.Uroom_nym,
					GetRoomName(RoomPosTableToRoom(rp2)));

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