diff --git a/src/fios.cpp b/src/fios.cpp index cdab456355..548efbfec2 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -129,11 +129,7 @@ const char *FiosBrowseTo(const FiosItem *item) case FIOS_TYPE_OLD_SCENARIO: case FIOS_TYPE_PNG: case FIOS_TYPE_BMP: - { - static char str_buffr[512]; - snprintf(str_buffr, lengthof(str_buffr), "%s%s", path, item->name); - return str_buffr; - } + return item->name; } return NULL; @@ -192,11 +188,76 @@ bool FileExists(const char *filename) typedef FiosType fios_getlist_callback_proc(SaveLoadDialogMode mode, const char *filename, const char *ext, char *title, const char *last); -/** Create a list of the files in a directory, according to some arbitrary rule. +/** + * Scanner to scan for a particular type of FIOS file. + */ +class FiosFileScanner : public FileScanner { + SaveLoadDialogMode mode; ///< The mode we want to search for + fios_getlist_callback_proc *callback_proc; ///< Callback to check whether the file may be added +public: + /** + * Create the scanner + * @param mode The mode we are in. Some modes don't allow 'parent'. + * @param callback_proc The function that is called where you need to do the filtering. + */ + FiosFileScanner(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc) : + mode(mode), + callback_proc(callback_proc) + {} + + /* virtual */ bool AddFile(const char *filename, size_t basepath_length); +}; + +/** + * Try to add a fios item set with the given filename. + * @param filename the full path to the file to read + * @param basepath_length amount of characters to chop of before to get a relative filename + * @return true if the file is added. + */ +bool FiosFileScanner::AddFile(const char *filename, size_t basepath_length) +{ + const char *ext = strrchr(filename, '.'); + if (ext == NULL) return false; + + char fios_title[64]; + fios_title[0] = '\0'; // reset the title; + + FiosType type = this->callback_proc(this->mode, filename, ext, fios_title, lastof(fios_title)); + if (type == FIOS_TYPE_INVALID) return false; + + for (const FiosItem *fios = _fios_items.Begin(); fios != _fios_items.End(); fios++) { + if (strcmp(fios->name, filename) == 0) return false; + } + + FiosItem *fios = _fios_items.Append(); + struct stat sb; + if (stat(filename, &sb) == 0) { + fios->mtime = sb.st_mtime; + } else { + fios->mtime = 0; + } + + fios->type = type; + strecpy(fios->name, filename, lastof(fios->name)); + + /* If the file doesn't have a title, use it's filename */ + const char *t = fios_title; + if (StrEmpty(fios_title)) { + t = strrchr(filename, PATHSEPCHAR); + t = (t == NULL) ? filename : (t + 1); + } + strecpy(fios->title, t, lastof(fios->title)); + str_validate(fios->title); + + return true; +} + + +/** Fill the list of the files in a directory, according to some arbitrary rule. * @param mode The mode we are in. Some modes don't allow 'parent'. * @param callback_proc The function that is called where you need to do the filtering. - * @return Return the list of files. */ -static FiosItem *FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc) + */ +static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc) { struct stat sb; struct dirent *dirent; @@ -248,35 +309,8 @@ static FiosItem *FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_ sort_start = _fios_items.Length(); /* Show files */ - dir = ttd_opendir(_fios_path); - if (dir != NULL) { - while ((dirent = readdir(dir)) != NULL) { - char fios_title[64]; - char *t; - strecpy(d_name, FS2OTTD(dirent->d_name), lastof(d_name)); - - if (!FiosIsValidFile(_fios_path, dirent, &sb) || !S_ISREG(sb.st_mode) || FiosIsHiddenFile(dirent)) continue; - - /* File has no extension, skip it */ - if ((t = strrchr(d_name, '.')) == NULL) continue; - fios_title[0] = '\0'; // reset the title; - - FiosType type = callback_proc(mode, d_name, t, fios_title, lastof(fios_title)); - if (type != FIOS_TYPE_INVALID) { - fios = _fios_items.Append(); - fios->mtime = sb.st_mtime; - fios->type = type; - strecpy(fios->name, d_name, lastof(fios->name)); - - /* Some callbacks want to lookup the title of the file. Allow that. - * If we just copy the title from the filename, strip the extension */ - t = (fios_title[0] == '\0') ? *t = '\0', d_name : fios_title; - strecpy(fios->title, t, lastof(fios->title)); - str_validate(fios->title); - } - } - closedir(dir); - } + FiosFileScanner scanner(mode, callback_proc); + scanner.Scan(NULL, _fios_path, false); qsort(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, sizeof(FiosItem), compare_FiosItems); @@ -284,8 +318,6 @@ static FiosItem *FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_ if (mode != SLD_NEW_GAME) FiosGetDrives(); _fios_items.Compact(); - - return _fios_items.Begin(); } /** diff --git a/src/fios.h b/src/fios.h index f119dd75c7..4f6f98c585 100644 --- a/src/fios.h +++ b/src/fios.h @@ -62,7 +62,7 @@ struct FiosItem { FiosType type; uint64 mtime; char title[64]; - char name[256 - 12 - 64]; + char name[MAX_PATH]; }; /* Deals with the type of the savegame, independent of extension */