From f9fbcabb3013237b86a7eafdaf1956b8ef9f1063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 24 Jan 2019 11:34:50 +0100 Subject: [PATCH] [escher/ion] Factorize code for removing a code point in text field/area --- escher/include/escher/text_area.h | 2 +- escher/src/text_area.cpp | 26 +++++++---------------- escher/src/text_field.cpp | 29 ++++++++++---------------- ion/include/ion/unicode/utf8_helper.h | 4 ++++ ion/src/shared/unicode/utf8_helper.cpp | 23 ++++++++++++++++++++ 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/escher/include/escher/text_area.h b/escher/include/escher/text_area.h index d861d27e3..95d215b41 100644 --- a/escher/include/escher/text_area.h +++ b/escher/include/escher/text_area.h @@ -75,7 +75,7 @@ protected: void insertText(const char * s, int textLength, char * location); void insertSpacesAtLocation(int numberOfSpaces, char * location); - CodePoint removeCodePoint(const char * * position); + CodePoint removeCodePoint(char * * position); size_t removeRemainingLine(const char * position, int direction); char operator[](size_t index) { assert(index < m_bufferSize); diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index cddf40b23..694f26be5 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -199,29 +199,17 @@ void TextArea::Text::insertSpacesAtLocation(int numberOfSpaces, char * location) } } -CodePoint TextArea::Text::removeCodePoint(const char * * position) { +CodePoint TextArea::Text::removeCodePoint(char * * position) { assert(m_buffer != nullptr); assert(m_buffer <= *position && *position < m_buffer + m_bufferSize); - // Find the beginning of the previous code point - UTF8Decoder decoder(m_buffer, *position); - CodePoint deletedCodePoint = decoder.previousCodePoint(); - const char * newCursorLocation = decoder.stringPosition(); - assert(newCursorLocation < *position); + CodePoint removedCodePoint = 0; + int removedSize = UTF8Helper::RemovePreviousCodePoint(m_buffer, *position, &removedCodePoint); + assert(removedSize > 0); - // Shift the buffer - int codePointSize = *position - newCursorLocation; - assert(codePointSize == UTF8Decoder::CharSizeOfCodePoint(deletedCodePoint)); - assert(newCursorLocation >= m_buffer); - for (size_t i = newCursorLocation - m_buffer; i < m_bufferSize; i++) { - m_buffer[i] = m_buffer[i + codePointSize]; - if (m_buffer[i] == 0) { - break; - } - } // Set the new cursor position - *position = newCursorLocation; - return deletedCodePoint; + *position = *position - removedSize; + return removedCodePoint; } size_t TextArea::Text::removeRemainingLine(const char * location, int direction) { @@ -401,7 +389,7 @@ bool TextArea::TextArea::ContentView::removeCodePoint() { return false; } bool lineBreak = false; - const char * cursorLoc = cursorLocation(); + char * cursorLoc = const_cast(cursorLocation()); lineBreak = m_text.removeCodePoint(&cursorLoc) == '\n'; setCursorLocation(cursorLoc); // Update the cursor layoutSubviews(); // Reposition the cursor diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index 6482a6dd5..713999917 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -143,35 +143,28 @@ KDSize TextField::ContentView::minimalSizeForOptimalDisplay() const { bool TextField::ContentView::removeCodePoint() { assert(m_isEditing); - if (cursorLocation() <= m_draftTextBuffer) { + + // Remove the code point if possible + CodePoint removedCodePoint = 0; + int removedSize = UTF8Helper::RemovePreviousCodePoint(m_draftTextBuffer, const_cast(cursorLocation()), &removedCodePoint); + if (removedSize == 0) { assert(cursorLocation() == m_draftTextBuffer); return false; } - UTF8Decoder decoder(m_draftTextBuffer, cursorLocation()); - decoder.previousCodePoint(); - const char * newCursorLocation = decoder.stringPosition(); - assert(newCursorLocation < cursorLocation()); - int removedCodePointLength = cursorLocation() - newCursorLocation; - m_currentDraftTextLength-= removedCodePointLength; + // Update the draft buffer length + m_currentDraftTextLength-= removedSize; + assert(m_draftTextBuffer[m_currentDraftTextLength] == 0); + // Reload the view and set the cursor location if (m_horizontalAlignment > 0.0f) { reloadRectFromPosition(m_draftTextBuffer); } - - setCursorLocation(newCursorLocation); + assert(cursorLocation() - removedSize >= m_draftTextBuffer); + setCursorLocation(cursorLocation() - removedSize); if (m_horizontalAlignment == 0.0f) { reloadRectFromPosition(cursorLocation()); } - - for (char * k = const_cast(cursorLocation()); k < m_draftTextBuffer + m_currentDraftTextLength + removedCodePointLength; k++) { - *k = *(k+removedCodePointLength); - if (*k == 0) { - break; - } - } - - assert(m_draftTextBuffer[m_currentDraftTextLength] == 0); layoutSubviews(); return true; } diff --git a/ion/include/ion/unicode/utf8_helper.h b/ion/include/ion/unicode/utf8_helper.h index 8a19ec440..5dc1c6099 100644 --- a/ion/include/ion/unicode/utf8_helper.h +++ b/ion/include/ion/unicode/utf8_helper.h @@ -43,6 +43,10 @@ const char * PerformAtCodePoints(const char * string, CodePoint c, CodePointAct bool PreviousCodePointIs(const char * buffer, const char * location, CodePoint c); bool CodePointIs(const char * location, CodePoint c); +// Shift the buffer and return the number of bytes removed. +int RemovePreviousCodePoint(const char * text, char * location, CodePoint * c); + + }; #endif diff --git a/ion/src/shared/unicode/utf8_helper.cpp b/ion/src/shared/unicode/utf8_helper.cpp index 79e4a7659..9bc689032 100644 --- a/ion/src/shared/unicode/utf8_helper.cpp +++ b/ion/src/shared/unicode/utf8_helper.cpp @@ -169,4 +169,27 @@ bool CodePointIs(const char * location, CodePoint c) { return decoder.nextCodePoint() == c; } +int RemovePreviousCodePoint(const char * text, char * location, CodePoint * c) { + assert(c != nullptr); + if (location <= text) { + assert(location == text); + return 0; + } + + // Find the previous code point + UTF8Decoder decoder(text, location); + *c = decoder.previousCodePoint(); + + // Shift the buffer + int codePointSize = UTF8Decoder::CharSizeOfCodePoint(*c); + char * iterator = location - codePointSize; + assert(iterator >= text); + do { + *iterator = *(iterator + codePointSize); + iterator++; + } while (*(iterator - 1) != 0); // Stop shifting after writing a null terminating char. + + return codePointSize; +} + };