mirror of
https://github.com/rehlds/metamod-r.git
synced 2024-12-29 08:05:41 +03:00
393 lines
8.4 KiB
C++
393 lines
8.4 KiB
C++
/*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* In addition, as a special exception, the author gives permission to
|
|
* link the code of this program with the Half-Life Game Engine ("HL
|
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
* respects for all of the code used other than the HL Engine and MODs
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
* you do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
|
|
bool CTextConsole::Init(IBaseSystem *system)
|
|
{
|
|
// NULL or a valid base system interface
|
|
m_System = system;
|
|
|
|
Q_memset(m_szConsoleText, 0, sizeof(m_szConsoleText));
|
|
m_nConsoleTextLen = 0;
|
|
m_nCursorPosition = 0;
|
|
|
|
Q_memset(m_szSavedConsoleText, 0, sizeof(m_szSavedConsoleText));
|
|
m_nSavedConsoleTextLen = 0;
|
|
|
|
Q_memset(m_aszLineBuffer, 0, sizeof(m_aszLineBuffer));
|
|
m_nTotalLines = 0;
|
|
m_nInputLine = 0;
|
|
m_nBrowseLine = 0;
|
|
|
|
// these are log messages, not related to console
|
|
Sys_Printf("\n");
|
|
Sys_Printf("Console initialized.\n");
|
|
|
|
m_ConsoleVisible = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CTextConsole::InitSystem(IBaseSystem *system)
|
|
{
|
|
m_System = system;
|
|
}
|
|
|
|
void CTextConsole::SetVisible(bool visible)
|
|
{
|
|
m_ConsoleVisible = visible;
|
|
}
|
|
|
|
bool CTextConsole::IsVisible()
|
|
{
|
|
return m_ConsoleVisible;
|
|
}
|
|
|
|
void CTextConsole::ShutDown()
|
|
{
|
|
;
|
|
}
|
|
|
|
void CTextConsole::Print(char *pszMsg)
|
|
{
|
|
if (m_nConsoleTextLen)
|
|
{
|
|
int nLen = m_nConsoleTextLen;
|
|
while (nLen--)
|
|
{
|
|
PrintRaw("\b \b");
|
|
}
|
|
}
|
|
|
|
PrintRaw(pszMsg);
|
|
|
|
if (m_nConsoleTextLen)
|
|
{
|
|
PrintRaw(m_szConsoleText, m_nConsoleTextLen);
|
|
}
|
|
|
|
UpdateStatus();
|
|
}
|
|
|
|
int CTextConsole::ReceiveNewline()
|
|
{
|
|
int nLen = 0;
|
|
|
|
Echo("\n");
|
|
|
|
if (m_nConsoleTextLen)
|
|
{
|
|
nLen = m_nConsoleTextLen;
|
|
|
|
m_szConsoleText[ m_nConsoleTextLen ] = '\0';
|
|
m_nConsoleTextLen = 0;
|
|
m_nCursorPosition = 0;
|
|
|
|
// cache line in buffer, but only if it's not a duplicate of the previous line
|
|
if ((m_nInputLine == 0) || (Q_strcmp(m_aszLineBuffer[ m_nInputLine - 1 ], m_szConsoleText)))
|
|
{
|
|
Q_strncpy(m_aszLineBuffer[ m_nInputLine ], m_szConsoleText, MAX_CONSOLE_TEXTLEN);
|
|
m_nInputLine++;
|
|
|
|
if (m_nInputLine > m_nTotalLines)
|
|
m_nTotalLines = m_nInputLine;
|
|
|
|
if (m_nInputLine >= MAX_BUFFER_LINES)
|
|
m_nInputLine = 0;
|
|
|
|
}
|
|
|
|
m_nBrowseLine = m_nInputLine;
|
|
}
|
|
|
|
return nLen;
|
|
}
|
|
|
|
void CTextConsole::ReceiveBackspace()
|
|
{
|
|
int nCount;
|
|
|
|
if (m_nCursorPosition == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_nConsoleTextLen--;
|
|
m_nCursorPosition--;
|
|
|
|
Echo("\b");
|
|
|
|
for (nCount = m_nCursorPosition; nCount < m_nConsoleTextLen; ++nCount)
|
|
{
|
|
m_szConsoleText[ nCount ] = m_szConsoleText[ nCount + 1 ];
|
|
Echo(m_szConsoleText + nCount, 1);
|
|
}
|
|
|
|
Echo(" ");
|
|
|
|
nCount = m_nConsoleTextLen;
|
|
while (nCount >= m_nCursorPosition)
|
|
{
|
|
Echo("\b");
|
|
nCount--;
|
|
}
|
|
|
|
m_nBrowseLine = m_nInputLine;
|
|
}
|
|
|
|
void CTextConsole::ReceiveTab()
|
|
{
|
|
if (!m_System)
|
|
return;
|
|
|
|
ObjectList matches;
|
|
m_szConsoleText[ m_nConsoleTextLen ] = '\0';
|
|
m_System->GetCommandMatches(m_szConsoleText, &matches);
|
|
|
|
if (matches.IsEmpty())
|
|
return;
|
|
|
|
if (matches.CountElements() == 1)
|
|
{
|
|
char *pszCmdName = (char *)matches.GetFirst();
|
|
char *pszRest = pszCmdName + Q_strlen(m_szConsoleText);
|
|
|
|
if (pszRest)
|
|
{
|
|
Echo(pszRest);
|
|
Q_strlcat(m_szConsoleText, pszRest);
|
|
m_nConsoleTextLen += Q_strlen(pszRest);
|
|
|
|
Echo(" ");
|
|
Q_strlcat(m_szConsoleText, " ");
|
|
m_nConsoleTextLen++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nLongestCmd = 0;
|
|
int nSmallestCmd = 0;
|
|
int nCurrentColumn;
|
|
int nTotalColumns;
|
|
char szCommonCmd[256]; // Should be enough.
|
|
char szFormatCmd[256];
|
|
char *pszSmallestCmd;
|
|
char *pszCurrentCmd = (char *)matches.GetFirst();
|
|
nSmallestCmd = Q_strlen(pszCurrentCmd);
|
|
pszSmallestCmd = pszCurrentCmd;
|
|
while (pszCurrentCmd)
|
|
{
|
|
if ((int)Q_strlen(pszCurrentCmd) > nLongestCmd)
|
|
{
|
|
nLongestCmd = Q_strlen(pszCurrentCmd);
|
|
}
|
|
if ((int)Q_strlen(pszCurrentCmd) < nSmallestCmd)
|
|
{
|
|
nSmallestCmd = Q_strlen(pszCurrentCmd);
|
|
pszSmallestCmd = pszCurrentCmd;
|
|
}
|
|
pszCurrentCmd = (char *)matches.GetNext();
|
|
}
|
|
|
|
nTotalColumns = (GetWidth() - 1) / (nLongestCmd + 1);
|
|
nCurrentColumn = 0;
|
|
|
|
Echo("\n");
|
|
Q_strcpy(szCommonCmd, pszSmallestCmd);
|
|
|
|
// Would be nice if these were sorted, but not that big a deal
|
|
pszCurrentCmd = (char *)matches.GetFirst();
|
|
while (pszCurrentCmd)
|
|
{
|
|
if (++nCurrentColumn > nTotalColumns)
|
|
{
|
|
Echo("\n");
|
|
nCurrentColumn = 1;
|
|
}
|
|
|
|
Q_snprintf(szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd);
|
|
Echo(szFormatCmd);
|
|
for (char *pCur = pszCurrentCmd, *pCommon = szCommonCmd; (*pCur && *pCommon); pCur++, pCommon++)
|
|
{
|
|
if (*pCur != *pCommon)
|
|
{
|
|
*pCommon = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pszCurrentCmd = (char *)matches.GetNext();
|
|
}
|
|
|
|
Echo("\n");
|
|
if (Q_strcmp(szCommonCmd, m_szConsoleText))
|
|
{
|
|
Q_strcpy(m_szConsoleText, szCommonCmd);
|
|
m_nConsoleTextLen = Q_strlen(szCommonCmd);
|
|
}
|
|
|
|
Echo(m_szConsoleText);
|
|
}
|
|
|
|
m_nCursorPosition = m_nConsoleTextLen;
|
|
m_nBrowseLine = m_nInputLine;
|
|
}
|
|
|
|
void CTextConsole::ReceiveStandardChar(const char ch)
|
|
{
|
|
int nCount;
|
|
|
|
// If the line buffer is maxed out, ignore this char
|
|
if (m_nConsoleTextLen >= (sizeof(m_szConsoleText) - 2))
|
|
{
|
|
return;
|
|
}
|
|
|
|
nCount = m_nConsoleTextLen;
|
|
while (nCount > m_nCursorPosition)
|
|
{
|
|
m_szConsoleText[ nCount ] = m_szConsoleText[ nCount - 1 ];
|
|
nCount--;
|
|
}
|
|
|
|
m_szConsoleText[ m_nCursorPosition ] = ch;
|
|
|
|
Echo(m_szConsoleText + m_nCursorPosition, m_nConsoleTextLen - m_nCursorPosition + 1);
|
|
|
|
m_nConsoleTextLen++;
|
|
m_nCursorPosition++;
|
|
|
|
nCount = m_nConsoleTextLen;
|
|
while (nCount > m_nCursorPosition)
|
|
{
|
|
Echo("\b");
|
|
nCount--;
|
|
}
|
|
|
|
m_nBrowseLine = m_nInputLine;
|
|
}
|
|
|
|
void CTextConsole::ReceiveUpArrow()
|
|
{
|
|
int nLastCommandInHistory = m_nInputLine + 1;
|
|
if (nLastCommandInHistory > m_nTotalLines)
|
|
nLastCommandInHistory = 0;
|
|
|
|
if (m_nBrowseLine == nLastCommandInHistory)
|
|
return;
|
|
|
|
if (m_nBrowseLine == m_nInputLine)
|
|
{
|
|
if (m_nConsoleTextLen > 0)
|
|
{
|
|
// Save off current text
|
|
Q_strncpy(m_szSavedConsoleText, m_szConsoleText, m_nConsoleTextLen);
|
|
// No terminator, it's a raw buffer we always know the length of
|
|
}
|
|
|
|
m_nSavedConsoleTextLen = m_nConsoleTextLen;
|
|
}
|
|
|
|
m_nBrowseLine--;
|
|
if (m_nBrowseLine < 0)
|
|
{
|
|
m_nBrowseLine = m_nTotalLines - 1;
|
|
}
|
|
|
|
// delete old line
|
|
while (m_nConsoleTextLen--)
|
|
{
|
|
Echo("\b \b");
|
|
}
|
|
|
|
// copy buffered line
|
|
Echo(m_aszLineBuffer[ m_nBrowseLine ]);
|
|
|
|
Q_strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN);
|
|
|
|
m_nConsoleTextLen = Q_strlen(m_aszLineBuffer[ m_nBrowseLine ]);
|
|
m_nCursorPosition = m_nConsoleTextLen;
|
|
}
|
|
|
|
void CTextConsole::ReceiveDownArrow()
|
|
{
|
|
if (m_nBrowseLine == m_nInputLine)
|
|
return;
|
|
|
|
if (++m_nBrowseLine > m_nTotalLines)
|
|
m_nBrowseLine = 0;
|
|
|
|
// delete old line
|
|
while (m_nConsoleTextLen--)
|
|
{
|
|
Echo("\b \b");
|
|
}
|
|
|
|
if (m_nBrowseLine == m_nInputLine)
|
|
{
|
|
if (m_nSavedConsoleTextLen > 0)
|
|
{
|
|
// Restore current text
|
|
Q_strncpy(m_szConsoleText, m_szSavedConsoleText, m_nSavedConsoleTextLen);
|
|
// No terminator, it's a raw buffer we always know the length of
|
|
|
|
Echo(m_szConsoleText, m_nSavedConsoleTextLen);
|
|
}
|
|
|
|
m_nConsoleTextLen = m_nSavedConsoleTextLen;
|
|
}
|
|
else
|
|
{
|
|
// copy buffered line
|
|
Echo(m_aszLineBuffer[ m_nBrowseLine ]);
|
|
Q_strncpy(m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN);
|
|
m_nConsoleTextLen = Q_strlen(m_aszLineBuffer[ m_nBrowseLine ]);
|
|
}
|
|
|
|
m_nCursorPosition = m_nConsoleTextLen;
|
|
}
|
|
|
|
void CTextConsole::ReceiveLeftArrow()
|
|
{
|
|
if (m_nCursorPosition == 0)
|
|
return;
|
|
|
|
Echo("\b");
|
|
m_nCursorPosition--;
|
|
}
|
|
|
|
void CTextConsole::ReceiveRightArrow()
|
|
{
|
|
if (m_nCursorPosition == m_nConsoleTextLen)
|
|
return;
|
|
|
|
Echo(m_szConsoleText + m_nCursorPosition, 1);
|
|
m_nCursorPosition++;
|
|
}
|