aboutsummaryrefslogtreecommitdiffstats
path: root/code/sys
diff options
context:
space:
mode:
Diffstat (limited to 'code/sys')
-rw-r--r--code/sys/con_win32.c196
1 files changed, 195 insertions, 1 deletions
diff --git a/code/sys/con_win32.c b/code/sys/con_win32.c
index 8e5718c..0e29dba 100644
--- a/code/sys/con_win32.c
+++ b/code/sys/con_win32.c
@@ -22,6 +22,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
+#include "windows.h"
+
+#define QCONSOLE_WIDTH 80
+#define QCONSOLE_HEIGHT 30
+
+#define QCONSOLE_THEME FOREGROUND_RED | \
+ BACKGROUND_RED | \
+ BACKGROUND_GREEN | \
+ BACKGROUND_BLUE
+
+#define QCONSOLE_INPUT_RECORDS 1024
+
+static int qconsole_chars = 0;
/*
==================
@@ -57,6 +70,31 @@ CON_Init
*/
void CON_Init( void )
{
+ SMALL_RECT win = { 0, 0, QCONSOLE_WIDTH-1, QCONSOLE_HEIGHT-1 };
+ HANDLE hout;
+ COORD screen = { 0, 0 };
+ DWORD written;
+ CONSOLE_SCREEN_BUFFER_INFO binfo;
+ SMALL_RECT rect;
+
+ SetConsoleTitle("ioquake3 Dedicated Server Console");
+
+ hout = GetStdHandle( STD_OUTPUT_HANDLE );
+
+ SetConsoleWindowInfo( hout, TRUE, &win );
+ SetConsoleTextAttribute( hout, QCONSOLE_THEME );
+ FillConsoleOutputAttribute( hout, QCONSOLE_THEME, 63999, screen, &written );
+
+ // adjust console scroll to match up with cursor position
+ GetConsoleScreenBufferInfo( hout, &binfo );
+ rect.Top = binfo.srWindow.Top;
+ 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 );
+
}
/*
@@ -66,5 +104,161 @@ CON_ConsoleInput
*/
char *CON_ConsoleInput( void )
{
- return NULL;
+ HANDLE hin, hout;
+ INPUT_RECORD buff[ QCONSOLE_INPUT_RECORDS ];
+ DWORD count = 0;
+ int i;
+ static char input[ 1024 ] = { "" };
+ int inputlen;
+ int newlinepos = -1;
+ CHAR_INFO line[ QCONSOLE_WIDTH ];
+ int linelen = 0;
+
+ inputlen = 0;
+ input[ 0 ] = '\0';
+
+ hin = GetStdHandle( STD_INPUT_HANDLE );
+ if( hin == INVALID_HANDLE_VALUE )
+ return NULL;
+ hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ if( hout == INVALID_HANDLE_VALUE )
+ return NULL;
+
+ if( !PeekConsoleInput( hin, buff, QCONSOLE_INPUT_RECORDS, &count ) )
+ return NULL;
+
+ // if we have overflowed, start dropping oldest input events
+ if( count == QCONSOLE_INPUT_RECORDS )
+ {
+ ReadConsoleInput( hin, buff, 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_RETURN )
+ {
+ newlinepos = i;
+ break;
+ }
+
+ if( linelen < QCONSOLE_WIDTH &&
+ buff[ i ].Event.KeyEvent.uChar.AsciiChar )
+ {
+ if( buff[ i ].Event.KeyEvent.wVirtualKeyCode == VK_BACK )
+ {
+ if( linelen > 0 )
+ linelen--;
+
+ }
+ else
+ {
+ line[ linelen ].Attributes = QCONSOLE_THEME;
+ line[ linelen++ ].Char.AsciiChar =
+ buff[ i ].Event.KeyEvent.uChar.AsciiChar;
+ }
+ }
+ }
+ }
+
+ // provide visual feedback for incomplete commands
+ if( linelen != qconsole_chars )
+ {
+ CONSOLE_SCREEN_BUFFER_INFO binfo;
+ COORD writeSize = { QCONSOLE_WIDTH, 1 };
+ COORD writePos = { 0, 0 };
+ SMALL_RECT writeArea = { 0, 0, 0, 0 };
+ int i;
+
+ // keep track of this so we don't need to re-write to console every frame
+ qconsole_chars = linelen;
+
+ GetConsoleScreenBufferInfo( hout, &binfo );
+
+ // adjust scrolling to cursor when typing
+ if( binfo.dwCursorPosition.Y > binfo.srWindow.Bottom )
+ {
+ SMALL_RECT rect;
+
+ rect.Top = binfo.srWindow.Top;
+ 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 );
+ GetConsoleScreenBufferInfo( hout, &binfo );
+ }
+
+ writeArea.Left = 0;
+ writeArea.Top = binfo.srWindow.Bottom;
+ writeArea.Bottom = binfo.srWindow.Bottom;
+ writeArea.Right = QCONSOLE_WIDTH;
+
+ // pad line with ' ' to handle VK_BACK
+ for( i = linelen; i < QCONSOLE_WIDTH; i++ )
+ {
+ line[ i ].Char.AsciiChar = ' ';
+ line[ i ].Attributes = QCONSOLE_THEME;
+ }
+
+ WriteConsoleOutput( hout, line, writeSize, writePos, &writeArea );
+
+ if( binfo.dwCursorPosition.X != linelen )
+ {
+ 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;
}