mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-02 08:51:57 +00:00
918 lines
20 KiB
C++
918 lines
20 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef ID_RETAIL
|
|
idCVar net_allowCheats( "net_allowCheats", "0", CVAR_BOOL | CVAR_ROM, "Allow cheats in multiplayer" );
|
|
#else
|
|
idCVar net_allowCheats( "net_allowCheats", "0", CVAR_BOOL | CVAR_NOCHEAT, "Allow cheats in multiplayer" );
|
|
#endif
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
idCmdSystemLocal
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
typedef struct commandDef_s
|
|
{
|
|
struct commandDef_s* next;
|
|
char* name;
|
|
cmdFunction_t function;
|
|
argCompletion_t argCompletion;
|
|
int flags;
|
|
char* description;
|
|
} commandDef_t;
|
|
|
|
/*
|
|
================================================
|
|
idCmdSystemLocal
|
|
================================================
|
|
*/
|
|
class idCmdSystemLocal : public idCmdSystem
|
|
{
|
|
public:
|
|
virtual void Init();
|
|
virtual void Shutdown();
|
|
|
|
virtual void AddCommand( const char* cmdName, cmdFunction_t function, int flags, const char* description, argCompletion_t argCompletion = NULL );
|
|
virtual void RemoveCommand( const char* cmdName );
|
|
virtual void RemoveFlaggedCommands( int flags );
|
|
|
|
virtual void CommandCompletion( void( *callback )( const char* s ) );
|
|
virtual void ArgCompletion( const char* cmdString, void( *callback )( const char* s ) );
|
|
virtual void ExecuteCommandText( const char* text );
|
|
virtual void AppendCommandText( const char* text );
|
|
|
|
virtual void BufferCommandText( cmdExecution_t exec, const char* text );
|
|
virtual void ExecuteCommandBuffer();
|
|
|
|
virtual void ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, bool stripFolder, ... );
|
|
virtual void ArgCompletion_DeclName( const idCmdArgs& args, void( *callback )( const char* s ), int type );
|
|
|
|
virtual void BufferCommandArgs( cmdExecution_t exec, const idCmdArgs& args );
|
|
|
|
virtual void SetupReloadEngine( const idCmdArgs& args );
|
|
virtual bool PostReloadEngine();
|
|
|
|
void SetWait( int numFrames )
|
|
{
|
|
wait = numFrames;
|
|
}
|
|
commandDef_t* GetCommands() const
|
|
{
|
|
return commands;
|
|
}
|
|
|
|
private:
|
|
static const int MAX_CMD_BUFFER = 0x10000;
|
|
|
|
commandDef_t* commands;
|
|
|
|
int wait;
|
|
int textLength;
|
|
byte textBuf[MAX_CMD_BUFFER];
|
|
|
|
idStr completionString;
|
|
idStrList completionParms;
|
|
|
|
// piggybacks on the text buffer, avoids tokenize again and screwing it up
|
|
idList<idCmdArgs> tokenizedCmds;
|
|
|
|
// a command stored to be executed after a reloadEngine and all associated commands have been processed
|
|
idCmdArgs postReload;
|
|
|
|
private:
|
|
void ExecuteTokenizedString( const idCmdArgs& args );
|
|
void InsertCommandText( const char* text );
|
|
|
|
static void ListByFlags( const idCmdArgs& args, cmdFlags_t flags );
|
|
static void List_f( const idCmdArgs& args );
|
|
static void SystemList_f( const idCmdArgs& args );
|
|
static void RendererList_f( const idCmdArgs& args );
|
|
static void SoundList_f( const idCmdArgs& args );
|
|
static void GameList_f( const idCmdArgs& args );
|
|
static void ToolList_f( const idCmdArgs& args );
|
|
static void Exec_f( const idCmdArgs& args );
|
|
static void Vstr_f( const idCmdArgs& args );
|
|
static void Echo_f( const idCmdArgs& args );
|
|
static void Parse_f( const idCmdArgs& args );
|
|
static void Wait_f( const idCmdArgs& args );
|
|
static void PrintMemInfo_f( const idCmdArgs& args );
|
|
};
|
|
|
|
idCmdSystemLocal cmdSystemLocal;
|
|
idCmdSystem* cmdSystem = &cmdSystemLocal;
|
|
|
|
/*
|
|
================================================
|
|
idSort_CommandDef
|
|
================================================
|
|
*/
|
|
class idSort_CommandDef : public idSort_Quick< commandDef_t, idSort_CommandDef >
|
|
{
|
|
public:
|
|
int Compare( const commandDef_t& a, const commandDef_t& b ) const
|
|
{
|
|
return idStr::Icmp( a.name, b.name );
|
|
}
|
|
};
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ListByFlags
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ListByFlags( const idCmdArgs& args, cmdFlags_t flags )
|
|
{
|
|
int i;
|
|
idStr match;
|
|
const commandDef_t* cmd;
|
|
idList<const commandDef_t*> cmdList;
|
|
|
|
if( args.Argc() > 1 )
|
|
{
|
|
match = args.Args( 1, -1 );
|
|
match.Replace( " ", "" );
|
|
}
|
|
else
|
|
{
|
|
match = "";
|
|
}
|
|
|
|
for( cmd = cmdSystemLocal.GetCommands(); cmd; cmd = cmd->next )
|
|
{
|
|
if( !( cmd->flags & flags ) )
|
|
{
|
|
continue;
|
|
}
|
|
if( match.Length() && idStr( cmd->name ).Filter( match, false ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
cmdList.Append( cmd );
|
|
}
|
|
|
|
//cmdList.SortWithTemplate( idSort_CommandDef() );
|
|
|
|
for( i = 0; i < cmdList.Num(); i++ )
|
|
{
|
|
cmd = cmdList[i];
|
|
|
|
common->Printf( " %-21s %s\n", cmd->name, cmd->description );
|
|
}
|
|
|
|
common->Printf( "%i commands\n", cmdList.Num() );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::List_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::List_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_ALL );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::SystemList_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::SystemList_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_SYSTEM );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::RendererList_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::RendererList_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_RENDERER );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::SoundList_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::SoundList_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_SOUND );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::GameList_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::GameList_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_GAME );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ToolList_f
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ToolList_f( const idCmdArgs& args )
|
|
{
|
|
idCmdSystemLocal::ListByFlags( args, CMD_FL_TOOL );
|
|
}
|
|
|
|
/*
|
|
===============
|
|
idCmdSystemLocal::Exec_f
|
|
===============
|
|
*/
|
|
void idCmdSystemLocal::Exec_f( const idCmdArgs& args )
|
|
{
|
|
char* f;
|
|
int len;
|
|
idStr filename;
|
|
|
|
if( args.Argc() != 2 )
|
|
{
|
|
common->Printf( "exec <filename> : execute a script file\n" );
|
|
return;
|
|
}
|
|
|
|
filename = args.Argv( 1 );
|
|
filename.DefaultFileExtension( ".cfg" );
|
|
len = fileSystem->ReadFile( filename, reinterpret_cast<void**>( &f ), NULL );
|
|
if( !f )
|
|
{
|
|
common->Printf( "couldn't exec %s\n", args.Argv( 1 ) );
|
|
return;
|
|
}
|
|
common->Printf( "execing %s\n", args.Argv( 1 ) );
|
|
|
|
cmdSystemLocal.BufferCommandText( CMD_EXEC_INSERT, f );
|
|
|
|
fileSystem->FreeFile( f );
|
|
}
|
|
|
|
/*
|
|
===============
|
|
idCmdSystemLocal::Vstr_f
|
|
|
|
Inserts the current value of a cvar as command text
|
|
===============
|
|
*/
|
|
void idCmdSystemLocal::Vstr_f( const idCmdArgs& args )
|
|
{
|
|
const char* v;
|
|
|
|
if( args.Argc() != 2 )
|
|
{
|
|
common->Printf( "vstr <variablename> : execute a variable command\n" );
|
|
return;
|
|
}
|
|
|
|
v = cvarSystem->GetCVarString( args.Argv( 1 ) );
|
|
|
|
cmdSystemLocal.BufferCommandText( CMD_EXEC_APPEND, va( "%s\n", v ) );
|
|
}
|
|
|
|
/*
|
|
===============
|
|
idCmdSystemLocal::Echo_f
|
|
|
|
Just prints the rest of the line to the console
|
|
===============
|
|
*/
|
|
void idCmdSystemLocal::Echo_f( const idCmdArgs& args )
|
|
{
|
|
int i;
|
|
|
|
for( i = 1; i < args.Argc(); i++ )
|
|
{
|
|
common->Printf( "%s ", args.Argv( i ) );
|
|
}
|
|
common->Printf( "\n" );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::Wait_f
|
|
|
|
Causes execution of the remainder of the command buffer to be delayed until next frame.
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::Wait_f( const idCmdArgs& args )
|
|
{
|
|
if( args.Argc() == 2 )
|
|
{
|
|
cmdSystemLocal.SetWait( atoi( args.Argv( 1 ) ) );
|
|
}
|
|
else
|
|
{
|
|
cmdSystemLocal.SetWait( 1 );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::Parse_f
|
|
|
|
This just prints out how the rest of the line was parsed, as a debugging tool.
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::Parse_f( const idCmdArgs& args )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < args.Argc(); i++ )
|
|
{
|
|
common->Printf( "%i: %s\n", i, args.Argv( i ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::Init
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::Init()
|
|
{
|
|
|
|
AddCommand( "listCmds", List_f, CMD_FL_SYSTEM, "lists commands" );
|
|
AddCommand( "listSystemCmds", SystemList_f, CMD_FL_SYSTEM, "lists system commands" );
|
|
AddCommand( "listRendererCmds", RendererList_f, CMD_FL_SYSTEM, "lists renderer commands" );
|
|
AddCommand( "listSoundCmds", SoundList_f, CMD_FL_SYSTEM, "lists sound commands" );
|
|
AddCommand( "listGameCmds", GameList_f, CMD_FL_SYSTEM, "lists game commands" );
|
|
AddCommand( "listToolCmds", ToolList_f, CMD_FL_SYSTEM, "lists tool commands" );
|
|
AddCommand( "exec", Exec_f, CMD_FL_SYSTEM, "executes a config file", ArgCompletion_ConfigName );
|
|
AddCommand( "vstr", Vstr_f, CMD_FL_SYSTEM, "inserts the current value of a cvar as command text" );
|
|
AddCommand( "echo", Echo_f, CMD_FL_SYSTEM, "prints text" );
|
|
AddCommand( "parse", Parse_f, CMD_FL_SYSTEM, "prints tokenized string" );
|
|
AddCommand( "wait", Wait_f, CMD_FL_SYSTEM, "delays remaining buffered commands one or more frames" );
|
|
|
|
// link in all the commands declared with static idCommandLink variables or CONSOLE_COMMAND macros
|
|
for( idCommandLink* link = CommandLinks(); link != NULL; link = link->next )
|
|
{
|
|
AddCommand( link->cmdName_, link->function_, CMD_FL_SYSTEM, link->description_, link->argCompletion_ );
|
|
}
|
|
|
|
completionString = "*";
|
|
|
|
textLength = 0;
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::Shutdown
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::Shutdown()
|
|
{
|
|
commandDef_t* cmd;
|
|
|
|
for( cmd = commands; cmd; cmd = commands )
|
|
{
|
|
commands = commands->next;
|
|
Mem_Free( cmd->name );
|
|
Mem_Free( cmd->description );
|
|
delete cmd;
|
|
}
|
|
|
|
completionString.Clear();
|
|
completionParms.Clear();
|
|
tokenizedCmds.Clear();
|
|
postReload.Clear();
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::AddCommand
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::AddCommand( const char* cmdName, cmdFunction_t function, int flags, const char* description, argCompletion_t argCompletion )
|
|
{
|
|
commandDef_t* cmd;
|
|
|
|
// fail if the command already exists
|
|
for( cmd = commands; cmd; cmd = cmd->next )
|
|
{
|
|
if( idStr::Cmp( cmdName, cmd->name ) == 0 )
|
|
{
|
|
if( function != cmd->function )
|
|
{
|
|
common->Printf( "idCmdSystemLocal::AddCommand: %s already defined\n", cmdName );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
cmd = new( TAG_SYSTEM ) commandDef_t;
|
|
cmd->name = Mem_CopyString( cmdName );
|
|
cmd->function = function;
|
|
cmd->argCompletion = argCompletion;
|
|
cmd->flags = flags;
|
|
cmd->description = Mem_CopyString( description );
|
|
cmd->next = commands;
|
|
commands = cmd;
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::RemoveCommand
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::RemoveCommand( const char* cmdName )
|
|
{
|
|
commandDef_t* cmd, **last;
|
|
|
|
for( last = &commands, cmd = *last; cmd; cmd = *last )
|
|
{
|
|
if( idStr::Cmp( cmdName, cmd->name ) == 0 )
|
|
{
|
|
*last = cmd->next;
|
|
Mem_Free( cmd->name );
|
|
Mem_Free( cmd->description );
|
|
delete cmd;
|
|
return;
|
|
}
|
|
last = &cmd->next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::RemoveFlaggedCommands
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::RemoveFlaggedCommands( int flags )
|
|
{
|
|
commandDef_t* cmd, **last;
|
|
|
|
for( last = &commands, cmd = *last; cmd; cmd = *last )
|
|
{
|
|
if( cmd->flags & flags )
|
|
{
|
|
*last = cmd->next;
|
|
Mem_Free( cmd->name );
|
|
Mem_Free( cmd->description );
|
|
delete cmd;
|
|
continue;
|
|
}
|
|
last = &cmd->next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::CommandCompletion
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::CommandCompletion( void( *callback )( const char* s ) )
|
|
{
|
|
commandDef_t* cmd;
|
|
|
|
for( cmd = commands; cmd; cmd = cmd->next )
|
|
{
|
|
callback( cmd->name );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ArgCompletion
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ArgCompletion( const char* cmdString, void( *callback )( const char* s ) )
|
|
{
|
|
commandDef_t* cmd;
|
|
idCmdArgs args;
|
|
|
|
args.TokenizeString( cmdString, false );
|
|
|
|
for( cmd = commands; cmd; cmd = cmd->next )
|
|
{
|
|
if( !cmd->argCompletion )
|
|
{
|
|
continue;
|
|
}
|
|
if( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 )
|
|
{
|
|
cmd->argCompletion( args, callback );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ExecuteTokenizedString
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ExecuteTokenizedString( const idCmdArgs& args )
|
|
{
|
|
commandDef_t* cmd, **prev;
|
|
|
|
// execute the command line
|
|
if( !args.Argc() )
|
|
{
|
|
return; // no tokens
|
|
}
|
|
|
|
// check registered command functions
|
|
for( prev = &commands; *prev; prev = &cmd->next )
|
|
{
|
|
cmd = *prev;
|
|
if( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 )
|
|
{
|
|
// rearrange the links so that the command will be
|
|
// near the head of the list next time it is used
|
|
*prev = cmd->next;
|
|
cmd->next = commands;
|
|
commands = cmd;
|
|
|
|
if( ( cmd->flags & ( CMD_FL_CHEAT | CMD_FL_TOOL ) ) && common->IsMultiplayer() && !net_allowCheats.GetBool() )
|
|
{
|
|
common->Printf( "Command '%s' not valid in multiplayer mode.\n", cmd->name );
|
|
return;
|
|
}
|
|
// perform the action
|
|
if( !cmd->function )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
cmd->function( args );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// check cvars
|
|
if( cvarSystem->Command( args ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
common->Printf( "Unknown command '%s'\n", args.Argv( 0 ) );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ExecuteCommandText
|
|
|
|
Tokenizes, then executes.
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ExecuteCommandText( const char* text )
|
|
{
|
|
ExecuteTokenizedString( idCmdArgs( text, false ) );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::InsertCommandText
|
|
|
|
Adds command text immediately after the current command
|
|
Adds a \n to the text
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::InsertCommandText( const char* text )
|
|
{
|
|
int len;
|
|
int i;
|
|
|
|
len = strlen( text ) + 1;
|
|
if( len + textLength > ( int )sizeof( textBuf ) )
|
|
{
|
|
common->Printf( "idCmdSystemLocal::InsertText: buffer overflow\n" );
|
|
return;
|
|
}
|
|
|
|
// move the existing command text
|
|
for( i = textLength - 1; i >= 0; i-- )
|
|
{
|
|
textBuf[ i + len ] = textBuf[ i ];
|
|
}
|
|
|
|
// copy the new text in
|
|
memcpy( textBuf, text, len - 1 );
|
|
|
|
// add a \n
|
|
textBuf[ len - 1 ] = '\n';
|
|
|
|
textLength += len;
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::AppendCommandText
|
|
|
|
Adds command text at the end of the buffer, does NOT add a final \n
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::AppendCommandText( const char* text )
|
|
{
|
|
int l;
|
|
|
|
l = strlen( text );
|
|
|
|
if( textLength + l >= ( int )sizeof( textBuf ) )
|
|
{
|
|
common->Printf( "idCmdSystemLocal::AppendText: buffer overflow\n" );
|
|
return;
|
|
}
|
|
memcpy( textBuf + textLength, text, l );
|
|
textLength += l;
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::BufferCommandText
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::BufferCommandText( cmdExecution_t exec, const char* text )
|
|
{
|
|
switch( exec )
|
|
{
|
|
case CMD_EXEC_NOW:
|
|
{
|
|
ExecuteCommandText( text );
|
|
break;
|
|
}
|
|
case CMD_EXEC_INSERT:
|
|
{
|
|
InsertCommandText( text );
|
|
break;
|
|
}
|
|
case CMD_EXEC_APPEND:
|
|
{
|
|
AppendCommandText( text );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
common->FatalError( "idCmdSystemLocal::BufferCommandText: bad exec type" );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::BufferCommandArgs
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::BufferCommandArgs( cmdExecution_t exec, const idCmdArgs& args )
|
|
{
|
|
switch( exec )
|
|
{
|
|
case CMD_EXEC_NOW:
|
|
{
|
|
ExecuteTokenizedString( args );
|
|
break;
|
|
}
|
|
case CMD_EXEC_APPEND:
|
|
{
|
|
AppendCommandText( "_execTokenized\n" );
|
|
tokenizedCmds.Append( args );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
common->FatalError( "idCmdSystemLocal::BufferCommandArgs: bad exec type" );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ExecuteCommandBuffer
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ExecuteCommandBuffer()
|
|
{
|
|
int i;
|
|
char* text;
|
|
int quotes;
|
|
idCmdArgs args;
|
|
|
|
while( textLength )
|
|
{
|
|
|
|
if( wait )
|
|
{
|
|
// skip out while text still remains in buffer, leaving it for next frame
|
|
wait--;
|
|
break;
|
|
}
|
|
|
|
// find a \n or ; line break
|
|
text = ( char* )textBuf;
|
|
|
|
quotes = 0;
|
|
for( i = 0; i < textLength; i++ )
|
|
{
|
|
if( text[i] == '"' )
|
|
{
|
|
quotes++;
|
|
}
|
|
if( !( quotes & 1 ) && text[i] == ';' )
|
|
{
|
|
break; // don't break if inside a quoted string
|
|
}
|
|
if( text[i] == '\n' || text[i] == '\r' )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
text[i] = 0;
|
|
|
|
if( !idStr::Cmp( text, "_execTokenized" ) )
|
|
{
|
|
args = tokenizedCmds[ 0 ];
|
|
tokenizedCmds.RemoveIndex( 0 );
|
|
}
|
|
else
|
|
{
|
|
args.TokenizeString( text, false );
|
|
}
|
|
|
|
// delete the text from the command buffer and move remaining commands down
|
|
// this is necessary because commands (exec) can insert data at the
|
|
// beginning of the text buffer
|
|
|
|
if( i == textLength )
|
|
{
|
|
textLength = 0;
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
textLength -= i;
|
|
memmove( text, text + i, textLength );
|
|
}
|
|
|
|
// execute the command line that we have already tokenized
|
|
ExecuteTokenizedString( args );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ArgCompletion_FolderExtension
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, bool stripFolder, ... )
|
|
{
|
|
int i;
|
|
idStr string;
|
|
const char* extension;
|
|
va_list argPtr;
|
|
|
|
string = args.Argv( 0 );
|
|
string += " ";
|
|
string += args.Argv( 1 );
|
|
|
|
if( string.Icmp( completionString ) != 0 )
|
|
{
|
|
idStr parm, path;
|
|
idFileList* names;
|
|
|
|
completionString = string;
|
|
completionParms.Clear();
|
|
|
|
parm = args.Argv( 1 );
|
|
parm.ExtractFilePath( path );
|
|
if( stripFolder || path.Length() == 0 )
|
|
{
|
|
path = folder + path;
|
|
}
|
|
path.StripTrailing( '/' );
|
|
|
|
// list folders
|
|
names = fileSystem->ListFiles( path, "/", true, true );
|
|
for( i = 0; i < names->GetNumFiles(); i++ )
|
|
{
|
|
idStr name = names->GetFile( i );
|
|
if( stripFolder )
|
|
{
|
|
name.Strip( folder );
|
|
}
|
|
else
|
|
{
|
|
name.Strip( "/" );
|
|
}
|
|
name = args.Argv( 0 ) + ( " " + name ) + "/";
|
|
completionParms.Append( name );
|
|
}
|
|
fileSystem->FreeFileList( names );
|
|
|
|
// list files
|
|
va_start( argPtr, stripFolder );
|
|
for( extension = va_arg( argPtr, const char* ); extension; extension = va_arg( argPtr, const char* ) )
|
|
{
|
|
names = fileSystem->ListFiles( path, extension, true, true );
|
|
for( i = 0; i < names->GetNumFiles(); i++ )
|
|
{
|
|
idStr name = names->GetFile( i );
|
|
if( stripFolder )
|
|
{
|
|
name.Strip( folder );
|
|
}
|
|
else
|
|
{
|
|
name.Strip( "/" );
|
|
}
|
|
name = args.Argv( 0 ) + ( " " + name );
|
|
completionParms.Append( name );
|
|
}
|
|
fileSystem->FreeFileList( names );
|
|
}
|
|
va_end( argPtr );
|
|
}
|
|
for( i = 0; i < completionParms.Num(); i++ )
|
|
{
|
|
callback( completionParms[i] );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::ArgCompletion_DeclName
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::ArgCompletion_DeclName( const idCmdArgs& args, void( *callback )( const char* s ), int type )
|
|
{
|
|
int i, num;
|
|
|
|
if( declManager == NULL )
|
|
{
|
|
return;
|
|
}
|
|
num = declManager->GetNumDecls( ( declType_t )type );
|
|
for( i = 0; i < num; i++ )
|
|
{
|
|
callback( idStr( args.Argv( 0 ) ) + " " + declManager->DeclByIndex( ( declType_t )type, i , false )->GetName() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::SetupReloadEngine
|
|
============
|
|
*/
|
|
void idCmdSystemLocal::SetupReloadEngine( const idCmdArgs& args )
|
|
{
|
|
BufferCommandText( CMD_EXEC_APPEND, "reloadEngine\n" );
|
|
postReload = args;
|
|
}
|
|
|
|
/*
|
|
============
|
|
idCmdSystemLocal::PostReloadEngine
|
|
============
|
|
*/
|
|
bool idCmdSystemLocal::PostReloadEngine()
|
|
{
|
|
if( !postReload.Argc() )
|
|
{
|
|
return false;
|
|
}
|
|
BufferCommandArgs( CMD_EXEC_APPEND, postReload );
|
|
postReload.Clear();
|
|
return true;
|
|
}
|