diff --git a/src/config.c b/src/config.c index 7c0d33793e..031ce02f72 100644 --- a/src/config.c +++ b/src/config.c @@ -1479,16 +1479,13 @@ static void title_sequence_open(const char *path, const char *customName) gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); if (customName == NULL) { - char nameBuffer[MAX_PATH], *name; + char nameBuffer[MAX_PATH]; safe_strncpy(nameBuffer, path, MAX_PATH); - name = nameBuffer + strlen(nameBuffer) - 1; - while (*name == '\\' || *name == '/') { - *name = 0; - name--; - } - while (*(name - 1) != '\\' && *(name - 1) != '/') { - name--; - } + // Get folder name + // First strip off the last folder separator + *strrchr(nameBuffer, platform_get_path_separator()) = '\0'; + // Then find the name of the folder + char *name = strrchr(nameBuffer, platform_get_path_separator()) + 1; safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; } @@ -1587,7 +1584,7 @@ void title_sequence_save_preset_script(int preset) platform_get_user_directory(path, "title sequences"); - strcat(path, path_get_filename(gConfigTitleSequences.presets[preset].name)); + strcat(path, gConfigTitleSequences.presets[preset].name); strncat(path, &separator, 1); strcat(path, "script.txt"); diff --git a/src/game.c b/src/game.c index 937189b681..f204ede49a 100644 --- a/src/game.c +++ b/src/game.c @@ -1056,7 +1056,7 @@ void save_game() } void save_game_as() { - window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, gScenarioSavePath); + window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, (char*)path_get_filename(gScenarioSavePath)); } diff --git a/src/ride/track.c b/src/ride/track.c index ac1bed27d3..8d1e34711b 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3093,8 +3093,6 @@ int save_track_design(uint8 rideIndex){ char path[MAX_PATH]; substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); - strcat(path, ".TD6"); - // Save track design format_string(RCT2_ADDRESS(0x141ED68, char), 2306, NULL); @@ -3201,6 +3199,7 @@ void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool { const utf8 *ch; int codepoint; + char *lastDot = strrchr(src, '.'); if (colour != 0) { dst = utf8_write_codepoint(dst, colour); @@ -3209,8 +3208,8 @@ void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool if (quotes) dst = utf8_write_codepoint(dst, FORMAT_OPENQUOTES); ch = src; - while ((codepoint = utf8_get_next(ch, &ch)) != 0) { - if (codepoint == '.') break; + while (lastDot > ch) { + codepoint = utf8_get_next(ch, &ch); dst = utf8_write_codepoint(dst, codepoint); } diff --git a/src/util/util.c b/src/util/util.c index ca657803c7..60b4a6ca6c 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -61,62 +61,55 @@ bool filename_valid_characters(const utf8 *filename) const char *path_get_filename(const utf8 *path) { - const char *result, *ch; + // Find last slash or backslash in the path + char *filename = strrchr(path, platform_get_path_separator()); - result = path; - for (ch = path; *ch != 0; ch++) { - if (*ch == '/' || *ch == '\\') { - if (*(ch + 1) != 0) - result = ch + 1; - } + // Checks if the path is valid (e.g. not just a file name) + if (filename == NULL) + { + log_warning("Invalid path given: %s", path); + // Return the input string to keep things working + return path; } - return result; + // Increase pointer by one, to get rid of the slashes + filename++; + + return filename; } const char *path_get_extension(const utf8 *path) { - const char *extension = NULL; - const char *ch = path; - while (*ch != 0) { - if (*ch == '.') - extension = ch; + // Get the filename from the path + const char *filename = path_get_filename(path); - ch++; - } + // Try to find the most-right dot in the filename + char *extension = strrchr(filename, '.'); + + // When no dot was found, return a pointer to the null-terminator if (extension == NULL) - extension = ch; + extension = strrchr(filename, '\0'); + return extension; } void path_set_extension(utf8 *path, const utf8 *newExtension) { - char *extension = NULL; - char *ch = path; - while (*ch != 0) { - if (*ch == '.') - extension = ch; - - ch++; - } - if (extension == NULL) - extension = ch; - + // Append a dot to the filename if the new extension doesn't start with it + char *endOfString = strrchr(path, '\0'); if (newExtension[0] != '.') - *extension++ = '.'; + *endOfString++ = '.'; - strcpy(extension, newExtension); + // Append the extension to the path + // No existing extensions should be removed ("ride.TD6" -> "ride.TD6.TD6") + safe_strncpy(endOfString, newExtension, MAX_PATH - (endOfString - path) - 1); } void path_remove_extension(utf8 *path) { - char *ch = path + strlen(path); - for (--ch; ch >= path; --ch) { - if (*ch == '.') { - *ch = '\0'; - break; - } - } + // Find last dot in filename, and replace it with a null-terminator + char *lastDot = strrchr(path, '.'); + if (*lastDot) *lastDot = '\0'; } bool readentirefile(const utf8 *path, void **outBuffer, int *outLength) diff --git a/src/windows/install_track.c b/src/windows/install_track.c index 62b25d86a3..a000405116 100644 --- a/src/windows/install_track.c +++ b/src/windows/install_track.c @@ -137,9 +137,7 @@ void window_install_track_open(const char* path) strncpy(track_path, path, MAX_PATH); track_path[MAX_PATH - 1] = '\0'; - char* track_name_pointer = track_path; - while (*track_name_pointer++ != '\0'); - while (*--track_name_pointer != '\\'); + char* track_name_pointer = strrchr(track_path, platform_get_path_separator()); track_name_pointer++; strncpy(track_dest_name, track_name_pointer, MAX_PATH); diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index a6e09be779..227483cce9 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -159,7 +159,7 @@ rct_window *window_loadsave_open(int type, char *defaultName) _defaultName[0] = 0; if (!str_is_null_or_empty(defaultName)) { - safe_strncpy(_defaultName, path_get_filename(defaultName), sizeof(_defaultName)); + safe_strncpy(_defaultName, defaultName, sizeof(_defaultName)); path_remove_extension(_defaultName); } @@ -277,7 +277,7 @@ static void window_loadsave_close(rct_window *w) static void window_loadsave_mouseup(rct_window *w, int widgetIndex) { int result; - char filename[MAX_PATH], filter[MAX_PATH]; + char path[MAX_PATH], filter[MAX_PATH]; switch (widgetIndex){ case WIDX_CLOSE: @@ -305,9 +305,9 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) break; } case WIDX_BROWSE: - safe_strncpy(filename, _directory, MAX_PATH); + safe_strncpy(path, _directory, MAX_PATH); if (_type & LOADSAVETYPE_SAVE) - strcat(filename, (char*)RCT2_ADDRESS_SCENARIO_NAME); + strcat(path, (char*)RCT2_ADDRESS_SCENARIO_NAME); memset(filter, '\0', MAX_PATH); safe_strncpy(filter, "*", MAX_PATH); @@ -315,30 +315,30 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) switch (_type) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_GAME), filename, filter, _extension); + result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_GAME), path, filter, _extension); break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_GAME), filename, filter, _extension); + result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_GAME), path, filter, _extension); break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_LANDSCAPE), filename, filter, _extension); + result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_LANDSCAPE), path, filter, _extension); break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_LANDSCAPE), filename, filter, _extension); + result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_LANDSCAPE), path, filter, _extension); break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_SCENARIO), filename, filter, _extension); + result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_SCENARIO), path, filter, _extension); break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(1039), filename, filter, _extension); + result = platform_open_common_file_dialog(1, (char*)language_get_string(1039), path, filter, _extension); break; } if (result) { - if (!has_extension(filename, _extension)) { - strncat(filename, _extension, MAX_PATH); + if (!has_extension(path, _extension)) { + strncat(path, _extension, MAX_PATH); } - window_loadsave_select(w, filename); + window_loadsave_select(w, path); } break; case WIDX_SORT_NAME: @@ -573,15 +573,6 @@ static void window_loadsave_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i } } -static int compare_string_case_insensitive(char const *a, char const *b) -{ - for (;; a++, b++) { - int d = tolower(*a) - tolower(*b); - if (d != 0 || !*a) - return d; - } -} - static int list_item_sort(const void *a, const void *b) { const loadsave_list_item *itemA = (loadsave_list_item*)a; @@ -592,15 +583,15 @@ static int list_item_sort(const void *a, const void *b) switch (gConfigGeneral.load_save_sort){ case SORT_NAME_ASCENDING: - return compare_string_case_insensitive(itemA->name, itemB->name); + return strcicmp(itemA->name, itemB->name); case SORT_NAME_DESCENDING: - return -compare_string_case_insensitive(itemA->name, itemB->name); + return -strcicmp(itemA->name, itemB->name); case SORT_DATE_DESCENDING: return (int) -difftime(itemA->date_modified, itemB->date_modified); case SORT_DATE_ASCENDING: return (int) difftime(itemA->date_modified, itemB->date_modified); default: - return compare_string_case_insensitive(itemA->name, itemB->name); + return strcicmp(itemA->name, itemB->name); } } @@ -745,7 +736,7 @@ static void window_loadsave_select(rct_window *w, const char *path) case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : if (gLoadSaveTitleSequenceSave) { utf8 newName[MAX_PATH]; - char *extension = (char*)path_get_extension(path_get_filename(path)); + char *extension = (char*)path_get_extension(path); safe_strncpy(newName, path_get_filename(path), MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6");