From ae3fa461917361aad99dbc066fbbf12aa889e4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 30 Jan 2020 16:31:58 +0100 Subject: [PATCH] [escher/text_field] Fix handling of \n The buffer length did not take into account the \n removal. In fact, we could just remove the \n while also removing the empty code points, which is what we do now. --- escher/src/text_field.cpp | 24 +++----------- ion/include/ion/unicode/utf8_helper.h | 5 ++- ion/src/shared/unicode/utf8_helper.cpp | 14 +++++--- ion/test/utf8_helper.cpp | 45 ++++++++++++++------------ 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index c330a42e4..ccbdfc5e5 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -131,24 +131,6 @@ bool TextField::ContentView::insertTextAtLocation(const char * text, char * loca *overridenByteLocation = overridenByte; m_currentDraftTextLength += textLength; - // Remove the \n code points - UTF8Decoder decoder(s_draftTextBuffer); - const char * codePointPointer = decoder.stringPosition(); - CodePoint codePoint = decoder.nextCodePoint(); - assert(!codePoint.isCombining()); - while (codePoint != UCodePointNull) { - assert(codePointPointer < s_draftTextBuffer + m_draftTextBufferSize); - if (codePoint == '\n') { - assert(UTF8Decoder::CharSizeOfCodePoint('\n') == 1); - strlcpy(const_cast(codePointPointer), codePointPointer + 1, (s_draftTextBuffer + m_draftTextBufferSize) - codePointPointer); - // Put the decoder to the code point replacing \n - decoder.setPosition(codePointPointer); - } else { - codePointPointer = decoder.stringPosition(); - } - codePoint = decoder.nextCodePoint(); - } - reloadRectFromPosition(m_horizontalAlignment == 0.0f ? location : s_draftTextBuffer); return true; } @@ -508,8 +490,10 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation, bo // Remove the Empty code points constexpr int bufferSize = TextField::maxBufferSize(); char buffer[bufferSize]; - UTF8Helper::CopyAndRemoveCodePoint(buffer, bufferSize, eventText, UCodePointEmpty); - + { + CodePoint c[] = {UCodePointEmpty, '\n'}; + UTF8Helper::CopyAndRemoveCodePoints(buffer, bufferSize, eventText, c, 2); + } // Replace System parentheses (used to keep layout tree structure) by normal parentheses Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(buffer); diff --git a/ion/include/ion/unicode/utf8_helper.h b/ion/include/ion/unicode/utf8_helper.h index 2c90d7096..d38d3117d 100644 --- a/ion/include/ion/unicode/utf8_helper.h +++ b/ion/include/ion/unicode/utf8_helper.h @@ -20,10 +20,9 @@ bool HasCodePoint(const char * s, CodePoint c); * stopping at the null-terminating char or the start of string. */ const char * NotCodePointSearch(const char * s, CodePoint c, bool goingLeft = false, const char * initialPosition = nullptr); -/* Copy src into dst while removing all code points c. Also update an index - * that should be lower if code points where removed before it. Ensure null- +/* Copy src into dst while removing all code points in codePoints. Ensure null- * termination of dst. */ -void CopyAndRemoveCodePoint(char * dst, size_t dstSize, const char * src, CodePoint c); +void CopyAndRemoveCodePoints(char * dst, size_t dstSize, const char * src, CodePoint * codePoints, int numberOfCodePoints); /* Remove all code points c. and update an index that should be lower if code * points where removed before it. Ensure null-termination of dst. */ diff --git a/ion/src/shared/unicode/utf8_helper.cpp b/ion/src/shared/unicode/utf8_helper.cpp index 76a3fbd72..9facb69a7 100644 --- a/ion/src/shared/unicode/utf8_helper.cpp +++ b/ion/src/shared/unicode/utf8_helper.cpp @@ -94,21 +94,27 @@ const char * NotCodePointSearch(const char * s, CodePoint c, bool goingLeft, con return codePointPointer; } -void CopyAndRemoveCodePoint(char * dst, size_t dstSize, const char * src, CodePoint c) { +void CopyAndRemoveCodePoints(char * dst, size_t dstSize, const char * src, CodePoint * codePoints, int numberOfCodePoints) { if (dstSize <= 0) { return; } + assert(numberOfCodePoints >= 1); UTF8Decoder decoder(src); const char * currentPointer = src; CodePoint codePoint = decoder.nextCodePoint(); const char * nextPointer = decoder.stringPosition(); size_t bufferIndex = 0; - size_t codePointCharSize = UTF8Decoder::CharSizeOfCodePoint(c); - (void)codePointCharSize; // Silence compilation warning about unused variable. // Remove CodePoint c while (codePoint != UCodePointNull && bufferIndex < dstSize) { - if (codePoint != c) { + bool remove = false; + for (int i = 0; i < numberOfCodePoints; i++) { + if (codePoint == codePoints[i]) { + remove = true; + break; + } + } + if (!remove) { size_t copySize = nextPointer - currentPointer; if (copySize > dstSize - 1 - bufferIndex) { // Copying the current code point to the buffer would overflow the buffer diff --git a/ion/test/utf8_helper.cpp b/ion/test/utf8_helper.cpp index cd1d1f36b..39be3b366 100644 --- a/ion/test/utf8_helper.cpp +++ b/ion/test/utf8_helper.cpp @@ -45,10 +45,10 @@ QUIZ_CASE(ion_utf8_helper_not_code_point_search) { assert_not_code_point_searched_is(s, UCodePointGreekSmallLetterPi, true, s+5, s+2); } -void assert_copy_and_remove_code_point_gives(char * dst, size_t dstSize, const char * src, CodePoint c, const char * result) { +void assert_copy_and_remove_code_points_gives(char * dst, size_t dstSize, const char * src, CodePoint * c, int numberOfCodePoints, const char * result) { size_t resultLen = strlen(result); quiz_assert(dstSize >= resultLen + 1); - UTF8Helper::CopyAndRemoveCodePoint(dst, dstSize, src, c); + UTF8Helper::CopyAndRemoveCodePoints(dst, dstSize, src, c, numberOfCodePoints); for (size_t i = 0; i <= resultLen; i++) { quiz_assert(dst[i] == result[i]); } @@ -59,49 +59,54 @@ QUIZ_CASE(ion_utf8_copy_and_remove_code_point) { char buffer[bufferSize]; const char * s = "12345"; - CodePoint c = '1'; + CodePoint c1[] = {'1'}; const char * result = "2345"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c1, 1, result); s = "12345"; - c = '2'; + CodePoint c2[] = {'2'}; result = "1345"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c2, 1, result); s = "2123224252"; - c = '2'; + CodePoint c3[] = {'2'}; result = "1345"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c3, 1, result); s = "12345"; - c = '6'; + CodePoint c4[] = {'6'}; result = "12345"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c4, 1, result); s = "12ᴇ4"; - c = UCodePointLatinLetterSmallCapitalE; + CodePoint c5[] = {UCodePointLatinLetterSmallCapitalE}; result = "124"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c5, 1, result); s = "12ᴇᴇᴇ4"; - c = UCodePointLatinLetterSmallCapitalE; + CodePoint c6[] = {UCodePointLatinLetterSmallCapitalE}; result = "124"; - assert_copy_and_remove_code_point_gives(buffer, bufferSize, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c6, 1, result); // The buffer size is to small to hold s s = "1234ᴇ"; - c = '5'; + CodePoint c7[] = {'5'}; result = "1234"; // "1234ᴇ" size is 7 - assert_copy_and_remove_code_point_gives(buffer, 6, s, c, result); - assert_copy_and_remove_code_point_gives(buffer, 7, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, 6, s, c7, 1, result); + assert_copy_and_remove_code_points_gives(buffer, 7, s, c7, 1, result); result = "1234ᴇ"; - assert_copy_and_remove_code_point_gives(buffer, 8, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, 8, s, c7, 1, result); s = "1234ᴇ"; - c = '4'; + CodePoint c8[] = {'4'}; result = "123ᴇ"; - assert_copy_and_remove_code_point_gives(buffer, 7, s, c, result); + assert_copy_and_remove_code_points_gives(buffer, 7, s, c8, 1, result); + // Remove several code points + s = "1234ᴇ3"; + CodePoint c9[] = {'4', UCodePointLatinLetterSmallCapitalE}; + result = "1233"; + assert_copy_and_remove_code_points_gives(buffer, bufferSize, s, c9, 2, result); } void assert_remove_code_point_gives(char * buffer, CodePoint c, const char * * indexToUpdate, const char * stoppingPosition, const char * indexToUpdateResult, const char * result) {