cvar.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. // cvar.c -- dynamic variable tracking
  2. #include "../game/q_shared.h"
  3. #include "qcommon.h"
  4. cvar_t *cvar_vars;
  5. cvar_t *cvar_cheats;
  6. int cvar_modifiedFlags;
  7. #define MAX_CVARS 1024
  8. cvar_t cvar_indexes[MAX_CVARS];
  9. int cvar_numIndexes;
  10. cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force);
  11. static char *lastMemPool = NULL;
  12. static int memPoolSize;
  13. //If the string came from the memory pool, don't really free it. The entire
  14. //memory pool will be wiped during the next level load.
  15. static void Cvar_FreeString(char *string)
  16. {
  17. if(!lastMemPool || string < lastMemPool ||
  18. string >= lastMemPool + memPoolSize) {
  19. Z_Free(string);
  20. }
  21. }
  22. /*
  23. ============
  24. Cvar_ValidateString
  25. ============
  26. */
  27. static qboolean Cvar_ValidateString( const char *s ) {
  28. if ( !s ) {
  29. return qfalse;
  30. }
  31. if ( strchr( s, '\\' ) ) {
  32. return qfalse;
  33. }
  34. if ( strchr( s, '\"' ) ) {
  35. return qfalse;
  36. }
  37. if ( strchr( s, ';' ) ) {
  38. return qfalse;
  39. }
  40. return qtrue;
  41. }
  42. /*
  43. ============
  44. Cvar_FindVar
  45. ============
  46. */
  47. static cvar_t *Cvar_FindVar( const char *var_name ) {
  48. cvar_t *var;
  49. for (var=cvar_vars ; var ; var=var->next) {
  50. if (!Q_stricmp(var_name, var->name)) {
  51. return var;
  52. }
  53. }
  54. return NULL;
  55. }
  56. /*
  57. ============
  58. Cvar_VariableValue
  59. ============
  60. */
  61. float Cvar_VariableValue( const char *var_name ) {
  62. cvar_t *var;
  63. var = Cvar_FindVar (var_name);
  64. if (!var)
  65. return 0;
  66. return var->value;
  67. }
  68. /*
  69. ============
  70. Cvar_VariableIntegerValue
  71. ============
  72. */
  73. int Cvar_VariableIntegerValue( const char *var_name ) {
  74. cvar_t *var;
  75. var = Cvar_FindVar (var_name);
  76. if (!var)
  77. return 0;
  78. return var->integer;
  79. }
  80. /*
  81. ============
  82. Cvar_VariableString
  83. ============
  84. */
  85. char *Cvar_VariableString( const char *var_name ) {
  86. cvar_t *var;
  87. var = Cvar_FindVar (var_name);
  88. if (!var)
  89. return "";
  90. return var->string;
  91. }
  92. /*
  93. ============
  94. Cvar_VariableStringBuffer
  95. ============
  96. */
  97. void Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) {
  98. cvar_t *var;
  99. var = Cvar_FindVar (var_name);
  100. if (!var) {
  101. *buffer = 0;
  102. }
  103. else {
  104. Q_strncpyz( buffer, var->string, bufsize );
  105. }
  106. }
  107. /*
  108. ============
  109. Cvar_CompleteVariable
  110. ============
  111. */
  112. char *Cvar_CompleteVariable( const char *partial ) {
  113. cvar_t *cvar;
  114. int len;
  115. len = strlen(partial);
  116. if ( !len ) {
  117. return NULL;
  118. }
  119. // check partial match
  120. for ( cvar=cvar_vars ; cvar ; cvar=cvar->next ) {
  121. if ( !Q_stricmpn (partial,cvar->name, len) ) {
  122. if ( (cvar->flags & CVAR_CHEAT) && !cvar_cheats->integer ) {
  123. continue;
  124. }
  125. else {
  126. return cvar->name;
  127. }
  128. }
  129. }
  130. return NULL;
  131. }
  132. /*
  133. ============
  134. Cvar_CompleteVariableNext - get the next cvar in alphabetical order.
  135. ============
  136. */
  137. char *Cvar_CompleteVariableNext (char *partial, char *last)
  138. {
  139. cvar_t *cvar, *base;
  140. int len;
  141. len = strlen(partial);
  142. if (!len)
  143. return NULL;
  144. // this check needed since cvars may be resetting from cmd searches
  145. base = NULL;
  146. if(last)
  147. {
  148. for (cvar=cvar_vars; cvar; cvar = cvar->next)
  149. {
  150. if(!Q_stricmp(last, cvar->name))
  151. {
  152. base = cvar->next;
  153. break;
  154. }
  155. }
  156. if(base == NULL)
  157. { //not found, either error or at end of list
  158. return NULL;
  159. }
  160. }
  161. else
  162. {
  163. base = cvar_vars;
  164. }
  165. // check partial match
  166. for (cvar=base ; cvar ; cvar=cvar->next)
  167. {
  168. if (!Q_stricmpn (partial,cvar->name, len)) {
  169. if ( (cvar->flags & CVAR_CHEAT) && !cvar_cheats->integer ) {
  170. continue;
  171. }
  172. else {
  173. return cvar->name;
  174. }
  175. }
  176. }
  177. return NULL;
  178. }
  179. /*
  180. ============
  181. Cvar_Get
  182. If the variable already exists, the value will not be set unless CVAR_ROM
  183. The flags will be or'ed in if the variable exists.
  184. ============
  185. */
  186. cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
  187. cvar_t *var;
  188. if ( !var_name || ! var_value ) {
  189. Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" );
  190. }
  191. if ( !Cvar_ValidateString( var_name ) ) {
  192. Com_Printf("invalid cvar name string: %s\n", var_name );
  193. var_name = "BADNAME";
  194. }
  195. #if 0 // FIXME: values with backslash happen
  196. if ( !Cvar_ValidateString( var_value ) ) {
  197. Com_Printf("invalid cvar value string: %s\n", var_value );
  198. var_value = "BADVALUE";
  199. }
  200. #endif
  201. var = Cvar_FindVar (var_name);
  202. if ( var ) {
  203. // if the C code is now specifying a variable that the user already
  204. // set a value for, take the new value as the reset value
  205. if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED )
  206. && var_value[0] ) {
  207. var->flags &= ~CVAR_USER_CREATED;
  208. Cvar_FreeString( var->resetString );
  209. var->resetString = CopyString( var_value );
  210. // ZOID--needs to be set so that cvars the game sets as
  211. // SERVERINFO get sent to clients
  212. cvar_modifiedFlags |= flags;
  213. }
  214. var->flags |= flags;
  215. // only allow one non-empty reset string without a warning
  216. if ( !var->resetString[0] ) {
  217. // we don't have a reset string yet
  218. Cvar_FreeString( var->resetString );
  219. var->resetString = CopyString( var_value );
  220. } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) {
  221. Com_Printf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n",
  222. var_name, var->resetString, var_value );
  223. }
  224. // if we have a latched string, take that value now
  225. if ( var->latchedString ) {
  226. char *s;
  227. s = var->latchedString;
  228. var->latchedString = NULL; // otherwise cvar_set2 would free it
  229. Cvar_Set2( var_name, s, qtrue );
  230. Cvar_FreeString( s );
  231. }
  232. // use a CVAR_SET for rom sets, get won't override
  233. #if 0
  234. // CVAR_ROM always overrides
  235. if ( flags & CVAR_ROM ) {
  236. Cvar_Set2( var_name, var_value, qtrue );
  237. }
  238. #endif
  239. return var;
  240. }
  241. //
  242. // allocate a new cvar
  243. //
  244. if ( cvar_numIndexes == MAX_CVARS ) {
  245. Com_Error( ERR_FATAL, "MAX_CVARS" );
  246. }
  247. var = &cvar_indexes[cvar_numIndexes];
  248. cvar_numIndexes++;
  249. var->name = CopyString (var_name);
  250. var->string = CopyString (var_value);
  251. var->modified = qtrue;
  252. var->modificationCount = 1;
  253. var->value = atof (var->string);
  254. var->integer = atoi(var->string);
  255. var->resetString = CopyString( var_value );
  256. // link the variable in
  257. var->next = cvar_vars;
  258. cvar_vars = var;
  259. var->flags = flags;
  260. return var;
  261. }
  262. /*
  263. ============
  264. Cvar_Set2
  265. ============
  266. */
  267. cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
  268. cvar_t *var;
  269. Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value );
  270. if ( !Cvar_ValidateString( var_name ) ) {
  271. Com_Printf("invalid cvar name string: %s\n", var_name );
  272. var_name = "BADNAME";
  273. }
  274. #if 0 // FIXME
  275. if ( value && !Cvar_ValidateString( value ) ) {
  276. Com_Printf("invalid cvar value string: %s\n", value );
  277. var_value = "BADVALUE";
  278. }
  279. #endif
  280. var = Cvar_FindVar (var_name);
  281. if (!var) {
  282. if ( !value ) {
  283. return NULL;
  284. }
  285. // create it
  286. if ( !force ) {
  287. return Cvar_Get( var_name, value, CVAR_USER_CREATED );
  288. } else {
  289. return Cvar_Get (var_name, value, 0);
  290. }
  291. }
  292. if (!value ) {
  293. value = var->resetString;
  294. }
  295. // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
  296. cvar_modifiedFlags |= var->flags;
  297. if (!force)
  298. {
  299. if (var->flags & CVAR_ROM)
  300. {
  301. Com_Printf ("%s is read only.\n", var_name);
  302. return var;
  303. }
  304. if (var->flags & CVAR_INIT)
  305. {
  306. Com_Printf ("%s is write protected.\n", var_name);
  307. return var;
  308. }
  309. if (var->flags & CVAR_LATCH)
  310. {
  311. if (var->latchedString)
  312. {
  313. if (strcmp(value, var->latchedString) == 0)
  314. return var;
  315. Cvar_FreeString (var->latchedString);
  316. }
  317. else
  318. {
  319. if (strcmp(value, var->string) == 0)
  320. return var;
  321. }
  322. Com_Printf ("%s will be changed upon restarting.\n", var_name);
  323. var->latchedString = CopyString(value);
  324. var->modified = qtrue;
  325. var->modificationCount++;
  326. return var;
  327. }
  328. if ( (var->flags & CVAR_CHEAT) && !cvar_cheats->integer )
  329. {
  330. Com_Printf ("%s is cheat protected.\n", var_name);
  331. return var;
  332. }
  333. }
  334. else
  335. {
  336. if (var->latchedString)
  337. {
  338. Cvar_FreeString (var->latchedString);
  339. var->latchedString = NULL;
  340. }
  341. }
  342. if (!strcmp(value, var->string))
  343. return var; // not changed
  344. var->modified = qtrue;
  345. var->modificationCount++;
  346. Cvar_FreeString (var->string); // free the old value string
  347. var->string = CopyString(value);
  348. var->value = atof (var->string);
  349. var->integer = atoi (var->string);
  350. return var;
  351. }
  352. /*
  353. ============
  354. Cvar_Set
  355. ============
  356. */
  357. void Cvar_Set( const char *var_name, const char *value) {
  358. Cvar_Set2 (var_name, value, qtrue);
  359. }
  360. /*
  361. ============
  362. Cvar_SetValue
  363. ============
  364. */
  365. void Cvar_SetValue( const char *var_name, float value) {
  366. char val[32];
  367. if ( value == (int)value ) {
  368. Com_sprintf (val, sizeof(val), "%i",(int)value);
  369. } else {
  370. Com_sprintf (val, sizeof(val), "%f",value);
  371. }
  372. Cvar_Set (var_name, val);
  373. }
  374. /*
  375. ============
  376. Cvar_Reset
  377. ============
  378. */
  379. void Cvar_Reset( const char *var_name ) {
  380. Cvar_Set2( var_name, NULL, qfalse );
  381. }
  382. /*
  383. ============
  384. Cvar_SetCheatState
  385. Any testing variables will be reset to the safe values
  386. ============
  387. */
  388. void Cvar_SetCheatState( void ) {
  389. cvar_t *var;
  390. // set all default vars to the safe value
  391. for ( var = cvar_vars ; var ; var = var->next ) {
  392. if ( var->flags & CVAR_CHEAT) {
  393. Cvar_Set( var->name, var->resetString );
  394. }
  395. }
  396. }
  397. /*
  398. ============
  399. Cvar_Command
  400. Handles variable inspection and changing from the console
  401. ============
  402. */
  403. qboolean Cvar_Command( void ) {
  404. cvar_t *v;
  405. // check variables
  406. v = Cvar_FindVar (Cmd_Argv(0));
  407. if (!v) {
  408. return qfalse;
  409. }
  410. // perform a variable print or set
  411. if ( Cmd_Argc() == 1 ) {
  412. Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\" default:\"%s" S_COLOR_WHITE "\"\n", v->name, v->string, v->resetString );
  413. if ( v->latchedString ) {
  414. Com_Printf( "latched: \"%s\"\n", v->latchedString );
  415. }
  416. return qtrue;
  417. }
  418. //JFM toggle test
  419. char *value;
  420. value = Cmd_Argv(1);
  421. if (value[0] =='!') //toggle
  422. {
  423. char buff[5];
  424. sprintf(buff,"%i",!v->value);
  425. Cvar_Set2 (v->name, buff, qfalse);// toggle the value
  426. }
  427. else
  428. Cvar_Set2 (v->name, value, qfalse);// set the value if forcing isn't required
  429. return qtrue;
  430. }
  431. /*
  432. ============
  433. Cvar_Toggle_f
  434. Toggles a cvar for easy single key binding
  435. ============
  436. */
  437. void Cvar_Toggle_f( void ) {
  438. int v;
  439. if ( Cmd_Argc() != 2 ) {
  440. Com_Printf ("usage: toggle <variable>\n");
  441. return;
  442. }
  443. v = Cvar_VariableIntegerValue( Cmd_Argv( 1 ) );
  444. v = !v;
  445. Cvar_Set2 (Cmd_Argv(1), va("%i", v), qfalse);
  446. }
  447. /*
  448. ============
  449. Cvar_Set_f
  450. Allows setting and defining of arbitrary cvars from console, even if they
  451. weren't declared in C code.
  452. ============
  453. */
  454. void Cvar_Set_f( void ) {
  455. int i, c, l, len;
  456. char combined[MAX_STRING_TOKENS];
  457. c = Cmd_Argc();
  458. if ( c < 3 ) {
  459. Com_Printf ("usage: set <variable> <value>\n");
  460. return;
  461. }
  462. combined[0] = 0;
  463. l = 0;
  464. for ( i = 2 ; i < c ; i++ ) {
  465. len = strlen ( Cmd_Argv( i ) + 1 );
  466. if ( l + len >= MAX_STRING_TOKENS - 2 ) {
  467. break;
  468. }
  469. strcat( combined, Cmd_Argv( i ) );
  470. if ( i != c-1 ) {
  471. strcat( combined, " " );
  472. }
  473. l += len;
  474. }
  475. Cvar_Set2 (Cmd_Argv(1), combined, qfalse);
  476. }
  477. /*
  478. ============
  479. Cvar_SetU_f
  480. As Cvar_Set, but also flags it as userinfo
  481. ============
  482. */
  483. void Cvar_SetU_f( void ) {
  484. cvar_t *v;
  485. if ( Cmd_Argc() != 3 ) {
  486. Com_Printf ("usage: setu <variable> <value>\n");
  487. return;
  488. }
  489. Cvar_Set_f();
  490. v = Cvar_FindVar( Cmd_Argv( 1 ) );
  491. if ( !v ) {
  492. return;
  493. }
  494. v->flags |= CVAR_USERINFO;
  495. }
  496. /*
  497. ============
  498. Cvar_SetS_f
  499. As Cvar_Set, but also flags it as userinfo
  500. ============
  501. */
  502. void Cvar_SetS_f( void ) {
  503. cvar_t *v;
  504. if ( Cmd_Argc() != 3 ) {
  505. Com_Printf ("usage: sets <variable> <value>\n");
  506. return;
  507. }
  508. Cvar_Set_f();
  509. v = Cvar_FindVar( Cmd_Argv( 1 ) );
  510. if ( !v ) {
  511. return;
  512. }
  513. v->flags |= CVAR_SERVERINFO;
  514. }
  515. /*
  516. ============
  517. Cvar_SetA_f
  518. As Cvar_Set, but also flags it as archived
  519. ============
  520. */
  521. void Cvar_SetA_f( void ) {
  522. cvar_t *v;
  523. if ( Cmd_Argc() != 3 ) {
  524. Com_Printf ("usage: seta <variable> <value>\n");
  525. return;
  526. }
  527. Cvar_Set_f();
  528. v = Cvar_FindVar( Cmd_Argv( 1 ) );
  529. if ( !v ) {
  530. return;
  531. }
  532. v->flags |= CVAR_ARCHIVE;
  533. }
  534. /*
  535. ============
  536. Cvar_Reset_f
  537. ============
  538. */
  539. void Cvar_Reset_f( void ) {
  540. if ( Cmd_Argc() != 2 ) {
  541. Com_Printf ("usage: reset <variable>\n");
  542. return;
  543. }
  544. Cvar_Reset( Cmd_Argv( 1 ) );
  545. }
  546. /*
  547. ============
  548. Cvar_WriteVariables
  549. Appends lines containing "set variable value" for all variables
  550. with the archive flag set to qtrue.
  551. ============
  552. */
  553. void Cvar_WriteVariables( fileHandle_t f ) {
  554. #ifndef _XBOX
  555. cvar_t *var;
  556. char buffer[1024];
  557. for (var = cvar_vars ; var ; var = var->next) {
  558. if (var->flags & CVAR_ARCHIVE ) {
  559. // write the latched value, even if it hasn't taken effect yet
  560. if ( var->latchedString ) {
  561. Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->latchedString);
  562. } else {
  563. Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->string);
  564. }
  565. FS_Printf (f, "%s", buffer);
  566. }
  567. }
  568. #endif
  569. }
  570. /*
  571. ============
  572. Cvar_List_f
  573. ============
  574. */
  575. void Cvar_List_f( void ) {
  576. cvar_t *var;
  577. int i;
  578. char *match;
  579. if ( Cmd_Argc() > 1 ) {
  580. match = Cmd_Argv( 1 );
  581. } else {
  582. match = NULL;
  583. }
  584. i = 0;
  585. for (var = cvar_vars ; var ; var = var->next, i++)
  586. {
  587. if (match && !Com_Filter(match, var->name, qfalse)) continue;
  588. if (var->flags & CVAR_SERVERINFO) {
  589. Com_Printf("S");
  590. } else {
  591. Com_Printf(" ");
  592. }
  593. if (var->flags & CVAR_USERINFO) {
  594. Com_Printf("U");
  595. } else {
  596. Com_Printf(" ");
  597. }
  598. if (var->flags & CVAR_ROM) {
  599. Com_Printf("R");
  600. } else {
  601. Com_Printf(" ");
  602. }
  603. if (var->flags & CVAR_INIT) {
  604. Com_Printf("I");
  605. } else {
  606. Com_Printf(" ");
  607. }
  608. if (var->flags & CVAR_ARCHIVE) {
  609. Com_Printf("A");
  610. } else {
  611. Com_Printf(" ");
  612. }
  613. if (var->flags & CVAR_LATCH) {
  614. Com_Printf("L");
  615. } else {
  616. Com_Printf(" ");
  617. }
  618. if (var->flags & CVAR_CHEAT) {
  619. if (!cvar_cheats->integer)
  620. {
  621. i--;
  622. continue;
  623. }
  624. Com_Printf("C");
  625. } else {
  626. Com_Printf(" ");
  627. }
  628. Com_Printf (" %s \"%s\"\n", var->name, var->string);
  629. }
  630. Com_Printf ("\n%i total cvars\n", i);
  631. }
  632. /*
  633. ============
  634. Cvar_Restart_f
  635. Resets all cvars to their hardcoded values
  636. ============
  637. */
  638. void Cvar_Restart_f( void ) {
  639. cvar_t *var;
  640. cvar_t **prev;
  641. prev = &cvar_vars;
  642. while ( 1 ) {
  643. var = *prev;
  644. if ( !var ) {
  645. break;
  646. }
  647. // don't mess with rom values, or some inter-module
  648. // communication will get broken (com_cl_running, etc)
  649. if ( var->flags & ( CVAR_ROM | CVAR_INIT | CVAR_NORESTART ) ) {
  650. prev = &var->next;
  651. continue;
  652. }
  653. // throw out any variables the user created
  654. if ( var->flags & CVAR_USER_CREATED ) {
  655. *prev = var->next;
  656. if ( var->name ) {
  657. Cvar_FreeString( var->name );
  658. }
  659. if ( var->string ) {
  660. Cvar_FreeString( var->string );
  661. }
  662. if ( var->latchedString ) {
  663. Cvar_FreeString( var->latchedString );
  664. }
  665. if ( var->resetString ) {
  666. Cvar_FreeString( var->resetString );
  667. }
  668. // clear the var completely, since we
  669. // can't remove the index from the list
  670. memset( var, 0, sizeof( var ) );
  671. continue;
  672. }
  673. Cvar_Set( var->name, var->resetString );
  674. prev = &var->next;
  675. }
  676. }
  677. /*
  678. =====================
  679. Cvar_InfoString
  680. =====================
  681. */
  682. char *Cvar_InfoString( int bit ) {
  683. static char info[MAX_INFO_STRING];
  684. cvar_t *var;
  685. info[0] = 0;
  686. for (var = cvar_vars ; var ; var = var->next) {
  687. if (var->flags & bit) {
  688. Info_SetValueForKey (info, var->name, var->string);
  689. }
  690. }
  691. return info;
  692. }
  693. /*
  694. =====================
  695. Cvar_InfoStringBuffer
  696. =====================
  697. */
  698. void Cvar_InfoStringBuffer( int bit, char* buff, int buffsize ) {
  699. Q_strncpyz(buff,Cvar_InfoString(bit),buffsize);
  700. }
  701. /*
  702. =====================
  703. Cvar_Register
  704. basically a slightly modified Cvar_Get for the interpreted modules
  705. =====================
  706. */
  707. void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) {
  708. cvar_t *cv;
  709. cv = Cvar_Get( varName, defaultValue, flags );
  710. if ( !vmCvar ) {
  711. return;
  712. }
  713. vmCvar->handle = cv - cvar_indexes;
  714. vmCvar->modificationCount = -1;
  715. Cvar_Update( vmCvar );
  716. }
  717. /*
  718. =====================
  719. Cvar_Register
  720. updates an interpreted modules' version of a cvar
  721. =====================
  722. */
  723. void Cvar_Update( vmCvar_t *vmCvar ) {
  724. cvar_t *cv;
  725. if ( (unsigned)vmCvar->handle >= cvar_numIndexes ) {
  726. Com_Error( ERR_DROP, "Cvar_Update: handle out of range" );
  727. }
  728. cv = cvar_indexes + vmCvar->handle;
  729. if ( cv->modificationCount == vmCvar->modificationCount ) {
  730. return;
  731. }
  732. if ( !cv->string ) {
  733. return; // variable might have been cleared by a cvar_restart
  734. }
  735. vmCvar->modificationCount = cv->modificationCount;
  736. Q_strncpyz( vmCvar->string, cv->string, sizeof( vmCvar->string ) );
  737. vmCvar->value = cv->value;
  738. vmCvar->integer = cv->integer;
  739. }
  740. /*
  741. ============
  742. Cvar_Init
  743. Reads in all archived cvars
  744. ============
  745. */
  746. void Cvar_Init (void) {
  747. cvar_cheats = Cvar_Get("helpUsObi", "0", CVAR_SYSTEMINFO );
  748. Cmd_AddCommand ("toggle", Cvar_Toggle_f);
  749. Cmd_AddCommand ("set", Cvar_Set_f);
  750. Cmd_AddCommand ("sets", Cvar_SetS_f);
  751. Cmd_AddCommand ("setu", Cvar_SetU_f);
  752. Cmd_AddCommand ("seta", Cvar_SetA_f);
  753. Cmd_AddCommand ("reset", Cvar_Reset_f);
  754. Cmd_AddCommand ("cvarlist", Cvar_List_f);
  755. Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
  756. }
  757. static void Cvar_Realloc(char **string, char *memPool, int &memPoolUsed)
  758. {
  759. if(string && *string)
  760. {
  761. char *temp = memPool + memPoolUsed;
  762. strcpy(temp, *string);
  763. memPoolUsed += strlen(*string) + 1;
  764. Cvar_FreeString(*string);
  765. *string = temp;
  766. }
  767. }
  768. //Turns many small allocation blocks into one big one.
  769. void Cvar_Defrag(void)
  770. {
  771. cvar_t *var;
  772. int totalMem = 0;
  773. int nextMemPoolSize;
  774. for (var = cvar_vars; var; var = var->next)
  775. {
  776. if (var->name) {
  777. totalMem += strlen(var->name) + 1;
  778. }
  779. if (var->string) {
  780. totalMem += strlen(var->string) + 1;
  781. }
  782. if (var->resetString) {
  783. totalMem += strlen(var->resetString) + 1;
  784. }
  785. if (var->latchedString) {
  786. totalMem += strlen(var->latchedString) + 1;
  787. }
  788. }
  789. char *mem = (char*)Z_Malloc(totalMem, TAG_SMALL, qfalse);
  790. nextMemPoolSize = totalMem;
  791. totalMem = 0;
  792. for (var = cvar_vars; var; var = var->next)
  793. {
  794. Cvar_Realloc(&var->name, mem, totalMem);
  795. Cvar_Realloc(&var->string, mem, totalMem);
  796. Cvar_Realloc(&var->resetString, mem, totalMem);
  797. Cvar_Realloc(&var->latchedString, mem, totalMem);
  798. }
  799. if(lastMemPool) {
  800. Z_Free(lastMemPool);
  801. }
  802. lastMemPool = mem;
  803. memPoolSize = nextMemPoolSize;
  804. }