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