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

📄 chwconn.cpp

📁 Windows上的MUD客户端程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		read( pstrBuffer, iLen );
		strOut.ReleaseBuffer( iLen );

		ASSERT( strOut.GetLength() == iLen );

		ParseText( strOut, (GetMode() == modeHtml) );

											// Display the text
		OutputBuffer( strOut );

		if (!IsAnyTextReceived())
		{
			SetAnyTextReceived();
			GetMainInfo()->DoAutoLogin();
		}
	}
}


void ChWorldConn::InitConnection()
{
	string		strOut;

	m_state = stateConnected;
											/* Make the default text output
												mode HTML, rather than <pre> */
	strOut = "<html>";

											/* Indicate that we will be using
												preformatted text */
	TurnHtmlOff( strOut );
	OutputBuffer( strOut, false );
}


void ChWorldConn::TermConnection()
{
	if (IsConnected())
	{
		string		strOut;

		m_state = stateNotConnected;
		TurnHtmlOn( strOut );
											/* Indicating that we are finished
												using preformatted text */
		OutputBuffer( strOut );
	}
}


void ChWorldConn::SendWorldCommand( const string& strCommand,
									bool boolUserCommand )
{
	SendLine( strCommand );

	if (boolUserCommand)
	{
		EchoState	echo = GetMainInfo()->GetEchoState();

		if (m_boolEcho && (echoOn == echo))
		{
			string		strCommandOut( strCommand );
			string		strOut;

			TurnHtmlOn( strOut );

			if (m_boolBold)
			{
				strOut += "<b>";
			}

			if (m_boolItalic)
			{
				strOut += "<i>";
			}
											/* Append the users' text to the
												output buffer */

			Display( strOut, strCommandOut );

			if (m_boolItalic)
			{
				strOut += "</i>";
			}

			if (m_boolBold)
			{
				strOut += "</b>";
			}

			strOut += "<br>";

			TurnHtmlOff( strOut );
			OutputBuffer( strOut, false );
		}
		else if (m_boolEcho && (echoOn != echo))
		{									// Just send a line break
			OutputBuffer( "\n" );
		}
	}
}


void ChWorldConn::Display( const string& strText )
{
	string		strOut;

	TurnHtmlOn( strOut );
	strOut += "<b>";

	Display( strOut, strText );
	
	strOut += "</b><br>";
	TurnHtmlOff( strOut );

	OutputBuffer( strOut, false );
}


void ChWorldConn::Display( string& strOut, const string& strText )
{
	string		strTextOut( strText );
	chuint32	luBackColor = m_ansiState.GetBackColor();
	chuint32	luForeColor = GetTextOutput()->GetDefForeColor();
	string		strColor;

	if (luForeColor == luBackColor)
	{
		luForeColor = (~luForeColor) & 0xffffff;
	}
	strColor.Format( "#%06lx", luForeColor );

	strOut += "<font text=\"" + strColor + "\">";

								/* Strip out HTML from the users'
									text and append it to the
									output buffer */

	ChHtmlWnd::EscapeForHTML( strTextOut );
	strOut += strTextOut;

	strOut += "</font>";
}


void ChWorldConn::UpdatePreferences()
{
	ChRegistry		worldPrefsReg( WORLD_PREFS_GROUP );

	worldPrefsReg.ReadBool( WORLD_PREFS_ECHO, m_boolEcho, true );
	worldPrefsReg.ReadBool( WORLD_PREFS_ECHO_BOLD, m_boolBold, true );
	worldPrefsReg.ReadBool( WORLD_PREFS_ECHO_ITALIC, m_boolItalic, false );
}


/*----------------------------------------------------------------------------
	ChWorldConn protected methods
----------------------------------------------------------------------------*/

