From f52d9a878de95ca50788f1773d2c7c48301a6789 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 8 Jan 2020 16:04:00 +0100 Subject: [PATCH] Fix T72878: Alphabetical sorting in Outliner sorts shorter names last E.g. "Cube" would be placed after "Cube.001", which is not what you'd expect. 2.80 handled this correctly. Loosely based on D6525 by @radcapricorn, but found a bug in that and prefered to do some further adjustments. Also activates test for this case. --- source/blender/blenlib/intern/string.c | 19 +++++++++++++------ tests/gtests/blenlib/BLI_string_test.cc | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 0b8ec44cbcd..1eed59e568e 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -685,6 +685,7 @@ int BLI_strcasecmp_natural(const char *s1, const char *s2) return numcompare; } + /* Some wasted work here, left_number_strcmp already consumes at least some digits. */ d1++; while (isdigit(s1[d1])) { d1++; @@ -695,14 +696,22 @@ int BLI_strcasecmp_natural(const char *s1, const char *s2) } } + /* Test for end of strings first so that shorter strings are ordered in front. */ + if (ELEM(0, s1[d1], s2[d2])) { + break; + } + c1 = tolower(s1[d1]); c2 = tolower(s2[d2]); - /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ - if (c1 == '.' && c2 != '.') { + if (c1 == c2) { + /* Continue iteration */ + } + /* Check for '.' so "foo.bar" comes before "foo 1.bar". */ + else if (c1 == '.') { return -1; } - if (c1 != '.' && c2 == '.') { + else if (c2 == '.') { return 1; } else if (c1 < c2) { @@ -711,9 +720,7 @@ int BLI_strcasecmp_natural(const char *s1, const char *s2) else if (c1 > c2) { return 1; } - else if (c1 == 0) { - break; - } + d1++; d2++; } diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc index b7c09796960..5766339f10d 100644 --- a/tests/gtests/blenlib/BLI_string_test.cc +++ b/tests/gtests/blenlib/BLI_string_test.cc @@ -801,7 +801,7 @@ TEST_F(StringCasecmpNatural, TextAndNumbers) const CompareWordsArray negative{ {"00je møder0", "00je møder1"}, {"05je møder0", "06je møder1"}, - // {"Cube", "Cube.001"}, + {"Cube", "Cube.001"}, {"Cube.001", "Cube.002"}, {"CUbe.001", "Cube.002"}, {"CUbe.002", "Cube.002"},