// --------------------------------------------------------------------------
// Citadel: MCI.CPP
//
// MCI Handler code

#include "ctdl.h"
#pragma hdrstop

#include "log.h"
#include "hall.h"
#include "room.h"
#include "tallybuf.h"
#include "term.h"


// --------------------------------------------------------------------------
// Contents
//
// MCI()			MCI


Bool MCIRecursionCheckerC::Start(MCICommandsE WhichOne)
	{
	assert(WhichOne >= (MCICommandsE) 0);
	assert(WhichOne < MCI_NUMCODES);

	if (MCIDisabled[WhichOne] || MCIBusy[WhichOne])
		{
		return (FALSE);
		}
	else
		{
		MCIBusy[WhichOne] = TRUE;
		return (TRUE);
		}
	}

void MCI_DispOrAsgn(const char *str, label vars[])
	{
	assert(str != NULL);
	assert(vars != NULL);

	if (TI()MCI_asgnnext)
		{
		strncpy(vars[TI()MCI_asgnvar], str, LABELSIZE);
		vars[TI()MCI_asgnvar][LABELSIZE] = 0;

		TI()MCI_asgnnext = FALSE;
		}
	else
		{
		mFormat(str);
		}
	}

void MCI(const char *c)
	{
	assert(c);

	char *OurCopy = strdup(c);

	if (OurCopy)
		{
		char string[100];

		OurCopy++;

		if (c[strlen(OurCopy) - 1] == 'X')
			{
			OurCopy[strlen(OurCopy) - 1] = 0;
			}

		if (TI()OC.MCI_goto)
			{
			if ((strncmpi(OurCopy, MCICodes[MCI_LABEL], 2) == SAMESTRING) &&
					(SameString(OurCopy + 2, TI()OC.MCI_label)))
				{
				ansi(14);
				TI()OC.MCI_goto = FALSE;
				TI()OC.MCI_label[0] = 0;
				}
			}
		else
			{
			int i;
			for (i = 0; strncmpi(OurCopy, MCICodes[i], 2) != SAMESTRING; i++);

			switch (i)
				{
				case MCI_REALNAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_REALNAME))
						{
						if (TI()loggedIn)
							{
							sprintf(string, pcts,
									special_deansi(TI()CurrentUser->GetRealName(), MCICodes[MCI_REALNAME]));
							MCI_DispOrAsgn(string, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_REALNAME);
						}

					break;
					}

				case MCI_LASTNAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_LASTNAME))
						{
						if (TI()loggedIn)
							{
							char *str = string;

							strcpy(str,
									special_deansi(TI()CurrentUser->GetName(),
									MCICodes[MCI_LASTNAME]));

							if (strrchr(str, ' '))
								{
								str = strrchr(string, ' ');
								}

							MCI_DispOrAsgn(str, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_LASTNAME);
						}

					break;
					}

				case MCI_PHONENUM:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_PHONENUM))
						{
						if (TI()loggedIn)
							{
							sprintf(string, pcts,
									special_deansi(TI()CurrentUser->GetPhoneNumber(), MCICodes[MCI_PHONENUM]));
							MCI_DispOrAsgn(string, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_PHONENUM);
						}

					break;
					}

				case MCI_ADDR:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_ADDR))
						{
						if (TI()loggedIn)
							{
							if (OurCopy[2] == '2')
								{
								sprintf(string, pcts,
										special_deansi(TI()CurrentUser->GetMailAddr2(), MCICodes[MCI_ADDR]));
								}
							else if (OurCopy[2] == '3')
								{
								sprintf(string, pcts,
										special_deansi(TI()CurrentUser->GetMailAddr3(), MCICodes[MCI_ADDR]));
								}
							else
								{
								sprintf(string, pcts,
										special_deansi(TI()CurrentUser->GetMailAddr1(), MCICodes[MCI_ADDR]));
								}

							MCI_DispOrAsgn(string, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_ADDR);
						}

					break;
					}

				case MCI_LASTCALLD:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_LASTCALLD))
						{
						strftime(string, 79, (TI()loggedIn) ?
								special_deansi(TI()CurrentUser->GetVerboseDateStamp(),
								MCICodes[MCI_LASTCALLD]) :
								special_deansi(cfg.vdatestamp, MCICodes[MCI_LASTCALLD]), 0l);

						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_LASTCALLD);
						}

					break;
					}

				case MCI_ACCTBAL:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_ACCTBAL))
						{
						sprintf(string, pctld, TI()CurrentUser->GetCredits() / 60);
						MCI_DispOrAsgn(string, TI()MCI_str);
						MCIRecursionChecker.End(MCI_ACCTBAL);
						}

					break;
					}

				case MCI_ROOMNAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_ROOMNAME))
						{
						strcpy(string,
								special_deansi(GetRoomName(TI()thisRoom),
								MCICodes[MCI_ROOMNAME]));
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_ROOMNAME);
						}

					break;
					}

				case MCI_HALLNAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_HALLNAME))
						{
						strcpy(string,
								special_deansi(HallData->GetEntry(TI()thisHall)->GetName(),
								MCICodes[MCI_HALLNAME]));
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_HALLNAME);
						}

					break;
					}

				case MCI_NODENAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_NODENAME))
						{
						strcpy(string,
								special_deansi(cfg.nodeTitle, MCICodes[MCI_NODENAME]));
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_NODENAME);
						}

					break;
					}

				case MCI_NODEPHONE:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_NODEPHONE))
						{
						strcpy(string,
								special_deansi(cfg.nodephone, MCICodes[MCI_NODEPHONE]));
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_NODEPHONE);
						}

					break;
					}

				case MCI_DISKFREE:
					{
					break;
					}

				case MCI_NUMMSGS:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_NUMMSGS))
						{
						sprintf(string, pctld, TI()MS.Read);
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_NUMMSGS);
						}

					break;
					}

				case MCI_CLS:
					{
					break;
					}

				case MCI_CALLNUM:
					{
					break;
					}

				case MCI_SYSOPNAME:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_SYSOPNAME))
						{
						sprintf(string, pcts,
								special_deansi(cfg.sysop, MCICodes[MCI_SYSOPNAME]));
						MCI_DispOrAsgn(string, TI()MCI_str);

						MCIRecursionChecker.End(MCI_SYSOPNAME);
						}

					break;
					}

				case MCI_CONNRATE:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_CONNRATE))
						{
						sprintf(string, pctlu, connectbauds[TI()ModemSpeed]);
						MCI_DispOrAsgn(string, TI()MCI_str);
						MCIRecursionChecker.End(MCI_CONNRATE);
						}

					break;
					}

				case MCI_PORTRATE:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_PORTRATE))
						{
						sprintf(string, pctlu, bauds[TI()SerialPort.GetSpeed()]);
						MCI_DispOrAsgn(string, TI()MCI_str);
						MCIRecursionChecker.End(MCI_PORTRATE);
						}

					break;
					}

				case MCI_MSGROOM:
					{
					if (TI()OC.UseMCI && MCIRecursionChecker.Start(MCI_MSGROOM))
						{
						sprintf(string, pctlu, GetRoomMessages(TI()thisRoom));
						MCI_DispOrAsgn(string, TI()MCI_str);
						MCIRecursionChecker.End(MCI_MSGROOM);
						}

					break;
					}

				case MCI_BEEPNUM:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_BEEPNUM))
						{
						int num;

						for (num = OurCopy[2] - '0'; num; num--)
							{
							oChar(BELL);
							}

						MCIRecursionChecker.End(MCI_BEEPNUM);
						}

					break;
					}

				case MCI_GETCHAR:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_GETCHAR))
						{
						TI()MCI_char[OurCopy[2] - '0'] = (char) iCharNE();
						MCIRecursionChecker.End(MCI_GETCHAR);
						}

					break;
					}

				case MCI_GETSTR:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_GETSTR))
						{
						UserControlType oldOF = TI()UserControl.GetOutFlag();

						getString(ns, TI()MCI_str[OurCopy[2] - '0'], LABELSIZE, FALSE,
								TRUE, ns);

						TI()UserControl.SetOutFlag(oldOF);

						MCIRecursionChecker.End(MCI_GETSTR);
						}

					break;
					}

				case MCI_PUTCHAR:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_PUTCHAR))
						{
						oChar(TI()MCI_char[OurCopy[2] - '0']);
						MCIRecursionChecker.End(MCI_PUTCHAR);
						}

					break;
					}

				case MCI_PUTSTR:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_PUTSTR))
						{
						MCI_DispOrAsgn(TI()MCI_str[OurCopy[2] - '0'], TI()MCI_str);

						MCIRecursionChecker.End(MCI_PUTSTR);
						}

					break;
					}

				case MCI_BSNUM:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_BSNUM))
						{
						int num;

						for (num = OurCopy[2] - '0'; num; num--)
							{
							doBS();
							}

						MCIRecursionChecker.End(MCI_BSNUM);
						}

					break;
					}

				case MCI_OUTSPEC:
					{
					break;
					}

				case MCI_SLOW:
					{
					break;
					}

				case MCI_PASSWORD:
					{
					if (TI()OC.UseMCI &&
							MCIRecursionChecker.Start(MCI_PASSWORD))
						{
						if (TI()loggedIn)
							{
							sprintf(string, pcts,
									special_deansi(TI()CurrentUser->GetPassword(), MCICodes[MCI_PASSWORD]));
							MCI_DispOrAsgn(string, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_PASSWORD);
						}

					break;
					}

				case MCI_INITIALS:
					{
					if (TI()OC.UseMCI &&
							MCIRecursionChecker.Start(MCI_INITIALS))
						{
						if (TI()loggedIn)
							{
							sprintf(string, pcts,
									special_deansi(TI()CurrentUser->GetInitials(), MCICodes[MCI_INITIALS]));
							MCI_DispOrAsgn(string, TI()MCI_str);
							}
						else
							{
							MCI_DispOrAsgn(getmsg(100), TI()MCI_str);
							}

						MCIRecursionChecker.End(MCI_INITIALS);
						}

					break;
					}

				case MCI_GOTO:
					{
					if (TI()OC.UseMCI &&
							TI()UserControl.GetOutFlag() != IMPERVIOUS &&
							MCIRecursionChecker.Start(MCI_GOTO))
						{
						TI()OC.MCI_goto = TRUE;
						strncpy(TI()OC.MCI_label, OurCopy + 2, LABELSIZE);
						TI()OC.MCI_label[LABELSIZE] = 0;

						if (TI()UserControl.GetOutFlag() == IMPERVIOUS)
							{
							TI()UserControl.SetOutFlag(OUTOK);
							}

						MCIRecursionChecker.End(MCI_GOTO);
						}

					break;
					}

				case MCI_COMPARE:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_COMPARE))
						{
						if (toupper(OurCopy[3]) == 'V' && isdigit(OurCopy[5]))
							{
							// variable comparison
							if (toupper(OurCopy[4]) == 'N')
								{
								// numeric
								TI()MCI_result = atoi(TI()MCI_str[OurCopy[2] - '0']) -
										atoi(TI()MCI_str[OurCopy[5] - '0']);
								}
							else if (toupper(OurCopy[4]) == 'C')
								{
								// character
								TI()MCI_result = toupper(TI()MCI_char[OurCopy[2] - '0']) -
										(TI()MCI_char[OurCopy[5] - '0']);
								}
							else
								{
								// string
								TI()MCI_result = strcmpi(TI()MCI_str[OurCopy[2] - '0'],
										TI()MCI_str[OurCopy[5] - '0']);
								}
							}
						else if (toupper(OurCopy[3]) == 'N')
							{
							// numeric
							TI()MCI_result = atoi(TI()MCI_str[OurCopy[2] - '0']) - atoi(OurCopy + 4);
							}
						else if (toupper(OurCopy[3]) == 'C')
							{
							// character
							TI()MCI_result = toupper(TI()MCI_char[OurCopy[2] - '0']) -
									toupper(OurCopy[4]);
							}
						else
							{
							// string
							TI()MCI_result = strcmpi(TI()MCI_str[OurCopy[2] - '0'], OurCopy + 4);
							}

						MCIRecursionChecker.End(MCI_COMPARE);
						}

					break;
					}

				case MCI_GT:
					{
					if (TI()OC.UseMCI &&
							MCIRecursionChecker.Start(MCI_GT))
						{
						if (TI()MCI_result > 0)
							{
							label temp;

							temp[0] = 'X';
							strncpy(temp + 1, OurCopy + 2, LABELSIZE - 1);
							temp[LABELSIZE] = 0;
							termCap(temp);
							}

						MCIRecursionChecker.End(MCI_GT);
						}

					break;
					}

				case MCI_LT:
					{
					if (TI()OC.UseMCI &&
							MCIRecursionChecker.Start(MCI_LT))
						{
						if (TI()MCI_result < 0)
							{
							label temp;

							temp[0] = 'X';
							strncpy(temp + 1, OurCopy + 2, LABELSIZE - 1);
							temp[LABELSIZE] = 0;
							termCap(temp);
							}

						MCIRecursionChecker.End(MCI_LT);
						}

					break;
					}

				case MCI_EQ:
					{
					if (TI()OC.UseMCI &&
							MCIRecursionChecker.Start(MCI_EQ))
						{
						if (TI()MCI_result == 0)
							{
							label temp;

							temp[0] = 'X';
							strncpy(temp + 1, OurCopy + 2, LABELSIZE - 1);
							temp[LABELSIZE] = 0;
							termCap(temp);
							}

						MCIRecursionChecker.End(MCI_EQ);
						}

					break;
					}

				case MCI_RANDOM:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_RANDOM))
						{
						sprintf(TI()MCI_str[OurCopy[2] - '0'], pctd, random(atoi(OurCopy + 3)) + 1);
						MCIRecursionChecker.End(MCI_RANDOM);
						}

					break;
					}

				case MCI_ASSIGN:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_ASSIGN))
						{
						strncpy(TI()MCI_str[OurCopy[2] - '0'], OurCopy + 3, LABELSIZE);
						TI()MCI_str[OurCopy[2] - '0'][LABELSIZE] = 0;
						MCIRecursionChecker.End(MCI_ASSIGN);
						}

					break;
					}

				case MCI_ADD:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_ADD))
						{
						int i = 3, sum = 0;

						while (isdigit(OurCopy[i]))
							{
							sum += atoi(TI()MCI_str[OurCopy[i++] - '0']);
							}
						sprintf(TI()MCI_str[OurCopy[2] - '0'], pctd, sum);
						MCIRecursionChecker.End(MCI_ADD);
						}

					break;
					}

				case MCI_SUBTRACT:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							isdigit(OurCopy[3]) &&
							MCIRecursionChecker.Start(MCI_SUBTRACT))
						{
						int i = 4, dif = atoi(TI()MCI_str[OurCopy[3] - '0']);

						while (isdigit(OurCopy[i]))
							{
							dif -= atoi(TI()MCI_str[OurCopy[i++] - '0']);
							}

						sprintf(TI()MCI_str[OurCopy[2] - '0'], pctd, dif);
						MCIRecursionChecker.End(MCI_SUBTRACT);
						}

					break;
					}

				case MCI_TIMES:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							isdigit(OurCopy[3]) &&
							MCIRecursionChecker.Start(MCI_TIMES))
						{
						int i = 4, prd = atoi(TI()MCI_str[OurCopy[3] - '0']);

						while (isdigit(OurCopy[i]))
							{
							prd *= atoi(TI()MCI_str[OurCopy[i++] - '0']);
							}
						sprintf(TI()MCI_str[OurCopy[2] - '0'], pctd, prd);
						MCIRecursionChecker.End(MCI_TIMES);
						}

					break;
					}

				case MCI_DIVIDE:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							isdigit(OurCopy[3]) &&
							MCIRecursionChecker.Start(MCI_DIVIDE))
						{
						int i = 4, quo = atoi(TI()MCI_str[OurCopy[3] - '0']);

						while (isdigit(OurCopy[i]))
							{
							int divisor = atoi(TI()MCI_str[OurCopy[i++] - '0']);

							if (divisor)
								{
								quo /= divisor;
								}
							else
								{
								quo = INT_MAX;	// cheezy, huh?
								}
							}

						sprintf(TI()MCI_str[OurCopy[2] - '0'], pctd, quo);
						MCIRecursionChecker.End(MCI_DIVIDE);
						}

					break;
					}

				case MCI_ASGNNEXT:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_ASGNNEXT))
						{
						TI()MCI_asgnnext = TRUE;
						TI()MCI_asgnvar = OurCopy[2] - '0';
						MCIRecursionChecker.End(MCI_ASGNNEXT);
						}

					break;
					}

				case MCI_HANGINGINDENT:
					{
					if (TI()OC.UseMCI && isdigit(OurCopy[2]) &&
							MCIRecursionChecker.Start(MCI_HANGINGINDENT))
						{
						TI()OC.HangingIndent = atoi(OurCopy + 2);
						MCIRecursionChecker.End(MCI_HANGINGINDENT);
						}
					}
				}
			}

		delete [] OurCopy;
		}
	}
