From 7fccfcafc99fe8a81bee1e2cc32e3e383d238dc2 Mon Sep 17 00:00:00 2001 From: tma Date: Fri, 30 Nov 2007 18:32:52 +0000 Subject: * Add con_log.c to log all console output * Add con_passive.c to cut down on #ifdef DEDICATED in sys_main.c * Add Sys_ErrorDialog to report ERR_FATALs to the user + On Windows use a MessageBox and offer to copy the console log to the clipboard + On everything else print to the terminal and save the console log as crashlog.txt git-svn-id: svn://svn.icculus.org/quake3/trunk@1222 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/qcommon/files.c | 2 +- code/sys/con_log.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ code/sys/con_passive.c | 68 ++++++++++++++++++++++++++ code/sys/con_tty.c | 26 ++++++++-- code/sys/con_win32.c | 29 ++++++----- code/sys/sys_local.h | 17 ++++--- code/sys/sys_main.c | 83 ++++++------------------------- code/sys/sys_unix.c | 38 +++++++++++++-- code/sys/sys_win32.c | 40 +++++++++++++++ 9 files changed, 337 insertions(+), 95 deletions(-) create mode 100644 code/sys/con_log.c create mode 100644 code/sys/con_passive.c (limited to 'code') diff --git a/code/qcommon/files.c b/code/qcommon/files.c index af5eaec..cf989c4 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -2872,7 +2872,7 @@ static void FS_CheckPak0( void ) if(!fs_gamedirvar->string[0] || !Q_stricmp( fs_gamedirvar->string, BASEGAME ) || !Q_stricmp( fs_gamedirvar->string, "missionpack" )) - Com_Error(ERR_FATAL, "\n*** you need to install Quake III Arena in order to play ***"); + Com_Error(ERR_FATAL, "You need to install Quake III Arena in order to play"); } } diff --git a/code/sys/con_log.c b/code/sys/con_log.c new file mode 100644 index 0000000..ca43a6b --- /dev/null +++ b/code/sys/con_log.c @@ -0,0 +1,129 @@ +/* +=========================================================================== +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" + +#define MAX_LOG 32768 + +static char consoleLog[ MAX_LOG ]; +static unsigned int write = 0; +static unsigned int read = 0; + +/* +================== +CON_LogSize +================== +*/ +unsigned int CON_LogSize( void ) +{ + if( read <= write ) + return write - read; + else + return write + MAX_LOG - read; +} + +/* +================== +CON_LogFree +================== +*/ +static unsigned int CON_LogFree( void ) +{ + return MAX_LOG - CON_LogSize( ) - 1; +} + +/* +================== +CON_LogWrite +================== +*/ +unsigned int CON_LogWrite( const char *in ) +{ + unsigned int length = strlen( in ); + unsigned int firstChunk; + unsigned int secondChunk; + + while( CON_LogFree( ) < length && CON_LogSize( ) > 0 ) + { + // Free enough space + while( consoleLog[ read ] != '\n' && CON_LogSize( ) > 1 ) + read = ( read + 1 ) % MAX_LOG; + + // Skip past the '\n' + read = ( read + 1 ) % MAX_LOG; + } + + if( CON_LogFree( ) < length ) + return 0; + + if( write + length > MAX_LOG ) + { + firstChunk = MAX_LOG - write; + secondChunk = length - firstChunk; + } + else + { + firstChunk = length; + secondChunk = 0; + } + + Com_Memcpy( consoleLog + write, in, firstChunk ); + Com_Memcpy( consoleLog, in + firstChunk, secondChunk ); + + write = ( write + length ) % MAX_LOG; + + return length; +} + +/* +================== +CON_LogRead +================== +*/ +unsigned int CON_LogRead( char *out, unsigned int outSize ) +{ + unsigned int firstChunk; + unsigned int secondChunk; + + if( CON_LogSize( ) < outSize ) + outSize = CON_LogSize( ); + + if( read + outSize > MAX_LOG ) + { + firstChunk = MAX_LOG - read; + secondChunk = outSize - firstChunk; + } + else + { + firstChunk = outSize; + secondChunk = 0; + } + + Com_Memcpy( out, consoleLog + read, firstChunk ); + Com_Memcpy( out + firstChunk, out, secondChunk ); + + read = ( read + outSize ) % MAX_LOG; + + return outSize; +} diff --git a/code/sys/con_passive.c b/code/sys/con_passive.c new file mode 100644 index 0000000..794c895 --- /dev/null +++ b/code/sys/con_passive.c @@ -0,0 +1,68 @@ +/* +=========================================================================== +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 + +/* +================== +CON_Shutdown +================== +*/ +void CON_Shutdown( void ) +{ +} + +/* +================== +CON_Init +================== +*/ +void CON_Init( void ) +{ +} + +/* +================== +CON_Input +================== +*/ +char *CON_Input( void ) +{ + return NULL; +} + +/* +================== +CON_Print +================== +*/ +void CON_Print( const char *msg ) +{ + if( com_ansiColor && com_ansiColor->integer ) + Sys_AnsiColorPrint( msg ); + else + fputs( msg, stderr ); +} diff --git a/code/sys/con_tty.c b/code/sys/con_tty.c index ee729da..c2e553a 100644 --- a/code/sys/con_tty.c +++ b/code/sys/con_tty.c @@ -22,6 +22,7 @@ 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 #include @@ -101,7 +102,7 @@ Clear the display of the line currently edited bring cursor back to beginning of line ================== */ -void CON_Hide( void ) +static void CON_Hide( void ) { if( ttycon_on ) { @@ -131,7 +132,7 @@ Show the current line FIXME need to position the cursor if needed? ================== */ -void CON_Show( void ) +static void CON_Show( void ) { if( ttycon_on ) { @@ -296,10 +297,10 @@ void CON_Init( void ) /* ================== -CON_ConsoleInput +CON_Input ================== */ -char *CON_ConsoleInput( void ) +char *CON_Input( void ) { // we use this when sending back commands static char text[256]; @@ -439,3 +440,20 @@ char *CON_ConsoleInput( void ) return text; } } + +/* +================== +CON_Print +================== +*/ +void CON_Print( const char *msg ) +{ + CON_Hide( ); + + if( com_ansiColor && com_ansiColor->integer ) + Sys_AnsiColorPrint( msg ); + else + fputs( msg, stderr ); + + CON_Show( ); +} diff --git a/code/sys/con_win32.c b/code/sys/con_win32.c index 23a5ae7..787c74f 100644 --- a/code/sys/con_win32.c +++ b/code/sys/con_win32.c @@ -130,21 +130,12 @@ static void CON_HistNext( void ) } -/* -================== -CON_Hide -================== -*/ -void CON_Hide( void ) -{ -} - /* ================== CON_Show ================== */ -void CON_Show( void ) +static void CON_Show( void ) { CONSOLE_SCREEN_BUFFER_INFO binfo; COORD writeSize = { MAX_EDIT_LINE, 1 }; @@ -155,7 +146,7 @@ void CON_Show( void ) GetConsoleScreenBufferInfo( qconsole_hout, &binfo ); - // if we' re in the middle of printf, don't bother writing the buffer + // if we're in the middle of printf, don't bother writing the buffer if( binfo.dwCursorPosition.X != 0 ) return; @@ -249,10 +240,10 @@ void CON_Init( void ) /* ================== -CON_ConsoleInput +CON_Input ================== */ -char *CON_ConsoleInput( void ) +char *CON_Input( void ) { INPUT_RECORD buff[ MAX_EDIT_LINE ]; DWORD count = 0, events = 0; @@ -353,3 +344,15 @@ char *CON_ConsoleInput( void ) return qconsole_line; } + +/* +================== +CON_Print +================== +*/ +void CON_Print( const char *msg ) +{ + fputs( msg, stderr ); + + CON_Show( ); +} diff --git a/code/sys/sys_local.h b/code/sys/sys_local.h index af0ed7c..e837b8b 100644 --- a/code/sys/sys_local.h +++ b/code/sys/sys_local.h @@ -29,19 +29,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MINSDL_PATCH 7 // Input subsystem -void IN_Init (void); -void IN_Frame (void); -void IN_Shutdown (void); +void IN_Init( void ); +void IN_Frame( void ); +void IN_Shutdown( void ); // Console -void CON_Hide( void ); -void CON_Show( void ); void CON_Shutdown( void ); void CON_Init( void ); -char *CON_ConsoleInput(void); +char *CON_Input( void ); +void CON_Print( const char *message ); + +unsigned int CON_LogSize( void ); +unsigned int CON_LogWrite( const char *in ); +unsigned int CON_LogRead( char *out, unsigned int outSize ); #ifdef MACOS_X char *Sys_StripAppBundle( char *pwd ); #endif void Sys_SigHandler( int signal ); +void Sys_ErrorDialog( const char *error ); +void Sys_AnsiColorPrint( const char *msg ); diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index bf0eb94..4c3f703 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -106,34 +106,6 @@ void Sys_In_Restart_f( void ) IN_Init(); } -/* -================= -Sys_ConsoleInputInit - -Start the console input subsystem -================= -*/ -void Sys_ConsoleInputInit( void ) -{ -#ifdef DEDICATED - CON_Init( ); -#endif -} - -/* -================= -Sys_ConsoleInputShutdown - -Shutdown the console input subsystem -================= -*/ -void Sys_ConsoleInputShutdown( void ) -{ -#ifdef DEDICATED - CON_Shutdown( ); -#endif -} - /* ================= Sys_ConsoleInput @@ -143,11 +115,7 @@ Handle new console input */ char *Sys_ConsoleInput(void) { -#ifdef DEDICATED - return CON_ConsoleInput( ); -#endif - - return NULL; + return CON_Input( ); } /* @@ -159,18 +127,18 @@ Single exit point (regular exit or in case of error) */ void Sys_Exit( int ex ) { - Sys_ConsoleInputShutdown(); + CON_Shutdown( ); #ifndef DEDICATED SDL_Quit( ); #endif #ifdef NDEBUG - exit(ex); + exit( ex ); #else // Cause a backtrace on error exits assert( ex == 0 ); - exit(ex); + exit( ex ); #endif } @@ -179,10 +147,10 @@ void Sys_Exit( int ex ) Sys_Quit ================= */ -void Sys_Quit (void) +void Sys_Quit( void ) { - CL_Shutdown (); - Sys_Exit(0); + CL_Shutdown( ); + Sys_Exit( 0 ); } /* @@ -227,7 +195,7 @@ Sys_AnsiColorPrint Transform Q3 colour codes to ANSI escape sequences ================= */ -static void Sys_AnsiColorPrint( const char *msg ) +void Sys_AnsiColorPrint( const char *msg ) { static char buffer[ MAXPRINTMSG ]; int length = 0; @@ -296,18 +264,8 @@ Sys_Print */ void Sys_Print( const char *msg ) { -#ifdef DEDICATED - CON_Hide(); -#endif - - if( com_ansiColor && com_ansiColor->integer ) - Sys_AnsiColorPrint( msg ); - else - fputs(msg, stderr); - -#ifdef DEDICATED - CON_Show(); -#endif + CON_LogWrite( msg ); + CON_Print( msg ); } /* @@ -320,16 +278,13 @@ void Sys_Error( const char *error, ... ) va_list argptr; char string[1024]; -#ifdef DEDICATED - CON_Hide(); -#endif - CL_Shutdown (); va_start (argptr,error); Q_vsnprintf (string, sizeof(string), error, argptr); va_end (argptr); - fprintf(stderr, "Sys_Error: %s\n", string); + + Sys_ErrorDialog( string ); Sys_Exit( 1 ); } @@ -348,15 +303,7 @@ void Sys_Warn( char *warning, ... ) Q_vsnprintf (string, sizeof(string), warning, argptr); va_end (argptr); -#ifdef DEDICATED - CON_Hide(); -#endif - - fprintf(stderr, "Warning: %s", string); - -#ifdef DEDICATED - CON_Show(); -#endif + CON_Print( va( "Warning: %s", string ) ); } /* @@ -624,9 +571,9 @@ int main( int argc, char **argv ) } Com_Init( commandLine ); - NET_Init(); + NET_Init( ); - Sys_ConsoleInputInit(); + CON_Init( ); #ifndef _WIN32 // Windows doesn't have these signals diff --git a/code/sys/sys_unix.c b/code/sys/sys_unix.c index adb3324..9d9d5aa 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -19,6 +19,11 @@ 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 #include #include @@ -30,9 +35,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include -#include "../qcommon/q_shared.h" -#include "../qcommon/qcommon.h" - // Used to determine where to store user-specific files static char homePath[ MAX_OSPATH ] = { 0 }; @@ -476,3 +478,33 @@ void Sys_Sleep( int msec ) select((fileno(stdin) + 1), &fdset, NULL, NULL, &timeout); } } + +/* +============== +Sys_ErrorDialog + +Display an error message +============== +*/ +void Sys_ErrorDialog( const char *error ) +{ + char buffer[ 1024 ]; + unsigned int size; + fileHandle_t f; + const char *fileName = "crashlog.txt"; + + Sys_Print( va( "%s\n", error ) ); + + // Write console log to file + f = FS_FOpenFileWrite( fileName ); + if( !f ) + { + Com_Printf( "ERROR: couldn't open %s\n", fileName ); + return; + } + + while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) + FS_Write( buffer, size, f ); + + FS_FCloseFile( f ); +} diff --git a/code/sys/sys_win32.c b/code/sys/sys_win32.c index 64a57a2..18724b3 100644 --- a/code/sys/sys_win32.c +++ b/code/sys/sys_win32.c @@ -525,3 +525,43 @@ void Sys_Sleep( int msec ) WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), msec ); } +/* +============== +Sys_ErrorDialog + +Display an error message +============== +*/ +void Sys_ErrorDialog( const char *error ) +{ + if( MessageBox( NULL, va( "%s. Copy console log to clipboard?", error ), + NULL, MB_YESNO|MB_ICONERROR ) == IDYES ) + { + HGLOBAL memoryHandle; + char *clipMemory; + + memoryHandle = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, CON_LogSize( ) + 1 ); + clipMemory = (char *)GlobalLock( memoryHandle ); + + if( clipMemory ) + { + char *p = clipMemory; + char buffer[ 1024 ]; + unsigned int size; + + while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) + { + Com_Memcpy( p, buffer, size ); + p += size; + } + + *p = '\0'; + + if( OpenClipboard( NULL ) && EmptyClipboard( ) ) + SetClipboardData( CF_TEXT, memoryHandle ); + + GlobalUnlock( clipMemory ); + CloseClipboard( ); + } + } +} -- cgit v1.2.3