Fixed ctrl + backspace on empty lines

Fix <word><space><caret> scenario

Fix move left & right for lines without words
This commit is contained in:
Marc Garcia Puig 2022-02-21 22:32:24 +01:00
parent c630c2001d
commit f22d257025
2 changed files with 42 additions and 22 deletions

View File

@ -2133,16 +2133,21 @@ void TextEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
if (p_move_by_word) { if (p_move_by_word) {
int cc = caret.column; int cc = caret.column;
// If the caret is at the start of the line, and not on the first line, move it up to the end of the previous line.
if (cc == 0 && caret.line > 0) { if (cc == 0 && caret.line > 0) {
set_caret_line(caret.line - 1); set_caret_line(caret.line - 1);
set_caret_column(text[caret.line].length()); set_caret_column(text[caret.line].length());
} else { } else {
PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = words.size() - 2; i >= 0; i = i - 2) { if (words.is_empty() || cc <= words[0]) {
if (words[i] < cc) { // This solves the scenario where there are no words but glyfs that can be ignored.
cc = words[i]; cc = 0;
break; } else {
for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i] < cc) {
cc = words[i];
break;
}
} }
} }
set_caret_column(cc); set_caret_column(cc);
@ -2184,16 +2189,21 @@ void TextEdit::_move_caret_right(bool p_select, bool p_move_by_word) {
if (p_move_by_word) { if (p_move_by_word) {
int cc = caret.column; int cc = caret.column;
// If the caret is at the end of the line, and not on the last line, move it down to the beginning of the next line.
if (cc == text[caret.line].length() && caret.line < text.size() - 1) { if (cc == text[caret.line].length() && caret.line < text.size() - 1) {
set_caret_line(caret.line + 1); set_caret_line(caret.line + 1);
set_caret_column(0); set_caret_column(0);
} else { } else {
PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = 1; i < words.size(); i = i + 2) { if (words.is_empty() || cc >= words[words.size() - 1]) {
if (words[i] > cc) { // This solves the scenario where there are no words but glyfs that can be ignored.
cc = words[i]; cc = text[caret.line].length();
break; } else {
for (int i = 1; i < words.size(); i = i + 2) {
if (words[i] > cc) {
cc = words[i];
break;
}
} }
} }
set_caret_column(cc); set_caret_column(cc);
@ -2364,11 +2374,11 @@ void TextEdit::_move_caret_page_down(bool p_select) {
} }
void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) { void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
if (!editable) { if (!editable || (caret.column == 0 && caret.line == 0)) {
return; return;
} }
if (has_selection() || (!p_all_to_left && !p_word)) { if (has_selection() || (!p_all_to_left && !p_word) || caret.column == 0) {
backspace(); backspace();
return; return;
} }
@ -2381,20 +2391,30 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
} }
if (p_word) { if (p_word) {
int line = caret.line;
int column = caret.column; int column = caret.column;
// Check for the case "<word><space><caret>" and ignore the space.
PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid()); // No need to check for column being 0 since it is cheked above.
for (int i = words.size() - 2; i >= 0; i = i - 2) { if (is_whitespace(text[caret.line][caret.column - 1])) {
if (words[i] < column) { column -= 1;
column = words[i]; }
break; // Get a list with the indices of the word bounds of the given text line.
const PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
if (words.is_empty() || column <= words[0]) {
// If "words" is empty, meaning no words are left, we can remove everything until the begining of the line.
column = 0;
} else {
// Otherwise search for the first word break that is smaller than the index from we're currentlu deleteing
for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i] < column) {
column = words[i];
break;
}
} }
} }
_remove_text(line, column, caret.line, caret.column); _remove_text(caret.line, column, caret.line, caret.column);
set_caret_line(line, false); set_caret_line(caret.line, false);
set_caret_column(column); set_caret_column(column);
return; return;
} }

View File

@ -758,7 +758,7 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, in
int word_start = range.x; int word_start = range.x;
int l_size = shaped_text_get_glyph_count(p_shaped); const int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) { for (int i = 0; i < l_size; i++) {