⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 MudMaster 2000 的C++源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//	_screen.SetColor(wOriginalAttr);
	return(0);
}

void SendText(const char *pszText, BOOL bAppendCR)
{
	if (!_bConnected)
	{
		PrintMessage("No Session Active.");
		return;
	}

	if (!_bUsingModem)
	{
		int nNumSent = send(_hActiveSocket,pszText,strlen(pszText),0);
		if (nNumSent == SOCKET_ERROR)
		{
			PrintError();
			return;
		}
		if (bAppendCR)
		{
			if (send(_hActiveSocket,"\r\n",2,0) == SOCKET_ERROR)
			{
				PrintError();
				return;
			}
		}
	}
	else
	{
		int nNumSent = _modem.Send(pszText);
		if (!nNumSent)
		{
			// have an error.
			return;
		}
		if (bAppendCR)
		{
			if (!_modem.Send("\r\n"))
			{
				// have an error.
				return;
			}
		}
	}
}

extern "C" void DllCallback(const char *pszText)
{
	CString strText;

	strText = pszText;
	_debugStack.Push(0,STACK_TYPE_DLL_CALLBACK);
	HandleInput(strText);
	_debugStack.Pop();
}

void HandleInput(CString &strLine)
{
	if (strLine.IsEmpty())
	{
		if (_config.bEcho)
		{
			BOOL bActionsState = _terminal.ActionsState();
			if (bActionsState)
				_terminal.ActionsOff();
			_terminal.Print("\n");
			if (bActionsState)
				_terminal.ActionsOn();
			_tiUserInput.SetFocus();
		}
		SendText("\r\n",FALSE);
		return;
	}

	if (strLine.GetAt(0) == '!')
		strLine = _strLastLine;

	int nLen = strLine.GetLength();
	// If the first character is a the command char, and the next
	// character is a digit, then it is a line to be repeated.
	if (strLine.GetAt(0) == _config.chCommand && nLen > 2 && isdigit(strLine.GetAt(1)))
	{
		int nIndex = strLine.Find(' ');
		if (nIndex != -1)
		{
			CString strTemp(strLine.Right(nLen-nIndex-1));
			CString strText;
			int nReps = atoi(((const char *)strLine)+1);
			for (int i=0;i<nReps;i++)
			{
				// have to keep copying it in fresh because I'm passing
				// the CStrings by value to keep from having to copy
				// them over and over to work with them.  But this means
				// the contents of the string passed down can and will
				// be corrupted by the time it gets back.
				strText = strTemp;
				HandleInput(strText);
			}
			return;
		}
		else
		{
			PrintMessage("Invalid Command.",TRUE,TRUE);
			_debugStack.DumpStack(_config.nDebugDepth);
			return;
		}
	}

	CString strTemp;
	int nStatementCount = 0;
	int nIndex = 0;
	while(nIndex < nLen)
	{
		if (strLine[nIndex] == _config.chBlockStart)
			nStatementCount++;

		if (strLine[nIndex] == _config.chBlockEnd)
			nStatementCount--;

		// Check for the escape character.
		if (strLine[nIndex] == _config.chEscape)
		{
			// Need to check and see what next character is.
			// Make sure there is still 1 more to read.
			nIndex++;
			if (nIndex < nLen)
			{
				if (strLine[nIndex] == _config.chEscape)
					strTemp += _config.chEscape;
				else
					if (strLine[nIndex] == _config.chSeparator)
						strTemp += _config.chSeparator;
					else
					{
						strTemp += _config.chEscape;
						strTemp += strLine[nIndex];
					}
			}
			else
				strTemp += _config.chEscape;

			nIndex++;
			continue;
		}

		// Only process a semi-colon if not within a statement block.
		if (strLine[nIndex] == _config.chSeparator && !nStatementCount)
		{
			if (!strTemp.IsEmpty())
			{
				if (strTemp.GetLength() > 2 && strTemp.GetAt(0) == _config.chCommand && isdigit(strTemp.GetAt(1)))
					HandleInput(strTemp);
				else
					ProcessLine(strTemp);
				strTemp.Empty();
			}
			nIndex++;
			continue;
		}
		
		strTemp += strLine[nIndex];
		nIndex++;
	}

	if (!strTemp.IsEmpty())
	{
		if (strTemp.GetLength() > 2 && strTemp.GetAt(0) == _config.chCommand && isdigit(strTemp.GetAt(1)))
			HandleInput(strTemp);
		else
			ProcessLine(strTemp);
	}
}