void ChWorldConn::ParseText( string& strText, bool boolNewlinesToBreaks )
{
	string			strWorking;
	const char*		pstrOriginText;
	int				iStartOfLine = 0;
	ChBufferString	strParsedBuffer;

	pstrOriginText = strText;

	while (*pstrOriginText)
	{
		bool	boolMoveToNextChar = true;

		switch (m_parseState)
		{
			case parseStateScanning:
			{
				switch( (unsigned char)*pstrOriginText )
				{
					case ESCAPE:
					{
						m_parseState = parseStateEscape;
						break;
					}

					case TN_IAC:			// 0xff
					{
						m_parseState = parseTelnetIAC;
						break;
					}

					case '\n':
					{
						if (*(pstrOriginText + 1) == '\r')
						{
							pstrOriginText++;
						}

						ParseEndOfLine( strParsedBuffer, iStartOfLine, true );

											// Append a newline or <br>

						if (boolNewlinesToBreaks)
						{
							strParsedBuffer += "<br>";
						}
						else
						{
							strParsedBuffer += '\n';
						}

						iStartOfLine = strParsedBuffer.GetLength();
						break;
					}

					case '\r':
					{
						if (*(pstrOriginText + 1) == '\n')
						{
							pstrOriginText++;
						}

						ParseEndOfLine( strParsedBuffer, iStartOfLine, true );

											// Append a newline or <br>

						if (boolNewlinesToBreaks)
						{
							strParsedBuffer += "<br>";
						}
						else
						{
							strParsedBuffer += '\n';
						}

						iStartOfLine = strParsedBuffer.GetLength();
						break;
					}

					default:
					{
						if (isprint( *pstrOriginText ) || ('\t' == *pstrOriginText))
						{
							strParsedBuffer += *pstrOriginText;
						}
						break;
					}
				}
				break;
			}

			case parseStateEscape:
			{
				switch( *pstrOriginText )
				{
					case '[':
					{
						m_parseState = parseStateAnsi;
						break;
					}

					default:
					{
						strParsedBuffer += ESCAPE;
						strParsedBuffer += *pstrOriginText;

											/* Set the state back to being
												between sequences */

						m_parseState = parseStateScanning;
						break;
					}
				}
				break;
			}

			case parseStateAnsi:
			{
				bool		boolEndOfPacket;

				ASSERT( *pstrOriginText );
											/* Search for the end of the ANSI
												sequence (which may contain
												digits or semi-colons) */

				while ((ANSI_SEPARATOR == *pstrOriginText) ||
						isdigit( *pstrOriginText ))
				{
					m_strAnsiSequence += *pstrOriginText;
					pstrOriginText++;
				}
											/* Figure out if we've hit the end
												of the packet before
												encountering the end of the
												ANSI sequence */

				boolEndOfPacket = (0 == *pstrOriginText);
				if (!boolEndOfPacket)
				{							/* Move to processing the ANSI
												terminating character */

					m_parseState = parseStateAnsiTerm;
				}

				boolMoveToNextChar = false;
				break;
			}

			case parseStateAnsiTerm:
			{
				char	cTerm = *pstrOriginText;
				bool	boolValidSequence = true;

				if (cTerm == '\n' || cTerm == '\r' || cTerm == ESCAPE)
				{
											/* Don't strip off newline or
												ESCAPE terms */
					boolMoveToNextChar = false;
					boolValidSequence = false;
				}
				else if (m_strAnsiSequence.IsEmpty())
				{
					#if defined( DUMP_ANSI_CODES )
					{
						string		strSequence;

						strSequence.Format( "ANSI(unknown: [%c)",
											(char)*pstrOriginText );
						AnsiDisplay( strSequence );
					}
					#endif	// defined( DUMP_ANSI_CODES )

					boolValidSequence = false;
				}

				if (boolValidSequence)
				{
					ProcessAnsiCodes( cTerm, m_strAnsiSequence,
										strParsedBuffer );
				}
											// State goes back to 'scanning'
				m_strAnsiSequence = "";
				m_parseState = parseStateScanning;
				break;
			}

			case parseTelnetIAC:
			{
				m_iTelnetCmd = (unsigned char)*pstrOriginText;

				if ((TN_WILL == m_iTelnetCmd) || (TN_WONT == m_iTelnetCmd) ||
					(TN_DO == m_iTelnetCmd) || (TN_DONT == m_iTelnetCmd))
				{
					m_parseState = parseTelnetCmd;
				}
				else if ((TN_GA == m_iTelnetCmd) || (TN_EOR == m_iTelnetCmd))
				{
											// This is definitely a prompt

					#if defined( DUMP_TELNET_CODES )
					{
						string		strSequence;
						string		strOut;

						strSequence.Format( "rcvd IAC %s\n",
											pstrTelnetLabel[m_iTelnetCmd] );
						TelnetDisplay( strSequence );
					}
					#endif	// defined( DUMP_TELNET_CODES )

											// State goes back to 'scanning'

					m_parseState = parseStateScanning;
				}
				else
				{
					strParsedBuffer += (char)TN_IAC;
					strParsedBuffer += *pstrOriginText;

					m_parseState = parseStateScanning;
				}
				break;
			}

			case parseTelnetCmd:
			{
				DoTelnetCmd( m_iTelnetCmd, (unsigned char)*pstrOriginText );
				m_parseState = parseStateScanning;
				break;
			}

			default:
			{
				TRACE( "Error in parse state!\n" );
				ASSERT( false );
				break;
			}
		}

		if (boolMoveToNextChar && *pstrOriginText)
		{
			pstrOriginText++;
		}
	}

	ParseEndOfLine( strParsedBuffer, iStartOfLine, false );

											// Return the parsed buffer
	strText = strParsedBuffer;
}


