diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index 3a6a454c9..e1e7c6638 100644 --- a/PowerEditor/src/MISC/Common/Common.cpp +++ b/PowerEditor/src/MISC/Common/Common.cpp @@ -778,13 +778,16 @@ int stoiStrict(const generic_string& input) } } -bool allLinesAreNumeric(const std::vector& lines) +bool allLinesAreNumericOrEmpty(const std::vector& lines) { for (const generic_string& line : lines) { try { - stoiStrict(line); + if (!line.empty()) + { + stoiStrict(line); + } } catch (std::invalid_argument&) { @@ -798,6 +801,18 @@ bool allLinesAreNumeric(const std::vector& lines) return true; } +std::vector repeatString(const generic_string& text, const size_t count) +{ + std::vector output; + output.reserve(count); + for (size_t i = 0; i < count; ++i) + { + output.push_back(text); + } + assert(output.size() == count); + return output; +} + std::vector lexicographicSort(std::vector input, bool isDescending) { std::sort(input.begin(), input.end(), [isDescending](generic_string a, generic_string b) @@ -816,14 +831,24 @@ std::vector lexicographicSort(std::vector input, std::vector numericSort(std::vector input, bool isDescending) { - // Pre-condition: all strings in "input" are convertible to int with stoiStrict. - std::vector inputAsInts; - inputAsInts.reserve(input.size()); + // Pre-condition: all strings in "input" are either empty or convertible to int with stoiStrict. + // Note that empty lines are filtered out and added back manually to the output at the end. + std::vector nonEmptyinputAsInts; + size_t nofEmptyLines = 0; + nonEmptyinputAsInts.reserve(input.size()); for (const generic_string& line : input) { - inputAsInts.push_back(stoiStrict(line)); + if (line.empty()) + { + ++nofEmptyLines; + } + else + { + nonEmptyinputAsInts.push_back(stoiStrict(line)); + } } - std::sort(inputAsInts.begin(), inputAsInts.end(), [isDescending](int a, int b) + assert(nonEmptyinputAsInts.size() + nofEmptyLines == input.size()); + std::sort(nonEmptyinputAsInts.begin(), nonEmptyinputAsInts.end(), [isDescending](int a, int b) { if (isDescending) { @@ -836,9 +861,19 @@ std::vector numericSort(std::vector input, bool }); std::vector output; output.reserve(input.size()); - for (const int& sortedInt : inputAsInts) + const std::vector empties = repeatString(TEXT(""), nofEmptyLines); + if (!isDescending) + { + output.insert(output.end(), empties.begin(), empties.end()); + } + for (const int& sortedInt : nonEmptyinputAsInts) { output.push_back(std::to_wstring(sortedInt)); } + if (isDescending) + { + output.insert(output.end(), empties.begin(), empties.end()); + } + assert(output.size() == input.size()); return output; } \ No newline at end of file diff --git a/PowerEditor/src/MISC/Common/Common.h b/PowerEditor/src/MISC/Common/Common.h index a8dc3143a..a86e63298 100644 --- a/PowerEditor/src/MISC/Common/Common.h +++ b/PowerEditor/src/MISC/Common/Common.h @@ -191,7 +191,8 @@ generic_string stringReplace(generic_string subject, const generic_string& searc std::vector stringSplit(const generic_string& input, const generic_string& delimiter); generic_string stringJoin(const std::vector& strings, const generic_string& separator); int stoiStrict(const generic_string& input); -bool allLinesAreNumeric(const std::vector& lines); +bool allLinesAreNumericOrEmpty(const std::vector& lines); +std::vector repeatString(const generic_string& text, const size_t count); std::vector numericSort(std::vector input, bool isDescending); std::vector lexicographicSort(std::vector input, bool isDescending); diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp index dcfe800f8..91cad99a3 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp @@ -2968,7 +2968,7 @@ void ScintillaEditView::sortLines(size_t fromLine, size_t toLine, bool isDescend } } assert(toLine - fromLine + 1 == splitText.size()); - const bool isNumericSort = allLinesAreNumeric(splitText); + const bool isNumericSort = allLinesAreNumericOrEmpty(splitText); std::vector sortedText; if (isNumericSort) {