reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit eb453aaca94cc029b16ded25726ae45ed3fc75e8
parent 4b3d4eaeb0b466543862a3e9b08e83d51a5ba555
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Wed,  6 May 2020 19:31:33 -0400

strip away RTF to enable richtext display on Linux [p=2247988]

Diffstat:
Msrc/richedit-generic.cpp | 6++++--
Msrc/string.cpp | 30++++++++++++++++++++++++++++++
Msrc/string.hpp | 1+
Mtest/string.cpp | 35+++++++++++++++++++++++++++++++++++
4 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/src/richedit-generic.cpp b/src/richedit-generic.cpp @@ -17,6 +17,8 @@ #include "richedit.hpp" +#include "string.hpp" + // This is the Linux implementation of RichEdit // See also richedit.mm and richedit-win32.cpp @@ -42,6 +44,6 @@ void RichEdit::setPlainText(const std::string &text) bool RichEdit::setRichText(const std::string &rtf) { - (void)rtf; - return false; + setPlainText(String::stripRtf(rtf)); + return true; } diff --git a/src/string.cpp b/src/string.cpp @@ -17,8 +17,10 @@ #include "string.hpp" +#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/trim.hpp> #include <cstdarg> +#include <regex> #include <sstream> std::string String::format(const char *fmt, ...) @@ -63,6 +65,34 @@ std::string String::indent(const std::string &text) return output; } +std::string String::stripRtf(const std::string &rtf) +{ + static const std::regex rtfRules( + // passthrough for later replacement to \n + R"((\\line |\\par\}))" "|" + R"(\\line(\n)\s*)" "|" + + // preserve literal braces + R"(\\([\{\}]))" "|" + + // hidden groups (strip contents) + R"(\{\\(?:f\d+|fonttbl|colortbl)[^\{\}]+\})" "|" + + // formatting tags and groups (keep contents) + R"(\\\w+\s?|\{|\})" "|" + + // newlines and indentation + R"(\s*\n\s*)" + ); + + std::string text = std::regex_replace(rtf, rtfRules, "$1$2$3"); + boost::algorithm::replace_all(text, "\\line ", "\n"); + boost::algorithm::replace_all(text, "\\par}", "\n\n"); + boost::algorithm::trim(text); + + return text; +} + void String::ImplDetail::imbueStream(std::ostream &stream) { class NumPunct : public std::numpunct<char> diff --git a/src/string.hpp b/src/string.hpp @@ -32,6 +32,7 @@ namespace String { std::string format(const char *fmt, ...); std::string indent(const std::string &); + std::string stripRtf(const std::string &); template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> std::string number(const T v) diff --git a/test/string.cpp b/test/string.cpp @@ -25,3 +25,38 @@ TEST_CASE("indent string", M) { TEST_CASE("pretty-print numbers", M) { REQUIRE(String::number(42'000'000) == "42,000,000"); } + +TEST_CASE("strip RTF header", M) { + REQUIRE("Hello World" == String::stripRtf(R"( + {\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard + Hello World + } + )")); +} + +TEST_CASE("strip RTF color header", M) { + REQUIRE("Hello World" == String::stripRtf(R"( + {\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}} + {\colortbl;\red255\green0\blue0;\red0\green0\blue255;} + \widowctrl\hyphauto + Hello World + } + )")); +} + +TEST_CASE("strip RTF paragraphs", M) { + REQUIRE("foo\n\nbar\n\nbaz" == String::stripRtf(R"( + {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 foo\par} + {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 bar\par} + {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs36 baz\par} + )")); +} + +TEST_CASE("strip RTF line breaks", M) { + REQUIRE("foo\nbar\nbaz" == String::stripRtf(R"(foo\line bar\line + baz\line)")); +} + +TEST_CASE("strip RTF literal braces", M) { + REQUIRE("{ }" == String::stripRtf(R"(\{ \})")); +}