Configuration Variables
-----------------------

  $Id: cvar.txt,v 1.2 2001/08/12 08:04:54 knghtbrd Exp $

  The Configuration Variable system used in Project Twilight is a more
  dynamic version of the Console Variable system used by NQ/QW.  It's fair
  to say that it more resembles the Cvar code used by Q3A, but is actually
  even more flexible than that, although the structure has not changed
  significantly:

    typedef struct cvar_s {
        char               *name;
        char               *string;
        float               value;
        int                 flags;

        void              (*callback) (struct cvar_s *var);
    } cvar_t;


  Comparing this with the QW Cvar system illustrates a few differences
  right from the start.  First, the boolean values for archive and info
  are gone, replaced by a flags bitfield.  There is now a function which 
  will be called when the Cvar changes, if defined.  The real change,
  however, is in the API used to manipulate Cvars.

  To create a Cvar, declare a pointer for it

    cvar_t     *_windowed mouse;

  and find a good place to initialize it.  Initializing a Cvar is done
  with the Cvar_Get function.

    _windowed_mouse = Cvar_Get ("_windowed_mouse", "1", CVAR_ARCHIVE,
    	                NULL);

  Now Q3A does not have a _windowed_mouse Cvar, but I can tell you that if
  it did, its declaration would look almost exactly like the above, with
  the notable exception of the NULL passed as the last parameter.  Here's
  the formal declaration of Cvar_Get:

    cvar_t *
    Cvar_Get (
        const char *name,             // name as it appears to users
        const char *value,            // default value of the Cvar
        const int flags,              // bitfield for special flags
        const cvar_callback callback  // function called on change
    );

  A Cvar's default value is a string, which will often represent at least
  one number.  It is possible for a Cvar to contain up to five numbers,
  just seperate them in the string with spaces or commas.

  The flags bitfield recognizes several flags.  All of the ones which
  really matter are implemented, but a couple of them do not yet perform
  their assigned tasks.  Here's the list:

    CVAR_NONE           Cvar has no flags
    CVAR_ARCHIVE        Cvar should be saved on exit
    CVAR_USER           Cvar was created by the user
    CVAR_TEMP           Cvar was created by gamecode
    CVAR_USERINFO       Cvar is sent to the server
    CVAR_SERVERINFO     FIXME: QWism, not yet implemented
    CVAR_ROM            Cvar cannot be changed by user

  CVAR_TEMP variables are not implemented yet, but will allow the gamecode
  to create variables on the client which will be deleted upon disconnect
  from the server.  If combined with code to allow saving settings in a
  file on the client's machine, this could allow games the opportunity to
  store persistant information about preferred settings and other things.

  Note that Cvar_Get does not necessarily create a Cvar.  It is possible
  to create a Cvar on the command line, in which Cvar_Get will simply
  update the flags and callback of the Cvar, but not otherwise modify it.
  This is useful for Cvars which normally have the flag CVAR_ROM, such as
  those relating to filesystem locations of necessary files.  The user may
  specify these locations on the command line, but as soon as one of them
  is returned via Cvar_Get, its flags will contain CVAR_ROM instead of
  CVAR_USER, and it may not be changed from that point onward by the user.

  The callback function, if set, is called upon Cvar_Get, and then again
  on Cvar_Sets which modify its value.  Outside of one of these callback
  functions, the contents of the Cvar structure should never be altered by
  any portion of the engine.  A callback function, on the other hand, may
  freely modify its data members at will, enforcing range limits or
  whatever else is desired.  If a modification made to a Cvar is to change
  its numerical value(s), the string should be updated to reflect this as
  it is the string which is reported when a user queries a Cvar's content.


  Using a Cvar once you have created it is fairly straightforward.  If the
  Cvar contains a string, where you would have referred to var.string
  before, use var->string now.  If you would have referred to var.value,
  you'd use var->value instead.  If the Cvar does not contain numeric data
  the value will be 0.0.


  It is sometimes necessary to iterate through every Cvar, even though
  this is generally considered to be something you should not do if you
  can avoid it.  In case you ever need to do it, three functions have been
  created to help.  Here are their declarations:

    struct cvar_foreach_s *
    Cvar_ForeachStart (void);

    cvar_t *
    Cvar_ForeachNext (
        struct cvar_foreach_s *id     // Search ID
    );

    void
    Cvar_ForeachEnd (
        struct cvar_foreach_s *id     // Search ID
    );

  Create a pointer to a struct cvar_foreach_s and assign the result of
  Cvar_ForeachStart to it.  Then call Cvar_ForeachNext with that pointer
  as its argument until you've either found what you're looking for or you
  get a NULL back for a Cvar, at which point you've reached the end of the
  list.  Cvar_ForeachEnd frees up any memory used by this process.  If you
  really need to go through the entire list, that's all there is to doing
  it.  The contents of cvar_foreach_s should be considered opaque and are
  subject to change.


  There is another way to find a single Cvar if you need to do so, based
  on its name:

  cvar_t *
  Cvar_Find (
        const char *name              // user-visible name of the Cvar
  );


  That's really all there is to the Cvar system.  It's really quite simple
  once you get the hang of it.