void FindStatement(CString &strText, CString &strResult)
{
	strResult.Empty();
	strText.TrimRight();
	strText.TrimLeft();
	if (strText.IsEmpty())
		return;
	char chEndChar = _config.chBlockEnd;
	char chStartChar = _config.chBlockStart;
	int nBlockCount = 0;
	if (strText[0] != _config.chBlockStart)
	{
		chEndChar = ' ';
		chStartChar = ' ';
		// If we are using spaces for parameter separators we
		// need to start it at one since we will never encounter
		// a starting space.
		nBlockCount = 1;
	}
	char ch;
	int nProcCount = 0;
	int nIndex = 0;
	int nLen = strText.GetLength();
	while(nIndex < nLen)
	{
		ch = strText[nIndex];

		if (ch == _config.chEscape && nIndex+1 < nLen && strText[nIndex+1] == '@')
		{
			strResult += "\\@";
			nIndex += 2;
			continue;
		}

		// Need to watch for procedures.  Each time we find a procedure
		// we need to look for a matched set of parens.
		if (ch == '@')
		{
			nProcCount++;
			nIndex++;
			strResult += ch;
			continue;
		}

		// If the user wants to print a closing paren while inside
		// a procedure definition, they need to use the escape char.
		if (ch == _config.chEscape && nIndex+1 < nLen && strText[nIndex+1] == ')')
		{
			strResult += "\\)";
			nIndex++;
			continue;
		}

		if (ch == ')' && nProcCount)
			nProcCount--;

		if (ch == chEndChar && !nProcCount)
		{
			nBlockCount--;
			if (!nBlockCount)
				break;
		}

		// If this is the first block symbol we need to skip over it, it should not
		// be part of our result string.
		if (ch == chStartChar && !nBlockCount)
		{
			nBlockCount++;
			nIndex++;
			continue;
		}
		
		if (ch == chStartChar && !nProcCount)
			nBlockCount++;

		strResult += ch;
		nIndex++;
	}

	if (nIndex+1 < nLen)
		strText = strText.Right(nLen-nIndex-1);
	else
		strText.Empty();
}

void ProcessLine(CString &strLine)
{
	if (strLine.IsEmpty())
		return;

	if ((strLine[0] != _config.chCommand && strLine[0] != '@') || 
		 (strLine[0] == _config.chCommand && strLine[1] == _config.chCommand))
	{
		// Get rid of the first command char if doubled up.
		if (strLine[0] == _config.chCommand && strLine[1] == _config.chCommand)
			strLine = strLine.Right(strLine.GetLength()-1);

		ReplaceVariables(strLine);
		if (!_config.bIgnoreAliases)
		{
			ALIAS_MAP *pMap = _aliases.FindMatch(strLine);
			if (pMap != NULL)
			{
				CString strText(pMap->strText);		 
				_debugStack.Push(_aliases.GetFindIndex(),STACK_TYPE_ALIAS);
				HandleInput(strText);
				_debugStack.Pop();
				return;
			}
		}

		if (_config.bSpeedWalk && strLine.GetLength() > 1 && IsWalkable(strLine))
		{
			DoSpeedWalk(strLine);
			return;
		}

		if (_config.bEcho)
		{
			BOOL bActionsState = _terminal.ActionsState();
			if (bActionsState)
				_terminal.ActionsOff();
			_terminal.Print(strLine+"\n");
			if (bActionsState)
				_terminal.ActionsOn();
			_tiUserInput.SetFocus();
		}

		// For the aliases that take a parameter and no param is passed
		// I think the trailing spaces are upsetting the mud.  So trim
		// the string first.
		strLine.TrimRight();

		if (strLine.IsEmpty())
			SendText("\r\n",FALSE);
		else
			SendText(strLine);
		return;
	}

	if (strLine[0] == '@')
	{
		if (DoProcedure(strLine))
			return;
		ReplaceVariables(strLine);
		CString strTemp(strLine);
		HandleInput(strTemp);
		return;
	}

	// Must have a space between the command and the first {
	CString strCommand;
	int nIndex = strLine.Find(' ');
	if (nIndex == -1)
	{
		strCommand = ((const char *)strLine)+1;
		strLine.Empty();
	}
	else
	{
		strCommand = strLine.Mid(1,nIndex-1);
		strLine = strLine.Right(strLine.GetLength()-nIndex-1);
	}
	strCommand.MakeLower();

	const char *pszCommand = (const char *)strCommand;

	HASHITEM *phi = _htCommands[*pszCommand];
	if (!phi || phi->nStart == HASHITEM_EMPTY || phi->nEnd == HASHITEM_EMPTY)
	{
		PrintMessage("Invalid Command.",TRUE,TRUE);
		_debugStack.DumpStack(_config.nDebugDepth);
		return;
	}

	for (int i=phi->nStart;i<=phi->nEnd && _commandList[i].proc;i++)
	{
		if (!_commandList[i].bWholeMatch)
		{
			if (IsPartial(pszCommand,_commandList[i].szCommand))
			{
				(_commandList[i].proc)(strLine);
				return;
			}
		}
		else
		{
			// Complete text match only.  Used to protect sensitive commands
			// from being accidentally triggered.
			if (!strcmp(pszCommand,_commandList[i].szCommand))
			{
				(_commandList[i].proc)(strLine);
				return;
			}
		}
	}

	PrintMessage("Invalid Command.",TRUE,TRUE);
	_debugStack.DumpStack(_config.nDebugDepth);
}

