Changeset - r3115:f1eba3dacb95
[Not reviewed]
master
0 3 0
Darkvater - 19 years ago 2006-03-01 23:53:20
darkvater@openttd.org
(svn r3719) - [1/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. This first part rewrites the configuration section to use the SaveLoad VarType in general.
- This unified structure consists of a SaveLoad type which stores all data relevant about the variable internals such as type, mem/filesize, address, version-control. The SettingDesc type is concerned more about the representation. Things like default value, string-name, minimum/maximum values, gui-behaviour etc.
- The SaveLoad type has received a few flags controlling saving/loading. These are:
SLF_SAVE_NO: the setting is not saved with the savegame, effectively making this setting player-based. Eg. it will NOT be overwritten when joining a network-game
SLF_CONFIG_NO: the setting is not saved to the configuration file so you cannot overwrite it ingame.
SLF_NETWORK_NO: the setting is not synchronised with the local settings when the game is loaded during network-play. Note that when SLF_SAVE_NO is set, SLF_NETWORK_NO is also set (which is logical), at least if the proper macros are used (in [2/4]).
- NOTE! The game is not compilable after this commit.
3 files changed with 225 insertions and 224 deletions:
0 comments (0 inline, 0 general)
saveload.h
Show inline comments
 
@@ -123,12 +123,19 @@ enum VarTypes {
 

	
 
	/* Shortcut values */
 
	SLE_UINT = SLE_UINT32,
 
	SLE_INT  = SLE_INT32,
 
	SLE_STRB = SLE_STRINGBUF,
 
	SLE_STRQ = SLE_STRINGQUOTE,
 

	
 
	/* 8 bytes allocated for a maximum of 8 flags
 
	 * Flags directing saving/loading of a variable */
 
	SLF_SAVE_NO      = 1 <<  8, ///< do not save with savegame, basically player-based
 
	SLF_CONFIG_NO    = 1 <<  9, ///< do not save to config file
 
	SLF_NETWORK_NO   = 1 << 10, ///< do not synchronize over network (but it is saved if SSF_SAVE_NO is not set)
 
	/* 5 more possible flags */
 
};
 

	
 
typedef uint32 VarType;
 

	
 
enum SaveLoadTypes {
 
	SL_VAR       = 0,
settings.c
Show inline comments
 
@@ -410,13 +410,13 @@ static int parse_intlist(const char *p, 
 
/* Load parsed string-values into an integer-array (intlist)
 
 * @param str the string that contains the values (and will be parsed)
 
 * @param array pointer to the integer-arrays that will be filled
 
 * @param nelems the number of elements the array holds. Maximum is 64 elements
 
 * @param type the type of elements the array holds (eg INT8, UINT16, etc.)
 
 * @return return true on success and false on error */
 
static bool load_intlist(const char *str, void *array, int nelems, int type)
 
static bool load_intlist(const char *str, void *array, int nelems, VarType type)
 
{
 
	int items[64];
 
	int i, nitems;
 

	
 
	if (str == NULL) {
 
		memset(items, 0, sizeof(items));
 
@@ -424,22 +424,23 @@ static bool load_intlist(const char *str
 
	} else {
 
		nitems = parse_intlist(str, items, lengthof(items));
 
		if (nitems != nelems) return false;
 
	}
 

	
 
	switch (type) {
 
	case SDT_INT8:
 
	case SDT_UINT8:
 
	case SLE_VAR_BL:
 
	case SLE_VAR_I8:
 
	case SLE_VAR_U8:
 
		for (i = 0; i != nitems; i++) ((byte*)array)[i] = items[i];
 
		break;
 
	case SDT_INT16:
 
	case SDT_UINT16:
 
	case SLE_VAR_I16:
 
	case SLE_VAR_U16:
 
		for (i = 0; i != nitems; i++) ((uint16*)array)[i] = items[i];
 
		break;
 
	case SDT_INT32:
 
	case SDT_UINT32:
 
	case SLE_VAR_I32:
 
	case SLE_VAR_U32:
 
		for (i = 0; i != nitems; i++) ((uint32*)array)[i] = items[i];
 
		break;
 
	default: NOT_REACHED();
 
	}
 

	
 
	return true;
 
@@ -448,25 +449,26 @@ static bool load_intlist(const char *str
 
/* Convert an integer-array (intlist) to a string representation. Each value
 
 * is seperated by a comma
 
 * @param buf output buffer where the string-representation will be stored
 
 * @param array pointer to the integer-arrays that is read from
 
 * @param nelems the number of elements the array holds.
 
 * @param type the type of elements the array holds (eg INT8, UINT16, etc.) */
 
static void make_intlist(char *buf, const void *array, int nelems, int type)
 
static void make_intlist(char *buf, const void *array, int nelems, VarType type)
 
{
 
	int i, v = 0;
 
	const byte *p = (const byte*)array;
 

	
 
	for (i = 0; i != nelems; i++) {
 
		switch (type) {
 
		case SDT_INT8:   v = *(int8*)p;   p += 1; break;
 
		case SDT_UINT8:  v = *(byte*)p;   p += 1; break;
 
		case SDT_INT16:  v = *(int16*)p;  p += 2; break;
 
		case SDT_UINT16: v = *(uint16*)p; p += 2; break;
 
		case SDT_INT32:  v = *(int32*)p;  p += 4; break;
 
		case SDT_UINT32: v = *(uint32*)p; p += 4; break;
 
		case SLE_VAR_BL:
 
		case SLE_VAR_I8:  v = *(int8*)p;   p += 1; break;
 
		case SLE_VAR_U8:  v = *(byte*)p;   p += 1; break;
 
		case SLE_VAR_I16: v = *(int16*)p;  p += 2; break;
 
		case SLE_VAR_U16: v = *(uint16*)p; p += 2; break;
 
		case SLE_VAR_I32: v = *(int32*)p;  p += 4; break;
 
		case SLE_VAR_U32: v = *(uint32*)p; p += 4; break;
 
		default: NOT_REACHED();
 
		}
 
		buf += sprintf(buf, (i == 0) ? "%d" : ",%d", v);
 
	}
 
}
 

	
 
@@ -523,35 +525,19 @@ static void make_manyofmany(char *buf, c
 
		if (*many == '|') many++;
 
	}
 

	
 
	*buf = '\0';
 
}
 

	
 
/* Get the GenericType of a setting. This describes the main type
 
 * @param desc pointer to SettingDesc structure
 
 * @return return GenericType, see SettingDescType */
 
static inline int GetSettingGenericType(const SettingDesc *desc)
 
{
 
	return desc->flags & 0xFF00; // GB(desc->flags, 8, 8) << 8;
 
}
 

	
 
/* Get the NumberType of a setting. This describes the integer type
 
 * @param desc pointer to SettingDesc structure
 
 * @return return NumberType, see SettingDescType */
 
static inline int GetSettingNumberType(const SettingDesc *desc)
 
{
 
	return desc->flags & 0xF0; // GB(desc->flags, 4, 8); << 4
 
}
 

	
 
/** Convert a string representation (external) of a setting to the internal rep.
 
 * @param desc SettingDesc struct that holds all information about the variable
 
 * @param str input string that will be parsed based on the type of desc
 
 * @return return the parsed value of the setting */
 
static const void *string_to_val(const SettingDesc *desc, const char *str)
 
static const void *string_to_val(const SettingDescBase *desc, const char *str)
 
{
 
	switch (GetSettingGenericType(desc)) {
 
	switch (desc->cmd) {
 
	case SDT_NUMX: {
 
		char *end;
 
		unsigned long val = strtoul(str, &end, 0);
 
		if (*end != '\0') ShowInfoF("ini: trailing characters at end of setting '%s'", desc->name);
 
		return (void*)val;
 
	}
 
@@ -572,87 +558,95 @@ static const void *string_to_val(const S
 
			return (void*)true;
 
		if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0)
 
			return (void*)false;
 
		ShowInfoF("ini: invalid setting value '%s' for '%s'", str, desc->name);
 
		break;
 

	
 
	case SDT_STR:
 
	case SDT_STRB:
 
	case SDT_STRQ:
 
	case SDT_INTLIST:
 
	case SDT_CHAR:
 
		return str;
 
	case SDT_STRING:
 
	case SDT_INTLIST: return str;
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/** Set the value of a setting and if needed clamp the value to
 
 * the preset minimum and maximum.
 
 * @param ptr the variable itself
 
 * @param sd pointer to the 'information'-database of the variable
 
 * @param val signed long version of the new value
 
 * @pre SettingDesc is of type SDT_BOOLX, SDT_NUMX,
 
 * SDT_ONEOFMANY or SDT_MANYOFMANY. Other types are not supported as of now */
 
static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
 
{
 
	const SettingDescBase *sdb = &sd->desc;
 
	int32 min;
 

	
 
	if (sdb->cmd != SDT_BOOLX && sdb->cmd != SDT_NUMX &&
 
		  sdb->cmd != SDT_ONEOFMANY && sdb->cmd != SDT_MANYOFMANY) return;
 

	
 
	/* Override the minimum value. No value below sdb->min, except special value 0 */
 
	min = ((sdb->flags & SGF_0ISDISABLED) && val <= sdb->min) ? 0 : sdb->min;
 
	/* We cannot know the maximum value of a bitset variable, so just have faith */
 
	val = (sdb->cmd == SDT_MANYOFMANY) ? val : clamp(val, min, sdb->max);
 

	
 
	WriteValue(ptr, sd->save.conv, (int64)val);
 
}
 

	
 
/** Load values from a group of an IniFile structure into the internal representation
 
 * @param ini pointer to IniFile structure that holds administrative information
 
 * @param desc pointer to SettingDesc structure whose internally pointed variables will
 
 *        be given values
 
 * @param grpname the group of the IniFile to search in for the new values */
 
static void load_setting_desc(IniFile *ini, const SettingDesc *desc, const char *grpname)
 
static void ini_load_settings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object)
 
{
 
	IniGroup *group_def = ini_getgroup(ini, grpname, -1), *group;
 
	IniGroup *group;
 
	IniGroup *group_def = ini_getgroup(ini, grpname, -1);
 
	IniItem *item;
 
	const void *p;
 
	void *ptr;
 
	const char *s;
 

	
 
	for (;desc->name != NULL; desc++) {
 
	for (; sd->save.cmd != SL_END; sd++) {
 
		const SettingDescBase *sdb = &sd->desc;
 
		const SaveLoad        *sld = &sd->save;
 

	
 
		// XXX - wtf is this?? (group override?)
 
		const char *s = strchr(desc->name, '.');
 
		s = strchr(sdb->name, '.');
 
		if (s != NULL) {
 
			group = ini_getgroup(ini, desc->name, s - desc->name);
 
			group = ini_getgroup(ini, sdb->name, s - sdb->name);
 
			s++;
 
		} else {
 
			s = desc->name;
 
			s = sdb->name;
 
			group = group_def;
 
		}
 

	
 
		item = ini_getitem(group, s, false);
 
		p = (item == NULL) ? desc->def : string_to_val(desc, item->value);
 
		p = (item == NULL) ? sdb->def : string_to_val(sdb, item->value);
 
		ptr = ini_get_variable(sld, object);
 

	
 
		/* get pointer to the variable */
 
		ptr = desc->ptr;
 

	
 
		/* The main type of a variable/setting is in bytes 8-15
 
		 * The subtype (what kind of numbers do we have there) is in 0-7 */
 
		switch (GetSettingGenericType(desc)) {
 
		switch (sdb->cmd) {
 
		case SDT_BOOLX: /* All four are various types of (integer) numbers */
 
		case SDT_NUMX:
 
		case SDT_ONEOFMANY:
 
		case SDT_MANYOFMANY:
 
			switch (GetSettingNumberType(desc)) {
 
			case SDT_INT8:
 
			case SDT_UINT8:  *(byte*)ptr   = (byte)(unsigned long)p;   break;
 
			case SDT_INT16:
 
			case SDT_UINT16: *(uint16*)ptr = (uint16)(unsigned long)p; break;
 
			case SDT_INT32:
 
			case SDT_UINT32: *(uint32*)ptr = (uint32)(unsigned long)p; break;
 
			default: NOT_REACHED(); break;
 
			Write_ValidateSetting(ptr, sd, (unsigned long)p); break;
 

	
 
		case SDT_STRING:
 
			switch (GetVarMemType(sld->conv)) {
 
				case SLE_VAR_STRB:
 
				case SLE_VAR_STRQ:
 
					if (p != NULL) ttd_strlcpy((char*)ptr, p, sld->length);
 
					break;
 
				case SLE_VAR_CHAR: *(char*)ptr = *(char*)p; break;
 
				default: NOT_REACHED(); break;
 
			}
 
			break;
 

	
 
		case SDT_STR:
 
			free(*(char**)ptr);
 
			*(char**)ptr = strdup((const char*)p);
 
			break;
 

	
 
		case SDT_STRB:
 
		case SDT_STRQ:
 
			if (p != NULL) ttd_strlcpy((char*)ptr, p, GB(desc->flags, 16, 16));
 
			break;
 

	
 
		case SDT_CHAR:
 
			*(char*)ptr = *(char*)p;
 
			break;
 

	
 
		case SDT_INTLIST: {
 
			if (!load_intlist(p, ptr, GB(desc->flags, 16, 16), GetSettingNumberType(desc)))
 
				ShowInfoF("ini: error in array '%s'", desc->name);
 
			if (!load_intlist(p, ptr, sld->length, GetVarMemType(sld->conv)))
 
				ShowInfoF("ini: error in array '%s'", sdb->name);
 
			break;
 
		}
 
		default: NOT_REACHED(); break;
 
		}
 
	}
 
}
 
@@ -662,128 +656,154 @@ static void load_setting_desc(IniFile *i
 
 * @param desc read-only SettingDesc structure which contains the unmodified,
 
 *        loaded values of the configuration file and various information about it
 
 * @param grpname holds the name of the group (eg. [network]) where these will be saved
 
 * The function works as follows: for each item in the SettingDesc structure we have
 
 * a look if the value has changed since we started the game (the original values
 
 * are reloaded when saving). If settings indeed have changed, we get these and save them.*/
 
static void save_setting_desc(IniFile *ini, const SettingDesc *desc, const char *grpname)
 
static void ini_save_settings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object)
 
{
 
	IniGroup *group_def = NULL, *group;
 
	IniItem *item;
 
	const void *p;
 
	char buf[512];
 
	const char *s;
 
	void *ptr;
 
	uint32 i = 0;
 
	char buf[512]; // setting buffer
 
	const char *s;
 

	
 
	for (; desc->name != NULL; desc++) {
 
		if (desc->flags & SDT_NOSAVE) continue;
 
	for (; sd->save.cmd != SL_END; sd++) {
 
		const SettingDescBase *sdb = &sd->desc;
 
		const SaveLoad        *sld = &sd->save;
 

	
 
		/* If the setting is not saved to the configuration
 
		 * file, just continue with the next setting */
 
		if (sld->conv & SLF_CONFIG_NO) continue;
 

	
 
		// XXX - wtf is this?? (group override?)
 
		s = strchr(desc->name, '.');
 
		s = strchr(sdb->name, '.');
 
		if (s != NULL) {
 
			group = ini_getgroup(ini, desc->name, s - desc->name);
 
			group = ini_getgroup(ini, sdb->name, s - sdb->name);
 
			s++;
 
		} else {
 
			if (group_def == NULL) group_def = ini_getgroup(ini, grpname, -1);
 
			s = desc->name;
 
			s = sdb->name;
 
			group = group_def;
 
		}
 

	
 
		item = ini_getitem(group, s, true);
 

	
 
		/* get pointer to the variable */
 
		ptr = desc->ptr;
 
		ptr = ini_get_variable(sld, object);
 

	
 
		if (item->value != NULL) {
 
			// check if the value is the same as the old value
 
			p = string_to_val(desc, item->value);
 
			const void *p = string_to_val(sdb, item->value);
 

	
 
			/* The main type of a variable/setting is in bytes 8-15
 
			* The subtype (what kind of numbers do we have there) is in 0-7 */
 
			switch (GetSettingGenericType(desc)) {
 
			switch (sdb->cmd) {
 
			case SDT_BOOLX:
 
			case SDT_NUMX:
 
			case SDT_ONEOFMANY:
 
			case SDT_MANYOFMANY:
 
				switch (GetSettingNumberType(desc)) {
 
				case SDT_INT8:
 
				case SDT_UINT8:
 
				switch (GetVarMemType(sld->conv)) {
 
				case SLE_VAR_BL:
 
				case SLE_VAR_I8:
 
				case SLE_VAR_U8:
 
					if (*(byte*)ptr == (byte)(unsigned long)p) continue;
 
					break;
 
				case SDT_INT16:
 
				case SDT_UINT16:
 
				case SLE_VAR_I16:
 
				case SLE_VAR_U16:
 
					if (*(uint16*)ptr == (uint16)(unsigned long)p) continue;
 
					break;
 
				case SDT_INT32:
 
				case SDT_UINT32:
 
				case SLE_VAR_I32:
 
				case SLE_VAR_U32:
 
					if (*(uint32*)ptr == (uint32)(unsigned long)p) continue;
 
					break;
 
				default: NOT_REACHED();
 
				}
 
				break;
 
			case SDT_STR: assert(0); break;
 
			default: break; /* Assume the other types are always changed */
 
			}
 
		}
 

	
 
		/* Value has changed, get the new value and put it into a buffer */
 
		switch (GetSettingGenericType(desc)) {
 
		switch (sdb->cmd) {
 
		case SDT_BOOLX:
 
		case SDT_NUMX:
 
		case SDT_ONEOFMANY:
 
		case SDT_MANYOFMANY:
 
			switch (GetSettingNumberType(desc)) {
 
			case SDT_INT8:   i = *(int8*)ptr;   break;
 
			case SDT_UINT8:  i = *(byte*)ptr;   break;
 
			case SDT_INT16:  i = *(int16*)ptr;  break;
 
			case SDT_UINT16: i = *(uint16*)ptr; break;
 
			case SDT_INT32:  i = *(int32*)ptr;  break;
 
			case SDT_UINT32: i = *(uint32*)ptr; break;
 
		case SDT_MANYOFMANY: {
 
			uint32 i = (uint32)ReadValue(ptr, sld->conv);
 

	
 
			switch (sdb->cmd) {
 
			case SDT_BOOLX:      strcpy(buf, (i != 0) ? "true" : "false"); break;
 
			case SDT_NUMX:       sprintf(buf, "%u", i); break;
 
			case SDT_ONEOFMANY:  make_oneofmany(buf, sdb->many, i); break;
 
			case SDT_MANYOFMANY: make_manyofmany(buf, sdb->many, i); break;
 
			default: NOT_REACHED();
 
			}
 
		} break;
 

	
 
			switch (GetSettingGenericType(desc)) {
 
			case SDT_BOOLX:
 
				strcpy(buf, (i != 0) ? "true" : "false");
 
				break;
 
			case SDT_NUMX:
 
				sprintf(buf, "%u", i);
 
				break;
 
			case SDT_ONEOFMANY:
 
				make_oneofmany(buf, desc->many, i);
 
				break;
 
			case SDT_MANYOFMANY:
 
				make_manyofmany(buf, desc->many, i);
 
				break;
 
		case SDT_STRING:
 
			switch (GetVarMemType(sld->conv)) {
 
			case SLE_VAR_STRB: strcpy(buf, (char*)ptr); break;
 
			case SLE_VAR_STRQ: sprintf(buf, "\"%s\"", (char*)ptr); break;
 
			case SLE_VAR_CHAR: sprintf(buf, "\"%c\"", *(char*)ptr); break;
 
			default: NOT_REACHED();
 
			}
 
			break;
 

	
 
		case SDT_STR:
 
			strcpy(buf, *(char**)ptr);
 
			break;
 
		case SDT_STRB:
 
			strcpy(buf, (char*)ptr);
 
		case SDT_INTLIST:
 
			make_intlist(buf, ptr, sld->length, GetVarMemType(sld->conv));
 
			break;
 
		case SDT_STRQ:
 
			sprintf(buf, "\"%s\"", (char*)ptr);
 
			break;
 
		case SDT_CHAR:
 
			sprintf(buf, "\"%c\"", *(char*)ptr);
 
			break;
 
		case SDT_INTLIST:
 
			make_intlist(buf, ptr, GB(desc->flags, 16, 16), GetSettingNumberType(desc));
 
			break;
 
		default: NOT_REACHED();
 
		}
 

	
 
		/* The value is different, that means we have to write it to the ini */
 
		item->value = pool_strdup(&ini->pool, buf, strlen(buf));
 
	}
 
}
 

	
 
// loads all items from a *grpname section into the **list
 
static void ini_load_setting_list(IniFile *ini, const char *grpname, char **list, uint len)
 
{
 
	IniGroup *group = ini_getgroup(ini, grpname, -1);
 
	IniItem *item;
 
	uint i;
 

	
 
	if (group == NULL) return;
 

	
 
	item = group->item;
 
	for (i = 0; i != len; i++) {
 
		if (item == NULL) break;
 
		list[i] = strdup(item->value);
 
		item = item->next;
 
	}
 
}
 

	
 
static void ini_save_setting_list(IniFile *ini, const char *grpname, char **list, uint len)
 
{
 
	IniGroup *group = ini_getgroup(ini, grpname, -1);
 
	IniItem *item = NULL;
 
	uint i;
 
	bool first = true;
 

	
 
	if (group == NULL) return;
 
	group->item = NULL;
 

	
 
	for (i = 0; i != len; i++) {
 
		if (list[i] == NULL || list[i][0] == '\0') continue;
 

	
 
		if (first) { // add first item to the head of the group
 
			item = ini_item_alloc(group, list[i], strlen(list[i]));
 
			item->value = item->name;
 
			group->item = item;
 
			first = false;
 
		} else { // all other items are attached to the previous one
 
			item->next = ini_item_alloc(group, list[i], strlen(list[i]));
 
			item = item->next;
 
			item->value = item->name;
 
		}
 
	}
 
}
 

	
 
//***************************
 
// OTTD specific INI stuff
 
//***************************
 

	
 
#ifndef EXTERNAL_PLAYER
 
#define EXTERNAL_PLAYER "timidity"
 
@@ -1081,13 +1101,14 @@ static const SettingDesc currency_settin
 
	{ "to_euro",   SDT_UINT16,                                               (void*)0,   &_custom_currency.to_euro,   NULL },
 
	{ "prefix",    SDT_STRINGQUOT | lengthof(_custom_currency.prefix) << 16, NULL,       &_custom_currency.prefix,    NULL },
 
	{ "suffix",    SDT_STRINGQUOT | lengthof(_custom_currency.suffix) << 16, " credits", &_custom_currency.suffix,    NULL },
 
	{ NULL, 0, NULL, NULL, NULL }
 
};
 

	
 
typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname);
 
typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname, void *object);
 
typedef void SettingDescProcList(IniFile *ini, const char *grpname, char **list, uint len);
 

	
 
static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc)
 
{
 
	proc(ini, misc_settings,		"misc");
 
#ifdef WIN32
 
	proc(ini, win32_settings,		"win32");
 
@@ -1099,55 +1120,12 @@ static void HandleSettingDescs(IniFile *
 
	proc(ini, gameopt_settings, "gameopt");
 
	proc(ini, patch_settings,		"patches");
 
	proc(ini, patch_player_settings,		"patches");
 
	proc(ini, currency_settings,"currency");
 
}
 

	
 
// loads all items from a *grpname section into the **list
 
static void LoadList(IniFile *ini, const char *grpname, char **list, int len)
 
{
 
	IniGroup *group = ini_getgroup(ini, grpname, -1);
 
	IniItem *item;
 
	int i;
 

	
 
	if (!group)
 
		return;
 
	item = group->item;
 
	for ( i=0; i != len; i++) {
 
		if (item == NULL) break;
 
		list[i] = strdup(item->value);
 
		item = item->next;
 
	}
 
}
 

	
 
static void SaveList(IniFile *ini, const char *grpname, char **list, int len)
 
{
 
	IniGroup *group = ini_getgroup(ini, grpname, -1);
 
	IniItem *item = NULL;
 
	int i;
 
	bool first = true;
 

	
 
	if (group == NULL) return;
 
	group->item = NULL;
 

	
 
	for (i = 0; i != len; i++) {
 
		if (list[i] == NULL || list[i][0] == '\0') continue;
 

	
 
		if (first) { // add first item to the head of the group
 
			item = ini_item_alloc(group, list[i], strlen(list[i]));
 
			item->value = item->name;
 
			group->item = item;
 
			first = false;
 
		} else { // all other items are attached to the previous one
 
			item->next = ini_item_alloc(group, list[i], strlen(list[i]));
 
			item = item->next;
 
			item->value = item->name;
 
		}
 
	}
 
}
 

	
 
void LoadFromConfig(void)
 
{
 
	IniFile *ini = ini_load(_config_file);
 
	HandleSettingDescs(ini, load_setting_desc);
 
	LoadList(ini, "newgrf", _newgrf_files, lengthof(_newgrf_files));
 
#ifdef ENABLE_NETWORK
settings.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef SETTINGS_H
 
#define SETTINGS_H
 

	
 
/* Convention/Type of settings. This will be merged mostly with the SaveLoad
 
 * SLE_ enums. So it looks a bit strange. The layout is as follows:
 
 * bits 0-7: the type (size) of the variable. Eg int8, uint8, bool, etc. Same as VarTypes
 
 * bits 8-15: the generic variable type. Eg string, oneofmany, number, intlist
 
 * bits 16-31: the size of a string, an intlist (which is an implicit array). */
 
/* XXX - the GenericType will NOT be shifted in the final implementation, just for compatility */
 
#include "saveload.h"
 

	
 
/** Convention/Type of settings. This is then further specified if necessary
 
 * with the SLE_ (SLE_VAR/SLE_FILE) enums in saveload.h
 
 * @see VarTypes
 
 * @see SettingDescBase */
 
enum SettingDescType {
 
	/* 4 bytes allocated a maximum of 16 types for GenericType */
 
	SDT_NUMX        = 0 << 8, // value must be 0!!, refers to any number-type
 
	SDT_BOOLX       = 1 << 8, // a boolean number
 
	SDT_ONEOFMANY   = 2 << 8, // bitmasked number where only ONE bit may be set
 
	SDT_MANYOFMANY  = 3 << 8, // bitmasked number where MULTIPLE bits may be set
 
	SDT_INTLIST     = 4 << 8, // list of integers seperated by a comma ','
 
	SDT_STRING      = 5 << 8, // string which is only a pointer, so needs dynamic allocation
 
	SDT_STRINGBUF   = 6 << 8, // string with a fixed length, preset buffer
 
	SDT_STRINGQUOT  = 7 << 8, // string with quotation marks around it (enables spaces in string)
 
	SDT_CHAR        = 8 << 8, // single character
 
	/* 7 more possible primitives */
 
	SDT_NUMX        = 0, // any number-type
 
	SDT_BOOLX       = 1, // a boolean number
 
	SDT_ONEOFMANY   = 2, // bitmasked number where only ONE bit may be set
 
	SDT_MANYOFMANY  = 3, // bitmasked number where MULTIPLE bits may be set
 
	SDT_INTLIST     = 4, // list of integers seperated by a comma ','
 
	SDT_STRING      = 5, // string with a pre-allocated buffer
 
	/* 10 more possible primitives */
 
};
 

	
 
	/* 4 bytes allocated a maximum of 16 types for NumberType */
 
	SDT_INT8        = 0 << 4,
 
	SDT_UINT8       = 1 << 4,
 
	SDT_INT16       = 2 << 4,
 
	SDT_UINT16      = 3 << 4,
 
	SDT_INT32       = 4 << 4,
 
	SDT_UINT32      = 5 << 4,
 
	SDT_INT64       = 6 << 4,
 
	SDT_UINT64      = 7 << 4,
 
	/* 8 more possible primitives */
 

	
 
	/* Shortcut values */
 
	SDT_BOOL = SDT_BOOLX | SDT_UINT8,
 
	SDT_UINT = SDT_UINT32,
 
	SDT_INT  = SDT_INT32,
 
	SDT_STR  = SDT_STRING,
 
	SDT_STRB = SDT_STRINGBUF,
 
	SDT_STRQ = SDT_STRINGQUOT,
 

	
 
	/* The value is read from the configuration file but not saved */
 
	SDT_NOSAVE = 1 << 31,
 
enum SettingGuiFlag {
 
	/* 8 bytes allocated for a maximum of 8 flags
 
	 * Flags directing saving/loading of a variable */
 
	SGF_0ISDISABLED  = 1 << 0, ///< a value of zero means the feature is disabled
 
	SGF_NOCOMMA      = 1 << 1, ///< number without any thousand seperators (no formatting)
 
	SGF_MULTISTRING  = 1 << 2, ///< the value represents a limited number of string-options (internally integer)
 
	SGF_NETWORK_ONLY = 1 << 3, ///< this setting only applies to network games
 
	SGF_CURRENCY     = 1 << 4, ///< the number represents money, so when reading value multiply by exchange rate
 
	/* 3 more possible flags */
 
};
 

	
 
typedef enum {
 
	IGT_VARIABLES = 0, // values of the form "landscape = hilly"
 
	IGT_LIST = 1,      // a list of values, seperated by \n and terminated by the next group block
 
} IniGroupType;
 
typedef int32 OnChange(int32 var);
 
typedef byte SettingDescType;
 
typedef byte SettingGuiFlag;
 

	
 
typedef struct SettingDescBase {
 
	const char *name;       ///< name of the setting. Used in configuration file and for console
 
	const void *def;        ///< default value given when none is present
 
	SettingDescType cmd;    ///< various flags for the variable
 
	SettingGuiFlag flags;   ///< handles how a setting would show up in the GUI (text/currency, etc.)
 
	int32 min, max;         ///< minimum and maximum values
 
	const char *many;       ///< ONE/MANY_OF_MANY: string of possible values for this type
 
	StringID str;           ///< (translated) string with descriptive text; gui and console
 
	OnChange *proc;         ///< callback procedure for when the value is changed
 
} SettingDescBase;
 

	
 
typedef struct SettingDesc {
 
	const char *name;
 
	uint32 flags;
 
	const void *def;
 
	void *ptr;
 
	const void *many;
 
	SettingDescBase desc;   ///, Settings structure (going to configuration file)
 
	SaveLoad save;          ///< Internal structure (going to savegame, parts to config)
 
} SettingDesc;
 

	
 
/* NOTE: The only difference between SettingDesc and SettingDescGlob is
 
 * that one uses global variables as a source and the other offsets
 
 * in a struct which are bound to a certain variable during runtime.
 
 * The only way to differentiate between these two is to check if an object
 
 * has been passed to the function or not. If not, then it is a global variable
 
 * and save->variable has its address, otherwise save->variable only holds the
 
 * offset in a certain struct */
 
typedef SettingDesc SettingDescGlobVarList;
 

	
 
typedef enum {
 
	IGT_VARIABLES = 0, ///< values of the form "landscape = hilly"
 
	IGT_LIST = 1,      ///< a list of values, seperated by \n and terminated by the next group block
 
} IniGroupType;
 

	
 
/** Get the address of the variable. Which one to pick depends on the object
 
 * pointer. If it is NULL we are dealing with global variables so the address
 
 * is taken. If non-null only the offset is stored in the union and we need
 
 * to add this to the address of the object */
 
static inline void *ini_get_variable(const SaveLoad *sld, const void *object)
 
{
 
	return (object == NULL) ? sld->address : (byte*)object + (unsigned long)sld->address;
 
}
 

	
 
void IConsoleSetPatchSetting(const char *name, const char *value);
 
void IConsoleGetPatchSetting(const char *name);
 

	
 
#endif /* SETTINGS_H */
0 comments (0 inline, 0 general)