/* ================ Con_Dump_f Save the console contents out to a file ================ */ void Con_Dump_f( void ) { int l; fileHandle_t f; char name[ MAX_STRING_CHARS ]; l = Cmd_Argc(); if ( l > 2 ) { Cmd_PrintUsage(_("[<filename>]"), NULL); return; } if ( l == 1 ) { time_t now = time( NULL ); strftime( name, sizeof( name ), "condump/%Y%m%d-%H%M%S%z.txt", localtime( &now ) ); } else { Q_snprintf( name, sizeof( name ), "condump/%s", Cmd_Argv( 1 ) ); } f = FS_FOpenFileWrite( name ); if ( !f ) { Com_Log(LOG_ERROR, _( "couldn't open." )); return; } Com_Printf(_( "Dumped console text to %s.\n"), name ); // skip empty lines for ( l = consoleState.currentLine - consoleState.maxScrollbackLengthInLines + 1; l <= consoleState.currentLine; l++ ) { if ( consoleState.text[ CON_LINE( l ) ].ch ) { break; } } // write the remaining lines for ( ; l <= consoleState.currentLine; l++ ) { const char *buffer = Con_LineToString( l, qtrue ); FS_Write( buffer, strlen( buffer ), f ); } FS_FCloseFile( f ); }
/* ================ Con_Dump_f Save the console contents out to a file ================ */ void Con_Dump_f( void ) { int l; fileHandle_t f; if ( Cmd_Argc() != 2 ) { Com_Printf("%s", _( "usage: condump <filename>\n" )); return; } Com_Printf(_( "Dumped console text to %s.\n"), Cmd_Argv( 1 ) ); f = FS_FOpenFileWrite( Cmd_Argv( 1 ) ); if ( !f ) { Com_Printf("%s", _( "ERROR: couldn't open.\n" )); return; } // skip empty lines for ( l = con.current - con.totallines + 1; l <= con.current; l++ ) { if ( con.text[ CON_LINE( l ) ].ch ) { break; } } // write the remaining lines for ( ; l <= con.current; l++ ) { const char *buffer = Con_LineToString( l, qtrue ); FS_Write( buffer, strlen( buffer ), f ); } FS_FCloseFile( f ); }
/* ================ Con_Search_f Scroll up to the first console line containing a string ================ */ void Con_Search_f( void ) { int l, i; int direction; int c = Cmd_Argc(); if ( c < 2 ) { Cmd_PrintUsage(_("<string>…"), NULL); return; } direction = Q_stricmp( Cmd_Argv( 0 ), "searchDown" ) ? -1 : 1; // check the lines for ( l = consoleState.scrollLineIndex - 1 + direction; l <= consoleState.currentLine && consoleState.currentLine - l < consoleState.maxScrollbackLengthInLines; l += direction ) { const char *buffer = Con_LineToString( l, qtrue ); // Don't search commands for ( i = 1; i < c; i++ ) { if ( Q_stristr( buffer, Cmd_Argv( i ) ) ) { consoleState.scrollLineIndex = l + 1; if ( consoleState.scrollLineIndex > consoleState.currentLine ) { consoleState.bottomDisplayedLine = consoleState.currentLine; } return; } } } }
/* ================ Con_Search_f Scroll up to the first console line containing a string ================ */ void Con_Search_f( void ) { int l, i; int direction; int c = Cmd_Argc(); if ( c < 2 ) { Com_Printf(_( "usage: %s <string1> <string2> <…>\n"), Cmd_Argv( 0 ) ); return; } direction = Q_stricmp( Cmd_Argv( 0 ), "searchDown" ) ? -1 : 1; // check the lines for ( l = con.display - 1 + direction; l <= con.current && con.current - l < con.totallines; l += direction ) { const char *buffer = Con_LineToString( l, qtrue ); // Don't search commands for ( i = 1; i < c; i++ ) { if ( Q_stristr( buffer, Cmd_Argv( i ) ) ) { con.display = l + 1; if ( con.display > con.current ) { con.display = con.current; } return; } } } }
/* ================ Con_Grep_f Find all console lines containing a string ================ */ void Con_Grep_f( void ) { int l; char *search; char *printbuf = NULL; size_t pbAlloc = 0, pbLength = 0; if ( Cmd_Argc() != 2 ) { Cmd_PrintUsage(_("<string>"), NULL); return; } // skip empty lines for ( l = consoleState.currentLine - consoleState.maxScrollbackLengthInLines + 1; l <= consoleState.currentLine; l++ ) { if ( consoleState.text[ CON_LINE( l ) ].ch ) { break; } } // check the remaining lines search = Cmd_Argv( 1 ); for ( ; l <= consoleState.currentLine; l++ ) { const char *buffer = Con_LineToString( l, qfalse ); if ( Q_stristr( buffer, search ) ) { size_t i; buffer = Con_LineToColouredString( l, qtrue ); i = strlen( buffer ); if ( pbLength + i >= pbAlloc ) { char *nb; // allocate in 16K chunks - more than adequate pbAlloc = ( pbLength + i + 1 + 16383) & ~16383; nb = (char*) Z_Malloc( pbAlloc ); if( printbuf ) { strcpy( nb, printbuf ); Z_Free( printbuf ); } printbuf = nb; } Q_strcat( printbuf, pbAlloc, buffer ); pbLength += i; } } if( printbuf ) { char tmpbuf[ MAXPRINTMSG ]; int i; // print out in chunks so we don't go over the MAXPRINTMSG limit for ( i = 0; i < pbLength; i += MAXPRINTMSG - 1 ) { Q_strncpyz( tmpbuf, printbuf + i, sizeof( tmpbuf ) ); Com_Printf( "%s", tmpbuf ); } Z_Free( printbuf ); } }
/* ================ Con_Grep_f Find all console lines containing a string ================ */ void Con_Grep_f( void ) { int l; int lastcolor; char *search; char *printbuf = NULL; size_t pbAlloc = 0, pbLength = 0; if ( Cmd_Argc() != 2 ) { Com_Printf("%s", _( "usage: grep <string>\n" )); return; } // skip empty lines for ( l = con.current - con.totallines + 1; l <= con.current; l++ ) { if ( con.text[ CON_LINE( l ) ].ch ) { break; } } // check the remaining lines search = Cmd_Argv( 1 ); lastcolor = 7; for ( ; l <= con.current; l++ ) { const char *buffer = Con_LineToString( l, qfalse ); if ( Q_stristr( buffer, search ) ) { size_t i; buffer = Con_LineToColouredString( l, qtrue ); i = strlen( buffer ); if ( pbLength + i >= pbAlloc ) { char *nb; // allocate in 16K chunks - more than adequate pbAlloc = ( pbLength + i + 1 + 16383) & ~16383; nb = Z_Malloc( pbAlloc ); if( printbuf ) { strcpy( nb, printbuf ); Z_Free( printbuf ); } printbuf = nb; } Q_strcat( printbuf, pbAlloc, buffer ); pbLength += i; } } if( printbuf ) { Com_Printf( "%s", printbuf ); Z_Free( printbuf ); } }