void GetSocketError(CString &strError)
{
	long lError = WSAGetLastError();

	switch(lError)
	{
		case WSAECONNREFUSED :
			strError = "Connection Refused";
			break;

		case WSAENETUNREACH :
			strError = "Host Unreachable";
			break;

		case WSAETIMEDOUT :
			strError = "Connection Timed Out";
			break;

		case WSAEISCONN :
			strError = "Already Connected";
			break;

		case WSAEWOULDBLOCK :
			strError = "Would Block";
			break;

		case WSANOTINITIALISED :
			strError = "WSAStartup Not Called";
			break;

		case WSAENETDOWN :
			strError = "Network Subsytem Failed";
			break;

		case WSAEADDRNOTAVAIL :
			strError = "Host Unreachable";
			break;

		case WSAECONNRESET :
			strError = "Connect Reset by Remote Host";
			break;

		case WSAEADDRINUSE :
			strError = "Address already in use.";
			break;

		default :
			strError.Format("Unknown (%ld)",lError);
			break;
	}
}

void Connect(const char *pszName, const char *pszAddress, const char *pszPort)
{
	if (_bConnected)
	{
		PrintMessage("Already Connected.");
		return;
	}

	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));

	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr(pszAddress);
	sockAddr.sin_port = htons((u_short)atoi(pszPort));

	if (sockAddr.sin_addr.s_addr == INADDR_NONE)
	{
		CString strMessage("Looking up host: ");
		strMessage += pszAddress;
		strMessage += "...";
		PrintMessage(strMessage);

		LPHOSTENT lphost;
		lphost = gethostbyname(pszAddress);
		if (lphost != NULL)
			sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		else
		{
			PrintMessage("Error: Unable to find host.");
			return;
		}
	}

	// Get a socket handle.
	_hActiveSocket = socket(PF_INET,SOCK_STREAM,0);
	if (_hActiveSocket == INVALID_SOCKET)
	{
		PrintMessage("Error: Unable to get a socket handle.");
		return;
	}

	// Make sure it is a non-blocking socket.
	unsigned long lNonBlocking = 1;
	ioctlsocket(_hActiveSocket,FIONBIO,&lNonBlocking);

	CString strMessage("Connecting to ");
	strMessage += pszAddress;
	strMessage += " (ESC to abort) ...";
	PrintMessage(strMessage);
	int nResult = connect(_hActiveSocket,(SOCKADDR*)&sockAddr, sizeof(sockAddr));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -