mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-12-12 21:22:14 +00:00
* rewrite of the win32 dedicated console:
1) NET_Sleep() no longer watches for input, Sys_Sleep() added for waiting on input. 2) Added "CtrlHandler" for trapping Ctrl-C and other quit methods not handled by signals on windows 3) Added history support 4) Added tab completion 5) Removed automatic cursor/scroll adjustment (too problematic) 6) Enable mousewheel scrolling 7) Stop using the InputBuffer for editing This seems to work pretty well now, but I jumped the gun on a previous commit message by saying you can scroll now without locking up your server. That was only true up until the point that a server tried to print to the console, at that point it will hang until you release the scroll bar :( It may be possible to get around this by using a seperate thread for console output, but that's a whole new can of worms.
This commit is contained in:
parent
2052b94adc
commit
e46fe24426
8 changed files with 321 additions and 217 deletions
|
@ -1026,43 +1026,27 @@ void NET_Shutdown( void ) {
|
||||||
====================
|
====================
|
||||||
NET_Sleep
|
NET_Sleep
|
||||||
|
|
||||||
Sleeps msec or until something happens on the network or stdin
|
Sleeps msec or until something happens on the network
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
void NET_Sleep( int msec ) {
|
void NET_Sleep( int msec ) {
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
int highestfd = 0;
|
|
||||||
|
|
||||||
if (!com_dedicated->integer)
|
if (!com_dedicated->integer)
|
||||||
return; // we're not a server, just run full speed
|
return; // we're not a server, just run full speed
|
||||||
|
|
||||||
|
if (!ip_socket)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (msec < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
FD_ZERO(&fdset);
|
FD_ZERO(&fdset);
|
||||||
|
FD_SET(ip_socket, &fdset);
|
||||||
FD_SET(fileno(stdin), &fdset);
|
timeout.tv_sec = msec/1000;
|
||||||
highestfd = fileno(stdin) + 1;
|
timeout.tv_usec = (msec%1000)*1000;
|
||||||
|
select(ip_socket+1, &fdset, NULL, NULL, &timeout);
|
||||||
if(ip_socket)
|
|
||||||
{
|
|
||||||
FD_SET(ip_socket, &fdset); // network socket
|
|
||||||
if(ip_socket >= highestfd)
|
|
||||||
highestfd = ip_socket + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(highestfd)
|
|
||||||
{
|
|
||||||
if(msec >= 0)
|
|
||||||
{
|
|
||||||
timeout.tv_sec = msec/1000;
|
|
||||||
timeout.tv_usec = (msec%1000)*1000;
|
|
||||||
select(highestfd, &fdset, NULL, NULL, &timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Block indefinitely
|
|
||||||
select(highestfd, &fdset, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1030,6 +1030,7 @@ char *Sys_ConsoleInput(void);
|
||||||
|
|
||||||
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs );
|
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs );
|
||||||
void Sys_FreeFileList( char **list );
|
void Sys_FreeFileList( char **list );
|
||||||
|
void Sys_Sleep(int msec);
|
||||||
|
|
||||||
qboolean Sys_LowPhysicalMemory( void );
|
qboolean Sys_LowPhysicalMemory( void );
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,7 @@ void SV_Frame( int msec ) {
|
||||||
// Running as a server, but no map loaded
|
// Running as a server, but no map loaded
|
||||||
#ifdef DEDICATED
|
#ifdef DEDICATED
|
||||||
// Block until something interesting happens
|
// Block until something interesting happens
|
||||||
NET_Sleep(-1);
|
Sys_Sleep(-1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,21 +22,113 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "../qcommon/q_shared.h"
|
#include "../qcommon/q_shared.h"
|
||||||
#include "../qcommon/qcommon.h"
|
#include "../qcommon/qcommon.h"
|
||||||
|
#include "sys_local.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
|
#define QCONSOLE_HISTORY 32
|
||||||
|
|
||||||
#define QCONSOLE_THEME FOREGROUND_RED | \
|
static WORD qconsole_attrib;
|
||||||
BACKGROUND_RED | \
|
|
||||||
BACKGROUND_GREEN | \
|
|
||||||
BACKGROUND_BLUE
|
|
||||||
|
|
||||||
#define QCONSOLE_INPUT_RECORDS 1024
|
// saved console status
|
||||||
|
static DWORD qconsole_orig_mode;
|
||||||
|
static CONSOLE_CURSOR_INFO qconsole_orig_cursorinfo;
|
||||||
|
|
||||||
// used to track key input
|
// cmd history
|
||||||
static int qconsole_chars = 0;
|
static char qconsole_history[ QCONSOLE_HISTORY ][ MAX_EDIT_LINE ];
|
||||||
|
static int qconsole_history_pos = -1;
|
||||||
|
static int qconsole_history_oldest = 0;
|
||||||
|
|
||||||
|
// current edit buffer
|
||||||
|
static char qconsole_line[ MAX_EDIT_LINE ];
|
||||||
|
static int qconsole_linelen = 0;
|
||||||
|
|
||||||
|
static HANDLE qconsole_hout;
|
||||||
|
static HANDLE qconsole_hin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CON_CtrlHandler
|
||||||
|
|
||||||
|
The Windows Console doesn't use signals for terminating the application
|
||||||
|
with Ctrl-C, logging off, window closing, etc. Instead it uses a special
|
||||||
|
handler routine. Fortunately, the values for Ctrl signals don't seem to
|
||||||
|
overlap with true signal codes that Windows provides, so calling
|
||||||
|
Sys_SigHandler() with those numbers should be safe for generating unique
|
||||||
|
shutdown messages.
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static BOOL WINAPI CON_CtrlHandler( DWORD sig )
|
||||||
|
{
|
||||||
|
Sys_SigHandler( sig );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CON_HistAdd
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void CON_HistAdd( void )
|
||||||
|
{
|
||||||
|
Q_strncpyz( qconsole_history[ qconsole_history_oldest ], qconsole_line,
|
||||||
|
sizeof( qconsole_history[ qconsole_history_oldest ] ) );
|
||||||
|
|
||||||
|
if( qconsole_history_oldest >= QCONSOLE_HISTORY - 1 )
|
||||||
|
qconsole_history_oldest = 0;
|
||||||
|
else
|
||||||
|
qconsole_history_oldest++;
|
||||||
|
|
||||||
|
qconsole_history_pos = qconsole_history_oldest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CON_HistPrev
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void CON_HistPrev( void )
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = ( qconsole_history_pos < 1 ) ?
|
||||||
|
( QCONSOLE_HISTORY - 1 ) : ( qconsole_history_pos - 1 );
|
||||||
|
|
||||||
|
// don' t allow looping through history
|
||||||
|
if( pos == qconsole_history_oldest )
|
||||||
|
return;
|
||||||
|
|
||||||
|
qconsole_history_pos = pos;
|
||||||
|
Q_strncpyz( qconsole_line, qconsole_history[ qconsole_history_pos ],
|
||||||
|
sizeof( qconsole_line ) );
|
||||||
|
qconsole_linelen = strlen( qconsole_line );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CON_HistNext
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void CON_HistNext( void )
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = ( qconsole_history_pos >= QCONSOLE_HISTORY - 1 ) ?
|
||||||
|
0 : ( qconsole_history_pos + 1 );
|
||||||
|
|
||||||
|
// clear the edit buffer if they try to advance to a future command
|
||||||
|
if( pos == qconsole_history_oldest )
|
||||||
|
{
|
||||||
|
qconsole_line[ 0 ] = '\0';
|
||||||
|
qconsole_linelen = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qconsole_history_pos = pos;
|
||||||
|
Q_strncpyz( qconsole_line, qconsole_history[ qconsole_history_pos ],
|
||||||
|
sizeof( qconsole_line ) );
|
||||||
|
qconsole_linelen = strlen( qconsole_line );
|
||||||
|
}
|
||||||
|
|
||||||
// used to restore original color theme
|
|
||||||
static int qconsole_orig_attrib;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
|
@ -54,6 +146,46 @@ CON_Show
|
||||||
*/
|
*/
|
||||||
void CON_Show( void )
|
void CON_Show( void )
|
||||||
{
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO binfo;
|
||||||
|
COORD writeSize = { MAX_EDIT_LINE, 1 };
|
||||||
|
COORD writePos = { 0, 0 };
|
||||||
|
SMALL_RECT writeArea = { 0, 0, 0, 0 };
|
||||||
|
int i;
|
||||||
|
CHAR_INFO line[ MAX_EDIT_LINE ];
|
||||||
|
|
||||||
|
GetConsoleScreenBufferInfo( qconsole_hout, &binfo );
|
||||||
|
|
||||||
|
// if we' re in the middle of printf, don't bother writing the buffer
|
||||||
|
if( binfo.dwCursorPosition.X != 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
writeArea.Left = 0;
|
||||||
|
writeArea.Top = binfo.dwCursorPosition.Y;
|
||||||
|
writeArea.Bottom = binfo.dwCursorPosition.Y;
|
||||||
|
writeArea.Right = MAX_EDIT_LINE;
|
||||||
|
|
||||||
|
// build a space-padded CHAR_INFO array
|
||||||
|
for( i = 0; i < MAX_EDIT_LINE; i++ )
|
||||||
|
{
|
||||||
|
if( i < qconsole_linelen )
|
||||||
|
line[ i ].Char.AsciiChar = qconsole_line[ i ];
|
||||||
|
else
|
||||||
|
line[ i ].Char.AsciiChar = ' ';
|
||||||
|
|
||||||
|
line[ i ].Attributes = qconsole_attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( qconsole_linelen > binfo.srWindow.Right )
|
||||||
|
{
|
||||||
|
WriteConsoleOutput( qconsole_hout,
|
||||||
|
line + (qconsole_linelen - binfo.srWindow.Right ),
|
||||||
|
writeSize, writePos, &writeArea );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteConsoleOutput( qconsole_hout, line, writeSize,
|
||||||
|
writePos, &writeArea );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -63,15 +195,10 @@ CON_Shutdown
|
||||||
*/
|
*/
|
||||||
void CON_Shutdown( void )
|
void CON_Shutdown( void )
|
||||||
{
|
{
|
||||||
HANDLE hout;
|
SetConsoleMode( qconsole_hin, qconsole_orig_mode );
|
||||||
COORD screen = { 0, 0 };
|
SetConsoleCursorInfo( qconsole_hout, &qconsole_orig_cursorinfo );
|
||||||
DWORD written;
|
CloseHandle( qconsole_hout );
|
||||||
|
CloseHandle( qconsole_hin );
|
||||||
hout = GetStdHandle( STD_OUTPUT_HANDLE );
|
|
||||||
|
|
||||||
SetConsoleTextAttribute( hout, qconsole_orig_attrib );
|
|
||||||
FillConsoleOutputAttribute( hout, qconsole_orig_attrib, 63999,
|
|
||||||
screen, &written );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -81,34 +208,43 @@ CON_Init
|
||||||
*/
|
*/
|
||||||
void CON_Init( void )
|
void CON_Init( void )
|
||||||
{
|
{
|
||||||
HANDLE hout;
|
CONSOLE_CURSOR_INFO curs;
|
||||||
COORD screen = { 0, 0 };
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
DWORD written, read;
|
int i;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO binfo;
|
|
||||||
SMALL_RECT rect;
|
|
||||||
WORD oldattrib;
|
|
||||||
|
|
||||||
hout = GetStdHandle( STD_OUTPUT_HANDLE );
|
// handle Ctrl-C or other console termination
|
||||||
|
SetConsoleCtrlHandler( CON_CtrlHandler, TRUE );
|
||||||
|
|
||||||
// remember original color theme
|
qconsole_hin = GetStdHandle( STD_INPUT_HANDLE );
|
||||||
ReadConsoleOutputAttribute( hout, &oldattrib, 1, screen, &read );
|
if( qconsole_hin == INVALID_HANDLE_VALUE )
|
||||||
qconsole_orig_attrib = oldattrib;
|
return;
|
||||||
|
|
||||||
SetConsoleTitle("ioquake3 Dedicated Server Console");
|
qconsole_hout = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||||
|
if( qconsole_hout == INVALID_HANDLE_VALUE )
|
||||||
|
return;
|
||||||
|
|
||||||
SetConsoleTextAttribute( hout, QCONSOLE_THEME );
|
GetConsoleMode( qconsole_hin, &qconsole_orig_mode );
|
||||||
FillConsoleOutputAttribute( hout, QCONSOLE_THEME, 63999, screen, &written );
|
|
||||||
|
|
||||||
// adjust console scroll to match up with cursor position
|
// allow mouse wheel scrolling
|
||||||
GetConsoleScreenBufferInfo( hout, &binfo );
|
SetConsoleMode( qconsole_hin,
|
||||||
rect.Top = binfo.srWindow.Top;
|
qconsole_orig_mode & ~ENABLE_MOUSE_INPUT );
|
||||||
rect.Left = binfo.srWindow.Left;
|
|
||||||
rect.Bottom = binfo.srWindow.Bottom;
|
|
||||||
rect.Right = binfo.srWindow.Right;
|
|
||||||
rect.Top += ( binfo.dwCursorPosition.Y - binfo.srWindow.Bottom );
|
|
||||||
rect.Bottom = binfo.dwCursorPosition.Y;
|
|
||||||
SetConsoleWindowInfo( hout, TRUE, &rect );
|
|
||||||
|
|
||||||
|
FlushConsoleInputBuffer( qconsole_hin );
|
||||||
|
|
||||||
|
GetConsoleScreenBufferInfo( qconsole_hout, &info );
|
||||||
|
qconsole_attrib = info.wAttributes;
|
||||||
|
|
||||||
|
SetConsoleTitle("ioquake3 Dedicated Server Console");
|
||||||
|
|
||||||
|
// make cursor invisible
|
||||||
|
GetConsoleCursorInfo( qconsole_hout, &qconsole_orig_cursorinfo );
|
||||||
|
curs.dwSize = 1;
|
||||||
|
curs.bVisible = FALSE;
|
||||||
|
SetConsoleCursorInfo( qconsole_hout, &curs );
|
||||||
|
|
||||||
|
// initialize history
|
||||||
|
for( i = 0; i < QCONSOLE_HISTORY; i++ )
|
||||||
|
qconsole_history[ i ][ 0 ] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -118,167 +254,102 @@ CON_ConsoleInput
|
||||||
*/
|
*/
|
||||||
char *CON_ConsoleInput( void )
|
char *CON_ConsoleInput( void )
|
||||||
{
|
{
|
||||||
HANDLE hin, hout;
|
INPUT_RECORD buff[ MAX_EDIT_LINE ];
|
||||||
INPUT_RECORD buff[ QCONSOLE_INPUT_RECORDS ];
|
DWORD count = 0, events = 0;
|
||||||
DWORD count = 0;
|
WORD key = 0;
|
||||||
int i;
|
int i;
|
||||||
static char input[ 1024 ] = { "" };
|
int newlinepos = -1;
|
||||||
int inputlen;
|
|
||||||
int newlinepos = -1;
|
|
||||||
CHAR_INFO line[ QCONSOLE_INPUT_RECORDS ];
|
|
||||||
int linelen = 0;
|
|
||||||
|
|
||||||
inputlen = 0;
|
if( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) )
|
||||||
input[ 0 ] = '\0';
|
return NULL;
|
||||||
|
|
||||||
hin = GetStdHandle( STD_INPUT_HANDLE );
|
if( events < 1 )
|
||||||
if( hin == INVALID_HANDLE_VALUE )
|
return NULL;
|
||||||
return NULL;
|
|
||||||
hout = GetStdHandle( STD_OUTPUT_HANDLE );
|
|
||||||
if( hout == INVALID_HANDLE_VALUE )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if( !PeekConsoleInput( hin, buff, QCONSOLE_INPUT_RECORDS, &count ) )
|
// if we have overflowed, start dropping oldest input events
|
||||||
return NULL;
|
if( events >= MAX_EDIT_LINE )
|
||||||
|
{
|
||||||
|
ReadConsoleInput( qconsole_hin, buff, 1, &events );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// if we have overflowed, start dropping oldest input events
|
if( !ReadConsoleInput( qconsole_hin, buff, events, &count ) )
|
||||||
if( count == QCONSOLE_INPUT_RECORDS )
|
return NULL;
|
||||||
{
|
|
||||||
ReadConsoleInput( hin, buff, 1, &count );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < count; i++ )
|
FlushConsoleInputBuffer( qconsole_hin );
|
||||||
{
|
|
||||||
if( buff[ i ].EventType == KEY_EVENT && buff[ i ].Event.KeyEvent.bKeyDown )
|
|
||||||
{
|
|
||||||
if( buff[ i ].Event.KeyEvent.wVirtualKeyCode == VK_RETURN )
|
|
||||||
{
|
|
||||||
newlinepos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( linelen < QCONSOLE_INPUT_RECORDS &&
|
for( i = 0; i < count; i++ )
|
||||||
buff[ i ].Event.KeyEvent.uChar.AsciiChar )
|
{
|
||||||
{
|
if( buff[ i ].EventType != KEY_EVENT )
|
||||||
if( buff[ i ].Event.KeyEvent.wVirtualKeyCode == VK_BACK )
|
continue;
|
||||||
{
|
if( !buff[ i ].Event.KeyEvent.bKeyDown )
|
||||||
if( linelen > 0 )
|
continue;
|
||||||
linelen--;
|
|
||||||
|
|
||||||
}
|
key = buff[ i ].Event.KeyEvent.wVirtualKeyCode;
|
||||||
else
|
|
||||||
{
|
|
||||||
line[ linelen ].Attributes = QCONSOLE_THEME;
|
|
||||||
line[ linelen++ ].Char.AsciiChar =
|
|
||||||
buff[ i ].Event.KeyEvent.uChar.AsciiChar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// provide visual feedback for incomplete commands
|
if( key == VK_RETURN )
|
||||||
if( linelen != qconsole_chars )
|
{
|
||||||
{
|
newlinepos = i;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO binfo;
|
break;
|
||||||
COORD writeSize = { QCONSOLE_INPUT_RECORDS, 1 };
|
}
|
||||||
COORD writePos = { 0, 0 };
|
else if( key == VK_UP )
|
||||||
SMALL_RECT writeArea = { 0, 0, 0, 0 };
|
{
|
||||||
int i;
|
CON_HistPrev();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( key == VK_DOWN )
|
||||||
|
{
|
||||||
|
CON_HistNext();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( key == VK_TAB )
|
||||||
|
{
|
||||||
|
field_t f;
|
||||||
|
|
||||||
// keep track of this so we don't need to re-write to console every frame
|
Q_strncpyz( f.buffer, qconsole_line,
|
||||||
qconsole_chars = linelen;
|
sizeof( f.buffer ) );
|
||||||
|
Field_AutoComplete( &f );
|
||||||
|
Q_strncpyz( qconsole_line, f.buffer,
|
||||||
|
sizeof( qconsole_line ) );
|
||||||
|
qconsole_linelen = strlen( qconsole_line );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
GetConsoleScreenBufferInfo( hout, &binfo );
|
if( qconsole_linelen < sizeof( qconsole_line ) - 1 )
|
||||||
|
{
|
||||||
|
char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar;
|
||||||
|
|
||||||
// adjust scrolling to cursor when typing
|
if( key == VK_BACK )
|
||||||
if( binfo.dwCursorPosition.Y > binfo.srWindow.Bottom )
|
{
|
||||||
{
|
int pos = ( qconsole_linelen > 0 ) ?
|
||||||
SMALL_RECT rect;
|
qconsole_linelen - 1 : 0;
|
||||||
|
|
||||||
rect.Top = binfo.srWindow.Top;
|
qconsole_line[ pos ] = '\0';
|
||||||
rect.Left = binfo.srWindow.Left;
|
qconsole_linelen = pos;
|
||||||
rect.Bottom = binfo.srWindow.Bottom;
|
}
|
||||||
rect.Right = binfo.srWindow.Right;
|
else if( c )
|
||||||
|
{
|
||||||
|
qconsole_line[ qconsole_linelen++ ] = c;
|
||||||
|
qconsole_line[ qconsole_linelen ] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rect.Top += ( binfo.dwCursorPosition.Y - binfo.srWindow.Bottom );
|
CON_Show();
|
||||||
rect.Bottom = binfo.dwCursorPosition.Y;
|
|
||||||
|
|
||||||
SetConsoleWindowInfo( hout, TRUE, &rect );
|
if( newlinepos < 0)
|
||||||
GetConsoleScreenBufferInfo( hout, &binfo );
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
writeArea.Left = 0;
|
if( !qconsole_linelen )
|
||||||
writeArea.Top = binfo.srWindow.Bottom;
|
{
|
||||||
writeArea.Bottom = binfo.srWindow.Bottom;
|
Com_Printf( "\n" );
|
||||||
writeArea.Right = QCONSOLE_INPUT_RECORDS;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// pad line with ' ' to handle VK_BACK
|
CON_HistAdd();
|
||||||
for( i = linelen; i < QCONSOLE_INPUT_RECORDS; i++ )
|
Com_Printf( "%s\n", qconsole_line );
|
||||||
{
|
|
||||||
line[ i ].Char.AsciiChar = ' ';
|
|
||||||
line[ i ].Attributes = QCONSOLE_THEME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( linelen > binfo.srWindow.Right )
|
qconsole_linelen = 0;
|
||||||
{
|
|
||||||
WriteConsoleOutput( hout, line + (linelen - binfo.srWindow.Right ),
|
|
||||||
writeSize, writePos, &writeArea );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteConsoleOutput( hout, line, writeSize, writePos, &writeArea );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( binfo.dwCursorPosition.X != linelen )
|
return qconsole_line;
|
||||||
{
|
|
||||||
COORD cursorPos = { 0, 0 };
|
|
||||||
|
|
||||||
cursorPos.X = linelen;
|
|
||||||
cursorPos.Y = binfo.srWindow.Bottom;
|
|
||||||
SetConsoleCursorPosition( hout, cursorPos );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't touch the input buffer if this is an incomplete command
|
|
||||||
if( newlinepos < 0)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// add a newline
|
|
||||||
COORD cursorPos = { 0, 0 };
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO binfo;
|
|
||||||
|
|
||||||
GetConsoleScreenBufferInfo( hout, &binfo );
|
|
||||||
cursorPos.Y = binfo.srWindow.Bottom + 1;
|
|
||||||
SetConsoleCursorPosition( hout, cursorPos );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( !ReadConsoleInput( hin, buff, newlinepos+1, &count ) )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for( i = 0; i < count; i++ )
|
|
||||||
{
|
|
||||||
if( buff[ i ].EventType == KEY_EVENT && buff[ i ].Event.KeyEvent.bKeyDown )
|
|
||||||
{
|
|
||||||
if( buff[ i ].Event.KeyEvent.wVirtualKeyCode == VK_BACK )
|
|
||||||
{
|
|
||||||
if( inputlen > 0 )
|
|
||||||
input[ --inputlen ] = '\0';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( inputlen < ( sizeof( input ) - 1 ) &&
|
|
||||||
buff[ i ].Event.KeyEvent.uChar.AsciiChar )
|
|
||||||
{
|
|
||||||
input[ inputlen++ ] = buff[ i ].Event.KeyEvent.uChar.AsciiChar;
|
|
||||||
input[ inputlen ] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( !inputlen )
|
|
||||||
return NULL;
|
|
||||||
return input;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,3 +38,5 @@ char *CON_ConsoleInput(void);
|
||||||
#ifdef MACOS_X
|
#ifdef MACOS_X
|
||||||
char *Sys_StripAppBundle( char *pwd );
|
char *Sys_StripAppBundle( char *pwd );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void Sys_SigHandler( int signal );
|
||||||
|
|
|
@ -573,7 +573,7 @@ void Sys_ParseArgs( int argc, char **argv )
|
||||||
Sys_SigHandler
|
Sys_SigHandler
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static void Sys_SigHandler( int signal )
|
void Sys_SigHandler( int signal )
|
||||||
{
|
{
|
||||||
static qboolean signalcaught = qfalse;
|
static qboolean signalcaught = qfalse;
|
||||||
|
|
||||||
|
@ -641,6 +641,7 @@ int main( int argc, char **argv )
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Windows doesn't have these signals
|
// Windows doesn't have these signals
|
||||||
|
// see CON_CtrlHandler() in con_win32.c
|
||||||
signal( SIGHUP, Sys_SigHandler );
|
signal( SIGHUP, Sys_SigHandler );
|
||||||
signal( SIGQUIT, Sys_SigHandler );
|
signal( SIGQUIT, Sys_SigHandler );
|
||||||
signal( SIGTRAP, Sys_SigHandler );
|
signal( SIGTRAP, Sys_SigHandler );
|
||||||
|
|
|
@ -448,3 +448,31 @@ char *Sys_StripAppBundle( char *dir )
|
||||||
return cwd;
|
return cwd;
|
||||||
}
|
}
|
||||||
#endif // MACOS_X
|
#endif // MACOS_X
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
Sys_Sleep
|
||||||
|
|
||||||
|
Block execution for msec or until input is recieved.
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void Sys_Sleep( int msec )
|
||||||
|
{
|
||||||
|
fd_set fdset;
|
||||||
|
|
||||||
|
FD_ZERO(&fdset);
|
||||||
|
FD_SET(fileno(stdin), &fdset);
|
||||||
|
if( msec < 0 )
|
||||||
|
{
|
||||||
|
select((fileno(stdin) + 1), &fdset, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
timeout.tv_sec = msec/1000;
|
||||||
|
timeout.tv_usec = (msec%1000)*1000;
|
||||||
|
select((fileno(stdin) + 1), &fdset, NULL, NULL, &timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -508,3 +508,20 @@ void Sys_FreeFileList( char **list )
|
||||||
|
|
||||||
Z_Free( list );
|
Z_Free( list );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
Sys_Sleep
|
||||||
|
|
||||||
|
Block execution for msec or until input is recieved.
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void Sys_Sleep( int msec )
|
||||||
|
{
|
||||||
|
if( msec < 0 )
|
||||||
|
WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), INFINITE );
|
||||||
|
else
|
||||||
|
WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), msec );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue