Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

win_syscon.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // win_syscon.h
00023 #include "../client/client.h"
00024 #include "win_local.h"
00025 #include "resource.h"
00026 #include <errno.h>
00027 #include <float.h>
00028 #include <fcntl.h>
00029 #include <stdio.h>
00030 #include <direct.h>
00031 #include <io.h>
00032 #include <conio.h>
00033 
00034 #define COPY_ID         1
00035 #define QUIT_ID         2
00036 #define CLEAR_ID        3
00037 
00038 #define ERRORBOX_ID     10
00039 #define ERRORTEXT_ID    11
00040 
00041 #define EDIT_ID         100
00042 #define INPUT_ID        101
00043 
00044 typedef struct
00045 {
00046     HWND        hWnd;
00047     HWND        hwndBuffer;
00048 
00049     HWND        hwndButtonClear;
00050     HWND        hwndButtonCopy;
00051     HWND        hwndButtonQuit;
00052 
00053     HWND        hwndErrorBox;
00054     HWND        hwndErrorText;
00055 
00056     HBITMAP     hbmLogo;
00057     HBITMAP     hbmClearBitmap;
00058 
00059     HBRUSH      hbrEditBackground;
00060     HBRUSH      hbrErrorBackground;
00061 
00062     HFONT       hfBufferFont;
00063     HFONT       hfButtonFont;
00064 
00065     HWND        hwndInputLine;
00066 
00067     char        errorString[80];
00068 
00069     char        consoleText[512], returnedText[512];
00070     int         visLevel;
00071     qboolean    quitOnClose;
00072     int         windowWidth, windowHeight;
00073     
00074     WNDPROC     SysInputLineWndProc;
00075 
00076 } WinConData;
00077 
00078 static WinConData s_wcd;
00079 
00080 static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00081 {
00082     char *cmdString;
00083     static qboolean s_timePolarity;
00084 
00085     switch (uMsg)
00086     {
00087     case WM_ACTIVATE:
00088         if ( LOWORD( wParam ) != WA_INACTIVE )
00089         {
00090             SetFocus( s_wcd.hwndInputLine );
00091         }
00092 
00093         if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) )
00094         {
00095             // if the viewlog is open, check to see if it's being minimized
00096             if ( com_viewlog->integer == 1 )
00097             {
00098                 if ( HIWORD( wParam ) )     // minimized flag
00099                 {
00100                     Cvar_Set( "viewlog", "2" );
00101                 }
00102             }
00103             else if ( com_viewlog->integer == 2 )
00104             {
00105                 if ( !HIWORD( wParam ) )        // minimized flag
00106                 {
00107                     Cvar_Set( "viewlog", "1" );
00108                 }
00109             }
00110         }
00111         break;
00112 
00113     case WM_CLOSE:
00114         if ( ( com_dedicated && com_dedicated->integer ) )
00115         {
00116             cmdString = CopyString( "quit" );
00117             Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
00118         }
00119         else if ( s_wcd.quitOnClose )
00120         {
00121             PostQuitMessage( 0 );
00122         }
00123         else
00124         {
00125             Sys_ShowConsole( 0, qfalse );
00126             Cvar_Set( "viewlog", "0" );
00127         }
00128         return 0;
00129     case WM_CTLCOLORSTATIC:
00130         if ( ( HWND ) lParam == s_wcd.hwndBuffer )
00131         {
00132             SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0xB0 ) );
00133             SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) );
00134 
00135 #if 0   // this draws a background in the edit box, but there are issues with this
00136             if ( ( hdcScaled = CreateCompatibleDC( ( HDC ) wParam ) ) != 0 )
00137             {
00138                 if ( SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo ) )
00139                 {
00140                     StretchBlt( ( HDC ) wParam, 0, 0, 512, 384, 
00141                             hdcScaled, 0, 0, 512, 384,
00142                             SRCCOPY );
00143                 }
00144                 DeleteDC( hdcScaled );
00145             }
00146 #endif
00147             return ( long ) s_wcd.hbrEditBackground;
00148         }
00149         else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
00150         {
00151             if ( s_timePolarity & 1 )
00152             {
00153                 SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
00154                 SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x0, 0x00 ) );
00155             }
00156             else
00157             {
00158                 SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
00159                 SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) );
00160             }
00161             return ( long ) s_wcd.hbrErrorBackground;
00162         }
00163         break;
00164 
00165     case WM_COMMAND:
00166         if ( wParam == COPY_ID )
00167         {
00168             SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
00169             SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
00170         }
00171         else if ( wParam == QUIT_ID )
00172         {
00173             if ( s_wcd.quitOnClose )
00174             {
00175                 PostQuitMessage( 0 );
00176             }
00177             else
00178             {
00179                 cmdString = CopyString( "quit" );
00180                 Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
00181             }
00182         }
00183         else if ( wParam == CLEAR_ID )
00184         {
00185             SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
00186             SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
00187             UpdateWindow( s_wcd.hwndBuffer );
00188         }
00189         break;
00190     case WM_CREATE:
00191 //      s_wcd.hbmLogo = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP1 ) );
00192 //      s_wcd.hbmClearBitmap = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP2 ) );
00193         s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0xB0 ) );
00194         s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
00195         SetTimer( hWnd, 1, 1000, NULL );
00196         break;
00197     case WM_ERASEBKGND:
00198 #if 0
00199     HDC hdcScaled;
00200     HGDIOBJ oldObject;
00201 
00202 #if 1   // a single, large image
00203         hdcScaled = CreateCompatibleDC( ( HDC ) wParam );
00204         assert( hdcScaled != 0 );
00205 
00206         if ( hdcScaled )
00207         {
00208             oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo );
00209             assert( oldObject != 0 );
00210             if ( oldObject )
00211             {
00212                 StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight, 
00213                         hdcScaled, 0, 0, 512, 384,
00214                         SRCCOPY );
00215             }
00216             DeleteDC( hdcScaled );
00217             hdcScaled = 0;
00218         }
00219 #else   // a repeating brush
00220         {
00221             HBRUSH hbrClearBrush;
00222             RECT r;
00223 
00224             GetWindowRect( hWnd, &r );
00225 
00226             r.bottom = r.bottom - r.top + 1;
00227             r.right = r.right - r.left + 1;
00228             r.top = 0;
00229             r.left = 0;
00230 
00231             hbrClearBrush = CreatePatternBrush( s_wcd.hbmClearBitmap );
00232 
00233             assert( hbrClearBrush != 0 );
00234 
00235             if ( hbrClearBrush )
00236             {
00237                 FillRect( ( HDC ) wParam, &r, hbrClearBrush );
00238                 DeleteObject( hbrClearBrush );
00239             }
00240         }
00241 #endif
00242         return 1;
00243 #endif
00244         return DefWindowProc( hWnd, uMsg, wParam, lParam );
00245     case WM_TIMER:
00246         if ( wParam == 1 )
00247         {
00248             s_timePolarity = !s_timePolarity;
00249             if ( s_wcd.hwndErrorBox )
00250             {
00251                 InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
00252             }
00253         }
00254         break;
00255     }
00256 
00257     return DefWindowProc( hWnd, uMsg, wParam, lParam );
00258 }
00259 
00260 LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00261 {
00262     char inputBuffer[1024];
00263 
00264     switch ( uMsg )
00265     {
00266     case WM_KILLFOCUS:
00267         if ( ( HWND ) wParam == s_wcd.hWnd ||
00268              ( HWND ) wParam == s_wcd.hwndErrorBox )
00269         {
00270             SetFocus( hWnd );
00271             return 0;
00272         }
00273         break;
00274 
00275     case WM_CHAR:
00276         if ( wParam == 13 )
00277         {
00278             GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
00279             strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
00280             strcat( s_wcd.consoleText, "\n" );
00281             SetWindowText( s_wcd.hwndInputLine, "" );
00282 
00283             Sys_Print( va( "]%s\n", inputBuffer ) );
00284 
00285             return 0;
00286         }
00287     }
00288 
00289     return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
00290 }
00291 
00292 /*
00293 ** Sys_CreateConsole
00294 */
00295 void Sys_CreateConsole( void )
00296 {
00297     HDC hDC;
00298     WNDCLASS wc;
00299     RECT rect;
00300     const char *DEDCLASS = "Q3 WinConsole";
00301     int nHeight;
00302     int swidth, sheight;
00303     int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
00304 
00305     memset( &wc, 0, sizeof( wc ) );
00306 
00307     wc.style         = 0;
00308     wc.lpfnWndProc   = (WNDPROC) ConWndProc;
00309     wc.cbClsExtra    = 0;
00310     wc.cbWndExtra    = 0;
00311     wc.hInstance     = g_wv.hInstance;
00312     wc.hIcon         = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
00313     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
00314     wc.hbrBackground = (void *)COLOR_WINDOW;
00315     wc.lpszMenuName  = 0;
00316     wc.lpszClassName = DEDCLASS;
00317 
00318     if ( !RegisterClass (&wc) )
00319         return;
00320 
00321     rect.left = 0;
00322     rect.right = 540;
00323     rect.top = 0;
00324     rect.bottom = 450;
00325     AdjustWindowRect( &rect, DEDSTYLE, FALSE );
00326 
00327     hDC = GetDC( GetDesktopWindow() );
00328     swidth = GetDeviceCaps( hDC, HORZRES );
00329     sheight = GetDeviceCaps( hDC, VERTRES );
00330     ReleaseDC( GetDesktopWindow(), hDC );
00331 
00332     s_wcd.windowWidth = rect.right - rect.left + 1;
00333     s_wcd.windowHeight = rect.bottom - rect.top + 1;
00334 
00335     s_wcd.hWnd = CreateWindowEx( 0,
00336                                DEDCLASS,
00337                                "Quake 3 Console",
00338                                DEDSTYLE,
00339                                ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
00340                                NULL,
00341                                NULL,
00342                                g_wv.hInstance,
00343                                NULL );
00344 
00345     if ( s_wcd.hWnd == NULL )
00346     {
00347         return;
00348     }
00349 
00350     //
00351     // create fonts
00352     //
00353     hDC = GetDC( s_wcd.hWnd );
00354     nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
00355 
00356     s_wcd.hfBufferFont = CreateFont( nHeight,
00357                                       0,
00358                                       0,
00359                                       0,
00360                                       FW_LIGHT,
00361                                       0,
00362                                       0,
00363                                       0,
00364                                       DEFAULT_CHARSET,
00365                                       OUT_DEFAULT_PRECIS,
00366                                       CLIP_DEFAULT_PRECIS,
00367                                       DEFAULT_QUALITY,
00368                                       FF_MODERN | FIXED_PITCH,
00369                                       "Courier New" );
00370 
00371     ReleaseDC( s_wcd.hWnd, hDC );
00372 
00373     //
00374     // create the input line
00375     //
00376     s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | 
00377                                                 ES_LEFT | ES_AUTOHSCROLL,
00378                                                 6, 400, 528, 20,
00379                                                 s_wcd.hWnd, 
00380                                                 ( HMENU ) INPUT_ID, // child window ID
00381                                                 g_wv.hInstance, NULL );
00382 
00383     //
00384     // create the buttons
00385     //
00386     s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
00387                                                 5, 425, 72, 24,
00388                                                 s_wcd.hWnd, 
00389                                                 ( HMENU ) COPY_ID,  // child window ID
00390                                                 g_wv.hInstance, NULL );
00391     SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" );
00392 
00393     s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
00394                                                 82, 425, 72, 24,
00395                                                 s_wcd.hWnd, 
00396                                                 ( HMENU ) CLEAR_ID, // child window ID
00397                                                 g_wv.hInstance, NULL );
00398     SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" );
00399 
00400     s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
00401                                                 462, 425, 72, 24,
00402                                                 s_wcd.hWnd, 
00403                                                 ( HMENU ) QUIT_ID,  // child window ID
00404                                                 g_wv.hInstance, NULL );
00405     SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" );
00406 
00407 
00408     //
00409     // create the scrollbuffer
00410     //
00411     s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | 
00412                                                 ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
00413                                                 6, 40, 526, 354,
00414                                                 s_wcd.hWnd, 
00415                                                 ( HMENU ) EDIT_ID,  // child window ID
00416                                                 g_wv.hInstance, NULL );
00417     SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
00418 
00419     s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
00420     SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
00421 
00422     ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
00423     UpdateWindow( s_wcd.hWnd );
00424     SetForegroundWindow( s_wcd.hWnd );
00425     SetFocus( s_wcd.hwndInputLine );
00426 
00427     s_wcd.visLevel = 1;
00428 }
00429 
00430 /*
00431 ** Sys_DestroyConsole
00432 */
00433 void Sys_DestroyConsole( void ) {
00434     if ( s_wcd.hWnd ) {
00435         ShowWindow( s_wcd.hWnd, SW_HIDE );
00436         CloseWindow( s_wcd.hWnd );
00437         DestroyWindow( s_wcd.hWnd );
00438         s_wcd.hWnd = 0;
00439     }
00440 }
00441 
00442 /*
00443 ** Sys_ShowConsole
00444 */
00445 void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
00446 {
00447     s_wcd.quitOnClose = quitOnClose;
00448 
00449     if ( visLevel == s_wcd.visLevel )
00450     {
00451         return;
00452     }
00453 
00454     s_wcd.visLevel = visLevel;
00455 
00456     if ( !s_wcd.hWnd )
00457         return;
00458 
00459     switch ( visLevel )
00460     {
00461     case 0:
00462         ShowWindow( s_wcd.hWnd, SW_HIDE );
00463         break;
00464     case 1:
00465         ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
00466         SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
00467         break;
00468     case 2:
00469         ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
00470         break;
00471     default:
00472         Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
00473         break;
00474     }
00475 }
00476 
00477 /*
00478 ** Sys_ConsoleInput
00479 */
00480 char *Sys_ConsoleInput( void )
00481 {
00482     if ( s_wcd.consoleText[0] == 0 )
00483     {
00484         return NULL;
00485     }
00486         
00487     strcpy( s_wcd.returnedText, s_wcd.consoleText );
00488     s_wcd.consoleText[0] = 0;
00489     
00490     return s_wcd.returnedText;
00491 }
00492 
00493 /*
00494 ** Conbuf_AppendText
00495 */
00496 void Conbuf_AppendText( const char *pMsg )
00497 {
00498 #define CONSOLE_BUFFER_SIZE     16384
00499 
00500     char buffer[CONSOLE_BUFFER_SIZE*2];
00501     char *b = buffer;
00502     const char *msg;
00503     int bufLen;
00504     int i = 0;
00505     static unsigned long s_totalChars;
00506 
00507     //
00508     // if the message is REALLY long, use just the last portion of it
00509     //
00510     if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 )
00511     {
00512         msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
00513     }
00514     else
00515     {
00516         msg = pMsg;
00517     }
00518 
00519     //
00520     // copy into an intermediate buffer
00521     //
00522     while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) )
00523     {
00524         if ( msg[i] == '\n' && msg[i+1] == '\r' )
00525         {
00526             b[0] = '\r';
00527             b[1] = '\n';
00528             b += 2;
00529             i++;
00530         }
00531         else if ( msg[i] == '\r' )
00532         {
00533             b[0] = '\r';
00534             b[1] = '\n';
00535             b += 2;
00536         }
00537         else if ( msg[i] == '\n' )
00538         {
00539             b[0] = '\r';
00540             b[1] = '\n';
00541             b += 2;
00542         }
00543         else if ( Q_IsColorString( &msg[i] ) )
00544         {
00545             i++;
00546         }
00547         else
00548         {
00549             *b= msg[i];
00550             b++;
00551         }
00552         i++;
00553     }
00554     *b = 0;
00555     bufLen = b - buffer;
00556 
00557     s_totalChars += bufLen;
00558 
00559     //
00560     // replace selection instead of appending if we're overflowing
00561     //
00562     if ( s_totalChars > 0x7fff )
00563     {
00564         SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
00565         s_totalChars = bufLen;
00566     }
00567 
00568     //
00569     // put this text into the windows console
00570     //
00571     SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
00572     SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
00573     SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
00574 }
00575 
00576 /*
00577 ** Sys_SetErrorText
00578 */
00579 void Sys_SetErrorText( const char *buf )
00580 {
00581     Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
00582 
00583     if ( !s_wcd.hwndErrorBox )
00584     {
00585         s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
00586                                                     6, 5, 526, 30,
00587                                                     s_wcd.hWnd, 
00588                                                     ( HMENU ) ERRORBOX_ID,  // child window ID
00589                                                     g_wv.hInstance, NULL );
00590         SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
00591         SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
00592 
00593         DestroyWindow( s_wcd.hwndInputLine );
00594         s_wcd.hwndInputLine = NULL;
00595     }
00596 }

Generated on Thu Aug 25 12:38:07 2005 for Quake III Arena by  doxygen 1.3.9.1