aboutsummaryrefslogtreecommitdiff
path: root/code/sys/con_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/sys/con_win32.c')
-rw-r--r--code/sys/con_win32.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/code/sys/con_win32.c b/code/sys/con_win32.c
new file mode 100644
index 0000000..787c74f
--- /dev/null
+++ b/code/sys/con_win32.c
@@ -0,0 +1,358 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "../qcommon/q_shared.h"
+#include "../qcommon/qcommon.h"
+#include "sys_local.h"
+#include "windows.h"
+
+#define QCONSOLE_HISTORY 32
+
+static WORD qconsole_attrib;
+
+// saved console status
+static DWORD qconsole_orig_mode;
+static CONSOLE_CURSOR_INFO qconsole_orig_cursorinfo;
+
+// cmd history
+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 );
+}
+
+
+/*
+==================
+CON_Show
+==================
+*/
+static 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 );
+ }
+}
+
+/*
+==================
+CON_Shutdown
+==================
+*/
+void CON_Shutdown( void )
+{
+ SetConsoleMode( qconsole_hin, qconsole_orig_mode );
+ SetConsoleCursorInfo( qconsole_hout, &qconsole_orig_cursorinfo );
+ CloseHandle( qconsole_hout );
+ CloseHandle( qconsole_hin );
+}
+
+/*
+==================
+CON_Init
+==================
+*/
+void CON_Init( void )
+{
+ CONSOLE_CURSOR_INFO curs;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ int i;
+
+ // handle Ctrl-C or other console termination
+ SetConsoleCtrlHandler( CON_CtrlHandler, TRUE );
+
+ qconsole_hin = GetStdHandle( STD_INPUT_HANDLE );
+ if( qconsole_hin == INVALID_HANDLE_VALUE )
+ return;
+
+ qconsole_hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ if( qconsole_hout == INVALID_HANDLE_VALUE )
+ return;
+
+ GetConsoleMode( qconsole_hin, &qconsole_orig_mode );
+
+ // allow mouse wheel scrolling
+ SetConsoleMode( qconsole_hin,
+ qconsole_orig_mode & ~ENABLE_MOUSE_INPUT );
+
+ 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';
+}
+
+/*
+==================
+CON_Input
+==================
+*/
+char *CON_Input( void )
+{
+ INPUT_RECORD buff[ MAX_EDIT_LINE ];
+ DWORD count = 0, events = 0;
+ WORD key = 0;
+ int i;
+ int newlinepos = -1;
+
+ if( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) )
+ return NULL;
+
+ if( events < 1 )
+ return NULL;
+
+ // if we have overflowed, start dropping oldest input events
+ if( events >= MAX_EDIT_LINE )
+ {
+ ReadConsoleInput( qconsole_hin, buff, 1, &events );
+ return NULL;
+ }
+
+ if( !ReadConsoleInput( qconsole_hin, buff, events, &count ) )
+ return NULL;
+
+ FlushConsoleInputBuffer( qconsole_hin );
+
+ for( i = 0; i < count; i++ )
+ {
+ if( buff[ i ].EventType != KEY_EVENT )
+ continue;
+ if( !buff[ i ].Event.KeyEvent.bKeyDown )
+ continue;
+
+ key = buff[ i ].Event.KeyEvent.wVirtualKeyCode;
+
+ if( key == VK_RETURN )
+ {
+ newlinepos = i;
+ break;
+ }
+ else if( key == VK_UP )
+ {
+ CON_HistPrev();
+ break;
+ }
+ else if( key == VK_DOWN )
+ {
+ CON_HistNext();
+ break;
+ }
+ else if( key == VK_TAB )
+ {
+ field_t f;
+
+ Q_strncpyz( f.buffer, qconsole_line,
+ sizeof( f.buffer ) );
+ Field_AutoComplete( &f );
+ Q_strncpyz( qconsole_line, f.buffer,
+ sizeof( qconsole_line ) );
+ qconsole_linelen = strlen( qconsole_line );
+ break;
+ }
+
+ if( qconsole_linelen < sizeof( qconsole_line ) - 1 )
+ {
+ char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar;
+
+ if( key == VK_BACK )
+ {
+ int pos = ( qconsole_linelen > 0 ) ?
+ qconsole_linelen - 1 : 0;
+
+ qconsole_line[ pos ] = '\0';
+ qconsole_linelen = pos;
+ }
+ else if( c )
+ {
+ qconsole_line[ qconsole_linelen++ ] = c;
+ qconsole_line[ qconsole_linelen ] = '\0';
+ }
+ }
+ }
+
+ CON_Show();
+
+ if( newlinepos < 0)
+ return NULL;
+
+ if( !qconsole_linelen )
+ {
+ Com_Printf( "\n" );
+ return NULL;
+ }
+
+ CON_HistAdd();
+ Com_Printf( "%s\n", qconsole_line );
+
+ qconsole_linelen = 0;
+
+ return qconsole_line;
+}
+
+/*
+==================
+CON_Print
+==================
+*/
+void CON_Print( const char *msg )
+{
+ fputs( msg, stderr );
+
+ CON_Show( );
+}