mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-17 18:40:02 +00:00
engine: platform: win32: major refactoring of console code
This commit is contained in:
parent
58dbc1ba31
commit
95ee88720c
@ -353,9 +353,6 @@ void Sys_WaitForQuit( void )
|
||||
{
|
||||
#if XASH_WIN32
|
||||
MSG msg;
|
||||
|
||||
Wcon_RegisterHotkeys();
|
||||
|
||||
msg.message = 0;
|
||||
|
||||
// wait for the user to quit
|
||||
|
@ -89,10 +89,9 @@ void Wcon_ShowConsole( qboolean show );
|
||||
void Wcon_CreateConsole( void );
|
||||
void Wcon_DestroyConsole( void );
|
||||
void Wcon_DisableInput( void );
|
||||
void Wcon_Clear( void );
|
||||
char *Wcon_Input( void );
|
||||
void Wcon_WinPrint( const char *pMsg );
|
||||
void Wcon_RegisterHotkeys( void );
|
||||
void Wcon_SetStatus( const char *pStatus );
|
||||
#endif
|
||||
|
||||
// text messages
|
||||
|
@ -25,198 +25,429 @@ WIN32 CONSOLE
|
||||
*/
|
||||
|
||||
// console defines
|
||||
#define SUBMIT_ID 1 // "submit" button
|
||||
#define QUIT_ON_ESCAPE_ID 2 // escape event
|
||||
#define EDIT_ID 110
|
||||
#define INPUT_ID 109
|
||||
#define IDI_ICON1 101
|
||||
|
||||
#define SYSCONSOLE "XashConsole"
|
||||
#define COMMAND_HISTORY 64 // system console keep more commands than game console
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char title[64];
|
||||
HWND hWnd;
|
||||
HWND hwndBuffer;
|
||||
HWND hwndButtonSubmit;
|
||||
HBRUSH hbrEditBackground;
|
||||
HFONT hfBufferFont;
|
||||
HWND hwndInputLine;
|
||||
HANDLE hInput;
|
||||
HANDLE hOutput;
|
||||
int inputLine;
|
||||
int browseLine;
|
||||
int cursorPosition;
|
||||
int totalLines;
|
||||
int savedConsoleTextLen;
|
||||
int consoleTextLen;
|
||||
string consoleText;
|
||||
string returnedText;
|
||||
string historyLines[COMMAND_HISTORY];
|
||||
int nextHistoryLine;
|
||||
int historyLine;
|
||||
int status;
|
||||
int windowWidth, windowHeight;
|
||||
WNDPROC SysInputLineWndProc;
|
||||
size_t outLen;
|
||||
string savedConsoleText;
|
||||
string statusLine;
|
||||
string lineBuffer[COMMAND_HISTORY];
|
||||
qboolean inputEnabled;
|
||||
qboolean consoleVisible;
|
||||
|
||||
// log stuff
|
||||
qboolean log_active;
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
} WinConData;
|
||||
|
||||
static WinConData s_wcd;
|
||||
static WORD g_color_table[8] =
|
||||
{
|
||||
FOREGROUND_INTENSITY, // black
|
||||
FOREGROUND_RED, // red
|
||||
FOREGROUND_GREEN, // green
|
||||
FOREGROUND_RED | FOREGROUND_GREEN, // yellow
|
||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // blue
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE, // cyan
|
||||
FOREGROUND_RED | FOREGROUND_BLUE, // magenta
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // default color (white)
|
||||
};
|
||||
|
||||
static BOOL WINAPI Wcon_HandleConsole(DWORD CtrlType)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void Wcon_PrintInternal( const char *msg, int length )
|
||||
{
|
||||
char *pTemp;
|
||||
DWORD cbWritten;
|
||||
const char *pMsgString;
|
||||
static char tmpBuf[2048];
|
||||
static char szOutput[2048];
|
||||
|
||||
Q_strncpy( szOutput, msg, length ? (length + 1) : ( sizeof( szOutput ) - 1 ));
|
||||
if( length )
|
||||
szOutput[length + 1] = '\0';
|
||||
else
|
||||
szOutput[sizeof( szOutput ) - 1] = '\0';
|
||||
|
||||
pTemp = tmpBuf;
|
||||
pMsgString = szOutput;
|
||||
while( pMsgString && *pMsgString )
|
||||
{
|
||||
if( IsColorString( pMsgString ))
|
||||
{
|
||||
if (( pTemp - tmpBuf ) > 0 )
|
||||
{
|
||||
// dump accumulated text before change color
|
||||
*pTemp = 0; // terminate string
|
||||
WriteFile( s_wcd.hOutput, tmpBuf, Q_strlen(tmpBuf), &cbWritten, 0 );
|
||||
pTemp = tmpBuf;
|
||||
}
|
||||
|
||||
// set new color
|
||||
SetConsoleTextAttribute( s_wcd.hOutput, g_color_table[ColorIndex(*(pMsgString + 1))] );
|
||||
pMsgString += 2; // skip color info
|
||||
}
|
||||
else if(( pTemp - tmpBuf ) < sizeof( tmpBuf ) - 1 )
|
||||
{
|
||||
*pTemp++ = *pMsgString++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// temp buffer is full, dump it now
|
||||
*pTemp = 0; // terminate string
|
||||
WriteFile( s_wcd.hOutput, tmpBuf, Q_strlen(tmpBuf), &cbWritten, 0 );
|
||||
pTemp = tmpBuf;
|
||||
}
|
||||
}
|
||||
|
||||
// check for last portion
|
||||
if (( pTemp - tmpBuf ) > 0 )
|
||||
{
|
||||
// dump accumulated text
|
||||
*pTemp = 0; // terminate string
|
||||
WriteFile( s_wcd.hOutput, tmpBuf, Q_strlen(tmpBuf), &cbWritten, 0 );
|
||||
pTemp = tmpBuf;
|
||||
}
|
||||
|
||||
// restore white color
|
||||
SetConsoleTextAttribute( s_wcd.hOutput, g_color_table[7] );
|
||||
}
|
||||
|
||||
void Wcon_ShowConsole( qboolean show )
|
||||
{
|
||||
if( !s_wcd.hWnd || show == s_wcd.status )
|
||||
if( !s_wcd.hWnd || show == s_wcd.consoleVisible )
|
||||
return;
|
||||
|
||||
s_wcd.status = show;
|
||||
s_wcd.consoleVisible = show;
|
||||
if( show )
|
||||
{
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
||||
}
|
||||
else ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOW );
|
||||
else
|
||||
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
}
|
||||
|
||||
void Wcon_DisableInput( void )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED ) return;
|
||||
SendMessage( s_wcd.hwndButtonSubmit, WM_ENABLE, 0, 0 );
|
||||
SendMessage( s_wcd.hwndInputLine, WM_ENABLE, 0, 0 );
|
||||
if( host.type != HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
s_wcd.inputEnabled = false;
|
||||
}
|
||||
|
||||
void Wcon_SetInputText( const char *inputText )
|
||||
static void Wcon_SetInputText( const char *inputText )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED ) return;
|
||||
SetWindowText( s_wcd.hwndInputLine, inputText );
|
||||
SendMessage( s_wcd.hwndInputLine, EM_SETSEL, Q_strlen( inputText ), -1 );
|
||||
if( host.type != HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
while( s_wcd.consoleTextLen-- )
|
||||
{
|
||||
Wcon_PrintInternal( "\b \b", 0 );
|
||||
}
|
||||
Wcon_PrintInternal( inputText, 0 );
|
||||
Q_strncpy( s_wcd.consoleText, inputText, sizeof(s_wcd.consoleText) - 1 );
|
||||
s_wcd.consoleTextLen = Q_strlen( inputText );
|
||||
s_wcd.cursorPosition = s_wcd.consoleTextLen;
|
||||
s_wcd.browseLine = s_wcd.inputLine;
|
||||
}
|
||||
|
||||
static void Wcon_Clear_f( void )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED ) return;
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, (LPARAM)"" );
|
||||
UpdateWindow( s_wcd.hwndBuffer );
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
SMALL_RECT scrollRect;
|
||||
COORD scrollTarget;
|
||||
CHAR_INFO fill;
|
||||
|
||||
if( host.type != HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
if( !GetConsoleScreenBufferInfo( s_wcd.hOutput, &csbi ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scrollRect.Left = 0;
|
||||
scrollRect.Top = 0;
|
||||
scrollRect.Right = csbi.dwSize.X;
|
||||
scrollRect.Bottom = csbi.dwSize.Y;
|
||||
scrollTarget.X = 0;
|
||||
scrollTarget.Y = (SHORT)(0 - csbi.dwSize.Y);
|
||||
fill.Char.UnicodeChar = TEXT(' ');
|
||||
fill.Attributes = csbi.wAttributes;
|
||||
ScrollConsoleScreenBuffer( s_wcd.hOutput, &scrollRect, NULL, scrollTarget, &fill );
|
||||
|
||||
csbi.dwCursorPosition.X = 0;
|
||||
csbi.dwCursorPosition.Y = 0;
|
||||
SetConsoleCursorPosition( s_wcd.hOutput, csbi.dwCursorPosition );
|
||||
|
||||
s_wcd.consoleText[0] = '\0';
|
||||
s_wcd.consoleTextLen = 0;
|
||||
s_wcd.cursorPosition = 0;
|
||||
s_wcd.inputLine = 0;
|
||||
s_wcd.browseLine = 0;
|
||||
s_wcd.totalLines = 0;
|
||||
Wcon_PrintInternal( "\n", 0 );
|
||||
}
|
||||
|
||||
static int Wcon_KeyEvent( int key, qboolean down )
|
||||
static void Wcon_EventUpArrow()
|
||||
{
|
||||
char inputBuffer[1024];
|
||||
int nLastCommandInHistory = s_wcd.inputLine + 1;
|
||||
if( nLastCommandInHistory > s_wcd.totalLines )
|
||||
nLastCommandInHistory = 0;
|
||||
|
||||
if( !down )
|
||||
return 0;
|
||||
if( s_wcd.browseLine == nLastCommandInHistory )
|
||||
return;
|
||||
|
||||
if( s_wcd.browseLine == s_wcd.inputLine )
|
||||
{
|
||||
if( s_wcd.consoleTextLen > 0 )
|
||||
{
|
||||
Q_strncpy( s_wcd.savedConsoleText, s_wcd.consoleText, s_wcd.consoleTextLen );
|
||||
}
|
||||
s_wcd.savedConsoleTextLen = s_wcd.consoleTextLen;
|
||||
}
|
||||
|
||||
s_wcd.browseLine--;
|
||||
if( s_wcd.browseLine < 0 )
|
||||
{
|
||||
s_wcd.browseLine = s_wcd.totalLines - 1;
|
||||
}
|
||||
|
||||
while( s_wcd.consoleTextLen-- )
|
||||
{
|
||||
Wcon_PrintInternal( "\b \b", 0 );
|
||||
}
|
||||
|
||||
Wcon_PrintInternal( s_wcd.lineBuffer[s_wcd.browseLine], 0 );
|
||||
Q_strncpy( s_wcd.consoleText, s_wcd.lineBuffer[s_wcd.browseLine], sizeof( s_wcd.consoleText ));
|
||||
s_wcd.consoleTextLen = Q_strlen( s_wcd.lineBuffer[s_wcd.browseLine] );
|
||||
s_wcd.cursorPosition = s_wcd.consoleTextLen;
|
||||
}
|
||||
|
||||
static void Wcon_EventDownArrow()
|
||||
{
|
||||
if( s_wcd.browseLine == s_wcd.inputLine )
|
||||
return;
|
||||
|
||||
if( ++s_wcd.browseLine > s_wcd.totalLines )
|
||||
s_wcd.browseLine = 0;
|
||||
|
||||
while( s_wcd.consoleTextLen-- )
|
||||
{
|
||||
Wcon_PrintInternal( "\b \b", 0 );
|
||||
}
|
||||
|
||||
if( s_wcd.browseLine == s_wcd.inputLine )
|
||||
{
|
||||
if( s_wcd.savedConsoleTextLen > 0 )
|
||||
{
|
||||
Q_strncpy( s_wcd.consoleText, s_wcd.savedConsoleText, s_wcd.savedConsoleTextLen );
|
||||
Wcon_PrintInternal( s_wcd.consoleText, s_wcd.savedConsoleTextLen );
|
||||
}
|
||||
s_wcd.consoleTextLen = s_wcd.savedConsoleTextLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
Wcon_PrintInternal( s_wcd.lineBuffer[s_wcd.browseLine], 0 );
|
||||
Q_strncpy( s_wcd.consoleText, s_wcd.lineBuffer[s_wcd.browseLine], sizeof( s_wcd.consoleText ));
|
||||
s_wcd.consoleTextLen = Q_strlen( s_wcd.lineBuffer[s_wcd.browseLine] );
|
||||
}
|
||||
s_wcd.cursorPosition = s_wcd.consoleTextLen;
|
||||
}
|
||||
|
||||
static void Wcon_EventLeftArrow()
|
||||
{
|
||||
if( s_wcd.cursorPosition == 0 )
|
||||
return;
|
||||
|
||||
Wcon_PrintInternal( "\b", 0 );
|
||||
s_wcd.cursorPosition--;
|
||||
}
|
||||
|
||||
static void Wcon_EventRightArrow()
|
||||
{
|
||||
if( s_wcd.cursorPosition == s_wcd.consoleTextLen )
|
||||
return;
|
||||
|
||||
Wcon_PrintInternal( s_wcd.consoleText + s_wcd.cursorPosition, 1 );
|
||||
s_wcd.cursorPosition++;
|
||||
}
|
||||
|
||||
static int Wcon_EventNewline()
|
||||
{
|
||||
int nLen;
|
||||
|
||||
nLen = 0;
|
||||
Wcon_PrintInternal( "\n", 0 );
|
||||
if( s_wcd.consoleTextLen )
|
||||
{
|
||||
nLen = s_wcd.consoleTextLen;
|
||||
|
||||
s_wcd.consoleText[s_wcd.consoleTextLen] = '\0';
|
||||
s_wcd.consoleTextLen = 0;
|
||||
s_wcd.cursorPosition = 0;
|
||||
|
||||
if (( s_wcd.inputLine == 0 ) || ( Q_strcmp( s_wcd.lineBuffer[s_wcd.inputLine - 1], s_wcd.consoleText )))
|
||||
{
|
||||
Q_strncpy( s_wcd.lineBuffer[s_wcd.inputLine], s_wcd.consoleText, sizeof( s_wcd.consoleText ));
|
||||
s_wcd.inputLine++;
|
||||
|
||||
if( s_wcd.inputLine > s_wcd.totalLines )
|
||||
s_wcd.totalLines = s_wcd.inputLine;
|
||||
|
||||
if( s_wcd.inputLine >= COMMAND_HISTORY )
|
||||
s_wcd.inputLine = 0;
|
||||
}
|
||||
s_wcd.browseLine = s_wcd.inputLine;
|
||||
}
|
||||
return nLen;
|
||||
}
|
||||
|
||||
static void Wcon_EventBackspace()
|
||||
{
|
||||
int nCount;
|
||||
|
||||
if( s_wcd.cursorPosition < 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_wcd.consoleTextLen--;
|
||||
s_wcd.cursorPosition--;
|
||||
|
||||
Wcon_PrintInternal( "\b", 0 );
|
||||
|
||||
for( nCount = s_wcd.cursorPosition; nCount < s_wcd.consoleTextLen; ++nCount )
|
||||
{
|
||||
s_wcd.consoleText[nCount] = s_wcd.consoleText[nCount + 1];
|
||||
Wcon_PrintInternal( s_wcd.consoleText + nCount, 1 );
|
||||
}
|
||||
|
||||
Wcon_PrintInternal( " ", 0 );
|
||||
|
||||
nCount = s_wcd.consoleTextLen;
|
||||
while( nCount >= s_wcd.cursorPosition )
|
||||
{
|
||||
Wcon_PrintInternal( "\b", 0 );
|
||||
nCount--;
|
||||
}
|
||||
|
||||
s_wcd.browseLine = s_wcd.inputLine;
|
||||
}
|
||||
|
||||
static void Wcon_EventTab()
|
||||
{
|
||||
s_wcd.consoleText[s_wcd.consoleTextLen] = '\0';
|
||||
Cmd_AutoComplete( s_wcd.consoleText );
|
||||
Wcon_SetInputText( s_wcd.consoleText );
|
||||
}
|
||||
|
||||
static void Wcon_EventCharacter(char c)
|
||||
{
|
||||
int nCount;
|
||||
|
||||
if( s_wcd.consoleTextLen >= ( sizeof( s_wcd.consoleText ) - 2 ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nCount = s_wcd.consoleTextLen;
|
||||
while( nCount > s_wcd.cursorPosition )
|
||||
{
|
||||
s_wcd.consoleText[nCount] = s_wcd.consoleText[nCount - 1];
|
||||
nCount--;
|
||||
}
|
||||
|
||||
s_wcd.consoleText[s_wcd.cursorPosition] = c;
|
||||
Wcon_PrintInternal( s_wcd.consoleText + s_wcd.cursorPosition, s_wcd.consoleTextLen - s_wcd.cursorPosition + 1 );
|
||||
s_wcd.consoleTextLen++;
|
||||
s_wcd.cursorPosition++;
|
||||
|
||||
nCount = s_wcd.consoleTextLen;
|
||||
while( nCount > s_wcd.cursorPosition )
|
||||
{
|
||||
Wcon_PrintInternal( "\b", 0 );
|
||||
nCount--;
|
||||
}
|
||||
|
||||
s_wcd.browseLine = s_wcd.inputLine;
|
||||
}
|
||||
|
||||
static void Wcon_UpdateStatusLine()
|
||||
{
|
||||
COORD coord;
|
||||
WORD wAttrib;
|
||||
DWORD dwWritten;
|
||||
|
||||
coord.X = 0;
|
||||
coord.Y = 0;
|
||||
wAttrib = g_color_table[5] | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
|
||||
|
||||
FillConsoleOutputCharacter( s_wcd.hOutput, ' ', 80, coord, &dwWritten );
|
||||
FillConsoleOutputAttribute( s_wcd.hOutput, wAttrib, 80, coord, &dwWritten );
|
||||
WriteConsoleOutputCharacter( s_wcd.hOutput, s_wcd.statusLine, Q_strlen(s_wcd.statusLine), coord, &dwWritten );
|
||||
}
|
||||
|
||||
static char *Wcon_KeyEvent( int key, WCHAR character )
|
||||
{
|
||||
int nLen;
|
||||
char inputBuffer[1024];
|
||||
|
||||
switch( key )
|
||||
{
|
||||
case VK_TAB:
|
||||
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ));
|
||||
Cmd_AutoComplete( inputBuffer );
|
||||
Wcon_SetInputText( inputBuffer );
|
||||
return 1;
|
||||
case VK_DOWN:
|
||||
if( s_wcd.historyLine == s_wcd.nextHistoryLine )
|
||||
return 0;
|
||||
s_wcd.historyLine++;
|
||||
Wcon_SetInputText( s_wcd.historyLines[s_wcd.historyLine % COMMAND_HISTORY] );
|
||||
return 1;
|
||||
case VK_UP:
|
||||
if( s_wcd.nextHistoryLine - s_wcd.historyLine < COMMAND_HISTORY && s_wcd.historyLine > 0 )
|
||||
s_wcd.historyLine--;
|
||||
Wcon_SetInputText( s_wcd.historyLines[s_wcd.historyLine % COMMAND_HISTORY] );
|
||||
return 1;
|
||||
Wcon_EventUpArrow();
|
||||
return NULL;
|
||||
case VK_DOWN:
|
||||
Wcon_EventDownArrow();
|
||||
return NULL;
|
||||
case VK_LEFT:
|
||||
Wcon_EventLeftArrow();
|
||||
return NULL;
|
||||
case VK_RIGHT:
|
||||
Wcon_EventRightArrow();
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long _stdcall Wcon_WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch( uMsg )
|
||||
switch( character )
|
||||
{
|
||||
case WM_ACTIVATE:
|
||||
if( LOWORD( wParam ) != WA_INACTIVE )
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
if( host.status == HOST_ERR_FATAL )
|
||||
{
|
||||
// send windows message
|
||||
PostQuitMessage( 0 );
|
||||
}
|
||||
else Sys_Quit(); // otherwise
|
||||
return 0;
|
||||
case WM_CTLCOLORSTATIC:
|
||||
if((HWND)lParam == s_wcd.hwndBuffer )
|
||||
{
|
||||
SetBkColor((HDC)wParam, RGB( 0x90, 0x90, 0x90 ));
|
||||
SetTextColor((HDC)wParam, RGB( 0xff, 0xff, 0xff ));
|
||||
return (long)s_wcd.hbrEditBackground;
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
if( wParam == SUBMIT_ID )
|
||||
{
|
||||
SendMessage( s_wcd.hwndInputLine, WM_CHAR, 13, 0L );
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
}
|
||||
break;
|
||||
case WM_HOTKEY:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case QUIT_ON_ESCAPE_ID:
|
||||
PostQuitMessage( 0 );
|
||||
case '\r': // Enter
|
||||
nLen = Wcon_EventNewline();
|
||||
if (nLen)
|
||||
{
|
||||
return s_wcd.consoleText;
|
||||
}
|
||||
break;
|
||||
case '\b': // Backspace
|
||||
Wcon_EventBackspace();
|
||||
break;
|
||||
case '\t': // TAB
|
||||
Wcon_EventTab();
|
||||
break;
|
||||
default:
|
||||
// TODO implement converting wide chars to UTF-8 and properly handling it
|
||||
if (( character >= ' ' ) && ( character <= '~' ))
|
||||
{
|
||||
Wcon_EventCharacter(character);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_CREATE:
|
||||
s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x90, 0x90, 0x90 ));
|
||||
break;
|
||||
}
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long _stdcall Wcon_InputLineProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
char inputBuffer[1024];
|
||||
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_KILLFOCUS:
|
||||
if(( HWND )wParam == s_wcd.hWnd )
|
||||
{
|
||||
SetFocus( hWnd );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYDOWN:
|
||||
if( Wcon_KeyEvent( LOWORD( wParam ), true ))
|
||||
return 0;
|
||||
break;
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP:
|
||||
if( Wcon_KeyEvent( LOWORD( wParam ), false ))
|
||||
return 0;
|
||||
break;
|
||||
case WM_CHAR:
|
||||
if( Wcon_KeyEvent( wParam, true ))
|
||||
return 0;
|
||||
if( wParam == 13 && host.status != HOST_ERR_FATAL )
|
||||
{
|
||||
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ));
|
||||
Q_strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - Q_strlen( s_wcd.consoleText ) - 5 );
|
||||
Q_strcat( s_wcd.consoleText, "\n" );
|
||||
SetWindowText( s_wcd.hwndInputLine, "" );
|
||||
Con_Printf( ">%s\n", inputBuffer );
|
||||
|
||||
// copy line to history buffer
|
||||
Q_strncpy( s_wcd.historyLines[s_wcd.nextHistoryLine % COMMAND_HISTORY], inputBuffer, MAX_STRING );
|
||||
s_wcd.nextHistoryLine++;
|
||||
s_wcd.historyLine = s_wcd.nextHistoryLine;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
@ -224,6 +455,7 @@ WIN32 IO
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
Con_WinPrint
|
||||
@ -233,24 +465,26 @@ print into window console
|
||||
*/
|
||||
void Wcon_WinPrint( const char *pMsg )
|
||||
{
|
||||
size_t len = Q_strlen( pMsg );
|
||||
|
||||
// replace selection instead of appending if we're overflowing
|
||||
s_wcd.outLen += len;
|
||||
if( s_wcd.outLen >= 0x7fff )
|
||||
int nLen;
|
||||
if( s_wcd.consoleTextLen )
|
||||
{
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
||||
s_wcd.outLen = len;
|
||||
nLen = s_wcd.consoleTextLen;
|
||||
while (nLen--)
|
||||
{
|
||||
Wcon_PrintInternal( "\b \b", 0 );
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM)pMsg );
|
||||
Wcon_PrintInternal( pMsg, 0 );
|
||||
|
||||
// put this text into the windows console
|
||||
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
|
||||
if( s_wcd.consoleTextLen )
|
||||
{
|
||||
Wcon_PrintInternal( s_wcd.consoleText, s_wcd.consoleTextLen );
|
||||
}
|
||||
|
||||
Wcon_UpdateStatusLine();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_CreateConsole
|
||||
@ -260,107 +494,38 @@ create win32 console
|
||||
*/
|
||||
void Wcon_CreateConsole( void )
|
||||
{
|
||||
HDC hDC;
|
||||
WNDCLASS wc;
|
||||
RECT rect;
|
||||
int nHeight;
|
||||
int swidth, sheight, fontsize;
|
||||
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION;
|
||||
int CONSTYLE = WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_BORDER|WS_EX_CLIENTEDGE|ES_LEFT|ES_MULTILINE|ES_AUTOVSCROLL|ES_READONLY;
|
||||
string FontName;
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = (WNDPROC)Wcon_WndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = host.hInst;
|
||||
wc.hIcon = LoadIcon( host.hInst, MAKEINTRESOURCE( IDI_ICON1 ));
|
||||
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wc.hbrBackground = (void *)COLOR_3DSHADOW;
|
||||
wc.lpszClassName = SYSCONSOLE;
|
||||
wc.lpszMenuName = 0;
|
||||
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
s_wcd.log_active = true;
|
||||
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
rect.left = 0;
|
||||
rect.right = 536;
|
||||
rect.top = 0;
|
||||
rect.bottom = 364;
|
||||
Q_strncpy( FontName, "Fixedsys", sizeof( FontName ));
|
||||
Q_strncpy( s_wcd.title, va( "Xash3D %s", XASH_VERSION ), sizeof( s_wcd.title ));
|
||||
Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path ));
|
||||
fontsize = 8;
|
||||
}
|
||||
else // dedicated console
|
||||
{
|
||||
rect.left = 0;
|
||||
rect.right = 640;
|
||||
rect.top = 0;
|
||||
rect.bottom = 392;
|
||||
Q_strncpy( FontName, "System", sizeof( FontName ));
|
||||
Q_strncpy( s_wcd.title, va( "XashDS %s", XASH_VERSION ), sizeof( s_wcd.title ));
|
||||
Q_strncpy( s_wcd.log_path, "dedicated.log", sizeof( s_wcd.log_path ));
|
||||
s_wcd.log_active = true; // always make log
|
||||
fontsize = 14;
|
||||
}
|
||||
|
||||
if( !RegisterClass( &wc ))
|
||||
AllocConsole();
|
||||
SetConsoleTitle( s_wcd.title );
|
||||
SetConsoleCP( CP_UTF8 );
|
||||
SetConsoleOutputCP( CP_UTF8 );
|
||||
|
||||
s_wcd.hWnd = GetConsoleWindow();
|
||||
s_wcd.hInput = GetStdHandle( STD_INPUT_HANDLE );
|
||||
s_wcd.hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||
s_wcd.inputEnabled = true;
|
||||
|
||||
if( !SetConsoleCtrlHandler( &Wcon_HandleConsole, TRUE ))
|
||||
{
|
||||
// print into log
|
||||
Con_Reportf( S_ERROR "Can't register window class '%s'\n", SYSCONSOLE );
|
||||
Con_Reportf( S_ERROR "Couldn't attach console handler function\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
swidth = GetDeviceCaps( hDC, HORZRES );
|
||||
sheight = GetDeviceCaps( hDC, VERTRES );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
|
||||
s_wcd.windowWidth = rect.right - rect.left;
|
||||
s_wcd.windowHeight = rect.bottom - rect.top;
|
||||
|
||||
s_wcd.hWnd = CreateWindowEx( WS_EX_DLGMODALFRAME, SYSCONSOLE, s_wcd.title, DEDSTYLE, ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1, NULL, NULL, host.hInst, NULL );
|
||||
if( s_wcd.hWnd == NULL )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Can't create window '%s'\n", s_wcd.title );
|
||||
return;
|
||||
}
|
||||
|
||||
// create fonts
|
||||
hDC = GetDC( s_wcd.hWnd );
|
||||
nHeight = -MulDiv( fontsize, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
|
||||
s_wcd.hfBufferFont = CreateFont( nHeight, 0, 0, 0, FW_LIGHT, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN|FIXED_PITCH, FontName );
|
||||
ReleaseDC( s_wcd.hWnd, hDC );
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
// create the input line
|
||||
s_wcd.hwndInputLine = CreateWindowEx( WS_EX_CLIENTEDGE, "edit", NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL, 0, 366, 550, 25, s_wcd.hWnd, (HMENU)INPUT_ID, host.hInst, NULL );
|
||||
|
||||
s_wcd.hwndButtonSubmit = CreateWindow( "button", NULL, BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 552, 367, 87, 25, s_wcd.hWnd, (HMENU)SUBMIT_ID, host.hInst, NULL );
|
||||
SendMessage( s_wcd.hwndButtonSubmit, WM_SETTEXT, 0, ( LPARAM ) "submit" );
|
||||
}
|
||||
|
||||
// create the scrollbuffer
|
||||
GetClientRect( s_wcd.hWnd, &rect );
|
||||
|
||||
s_wcd.hwndBuffer = CreateWindowEx( WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE, "edit", NULL, CONSTYLE, 0, 0, rect.right - rect.left, Q_min(365, rect.bottom), s_wcd.hWnd, (HMENU)EDIT_ID, host.hInst, NULL );
|
||||
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, (WPARAM)s_wcd.hfBufferFont, 0 );
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
s_wcd.SysInputLineWndProc = (WNDPROC)SetWindowLongPtr( s_wcd.hwndInputLine, GWLP_WNDPROC, (LONG_PTR)Wcon_InputLineProc );
|
||||
#else
|
||||
s_wcd.SysInputLineWndProc = (WNDPROC)SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, (long)Wcon_InputLineProc );
|
||||
#endif
|
||||
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM )s_wcd.hfBufferFont, 0 );
|
||||
}
|
||||
SetWindowPos( s_wcd.hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_SHOWWINDOW );
|
||||
|
||||
// show console if needed
|
||||
if( host.con_showalways )
|
||||
@ -369,13 +534,11 @@ void Wcon_CreateConsole( void )
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT );
|
||||
UpdateWindow( s_wcd.hWnd );
|
||||
SetForegroundWindow( s_wcd.hWnd );
|
||||
|
||||
if( host.type != HOST_DEDICATED )
|
||||
SetFocus( s_wcd.hWnd );
|
||||
else SetFocus( s_wcd.hwndInputLine );
|
||||
s_wcd.status = true;
|
||||
SetFocus( s_wcd.hWnd );
|
||||
s_wcd.consoleVisible = true;
|
||||
}
|
||||
else s_wcd.status = false;
|
||||
else
|
||||
s_wcd.consoleVisible = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -387,7 +550,9 @@ register console commands (dedicated only)
|
||||
*/
|
||||
void Wcon_InitConsoleCommands( void )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED ) return;
|
||||
if( host.type != HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
|
||||
}
|
||||
|
||||
@ -407,33 +572,15 @@ void Wcon_DestroyConsole( void )
|
||||
|
||||
if( s_wcd.hWnd )
|
||||
{
|
||||
DeleteObject( s_wcd.hbrEditBackground );
|
||||
DeleteObject( s_wcd.hfBufferFont );
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
ShowWindow( s_wcd.hwndButtonSubmit, SW_HIDE );
|
||||
DestroyWindow( s_wcd.hwndButtonSubmit );
|
||||
s_wcd.hwndButtonSubmit = 0;
|
||||
|
||||
ShowWindow( s_wcd.hwndInputLine, SW_HIDE );
|
||||
DestroyWindow( s_wcd.hwndInputLine );
|
||||
s_wcd.hwndInputLine = 0;
|
||||
}
|
||||
|
||||
ShowWindow( s_wcd.hwndBuffer, SW_HIDE );
|
||||
DestroyWindow( s_wcd.hwndBuffer );
|
||||
s_wcd.hwndBuffer = 0;
|
||||
|
||||
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
DestroyWindow( s_wcd.hWnd );
|
||||
s_wcd.hWnd = 0;
|
||||
}
|
||||
|
||||
UnregisterClass( SYSCONSOLE, host.hInst );
|
||||
FreeConsole();
|
||||
|
||||
// place it here in case Sys_Crash working properly
|
||||
if( host.hMutex ) CloseHandle( host.hMutex );
|
||||
if( host.hMutex )
|
||||
CloseHandle( host.hMutex );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -445,26 +592,57 @@ returned input text
|
||||
*/
|
||||
char *Wcon_Input( void )
|
||||
{
|
||||
if( s_wcd.consoleText[0] == 0 )
|
||||
int i;
|
||||
int eventsCount;
|
||||
static INPUT_RECORD events[1024];
|
||||
|
||||
if( !s_wcd.inputEnabled )
|
||||
return NULL;
|
||||
|
||||
Q_strncpy( s_wcd.returnedText, s_wcd.consoleText, sizeof( s_wcd.returnedText ));
|
||||
s_wcd.consoleText[0] = 0;
|
||||
while( true )
|
||||
{
|
||||
if( !GetNumberOfConsoleInputEvents( s_wcd.hInput, &eventsCount ))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s_wcd.returnedText;
|
||||
if( eventsCount <= 0 )
|
||||
break;
|
||||
|
||||
if( !ReadConsoleInputW( s_wcd.hInput, events, ARRAYSIZE( events ), &eventsCount ))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( eventsCount == 0 )
|
||||
return NULL;
|
||||
|
||||
for( i = 0; i < eventsCount; i++ )
|
||||
{
|
||||
INPUT_RECORD *pRec = &events[i];
|
||||
if( pRec->EventType != KEY_EVENT )
|
||||
continue;
|
||||
|
||||
if( pRec->Event.KeyEvent.bKeyDown )
|
||||
return Wcon_KeyEvent( pRec->Event.KeyEvent.wVirtualKeyCode, pRec->Event.KeyEvent.uChar.UnicodeChar );
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_SetFocus
|
||||
Wcon_SetStatus
|
||||
|
||||
change focus to console hwnd
|
||||
set server status string in console
|
||||
================
|
||||
*/
|
||||
void Wcon_RegisterHotkeys( void )
|
||||
void Wcon_SetStatus( const char *pStatus )
|
||||
{
|
||||
SetFocus( s_wcd.hWnd );
|
||||
if( host.type != HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
// user can hit escape for quit
|
||||
RegisterHotKey( s_wcd.hWnd, QUIT_ON_ESCAPE_ID, 0, VK_ESCAPE );
|
||||
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );
|
||||
s_wcd.statusLine[sizeof( s_wcd.statusLine ) - 2] = '\0';
|
||||
Wcon_UpdateStatusLine();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user