|
@@ -304,51 +304,51 @@ static bool ini_save(const char *filenam
|
|
|
if (f == NULL) return false;
|
|
|
|
|
|
for(group = ini->group; group; group = group->next) {
|
|
|
if (group->comment) fputs(group->comment, f);
|
|
|
fprintf(f, "[%s]\n", group->name);
|
|
|
for(item = group->item; item; item = item->next) {
|
|
|
if (item->comment) fputs(item->comment, f);
|
|
|
fprintf(f, "%s = %s\n", item->name, item->value ? item->value : "");
|
|
|
}
|
|
|
}
|
|
|
if (ini->comment) fputs(ini->comment, f);
|
|
|
|
|
|
fclose(f);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static void ini_free(IniFile *ini)
|
|
|
{
|
|
|
pool_free(&ini->pool);
|
|
|
}
|
|
|
|
|
|
struct SettingDesc {
|
|
|
const char *name;
|
|
|
int flags;
|
|
|
void *def;
|
|
|
const void *def;
|
|
|
void *ptr;
|
|
|
void *b;
|
|
|
const void *b;
|
|
|
|
|
|
};
|
|
|
|
|
|
static int lookup_oneofmany(const char *many, const char *one, int onelen)
|
|
|
{
|
|
|
const char *s;
|
|
|
int idx;
|
|
|
|
|
|
if (onelen == -1) onelen = strlen(one);
|
|
|
|
|
|
// check if it's an integer
|
|
|
if (*one >= '0' && *one <= '9')
|
|
|
return strtoul(one, NULL, 0);
|
|
|
|
|
|
idx = 0;
|
|
|
for(;;) {
|
|
|
// find end of item
|
|
|
s = many;
|
|
|
while (*s != '|' && *s != 0) s++;
|
|
|
if (s - many == onelen && !memcmp(one, many, onelen)) return idx;
|
|
|
if (*s == 0) return -1;
|
|
|
many = s + 1;
|
|
|
idx++;
|
|
|
}
|
|
@@ -472,92 +472,92 @@ static void make_oneofmany(char *buf, co
|
|
|
static void make_manyofmany(char *buf, const char *many, uint32 x)
|
|
|
{
|
|
|
const char *start;
|
|
|
int i = 0;
|
|
|
bool init = true;
|
|
|
|
|
|
do {
|
|
|
start = many;
|
|
|
while (*many != 0 && *many != '|') many++;
|
|
|
if (x & 1) {
|
|
|
if (!init) *buf++ = '|';
|
|
|
init = false;
|
|
|
if (start == many) {
|
|
|
buf += sprintf(buf, "%d", i);
|
|
|
} else {
|
|
|
memcpy(buf, start, many - start);
|
|
|
buf += many - start;
|
|
|
}
|
|
|
}
|
|
|
if (*many == '|') many++;
|
|
|
} while (++i, x>>=1);
|
|
|
*buf = 0;
|
|
|
}
|
|
|
|
|
|
static void *string_to_val(const SettingDesc *desc, const char *str)
|
|
|
static const void *string_to_val(const SettingDesc *desc, const char *str)
|
|
|
{
|
|
|
unsigned long val;
|
|
|
char *end;
|
|
|
|
|
|
switch(desc->flags & 0xF) {
|
|
|
case SDT_INTX:
|
|
|
val = strtol(str, &end, 0);
|
|
|
if (*end != 0) ShowInfoF("ini: trailing characters at end of setting '%s'", desc->name);
|
|
|
return (void*)val;
|
|
|
case SDT_ONEOFMANY: {
|
|
|
int r = lookup_oneofmany((char*)desc->b, str, -1);
|
|
|
if (r != -1) return (void*)r;
|
|
|
ShowInfoF("ini: invalid value '%s' for '%s'", str, desc->name);
|
|
|
return 0;
|
|
|
}
|
|
|
case SDT_MANYOFMANY: {
|
|
|
uint32 r = lookup_manyofmany(desc->b, str);
|
|
|
if (r != (uint32)-1) return (void*)r;
|
|
|
ShowInfoF("ini: invalid value '%s' for '%s'", str, desc->name);
|
|
|
return 0;
|
|
|
}
|
|
|
case SDT_BOOLX:
|
|
|
if (!strcmp(str, "true") || !strcmp(str, "on") || !strcmp(str, "1"))
|
|
|
return (void*)true;
|
|
|
if (!strcmp(str, "false") || !strcmp(str, "off") || !strcmp(str, "0"))
|
|
|
return (void*)false;
|
|
|
ShowInfoF("ini: invalid setting value '%s' for '%s'", str, desc->name);
|
|
|
break;
|
|
|
|
|
|
case SDT_STRING:
|
|
|
case SDT_STRINGBUF:
|
|
|
case SDT_INTLIST:
|
|
|
return (void*)str;
|
|
|
}
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
static void load_setting_desc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base)
|
|
|
static void load_setting_desc(IniFile *ini, const SettingDesc *desc, const void *grpname, void *base)
|
|
|
{
|
|
|
IniGroup *group_def = ini_getgroup(ini, grpname, -1), *group;
|
|
|
IniItem *item;
|
|
|
void *p;
|
|
|
const void *p;
|
|
|
void *ptr;
|
|
|
|
|
|
for (;desc->name;desc++) {
|
|
|
// group override?
|
|
|
const char *s = strchr(desc->name, '.');
|
|
|
if (s) {
|
|
|
group = ini_getgroup(ini, desc->name, s - desc->name);
|
|
|
s++;
|
|
|
} else {
|
|
|
s = desc->name;
|
|
|
group = group_def;
|
|
|
}
|
|
|
|
|
|
item = ini_getitem(group, s, false);
|
|
|
if (!item) {
|
|
|
p = desc->def;
|
|
|
} else {
|
|
|
p = string_to_val(desc, item->value);
|
|
|
}
|
|
|
|
|
|
// get ptr to array
|
|
|
ptr = desc->ptr;
|
|
|
if ( (uint32)ptr < 0x10000)
|
|
|
ptr = (byte*)base + (uint32)ptr;
|
|
@@ -582,53 +582,54 @@ static void load_setting_desc(IniFile *i
|
|
|
*(uint32*)ptr = (uint32)p;
|
|
|
break;
|
|
|
default:
|
|
|
NOT_REACHED();
|
|
|
}
|
|
|
break;
|
|
|
case SDT_STRING:
|
|
|
if (*(char**)ptr) free(*(char**)ptr);
|
|
|
*(char**)ptr = strdup((char*)p);
|
|
|
break;
|
|
|
case SDT_STRINGBUF:
|
|
|
if (p) ttd_strlcpy((char*)ptr, p, desc->flags >> 16);
|
|
|
break;
|
|
|
case SDT_INTLIST: {
|
|
|
if (!load_intlist(p, ptr, desc->flags >> 16, desc->flags >> 4 & 7))
|
|
|
ShowInfoF("ini: error in array '%s'", desc->name);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
NOT_REACHED();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void save_setting_desc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base)
|
|
|
static void save_setting_desc(IniFile *ini, const SettingDesc *desc, const void *grpname, void *base)
|
|
|
{
|
|
|
IniGroup *group_def = NULL, *group;
|
|
|
IniItem *item;
|
|
|
void *p, *ptr;
|
|
|
const void *p;
|
|
|
void *ptr;
|
|
|
int i = 0;
|
|
|
char buf[512]; // setting buffer
|
|
|
const char *s;
|
|
|
|
|
|
for (;desc->name;desc++) {
|
|
|
if (desc->flags & SDT_NOSAVE)
|
|
|
continue;
|
|
|
|
|
|
// group override?
|
|
|
s = strchr(desc->name, '.');
|
|
|
if (s) {
|
|
|
group = ini_getgroup(ini, desc->name, s - desc->name);
|
|
|
s++;
|
|
|
} else {
|
|
|
if (group_def == NULL)
|
|
|
group_def = ini_getgroup(ini, grpname, -1);
|
|
|
s = desc->name;
|
|
|
group = group_def;
|
|
|
}
|
|
|
|
|
|
item = ini_getitem(group, s, true);
|
|
|
|
|
|
// get ptr to array
|
|
|
ptr = desc->ptr;
|
|
@@ -862,49 +863,49 @@ static const SettingDesc patch_settings[
|
|
|
|
|
|
{"keep_all_autosave", SDT_BOOL, (void*)false, (void*)offsetof(Patches, keep_all_autosave), NULL},
|
|
|
|
|
|
{"extra_dynamite", SDT_BOOL, (void*)false, (void*)offsetof(Patches, extra_dynamite), NULL},
|
|
|
|
|
|
{"never_expire_vehicles",SDT_BOOL, (void*)false, (void*)offsetof(Patches, never_expire_vehicles),NULL},
|
|
|
{"extend_vehicle_life", SDT_UINT8, (void*)0, (void*)offsetof(Patches, extend_vehicle_life), NULL},
|
|
|
|
|
|
{"auto_euro", SDT_BOOL, (void*)true, (void*)offsetof(Patches, auto_euro), NULL},
|
|
|
|
|
|
{"serviceathelipad", SDT_BOOL, (void*)true, (void*)offsetof(Patches, serviceathelipad), NULL},
|
|
|
{"smooth_economy", SDT_BOOL, (void*)false, (void*)offsetof(Patches, smooth_economy), NULL},
|
|
|
{"dist_local_authority",SDT_UINT8, (void*)20, (void*)offsetof(Patches, dist_local_authority), NULL},
|
|
|
|
|
|
{"wait_oneway_signal", SDT_UINT8, (void*)15, (void*)offsetof(Patches, wait_oneway_signal), NULL},
|
|
|
{"wait_twoway_signal", SDT_UINT8, (void*)41, (void*)offsetof(Patches, wait_twoway_signal), NULL},
|
|
|
|
|
|
{"ainew_active", SDT_BOOL, (void*)false, (void*)offsetof(Patches, ainew_active), NULL},
|
|
|
|
|
|
{"drag_signals_density",SDT_UINT8, (void*)4, (void*)offsetof(Patches, drag_signals_density), NULL},
|
|
|
|
|
|
{NULL, 0, NULL, NULL, NULL}
|
|
|
};
|
|
|
|
|
|
typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, void *grpname, void *base);
|
|
|
typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const void *grpname, void *base);
|
|
|
|
|
|
static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc)
|
|
|
{
|
|
|
proc(ini, misc_settings, "misc", NULL);
|
|
|
proc(ini, win32_settings, "win32", NULL);
|
|
|
proc(ini, network_settings, "network", NULL);
|
|
|
proc(ini, music_settings, "music", &msf);
|
|
|
proc(ini, gameopt_settings, "gameopt", &_new_opt);
|
|
|
proc(ini, patch_settings, "patches", &_patches);
|
|
|
|
|
|
proc(ini, debug_settings, "debug", NULL);
|
|
|
}
|
|
|
|
|
|
void LoadGrfSettings(IniFile *ini)
|
|
|
{
|
|
|
IniGroup *group = ini_getgroup(ini, "newgrf", -1);
|
|
|
IniItem *item;
|
|
|
int i;
|
|
|
|
|
|
if (!group)
|
|
|
return;
|
|
|
|
|
|
for(i=0; i!=lengthof(_newgrf_files); i++) {
|
|
|
char buf[3];
|