mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user