27 #include "table/strings.h"
33 static char *_fios_path;
34 static const char *_fios_path_last;
36 SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
39 extern bool FiosIsRoot(
const char *path);
40 extern bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb);
41 extern bool FiosIsHiddenFile(
const struct dirent *ent);
42 extern void FiosGetDrives();
43 extern bool FiosGetDiskFreeSpace(
const char *path, uint64 *tot);
46 extern void GetOldSaveGameName(
const char *file,
char *title,
const char *last);
58 if ((_savegame_sort_order & SORT_BY_NAME) == 0 && da->mtime != db->mtime) {
59 r = da->mtime < db->mtime ? -1 : 1;
61 r = strcasecmp(da->title, db->title);
64 if (_savegame_sort_order & SORT_DESCENDING) r = -r;
85 return FiosGetDiskFreeSpace(*path, total_free) ? STR_SAVELOAD_BYTES_FREE : STR_ERROR_UNABLE_TO_READ_DRIVE;
98 seprintf(_fios_path, _fios_path_last, PATHSEP
"");
99 #elif defined(WIN32) || defined(__OS2__)
100 seprintf(_fios_path, _fios_path_last,
"%c:" PATHSEP, item->title[0]);
103 case FIOS_TYPE_INVALID:
106 case FIOS_TYPE_PARENT: {
108 char *s = strrchr(_fios_path, PATHSEPCHAR);
109 if (s != NULL && s != _fios_path) {
112 s = strrchr(_fios_path, PATHSEPCHAR);
115 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
117 }
else if ((s = strrchr(_fios_path,
':')) != NULL) {
125 strecat(_fios_path, item->name, _fios_path_last);
126 strecat(_fios_path, PATHSEP, _fios_path_last);
129 case FIOS_TYPE_DIRECT:
130 seprintf(_fios_path, _fios_path_last,
"%s", item->name);
134 case FIOS_TYPE_OLDFILE:
135 case FIOS_TYPE_SCENARIO:
136 case FIOS_TYPE_OLD_SCENARIO:
153 static void FiosMakeFilename(
char *buf,
const char *path,
const char *name,
const char *ext,
const char *last)
158 period = strrchr(name,
'.');
159 if (period != NULL && strcasecmp(period, ext) == 0) ext =
"";
160 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
162 unsigned char sepchar = path[(strlen(path) - 1)];
164 if (sepchar !=
':' && sepchar !=
'/') {
165 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
167 seprintf(buf, last,
"%s%s%s", path, name, ext);
170 seprintf(buf, last,
"%s%s", name, ext);
173 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
185 const char *extension = (_game_mode == GM_EDITOR) ?
".scn" :
".sav";
215 return unlink(filename) == 0;
218 typedef FiosType fios_getlist_callback_proc(
SaveLoadDialogMode mode,
const char *filename,
const char *ext,
char *title,
const char *last);
234 callback_proc(callback_proc)
237 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename);
248 const char *ext = strrchr(filename,
'.');
249 if (ext == NULL)
return false;
252 fios_title[0] =
'\0';
255 if (type == FIOS_TYPE_INVALID)
return false;
257 for (
const FiosItem *fios = _fios_items.
Begin(); fios != _fios_items.
End(); fios++) {
258 if (strcmp(fios->name, filename) == 0)
return false;
264 if (_tstat(
OTTD2FS(filename), &sb) == 0) {
267 if (stat(filename, &sb) == 0) {
269 fios->mtime = sb.st_mtime;
278 const char *t = fios_title;
280 t = strrchr(filename, PATHSEPCHAR);
281 t = (t == NULL) ? filename : (t + 1);
299 struct dirent *dirent;
303 char d_name[
sizeof(fios->name)];
308 if (!FiosIsRoot(_fios_path)) {
309 fios = _fios_items.
Append();
310 fios->type = FIOS_TYPE_PARENT;
313 strecpy(fios->title,
".. (Parent directory)",
lastof(fios->title));
318 while ((dirent = readdir(dir)) != NULL) {
322 if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
323 (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
324 strcmp(d_name,
".") != 0 && strcmp(d_name,
"..") != 0) {
325 fios = _fios_items.
Append();
326 fios->type = FIOS_TYPE_DIR;
329 seprintf(fios->title,
lastof(fios->title),
"%s" PATHSEP
" (Directory)", d_name);
338 SortingBits order = _savegame_sort_order;
339 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
341 _savegame_sort_order = order;
345 sort_start = _fios_items.
Length();
350 scanner.
Scan(NULL, _fios_path,
false);
352 scanner.
Scan(NULL, subdir,
true,
true);
378 if (f == NULL)
return;
380 size_t read = fread(title, 1, last - title, f);
381 assert(title + read <= last);
407 if (ext == NULL)
return FIOS_TYPE_INVALID;
409 if (strcasecmp(ext,
".sav") == 0) {
411 return FIOS_TYPE_FILE;
415 if (strcasecmp(ext,
".ss1") == 0 || strcasecmp(ext,
".sv1") == 0 ||
416 strcasecmp(ext,
".sv2") == 0) {
417 if (title != NULL) GetOldSaveGameName(file, title, last);
418 return FIOS_TYPE_OLDFILE;
422 return FIOS_TYPE_INVALID;
432 static char *fios_save_path = NULL;
433 static char *fios_save_path_last = NULL;
435 if (fios_save_path == NULL) {
436 fios_save_path = MallocT<char>(MAX_PATH);
437 fios_save_path_last = fios_save_path + MAX_PATH - 1;
438 FioGetDirectory(fios_save_path, fios_save_path_last,
SAVE_DIR);
441 _fios_path = fios_save_path;
442 _fios_path_last = fios_save_path_last;
464 if (strcasecmp(ext,
".scn") == 0) {
466 return FIOS_TYPE_SCENARIO;
470 if (strcasecmp(ext,
".sv0") == 0 || strcasecmp(ext,
".ss0") == 0 ) {
471 GetOldSaveGameName(file, title, last);
472 return FIOS_TYPE_OLD_SCENARIO;
476 return FIOS_TYPE_INVALID;
486 static char *fios_scn_path = NULL;
487 static char *fios_scn_path_last = NULL;
490 if (fios_scn_path == NULL) {
491 fios_scn_path = MallocT<char>(MAX_PATH);
492 fios_scn_path_last = fios_scn_path + MAX_PATH - 1;
493 FioGetDirectory(fios_scn_path, fios_scn_path_last,
SCENARIO_DIR);
496 _fios_path = fios_scn_path;
497 _fios_path_last = fios_scn_path_last;
499 char base_path[MAX_PATH];
505 static FiosType FiosGetHeightmapListCallback(
SaveLoadDialogMode mode,
const char *file,
const char *ext,
char *title,
const char *last)
512 FiosType type = FIOS_TYPE_INVALID;
515 if (strcasecmp(ext,
".png") == 0) type = FIOS_TYPE_PNG;
518 if (strcasecmp(ext,
".bmp") == 0) type = FIOS_TYPE_BMP;
520 if (type == FIOS_TYPE_INVALID)
return FIOS_TYPE_INVALID;
522 TarFileList::iterator it = _tar_filelist[
SCENARIO_DIR].find(file);
535 if (strncmp(buf, it->second.tar_filename, strlen(buf)) == 0) {
541 if (!match)
return FIOS_TYPE_INVALID;
555 static char *fios_hmap_path = NULL;
556 static char *fios_hmap_path_last = NULL;
558 if (fios_hmap_path == NULL) {
559 fios_hmap_path = MallocT<char>(MAX_PATH);
560 fios_hmap_path_last = fios_hmap_path + MAX_PATH - 1;
561 FioGetDirectory(fios_hmap_path, fios_hmap_path_last,
HEIGHTMAP_DIR);
564 _fios_path = fios_hmap_path;
565 _fios_path_last = fios_hmap_path_last;
567 char base_path[MAX_PATH];
579 static char *fios_screenshot_path = NULL;
581 if (fios_screenshot_path == NULL) {
582 fios_screenshot_path = MallocT<char>(MAX_PATH);
583 FioGetDirectory(fios_screenshot_path, fios_screenshot_path + MAX_PATH - 1,
SCREENSHOT_DIR);
586 return fios_screenshot_path;
589 #if defined(ENABLE_NETWORK)
591 #include "3rdparty/md5/md5.h"
597 char filename[MAX_PATH];
601 return this->scenid == other.
scenid &&
602 memcmp(this->md5sum, other.
md5sum,
sizeof(this->md5sum)) == 0;
607 return !(*
this == other);
626 if (this->scanned && !rescan)
return;
629 this->scanned =
true;
632 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename)
635 if (f == NULL)
return false;
638 int fret = fscanf(f,
"%i", &
id.scenid);
640 if (fret != 1)
return false;
645 char basename[MAX_PATH];
652 *strrchr(basename,
'.') =
'\0';
654 if (f == NULL)
return false;
657 while ((len = fread(buffer, 1, (size >
sizeof(buffer)) ?
sizeof(buffer) : size, f)) != 0 && size != 0) {
659 checksum.Append(buffer, len);
661 checksum.Finish(
id.md5sum);
681 _scanner.
Scan(
false);
684 if (md5sum ? (memcmp(id->md5sum, ci->
md5sum,
sizeof(id->md5sum)) == 0)