mirror of
https://github.com/Q3Rally-Team/rallyunlimited-engine.git
synced 2024-11-26 06:01:34 +00:00
1161 lines
28 KiB
C
1161 lines
28 KiB
C
/*
|
|
===========================================================================
|
|
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
|
|
===========================================================================
|
|
*/
|
|
// win_syscon.h
|
|
#include "../client/client.h"
|
|
#include "win_local.h"
|
|
#include "resource.h"
|
|
|
|
#define COPY_ID 1
|
|
#define QUIT_ID 2
|
|
#define CLEAR_ID 3
|
|
#define ERROR_TIMER_ID 4
|
|
|
|
#define CON_TIMER_ID 5
|
|
#define BUF_TIMER_ID 6
|
|
#define TEX_TIMER_ID 7
|
|
|
|
#define ERRORBOX_ID 10
|
|
#define ERRORTEXT_ID 11
|
|
|
|
#define EDIT_ID 100
|
|
#define INPUT_ID 101
|
|
#define STATUS_ID 102
|
|
|
|
#define DEFAULT_WIDTH 600
|
|
#define DEFAULT_HEIGHT 434
|
|
|
|
#define BORDERW 1
|
|
#define BORDERH 2
|
|
|
|
#define INPUT_HEIGHT 16
|
|
#define ERROR_HEIGHT 27
|
|
|
|
#define MAX_CONSIZE 65536
|
|
|
|
#define T TEXT
|
|
|
|
#define EDIT_COLOR RGB(0x00,0x00,0x10)
|
|
#define TEXT_COLOR RGB(0x40,0xEE,0x20)
|
|
|
|
#define ERROR_BG_COLOR RGB(0x90,0x80,0x80)
|
|
|
|
#define ERROR_COLOR_1 RGB(0xFF,0xFF,0x00)
|
|
#define ERROR_COLOR_2 RGB(0xF0,0x00,0x00)
|
|
|
|
static field_t console;
|
|
|
|
typedef struct
|
|
{
|
|
HWND hWnd;
|
|
HWND hwndBuffer;
|
|
|
|
HWND hwndInputLine;
|
|
|
|
HWND hwndStatusBar;
|
|
HWND hwndButtonClear;
|
|
HWND hwndButtonCopy;
|
|
|
|
HWND hwndErrorBox;
|
|
|
|
HBRUSH hbrEditBackground;
|
|
HBRUSH hbrErrorBackground;
|
|
|
|
HFONT hfBufferFont;
|
|
HFONT hfStatusFont;
|
|
|
|
char consoleText[512];
|
|
char returnedText[512];
|
|
|
|
int visLevel;
|
|
qboolean quitOnClose;
|
|
int windowWidth, windowHeight;
|
|
|
|
LONG_PTR SysInputLineWndProc;
|
|
LONG_PTR SysStatusWndProc;
|
|
LONG_PTR SysBufferWndProc;
|
|
|
|
qboolean newline;
|
|
|
|
} WinConData;
|
|
|
|
static WinConData s_wcd;
|
|
|
|
static int maxConSize; // up to MAX_CONSIZE
|
|
static int curConSize; // up to MAX_CONSIZE
|
|
|
|
static UINT texTimerID; // for flushing text in buffer
|
|
|
|
static char conBuffer[ MAXPRINTMSG ];
|
|
static int conBufPos;
|
|
|
|
static void AddBufferText( const char *text, int textLength );
|
|
|
|
static void ConClear( void )
|
|
{
|
|
//SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
|
//SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
|
|
SetWindowText( s_wcd.hwndBuffer, T("") );
|
|
UpdateWindow( s_wcd.hwndBuffer );
|
|
s_wcd.newline = qfalse;
|
|
curConSize = 0;
|
|
conBufPos = 0;
|
|
}
|
|
|
|
static int GetStatusBarHeight( void )
|
|
{
|
|
RECT rect;
|
|
|
|
if ( !s_wcd.hwndStatusBar )
|
|
return 22;
|
|
|
|
GetClientRect( s_wcd.hwndStatusBar, &rect );
|
|
|
|
return (rect.bottom-rect.top+1);
|
|
}
|
|
|
|
|
|
static int GetTimerMsec( void )
|
|
{
|
|
int msec;
|
|
if ( !com_sv_running || !com_sv_running->integer ) {
|
|
msec = 50; // 20fps
|
|
} else {
|
|
msec = 1000 / Cvar_VariableIntegerValue( "sv_fps" );
|
|
}
|
|
#ifndef DEDICATED
|
|
if ( com_cl_running && com_cl_running->integer ) {
|
|
if ( com_maxfps->integer ) {
|
|
msec = 1000 / com_maxfps->integer;
|
|
}
|
|
if ( Cvar_VariableIntegerValue( "com_maxfpsUnfocused" ) ) {
|
|
msec = 1000 / Cvar_VariableIntegerValue( "com_maxfpsUnfocused" );
|
|
}
|
|
if ( gw_minimized || CL_VideoRecording() ) {
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
return msec;
|
|
}
|
|
|
|
|
|
static LRESULT WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
char *cmdString;
|
|
static qboolean s_timePolarity;
|
|
static UINT conTimerID;
|
|
int v;
|
|
|
|
switch ( uMsg )
|
|
{
|
|
|
|
case WM_SETFOCUS:
|
|
if ( s_wcd.hwndInputLine )
|
|
{
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
}
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) )
|
|
{
|
|
// if the viewlog is open, check to see if it's being minimized
|
|
if ( com_viewlog->integer == 1 )
|
|
{
|
|
if ( HIWORD( wParam ) ) // minimized flag
|
|
{
|
|
Cvar_Set( "viewlog", "2" );
|
|
}
|
|
}
|
|
else if ( com_viewlog->integer == 2 )
|
|
{
|
|
if ( !HIWORD( wParam ) ) // minimized flag
|
|
{
|
|
Cvar_Set( "viewlog", "1" );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_QUERYENDSESSION:
|
|
if ( com_dedicated && com_dedicated->integer && !com_errorEntered )
|
|
{
|
|
cmdString = CopyString( "quit" );
|
|
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
|
|
}
|
|
else
|
|
{
|
|
PostQuitMessage( 0 );
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_CLOSE:
|
|
if ( com_dedicated && com_dedicated->integer && !com_errorEntered )
|
|
{
|
|
cmdString = CopyString( "quit" );
|
|
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
|
|
}
|
|
else if ( s_wcd.quitOnClose )
|
|
{
|
|
PostQuitMessage( 0 );
|
|
}
|
|
else
|
|
{
|
|
Sys_ShowConsole( 0, qfalse );
|
|
Cvar_Set( "viewlog", "0" );
|
|
}
|
|
return 0;
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
if ( ( HWND ) lParam == s_wcd.hwndBuffer )
|
|
{
|
|
SetBkColor( ( HDC ) wParam, EDIT_COLOR );
|
|
SetTextColor( ( HDC ) wParam, TEXT_COLOR );
|
|
return ( LRESULT ) s_wcd.hbrEditBackground;
|
|
}
|
|
else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
|
|
{
|
|
if ( s_timePolarity & 1 )
|
|
{
|
|
SetBkColor( ( HDC ) wParam, ERROR_BG_COLOR );
|
|
SetTextColor( ( HDC ) wParam, ERROR_COLOR_1 );
|
|
}
|
|
else
|
|
{
|
|
SetBkColor( ( HDC ) wParam, ERROR_BG_COLOR );
|
|
SetTextColor( ( HDC ) wParam, ERROR_COLOR_2 );
|
|
}
|
|
return ( LRESULT ) s_wcd.hbrErrorBackground;
|
|
}
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
s_wcd.hbrEditBackground = CreateSolidBrush( EDIT_COLOR );
|
|
GetWindowRect( hWnd, &g_wv.conRect );
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
GetWindowRect( hWnd, &g_wv.conRect );
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
RECT rect;
|
|
int sth;
|
|
|
|
sth = GetStatusBarHeight();
|
|
GetClientRect( hWnd, &rect );
|
|
|
|
s_wcd.windowWidth = rect.right - rect.left + 1;
|
|
s_wcd.windowHeight = rect.bottom - rect.top + 1;
|
|
|
|
if ( s_wcd.hwndErrorBox ) {
|
|
SetWindowPos( s_wcd.hwndBuffer, HWND_TOP, BORDERW, ERROR_HEIGHT + BORDERH*2, rect.right - BORDERW*2, rect.bottom - sth - ERROR_HEIGHT - BORDERH*3 + 1, SWP_NOZORDER );
|
|
} else {
|
|
SetWindowPos( s_wcd.hwndBuffer, HWND_TOP, BORDERW, BORDERH, rect.right - BORDERW*2, rect.bottom - sth - INPUT_HEIGHT - BORDERH*3 - 2, SWP_NOZORDER );
|
|
}
|
|
|
|
if ( s_wcd.hwndErrorBox ) {
|
|
SetWindowPos( s_wcd.hwndErrorBox, HWND_TOP, BORDERW, BORDERH, rect.right - BORDERW*2, ERROR_HEIGHT, SWP_NOZORDER );
|
|
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
|
|
}
|
|
|
|
if ( s_wcd.hwndInputLine ) {
|
|
SetWindowPos( s_wcd.hwndInputLine, HWND_TOP, BORDERW, rect.bottom - sth - INPUT_HEIGHT - BORDERH, rect.right - BORDERW*2, INPUT_HEIGHT, SWP_NOZORDER );
|
|
InvalidateRect( s_wcd.hwndInputLine, NULL, FALSE );
|
|
}
|
|
|
|
if ( s_wcd.hwndStatusBar ) {
|
|
SetWindowPos( s_wcd.hwndStatusBar, HWND_TOP, BORDERW, rect.bottom, rect.right - BORDERW*2, 26, SWP_NOZORDER );
|
|
InvalidateRect( s_wcd.hwndStatusBar, NULL, FALSE );
|
|
}
|
|
|
|
GetWindowRect( hWnd, &g_wv.conRect );
|
|
|
|
return 0;
|
|
}
|
|
|
|
case WM_SIZING:
|
|
{
|
|
int w, h;
|
|
RECT *r;
|
|
r = (LPRECT) lParam;
|
|
w = r->right - r->left - 280+BORDERW*2 + 1;
|
|
h = r->bottom - r->top - 155+BORDERH*3 + 1;
|
|
if ( w < 0 ) {
|
|
if ( wParam == WMSZ_RIGHT || wParam == WMSZ_TOPRIGHT || wParam == WMSZ_BOTTOMRIGHT ) {
|
|
r->right -= w;
|
|
}
|
|
if ( wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT ) {
|
|
r->left += w;
|
|
}
|
|
}
|
|
if ( h < 0 ) {
|
|
if ( wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT ) {
|
|
r->bottom -= h;
|
|
}
|
|
if ( wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT ) {
|
|
r->top += h;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_SYSCOMMAND:
|
|
// Prevent Alt+Letter commands from hanging the application temporarily
|
|
if ( wParam == SC_KEYMENU || wParam == SC_MOUSEMENU + HTSYSMENU || wParam == SC_CLOSE + HTSYSMENU )
|
|
return 0;
|
|
|
|
// simulate drag move to avoid ~500ms delay between DefWindowProc() and further WM_ENTERSIZEMOVE
|
|
if ( wParam == SC_MOVE + HTCAPTION )
|
|
{
|
|
mouse_event( MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN, 7, 0, 0, 0 );
|
|
mouse_event( MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN, (DWORD)-7, 0, 0, 0 );
|
|
}
|
|
break;
|
|
|
|
case WM_ENTERSIZEMOVE:
|
|
if ( conTimerID == 0 && (v = GetTimerMsec()) > 0 ) {
|
|
conTimerID = SetTimer( s_wcd.hWnd, CON_TIMER_ID, v, NULL );
|
|
}
|
|
break;
|
|
|
|
case WM_EXITSIZEMOVE:
|
|
if ( conTimerID != 0 ) {
|
|
KillTimer( s_wcd.hWnd, conTimerID );
|
|
conTimerID = 0;
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if ( wParam == ERROR_TIMER_ID )
|
|
{
|
|
s_timePolarity = !s_timePolarity;
|
|
if ( s_wcd.hwndErrorBox )
|
|
{
|
|
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
|
|
}
|
|
}
|
|
else if ( wParam == CON_TIMER_ID && conTimerID != 0 && !com_errorEntered )
|
|
{
|
|
#ifdef DEDICATED
|
|
Com_Frame( qfalse );
|
|
#else
|
|
//Com_Frame( CL_NoDelay() );
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
static LRESULT WINAPI BufferWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
static UINT bufTimerID;
|
|
int v;
|
|
|
|
switch ( uMsg ) {
|
|
|
|
case WM_VSCROLL:
|
|
if ( (int)LOWORD(wParam) == SB_ENDSCROLL ) {
|
|
if ( bufTimerID != 0 ) {
|
|
KillTimer( hWnd, bufTimerID );
|
|
bufTimerID = 0;
|
|
}
|
|
} else {
|
|
if ( bufTimerID == 0 && (v = GetTimerMsec()) > 0 ) {
|
|
bufTimerID = SetTimer( hWnd, BUF_TIMER_ID, v, NULL );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CAPTURECHANGED:
|
|
if ( (HWND)lParam == hWnd ) {
|
|
if ( bufTimerID == 0 && (v = GetTimerMsec()) > 0 )
|
|
bufTimerID = SetTimer( hWnd, BUF_TIMER_ID, v, NULL );
|
|
} else {
|
|
if ( bufTimerID != 0 ) {
|
|
KillTimer( hWnd, bufTimerID );
|
|
bufTimerID = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
#if 0 // this is actually redundant except setting focus to s_wcd.hwndInputLine
|
|
case WM_COPY: {
|
|
DWORD selStart, selEnd;
|
|
SendMessage( hWnd, EM_GETSEL, (WPARAM)&selStart, (LPARAM)&selEnd );
|
|
if ( selStart != selEnd ) {
|
|
if ( OpenClipboard( s_wcd.hWnd ) ) {
|
|
int len;
|
|
HGLOBAL hMem;
|
|
TCHAR *text, *tmp;
|
|
len = GetWindowTextLength( s_wcd.hwndBuffer ) + 1;
|
|
tmp = (TCHAR*) malloc( len * sizeof( TCHAR ) );
|
|
if ( tmp ) {
|
|
GetWindowText( s_wcd.hwndBuffer, tmp, len );
|
|
hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, ( selEnd - selStart + 1 ) * sizeof( TCHAR ) );
|
|
if ( hMem != NULL ) {
|
|
EmptyClipboard();
|
|
text = (TCHAR*) GlobalLock( hMem );
|
|
if ( text != NULL ) {
|
|
memcpy( text, tmp + selStart, ( selEnd - selStart ) * sizeof( text[0] ) );
|
|
}
|
|
GlobalUnlock( hMem );
|
|
#ifdef UNICODE
|
|
SetClipboardData( CF_UNICODETEXT, hMem );
|
|
#else
|
|
SetClipboardData( CF_TEXT, hMem );
|
|
#endif
|
|
}
|
|
free( tmp );
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
if ( s_wcd.hwndInputLine ) {
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case WM_TIMER:
|
|
if ( wParam == BUF_TIMER_ID && bufTimerID != 0 && !com_errorEntered )
|
|
{
|
|
#ifdef DEDICATED
|
|
Com_Frame( qfalse );
|
|
#else
|
|
//Com_Frame( CL_NoDelay() );
|
|
#endif
|
|
}
|
|
if ( wParam == TEX_TIMER_ID && texTimerID != 0 ) {
|
|
if ( conBufPos ) {
|
|
// dump text
|
|
AddBufferText( conBuffer, conBufPos );
|
|
conBufPos = 0;
|
|
} else {
|
|
// kill timer
|
|
KillTimer( hWnd, texTimerID );
|
|
texTimerID = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case WM_CONTEXTMENU:
|
|
return 0;
|
|
|
|
case WM_CHAR: {
|
|
if ( wParam != VK_CANCEL ) {
|
|
// forward to input line
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
SendMessage( s_wcd.hwndInputLine, WM_CHAR, wParam, lParam );
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc( (WNDPROC) s_wcd.SysBufferWndProc, hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
static LRESULT WINAPI StatusWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HGLOBAL hMem;
|
|
TCHAR *text;
|
|
int len;
|
|
|
|
switch (uMsg)
|
|
{
|
|
|
|
case WM_COMMAND:
|
|
if ( wParam == COPY_ID )
|
|
{
|
|
if ( OpenClipboard( s_wcd.hWnd ) )
|
|
{
|
|
EmptyClipboard();
|
|
len = GetWindowTextLength( s_wcd.hwndBuffer );
|
|
if ( len > 0 ) {
|
|
hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT,
|
|
(len + 1) * sizeof( TCHAR ) );
|
|
if ( hMem != NULL ) {
|
|
text = ( TCHAR* )GlobalLock( hMem );
|
|
if ( text != NULL ) {
|
|
GetWindowText( s_wcd.hwndBuffer, text, len + 1 );
|
|
}
|
|
GlobalUnlock( hMem );
|
|
#ifdef UNICODE
|
|
SetClipboardData( CF_UNICODETEXT, hMem );
|
|
#else
|
|
SetClipboardData( CF_TEXT, hMem );
|
|
#endif
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
if ( s_wcd.hwndInputLine ) {
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
}
|
|
}
|
|
else if ( wParam == CLEAR_ID )
|
|
{
|
|
ConClear();
|
|
if ( s_wcd.hwndInputLine ) {
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
}
|
|
}
|
|
break;
|
|
case WM_LBUTTONDBLCLK:
|
|
case WM_LBUTTONDOWN:
|
|
if ( s_wcd.hwndInputLine ) {
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
}
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc( (WNDPROC)s_wcd.SysStatusWndProc, hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
static LRESULT WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
TCHAR inputBuffer[ MAX_EDIT_LINE ];
|
|
int zDelta, fwKeys, i;
|
|
WPARAM scrollMsg;
|
|
|
|
switch ( uMsg )
|
|
{
|
|
#if 0
|
|
case WM_KILLFOCUS:
|
|
if ( (HWND)wParam == s_wcd.hwndBuffer ) {
|
|
SetFocus( s_wcd.hwndInputLine );
|
|
return 0;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case WM_MOUSEWHEEL:
|
|
zDelta = (short) HIWORD( wParam ) / WHEEL_DELTA;
|
|
if ( zDelta ) {
|
|
fwKeys = LOWORD( wParam );
|
|
if ( zDelta > 0 ) {
|
|
if ( fwKeys & MK_CONTROL )
|
|
scrollMsg = SB_PAGEUP;
|
|
else
|
|
scrollMsg = SB_LINEUP;
|
|
} else {
|
|
zDelta = -zDelta;
|
|
if ( fwKeys & MK_CONTROL )
|
|
scrollMsg = SB_PAGEDOWN;
|
|
else
|
|
scrollMsg = SB_LINEDOWN;
|
|
}
|
|
for ( i = 0; i < zDelta; i++ ) {
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLL, scrollMsg, 0 );
|
|
}
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
{
|
|
if ( wParam == 'L' && ( GetAsyncKeyState( VK_LCONTROL ) & 0x8000 || GetAsyncKeyState( VK_RCONTROL ) & 0x8000 ) ) {
|
|
ConClear();
|
|
return 0;
|
|
}
|
|
|
|
if ( wParam == VK_PRIOR ) {
|
|
if ( GetAsyncKeyState( VK_LCONTROL ) & 0x8000 || GetAsyncKeyState( VK_RCONTROL ) & 0x8000 )
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLL, (WPARAM)SB_PAGEUP, 0 );
|
|
else
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLL, (WPARAM)SB_LINEUP, 0 );
|
|
return 0;
|
|
}
|
|
|
|
if ( wParam == VK_NEXT ) {
|
|
if ( GetAsyncKeyState( VK_LCONTROL ) & 0x8000 || GetAsyncKeyState( VK_RCONTROL ) & 0x8000 )
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLL, (WPARAM)SB_PAGEDOWN, 0 );
|
|
else
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLL, (WPARAM)SB_LINEDOWN, 0 );
|
|
return 0;
|
|
}
|
|
|
|
if ( wParam == VK_UP ) {
|
|
Con_HistoryGetPrev( &console );
|
|
SetWindowText( hWnd, AtoW( console.buffer ) );
|
|
SendMessage( hWnd, EM_SETSEL, (WPARAM) console.cursor, console.cursor );
|
|
return 0;
|
|
}
|
|
|
|
if ( wParam == VK_DOWN ) {
|
|
Con_HistoryGetNext( &console );
|
|
SetWindowText( hWnd, AtoW( console.buffer ) );
|
|
SendMessage( hWnd, EM_SETSEL, (WPARAM) console.cursor, console.cursor );
|
|
return 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_CHAR:
|
|
if ( wParam > 255 )
|
|
return 0;
|
|
if ( wParam == VK_RETURN )
|
|
{
|
|
DWORD pos;
|
|
char *s;
|
|
|
|
GetWindowText( hWnd, inputBuffer, sizeof( inputBuffer ) );
|
|
Q_strncpyz( console.buffer, WtoA( inputBuffer ), sizeof( console.buffer ) );
|
|
SendMessage( hWnd, EM_GETSEL, (WPARAM) &pos, (LPARAM) 0 );
|
|
console.cursor = pos;
|
|
Con_SaveField( &console );
|
|
|
|
s = console.buffer;
|
|
|
|
while ( *s == '\\' || *s == '/' ) // skip leading slashes
|
|
s++;
|
|
|
|
strncat( s_wcd.consoleText, s, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 2 );
|
|
strcat( s_wcd.consoleText, "\n" );
|
|
|
|
SetWindowText( s_wcd.hwndInputLine, T("") );
|
|
Field_Clear( &console );
|
|
|
|
Sys_Print( va( "]%s\n", WtoA( inputBuffer ) ) );
|
|
|
|
return 0;
|
|
}
|
|
|
|
if ( wParam == VK_TAB ) {
|
|
DWORD pos;
|
|
|
|
GetWindowText( hWnd, inputBuffer, sizeof( inputBuffer ) );
|
|
Q_strncpyz( console.buffer, WtoA( inputBuffer ), sizeof( console.buffer ) );
|
|
SendMessage( hWnd, EM_GETSEL, (WPARAM) &pos, (LPARAM) 0 );
|
|
console.cursor = pos;
|
|
|
|
Field_AutoComplete( &console );
|
|
|
|
SetWindowText( hWnd, AtoW( console.buffer ) );
|
|
SendMessage( hWnd, EM_SETSEL, console.cursor, console.cursor );
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
return 0;
|
|
}
|
|
|
|
return CallWindowProc( (WNDPROC)s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
/*
|
|
** Sys_CreateConsole
|
|
*/
|
|
void Sys_CreateConsole( const char *title, int xPos, int yPos, qboolean useXYpos )
|
|
{
|
|
HDC hDC;
|
|
WNDCLASS wc;
|
|
RECT rect;
|
|
const TCHAR *DEDCLASS = T("Q3 WinConsole");
|
|
|
|
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX;
|
|
int fontWidth, fontHeight, statusFontHeight;
|
|
int widths[2] = { 140, -1 };
|
|
int borders[3];
|
|
int x, y, w, h, sth;
|
|
int con_x, con_y;
|
|
|
|
HMONITOR hMonitor;
|
|
MONITORINFO mInfo;
|
|
POINT p;
|
|
|
|
memset( &wc, 0, sizeof( wc ) );
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = ConWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = g_wv.hInstance;
|
|
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
|
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(LRESULT)COLOR_WINDOW;
|
|
wc.lpszMenuName = 0;
|
|
wc.lpszClassName = DEDCLASS;
|
|
|
|
if ( !RegisterClass (&wc) )
|
|
return;
|
|
|
|
rect.left = 0;
|
|
rect.right = DEFAULT_WIDTH;
|
|
rect.top = 0;
|
|
rect.bottom = DEFAULT_HEIGHT;
|
|
|
|
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
|
|
|
|
// try to use command line provided coodinates to locate primary monitor
|
|
if ( useXYpos ) {
|
|
p.x = xPos;
|
|
p.y = yPos;
|
|
} else {
|
|
GetCursorPos( &p );
|
|
}
|
|
|
|
memset( &mInfo, 0, sizeof( mInfo ) );
|
|
mInfo.cbSize = sizeof( MONITORINFO );
|
|
// Query display dimensions
|
|
hMonitor = MonitorFromPoint( p, MONITOR_DEFAULTTONEAREST );
|
|
if ( hMonitor && GetMonitorInfo( hMonitor, &mInfo ) ) {
|
|
// current monitor info
|
|
w = mInfo.rcMonitor.right - mInfo.rcMonitor.left;
|
|
h = mInfo.rcMonitor.bottom - mInfo.rcMonitor.top;
|
|
x = mInfo.rcMonitor.left;
|
|
y = mInfo.rcMonitor.top;
|
|
} else {
|
|
// primary display info
|
|
hDC = GetDC( GetDesktopWindow() );
|
|
w = GetDeviceCaps( hDC, HORZRES );
|
|
h = GetDeviceCaps( hDC, VERTRES );
|
|
x = 0;
|
|
y = 0;
|
|
ReleaseDC( GetDesktopWindow(), hDC );
|
|
}
|
|
|
|
fontWidth = -8;
|
|
fontHeight = -12;
|
|
statusFontHeight = -11;
|
|
|
|
s_wcd.windowWidth = rect.right - rect.left + 1;
|
|
s_wcd.windowHeight = rect.bottom - rect.top + 1;
|
|
|
|
#ifdef DEDICATED
|
|
if ( useXYpos )
|
|
{
|
|
con_x = xPos;
|
|
con_y = yPos;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
con_x = x + ( w - s_wcd.windowWidth ) / 2;
|
|
con_y = y + ( h - s_wcd.windowHeight ) / 2;
|
|
}
|
|
|
|
s_wcd.hWnd = CreateWindowEx( 0, DEDCLASS,
|
|
T(CONSOLE_WINDOW_TITLE), DEDSTYLE, con_x, con_y,
|
|
s_wcd.windowWidth, s_wcd.windowHeight,
|
|
NULL, NULL, g_wv.hInstance, NULL );
|
|
|
|
if ( s_wcd.hWnd == NULL )
|
|
return;
|
|
|
|
InitCommonControls();
|
|
|
|
s_wcd.hfBufferFont = CreateFont( fontHeight, fontWidth,
|
|
0,
|
|
0,
|
|
FW_DONTCARE,
|
|
FALSE,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_CHARSET,
|
|
OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
DEFAULT_QUALITY,
|
|
FF_MODERN | FIXED_PITCH,
|
|
T("Terminal") );
|
|
|
|
s_wcd.hfStatusFont = CreateFont( statusFontHeight, 0,
|
|
0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
|
DEFAULT_CHARSET,
|
|
OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
DEFAULT_QUALITY,
|
|
DEFAULT_PITCH,
|
|
T("Tahoma") );
|
|
|
|
s_wcd.hwndStatusBar = CreateWindow( STATUSCLASSNAME, NULL, WS_VISIBLE | WS_CHILD,
|
|
1,1,32,32, s_wcd.hWnd, NULL, g_wv.hInstance, NULL );
|
|
|
|
// split statusbar into parts and set styles
|
|
SendMessage( s_wcd.hwndStatusBar, WM_SETFONT, ( WPARAM ) s_wcd.hfStatusFont, 0 );
|
|
SendMessage( s_wcd.hwndStatusBar, SB_GETBORDERS, 0, (LPARAM)&borders );
|
|
widths[0] += borders[1]*2; // count vertical borders
|
|
SendMessage( s_wcd.hwndStatusBar, SB_SETPARTS, 2, (LPARAM)&widths );
|
|
SendMessage( s_wcd.hwndStatusBar, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"" );
|
|
|
|
SendMessage( s_wcd.hwndStatusBar, SB_GETRECT, 0, (LPARAM)&rect );
|
|
rect.left += borders[1];
|
|
rect.right -= borders[1];
|
|
x = rect.left;
|
|
h = rect.bottom - rect.top - 1;
|
|
w = (rect.right - rect.left - 4) / 2;
|
|
|
|
// create the buttons
|
|
s_wcd.hwndButtonCopy = CreateWindow( T("button"), T("copy"), WS_VISIBLE | WS_CHILD,
|
|
x, rect.top, w, h, s_wcd.hwndStatusBar, (HMENU)(LRESULT)COPY_ID, g_wv.hInstance, NULL );
|
|
x += w + 4;
|
|
|
|
s_wcd.hwndButtonClear = CreateWindow( T("button"), T("clear"), WS_VISIBLE | WS_CHILD,
|
|
x, rect.top, w, h, s_wcd.hwndStatusBar, (HMENU)(LRESULT)CLEAR_ID, g_wv.hInstance, NULL );
|
|
|
|
SendMessage( s_wcd.hwndButtonCopy, WM_SETFONT, ( WPARAM ) s_wcd.hfStatusFont, 0 );
|
|
SendMessage( s_wcd.hwndButtonClear, WM_SETFONT, ( WPARAM ) s_wcd.hfStatusFont, 0 );
|
|
|
|
sth = GetStatusBarHeight();
|
|
GetClientRect( s_wcd.hWnd, &rect );
|
|
|
|
// create fonts
|
|
//hDC = GetDC( s_wcd.hWnd );
|
|
//nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY ), 72);
|
|
//ReleaseDC( s_wcd.hWnd, hDC );
|
|
|
|
// create the input line
|
|
s_wcd.hwndInputLine = CreateWindow( T("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
|
|
ES_LEFT | ES_AUTOHSCROLL,
|
|
BORDERW, rect.bottom - sth - INPUT_HEIGHT - BORDERH, rect.right - BORDERW*2, INPUT_HEIGHT,
|
|
s_wcd.hWnd,
|
|
(HMENU)(LRESULT)INPUT_ID, // child window ID
|
|
g_wv.hInstance, NULL );
|
|
|
|
// create the scrollbuffer
|
|
s_wcd.hwndBuffer = CreateWindow( T("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
|
|
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_NOHIDESEL,
|
|
BORDERW, BORDERH, rect.right - BORDERW*2, rect.bottom - sth - INPUT_HEIGHT - BORDERH*3 - 2,
|
|
s_wcd.hWnd,
|
|
(HMENU)(LRESULT)EDIT_ID, // child window ID
|
|
g_wv.hInstance, NULL );
|
|
|
|
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
|
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
|
|
|
s_wcd.SysInputLineWndProc = SetWindowLongPtr( s_wcd.hwndInputLine, GWLP_WNDPROC, ( LONG_PTR ) InputLineWndProc );
|
|
s_wcd.SysStatusWndProc = SetWindowLongPtr( s_wcd.hwndStatusBar, GWLP_WNDPROC, ( LONG_PTR ) StatusWndProc );
|
|
s_wcd.SysBufferWndProc = SetWindowLongPtr( s_wcd.hwndBuffer, GWLP_WNDPROC, ( LONG_PTR ) BufferWndProc );
|
|
|
|
if ( title && *title ) {
|
|
SetWindowText( s_wcd.hWnd, AtoW( title ) );
|
|
}
|
|
|
|
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT );
|
|
UpdateWindow( s_wcd.hWnd );
|
|
SetForegroundWindow( s_wcd.hWnd );
|
|
|
|
SendMessage( s_wcd.hwndBuffer, EM_SETLIMITTEXT, MAX_CONSIZE, 0 );
|
|
maxConSize = SendMessage( s_wcd.hwndBuffer, EM_GETLIMITTEXT, 0, 0 );
|
|
|
|
SendMessage( s_wcd.hwndInputLine, EM_SETLIMITTEXT, MAX_EDIT_LINE, 0 );
|
|
|
|
Field_Clear( &console );
|
|
|
|
ConClear();
|
|
|
|
Sys_SetStatus( "Server is not running" );
|
|
|
|
s_wcd.visLevel = 1;
|
|
}
|
|
|
|
|
|
/*
|
|
** Sys_DestroyConsole
|
|
*/
|
|
void Sys_DestroyConsole( void )
|
|
{
|
|
if ( s_wcd.hWnd )
|
|
{
|
|
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
|
CloseWindow( s_wcd.hWnd );
|
|
DestroyWindow( s_wcd.hWnd );
|
|
s_wcd.hWnd = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Sys_ShowConsole
|
|
*/
|
|
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
|
|
{
|
|
s_wcd.quitOnClose = quitOnClose;
|
|
|
|
if ( visLevel == s_wcd.visLevel )
|
|
{
|
|
return;
|
|
}
|
|
|
|
s_wcd.visLevel = visLevel;
|
|
|
|
if ( !s_wcd.hWnd )
|
|
return;
|
|
|
|
switch ( visLevel )
|
|
{
|
|
case 0:
|
|
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
|
break;
|
|
case 1:
|
|
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
|
|
curConSize = GetWindowTextLength( s_wcd.hwndBuffer );
|
|
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, curConSize, curConSize );
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
|
|
//SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
|
break;
|
|
case 2:
|
|
ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
|
|
break;
|
|
default:
|
|
Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
Sys_SetStatus
|
|
=============
|
|
*/
|
|
void QDECL Sys_SetStatus( const char *format, ... )
|
|
{
|
|
va_list argptr;
|
|
char text[256];
|
|
|
|
if ( s_wcd.hwndStatusBar == NULL )
|
|
return;
|
|
|
|
text[0] = ' '; // add leading space for better look :P
|
|
va_start( argptr, format );
|
|
Q_vsnprintf( text + 1, sizeof( text ) - 1, format, argptr );
|
|
va_end( argptr );
|
|
|
|
SendMessage( s_wcd.hwndStatusBar, SB_SETTEXT, (WPARAM) 1 | 0, (LPARAM) AtoW( text ) );
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Sys_ConsoleInput
|
|
=================
|
|
*/
|
|
char *Sys_ConsoleInput( void )
|
|
{
|
|
if ( s_wcd.consoleText[0] == '\0' )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
strcpy( s_wcd.returnedText, s_wcd.consoleText );
|
|
s_wcd.consoleText[0] = '\0';
|
|
|
|
return s_wcd.returnedText;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Conbuf_AppendText
|
|
=================
|
|
*/
|
|
void Conbuf_AppendText( const char *msg )
|
|
{
|
|
char buffer[MAXPRINTMSG*2]; // reserve space for CR-LF expansion
|
|
char *b = buffer;
|
|
int bufLen, n;
|
|
|
|
n = strlen( msg );
|
|
|
|
// if the message is REALLY long, use just the last portion of it
|
|
if ( n > (MAXPRINTMSG - 1) ) {
|
|
msg += n - (MAXPRINTMSG - 1);
|
|
}
|
|
|
|
// insert skipped newline from previous message
|
|
if ( s_wcd.newline ) {
|
|
s_wcd.newline = qfalse;
|
|
*b++ = '\r';
|
|
*b++ = '\n';
|
|
}
|
|
|
|
// copy into an intermediate buffer
|
|
while ( *msg )
|
|
{
|
|
if ( *msg == '\n' )
|
|
{
|
|
*b++ = '\r';
|
|
*b++ = '\n';
|
|
msg++;
|
|
}
|
|
else if ( *msg == '\r' )
|
|
{
|
|
*b++ = '\r';
|
|
*b++ = '\n';
|
|
msg++;
|
|
if ( *msg == '\n' )
|
|
msg++;
|
|
}
|
|
else if ( Q_IsColorString( msg ) )
|
|
{
|
|
msg += 2;
|
|
}
|
|
else
|
|
{
|
|
*b++ = *msg++;
|
|
}
|
|
}
|
|
|
|
// try to skip ending newline to avoid inserting empty line in edit control
|
|
if ( b - buffer >= 2 && *(b-1) == '\n' && *(b-2) == '\r' ) {
|
|
s_wcd.newline = qtrue;
|
|
b -= 2;
|
|
}
|
|
|
|
*b = '\0';
|
|
bufLen = b - buffer;
|
|
|
|
// not enough space in buffer -> flush
|
|
if ( bufLen + conBufPos >= sizeof( conBuffer )-1 ) {
|
|
AddBufferText( conBuffer, conBufPos );
|
|
conBufPos = 0;
|
|
}
|
|
|
|
// new message is too long -> flush
|
|
if ( bufLen >= sizeof( conBuffer )-1 ) {
|
|
if ( conBufPos ) {
|
|
AddBufferText( conBuffer, conBufPos );
|
|
conBufPos = 0;
|
|
}
|
|
AddBufferText( buffer, bufLen );
|
|
return;
|
|
}
|
|
|
|
// accumulate
|
|
memcpy( conBuffer + conBufPos, buffer, bufLen + 1 );
|
|
conBufPos += bufLen;
|
|
|
|
// set flush timer
|
|
if ( texTimerID == 0 ) {
|
|
texTimerID = SetTimer( s_wcd.hwndBuffer, TEX_TIMER_ID,
|
|
s_wcd.visLevel == 1 ? 25 : 100, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
static void AddBufferText( const char *text, int textLength )
|
|
{
|
|
int lineCount;
|
|
int pos, n;
|
|
|
|
if ( textLength + curConSize >= maxConSize ) {
|
|
lineCount = SendMessage( s_wcd.hwndBuffer, EM_GETLINECOUNT, 0, 0 );
|
|
// cut off half from total lines count
|
|
lineCount /= 2;
|
|
if ( lineCount <= 1 ) {
|
|
SetWindowText( s_wcd.hwndBuffer, T("") );
|
|
} else {
|
|
pos = SendMessage( s_wcd.hwndBuffer, EM_LINEINDEX, lineCount, 0 );
|
|
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, pos );
|
|
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, (LPARAM) TEXT("") );
|
|
}
|
|
curConSize = 0;
|
|
}
|
|
|
|
if ( !curConSize )
|
|
curConSize = GetWindowTextLength( s_wcd.hwndBuffer );
|
|
|
|
SendMessage( s_wcd.hwndBuffer, EM_GETSEL, (WPARAM)(LPDWORD)&pos, (LPARAM)(LPDWORD)&n );
|
|
if ( pos != curConSize || n != curConSize ) {
|
|
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, curConSize, curConSize );
|
|
}
|
|
|
|
// put this text into the windows console
|
|
//SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
|
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
|
|
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) AtoW( text ) );
|
|
|
|
curConSize += textLength;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** Sys_SetErrorText
|
|
*/
|
|
void Sys_SetErrorText( const char *buf )
|
|
{
|
|
RECT rect;
|
|
int sth;
|
|
|
|
if ( s_wcd.hwndErrorBox ) // already created
|
|
return;
|
|
|
|
// remove input field
|
|
DestroyWindow( s_wcd.hwndInputLine );
|
|
s_wcd.hwndInputLine = NULL;
|
|
|
|
EnableWindow( s_wcd.hwndButtonClear, FALSE );
|
|
|
|
s_wcd.hbrErrorBackground = CreateSolidBrush( ERROR_BG_COLOR );
|
|
SetTimer( s_wcd.hWnd, ERROR_TIMER_ID, 1000, NULL );
|
|
|
|
sth = GetStatusBarHeight();
|
|
GetClientRect( s_wcd.hWnd, &rect );
|
|
|
|
// shift buffer position
|
|
SetWindowPos( s_wcd.hwndBuffer, HWND_TOP, BORDERW, ERROR_HEIGHT + BORDERH*2, rect.right - BORDERW*2, rect.bottom - sth - ERROR_HEIGHT - BORDERH*3+1, SWP_NOZORDER );
|
|
|
|
s_wcd.hwndErrorBox = CreateWindow( T("static"), NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
|
|
BORDERW, BORDERH, rect.right - BORDERW*2, ERROR_HEIGHT,
|
|
s_wcd.hWnd,
|
|
(HMENU)(LRESULT)ERRORBOX_ID, // child window ID
|
|
g_wv.hInstance, NULL );
|
|
|
|
SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
|
SetWindowText( s_wcd.hwndErrorBox, AtoW( buf ) );
|
|
|
|
Sys_SetStatus( "Fatal error occurred" );
|
|
}
|
|
|
|
|
|
void HandleConsoleEvents( void ) {
|
|
MSG msg;
|
|
|
|
// pump the message loop
|
|
while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) {
|
|
if ( GetMessage( &msg, NULL, 0, 0 ) <= 0 ) {
|
|
Cmd_Clear();
|
|
Com_Quit_f();
|
|
}
|
|
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
}
|