CmdSystem.cpp 20 KB

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