[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.
This commit is contained in:
Léa Saviot
2020-01-30 16:31:58 +01:00
parent 4b996b333b
commit ae3fa46191
4 changed files with 41 additions and 47 deletions

View File

@@ -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<char *>(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);

View File

@@ -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. */

View File

@@ -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

View File

@@ -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) {