[apps/code] autocompletionText uses the right text length

Before, there was no notion that the autocompleted text might not be a
null terminated string.
This commit is contained in:
Léa Saviot
2020-03-24 18:03:46 +01:00
committed by Émilie Feral
parent 12bb77cd9f
commit eeb42f2544
10 changed files with 31 additions and 35 deletions

View File

@@ -256,6 +256,7 @@ void PythonTextArea::addAutocompletion() {
const char * autocompletionLocation = const_cast<char *>(cursorLocation());
const char * textToInsert = nullptr;
int textToInsertLength = 0;
CodePoint prevCodePoint = UTF8Helper::PreviousCodePoint(m_contentView.editedText(), autocompletionLocation);
if (!UTF8Helper::CodePointIsEndOfWord(prevCodePoint)
&& UTF8Helper::CodePointIsEndOfWord(UTF8Helper::CodePointAtLocation(autocompletionLocation)))
@@ -267,11 +268,11 @@ void PythonTextArea::addAutocompletion() {
* builtins, then in the imported modules/scripts. */
VariableBoxController * varBox = m_contentView.pythonDelegate()->variableBoxController();
const char * beginningOfWord = m_contentView.textToAutocomplete();
textToInsert = varBox->autocompletionForText(m_contentView.pythonDelegate()->menuController()->editedScriptIndex(), beginningOfWord);
textToInsert = varBox->autocompletionForText(m_contentView.pythonDelegate()->menuController()->editedScriptIndex(), beginningOfWord, &textToInsertLength);
}
// Try to insert the text (this might fail if the buffer is full)
if (textToInsert && m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation))) {
if (textToInsert && textToInsertLength > 0 && m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength)) {
m_contentView.setAutocompleting(true);
}
}

View File

