CmdSystem.cpp (20450B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 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. 23 24 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. 25 26 =========================================================================== 27 */ 28 29 #include "../idlib/precompiled.h" 30 #pragma hdrstop 31 32 #ifdef ID_RETAIL 33 idCVar net_allowCheats( "net_allowCheats", "0", CVAR_BOOL | CVAR_ROM, "Allow cheats in multiplayer" ); 34 #else 35 idCVar net_allowCheats( "net_allowCheats", "0", CVAR_BOOL | CVAR_NOCHEAT, "Allow cheats in multiplayer" ); 36 #endif 37 38 /* 39 =============================================================================== 40 41 idCmdSystemLocal 42 43 =============================================================================== 44 */ 45 46 typedef struct commandDef_s { 47 struct commandDef_s * next; 48 char * name; 49 cmdFunction_t function; 50 argCompletion_t argCompletion; 51 int flags; 52 char * description; 53 } commandDef_t; 54 55 /* 56 ================================================ 57 idCmdSystemLocal 58 ================================================ 59 */ 60 class idCmdSystemLocal : public idCmdSystem { 61 public: 62 virtual void Init(); 63 virtual void Shutdown(); 64 65 virtual void AddCommand( const char *cmdName, cmdFunction_t function, int flags, const char *description, argCompletion_t argCompletion = NULL ); 66 virtual void RemoveCommand( const char *cmdName ); 67 virtual void RemoveFlaggedCommands( int flags ); 68 69 virtual void CommandCompletion( void(*callback)( const char *s ) ); 70 virtual void ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ); 71 virtual void ExecuteCommandText( const char * text ); 72 virtual void AppendCommandText( const char * text ); 73 74 virtual void BufferCommandText( cmdExecution_t exec, const char *text ); 75 virtual void ExecuteCommandBuffer(); 76 77 virtual void ArgCompletion_FolderExtension( const idCmdArgs &args, void(*callback)( const char *s ), const char *folder, bool stripFolder, ... ); 78 virtual void ArgCompletion_DeclName( const idCmdArgs &args, void(*callback)( const char *s ), int type ); 79 80 virtual void BufferCommandArgs( cmdExecution_t exec, const idCmdArgs &args ); 81 82 virtual void SetupReloadEngine( const idCmdArgs &args ); 83 virtual bool PostReloadEngine(); 84 85 void SetWait( int numFrames ) { wait = numFrames; } 86 commandDef_t * GetCommands() const { return commands; } 87 88 private: 89 static const int MAX_CMD_BUFFER = 0x10000; 90 91 commandDef_t * commands; 92 93 int wait; 94 int textLength; 95 byte textBuf[MAX_CMD_BUFFER]; 96 97 idStr completionString; 98 idStrList completionParms; 99 100 // piggybacks on the text buffer, avoids tokenize again and screwing it up 101 idList<idCmdArgs> tokenizedCmds; 102 103 // a command stored to be executed after a reloadEngine and all associated commands have been processed 104 idCmdArgs postReload; 105 106 private: 107 void ExecuteTokenizedString( const idCmdArgs &args ); 108 void InsertCommandText( const char *text ); 109 110 static void ListByFlags( const idCmdArgs &args, cmdFlags_t flags ); 111 static void List_f( const idCmdArgs &args ); 112 static void SystemList_f( const idCmdArgs &args ); 113 static void RendererList_f( const idCmdArgs &args ); 114 static void SoundList_f( const idCmdArgs &args ); 115 static void GameList_f( const idCmdArgs &args ); 116 static void ToolList_f( const idCmdArgs &args ); 117 static void Exec_f( const idCmdArgs &args ); 118 static void Vstr_f( const idCmdArgs &args ); 119 static void Echo_f( const idCmdArgs &args ); 120 static void Parse_f( const idCmdArgs &args ); 121 static void Wait_f( const idCmdArgs &args ); 122 static void PrintMemInfo_f( const idCmdArgs &args ); 123 }; 124 125 idCmdSystemLocal cmdSystemLocal; 126 idCmdSystem * cmdSystem = &cmdSystemLocal; 127 128 /* 129 ================================================ 130 idSort_CommandDef 131 ================================================ 132 */ 133 class idSort_CommandDef : public idSort_Quick< commandDef_t, idSort_CommandDef > { 134 public: 135 int Compare( const commandDef_t & a, const commandDef_t & b ) const { return idStr::Icmp( a.name, b.name ); } 136 }; 137 138 /* 139 ============ 140 idCmdSystemLocal::ListByFlags 141 ============ 142 */ 143 void idCmdSystemLocal::ListByFlags( const idCmdArgs &args, cmdFlags_t flags ) { 144 int i; 145 idStr match; 146 const commandDef_t *cmd; 147 idList<const commandDef_t *> cmdList; 148 149 if ( args.Argc() > 1 ) { 150 match = args.Args( 1, -1 ); 151 match.Replace( " ", "" ); 152 } else { 153 match = ""; 154 } 155 156 for ( cmd = cmdSystemLocal.GetCommands(); cmd; cmd = cmd->next ) { 157 if ( !( cmd->flags & flags ) ) { 158 continue; 159 } 160 if ( match.Length() && idStr( cmd->name ).Filter( match, false ) == 0 ) { 161 continue; 162 } 163 164 cmdList.Append( cmd ); 165 } 166 167 //cmdList.SortWithTemplate( idSort_CommandDef() ); 168 169 for ( i = 0; i < cmdList.Num(); i++ ) { 170 cmd = cmdList[i]; 171 172 common->Printf( " %-21s %s\n", cmd->name, cmd->description ); 173 } 174 175 common->Printf( "%i commands\n", cmdList.Num() ); 176 } 177 178 /* 179 ============ 180 idCmdSystemLocal::List_f 181 ============ 182 */ 183 void idCmdSystemLocal::List_f( const idCmdArgs &args ) { 184 idCmdSystemLocal::ListByFlags( args, CMD_FL_ALL ); 185 } 186 187 /* 188 ============ 189 idCmdSystemLocal::SystemList_f 190 ============ 191 */ 192 void idCmdSystemLocal::SystemList_f( const idCmdArgs &args ) { 193 idCmdSystemLocal::ListByFlags( args, CMD_FL_SYSTEM ); 194 } 195 196 /* 197 ============ 198 idCmdSystemLocal::RendererList_f 199 ============ 200 */ 201 void idCmdSystemLocal::RendererList_f( const idCmdArgs &args ) { 202 idCmdSystemLocal::ListByFlags( args, CMD_FL_RENDERER ); 203 } 204 205 /* 206 ============ 207 idCmdSystemLocal::SoundList_f 208 ============ 209 */ 210 void idCmdSystemLocal::SoundList_f( const idCmdArgs &args ) { 211 idCmdSystemLocal::ListByFlags( args, CMD_FL_SOUND ); 212 } 213 214 /* 215 ============ 216 idCmdSystemLocal::GameList_f 217 ============ 218 */ 219 void idCmdSystemLocal::GameList_f( const idCmdArgs &args ) { 220 idCmdSystemLocal::ListByFlags( args, CMD_FL_GAME ); 221 } 222 223 /* 224 ============ 225 idCmdSystemLocal::ToolList_f 226 ============ 227 */ 228 void idCmdSystemLocal::ToolList_f( const idCmdArgs &args ) { 229 idCmdSystemLocal::ListByFlags( args, CMD_FL_TOOL ); 230 } 231 232 /* 233 =============== 234 idCmdSystemLocal::Exec_f 235 =============== 236 */ 237 void idCmdSystemLocal::Exec_f( const idCmdArgs &args ) { 238 char * f; 239 int len; 240 idStr filename; 241 242 if ( args.Argc () != 2 ) { 243 common->Printf( "exec <filename> : execute a script file\n" ); 244 return; 245 } 246 247 filename = args.Argv(1); 248 filename.DefaultFileExtension( ".cfg" ); 249 len = fileSystem->ReadFile( filename, reinterpret_cast<void **>(&f), NULL ); 250 if ( !f ) { 251 common->Printf( "couldn't exec %s\n", args.Argv(1) ); 252 return; 253 } 254 common->Printf( "execing %s\n", args.Argv(1) ); 255 256 cmdSystemLocal.BufferCommandText( CMD_EXEC_INSERT, f ); 257 258 fileSystem->FreeFile( f ); 259 } 260 261 /* 262 =============== 263 idCmdSystemLocal::Vstr_f 264 265 Inserts the current value of a cvar as command text 266 =============== 267 */ 268 void idCmdSystemLocal::Vstr_f( const idCmdArgs &args ) { 269 const char *v; 270 271 if ( args.Argc () != 2 ) { 272 common->Printf( "vstr <variablename> : execute a variable command\n" ); 273 return; 274 } 275 276 v = cvarSystem->GetCVarString( args.Argv( 1 ) ); 277 278 cmdSystemLocal.BufferCommandText( CMD_EXEC_APPEND, va( "%s\n", v ) ); 279 } 280 281 /* 282 =============== 283 idCmdSystemLocal::Echo_f 284 285 Just prints the rest of the line to the console 286 =============== 287 */ 288 void idCmdSystemLocal::Echo_f( const idCmdArgs &args ) { 289 int i; 290 291 for ( i = 1; i < args.Argc(); i++ ) { 292 common->Printf( "%s ", args.Argv( i ) ); 293 } 294 common->Printf( "\n" ); 295 } 296 297 /* 298 ============ 299 idCmdSystemLocal::Wait_f 300 301 Causes execution of the remainder of the command buffer to be delayed until next frame. 302 ============ 303 */ 304 void idCmdSystemLocal::Wait_f( const idCmdArgs &args ) { 305 if ( args.Argc() == 2 ) { 306 cmdSystemLocal.SetWait( atoi( args.Argv( 1 ) ) ); 307 } else { 308 cmdSystemLocal.SetWait( 1 ); 309 } 310 } 311 312 /* 313 ============ 314 idCmdSystemLocal::Parse_f 315 316 This just prints out how the rest of the line was parsed, as a debugging tool. 317 ============ 318 */ 319 void idCmdSystemLocal::Parse_f( const idCmdArgs &args ) { 320 int i; 321 322 for ( i = 0; i < args.Argc(); i++ ) { 323 common->Printf( "%i: %s\n", i, args.Argv(i) ); 324 } 325 } 326 327 /* 328 ============ 329 idCmdSystemLocal::Init 330 ============ 331 */ 332 void idCmdSystemLocal::Init() { 333 334 AddCommand( "listCmds", List_f, CMD_FL_SYSTEM, "lists commands" ); 335 AddCommand( "listSystemCmds", SystemList_f, CMD_FL_SYSTEM, "lists system commands" ); 336 AddCommand( "listRendererCmds", RendererList_f, CMD_FL_SYSTEM, "lists renderer commands" ); 337 AddCommand( "listSoundCmds", SoundList_f, CMD_FL_SYSTEM, "lists sound commands" ); 338 AddCommand( "listGameCmds", GameList_f, CMD_FL_SYSTEM, "lists game commands" ); 339 AddCommand( "listToolCmds", ToolList_f, CMD_FL_SYSTEM, "lists tool commands" ); 340 AddCommand( "exec", Exec_f, CMD_FL_SYSTEM, "executes a config file", ArgCompletion_ConfigName ); 341 AddCommand( "vstr", Vstr_f, CMD_FL_SYSTEM, "inserts the current value of a cvar as command text" ); 342 AddCommand( "echo", Echo_f, CMD_FL_SYSTEM, "prints text" ); 343 AddCommand( "parse", Parse_f, CMD_FL_SYSTEM, "prints tokenized string" ); 344 AddCommand( "wait", Wait_f, CMD_FL_SYSTEM, "delays remaining buffered commands one or more frames" ); 345 346 // link in all the commands declared with static idCommandLink variables or CONSOLE_COMMAND macros 347 for ( idCommandLink * link = CommandLinks(); link != NULL; link = link->next ) { 348 AddCommand( link->cmdName_, link->function_, CMD_FL_SYSTEM, link->description_, link->argCompletion_ ); 349 } 350 351 completionString = "*"; 352 353 textLength = 0; 354 } 355 356 /* 357 ============ 358 idCmdSystemLocal::Shutdown 359 ============ 360 */ 361 void idCmdSystemLocal::Shutdown() { 362 commandDef_t *cmd; 363 364 for ( cmd = commands; cmd; cmd = commands ) { 365 commands = commands->next; 366 Mem_Free( cmd->name ); 367 Mem_Free( cmd->description ); 368 delete cmd; 369 } 370 371 completionString.Clear(); 372 completionParms.Clear(); 373 tokenizedCmds.Clear(); 374 postReload.Clear(); 375 } 376 377 /* 378 ============ 379 idCmdSystemLocal::AddCommand 380 ============ 381 */ 382 void idCmdSystemLocal::AddCommand( const char *cmdName, cmdFunction_t function, int flags, const char *description, argCompletion_t argCompletion ) { 383 commandDef_t *cmd; 384 385 // fail if the command already exists 386 for ( cmd = commands; cmd; cmd = cmd->next ) { 387 if ( idStr::Cmp( cmdName, cmd->name ) == 0 ) { 388 if ( function != cmd->function ) { 389 common->Printf( "idCmdSystemLocal::AddCommand: %s already defined\n", cmdName ); 390 } 391 return; 392 } 393 } 394 395 cmd = new (TAG_SYSTEM) commandDef_t; 396 cmd->name = Mem_CopyString( cmdName ); 397 cmd->function = function; 398 cmd->argCompletion = argCompletion; 399 cmd->flags = flags; 400 cmd->description = Mem_CopyString( description ); 401 cmd->next = commands; 402 commands = cmd; 403 } 404 405 /* 406 ============ 407 idCmdSystemLocal::RemoveCommand 408 ============ 409 */ 410 void idCmdSystemLocal::RemoveCommand( const char *cmdName ) { 411 commandDef_t *cmd, **last; 412 413 for ( last = &commands, cmd = *last; cmd; cmd = *last ) { 414 if ( idStr::Cmp( cmdName, cmd->name ) == 0 ) { 415 *last = cmd->next; 416 Mem_Free( cmd->name ); 417 Mem_Free( cmd->description ); 418 delete cmd; 419 return; 420 } 421 last = &cmd->next; 422 } 423 } 424 425 /* 426 ============ 427 idCmdSystemLocal::RemoveFlaggedCommands 428 ============ 429 */ 430 void idCmdSystemLocal::RemoveFlaggedCommands( int flags ) { 431 commandDef_t *cmd, **last; 432 433 for ( last = &commands, cmd = *last; cmd; cmd = *last ) { 434 if ( cmd->flags & flags ) { 435 *last = cmd->next; 436 Mem_Free( cmd->name ); 437 Mem_Free( cmd->description ); 438 delete cmd; 439 continue; 440 } 441 last = &cmd->next; 442 } 443 } 444 445 /* 446 ============ 447 idCmdSystemLocal::CommandCompletion 448 ============ 449 */ 450 void idCmdSystemLocal::CommandCompletion( void(*callback)( const char *s ) ) { 451 commandDef_t *cmd; 452 453 for ( cmd = commands; cmd; cmd = cmd->next ) { 454 callback( cmd->name ); 455 } 456 } 457 458 /* 459 ============ 460 idCmdSystemLocal::ArgCompletion 461 ============ 462 */ 463 void idCmdSystemLocal::ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ) { 464 commandDef_t *cmd; 465 idCmdArgs args; 466 467 args.TokenizeString( cmdString, false ); 468 469 for ( cmd = commands; cmd; cmd = cmd->next ) { 470 if ( !cmd->argCompletion ) { 471 continue; 472 } 473 if ( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 ) { 474 cmd->argCompletion( args, callback ); 475 break; 476 } 477 } 478 } 479 480 /* 481 ============ 482 idCmdSystemLocal::ExecuteTokenizedString 483 ============ 484 */ 485 void idCmdSystemLocal::ExecuteTokenizedString( const idCmdArgs &args ) { 486 commandDef_t *cmd, **prev; 487 488 // execute the command line 489 if ( !args.Argc() ) { 490 return; // no tokens 491 } 492 493 // check registered command functions 494 for ( prev = &commands; *prev; prev = &cmd->next ) { 495 cmd = *prev; 496 if ( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 ) { 497 // rearrange the links so that the command will be 498 // near the head of the list next time it is used 499 *prev = cmd->next; 500 cmd->next = commands; 501 commands = cmd; 502 503 if ( ( cmd->flags & (CMD_FL_CHEAT|CMD_FL_TOOL) ) && common->IsMultiplayer() && !net_allowCheats.GetBool() ) { 504 common->Printf( "Command '%s' not valid in multiplayer mode.\n", cmd->name ); 505 return; 506 } 507 // perform the action 508 if ( !cmd->function ) { 509 break; 510 } else { 511 cmd->function( args ); 512 } 513 return; 514 } 515 } 516 517 // check cvars 518 if ( cvarSystem->Command( args ) ) { 519 return; 520 } 521 522 common->Printf( "Unknown command '%s'\n", args.Argv( 0 ) ); 523 } 524 525 /* 526 ============ 527 idCmdSystemLocal::ExecuteCommandText 528 529 Tokenizes, then executes. 530 ============ 531 */ 532 void idCmdSystemLocal::ExecuteCommandText( const char *text ) { 533 ExecuteTokenizedString( idCmdArgs( text, false ) ); 534 } 535 536 /* 537 ============ 538 idCmdSystemLocal::InsertCommandText 539 540 Adds command text immediately after the current command 541 Adds a \n to the text 542 ============ 543 */ 544 void idCmdSystemLocal::InsertCommandText( const char *text ) { 545 int len; 546 int i; 547 548 len = strlen( text ) + 1; 549 if ( len + textLength > (int)sizeof( textBuf ) ) { 550 common->Printf( "idCmdSystemLocal::InsertText: buffer overflow\n" ); 551 return; 552 } 553 554 // move the existing command text 555 for ( i = textLength - 1; i >= 0; i-- ) { 556 textBuf[ i + len ] = textBuf[ i ]; 557 } 558 559 // copy the new text in 560 memcpy( textBuf, text, len - 1 ); 561 562 // add a \n 563 textBuf[ len - 1 ] = '\n'; 564 565 textLength += len; 566 } 567 568 /* 569 ============ 570 idCmdSystemLocal::AppendCommandText 571 572 Adds command text at the end of the buffer, does NOT add a final \n 573 ============ 574 */ 575 void idCmdSystemLocal::AppendCommandText( const char *text ) { 576 int l; 577 578 l = strlen( text ); 579 580 if ( textLength + l >= (int)sizeof( textBuf ) ) { 581 common->Printf( "idCmdSystemLocal::AppendText: buffer overflow\n" ); 582 return; 583 } 584 memcpy( textBuf + textLength, text, l ); 585 textLength += l; 586 } 587 588 /* 589 ============ 590 idCmdSystemLocal::BufferCommandText 591 ============ 592 */ 593 void idCmdSystemLocal::BufferCommandText( cmdExecution_t exec, const char *text ) { 594 switch( exec ) { 595 case CMD_EXEC_NOW: { 596 ExecuteCommandText( text ); 597 break; 598 } 599 case CMD_EXEC_INSERT: { 600 InsertCommandText( text ); 601 break; 602 } 603 case CMD_EXEC_APPEND: { 604 AppendCommandText( text ); 605 break; 606 } 607 default: { 608 common->FatalError( "idCmdSystemLocal::BufferCommandText: bad exec type" ); 609 } 610 } 611 } 612 613 /* 614 ============ 615 idCmdSystemLocal::BufferCommandArgs 616 ============ 617 */ 618 void idCmdSystemLocal::BufferCommandArgs( cmdExecution_t exec, const idCmdArgs &args ) { 619 switch ( exec ) { 620 case CMD_EXEC_NOW: { 621 ExecuteTokenizedString( args ); 622 break; 623 } 624 case CMD_EXEC_APPEND: { 625 AppendCommandText( "_execTokenized\n" ); 626 tokenizedCmds.Append( args ); 627 break; 628 } 629 default: { 630 common->FatalError( "idCmdSystemLocal::BufferCommandArgs: bad exec type" ); 631 } 632 } 633 } 634 635 /* 636 ============ 637 idCmdSystemLocal::ExecuteCommandBuffer 638 ============ 639 */ 640 void idCmdSystemLocal::ExecuteCommandBuffer() { 641 int i; 642 char * text; 643 int quotes; 644 idCmdArgs args; 645 646 while( textLength ) { 647 648 if ( wait ) { 649 // skip out while text still remains in buffer, leaving it for next frame 650 wait--; 651 break; 652 } 653 654 // find a \n or ; line break 655 text = (char *)textBuf; 656 657 quotes = 0; 658 for ( i = 0; i < textLength; i++ ) { 659 if ( text[i] == '"' ) { 660 quotes++; 661 } 662 if ( !( quotes & 1 ) && text[i] == ';' ) { 663 break; // don't break if inside a quoted string 664 } 665 if ( text[i] == '\n' || text[i] == '\r' ) { 666 break; 667 } 668 } 669 670 text[i] = 0; 671 672 if ( !idStr::Cmp( text, "_execTokenized" ) ) { 673 args = tokenizedCmds[ 0 ]; 674 tokenizedCmds.RemoveIndex( 0 ); 675 } else { 676 args.TokenizeString( text, false ); 677 } 678 679 // delete the text from the command buffer and move remaining commands down 680 // this is necessary because commands (exec) can insert data at the 681 // beginning of the text buffer 682 683 if ( i == textLength ) { 684 textLength = 0; 685 } else { 686 i++; 687 textLength -= i; 688 memmove( text, text+i, textLength ); 689 } 690 691 // execute the command line that we have already tokenized 692 ExecuteTokenizedString( args ); 693 } 694 } 695 696 /* 697 ============ 698 idCmdSystemLocal::ArgCompletion_FolderExtension 699 ============ 700 */ 701 void idCmdSystemLocal::ArgCompletion_FolderExtension( const idCmdArgs &args, void(*callback)( const char *s ), const char *folder, bool stripFolder, ... ) { 702 int i; 703 idStr string; 704 const char *extension; 705 va_list argPtr; 706 707 string = args.Argv( 0 ); 708 string += " "; 709 string += args.Argv( 1 ); 710 711 if ( string.Icmp( completionString ) != 0 ) { 712 idStr parm, path; 713 idFileList *names; 714 715 completionString = string; 716 completionParms.Clear(); 717 718 parm = args.Argv( 1 ); 719 parm.ExtractFilePath( path ); 720 if ( stripFolder || path.Length() == 0 ) { 721 path = folder + path; 722 } 723 path.StripTrailing( '/' ); 724 725 // list folders 726 names = fileSystem->ListFiles( path, "/", true, true ); 727 for ( i = 0; i < names->GetNumFiles(); i++ ) { 728 idStr name = names->GetFile( i ); 729 if ( stripFolder ) { 730 name.Strip( folder ); 731 } else { 732 name.Strip( "/" ); 733 } 734 name = args.Argv( 0 ) + ( " " + name ) + "/"; 735 completionParms.Append( name ); 736 } 737 fileSystem->FreeFileList( names ); 738 739 // list files 740 va_start( argPtr, stripFolder ); 741 for ( extension = va_arg( argPtr, const char * ); extension; extension = va_arg( argPtr, const char * ) ) { 742 names = fileSystem->ListFiles( path, extension, true, true ); 743 for ( i = 0; i < names->GetNumFiles(); i++ ) { 744 idStr name = names->GetFile( i ); 745 if ( stripFolder ) { 746 name.Strip( folder ); 747 } else { 748 name.Strip( "/" ); 749 } 750 name = args.Argv( 0 ) + ( " " + name ); 751 completionParms.Append( name ); 752 } 753 fileSystem->FreeFileList( names ); 754 } 755 va_end( argPtr ); 756 } 757 for ( i = 0; i < completionParms.Num(); i++ ) { 758 callback( completionParms[i] ); 759 } 760 } 761 762 /* 763 ============ 764 idCmdSystemLocal::ArgCompletion_DeclName 765 ============ 766 */ 767 void idCmdSystemLocal::ArgCompletion_DeclName( const idCmdArgs &args, void(*callback)( const char *s ), int type ) { 768 int i, num; 769 770 if ( declManager == NULL ) { 771 return; 772 } 773 num = declManager->GetNumDecls( (declType_t)type ); 774 for ( i = 0; i < num; i++ ) { 775 callback( idStr( args.Argv( 0 ) ) + " " + declManager->DeclByIndex( (declType_t)type, i , false )->GetName() ); 776 } 777 } 778 779 /* 780 ============ 781 idCmdSystemLocal::SetupReloadEngine 782 ============ 783 */ 784 void idCmdSystemLocal::SetupReloadEngine( const idCmdArgs &args ) { 785 BufferCommandText( CMD_EXEC_APPEND, "reloadEngine\n" ); 786 postReload = args; 787 } 788 789 /* 790 ============ 791 idCmdSystemLocal::PostReloadEngine 792 ============ 793 */ 794 bool idCmdSystemLocal::PostReloadEngine() { 795 if ( !postReload.Argc() ) { 796 return false; 797 } 798 BufferCommandArgs( CMD_EXEC_APPEND, postReload ); 799 postReload.Clear(); 800 return true; 801 }