2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
23
#include "../client/client.h"
24
#include "win_local.h"
38
#define ERRORBOX_ID 10
39
#define ERRORTEXT_ID 11
57
HBITMAP hbmClearBitmap;
59
HBRUSH hbrEditBackground;
60
HBRUSH hbrErrorBackground;
69
char consoleText[512], returnedText[512];
72
int windowWidth, windowHeight;
74
WNDPROC SysInputLineWndProc;
78
static WinConData s_wcd;
80
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
83
static qboolean s_timePolarity;
88
if ( LOWORD( wParam ) != WA_INACTIVE )
90
SetFocus( s_wcd.hwndInputLine );
93
if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) )
95
// if the viewlog is open, check to see if it's being minimized
96
if ( com_viewlog->integer == 1 )
98
if ( HIWORD( wParam ) ) // minimized flag
100
Cvar_Set( "viewlog", "2" );
103
else if ( com_viewlog->integer == 2 )
105
if ( !HIWORD( wParam ) ) // minimized flag
107
Cvar_Set( "viewlog", "1" );
114
if ( ( com_dedicated && com_dedicated->integer ) )
116
cmdString = CopyString( "quit" );
117
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
119
else if ( s_wcd.quitOnClose )
121
PostQuitMessage( 0 );
125
Sys_ShowConsole( 0, qfalse );
126
Cvar_Set( "viewlog", "0" );
129
case WM_CTLCOLORSTATIC:
130
if ( ( HWND ) lParam == s_wcd.hwndBuffer )
132
SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0xB0 ) );
133
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) );
135
#if 0 // this draws a background in the edit box, but there are issues with this
136
if ( ( hdcScaled = CreateCompatibleDC( ( HDC ) wParam ) ) != 0 )
138
if ( SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo ) )
140
StretchBlt( ( HDC ) wParam, 0, 0, 512, 384,
141
hdcScaled, 0, 0, 512, 384,
144
DeleteDC( hdcScaled );
147
return ( long ) s_wcd.hbrEditBackground;
149
else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
151
if ( s_timePolarity & 1 )
153
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
154
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x0, 0x00 ) );
158
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
159
SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) );
161
return ( long ) s_wcd.hbrErrorBackground;
166
if ( wParam == COPY_ID )
168
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
169
SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
171
else if ( wParam == QUIT_ID )
173
if ( s_wcd.quitOnClose )
175
PostQuitMessage( 0 );
179
cmdString = CopyString( "quit" );
180
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
183
else if ( wParam == CLEAR_ID )
185
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
186
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
187
UpdateWindow( s_wcd.hwndBuffer );
191
// s_wcd.hbmLogo = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP1 ) );
192
// s_wcd.hbmClearBitmap = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP2 ) );
193
s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0xB0 ) );
194
s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
195
SetTimer( hWnd, 1, 1000, NULL );
202
#if 1 // a single, large image
203
hdcScaled = CreateCompatibleDC( ( HDC ) wParam );
204
assert( hdcScaled != 0 );
208
oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo );
209
assert( oldObject != 0 );
212
StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight,
213
hdcScaled, 0, 0, 512, 384,
216
DeleteDC( hdcScaled );
219
#else // a repeating brush
221
HBRUSH hbrClearBrush;
224
GetWindowRect( hWnd, &r );
226
r.bottom = r.bottom - r.top + 1;
227
r.right = r.right - r.left + 1;
231
hbrClearBrush = CreatePatternBrush( s_wcd.hbmClearBitmap );
233
assert( hbrClearBrush != 0 );
237
FillRect( ( HDC ) wParam, &r, hbrClearBrush );
238
DeleteObject( hbrClearBrush );
244
return DefWindowProc( hWnd, uMsg, wParam, lParam );
248
s_timePolarity = !s_timePolarity;
249
if ( s_wcd.hwndErrorBox )
251
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
257
return DefWindowProc( hWnd, uMsg, wParam, lParam );
260
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
262
char inputBuffer[1024];
267
if ( ( HWND ) wParam == s_wcd.hWnd ||
268
( HWND ) wParam == s_wcd.hwndErrorBox )
278
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
279
strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
280
strcat( s_wcd.consoleText, "\n" );
281
SetWindowText( s_wcd.hwndInputLine, "" );
283
Sys_Print( va( "]%s\n", inputBuffer ) );
289
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
295
void Sys_CreateConsole( void )
300
const char *DEDCLASS = "Q3 WinConsole";
303
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
305
memset( &wc, 0, sizeof( wc ) );
308
wc.lpfnWndProc = (WNDPROC) ConWndProc;
311
wc.hInstance = g_wv.hInstance;
312
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
313
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
314
wc.hbrBackground = (void *)COLOR_WINDOW;
316
wc.lpszClassName = DEDCLASS;
318
if ( !RegisterClass (&wc) )
325
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
327
hDC = GetDC( GetDesktopWindow() );
328
swidth = GetDeviceCaps( hDC, HORZRES );
329
sheight = GetDeviceCaps( hDC, VERTRES );
330
ReleaseDC( GetDesktopWindow(), hDC );
332
s_wcd.windowWidth = rect.right - rect.left + 1;
333
s_wcd.windowHeight = rect.bottom - rect.top + 1;
335
s_wcd.hWnd = CreateWindowEx( 0,
337
CONSOLE_WINDOW_TITLE,
339
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
345
if ( s_wcd.hWnd == NULL )
353
hDC = GetDC( s_wcd.hWnd );
354
nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
356
s_wcd.hfBufferFont = CreateFont( nHeight,
368
FF_MODERN | FIXED_PITCH,
371
ReleaseDC( s_wcd.hWnd, hDC );
374
// create the input line
376
s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
377
ES_LEFT | ES_AUTOHSCROLL,
380
( HMENU ) INPUT_ID, // child window ID
381
g_wv.hInstance, NULL );
384
// create the buttons
386
s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
389
( HMENU ) COPY_ID, // child window ID
390
g_wv.hInstance, NULL );
391
SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" );
393
s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
396
( HMENU ) CLEAR_ID, // child window ID
397
g_wv.hInstance, NULL );
398
SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" );
400
s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
403
( HMENU ) QUIT_ID, // child window ID
404
g_wv.hInstance, NULL );
405
SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" );
409
// create the scrollbuffer
411
s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
412
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
415
( HMENU ) EDIT_ID, // child window ID
416
g_wv.hInstance, NULL );
417
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
419
s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
420
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
422
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
423
UpdateWindow( s_wcd.hWnd );
424
SetForegroundWindow( s_wcd.hWnd );
425
SetFocus( s_wcd.hwndInputLine );
431
** Sys_DestroyConsole
433
void Sys_DestroyConsole( void ) {
435
ShowWindow( s_wcd.hWnd, SW_HIDE );
436
CloseWindow( s_wcd.hWnd );
437
DestroyWindow( s_wcd.hWnd );
445
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
447
s_wcd.quitOnClose = quitOnClose;
449
if ( visLevel == s_wcd.visLevel )
454
s_wcd.visLevel = visLevel;
462
ShowWindow( s_wcd.hWnd, SW_HIDE );
465
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
466
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
469
ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
472
Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
480
char *Sys_ConsoleInput( void )
482
if ( s_wcd.consoleText[0] == 0 )
487
strcpy( s_wcd.returnedText, s_wcd.consoleText );
488
s_wcd.consoleText[0] = 0;
490
return s_wcd.returnedText;
496
void Conbuf_AppendText( const char *pMsg )
498
#define CONSOLE_BUFFER_SIZE 16384
500
char buffer[CONSOLE_BUFFER_SIZE*2];
505
static unsigned long s_totalChars;
508
// if the message is REALLY long, use just the last portion of it
510
if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 )
512
msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
520
// copy into an intermediate buffer
522
while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) )
524
if ( msg[i] == '\n' && msg[i+1] == '\r' )
531
else if ( msg[i] == '\r' )
537
else if ( msg[i] == '\n' )
543
else if ( Q_IsColorString( &msg[i] ) )
557
s_totalChars += bufLen;
560
// replace selection instead of appending if we're overflowing
562
if ( s_totalChars > 0x7fff )
564
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
565
s_totalChars = bufLen;
569
// put this text into the windows console
571
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
572
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
573
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
579
void Sys_SetErrorText( const char *buf )
581
Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
583
if ( !s_wcd.hwndErrorBox )
585
s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
588
( HMENU ) ERRORBOX_ID, // child window ID
589
g_wv.hInstance, NULL );
590
SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
591
SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
593
DestroyWindow( s_wcd.hwndInputLine );
594
s_wcd.hwndInputLine = NULL;