This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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++;
}

View 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