changeset 5838 | 9c3129cb019b |
parent 5835 | e0ff603ae0b7 |
child 5852 | cb3f71b16e1a |
5837:96b4b92b86ae | 5838:9c3129cb019b |
---|---|
38 #include "newgrf.h" |
38 #include "newgrf.h" |
39 #include "newgrf_config.h" |
39 #include "newgrf_config.h" |
40 #include "genworld.h" |
40 #include "genworld.h" |
41 #include "date.h" |
41 #include "date.h" |
42 #include "rail.h" |
42 #include "rail.h" |
43 #include "helpers.hpp" |
|
43 #ifdef WITH_FREETYPE |
44 #ifdef WITH_FREETYPE |
44 #include "gfx.h" |
45 #include "gfx.h" |
45 #include "fontcache.h" |
46 #include "fontcache.h" |
46 #endif |
47 #endif |
47 |
48 |
72 static SettingsMemoryPool *pool_new(uint minsize) |
73 static SettingsMemoryPool *pool_new(uint minsize) |
73 { |
74 { |
74 SettingsMemoryPool *p; |
75 SettingsMemoryPool *p; |
75 if (minsize < 4096 - 12) minsize = 4096 - 12; |
76 if (minsize < 4096 - 12) minsize = 4096 - 12; |
76 |
77 |
77 p = malloc(sizeof(SettingsMemoryPool) - 1 + minsize); |
78 p = (SettingsMemoryPool*)malloc(sizeof(SettingsMemoryPool) - 1 + minsize); |
78 p->pos = 0; |
79 p->pos = 0; |
79 p->size = minsize; |
80 p->size = minsize; |
80 p->next = NULL; |
81 p->next = NULL; |
81 return p; |
82 return p; |
82 } |
83 } |
109 return p->mem + pos; |
110 return p->mem + pos; |
110 } |
111 } |
111 |
112 |
112 static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, uint size) |
113 static void *pool_strdup(SettingsMemoryPool **pool, const char *mem, uint size) |
113 { |
114 { |
114 byte *p = pool_alloc(pool, size + 1); |
115 byte *p = (byte*)pool_alloc(pool, size + 1); |
115 p[size] = 0; |
116 p[size] = 0; |
116 memcpy(p, mem, size); |
117 memcpy(p, mem, size); |
117 return p; |
118 return p; |
118 } |
119 } |
119 |
120 |
166 } |
167 } |
167 |
168 |
168 // allocate an ini group object |
169 // allocate an ini group object |
169 static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len) |
170 static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len) |
170 { |
171 { |
171 IniGroup *grp = pool_alloc(&ini->pool, sizeof(IniGroup)); |
172 IniGroup *grp = (IniGroup*)pool_alloc(&ini->pool, sizeof(IniGroup)); |
172 grp->ini = ini; |
173 grp->ini = ini; |
173 grp->name = pool_strdup(&ini->pool, grpt, len); |
174 grp->name = (char*)pool_strdup(&ini->pool, grpt, len); |
174 if (!strcmp(grp->name, "newgrf") || !strcmp(grp->name, "servers") || !strcmp(grp->name, "bans")) { |
175 if (!strcmp(grp->name, "newgrf") || !strcmp(grp->name, "servers") || !strcmp(grp->name, "bans")) { |
175 grp->type = IGT_LIST; |
176 grp->type = IGT_LIST; |
176 } else { |
177 } else { |
177 grp->type = IGT_VARIABLES; |
178 grp->type = IGT_VARIABLES; |
178 } |
179 } |
185 return grp; |
186 return grp; |
186 } |
187 } |
187 |
188 |
188 static IniItem *ini_item_alloc(IniGroup *group, const char *name, int len) |
189 static IniItem *ini_item_alloc(IniGroup *group, const char *name, int len) |
189 { |
190 { |
190 IniItem *item = pool_alloc(&group->ini->pool, sizeof(IniItem)); |
191 IniItem *item = (IniItem*)pool_alloc(&group->ini->pool, sizeof(IniItem)); |
191 item->name = pool_strdup(&group->ini->pool, name, len); |
192 item->name = (char*)pool_strdup(&group->ini->pool, name, len); |
192 item->next = NULL; |
193 item->next = NULL; |
193 item->comment = NULL; |
194 item->comment = NULL; |
194 item->value = NULL; |
195 item->value = NULL; |
195 *group->last_item = item; |
196 *group->last_item = item; |
196 group->last_item = &item->next; |
197 group->last_item = &item->next; |
233 uint pos; |
234 uint pos; |
234 // add to comment |
235 // add to comment |
235 if (ns > a) { |
236 if (ns > a) { |
236 a = max(a, 128); |
237 a = max(a, 128); |
237 do a*=2; while (a < ns); |
238 do a*=2; while (a < ns); |
238 comment = realloc(comment, comment_alloc = a); |
239 ReallocT(&comment, comment_alloc = a); |
239 } |
240 } |
240 pos = comment_size; |
241 pos = comment_size; |
241 comment_size += (e - s + 1); |
242 comment_size += (e - s + 1); |
242 comment[pos + e - s] = '\n'; // comment newline |
243 comment[pos + e - s] = '\n'; // comment newline |
243 memcpy(comment + pos, s, e - s); // copy comment contents |
244 memcpy(comment + pos, s, e - s); // copy comment contents |
252 e--; |
253 e--; |
253 } |
254 } |
254 s++; // skip [ |
255 s++; // skip [ |
255 group = ini_group_alloc(ini, s, e - s); |
256 group = ini_group_alloc(ini, s, e - s); |
256 if (comment_size) { |
257 if (comment_size) { |
257 group->comment = pool_strdup(&ini->pool, comment, comment_size); |
258 group->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
258 comment_size = 0; |
259 comment_size = 0; |
259 } |
260 } |
260 } else if (group) { |
261 } else if (group) { |
261 // find end of keyname |
262 // find end of keyname |
262 for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++); |
263 for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++); |
263 |
264 |
264 // it's an item in an existing group |
265 // it's an item in an existing group |
265 item = ini_item_alloc(group, s, t-s); |
266 item = ini_item_alloc(group, s, t-s); |
266 if (comment_size) { |
267 if (comment_size) { |
267 item->comment = pool_strdup(&ini->pool, comment, comment_size); |
268 item->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
268 comment_size = 0; |
269 comment_size = 0; |
269 } |
270 } |
270 |
271 |
271 // find start of parameter |
272 // find start of parameter |
272 while (*t == '=' || *t == ' ' || *t == '\t') t++; |
273 while (*t == '=' || *t == ' ' || *t == '\t') t++; |
277 // remove ending quotation marks |
278 // remove ending quotation marks |
278 e = t + strlen(t); |
279 e = t + strlen(t); |
279 if (e > t && e[-1] == '\"') e--; |
280 if (e > t && e[-1] == '\"') e--; |
280 *e = '\0'; |
281 *e = '\0'; |
281 |
282 |
282 item->value = pool_strdup(&ini->pool, t, e - t); |
283 item->value = (char*)pool_strdup(&ini->pool, t, e - t); |
283 } else { |
284 } else { |
284 // it's an orphan item |
285 // it's an orphan item |
285 ShowInfoF("ini: '%s' outside of group", buffer); |
286 ShowInfoF("ini: '%s' outside of group", buffer); |
286 } |
287 } |
287 } |
288 } |
288 |
289 |
289 if (comment_size > 0) { |
290 if (comment_size > 0) { |
290 ini->comment = pool_strdup(&ini->pool, comment, comment_size); |
291 ini->comment = (char*)pool_strdup(&ini->pool, comment, comment_size); |
291 comment_size = 0; |
292 comment_size = 0; |
292 } |
293 } |
293 |
294 |
294 free(comment); |
295 free(comment); |
295 fclose(in); |
296 fclose(in); |
309 if (!memcmp(group->name, name, len) && group->name[len] == 0) |
310 if (!memcmp(group->name, name, len) && group->name[len] == 0) |
310 return group; |
311 return group; |
311 |
312 |
312 // otherwise make a new one |
313 // otherwise make a new one |
313 group = ini_group_alloc(ini, name, len); |
314 group = ini_group_alloc(ini, name, len); |
314 group->comment = pool_strdup(&ini->pool, "\n", 1); |
315 group->comment = (char*)pool_strdup(&ini->pool, "\n", 1); |
315 return group; |
316 return group; |
316 } |
317 } |
317 |
318 |
318 // lookup an item or make a new one |
319 // lookup an item or make a new one |
319 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) |
320 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) |
601 ShowInfoF("ini: invalid setting value '%s' for '%s'", str, desc->name); |
602 ShowInfoF("ini: invalid setting value '%s' for '%s'", str, desc->name); |
602 break; |
603 break; |
603 |
604 |
604 case SDT_STRING: |
605 case SDT_STRING: |
605 case SDT_INTLIST: return str; |
606 case SDT_INTLIST: return str; |
607 default: break; |
|
606 } |
608 } |
607 |
609 |
608 return NULL; |
610 return NULL; |
609 } |
611 } |
610 |
612 |
702 |
704 |
703 case SDT_STRING: |
705 case SDT_STRING: |
704 switch (GetVarMemType(sld->conv)) { |
706 switch (GetVarMemType(sld->conv)) { |
705 case SLE_VAR_STRB: |
707 case SLE_VAR_STRB: |
706 case SLE_VAR_STRBQ: |
708 case SLE_VAR_STRBQ: |
707 if (p != NULL) ttd_strlcpy((char*)ptr, p, sld->length); |
709 if (p != NULL) ttd_strlcpy((char*)ptr, (const char*)p, sld->length); |
708 break; |
710 break; |
709 case SLE_VAR_STR: |
711 case SLE_VAR_STR: |
710 case SLE_VAR_STRQ: |
712 case SLE_VAR_STRQ: |
711 if (p != NULL) { |
713 if (p != NULL) { |
712 free(*(char**)ptr); |
714 free(*(char**)ptr); |
717 default: NOT_REACHED(); break; |
719 default: NOT_REACHED(); break; |
718 } |
720 } |
719 break; |
721 break; |
720 |
722 |
721 case SDT_INTLIST: { |
723 case SDT_INTLIST: { |
722 if (!load_intlist(p, ptr, sld->length, GetVarMemType(sld->conv))) |
724 if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) |
723 ShowInfoF("ini: error in array '%s'", sdb->name); |
725 ShowInfoF("ini: error in array '%s'", sdb->name); |
724 break; |
726 break; |
725 } |
727 } |
726 default: NOT_REACHED(); break; |
728 default: NOT_REACHED(); break; |
727 } |
729 } |
780 case SDT_NUMX: |
782 case SDT_NUMX: |
781 case SDT_ONEOFMANY: |
783 case SDT_ONEOFMANY: |
782 case SDT_MANYOFMANY: |
784 case SDT_MANYOFMANY: |
783 switch (GetVarMemType(sld->conv)) { |
785 switch (GetVarMemType(sld->conv)) { |
784 case SLE_VAR_BL: |
786 case SLE_VAR_BL: |
785 if (*(bool*)ptr == (bool)(unsigned long)p) continue; |
787 if (*(bool*)ptr == (p != NULL)) continue; |
786 break; |
788 break; |
787 case SLE_VAR_I8: |
789 case SLE_VAR_I8: |
788 case SLE_VAR_U8: |
790 case SLE_VAR_U8: |
789 if (*(byte*)ptr == (byte)(unsigned long)p) continue; |
791 if (*(byte*)ptr == (byte)(unsigned long)p) continue; |
790 break; |
792 break; |
836 break; |
838 break; |
837 default: NOT_REACHED(); |
839 default: NOT_REACHED(); |
838 } |
840 } |
839 |
841 |
840 /* The value is different, that means we have to write it to the ini */ |
842 /* The value is different, that means we have to write it to the ini */ |
841 item->value = pool_strdup(&ini->pool, buf, strlen(buf)); |
843 item->value = (char*)pool_strdup(&ini->pool, buf, strlen(buf)); |
842 } |
844 } |
843 } |
845 } |
844 |
846 |
845 /** Loads all items from a 'grpname' section into a list |
847 /** Loads all items from a 'grpname' section into a list |
846 * The list parameter can be a NULL pointer, in this case nothing will be |
848 * The list parameter can be a NULL pointer, in this case nothing will be |
943 * internal structure somewhat so it needs a little looking. There are _NULL() |
945 * internal structure somewhat so it needs a little looking. There are _NULL() |
944 * macros as well, these fill up space so you can add more patches there (in |
946 * macros as well, these fill up space so you can add more patches there (in |
945 * place) and you DON'T have to increase the savegame version. */ |
947 * place) and you DON'T have to increase the savegame version. */ |
946 |
948 |
947 #define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, proc)\ |
949 #define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, proc)\ |
948 {name, (const void*)(def), cmd, guiflags, min, max, interval, many, str, proc} |
950 {name, (const void*)(def), {cmd}, {guiflags}, min, max, interval, many, str, proc} |
949 |
951 |
950 /* Macros for various objects to go in the configuration file. |
952 /* Macros for various objects to go in the configuration file. |
951 * This section is for global variables */ |
953 * This section is for global variables */ |
952 #define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, proc, from, to)\ |
954 #define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, proc, from, to)\ |
953 {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to)} |
955 {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to)} |
954 |
956 |
955 #define SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, from, to)\ |
957 #define SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, from, to)\ |
956 SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, NULL, str, proc, from, to) |
958 SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, NULL, str, proc, from, to) |
957 #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc)\ |
959 #define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc)\ |
958 SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, 0, SL_MAX_VERSION) |
960 SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, 0, SL_MAX_VERSION) |
981 SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, proc, from, to) |
983 SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, proc, from, to) |
982 #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, proc)\ |
984 #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, proc)\ |
983 SDTG_CONDMMANY(name, type, flags, guiflags, var, def, full, str, proc, 0, SL_MAX_VERSION) |
985 SDTG_CONDMMANY(name, type, flags, guiflags, var, def, full, str, proc, 0, SL_MAX_VERSION) |
984 |
986 |
985 #define SDTG_CONDNULL(length, from, to)\ |
987 #define SDTG_CONDNULL(length, from, to)\ |
986 {{"", NULL, 0, 0, 0, 0, 0, NULL, STR_NULL, NULL}, SLEG_CONDNULL(length, from, to)} |
988 {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL}, SLEG_CONDNULL(length, from, to)} |
987 |
989 |
988 #define SDTG_END() {{NULL, NULL, 0, 0, 0, 0, 0, NULL, STR_NULL, NULL}, SLEG_END()} |
990 #define SDTG_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL}, SLEG_END()} |
989 |
991 |
990 /* Macros for various objects to go in the configuration file. |
992 /* Macros for various objects to go in the configuration file. |
991 * This section is for structures where their various members are saved */ |
993 * This section is for structures where their various members are saved */ |
992 #define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, proc, from, to)\ |
994 #define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, proc, from, to)\ |
993 {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to)} |
995 {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to)} |
1030 SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, proc, from, to) |
1032 SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, proc, from, to) |
1031 #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc)\ |
1033 #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc)\ |
1032 SDT_CONDMMANY(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, full, str, proc) |
1034 SDT_CONDMMANY(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, full, str, proc) |
1033 |
1035 |
1034 #define SDT_CONDNULL(length, from, to)\ |
1036 #define SDT_CONDNULL(length, from, to)\ |
1035 {{"", NULL, 0, 0, 0, 0, 0, NULL, STR_NULL, NULL}, SLE_CONDNULL(length, from, to)} |
1037 {{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL}, SLE_CONDNULL(length, from, to)} |
1036 |
1038 |
1037 #define SDT_END() {{NULL, NULL, 0, 0, 0, 0, 0, NULL, STR_NULL, NULL}, SLE_END()} |
1039 #define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL}, SLE_END()} |
1038 |
1040 |
1039 /* Shortcuts for macros below. Logically if we don't save the value |
1041 /* Shortcuts for macros below. Logically if we don't save the value |
1040 * we also don't sync it in a network game */ |
1042 * we also don't sync it in a network game */ |
1041 #define S SLF_SAVE_NO | SLF_NETWORK_NO |
1043 #define S SLF_SAVE_NO | SLF_NETWORK_NO |
1042 #define NS SLF_SAVE_NO |
1044 #define NS SLF_SAVE_NO |
1505 GRFConfig **curr = &first; |
1507 GRFConfig **curr = &first; |
1506 |
1508 |
1507 if (group == NULL) return NULL; |
1509 if (group == NULL) return NULL; |
1508 |
1510 |
1509 for (item = group->item; item != NULL; item = item->next) { |
1511 for (item = group->item; item != NULL; item = item->next) { |
1510 GRFConfig *c = calloc(1, sizeof(*c)); |
1512 GRFConfig *c; |
1513 CallocT(&c, 1); |
|
1511 c->filename = strdup(item->name); |
1514 c->filename = strdup(item->name); |
1512 |
1515 |
1513 /* Parse parameters */ |
1516 /* Parse parameters */ |
1514 if (*item->value != '\0') { |
1517 if (*item->value != '\0') { |
1515 c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param)); |
1518 c->num_params = parse_intlist(item->value, (int*)c->param, lengthof(c->param)); |
1564 for (c = list; c != NULL; c = c->next) { |
1567 for (c = list; c != NULL; c = c->next) { |
1565 char params[512]; |
1568 char params[512]; |
1566 GRFBuildParamList(params, c, lastof(params)); |
1569 GRFBuildParamList(params, c, lastof(params)); |
1567 |
1570 |
1568 *item = ini_item_alloc(group, c->filename, strlen(c->filename)); |
1571 *item = ini_item_alloc(group, c->filename, strlen(c->filename)); |
1569 (*item)->value = pool_strdup(&ini->pool, params, strlen(params)); |
1572 (*item)->value = (char*)pool_strdup(&ini->pool, params, strlen(params)); |
1570 item = &(*item)->next; |
1573 item = &(*item)->next; |
1571 } |
1574 } |
1572 } |
1575 } |
1573 |
1576 |
1574 /* Common handler for saving/loading variables to the configuration file */ |
1577 /* Common handler for saving/loading variables to the configuration file */ |
1841 * them with the default values just as it was in the old days. |
1844 * them with the default values just as it was in the old days. |
1842 * Also new games need this copying-over */ |
1845 * Also new games need this copying-over */ |
1843 _patches = _patches_newgame; /* backwards compatibility */ |
1846 _patches = _patches_newgame; /* backwards compatibility */ |
1844 } |
1847 } |
1845 |
1848 |
1846 const ChunkHandler _setting_chunk_handlers[] = { |
1849 extern const ChunkHandler _setting_chunk_handlers[] = { |
1847 { 'OPTS', Save_OPTS, Load_OPTS, CH_RIFF}, |
1850 { 'OPTS', Save_OPTS, Load_OPTS, CH_RIFF}, |
1848 { 'PATS', Save_PATS, Load_PATS, CH_RIFF | CH_LAST}, |
1851 { 'PATS', Save_PATS, Load_PATS, CH_RIFF | CH_LAST}, |
1849 }; |
1852 }; |
1850 |
1853 |
1851 static bool IsSignedVarMemType(VarType vt) |
1854 static bool IsSignedVarMemType(VarType vt) |