@@ -331,7 +331,7 @@ void VariableBoxController::loadFunctionsAndVariables(int scriptIndex, const cha
#endif
}
const char * VariableBoxController::autocompletionForText(int scriptIndex, const char * text) {
const char * VariableBoxController::autocompletionForText(int scriptIndex, const char * text, int * textToInsertLength) {
// TODO LEA Accelerate
loadFunctionsAndVariables(scriptIndex, text);
const char * endOfText = UTF8Helper::EndOfWord(text);
@@ -342,6 +342,7 @@ const char * VariableBoxController::autocompletionForText(int scriptIndex, const
const char * currentName = node->name();
int currentNameLength = node->nameLength();
if ((currentNameLength < 0 || currentNameLength != textLength) && strncmp(text, currentName, textLength) == 0) {
*textToInsertLength = currentNameLength - textLength;
return currentName + textLength;
}
}

View File

@@ -27,7 +27,7 @@ public:
/* VariableBoxController */
void loadFunctionsAndVariables(int scriptIndex, const char * textToAutocomplete);
const char * autocompletionForText(int scriptIndex, const char * text);
const char * autocompletionForText(int scriptIndex, const char * text, int * textToInsertLength);
private:
constexpr static int k_maxScriptObjectNameSize = 100;
constexpr static int k_maxNumberOfDisplayedRows = 6; // 240/40

View File

@@ -117,7 +117,7 @@ protected:
const char * editedText() const override { return m_text.text(); }
size_t editedTextLength() const override { return m_text.textLength(); }
const Text * getText() const { return &m_text; }
bool insertTextAtLocation(const char * text, char * location) override;
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
void moveCursorGeo(int deltaX, int deltaY);
bool removePreviousGlyph() override;
bool removeEndOfLine() override;

View File

@@ -74,7 +74,7 @@ protected:
/* If the text to be appended is too long to be added without overflowing the
* buffer, nothing is done (not even adding few letters from the text to reach
* the maximum buffer capacity) and false is returned. */
bool insertTextAtLocation(const char * text, char * location) override;
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
KDSize minimalSizeForOptimalDisplay() const override;
bool removePreviousGlyph() override;
bool removeEndOfLine() override;

View File

@@ -49,7 +49,7 @@ protected:
// Virtual text get/add/remove
virtual const char * text() const = 0;
virtual bool insertTextAtLocation(const char * text, char * location) = 0;
virtual bool insertTextAtLocation(const char * text, char * location, int textLength = -1) = 0;
virtual bool removePreviousGlyph() = 0;
virtual bool removeEndOfLine() = 0;

View File

@@ -458,26 +458,19 @@ void TextArea::ContentView::setText(char * textBuffer, size_t textBufferSize) {
m_cursorLocation = text();
}
bool TextArea::ContentView::insertTextAtLocation(const char * text, char * location) {
int textSize = strlen(text);
if (m_text.textLength() + textSize >= m_text.bufferSize() || textSize == 0) {
bool TextArea::ContentView::insertTextAtLocation(const char * text, char * location, int textLength) {
int textLen = textLength < 0 ? strlen(text) : textLength;
assert(textLen < 0 || textLen <= strlen(text));
if (m_text.textLength() + textLen >= m_text.bufferSize() || textLen == 0) {
return false;
}
bool lineBreak = false;
// Scan for \n and 0
const char * nullLocation = UTF8Helper::PerformAtCodePoints(
text, '\n',
[](int codePointOffset, void * lineBreak, int context1, int context2) {
*((bool *)lineBreak) = true;
},
[](int c1, void * c2, int c3, int c4) { },
&lineBreak, 0);
// Scan for \n
bool lineBreak = UTF8Helper::HasCodePoint(text, '\n', text + textLen);
assert(UTF8Helper::CodePointIs(nullLocation, 0));
m_text.insertText(text, nullLocation - text, location);
m_text.insertText(text, textLen, location);
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, nullLocation - text);
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, textLen);
reloadRectFromPosition(location, lineBreak);
return true;
}

View File

@@ -119,10 +119,10 @@ void TextField::ContentView::reinitDraftTextBuffer() {
setCursorLocation(s_draftTextBuffer);
}
bool TextField::ContentView::insertTextAtLocation(const char * text, char * location) {
bool TextField::ContentView::insertTextAtLocation(const char * text, char * location, int textLen) {
assert(m_isEditing);
int textLength = strlen(text);
int textLength = textLen < 0 ? strlen(text) : textLen;
if (m_currentDraftTextLength + textLength >= m_draftTextBufferSize || textLength == 0) {
return false;
}
@@ -130,12 +130,12 @@ bool TextField::ContentView::insertTextAtLocation(const char * text, char * loca
memmove(location + textLength, location, (s_draftTextBuffer + m_currentDraftTextLength + 1) - location);
// Caution! One byte will be overridden by the null-terminating char of strlcpy
char * overridenByteLocation = location + textLength;
size_t copySize = std::min(textLength, (s_draftTextBuffer + m_draftTextBufferSize) - location);
char * overridenByteLocation = location + copySize;
char overridenByte = *overridenByteLocation;
strlcpy(location, text, (s_draftTextBuffer + m_draftTextBufferSize) - location);
assert(overridenByteLocation < s_draftTextBuffer + m_draftTextBufferSize);
strlcpy(location, text, copySize);
*overridenByteLocation = overridenByte;
m_currentDraftTextLength += textLength;
m_currentDraftTextLength += copySize;
reloadRectFromPosition(m_horizontalAlignment == 0.0f ? location : s_draftTextBuffer);
return true;

View File

@@ -11,10 +11,10 @@ int CountOccurrences(const char * s, CodePoint c);
/* Returns the first occurence of a code point in a string, the position of the
* null terminating char otherwise. */
const char * CodePointSearch(const char * s, CodePoint c);
const char * CodePointSearch(const char * s, CodePoint c, const char * stoppingPosition = nullptr);
// Returns true if the text had the code point
bool HasCodePoint(const char * s, CodePoint c);
bool HasCodePoint(const char * s, CodePoint c, const char * stoppingPosition = nullptr);
/* Returns the first occurence of a code point that is not c in a string,
* stopping at the null-terminating char or the start of string. */

View File

@@ -33,10 +33,10 @@ int CountOccurrences(const char * s, CodePoint c) {
return count;
}
const char * CodePointSearch(const char * s, CodePoint c) {
const char * CodePointSearch(const char * s, CodePoint c, const char * stoppingPosition) {
if (UTF8Decoder::CharSizeOfCodePoint(c) == 1) {
const char * result = s;
while (*result != 0 && *result != c) {
while (*result != 0 && *result != c && (stoppingPosition == nullptr || result != stoppingPosition)) {
result++;
}
return result;
@@ -45,7 +45,7 @@ const char * CodePointSearch(const char * s, CodePoint c) {
const char * currentPointer = s;
CodePoint codePoint = decoder.nextCodePoint();
const char * nextPointer = decoder.stringPosition();
while (codePoint != UCodePointNull && codePoint != c) {
while (codePoint != UCodePointNull && codePoint != c && (stoppingPosition == nullptr || currentPointer < stoppingPosition)) {
currentPointer = nextPointer;
codePoint = decoder.nextCodePoint();
nextPointer = decoder.stringPosition();
@@ -53,9 +53,10 @@ const char * CodePointSearch(const char * s, CodePoint c) {
return currentPointer;
}
bool HasCodePoint(const char * s, CodePoint c) {
bool HasCodePoint(const char * s, CodePoint c, const char * stoppingPosition) {
assert(c != 0);
return *CodePointSearch(s, c) != 0;
const char * resultPosition = CodePointSearch(s, c, stoppingPosition);
return *resultPosition != 0 && (stoppingPosition == nullptr || resultPosition < stoppingPosition);
}
const char * NotCodePointSearch(const char * s, CodePoint c, bool goingLeft, const char * initialPosition) {