From ea36c6e5d7e0f3cbc3742dfb136d6aae5b42877e Mon Sep 17 00:00:00 2001 From: Arthur Camouseigt Date: Mon, 7 Sep 2020 16:18:49 +0200 Subject: [PATCH] [Clipboard] Changed the general copy/paste Fixed issues due to copy/paste of empty formulas. When pasted, empty formulas are now recognized by the parser and apear with the correct layout Without this process, copying an empty integral then pasting it gives : int((), x, (), ()) instead of drawing an empty integral Change-Id: I680aaf4eea953149e2d57efa8153ab4d3f93e2a7 --- escher/include/escher/clipboard.h | 2 +- escher/src/clipboard.cpp | 25 +++++++++++++++++++++++++ escher/test/clipboard.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/escher/include/escher/clipboard.h b/escher/include/escher/clipboard.h index 808cbd9d3..63431faec 100644 --- a/escher/include/escher/clipboard.h +++ b/escher/include/escher/clipboard.h @@ -9,7 +9,7 @@ class Clipboard { public: static Clipboard * sharedClipboard(); void store(const char * storedText, int length = -1); - const char * storedText() { return m_textBuffer; } + const char * storedText(); void reset(); void enterPython() { replaceCharForPython(true); } void exitPython() { replaceCharForPython(false); } diff --git a/escher/src/clipboard.cpp b/escher/src/clipboard.cpp index 5fa300799..863ea183a 100644 --- a/escher/src/clipboard.cpp +++ b/escher/src/clipboard.cpp @@ -12,6 +12,31 @@ void Clipboard::store(const char * storedText, int length) { strlcpy(m_textBuffer, storedText, length == -1 ? TextField::maxBufferSize() : std::min(TextField::maxBufferSize(), length + 1)); } +const char * Clipboard::storedText() { + /* In order to allow copy/paste of empty formulas, we need to add empty + * layouts between empty system parenthesis. This way, when the expression + * is parsed, it is recognized as a proper formula and appears with the correct + * visual layout. + * Without this process, copying an empty integral then pasting it gives : + * int((), x, (), ()) instead of drawing an empty integral. + * + * Furthermore, in case the user switches from linear to natural writing mode + * we need to add an empty layout between parenthesis to allow proper layout + * construction. */ + constexpr int numberOfPairs = 6; + constexpr UTF8Helper::TextPair textPairs[numberOfPairs] = { + UTF8Helper::TextPair("()", "(\x11)"), + UTF8Helper::TextPair("[]", "[\x11]"), + UTF8Helper::TextPair("[,", "[\x11,"), + UTF8Helper::TextPair(",,", ",\x11,"), + UTF8Helper::TextPair(",]", ",\x11]"), + UTF8Helper::TextPair("\x12\x13", "\x12\x11\x13"), + }; + + UTF8Helper::tryAndReplacePatternsInStringByPatterns(m_textBuffer, TextField::maxBufferSize(), (UTF8Helper::TextPair *) &textPairs, numberOfPairs, true); + return m_textBuffer; +} + void Clipboard::reset() { strlcpy(m_textBuffer, "", 1); } diff --git a/escher/test/clipboard.cpp b/escher/test/clipboard.cpp index 7c895c9b4..510c683ef 100644 --- a/escher/test/clipboard.cpp +++ b/escher/test/clipboard.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include void assert_clipboard_enters_and_exits_python(const char * string, const char * stringResult) { @@ -19,3 +21,29 @@ QUIZ_CASE(escher_clipboard_enters_and_exits_python) { assert_clipboard_enters_and_exits_python("1×𝐢^2", "1*1j**2"); assert_clipboard_enters_and_exits_python("12^(1/4)×(π/6)×(12×π)^(1/4)", "12**(1/4)*(pi/6)*(12*pi)**(1/4)"); } + +using namespace Poincare; + +void assert_stored_text_is_parseable(Poincare::Layout layout) { + constexpr int bufferSize = 500; + char buffer[bufferSize]; + layout.serializeForParsing(buffer, bufferSize); + Clipboard * clipboard = Clipboard::sharedClipboard(); + clipboard->store(buffer); + Expression e = Expression::Parse(clipboard->storedText(), nullptr, false); + Layout result = e.createLayout(Preferences::sharedPreferences()->displayMode(), Poincare::PrintFloat::k_numberOfStoredSignificantDigits); + quiz_assert(layout.isIdenticalTo(result)); +} + +QUIZ_CASE(escher_clipboard_stored_text_is_parseable) { + Layout l = IntegralLayout::Builder(EmptyLayout::Builder(), CodePointLayout::Builder('x'), EmptyLayout::Builder(), EmptyLayout::Builder()); + assert_stored_text_is_parseable(l); + l = NthRootLayout::Builder(EmptyLayout::Builder()); + assert_stored_text_is_parseable(l); + l = MatrixLayout::Builder(CodePointLayout::Builder('1'), EmptyLayout::Builder(), EmptyLayout::Builder(), CodePointLayout::Builder('2')); + assert_stored_text_is_parseable(l); + l = SumLayout::Builder(EmptyLayout::Builder(), CodePointLayout::Builder('n'), EmptyLayout::Builder(), EmptyLayout::Builder()); + assert_stored_text_is_parseable(l); + l = SumLayout::Builder(EmptyLayout::Builder(), CodePointLayout::Builder('n'), EmptyLayout::Builder(), EmptyLayout::Builder()); + assert_stored_text_is_parseable(l);; +} \ No newline at end of file