initial
This commit is contained in:
360
dedicated/console/TextConsoleUnix.cpp
Normal file
360
dedicated/console/TextConsoleUnix.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// CTextConsoleUnix.cpp: Unix implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "TextConsoleUnix.h"
|
||||
|
||||
// un-needed include...
|
||||
//#include "resource.h"
|
||||
#include "tier0/icommandline.h"
|
||||
//#include "../ifilesystem.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
|
||||
#define CONSOLE_LOG_FILE "console.log"
|
||||
|
||||
bool CTextConsoleUnix::Init( )
|
||||
{
|
||||
static struct termios termNew;
|
||||
sigset_t block_ttou;
|
||||
|
||||
sigemptyset (&block_ttou);
|
||||
sigaddset (&block_ttou, SIGTTOU);
|
||||
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
|
||||
|
||||
tty = stdout;
|
||||
|
||||
// this code is for echo-ing key presses to the connected tty
|
||||
// (which is != STDOUT)
|
||||
if ( isatty(STDIN_FILENO) )
|
||||
{
|
||||
tty = fopen( ctermid( NULL ), "w+" );
|
||||
if ( !tty )
|
||||
{
|
||||
printf("Unable to open tty(%s) for output\n", ctermid( NULL ) );
|
||||
tty = stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
setbuf( tty, NULL ); // turn buffering off
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tty = fopen( "/dev/null", "w+" );
|
||||
if ( !tty )
|
||||
{
|
||||
tty = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
tcgetattr( STDIN_FILENO, &termStored );
|
||||
|
||||
memcpy( &termNew, &termStored, sizeof( struct termios ) );
|
||||
|
||||
/* Disable canonical mode, and set buffer size to 1 byte */
|
||||
termNew.c_lflag &= ( ~ICANON );
|
||||
termNew.c_cc[ VMIN ] = 1;
|
||||
termNew.c_cc[ VTIME ] = 0;
|
||||
|
||||
/* disable echo */
|
||||
termNew.c_lflag &= ( ~ECHO );
|
||||
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &termNew );
|
||||
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
|
||||
|
||||
m_bConDebug = CommandLine()->FindParm( "-condebug" ) != 0;
|
||||
if ( m_bConDebug && CommandLine()->FindParm( "-conclearlog" ) )
|
||||
{
|
||||
g_pFullFileSystem->RemoveFile( CONSOLE_LOG_FILE, "GAME" );
|
||||
}
|
||||
|
||||
return CTextConsole::Init();
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleUnix::ShutDown( void )
|
||||
{
|
||||
sigset_t block_ttou;
|
||||
|
||||
sigemptyset (&block_ttou);
|
||||
sigaddset (&block_ttou, SIGTTOU);
|
||||
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &termStored );
|
||||
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
|
||||
|
||||
CTextConsole::ShutDown();
|
||||
}
|
||||
|
||||
|
||||
// return 0 if the kb isn't hit
|
||||
int CTextConsoleUnix::kbhit( void )
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
FD_ZERO( &rfds );
|
||||
FD_SET( STDIN_FILENO, &rfds );
|
||||
|
||||
/* Return immediately. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
/* Must be in raw or cbreak mode for this to work correctly. */
|
||||
return select( STDIN_FILENO + 1, &rfds, NULL, NULL, &tv )!=-1 && FD_ISSET( STDIN_FILENO, &rfds );
|
||||
}
|
||||
|
||||
|
||||
char * CTextConsoleUnix::GetLine( void )
|
||||
{
|
||||
if ( !kbhit() ) // early return for 99.999% case :)
|
||||
return NULL;
|
||||
|
||||
escape_sequence_t es;
|
||||
|
||||
es = ESCAPE_CLEAR;
|
||||
sigset_t block_ttou;
|
||||
|
||||
sigemptyset (&block_ttou);
|
||||
sigaddset (&block_ttou, SIGTTOU);
|
||||
sigaddset (&block_ttou, SIGTTIN);
|
||||
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
|
||||
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
char ch;
|
||||
int nLen;
|
||||
|
||||
if ( !kbhit() )
|
||||
break;
|
||||
ch = 0;
|
||||
int numRead = read( STDIN_FILENO, &ch, 1 );
|
||||
if ( !numRead )
|
||||
break;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\n': // Enter
|
||||
es = ESCAPE_CLEAR;
|
||||
|
||||
nLen = ReceiveNewline();
|
||||
if ( nLen )
|
||||
{
|
||||
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
|
||||
return m_szConsoleText;
|
||||
}
|
||||
break;
|
||||
|
||||
case 127: // Backspace
|
||||
case '\b': // Backspace
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveBackspace();
|
||||
break;
|
||||
|
||||
case '\t': // TAB
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveTab();
|
||||
break;
|
||||
|
||||
case 27: // Escape character
|
||||
es = ESCAPE_RECEIVED;
|
||||
break;
|
||||
|
||||
case '[': // 2nd part of escape sequence
|
||||
case 'O':
|
||||
case 'o':
|
||||
switch( es )
|
||||
{
|
||||
case ESCAPE_CLEAR:
|
||||
case ESCAPE_BRACKET_RECEIVED:
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
break;
|
||||
|
||||
case ESCAPE_RECEIVED:
|
||||
es = ESCAPE_BRACKET_RECEIVED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
if ( es == ESCAPE_BRACKET_RECEIVED )
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveUpArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if ( es == ESCAPE_BRACKET_RECEIVED )
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveDownArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
if ( es == ESCAPE_BRACKET_RECEIVED )
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveRightArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if ( es == ESCAPE_BRACKET_RECEIVED )
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveLeftArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( es != ESCAPE_BRACKET_RECEIVED ) // Just eat this char if it's an unsupported escape
|
||||
{
|
||||
if ( ( ch >= ' ') && ( ch <= '~' ) ) // dont' accept nonprintable chars
|
||||
{
|
||||
es = ESCAPE_CLEAR;
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
fflush( stdout );
|
||||
}
|
||||
|
||||
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleUnix::PrintRaw( char * pszMsg, int nChars )
|
||||
{
|
||||
if ( m_bConDebug )
|
||||
{
|
||||
FileHandle_t fh = g_pFullFileSystem->Open( CONSOLE_LOG_FILE, "a" );
|
||||
if ( fh != FILESYSTEM_INVALID_HANDLE )
|
||||
{
|
||||
if ( nChars == 0 )
|
||||
{
|
||||
g_pFullFileSystem->Write( pszMsg, strlen( pszMsg ), fh );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFullFileSystem->Write( pszMsg, nChars, fh );
|
||||
}
|
||||
g_pFullFileSystem->Close( fh );
|
||||
}
|
||||
}
|
||||
|
||||
if ( nChars == 0 )
|
||||
{
|
||||
printf( "%s", pszMsg );
|
||||
}
|
||||
else
|
||||
{
|
||||
int nCount;
|
||||
|
||||
for ( nCount = 0; nCount < nChars; nCount++ )
|
||||
{
|
||||
printf( "%c", pszMsg[ nCount ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleUnix::Echo( char * pszMsg, int nChars )
|
||||
{
|
||||
if ( nChars == 0 )
|
||||
{
|
||||
fprintf( tty, "%s", pszMsg );
|
||||
}
|
||||
else
|
||||
{
|
||||
int nCount;
|
||||
|
||||
for ( nCount = 0; nCount < nChars; nCount++ )
|
||||
{
|
||||
fprintf( tty, "%c", pszMsg[ nCount ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CTextConsoleUnix::GetWidth( void )
|
||||
{
|
||||
struct winsize ws;
|
||||
int nWidth;
|
||||
|
||||
nWidth = 0;
|
||||
|
||||
if ( ioctl( STDOUT_FILENO, TIOCGWINSZ, &ws ) == 0 )
|
||||
{
|
||||
nWidth = (int)ws.ws_col;
|
||||
}
|
||||
|
||||
/* if ( nWidth <= 0 )
|
||||
{
|
||||
char * ss;
|
||||
|
||||
ss = getenv( "COLUMNS" );
|
||||
|
||||
if ( ss )
|
||||
{
|
||||
nWidth = atoi( ss );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ( nWidth <= 1 )
|
||||
{
|
||||
nWidth = 80;
|
||||
}
|
||||
|
||||
return nWidth;
|
||||
}
|
||||
|
||||
|
||||
#endif // ndef _WIN32
|
||||
59
dedicated/console/TextConsoleUnix.h
Normal file
59
dedicated/console/TextConsoleUnix.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsoleUnix.h: Unix interface for the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined TEXTCONSOLE_UNIX_H
|
||||
#define TEXTCONSOLE_UNIX_H
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include "textconsole.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ESCAPE_CLEAR = 0,
|
||||
ESCAPE_RECEIVED,
|
||||
ESCAPE_BRACKET_RECEIVED
|
||||
} escape_sequence_t;
|
||||
|
||||
|
||||
class CTextConsoleUnix : public CTextConsole
|
||||
{
|
||||
public:
|
||||
virtual ~CTextConsoleUnix()
|
||||
{
|
||||
};
|
||||
|
||||
bool Init();
|
||||
void ShutDown( void );
|
||||
void PrintRaw( char * pszMsg, int nChars = 0 );
|
||||
void Echo( char * pszMsg, int nChars = 0 );
|
||||
char * GetLine( void );
|
||||
int GetWidth( void );
|
||||
|
||||
private:
|
||||
int kbhit( void );
|
||||
|
||||
bool m_bConDebug;
|
||||
|
||||
struct termios termStored;
|
||||
FILE *tty;
|
||||
};
|
||||
|
||||
|
||||
#endif // _ndef WIN32
|
||||
|
||||
|
||||
#endif // !defined
|
||||
277
dedicated/console/TextConsoleWin32.cpp
Normal file
277
dedicated/console/TextConsoleWin32.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// CTextConsoleWin32.cpp: Win32 implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma warning(disable:4100) //unreferenced formal parameter
|
||||
#include "TextConsoleWin32.h"
|
||||
#pragma warning(default:4100) //unreferenced formal parameter
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
BOOL WINAPI ConsoleHandlerRoutine( DWORD CtrlType )
|
||||
{
|
||||
NOTE_UNUSED( CtrlType );
|
||||
/* TODO ?
|
||||
if ( CtrlType != CTRL_C_EVENT && CtrlType != CTRL_BREAK_EVENT )
|
||||
m_System->Stop(); // don't quit on break or ctrl+c
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// GetConsoleHwnd() helper function from MSDN Knowledge Base Article Q124103
|
||||
// needed, because HWND GetConsoleWindow(VOID) is not avaliable under Win95/98/ME
|
||||
|
||||
HWND GetConsoleHwnd(void)
|
||||
{
|
||||
HWND hwndFound; // This is what is returned to the caller.
|
||||
char pszNewWindowTitle[1024]; // Contains fabricated WindowTitle
|
||||
char pszOldWindowTitle[1024]; // Contains original WindowTitle
|
||||
|
||||
// Fetch current window title.
|
||||
GetConsoleTitle( pszOldWindowTitle, 1024 );
|
||||
|
||||
// Format a "unique" NewWindowTitle.
|
||||
wsprintf( pszNewWindowTitle,"%d/%d", GetTickCount(), GetCurrentProcessId() );
|
||||
|
||||
// Change current window title.
|
||||
SetConsoleTitle(pszNewWindowTitle);
|
||||
|
||||
// Ensure window title has been updated.
|
||||
Sleep(40);
|
||||
|
||||
// Look for NewWindowTitle.
|
||||
hwndFound = FindWindow( NULL, pszNewWindowTitle );
|
||||
|
||||
// Restore original window title.
|
||||
|
||||
SetConsoleTitle( pszOldWindowTitle );
|
||||
|
||||
return hwndFound;
|
||||
}
|
||||
|
||||
CTextConsoleWin32::CTextConsoleWin32()
|
||||
{
|
||||
hinput = houtput = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
bool CTextConsoleWin32::Init( /*IBaseSystem * system*/ )
|
||||
{
|
||||
if ( !AllocConsole () )
|
||||
|
||||
//m_System = system;
|
||||
|
||||
//if ( m_System )
|
||||
// SetTitle( m_System->GetName() );
|
||||
//else
|
||||
SetTitle( "SOURCE DEDICATED SERVER" );
|
||||
|
||||
hinput = GetStdHandle ( STD_INPUT_HANDLE );
|
||||
houtput = GetStdHandle ( STD_OUTPUT_HANDLE );
|
||||
|
||||
if ( !SetConsoleCtrlHandler( &ConsoleHandlerRoutine, TRUE) )
|
||||
{
|
||||
Print( "WARNING! TextConsole::Init: Could not attach console hook.\n" );
|
||||
}
|
||||
|
||||
Attrib = FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY ;
|
||||
|
||||
SetWindowPos( GetConsoleHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_SHOWWINDOW );
|
||||
|
||||
return CTextConsole::Init( /*system */ );
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ShutDown( void )
|
||||
{
|
||||
FreeConsole();
|
||||
|
||||
CTextConsole::ShutDown();
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::SetVisible( bool visible )
|
||||
{
|
||||
ShowWindow ( GetConsoleHwnd(), visible ? SW_SHOW : SW_HIDE );
|
||||
m_ConsoleVisible = visible;
|
||||
}
|
||||
|
||||
char * CTextConsoleWin32::GetLine( void )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
INPUT_RECORD recs[ 1024 ];
|
||||
unsigned long numread;
|
||||
unsigned long numevents;
|
||||
|
||||
if ( !GetNumberOfConsoleInputEvents( hinput, &numevents ) )
|
||||
{
|
||||
Error("CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( numevents <= 0 )
|
||||
break;
|
||||
|
||||
if ( !ReadConsoleInput( hinput, recs, ARRAYSIZE( recs ), &numread ) )
|
||||
{
|
||||
Error("CTextConsoleWin32::GetLine: !ReadConsoleInput");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( numread == 0 )
|
||||
return NULL;
|
||||
|
||||
for ( int i=0; i < (int)numread; i++ )
|
||||
{
|
||||
INPUT_RECORD *pRec = &recs[i];
|
||||
if ( pRec->EventType != KEY_EVENT )
|
||||
continue;
|
||||
|
||||
if ( pRec->Event.KeyEvent.bKeyDown )
|
||||
{
|
||||
// check for cursor keys
|
||||
if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_UP )
|
||||
{
|
||||
ReceiveUpArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_DOWN )
|
||||
{
|
||||
ReceiveDownArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_LEFT )
|
||||
{
|
||||
ReceiveLeftArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT )
|
||||
{
|
||||
ReceiveRightArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
char ch;
|
||||
int nLen;
|
||||
|
||||
ch = pRec->Event.KeyEvent.uChar.AsciiChar;
|
||||
switch ( ch )
|
||||
{
|
||||
case '\r': // Enter
|
||||
nLen = ReceiveNewline();
|
||||
if ( nLen )
|
||||
{
|
||||
return m_szConsoleText;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\b': // Backspace
|
||||
ReceiveBackspace();
|
||||
break;
|
||||
|
||||
case '\t': // TAB
|
||||
ReceiveTab();
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( ( ch >= ' ') && ( ch <= '~' ) ) // dont' accept nonprintable chars
|
||||
{
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::PrintRaw( char * pszMsg, int nChars )
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
if ( houtput == INVALID_HANDLE_VALUE )
|
||||
return;
|
||||
|
||||
if ( nChars == 0 )
|
||||
{
|
||||
WriteFile( houtput, pszMsg, strlen( pszMsg ), &dummy, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteFile( houtput, pszMsg, nChars, &dummy, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::Echo( char * pszMsg, int nChars )
|
||||
{
|
||||
PrintRaw( pszMsg, nChars );
|
||||
}
|
||||
int CTextConsoleWin32::GetWidth( void )
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
int nWidth;
|
||||
|
||||
nWidth = 0;
|
||||
|
||||
if ( GetConsoleScreenBufferInfo( houtput, &csbi ) )
|
||||
{
|
||||
nWidth = csbi.dwSize.X;
|
||||
}
|
||||
|
||||
if ( nWidth <= 1 )
|
||||
nWidth = 80;
|
||||
|
||||
return nWidth;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::SetStatusLine( char * pszStatus )
|
||||
{
|
||||
strncpy( statusline, pszStatus, 80 );
|
||||
statusline[ 79 ] = '\0';
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::UpdateStatus( void )
|
||||
{
|
||||
COORD coord;
|
||||
DWORD dwWritten = 0;
|
||||
WORD wAttrib[ 80 ];
|
||||
|
||||
for ( int i = 0; i < 80; i++ )
|
||||
{
|
||||
wAttrib[i] = Attrib; //FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY ;
|
||||
}
|
||||
|
||||
coord.X = coord.Y = 0;
|
||||
|
||||
WriteConsoleOutputAttribute( houtput, wAttrib, 80, coord, &dwWritten );
|
||||
WriteConsoleOutputCharacter( houtput, statusline, 80, coord, &dwWritten );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::SetTitle( char * pszTitle )
|
||||
{
|
||||
SetConsoleTitle( pszTitle );
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::SetColor(WORD attrib)
|
||||
{
|
||||
Attrib = attrib;
|
||||
}
|
||||
|
||||
#endif
|
||||
55
dedicated/console/TextConsoleWin32.h
Normal file
55
dedicated/console/TextConsoleWin32.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsoleWin32.h: Win32 interface for the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined TEXTCONSOLE_WIN32_H
|
||||
#define TEXTCONSOLE_WIN32_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include "TextConsole.h"
|
||||
|
||||
class CTextConsoleWin32 : public CTextConsole
|
||||
{
|
||||
public:
|
||||
CTextConsoleWin32();
|
||||
virtual ~CTextConsoleWin32()
|
||||
{
|
||||
};
|
||||
|
||||
bool Init( /*IBaseSystem * system*/ );
|
||||
void ShutDown( void );
|
||||
void PrintRaw( char * pszMsz, int nChars = 0 );
|
||||
void Echo( char * pszMsz, int nChars = 0 );
|
||||
char * GetLine( void );
|
||||
int GetWidth( void );
|
||||
void SetTitle( char * pszTitle );
|
||||
void SetStatusLine( char * pszStatus );
|
||||
void UpdateStatus( void );
|
||||
void SetColor( WORD );
|
||||
void SetVisible( bool visible );
|
||||
|
||||
private:
|
||||
HANDLE hinput; // standard input handle
|
||||
HANDLE houtput; // standard output handle
|
||||
WORD Attrib; // attrib colours for status bar
|
||||
|
||||
char statusline[81]; // first line in console is status line
|
||||
};
|
||||
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#endif // !defined
|
||||
427
dedicated/console/conproc.cpp
Normal file
427
dedicated/console/conproc.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifdef _WIN32
|
||||
// conproc.c -- support for qhost
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include "conproc.h"
|
||||
#include "isys.h"
|
||||
#include "tier0/icommandline.h"
|
||||
|
||||
static HANDLE heventDone;
|
||||
static HANDLE hfileBuffer;
|
||||
static HANDLE heventChildSend;
|
||||
static HANDLE heventParentSend;
|
||||
static HANDLE hStdout;
|
||||
static HANDLE hStdin;
|
||||
|
||||
/*
|
||||
==============
|
||||
SetConsoleCXCY
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
COORD coordMax;
|
||||
|
||||
coordMax = GetLargestConsoleWindowSize(hStdout);
|
||||
|
||||
if (cy > coordMax.Y)
|
||||
cy = coordMax.Y;
|
||||
|
||||
if (cx > coordMax.X)
|
||||
cx = coordMax.X;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// height
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = info.dwSize.X - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = cy - 1;
|
||||
|
||||
if (cy < info.dwSize.Y)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cy > info.dwSize.Y)
|
||||
{
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// width
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = cx - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = info.dwSize.Y - 1;
|
||||
|
||||
if (cx < info.dwSize.X)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cx > info.dwSize.X)
|
||||
{
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GetMappedBuffer
|
||||
|
||||
==============
|
||||
*/
|
||||
LPVOID GetMappedBuffer (HANDLE hfileBuffer)
|
||||
{
|
||||
LPVOID pBuffer;
|
||||
|
||||
pBuffer = MapViewOfFile (hfileBuffer,
|
||||
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReleaseMappedBuffer
|
||||
|
||||
==============
|
||||
*/
|
||||
void ReleaseMappedBuffer (LPVOID pBuffer)
|
||||
{
|
||||
UnmapViewOfFile (pBuffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GetScreenBufferLines
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL GetScreenBufferLines (int *piLines)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
BOOL bRet;
|
||||
|
||||
bRet = GetConsoleScreenBufferInfo (hStdout, &info);
|
||||
|
||||
if (bRet)
|
||||
*piLines = info.dwSize.Y;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SetScreenBufferLines
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL SetScreenBufferLines (int iLines)
|
||||
{
|
||||
return SetConsoleCXCY (hStdout, 80, iLines);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReadText
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
|
||||
{
|
||||
COORD coord;
|
||||
DWORD dwRead;
|
||||
BOOL bRet;
|
||||
|
||||
coord.X = 0;
|
||||
coord.Y = iBeginLine;
|
||||
|
||||
bRet = ReadConsoleOutputCharacter(
|
||||
hStdout,
|
||||
pszText,
|
||||
80 * (iEndLine - iBeginLine + 1),
|
||||
coord,
|
||||
&dwRead);
|
||||
|
||||
// Make sure it's null terminated.
|
||||
if (bRet)
|
||||
pszText[dwRead] = '\0';
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CharToCode
|
||||
|
||||
==============
|
||||
*/
|
||||
int CharToCode (char c)
|
||||
{
|
||||
char upper;
|
||||
|
||||
upper = toupper(c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 13:
|
||||
return 28;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isalpha(c))
|
||||
return (30 + upper - 65);
|
||||
|
||||
if (isdigit(c))
|
||||
return (1 + upper - 47);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteText
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL WriteText (LPCTSTR szText)
|
||||
{
|
||||
DWORD dwWritten;
|
||||
INPUT_RECORD rec;
|
||||
char upper, *sz;
|
||||
|
||||
sz = (LPTSTR) szText;
|
||||
|
||||
while (*sz)
|
||||
{
|
||||
// 13 is the code for a carriage return (\n) instead of 10.
|
||||
if (*sz == 10)
|
||||
*sz = 13;
|
||||
|
||||
upper = toupper(*sz);
|
||||
|
||||
rec.EventType = KEY_EVENT;
|
||||
rec.Event.KeyEvent.bKeyDown = TRUE;
|
||||
rec.Event.KeyEvent.wRepeatCount = 1;
|
||||
rec.Event.KeyEvent.wVirtualKeyCode = upper;
|
||||
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
|
||||
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
|
||||
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
|
||||
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
rec.Event.KeyEvent.bKeyDown = FALSE;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
sz++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
RequestProc
|
||||
|
||||
==============
|
||||
*/
|
||||
unsigned _stdcall RequestProc (void *arg)
|
||||
{
|
||||
int *pBuffer;
|
||||
DWORD dwRet;
|
||||
HANDLE heventWait[2];
|
||||
int iBeginLine, iEndLine;
|
||||
|
||||
heventWait[0] = heventParentSend;
|
||||
heventWait[1] = heventDone;
|
||||
|
||||
while (1)
|
||||
{
|
||||
dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
|
||||
|
||||
// heventDone fired, so we're exiting.
|
||||
if (dwRet == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
|
||||
pBuffer = (int *) GetMappedBuffer (hfileBuffer);
|
||||
|
||||
// hfileBuffer is invalid. Just leave.
|
||||
if (!pBuffer)
|
||||
{
|
||||
sys->Printf ("Request Proc: Invalid -HFILE handle\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pBuffer[0])
|
||||
{
|
||||
case CCOM_WRITE_TEXT:
|
||||
// Param1 : Text
|
||||
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
|
||||
break;
|
||||
|
||||
case CCOM_GET_TEXT:
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
iBeginLine = pBuffer[1];
|
||||
iEndLine = pBuffer[2];
|
||||
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
|
||||
iEndLine);
|
||||
break;
|
||||
|
||||
case CCOM_GET_SCR_LINES:
|
||||
// No params
|
||||
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
|
||||
break;
|
||||
|
||||
case CCOM_SET_SCR_LINES:
|
||||
// Param1 : Number of lines
|
||||
pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
ReleaseMappedBuffer (pBuffer);
|
||||
SetEvent (heventChildSend);
|
||||
}
|
||||
|
||||
_endthreadex (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
DeinitConProc
|
||||
|
||||
==============
|
||||
*/
|
||||
void DeinitConProc (void)
|
||||
{
|
||||
if ( heventDone )
|
||||
{
|
||||
SetEvent ( heventDone );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
InitConProc
|
||||
|
||||
==============
|
||||
*/
|
||||
void InitConProc ( void )
|
||||
{
|
||||
unsigned threadAddr;
|
||||
HANDLE hFile = (HANDLE)0;
|
||||
HANDLE heventParent = (HANDLE)0;
|
||||
HANDLE heventChild = (HANDLE)0;
|
||||
int WantHeight = 50;
|
||||
const char *p;
|
||||
|
||||
// give external front ends a chance to hook into the console
|
||||
if ( CommandLine()->CheckParm ( "-HFILE", &p ) && p )
|
||||
{
|
||||
hFile = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
if ( CommandLine()->CheckParm ( "-HPARENT", &p ) && p )
|
||||
{
|
||||
heventParent = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
if ( CommandLine()->CheckParm ( "-HCHILD", &p ) && p )
|
||||
{
|
||||
heventChild = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
// ignore if we don't have all the events.
|
||||
if ( !hFile || !heventParent || !heventChild )
|
||||
{
|
||||
//sys->Printf ("\n\nNo external front end present.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
sys->Printf( "\n\nInitConProc: Setting up external control.\n" );
|
||||
|
||||
hfileBuffer = hFile;
|
||||
heventParentSend = heventParent;
|
||||
heventChildSend = heventChild;
|
||||
|
||||
// So we'll know when to go away.
|
||||
heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
if (!heventDone)
|
||||
{
|
||||
sys->Printf ("InitConProc: Couldn't create heventDone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
|
||||
{
|
||||
CloseHandle (heventDone);
|
||||
sys->Printf ("InitConProc: Couldn't create third party thread\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// save off the input/output handles.
|
||||
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
hStdin = GetStdHandle (STD_INPUT_HANDLE);
|
||||
|
||||
if ( CommandLine()->CheckParm( "-conheight", &p ) && p )
|
||||
{
|
||||
WantHeight = atoi( p );
|
||||
}
|
||||
|
||||
// Force 80 character width, at least 25 character height
|
||||
SetConsoleCXCY( hStdout, 80, WantHeight );
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
30
dedicated/console/conproc.h
Normal file
30
dedicated/console/conproc.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// conproc.h -- support for external server monitoring programs
|
||||
#ifndef INC_CONPROCH
|
||||
#define INC_CONPROCH
|
||||
|
||||
#define CCOM_WRITE_TEXT 0x2
|
||||
// Param1 : Text
|
||||
|
||||
#define CCOM_GET_TEXT 0x3
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
|
||||
#define CCOM_GET_SCR_LINES 0x4
|
||||
// No params
|
||||
|
||||
#define CCOM_SET_SCR_LINES 0x5
|
||||
// Param1 : Number of lines
|
||||
|
||||
void InitConProc ( void );
|
||||
void DeinitConProc ( void );
|
||||
|
||||
void WriteStatusText( char *psz );
|
||||
|
||||
#endif // !INC_CONPROCH
|
||||
406
dedicated/console/textconsole.cpp
Normal file
406
dedicated/console/textconsole.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsole.cpp: implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#include "port.h"
|
||||
#pragma warning(disable:4100) //unreferenced formal parameter
|
||||
#include "textconsole.h"
|
||||
#pragma warning(default:4100) //unreferenced formal parameter
|
||||
#include "utlvector.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
bool CTextConsole::Init( /*IBaseSystem * system*/ )
|
||||
{
|
||||
//m_System = system; // NULL or a valid base system interface
|
||||
|
||||
memset( m_szConsoleText, 0, sizeof( m_szConsoleText ) );
|
||||
m_nConsoleTextLen = 0;
|
||||
m_nCursorPosition = 0;
|
||||
|
||||
memset( m_szSavedConsoleText, 0, sizeof( m_szSavedConsoleText ) );
|
||||
m_nSavedConsoleTextLen = 0;
|
||||
|
||||
memset( m_aszLineBuffer, 0, sizeof( m_aszLineBuffer ) );
|
||||
m_nTotalLines = 0;
|
||||
m_nInputLine = 0;
|
||||
m_nBrowseLine = 0;
|
||||
|
||||
// these are log messages, not related to console
|
||||
Msg( "\n" );
|
||||
Msg( "Console initialized.\n" );
|
||||
|
||||
m_ConsoleVisible = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTextConsole::SetVisible( bool visible )
|
||||
{
|
||||
m_ConsoleVisible = visible;
|
||||
}
|
||||
|
||||
bool CTextConsole::IsVisible()
|
||||
{
|
||||
return m_ConsoleVisible;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsole::ShutDown( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CTextConsole::Print( char * pszMsg )
|
||||
{
|
||||
if ( m_nConsoleTextLen )
|
||||
{
|
||||
int nLen;
|
||||
|
||||
nLen = m_nConsoleTextLen;
|
||||
|
||||
while ( nLen-- )
|
||||
{
|
||||
PrintRaw( "\b \b" );
|
||||
}
|
||||
}
|
||||
|
||||
PrintRaw( pszMsg );
|
||||
|
||||
if ( m_nConsoleTextLen )
|
||||
{
|
||||
PrintRaw( m_szConsoleText, m_nConsoleTextLen );
|
||||
}
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
|
||||
int CTextConsole::ReceiveNewline( void )
|
||||
{
|
||||
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 ) || ( strcmp( m_aszLineBuffer[ m_nInputLine - 1 ], m_szConsoleText ) ) )
|
||||
{
|
||||
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( void )
|
||||
{
|
||||
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( void )
|
||||
{
|
||||
CUtlVector<char *> matches;
|
||||
|
||||
//if ( !m_System )
|
||||
// return;
|
||||
|
||||
m_szConsoleText[ m_nConsoleTextLen ] = 0;
|
||||
|
||||
//m_System->GetCommandMatches( m_szConsoleText, &matches );
|
||||
|
||||
if ( matches.Count() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( matches.Count() == 1 )
|
||||
{
|
||||
char * pszCmdName;
|
||||
char * pszRest;
|
||||
|
||||
pszCmdName = matches[0];
|
||||
pszRest = pszCmdName + strlen( m_szConsoleText );
|
||||
|
||||
if ( pszRest )
|
||||
{
|
||||
Echo( pszRest );
|
||||
strcat( m_szConsoleText, pszRest );
|
||||
m_nConsoleTextLen += strlen( pszRest );
|
||||
|
||||
Echo( " " );
|
||||
strcat( m_szConsoleText, " " );
|
||||
m_nConsoleTextLen++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int nLongestCmd;
|
||||
int nTotalColumns;
|
||||
int nCurrentColumn;
|
||||
char * pszCurrentCmd;
|
||||
int i = 0;
|
||||
|
||||
nLongestCmd = 0;
|
||||
|
||||
pszCurrentCmd = matches[0];
|
||||
while ( pszCurrentCmd )
|
||||
{
|
||||
if ( (int)strlen( pszCurrentCmd) > nLongestCmd )
|
||||
{
|
||||
nLongestCmd = strlen( pszCurrentCmd);
|
||||
}
|
||||
|
||||
i++;
|
||||
pszCurrentCmd = (char *)matches[i];
|
||||
}
|
||||
|
||||
nTotalColumns = ( GetWidth() - 1 ) / ( nLongestCmd + 1 );
|
||||
nCurrentColumn = 0;
|
||||
|
||||
Echo( "\n" );
|
||||
|
||||
// Would be nice if these were sorted, but not that big a deal
|
||||
pszCurrentCmd = matches[0];
|
||||
i = 0;
|
||||
while ( pszCurrentCmd )
|
||||
{
|
||||
char szFormatCmd[ 256 ];
|
||||
|
||||
nCurrentColumn++;
|
||||
|
||||
if ( nCurrentColumn > nTotalColumns )
|
||||
{
|
||||
Echo( "\n" );
|
||||
nCurrentColumn = 1;
|
||||
}
|
||||
|
||||
Q_snprintf( szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd );
|
||||
Echo( szFormatCmd );
|
||||
|
||||
i++;
|
||||
pszCurrentCmd = matches[i];
|
||||
}
|
||||
|
||||
Echo( "\n" );
|
||||
Echo( m_szConsoleText );
|
||||
// TODO: Tack on 'common' chars in all the matches, i.e. if I typed 'con' and all the
|
||||
// matches begin with 'connect_' then print the matches but also complete the
|
||||
// command up to that point at least.
|
||||
}
|
||||
|
||||
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( void )
|
||||
{
|
||||
int nLastCommandInHistory;
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
while ( m_nConsoleTextLen-- ) // delete old line
|
||||
{
|
||||
Echo( "\b \b" );
|
||||
}
|
||||
|
||||
// copy buffered line
|
||||
Echo( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
|
||||
strncpy( m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN );
|
||||
m_nConsoleTextLen = strlen( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
|
||||
m_nCursorPosition = m_nConsoleTextLen;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsole::ReceiveDownArrow( void )
|
||||
{
|
||||
if ( m_nBrowseLine == m_nInputLine )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nBrowseLine++;
|
||||
if ( m_nBrowseLine > m_nTotalLines )
|
||||
{
|
||||
m_nBrowseLine = 0;
|
||||
}
|
||||
|
||||
while ( m_nConsoleTextLen-- ) // delete old line
|
||||
{
|
||||
Echo( "\b \b" );
|
||||
}
|
||||
|
||||
if ( m_nBrowseLine == m_nInputLine )
|
||||
{
|
||||
if ( m_nSavedConsoleTextLen > 0 )
|
||||
{
|
||||
// Restore current text
|
||||
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 ] );
|
||||
|
||||
strncpy( m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN );
|
||||
|
||||
m_nConsoleTextLen = strlen( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
}
|
||||
|
||||
m_nCursorPosition = m_nConsoleTextLen;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsole::ReceiveLeftArrow( void )
|
||||
{
|
||||
if ( m_nCursorPosition == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Echo( "\b" );
|
||||
m_nCursorPosition--;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsole::ReceiveRightArrow( void )
|
||||
{
|
||||
if ( m_nCursorPosition == m_nConsoleTextLen )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Echo( m_szConsoleText + m_nCursorPosition, 1 );
|
||||
m_nCursorPosition++;
|
||||
}
|
||||
76
dedicated/console/textconsole.h
Normal file
76
dedicated/console/textconsole.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined TEXTCONSOLE_H
|
||||
#define TEXTCONSOLE_H
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#define MAX_CONSOLE_TEXTLEN 256
|
||||
#define MAX_BUFFER_LINES 30
|
||||
|
||||
//class IBaseSystem;
|
||||
|
||||
class CTextConsole
|
||||
{
|
||||
public:
|
||||
virtual ~CTextConsole()
|
||||
{
|
||||
};
|
||||
|
||||
virtual bool Init ( /*IBaseSystem * system*/ );
|
||||
virtual void ShutDown( void );
|
||||
virtual void Print( char * pszMsg );
|
||||
|
||||
virtual void SetTitle( char * pszTitle ) { };
|
||||
virtual void SetStatusLine( char * pszStatus ) { };
|
||||
virtual void UpdateStatus() { };
|
||||
|
||||
// Must be provided by children
|
||||
virtual void PrintRaw( char * pszMsg, int nChars = 0 ) = 0;
|
||||
virtual void Echo( char * pszMsg, int nChars = 0 ) = 0;
|
||||
virtual char * GetLine( void ) = 0;
|
||||
virtual int GetWidth( void ) = 0;
|
||||
|
||||
virtual void SetVisible( bool visible );
|
||||
virtual bool IsVisible();
|
||||
|
||||
|
||||
protected:
|
||||
char m_szConsoleText[ MAX_CONSOLE_TEXTLEN ]; // console text buffer
|
||||
int m_nConsoleTextLen; // console textbuffer length
|
||||
int m_nCursorPosition; // position in the current input line
|
||||
|
||||
// Saved input data when scrolling back through command history
|
||||
char m_szSavedConsoleText[ MAX_CONSOLE_TEXTLEN ]; // console text buffer
|
||||
int m_nSavedConsoleTextLen; // console textbuffer length
|
||||
|
||||
char m_aszLineBuffer[ MAX_BUFFER_LINES ][ MAX_CONSOLE_TEXTLEN ]; // command buffer last MAX_BUFFER_LINES commands
|
||||
int m_nInputLine; // Current line being entered
|
||||
int m_nBrowseLine; // current buffer line for up/down arrow
|
||||
int m_nTotalLines; // # of nonempty lines in the buffer
|
||||
|
||||
bool m_ConsoleVisible;
|
||||
|
||||
// IBaseSystem * m_System;
|
||||
|
||||
int ReceiveNewline( void );
|
||||
void ReceiveBackspace( void );
|
||||
void ReceiveTab( void );
|
||||
void ReceiveStandardChar( const char ch );
|
||||
void ReceiveUpArrow( void );
|
||||
void ReceiveDownArrow( void );
|
||||
void ReceiveLeftArrow( void );
|
||||
void ReceiveRightArrow( void );
|
||||
};
|
||||
|
||||
#endif // !defined
|
||||
Reference in New Issue
Block a user