void ChWorldConn::ParseEndOfLine( ChBufferString& strBuffer, int iStartOfLine,
									bool boolEndOfLine )
{
	register int		iBufferLen = strBuffer.GetLength();

	ASSERT( iBufferLen >= iStartOfLine );

	if (iStartOfLine != iBufferLen)
	{
		const char*		pstrBuffer = strBuffer;
		int				iLen = iBufferLen - iStartOfLine;
		
		pstrBuffer += iStartOfLine;
		AddToTextBlock( pstrBuffer, iLen, boolEndOfLine );
	}
}


void ChWorldConn::ProcessAnsiCodes( char cCodeType, const char* pstrCodes,
									ChBufferString& strBuffer )
{
	string		strAnsiHTML;

	cCodeType = (char)tolower( cCodeType );
	if ((cCodeType != ANSI_MODE) && (cCodeType != ANSI_ERASE))
	{
											/* Right now we only support two
												types of ANSI sequence */
		return;
	}

	while (*pstrCodes != 0)
	{
		while (*pstrCodes == ANSI_SEPARATOR)
		{									// Strip out separators
			pstrCodes++;
		}

		if (isdigit( *pstrCodes ))
		{									// There's a code here
			int		iCode = 0;
			string	strAnsiOutput;

			while (isdigit( *pstrCodes ))
			{
				iCode = (iCode * 10) + (int)(*pstrCodes - '0');
				pstrCodes++;
			}

			ProcessAnsiCode( cCodeType, iCode, strAnsiHTML );
		}
	}

	if (strAnsiHTML.GetLength() > 0)
	{
		string		strTemp;
											// Add HTML
		TurnHtmlOn( strTemp );
		strTemp += strAnsiHTML;
		TurnHtmlOff( strTemp );

		strBuffer += strTemp;
	}
}


void ChWorldConn::ProcessAnsiCode( char cCodeType, int iCode,
									string& strOutput )
{
	string		strCodeHTML;

	switch( cCodeType )
	{
		case ANSI_MODE:
		{
			switch( iCode )
			{
				case 0:						// Reset all
				{
					AnsiDisplay( "ANSI(reset)" );

⌨️ 快捷键说明

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