From 574477866fe3e82a87214848d3d4b505535f2d3b Mon Sep 17 00:00:00 2001 From: Filoppi Date: Tue, 11 May 2021 16:30:29 +0300 Subject: [PATCH] InputCommon: fix serialization of control expression with line breaks The control expression editor allows line breaks, but the serialization was losing anything after the first line break (/r /n). Instead of opting to encode them and decode them on serialization (which I tried but was not safe, as it would lose /n written in the string by users), I opted to replace them with a space. --- Source/Core/Common/StringUtil.cpp | 9 ++++++++- Source/Core/Common/StringUtil.h | 2 ++ .../ControllerEmu/ControlGroup/ControlGroup.cpp | 9 +++++++-- .../InputCommon/ControllerEmu/Setting/NumericSetting.h | 9 ++++++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index ffda64c79f..9c57bf944a 100644 --- a/Source/Core/Common/StringUtil.cpp +++ b/Source/Core/Common/StringUtil.cpp @@ -219,7 +219,7 @@ std::string ArrayToString(const u8* data, u32 size, int line_len, bool spaces) return oss.str(); } -// Turns " hello " into "hello". Also handles tabs. +// Turns "\n\r\t hello " into "hello" (trims at the start and end but not inside). std::string_view StripSpaces(std::string_view str) { const size_t s = str.find_first_not_of(" \t\r\n"); @@ -241,6 +241,13 @@ std::string_view StripQuotes(std::string_view s) return s; } +// Turns "\n\rhello" into " hello". +void ReplaceBreaksWithSpaces(std::string& str) +{ + std::replace(str.begin(), str.end(), '\r', ' '); + std::replace(str.begin(), str.end(), '\n', ' '); +} + bool TryParse(const std::string& str, bool* const output) { float value; diff --git a/Source/Core/Common/StringUtil.h b/Source/Core/Common/StringUtil.h index 615127d191..ada0eee3bd 100644 --- a/Source/Core/Common/StringUtil.h +++ b/Source/Core/Common/StringUtil.h @@ -52,6 +52,8 @@ std::string_view StripQuotes(std::string_view s); std::string ReplaceAll(std::string result, std::string_view src, std::string_view dest); +void ReplaceBreaksWithSpaces(std::string& str); + bool TryParse(const std::string& str, bool* output); template || std::is_enum_v>* = nullptr> diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp index 84c7238e48..2862445392 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp @@ -117,7 +117,10 @@ void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, for (auto& c : controls) { // control expression - sec->Set(group + c->name, c->control_ref->GetExpression(), ""); + std::string expression = c->control_ref->GetExpression(); + // We can't save line breaks in a single line config. Restoring them is too complicated. + ReplaceBreaksWithSpaces(expression); + sec->Set(group + c->name, expression, ""); // range sec->Set(group + c->name + "/Range", c->control_ref->range * 100.0, 100.0); @@ -135,7 +138,9 @@ void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, } else { - sec->Set(base + name, ext->GetSelectionSetting().GetInputReference().GetExpression(), "None"); + std::string expression = ext->GetSelectionSetting().GetInputReference().GetExpression(); + ReplaceBreaksWithSpaces(expression); + sec->Set(base + name, expression, "None"); } for (auto& ai : ext->GetAttachmentList()) diff --git a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h index 443f34d2ec..86bd2e39c3 100644 --- a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h +++ b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h @@ -113,9 +113,16 @@ public: void SaveToIni(IniFile::Section& section, const std::string& group_name) const override { if (IsSimpleValue()) + { section.Set(group_name + m_details.ini_name, GetValue(), m_default_value); + } else - section.Set(group_name + m_details.ini_name, m_value.m_input.GetExpression(), ""); + { + // We can't save line breaks in a single line config. Restoring them is too complicated. + std::string expression = m_value.m_input.GetExpression(); + ReplaceBreaksWithSpaces(expression); + section.Set(group_name + m_details.ini_name, expression, ""); + } } bool IsSimpleValue() const override { return m_value.IsSimpleValue(); }