mudwindow.cpp
来自「MudMaster 2000 的C++源码」· C++ 代码 · 共 838 行 · 第 1/2 页
CPP
838 行
/************************************************************************************
Copyright (c) 2000 Aaron O'Neil
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2) Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3) Redistributions in binary form must reproduce the above copyright notice on
program startup. Additional credits for program modification are acceptable
but original copyright and credits must be visible at startup.
4) You may charge a reasonable copying fee for any distribution of Mud Master.
You may charge any fee you choose for support of Mud Master. You may not
charge a fee for Mud Master itself.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**************************************************************************************/
#include "StdAfx.h"
#include "Extern.h"
#include "MudWindow.h"
#include "ScrollBack.h"
#include "Actions.h"
#include "LogFile.h"
#include "Gags.h"
#include "Highlights.h"
#include "Sound.h"
#include "Msp.h"
#include "Chat.h"
#include "Substitute.h"
int _nForeColor;
int _nBackColor;
CMudWindow::CMudWindow() : CScreen()
{
m_pAnsiBuf = new char[MAX_ANSI_LEN+1];
m_bPossibleAnsi = 0;
m_nAnsiIndex = 0;
m_bBold = FALSE;
m_bLastWasBold = FALSE;
m_bDoActions = TRUE;
m_nWindowLines = 24;
m_bTelnetCommand = FALSE;
m_bTelnetOption = FALSE;
m_bMSP = FALSE;
m_nMSPIndex = 0;
m_bEatEnter = FALSE;
_nForeColor = F_LIGHTGREY;
_nBackColor = B_BLACK;
m_nCurrentColor = _nForeColor | _nBackColor;
}
CMudWindow::~CMudWindow()
{
delete [] m_pAnsiBuf;
}
void CMudWindow::Init()
{
ClearScreen();
CString strCopyRight;
strCopyRight.Format("Mud Master - Version %s - Copyright (c) 2000 Aaron O'Neil\n"
"All rights reserved.\n\n",
(const char *)_config.strVersion);
SetColor(F_LIGHTGREEN);
Gotoxy(0,1);
Print(strCopyRight);
SetColor(F_LIGHTGREY);
Print("TIP: If you are running Mud Master from Windows 95/98 start a dos prompt and\n");
Print("run it from there. Launching Mud Master from the Windows Explorer or the start\n");
Print("menu will cause it to run noticably slower.\n\n");
Print("Ctrl+X Exits the program. \"/help\" for program help.\n\n");
}
void CMudWindow::Mode25()
{
COORD c;
c.X = 80;
c.Y = 25;
SetConsoleScreenBufferSize(m_hScreen,c);
ClearScreen();
m_nWindowLines = 24;
}
void CMudWindow::Mode50()
{
COORD c;
c.X = 80;
c.Y = 50;
SetConsoleScreenBufferSize(m_hScreen,c);
ClearScreen();
m_nWindowLines = 49;
}
void CMudWindow::Print(const char *pszText, int nTextLen)
{
if (!nTextLen)
nTextLen = strlen(pszText);
if (_chat.GetSnoopCount())
_chat.SendSnoop(pszText);
CTextLine tlText;
tlText.m_nLen = 0;
m_nCurrentColor = m_wAttr;
unsigned char ch;
int i = 0;
while(i < nTextLen)
{
// Eat up any NULLs embedded in the text stream.
if (!pszText[i])
{
i++;
continue;
}
ch = pszText[i];
// Check for a telnet command.
if (!m_bPossibleAnsi && ch == IAC)
{
// If this is the second IAC then it really is sending
// the 255 char, not a telnet command.
if (m_bTelnetCommand)
{
// Might as well just eat it up since it isn't a
// printable character anyway.
m_bTelnetCommand = FALSE;
i++;
}
else
{
m_bTelnetCommand = TRUE;
i++;
}
continue;
}
// We are receiving a telnet command.
if (m_bTelnetCommand)
{
// Handle the telnet command. If the command needs an
// option, the TelnetCommand will set the m_bTelnetOption
// var to TRUE.
TelnetCommand(ch);
m_bTelnetCommand = FALSE;
i++;
continue;
}
// We are receiving a telent option.
if (m_bTelnetOption)
{
// Handle the option.
TelnetOption(ch);
m_bTelnetOption = FALSE;
i++;
continue;
}
// Check for ANSI escape char.
if (!m_bTelnetOption && !m_bTelnetCommand && !m_bPossibleAnsi && ch == 27)
{
// Possible have an ANSI sequence coming in.
m_bPossibleAnsi = TRUE;
m_nAnsiIndex = 0;
i++;
continue;
}
if (!m_bTelnetOption && !m_bTelnetCommand && m_bPossibleAnsi)
{
// If we don't have anything in buffer yet
// should be expecting a [.
if (!m_nAnsiIndex)
{
if (ch == '[')
{
// eat it up, it isn't important.
i++;
m_pAnsiBuf[m_nAnsiIndex++] = ' ';
continue;
}
else
m_bPossibleAnsi = FALSE;
}
else
if (isalpha(ch))
{
// First alpha char signals end of an ANSI sequence.
m_pAnsiBuf[m_nAnsiIndex++] = ch;
m_pAnsiBuf[m_nAnsiIndex] = '\x0';
m_bPossibleAnsi = FALSE;
TranslateAnsi();
i++;
continue;
}
else
{
m_pAnsiBuf[m_nAnsiIndex++] = ch;
i++;
continue;
}
}
if (m_bMSP)
{
m_szMSPBuf[m_nMSPIndex] = ch;
// Check the first characters at the beginning of the string to make sure
// it is an MSP string.
if (m_nMSPIndex < MSP_TAG_LEN)
if (m_szMSPBuf[m_nMSPIndex] != _szMSPSound[m_nMSPIndex] && m_szMSPBuf[m_nMSPIndex] != _szMSPMusic[m_nMSPIndex])
{
// If they aren't equal, this isn't an msp string. Need to print
// out the characters we hae built up in the buffer.
int nIndex = 0;
while(nIndex <= m_nMSPIndex)
{
if (m_szMSPBuf[nIndex] == '\r')
{
nIndex++;
continue;
}
// Save the char in the buffer.
tlText.m_ptrText[tlText.m_nLen] = m_szMSPBuf[nIndex];
tlText.m_ptrAttr[tlText.m_nLen] = m_nCurrentColor;
tlText.m_nLen++;
// If the character is a line feed, or we have reached the
// limit our buffer can store, print the line.
if (ch == 0x0a || tlText.m_nLen == MAX_TEXTLINE_LEN)
{
tlText.m_ptrText[tlText.m_nLen] = '\x0';
PrintTextLine(tlText);
tlText.m_nLen = 0;
}
nIndex++;
}
m_bMSP = FALSE;
i++;
continue;
}
m_nMSPIndex++;
// MSP strings are terminated with a line feed.
if (ch == '\n')
{
m_bMSP = FALSE;
m_szMSPBuf[m_nMSPIndex] = '\x0';
DoMSP();
}
i++;
continue;
}
// Any time we see a ! there is a chance we are getting an MSP
// string.
if (ch == '!' && _config.bMspOn)
{
m_szMSPBuf[0] = '!';
m_nMSPIndex = 1;
m_bMSP = TRUE;
i++;
continue;
}
// Chow the carriage returns. Using a line feed as an end
// of line character.
if (ch == '\r')
{
i++;
continue;
}
// Save the char in the buffer.
tlText.m_ptrText[tlText.m_nLen] = ch;
tlText.m_ptrAttr[tlText.m_nLen] = m_nCurrentColor;
tlText.m_nLen++;
// If the character is a line feed, or we have reached the
// limit our buffer can store, print the line.
if (ch == 0x0a || tlText.m_nLen == MAX_TEXTLINE_LEN)
{
// Chows up the empty line after the gag.
if (m_bEatEnter && tlText.m_nLen == 1)
{
m_bEatEnter = FALSE;
tlText.m_nLen = 0;
i++;
continue;
}
tlText.m_ptrText[tlText.m_nLen] = '\x0';
PrintTextLine(tlText);
tlText.m_nLen = 0;
// This needs to be reset on the very next printed line
// if there wasn't an empty line after the gag. If not
// the next empty line down the road (which could be a
// ways off) gets eaten.
m_bEatEnter = FALSE;
}
i++;
}
if (tlText.m_nLen)
{
tlText.m_ptrText[tlText.m_nLen] = '\x0';
PrintTextLine(tlText);
}
}
void CMudWindow::TranslateAnsi()
{
if (m_nAnsiIndex < 1)
return;
// For now I'm only going to worry about color codes.
if (m_pAnsiBuf[m_nAnsiIndex-1] != 'm')
{
/*int nLen = strlen(m_pAnsiBuf);
if (nLen > MAX_TEXTLINE_LEN)
return;
CTextLine tlText;
strcpy(tlText.m_ptrText,m_pAnsiBuf);
for (int i=0;i<nLen;i++)
tlText.m_ptrAttr[i] = m_nCurrentColor;
tlText.m_nLen = nLen;
PrintTextLine(tlText); */
return;
}
// Get rid of the letter.
m_nAnsiIndex--;
m_pAnsiBuf[m_nAnsiIndex] = '\x0';
// Some mud I've seen keeps sending just the letter 'm', not idea what it expects.
// That'll leave the buffer empty though.
if (m_nAnsiIndex < 1)
return;
WORD wAttr;
int nValue;
char *ptrToken = strtok(m_pAnsiBuf,";");
while(ptrToken != NULL)
{
nValue = atoi(ptrToken);
if (nValue == 1)
{
// I'm thinking maybe two bolds in a row means
// display white text. That seems to be the pattern
// medievia is following when they want white.
if (m_bLastWasBold)
{
_nForeColor = F_WHITE;
m_nCurrentColor = _nForeColor | _nBackColor;
}
else
{
_nForeColor |= FOREGROUND_INTENSITY;
m_nCurrentColor = _nForeColor | _nBackColor;
}
m_bBold = TRUE;
m_bLastWasBold = TRUE;
}
else
{
m_bLastWasBold = FALSE;
if (nValue == 0)
{
m_bBold = FALSE;
_nForeColor = F_LIGHTGREY;
_nBackColor = B_BLACK;
m_nCurrentColor = _nForeColor | _nBackColor;
}
else
if (nValue >= 30 && nValue <= 37)
{
switch(nValue)
{
case 30 : // Black
wAttr = F_BLACK;
break;
case 31 : // Red
wAttr = F_RED;
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?