diff options
Diffstat (limited to 'src/sys/con_win32.c')
-rw-r--r-- | src/sys/con_win32.c | 216 |
1 files changed, 215 insertions, 1 deletions
diff --git a/src/sys/con_win32.c b/src/sys/con_win32.c index ea3cfb7c..55020e26 100644 --- a/src/sys/con_win32.c +++ b/src/sys/con_win32.c @@ -22,6 +22,21 @@ 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_THEME FOREGROUND_RED | \ + BACKGROUND_RED | \ + BACKGROUND_GREEN | \ + BACKGROUND_BLUE + +#define QCONSOLE_INPUT_RECORDS 1024 + +// used to track key input +static int qconsole_chars = 0; + +// used to restore original color theme +static int qconsole_orig_attrib; /* ================== @@ -48,6 +63,15 @@ CON_Shutdown */ void CON_Shutdown( void ) { + HANDLE hout; + COORD screen = { 0, 0 }; + DWORD written; + + hout = GetStdHandle( STD_OUTPUT_HANDLE ); + + SetConsoleTextAttribute( hout, qconsole_orig_attrib ); + FillConsoleOutputAttribute( hout, qconsole_orig_attrib, 63999, + screen, &written ); } /* @@ -57,6 +81,34 @@ CON_Init */ void CON_Init( void ) { + HANDLE hout; + COORD screen = { 0, 0 }; + DWORD written, read; + CONSOLE_SCREEN_BUFFER_INFO binfo; + SMALL_RECT rect; + WORD oldattrib; + + hout = GetStdHandle( STD_OUTPUT_HANDLE ); + + // remember original color theme + ReadConsoleOutputAttribute( hout, &oldattrib, 1, screen, &read ); + qconsole_orig_attrib = oldattrib; + + SetConsoleTitle("ioquake3 Dedicated Server Console"); + + 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 +118,167 @@ 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_INPUT_RECORDS ]; + 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_INPUT_RECORDS && + 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_INPUT_RECORDS, 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_INPUT_RECORDS; + + // pad line with ' ' to handle VK_BACK + for( i = linelen; i < QCONSOLE_INPUT_RECORDS; i++ ) + { + line[ i ].Char.AsciiChar = ' '; + line[ i ].Attributes = QCONSOLE_THEME; + } + + if( linelen > binfo.srWindow.Right ) + { + WriteConsoleOutput( hout, line + (linelen - binfo.srWindow.Right ), + writeSize, writePos, &writeArea ); + } + else + { + 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; } |