Selaa lähdekoodia

Merge pull request #50371 from Paulb23/text_edit_cleanup

Rémi Verschelde 4 vuotta sitten
vanhempi
commit
a695a6764e

+ 2 - 2
doc/classes/CodeEdit.xml

@@ -645,7 +645,7 @@
 			The tint of text outline of the [CodeEdit].
 		</theme_item>
 		<theme_item name="font_readonly_color" data_type="color" type="Color" default="Color(0.88, 0.88, 0.88, 0.5)">
-			Sets the font [Color] when [member TextEdit.readonly] is enabled.
+			Sets the font [Color] when [member TextEdit.editable] is disabled.
 		</theme_item>
 		<theme_item name="font_selected_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)">
 			Sets the [Color] of the selected text. [member TextEdit.override_selected_font_color] has to be enabled.
@@ -669,7 +669,7 @@
 			The size of the text outline.
 		</theme_item>
 		<theme_item name="read_only" data_type="style" type="StyleBox">
-			Sets the [StyleBox] when [member TextEdit.readonly] is enabled.
+			Sets the [StyleBox] when [member TextEdit.editable] is disabled.
 		</theme_item>
 		<theme_item name="selection_color" data_type="color" type="Color" default="Color(0.49, 0.49, 0.49, 1)">
 			Sets the highlight [Color] of text selections.

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 468 - 109
doc/classes/TextEdit.xml


+ 112 - 116
editor/code_editor.cpp

@@ -44,7 +44,7 @@
 void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
 	text_editor = p_edit;
 
-	line->set_text(itos(text_editor->cursor_get_line()));
+	line->set_text(itos(text_editor->get_caret_line()));
 	line->select_all();
 	popup_centered(Size2(180, 80) * EDSCALE);
 	line->grab_focus();
@@ -59,7 +59,7 @@ void GotoLineDialog::ok_pressed() {
 		return;
 	}
 	text_editor->unfold_line(get_line() - 1);
-	text_editor->cursor_set_line(get_line() - 1);
+	text_editor->set_caret_line(get_line() - 1);
 	hide();
 }
 
@@ -142,26 +142,23 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) {
 }
 
 bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) {
-	int line, col;
 	String text = get_search_text();
+	Point2i pos = text_editor->search(text, p_flags, p_from_line, p_from_col);
 
-	bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col);
-
-	if (found) {
+	if (pos.x != -1) {
 		if (!preserve_cursor && !is_selection_only()) {
-			text_editor->unfold_line(line);
-			text_editor->cursor_set_line(line, false);
-			text_editor->cursor_set_column(col + text.length(), false);
-			text_editor->center_viewport_to_cursor();
-			text_editor->select(line, col, line, col + text.length());
+			text_editor->unfold_line(pos.y);
+			text_editor->set_caret_line(pos.y, false);
+			text_editor->set_caret_column(pos.x + text.length(), false);
+			text_editor->center_viewport_to_caret();
+			text_editor->select(pos.y, pos.x, pos.y, pos.x + text.length());
 		}
 
 		text_editor->set_search_text(text);
 		text_editor->set_search_flags(p_flags);
-		text_editor->set_current_search_result(line, col);
 
-		result_line = line;
-		result_col = col;
+		result_line = pos.y;
+		result_col = pos.x;
 
 		_update_results_count();
 	} else {
@@ -170,16 +167,15 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
 		result_col = -1;
 		text_editor->set_search_text("");
 		text_editor->set_search_flags(p_flags);
-		text_editor->set_current_search_result(line, col);
 	}
 
 	_update_matches_label();
 
-	return found;
+	return pos.x != -1;
 }
 
 void FindReplaceBar::_replace() {
-	bool selection_enabled = text_editor->is_selection_active();
+	bool selection_enabled = text_editor->has_selection();
 	Point2i selection_begin, selection_end;
 	if (selection_enabled) {
 		selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column());
@@ -191,8 +187,8 @@ void FindReplaceBar::_replace() {
 
 	text_editor->begin_complex_operation();
 	if (selection_enabled && is_selection_only()) { // To restrict search_current() to selected region
-		text_editor->cursor_set_line(selection_begin.width);
-		text_editor->cursor_set_column(selection_begin.height);
+		text_editor->set_caret_line(selection_begin.width);
+		text_editor->set_caret_column(selection_begin.height);
 	}
 
 	if (search_current()) {
@@ -203,13 +199,13 @@ void FindReplaceBar::_replace() {
 			Point2i match_from(result_line, result_col);
 			Point2i match_to(result_line, result_col + search_text_len);
 			if (!(match_from < selection_begin || match_to > selection_end)) {
-				text_editor->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_caret(replace_text);
 				if (match_to.x == selection_end.x) { // Adjust selection bounds if necessary
 					selection_end.y += replace_text.length() - search_text_len;
 				}
 			}
 		} else {
-			text_editor->insert_text_at_cursor(replace_text);
+			text_editor->insert_text_at_caret(replace_text);
 		}
 	}
 	text_editor->end_complex_operation();
@@ -226,10 +222,10 @@ void FindReplaceBar::_replace() {
 void FindReplaceBar::_replace_all() {
 	text_editor->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
 	// Line as x so it gets priority in comparison, column as y.
-	Point2i orig_cursor(text_editor->cursor_get_line(), text_editor->cursor_get_column());
+	Point2i orig_cursor(text_editor->get_caret_line(), text_editor->get_caret_column());
 	Point2i prev_match = Point2(-1, -1);
 
-	bool selection_enabled = text_editor->is_selection_active();
+	bool selection_enabled = text_editor->has_selection();
 	Point2i selection_begin, selection_end;
 	if (selection_enabled) {
 		selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column());
@@ -238,8 +234,8 @@ void FindReplaceBar::_replace_all() {
 
 	int vsval = text_editor->get_v_scroll();
 
-	text_editor->cursor_set_line(0);
-	text_editor->cursor_set_column(0);
+	text_editor->set_caret_line(0);
+	text_editor->set_caret_column(0);
 
 	String replace_text = get_replace_text();
 	int search_text_len = get_search_text().length();
@@ -251,8 +247,8 @@ void FindReplaceBar::_replace_all() {
 	text_editor->begin_complex_operation();
 
 	if (selection_enabled && is_selection_only()) {
-		text_editor->cursor_set_line(selection_begin.width);
-		text_editor->cursor_set_column(selection_begin.height);
+		text_editor->set_caret_line(selection_begin.width);
+		text_editor->set_caret_column(selection_begin.height);
 	}
 	if (search_current()) {
 		do {
@@ -275,14 +271,14 @@ void FindReplaceBar::_replace_all() {
 				}
 
 				// Replace but adjust selection bounds.
-				text_editor->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_caret(replace_text);
 				if (match_to.x == selection_end.x) {
 					selection_end.y += replace_text.length() - search_text_len;
 				}
 
 			} else {
 				// Just replace.
-				text_editor->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_caret(replace_text);
 			}
 
 			rc++;
@@ -294,8 +290,8 @@ void FindReplaceBar::_replace_all() {
 	replace_all_mode = false;
 
 	// Restore editor state (selection, cursor, scroll).
-	text_editor->cursor_set_line(orig_cursor.x);
-	text_editor->cursor_set_column(orig_cursor.y);
+	text_editor->set_caret_line(orig_cursor.x);
+	text_editor->set_caret_column(orig_cursor.y);
 
 	if (selection_enabled && is_selection_only()) {
 		// Reselect.
@@ -313,10 +309,10 @@ void FindReplaceBar::_replace_all() {
 }
 
 void FindReplaceBar::_get_search_from(int &r_line, int &r_col) {
-	r_line = text_editor->cursor_get_line();
-	r_col = text_editor->cursor_get_column();
+	r_line = text_editor->get_caret_line();
+	r_col = text_editor->get_caret_column();
 
-	if (text_editor->is_selection_active() && is_selection_only()) {
+	if (text_editor->has_selection() && is_selection_only()) {
 		return;
 	}
 
@@ -409,7 +405,7 @@ bool FindReplaceBar::search_prev() {
 
 	int line, col;
 	_get_search_from(line, col);
-	if (text_editor->is_selection_active()) {
+	if (text_editor->has_selection()) {
 		col--; // Skip currently selected word.
 	}
 
@@ -487,8 +483,8 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) {
 		search_text->call_deferred(SNAME("grab_focus"));
 	}
 
-	if (text_editor->is_selection_active() && !selection_only->is_pressed()) {
-		search_text->set_text(text_editor->get_selection_text());
+	if (text_editor->has_selection() && !selection_only->is_pressed()) {
+		search_text->set_text(text_editor->get_selected_text());
 	}
 
 	if (!get_search_text().is_empty()) {
@@ -521,9 +517,9 @@ void FindReplaceBar::popup_replace() {
 		hbc_option_replace->show();
 	}
 
-	selection_only->set_pressed((text_editor->is_selection_active() && text_editor->get_selection_from_line() < text_editor->get_selection_to_line()));
+	selection_only->set_pressed((text_editor->has_selection() && text_editor->get_selection_from_line() < text_editor->get_selection_to_line()));
 
-	_show_search(is_visible() || text_editor->is_selection_active());
+	_show_search(is_visible() || text_editor->has_selection());
 }
 
 void FindReplaceBar::_search_options_changed(bool p_pressed) {
@@ -554,7 +550,7 @@ void FindReplaceBar::_search_text_submitted(const String &p_text) {
 }
 
 void FindReplaceBar::_replace_text_submitted(const String &p_text) {
-	if (selection_only->is_pressed() && text_editor->is_selection_active()) {
+	if (selection_only->is_pressed() && text_editor->has_selection()) {
 		_replace_all();
 		_hide_bar();
 	} else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
@@ -807,10 +803,10 @@ void CodeTextEditor::_reset_zoom() {
 }
 
 void CodeTextEditor::_line_col_changed() {
-	String line = text_editor->get_line(text_editor->cursor_get_line());
+	String line = text_editor->get_line(text_editor->get_caret_line());
 
 	int positional_column = 0;
-	for (int i = 0; i < text_editor->cursor_get_column(); i++) {
+	for (int i = 0; i < text_editor->get_caret_column(); i++) {
 		if (line[i] == '\t') {
 			positional_column += text_editor->get_indent_size(); //tab size
 		} else {
@@ -820,7 +816,7 @@ void CodeTextEditor::_line_col_changed() {
 
 	StringBuilder sb;
 	sb.append("(");
-	sb.append(itos(text_editor->cursor_get_line() + 1).lpad(3));
+	sb.append(itos(text_editor->get_caret_line() + 1).lpad(3));
 	sb.append(",");
 	sb.append(itos(positional_column + 1).lpad(3));
 	sb.append(")");
@@ -950,11 +946,11 @@ void CodeTextEditor::update_editor_settings() {
 	text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
 	text_editor->set_line_folding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
 	text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
-	text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap"));
-	text_editor->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
-	text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
-	text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
-	text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
+	text_editor->set_line_wrapping_mode((TextEdit::LineWrappingMode)EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap").operator int());
+	text_editor->set_scroll_past_end_of_file_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
+	text_editor->set_caret_type((TextEdit::CaretType)EditorSettings::get_singleton()->get("text_editor/cursor/type").operator int());
+	text_editor->set_caret_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
+	text_editor->set_caret_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
 	text_editor->set_auto_brace_completion_enabled(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
 
 	if (EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines")) {
@@ -1039,8 +1035,8 @@ void CodeTextEditor::convert_indent_to_spaces() {
 		indent += " ";
 	}
 
-	int cursor_line = text_editor->cursor_get_line();
-	int cursor_column = text_editor->cursor_get_column();
+	int cursor_line = text_editor->get_caret_line();
+	int cursor_column = text_editor->get_caret_column();
 
 	bool changed_indentation = false;
 	for (int i = 0; i < text_editor->get_line_count(); i++) {
@@ -1069,7 +1065,7 @@ void CodeTextEditor::convert_indent_to_spaces() {
 		}
 	}
 	if (changed_indentation) {
-		text_editor->cursor_set_column(cursor_column);
+		text_editor->set_caret_column(cursor_column);
 		text_editor->end_complex_operation();
 		text_editor->update();
 	}
@@ -1079,8 +1075,8 @@ void CodeTextEditor::convert_indent_to_tabs() {
 	int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size");
 	indent_size -= 1;
 
-	int cursor_line = text_editor->cursor_get_line();
-	int cursor_column = text_editor->cursor_get_column();
+	int cursor_line = text_editor->get_caret_line();
+	int cursor_column = text_editor->get_caret_column();
 
 	bool changed_indentation = false;
 	for (int i = 0; i < text_editor->get_line_count(); i++) {
@@ -1118,14 +1114,14 @@ void CodeTextEditor::convert_indent_to_tabs() {
 		}
 	}
 	if (changed_indentation) {
-		text_editor->cursor_set_column(cursor_column);
+		text_editor->set_caret_column(cursor_column);
 		text_editor->end_complex_operation();
 		text_editor->update();
 	}
 }
 
 void CodeTextEditor::convert_case(CaseStyle p_case) {
-	if (!text_editor->is_selection_active()) {
+	if (!text_editor->has_selection()) {
 		return;
 	}
 
@@ -1171,12 +1167,12 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
 
 void CodeTextEditor::move_lines_up() {
 	text_editor->begin_complex_operation();
-	if (text_editor->is_selection_active()) {
+	if (text_editor->has_selection()) {
 		int from_line = text_editor->get_selection_from_line();
 		int from_col = text_editor->get_selection_from_column();
 		int to_line = text_editor->get_selection_to_line();
 		int to_column = text_editor->get_selection_to_column();
-		int cursor_line = text_editor->cursor_get_line();
+		int cursor_line = text_editor->get_caret_line();
 
 		for (int i = from_line; i <= to_line; i++) {
 			int line_id = i;
@@ -1190,15 +1186,15 @@ void CodeTextEditor::move_lines_up() {
 			text_editor->unfold_line(next_id);
 
 			text_editor->swap_lines(line_id, next_id);
-			text_editor->cursor_set_line(next_id);
+			text_editor->set_caret_line(next_id);
 		}
 		int from_line_up = from_line > 0 ? from_line - 1 : from_line;
 		int to_line_up = to_line > 0 ? to_line - 1 : to_line;
 		int cursor_line_up = cursor_line > 0 ? cursor_line - 1 : cursor_line;
 		text_editor->select(from_line_up, from_col, to_line_up, to_column);
-		text_editor->cursor_set_line(cursor_line_up);
+		text_editor->set_caret_line(cursor_line_up);
 	} else {
-		int line_id = text_editor->cursor_get_line();
+		int line_id = text_editor->get_caret_line();
 		int next_id = line_id - 1;
 
 		if (line_id == 0 || next_id < 0) {
@@ -1209,7 +1205,7 @@ void CodeTextEditor::move_lines_up() {
 		text_editor->unfold_line(next_id);
 
 		text_editor->swap_lines(line_id, next_id);
-		text_editor->cursor_set_line(next_id);
+		text_editor->set_caret_line(next_id);
 	}
 	text_editor->end_complex_operation();
 	text_editor->update();
@@ -1217,12 +1213,12 @@ void CodeTextEditor::move_lines_up() {
 
 void CodeTextEditor::move_lines_down() {
 	text_editor->begin_complex_operation();
-	if (text_editor->is_selection_active()) {
+	if (text_editor->has_selection()) {
 		int from_line = text_editor->get_selection_from_line();
 		int from_col = text_editor->get_selection_from_column();
 		int to_line = text_editor->get_selection_to_line();
 		int to_column = text_editor->get_selection_to_column();
-		int cursor_line = text_editor->cursor_get_line();
+		int cursor_line = text_editor->get_caret_line();
 
 		for (int i = to_line; i >= from_line; i--) {
 			int line_id = i;
@@ -1236,15 +1232,15 @@ void CodeTextEditor::move_lines_down() {
 			text_editor->unfold_line(next_id);
 
 			text_editor->swap_lines(line_id, next_id);
-			text_editor->cursor_set_line(next_id);
+			text_editor->set_caret_line(next_id);
 		}
 		int from_line_down = from_line < text_editor->get_line_count() ? from_line + 1 : from_line;
 		int to_line_down = to_line < text_editor->get_line_count() ? to_line + 1 : to_line;
 		int cursor_line_down = cursor_line < text_editor->get_line_count() ? cursor_line + 1 : cursor_line;
 		text_editor->select(from_line_down, from_col, to_line_down, to_column);
-		text_editor->cursor_set_line(cursor_line_down);
+		text_editor->set_caret_line(cursor_line_down);
 	} else {
-		int line_id = text_editor->cursor_get_line();
+		int line_id = text_editor->get_caret_line();
 		int next_id = line_id + 1;
 
 		if (line_id == text_editor->get_line_count() - 1 || next_id > text_editor->get_line_count()) {
@@ -1255,7 +1251,7 @@ void CodeTextEditor::move_lines_down() {
 		text_editor->unfold_line(next_id);
 
 		text_editor->swap_lines(line_id, next_id);
-		text_editor->cursor_set_line(next_id);
+		text_editor->set_caret_line(next_id);
 	}
 	text_editor->end_complex_operation();
 	text_editor->update();
@@ -1266,57 +1262,57 @@ void CodeTextEditor::_delete_line(int p_line) {
 	// so `begin_complex_operation` is omitted here
 	text_editor->set_line(p_line, "");
 	if (p_line == 0 && text_editor->get_line_count() > 1) {
-		text_editor->cursor_set_line(1);
-		text_editor->cursor_set_column(0);
+		text_editor->set_caret_line(1);
+		text_editor->set_caret_column(0);
 	}
 	text_editor->backspace();
 	text_editor->unfold_line(p_line);
-	text_editor->cursor_set_line(p_line);
+	text_editor->set_caret_line(p_line);
 }
 
 void CodeTextEditor::delete_lines() {
 	text_editor->begin_complex_operation();
-	if (text_editor->is_selection_active()) {
+	if (text_editor->has_selection()) {
 		int to_line = text_editor->get_selection_to_line();
 		int from_line = text_editor->get_selection_from_line();
 		int count = Math::abs(to_line - from_line) + 1;
 
-		text_editor->cursor_set_line(from_line, false);
+		text_editor->set_caret_line(from_line, false);
 		for (int i = 0; i < count; i++) {
 			_delete_line(from_line);
 		}
 		text_editor->deselect();
 	} else {
-		_delete_line(text_editor->cursor_get_line());
+		_delete_line(text_editor->get_caret_line());
 	}
 	text_editor->end_complex_operation();
 }
 
 void CodeTextEditor::duplicate_selection() {
-	const int cursor_column = text_editor->cursor_get_column();
-	int from_line = text_editor->cursor_get_line();
-	int to_line = text_editor->cursor_get_line();
+	const int cursor_column = text_editor->get_caret_column();
+	int from_line = text_editor->get_caret_line();
+	int to_line = text_editor->get_caret_line();
 	int from_column = 0;
 	int to_column = 0;
 	int cursor_new_line = to_line + 1;
-	int cursor_new_column = text_editor->cursor_get_column();
+	int cursor_new_column = text_editor->get_caret_column();
 	String new_text = "\n" + text_editor->get_line(from_line);
 	bool selection_active = false;
 
-	text_editor->cursor_set_column(text_editor->get_line(from_line).length());
-	if (text_editor->is_selection_active()) {
+	text_editor->set_caret_column(text_editor->get_line(from_line).length());
+	if (text_editor->has_selection()) {
 		from_column = text_editor->get_selection_from_column();
 		to_column = text_editor->get_selection_to_column();
 
 		from_line = text_editor->get_selection_from_line();
 		to_line = text_editor->get_selection_to_line();
-		cursor_new_line = to_line + text_editor->cursor_get_line() - from_line;
+		cursor_new_line = to_line + text_editor->get_caret_line() - from_line;
 		cursor_new_column = to_column == cursor_column ? 2 * to_column - from_column : to_column;
-		new_text = text_editor->get_selection_text();
+		new_text = text_editor->get_selected_text();
 		selection_active = true;
 
-		text_editor->cursor_set_line(to_line);
-		text_editor->cursor_set_column(to_column);
+		text_editor->set_caret_line(to_line);
+		text_editor->set_caret_column(to_column);
 	}
 
 	text_editor->begin_complex_operation();
@@ -1325,9 +1321,9 @@ void CodeTextEditor::duplicate_selection() {
 		text_editor->unfold_line(i);
 	}
 	text_editor->deselect();
-	text_editor->insert_text_at_cursor(new_text);
-	text_editor->cursor_set_line(cursor_new_line);
-	text_editor->cursor_set_column(cursor_new_column);
+	text_editor->insert_text_at_caret(new_text);
+	text_editor->set_caret_line(cursor_new_line);
+	text_editor->set_caret_column(cursor_new_column);
 	if (selection_active) {
 		text_editor->select(to_line, to_column, 2 * to_line - from_line, to_line == from_line ? 2 * to_column - from_column : to_column);
 	}
@@ -1338,7 +1334,7 @@ void CodeTextEditor::duplicate_selection() {
 
 void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
 	text_editor->begin_complex_operation();
-	if (text_editor->is_selection_active()) {
+	if (text_editor->has_selection()) {
 		int begin = text_editor->get_selection_from_line();
 		int end = text_editor->get_selection_to_line();
 
@@ -1348,7 +1344,7 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
 		}
 
 		int col_to = text_editor->get_selection_to_column();
-		int cursor_pos = text_editor->cursor_get_column();
+		int cursor_pos = text_editor->get_caret_column();
 
 		// Check if all lines in the selected block are commented.
 		bool is_commented = true;
@@ -1377,7 +1373,7 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
 		int offset = (is_commented ? -1 : 1) * delimiter.length();
 		int col_from = text_editor->get_selection_from_column() > 0 ? text_editor->get_selection_from_column() + offset : 0;
 
-		if (is_commented && text_editor->cursor_get_column() == text_editor->get_line(text_editor->cursor_get_line()).length() + 1) {
+		if (is_commented && text_editor->get_caret_column() == text_editor->get_line(text_editor->get_caret_line()).length() + 1) {
 			cursor_pos += 1;
 		}
 
@@ -1385,19 +1381,19 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
 			col_to += offset;
 		}
 
-		if (text_editor->cursor_get_column() != 0) {
+		if (text_editor->get_caret_column() != 0) {
 			cursor_pos += offset;
 		}
 
 		text_editor->select(begin, col_from, text_editor->get_selection_to_line(), col_to);
-		text_editor->cursor_set_column(cursor_pos);
+		text_editor->set_caret_column(cursor_pos);
 
 	} else {
-		int begin = text_editor->cursor_get_line();
+		int begin = text_editor->get_caret_line();
 		String line_text = text_editor->get_line(begin);
 		int delimiter_length = delimiter.length();
 
-		int col = text_editor->cursor_get_column();
+		int col = text_editor->get_caret_column();
 		if (line_text.begins_with(delimiter)) {
 			line_text = line_text.substr(delimiter_length, line_text.length());
 			col -= delimiter_length;
@@ -1407,7 +1403,7 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
 		}
 
 		text_editor->set_line(begin, line_text);
-		text_editor->cursor_set_column(col);
+		text_editor->set_caret_column(col);
 	}
 	text_editor->end_complex_operation();
 	text_editor->update();
@@ -1428,7 +1424,7 @@ void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
 
 void CodeTextEditor::goto_line_centered(int p_line) {
 	goto_line(p_line);
-	text_editor->call_deferred(SNAME("center_viewport_to_cursor"));
+	text_editor->call_deferred(SNAME("center_viewport_to_caret"));
 }
 
 void CodeTextEditor::set_executing_line(int p_line) {
@@ -1444,11 +1440,11 @@ Variant CodeTextEditor::get_edit_state() {
 
 	state["scroll_position"] = text_editor->get_v_scroll();
 	state["h_scroll_position"] = text_editor->get_h_scroll();
-	state["column"] = text_editor->cursor_get_column();
-	state["row"] = text_editor->cursor_get_line();
+	state["column"] = text_editor->get_caret_column();
+	state["row"] = text_editor->get_caret_line();
 
-	state["selection"] = get_text_editor()->is_selection_active();
-	if (get_text_editor()->is_selection_active()) {
+	state["selection"] = get_text_editor()->has_selection();
+	if (get_text_editor()->has_selection()) {
 		state["selection_from_line"] = text_editor->get_selection_from_line();
 		state["selection_from_column"] = text_editor->get_selection_from_column();
 		state["selection_to_line"] = text_editor->get_selection_to_line();
@@ -1469,8 +1465,8 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
 	Dictionary state = p_state;
 
 	/* update the row first as it sets the column to 0 */
-	text_editor->cursor_set_line(state["row"]);
-	text_editor->cursor_set_column(state["column"]);
+	text_editor->set_caret_line(state["row"]);
+	text_editor->set_caret_column(state["column"]);
 	text_editor->set_v_scroll(state["scroll_position"]);
 	text_editor->set_h_scroll(state["h_scroll_position"]);
 
@@ -1517,9 +1513,9 @@ void CodeTextEditor::set_error_pos(int p_line, int p_column) {
 void CodeTextEditor::goto_error() {
 	if (error->get_text() != "") {
 		text_editor->unfold_line(error_line);
-		text_editor->cursor_set_line(error_line);
-		text_editor->cursor_set_column(error_column);
-		text_editor->center_viewport_to_cursor();
+		text_editor->set_caret_line(error_line);
+		text_editor->set_caret_column(error_column);
+		text_editor->center_viewport_to_caret();
 	}
 }
 
@@ -1712,7 +1708,7 @@ void CodeTextEditor::set_warning_count(int p_warning_count) {
 }
 
 void CodeTextEditor::toggle_bookmark() {
-	int line = text_editor->cursor_get_line();
+	int line = text_editor->get_caret_line();
 	text_editor->set_line_as_bookmarked(line, !text_editor->is_line_bookmarked(line));
 }
 
@@ -1722,18 +1718,18 @@ void CodeTextEditor::goto_next_bookmark() {
 		return;
 	}
 
-	int line = text_editor->cursor_get_line();
+	int line = text_editor->get_caret_line();
 	if (line >= (int)bmarks[bmarks.size() - 1]) {
 		text_editor->unfold_line(bmarks[0]);
-		text_editor->cursor_set_line(bmarks[0]);
-		text_editor->center_viewport_to_cursor();
+		text_editor->set_caret_line(bmarks[0]);
+		text_editor->center_viewport_to_caret();
 	} else {
 		for (int i = 0; i < bmarks.size(); i++) {
 			int bmark_line = bmarks[i];
 			if (bmark_line > line) {
 				text_editor->unfold_line(bmark_line);
-				text_editor->cursor_set_line(bmark_line);
-				text_editor->center_viewport_to_cursor();
+				text_editor->set_caret_line(bmark_line);
+				text_editor->center_viewport_to_caret();
 				return;
 			}
 		}
@@ -1746,18 +1742,18 @@ void CodeTextEditor::goto_prev_bookmark() {
 		return;
 	}
 
-	int line = text_editor->cursor_get_line();
+	int line = text_editor->get_caret_line();
 	if (line <= (int)bmarks[0]) {
 		text_editor->unfold_line(bmarks[bmarks.size() - 1]);
-		text_editor->cursor_set_line(bmarks[bmarks.size() - 1]);
-		text_editor->center_viewport_to_cursor();
+		text_editor->set_caret_line(bmarks[bmarks.size() - 1]);
+		text_editor->center_viewport_to_caret();
 	} else {
 		for (int i = bmarks.size(); i >= 0; i--) {
 			int bmark_line = bmarks[i];
 			if (bmark_line < line) {
 				text_editor->unfold_line(bmark_line);
-				text_editor->cursor_set_line(bmark_line);
-				text_editor->center_viewport_to_cursor();
+				text_editor->set_caret_line(bmark_line);
+				text_editor->center_viewport_to_caret();
 				return;
 			}
 		}
@@ -1913,7 +1909,7 @@ CodeTextEditor::CodeTextEditor() {
 	line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP);
 
 	text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input));
-	text_editor->connect("cursor_changed", callable_mp(this, &CodeTextEditor::_line_col_changed));
+	text_editor->connect("caret_changed", callable_mp(this, &CodeTextEditor::_line_col_changed));
 	text_editor->connect("text_changed", callable_mp(this, &CodeTextEditor::_text_changed));
 	text_editor->connect("request_code_completion", callable_mp(this, &CodeTextEditor::_complete_request));
 	TypedArray<String> cs;

+ 1 - 1
editor/editor_native_shader_source_visualizer.cpp

@@ -51,7 +51,7 @@ void EditorNativeShaderSourceVisualizer::_inspect_shader(RID p_shader) {
 		versions->add_child(vtab);
 		for (int j = 0; j < nsc.versions[i].stages.size(); j++) {
 			TextEdit *vtext = memnew(TextEdit);
-			vtext->set_readonly(true);
+			vtext->set_editable(false);
 			vtext->set_name(nsc.versions[i].stages[j].name);
 			vtext->set_text(nsc.versions[i].stages[j].code);
 			vtext->set_v_size_flags(Control::SIZE_EXPAND_FILL);

+ 2 - 2
editor/editor_properties.cpp

@@ -121,7 +121,7 @@ void EditorPropertyMultilineText::_open_big_text() {
 	if (!big_text_dialog) {
 		big_text = memnew(TextEdit);
 		big_text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_big_text_changed));
-		big_text->set_wrap_enabled(true);
+		big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
 		big_text_dialog = memnew(AcceptDialog);
 		big_text_dialog->add_child(big_text);
 		big_text_dialog->set_title(TTR("Edit Text:"));
@@ -166,7 +166,7 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() {
 	set_bottom_editor(hb);
 	text = memnew(TextEdit);
 	text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_text_changed));
-	text->set_wrap_enabled(true);
+	text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
 	add_focusable(text);
 	hb->add_child(text);
 	text->set_h_size_flags(SIZE_EXPAND_FILL);

+ 5 - 2
editor/editor_settings.cpp

@@ -525,7 +525,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	_initial_set("text_editor/appearance/show_bookmark_gutter", true);
 	_initial_set("text_editor/appearance/show_info_gutter", true);
 	_initial_set("text_editor/appearance/code_folding", true);
-	_initial_set("text_editor/appearance/word_wrap", false);
+	_initial_set("text_editor/appearance/word_wrap", 0);
+	hints["text_editor/appearance/word_wrap"] = PropertyInfo(Variant::INT, "text_editor/appearance/word_wrap", PROPERTY_HINT_ENUM, "None,Boundary");
+
 	_initial_set("text_editor/appearance/show_line_length_guidelines", true);
 	_initial_set("text_editor/appearance/line_length_guideline_soft_column", 80);
 	hints["text_editor/appearance/line_length_guideline_soft_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/line_length_guideline_soft_column", PROPERTY_HINT_RANGE, "20, 160, 1");
@@ -546,7 +548,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 
 	// Cursor
 	_initial_set("text_editor/cursor/scroll_past_end_of_file", false);
-	_initial_set("text_editor/cursor/block_caret", false);
+	_initial_set("text_editor/cursor/type", 0);
+	hints["text_editor/cursor/type"] = PropertyInfo(Variant::INT, "text_editor/cursor/type", PROPERTY_HINT_ENUM, "Line,Block");
 	_initial_set("text_editor/cursor/caret_blink", true);
 	_initial_set("text_editor/cursor/caret_blink_speed", 0.5);
 	hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::FLOAT, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01");

+ 2 - 0
editor/editor_themes.cpp

@@ -1048,6 +1048,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_color("font_readonly_color", "LineEdit", font_readonly_color);
 	theme->set_color("caret_color", "TextEdit", font_color);
 	theme->set_color("selection_color", "TextEdit", selection_color);
+	theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE);
 
 	// CodeEdit
 	theme->set_stylebox("normal", "CodeEdit", style_widget);
@@ -1062,6 +1063,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_color("font_color", "CodeEdit", font_color);
 	theme->set_color("caret_color", "CodeEdit", font_color);
 	theme->set_color("selection_color", "CodeEdit", selection_color);
+	theme->set_constant("line_spacing", "CodeEdit", 4 * EDSCALE);
 
 	// H/VSplitContainer
 	theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1));

+ 1 - 1
editor/plugin_config_dialog.cpp

@@ -282,7 +282,7 @@ PluginConfigDialog::PluginConfigDialog() {
 
 	desc_edit = memnew(TextEdit);
 	desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
-	desc_edit->set_wrap_enabled(true);
+	desc_edit->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
 	grid->add_child(desc_edit);
 
 	// Author

+ 65 - 61
editor/plugins/script_text_editor.cpp

@@ -241,14 +241,14 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) {
 		goto_line_centered(p_line.operator int64_t());
 	} else if (p_line.get_type() == Variant::DICTIONARY) {
 		Dictionary meta = p_line.operator Dictionary();
-		code_editor->get_text_editor()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1);
+		code_editor->get_text_editor()->insert_line_at(meta["line"].operator int64_t() - 1, "# warning-ignore:" + meta["code"].operator String());
 		_validate_script();
 	}
 }
 
 void ScriptTextEditor::_error_clicked(Variant p_line) {
 	if (p_line.get_type() == Variant::INT) {
-		code_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t());
+		code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
 	}
 }
 
@@ -256,14 +256,14 @@ void ScriptTextEditor::reload_text() {
 	ERR_FAIL_COND(script.is_null());
 
 	CodeEdit *te = code_editor->get_text_editor();
-	int column = te->cursor_get_column();
-	int row = te->cursor_get_line();
+	int column = te->get_caret_column();
+	int row = te->get_caret_line();
 	int h = te->get_h_scroll();
 	int v = te->get_v_scroll();
 
 	te->set_text(script->get_source_code());
-	te->cursor_set_line(row);
-	te->cursor_set_column(column);
+	te->set_caret_line(row);
+	te->set_caret_column(column);
 	te->set_h_scroll(h);
 	te->set_v_scroll(v);
 
@@ -281,12 +281,12 @@ void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray
 		pos = code_editor->get_text_editor()->get_line_count() + 2;
 		String func = script->get_language()->make_function("", p_function, p_args);
 		//code=code+func;
-		code_editor->get_text_editor()->cursor_set_line(pos + 1);
-		code_editor->get_text_editor()->cursor_set_column(1000000); //none shall be that big
-		code_editor->get_text_editor()->insert_text_at_cursor("\n\n" + func);
+		code_editor->get_text_editor()->set_caret_line(pos + 1);
+		code_editor->get_text_editor()->set_caret_column(1000000); //none shall be that big
+		code_editor->get_text_editor()->insert_text_at_caret("\n\n" + func);
 	}
-	code_editor->get_text_editor()->cursor_set_line(pos);
-	code_editor->get_text_editor()->cursor_set_column(1);
+	code_editor->get_text_editor()->set_caret_line(pos);
+	code_editor->get_text_editor()->set_caret_column(1);
 }
 
 bool ScriptTextEditor::show_members_overview() {
@@ -726,7 +726,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) {
 		_edit_option(breakpoints_menu->get_item_id(p_idx));
 	} else {
 		code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx));
-		code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_cursor")); //Need to be deferred, because goto uses call_deferred().
+		code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_caret")); //Need to be deferred, because goto uses call_deferred().
 	}
 }
 
@@ -884,7 +884,7 @@ void ScriptTextEditor::update_toggle_scripts_button() {
 
 void ScriptTextEditor::_update_connected_methods() {
 	CodeEdit *text_edit = code_editor->get_text_editor();
-	text_edit->set_gutter_width(connection_gutter, text_edit->get_row_height());
+	text_edit->set_gutter_width(connection_gutter, text_edit->get_line_height());
 	for (int i = 0; i < text_edit->get_line_count(); i++) {
 		if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") {
 			continue;
@@ -1054,7 +1054,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			code_editor->duplicate_selection();
 		} break;
 		case EDIT_TOGGLE_FOLD_LINE: {
-			tx->toggle_foldable_line(tx->cursor_get_line());
+			tx->toggle_foldable_line(tx->get_caret_line());
 			tx->update();
 		} break;
 		case EDIT_FOLD_ALL_LINES: {
@@ -1062,7 +1062,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			tx->update();
 		} break;
 		case EDIT_UNFOLD_ALL_LINES: {
-			tx->unhide_all_lines();
+			tx->unfold_all_lines();
 			tx->update();
 		} break;
 		case EDIT_TOGGLE_COMMENT: {
@@ -1080,7 +1080,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 
 			tx->begin_complex_operation();
 			int begin, end;
-			if (tx->is_selection_active()) {
+			if (tx->has_selection()) {
 				begin = tx->get_selection_from_line();
 				end = tx->get_selection_to_line();
 				// ignore if the cursor is not past the first column
@@ -1122,7 +1122,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 		} break;
 		case EDIT_EVALUATE: {
 			Expression expression;
-			Vector<String> lines = code_editor->get_text_editor()->get_selection_text().split("\n");
+			Vector<String> lines = code_editor->get_text_editor()->get_selected_text().split("\n");
 			PackedStringArray results;
 
 			for (int i = 0; i < lines.size(); i++) {
@@ -1142,7 +1142,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			}
 
 			code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo
-			code_editor->get_text_editor()->insert_text_at_cursor(String("\n").join(results));
+			code_editor->get_text_editor()->insert_text_at_caret(String("\n").join(results));
 			code_editor->get_text_editor()->end_complex_operation();
 		} break;
 		case SEARCH_FIND: {
@@ -1158,14 +1158,14 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			code_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		case SEARCH_IN_FILES: {
-			String selected_text = code_editor->get_text_editor()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selected_text();
 
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// So this will be delegated to the ScriptEditor.
 			emit_signal(SNAME("search_in_files_requested"), selected_text);
 		} break;
 		case REPLACE_IN_FILES: {
-			String selected_text = code_editor->get_text_editor()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selected_text();
 
 			emit_signal(SNAME("replace_in_files_requested"), selected_text);
 		} break;
@@ -1189,7 +1189,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			code_editor->remove_all_bookmarks();
 		} break;
 		case DEBUG_TOGGLE_BREAKPOINT: {
-			int line = tx->cursor_get_line();
+			int line = tx->get_caret_line();
 			bool dobreak = !tx->is_line_breakpointed(line);
 			tx->set_line_as_breakpoint(line, dobreak);
 			EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
@@ -1210,20 +1210,20 @@ void ScriptTextEditor::_edit_option(int p_op) {
 				return;
 			}
 
-			int line = tx->cursor_get_line();
+			int line = tx->get_caret_line();
 
 			// wrap around
 			if (line >= (int)bpoints[bpoints.size() - 1]) {
 				tx->unfold_line(bpoints[0]);
-				tx->cursor_set_line(bpoints[0]);
-				tx->center_viewport_to_cursor();
+				tx->set_caret_line(bpoints[0]);
+				tx->center_viewport_to_caret();
 			} else {
 				for (int i = 0; i < bpoints.size(); i++) {
 					int bline = bpoints[i];
 					if (bline > line) {
 						tx->unfold_line(bline);
-						tx->cursor_set_line(bline);
-						tx->center_viewport_to_cursor();
+						tx->set_caret_line(bline);
+						tx->center_viewport_to_caret();
 						return;
 					}
 				}
@@ -1236,19 +1236,19 @@ void ScriptTextEditor::_edit_option(int p_op) {
 				return;
 			}
 
-			int line = tx->cursor_get_line();
+			int line = tx->get_caret_line();
 			// wrap around
 			if (line <= (int)bpoints[0]) {
 				tx->unfold_line(bpoints[bpoints.size() - 1]);
-				tx->cursor_set_line(bpoints[bpoints.size() - 1]);
-				tx->center_viewport_to_cursor();
+				tx->set_caret_line(bpoints[bpoints.size() - 1]);
+				tx->center_viewport_to_caret();
 			} else {
 				for (int i = bpoints.size(); i >= 0; i--) {
 					int bline = bpoints[i];
 					if (bline < line) {
 						tx->unfold_line(bline);
-						tx->cursor_set_line(bline);
-						tx->center_viewport_to_cursor();
+						tx->set_caret_line(bline);
+						tx->center_viewport_to_caret();
 						return;
 					}
 				}
@@ -1256,21 +1256,21 @@ void ScriptTextEditor::_edit_option(int p_op) {
 
 		} break;
 		case HELP_CONTEXTUAL: {
-			String text = tx->get_selection_text();
+			String text = tx->get_selected_text();
 			if (text == "") {
-				text = tx->get_word_under_cursor();
+				text = tx->get_word_under_caret();
 			}
 			if (text != "") {
 				emit_signal(SNAME("request_help"), text);
 			}
 		} break;
 		case LOOKUP_SYMBOL: {
-			String text = tx->get_word_under_cursor();
+			String text = tx->get_word_under_caret();
 			if (text == "") {
-				text = tx->get_selection_text();
+				text = tx->get_selected_text();
 			}
 			if (text != "") {
-				_lookup_symbol(text, tx->cursor_get_line(), tx->cursor_get_column());
+				_lookup_symbol(text, tx->get_caret_line(), tx->get_caret_column());
 			}
 		} break;
 	}
@@ -1325,7 +1325,7 @@ void ScriptTextEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED:
 		case NOTIFICATION_ENTER_TREE: {
-			code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_row_height());
+			code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_line_height());
 		} break;
 		default:
 			break;
@@ -1422,8 +1422,10 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
 	Dictionary d = p_data;
 
 	CodeEdit *te = code_editor->get_text_editor();
-	int row, col;
-	te->_get_mouse_pos(p_point, row, col);
+
+	Point2i pos = te->get_line_column_at_pos(p_point);
+	int row = pos.y;
+	int col = pos.x;
 
 	if (d.has("type") && String(d["type"]) == "resource") {
 		Ref<Resource> res = d["resource"];
@@ -1436,9 +1438,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
 			return;
 		}
 
-		te->cursor_set_line(row);
-		te->cursor_set_column(col);
-		te->insert_text_at_cursor(res->get_path());
+		te->set_caret_line(row);
+		te->set_caret_column(col);
+		te->insert_text_at_caret(res->get_path());
 	}
 
 	if (d.has("type") && (String(d["type"]) == "files" || String(d["type"]) == "files_and_dirs")) {
@@ -1459,9 +1461,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
 			}
 		}
 
-		te->cursor_set_line(row);
-		te->cursor_set_column(col);
-		te->insert_text_at_cursor(text_to_drop);
+		te->set_caret_line(row);
+		te->set_caret_column(col);
+		te->insert_text_at_caret(text_to_drop);
 	}
 
 	if (d.has("type") && String(d["type"]) == "nodes") {
@@ -1489,9 +1491,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
 			text_to_drop += "\"" + path.c_escape() + "\"";
 		}
 
-		te->cursor_set_line(row);
-		te->cursor_set_column(col);
-		te->insert_text_at_cursor(text_to_drop);
+		te->set_caret_line(row);
+		te->set_caret_column(col);
+		te->insert_text_at_caret(text_to_drop);
 	}
 }
 
@@ -1505,18 +1507,20 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
 		local_pos = mb->get_global_position() - tx->get_global_position();
 		create_menu = true;
-	} else if (k.is_valid() && k->get_keycode() == KEY_MENU) {
-		local_pos = tx->_get_cursor_pixel_pos();
+	} else if (k.is_valid() && k->is_action("ui_menu", true)) {
+		tx->adjust_viewport_to_caret();
+		local_pos = tx->get_caret_draw_pos();
 		create_menu = true;
 	}
 
 	if (create_menu) {
-		int col, row;
-		tx->_get_mouse_pos(local_pos, row, col);
+		Point2i pos = tx->get_line_column_at_pos(local_pos);
+		int row = pos.y;
+		int col = pos.x;
 
-		tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
-		if (tx->is_right_click_moving_caret()) {
-			if (tx->is_selection_active()) {
+		tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+		if (tx->is_move_caret_on_right_click_enabled()) {
+			if (tx->has_selection()) {
 				int from_line = tx->get_selection_from_line();
 				int to_line = tx->get_selection_to_line();
 				int from_column = tx->get_selection_from_column();
@@ -1527,18 +1531,18 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 					tx->deselect();
 				}
 			}
-			if (!tx->is_selection_active()) {
-				tx->cursor_set_line(row, true, false);
-				tx->cursor_set_column(col);
+			if (!tx->has_selection()) {
+				tx->set_caret_line(row, false, false);
+				tx->set_caret_column(col);
 			}
 		}
 
 		String word_at_pos = tx->get_word_at_pos(local_pos);
 		if (word_at_pos == "") {
-			word_at_pos = tx->get_word_under_cursor();
+			word_at_pos = tx->get_word_under_caret();
 		}
 		if (word_at_pos == "") {
-			word_at_pos = tx->get_selection_text();
+			word_at_pos = tx->get_selected_text();
 		}
 
 		bool has_color = (word_at_pos == "Color");
@@ -1590,7 +1594,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 				has_color = false;
 			}
 		}
-		_make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition, local_pos);
+		_make_context_menu(tx->has_selection(), has_color, foldable, open_docs, goto_definition, local_pos);
 	}
 }
 

+ 19 - 16
editor/plugins/shader_editor_plugin.cpp

@@ -74,14 +74,14 @@ void ShaderTextEditor::reload_text() {
 	ERR_FAIL_COND(shader.is_null());
 
 	CodeEdit *te = get_text_editor();
-	int column = te->cursor_get_column();
-	int row = te->cursor_get_line();
+	int column = te->get_caret_column();
+	int row = te->get_caret_line();
 	int h = te->get_h_scroll();
 	int v = te->get_v_scroll();
 
 	te->set_text(shader->get_code());
-	te->cursor_set_line(row);
-	te->cursor_set_column(column);
+	te->set_caret_line(row);
+	te->set_caret_column(column);
 	te->set_h_scroll(h);
 	te->set_v_scroll(v);
 
@@ -408,7 +408,7 @@ void ShaderEditor::_show_warnings_panel(bool p_show) {
 
 void ShaderEditor::_warning_clicked(Variant p_line) {
 	if (p_line.get_type() == Variant::INT) {
-		shader_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t());
+		shader_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
 	}
 }
 
@@ -550,13 +550,15 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 	if (mb.is_valid()) {
 		if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) {
-			int col, row;
 			CodeEdit *tx = shader_editor->get_text_editor();
-			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
-			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
 
-			if (tx->is_right_click_moving_caret()) {
-				if (tx->is_selection_active()) {
+			Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position());
+			int row = pos.y;
+			int col = pos.x;
+			tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+
+			if (tx->is_move_caret_on_right_click_enabled()) {
+				if (tx->has_selection()) {
 					int from_line = tx->get_selection_from_line();
 					int to_line = tx->get_selection_to_line();
 					int from_column = tx->get_selection_from_column();
@@ -567,19 +569,20 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 						tx->deselect();
 					}
 				}
-				if (!tx->is_selection_active()) {
-					tx->cursor_set_line(row, true, false);
-					tx->cursor_set_column(col);
+				if (!tx->has_selection()) {
+					tx->set_caret_line(row, true, false);
+					tx->set_caret_column(col);
 				}
 			}
-			_make_context_menu(tx->is_selection_active(), get_local_mouse_position());
+			_make_context_menu(tx->has_selection(), get_local_mouse_position());
 		}
 	}
 
 	Ref<InputEventKey> k = ev;
-	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
+	if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) {
 		CodeEdit *tx = shader_editor->get_text_editor();
-		_make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
+		tx->adjust_viewport_to_caret();
+		_make_context_menu(tx->has_selection(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos()));
 		context_menu->grab_focus();
 	}
 }

+ 23 - 20
editor/plugins/text_editor.cpp

@@ -132,14 +132,14 @@ void TextEditor::reload_text() {
 	ERR_FAIL_COND(text_file.is_null());
 
 	CodeEdit *te = code_editor->get_text_editor();
-	int column = te->cursor_get_column();
-	int row = te->cursor_get_line();
+	int column = te->get_caret_column();
+	int row = te->get_caret_line();
 	int h = te->get_h_scroll();
 	int v = te->get_v_scroll();
 
 	te->set_text(text_file->get_text());
-	te->cursor_set_line(row);
-	te->cursor_set_column(column);
+	te->set_caret_line(row);
+	te->set_caret_column(column);
 	te->set_h_scroll(h);
 	te->set_v_scroll(v);
 
@@ -332,7 +332,7 @@ void TextEditor::_edit_option(int p_op) {
 			code_editor->duplicate_selection();
 		} break;
 		case EDIT_TOGGLE_FOLD_LINE: {
-			tx->toggle_foldable_line(tx->cursor_get_line());
+			tx->toggle_foldable_line(tx->get_caret_line());
 			tx->update();
 		} break;
 		case EDIT_FOLD_ALL_LINES: {
@@ -340,7 +340,7 @@ void TextEditor::_edit_option(int p_op) {
 			tx->update();
 		} break;
 		case EDIT_UNFOLD_ALL_LINES: {
-			tx->unhide_all_lines();
+			tx->unfold_all_lines();
 			tx->update();
 		} break;
 		case EDIT_TRIM_TRAILING_WHITESAPCE: {
@@ -374,14 +374,14 @@ void TextEditor::_edit_option(int p_op) {
 			code_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		case SEARCH_IN_FILES: {
-			String selected_text = code_editor->get_text_editor()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selected_text();
 
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// So this will be delegated to the ScriptEditor.
 			emit_signal(SNAME("search_in_files_requested"), selected_text);
 		} break;
 		case REPLACE_IN_FILES: {
-			String selected_text = code_editor->get_text_editor()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selected_text();
 
 			emit_signal(SNAME("replace_in_files_requested"), selected_text);
 		} break;
@@ -427,16 +427,18 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 	if (mb.is_valid()) {
 		if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
-			int col, row;
 			CodeEdit *tx = code_editor->get_text_editor();
-			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
 
-			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+			Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position());
+			int row = pos.y;
+			int col = pos.x;
+
+			tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
 			bool can_fold = tx->can_fold_line(row);
 			bool is_folded = tx->is_line_folded(row);
 
-			if (tx->is_right_click_moving_caret()) {
-				if (tx->is_selection_active()) {
+			if (tx->is_move_caret_on_right_click_enabled()) {
+				if (tx->has_selection()) {
 					int from_line = tx->get_selection_from_line();
 					int to_line = tx->get_selection_to_line();
 					int from_column = tx->get_selection_from_column();
@@ -447,23 +449,24 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 						tx->deselect();
 					}
 				}
-				if (!tx->is_selection_active()) {
-					tx->cursor_set_line(row, true, false);
-					tx->cursor_set_column(col);
+				if (!tx->has_selection()) {
+					tx->set_caret_line(row, true, false);
+					tx->set_caret_column(col);
 				}
 			}
 
 			if (!mb->is_pressed()) {
-				_make_context_menu(tx->is_selection_active(), can_fold, is_folded, get_local_mouse_position());
+				_make_context_menu(tx->has_selection(), can_fold, is_folded, get_local_mouse_position());
 			}
 		}
 	}
 
 	Ref<InputEventKey> k = ev;
-	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
+	if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) {
 		CodeEdit *tx = code_editor->get_text_editor();
-		int line = tx->cursor_get_line();
-		_make_context_menu(tx->is_selection_active(), tx->can_fold_line(line), tx->is_line_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
+		int line = tx->get_caret_line();
+		tx->adjust_viewport_to_caret();
+		_make_context_menu(tx->has_selection(), tx->can_fold_line(line), tx->is_line_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos()));
 		context_menu->grab_focus();
 	}
 }

+ 1 - 1
editor/plugins/version_control_editor_plugin.cpp

@@ -484,7 +484,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
 	commit_message->set_h_grow_direction(Control::GrowDirection::GROW_DIRECTION_BEGIN);
 	commit_message->set_v_grow_direction(Control::GrowDirection::GROW_DIRECTION_END);
 	commit_message->set_custom_minimum_size(Size2(200, 100));
-	commit_message->set_wrap_enabled(true);
+	commit_message->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
 	commit_message->connect("text_changed", callable_mp(this, &VersionControlEditorPlugin::_update_commit_button));
 	commit_message->connect("gui_input", callable_mp(this, &VersionControlEditorPlugin::_commit_message_gui_input));
 	commit_box_vbc->add_child(commit_message);

+ 1 - 1
editor/plugins/visual_shader_editor_plugin.cpp

@@ -3968,7 +3968,7 @@ VisualShaderEditor::VisualShaderEditor() {
 	preview_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	preview_text->set_syntax_highlighter(syntax_highlighter);
 	preview_text->set_draw_line_numbers(true);
-	preview_text->set_readonly(true);
+	preview_text->set_editable(false);
 
 	error_panel = memnew(PanelContainer);
 	preview_vbox->add_child(error_panel);

+ 225 - 210
scene/gui/code_edit.cpp

@@ -46,9 +46,16 @@ void CodeEdit::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED:
 		case NOTIFICATION_ENTER_TREE: {
-			set_gutter_width(main_gutter, get_row_height());
-			set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0', 0, cache.font_size).width);
-			set_gutter_width(fold_gutter, get_row_height() / 1.2);
+			style_normal = get_theme_stylebox(SNAME("normal"));
+
+			font = get_theme_font(SNAME("font"));
+			font_size = get_theme_font_size(SNAME("font_size"));
+
+			line_spacing = get_theme_constant(SNAME("line_spacing"));
+
+			set_gutter_width(main_gutter, get_line_height());
+			set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
+			set_gutter_width(fold_gutter, get_line_height() / 1.2);
 
 			breakpoint_color = get_theme_color(SNAME("breakpoint_color"));
 			breakpoint_icon = get_theme_icon(SNAME("breakpoint"));
@@ -65,7 +72,7 @@ void CodeEdit::_notification(int p_what) {
 			can_fold_icon = get_theme_icon(SNAME("can_fold"));
 			folded_icon = get_theme_icon(SNAME("folded"));
 
-			code_completion_max_width = get_theme_constant(SNAME("completion_max_width")) * cache.font->get_char_size('x').x;
+			code_completion_max_width = get_theme_constant(SNAME("completion_max_width")) * font->get_char_size('x').x;
 			code_completion_max_lines = get_theme_constant(SNAME("completion_lines"));
 			code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width"));
 			code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color"));
@@ -80,12 +87,12 @@ void CodeEdit::_notification(int p_what) {
 			const Size2 size = get_size();
 			const bool caret_visible = is_caret_visible();
 			const bool rtl = is_layout_rtl();
-			const int row_height = get_row_height();
+			const int row_height = get_line_height();
 
 			if (line_length_guideline_columns.size() > 0) {
-				const int xmargin_beg = cache.style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
-				const int xmargin_end = size.width - cache.style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
-				const int char_size = (int)cache.font->get_char_size('0', 0, cache.font_size).width;
+				const int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
+				const int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
+				const int char_size = (int)font->get_char_size('0', 0, font_size).width;
 
 				for (int i = 0; i < line_length_guideline_columns.size(); i++) {
 					const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll();
@@ -115,14 +122,14 @@ void CodeEdit::_notification(int p_what) {
 				const Point2 caret_pos = get_caret_draw_pos();
 				const int total_height = csb->get_minimum_size().y + code_completion_rect.size.height;
 				if (caret_pos.y + row_height + total_height > get_size().height) {
-					code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + cache.line_spacing;
+					code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + line_spacing;
 				} else {
-					code_completion_rect.position.y = caret_pos.y + (cache.line_spacing / 2.0f);
+					code_completion_rect.position.y = caret_pos.y + (line_spacing / 2.0f);
 					code_completion_below = true;
 				}
 
 				const int scroll_width = code_completion_options_count > code_completion_max_lines ? code_completion_scroll_width : 0;
-				const int code_completion_base_width = cache.font->get_string_size(code_completion_base).width;
+				const int code_completion_base_width = font->get_string_size(code_completion_base).width;
 				if (caret_pos.x - code_completion_base_width + code_completion_rect.size.width + scroll_width > get_size().width) {
 					code_completion_rect.position.x = get_size().width - code_completion_rect.size.width - scroll_width;
 				} else {
@@ -144,7 +151,7 @@ void CodeEdit::_notification(int p_what) {
 
 					Ref<TextLine> tl;
 					tl.instantiate();
-					tl->add_string(code_completion_options[l].display, cache.font, cache.font_size);
+					tl->add_string(code_completion_options[l].display, font, font_size);
 
 					int yofs = (row_height - tl->get_size().y) / 2;
 					Point2 title_pos(code_completion_rect.position.x, code_completion_rect.position.y + i * row_height + yofs);
@@ -183,8 +190,7 @@ void CodeEdit::_notification(int p_what) {
 
 			/* Code hint */
 			if (caret_visible && code_hint != "" && (!code_completion_active || (code_completion_below != code_hint_draw_below))) {
-				const Ref<Font> font = cache.font;
-				const int font_height = font->get_height(cache.font_size);
+				const int font_height = font->get_height(font_size);
 				Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"));
 				Color font_color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"));
 
@@ -193,37 +199,37 @@ void CodeEdit::_notification(int p_what) {
 
 				int max_width = 0;
 				for (int i = 0; i < line_count; i++) {
-					max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], cache.font_size).x);
+					max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], font_size).x);
 				}
-				Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (cache.line_spacing * line_count - 1));
+				Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (line_spacing * line_count - 1));
 
-				int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), cache.font_size).x;
+				int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), font_size).x;
 				if (code_hint_xpos == -0xFFFF) {
 					code_hint_xpos = get_caret_draw_pos().x - offset;
 				}
 				Point2 hint_ofs = Vector2(code_hint_xpos, get_caret_draw_pos().y);
 				if (code_hint_draw_below) {
-					hint_ofs.y += cache.line_spacing / 2.0f;
+					hint_ofs.y += line_spacing / 2.0f;
 				} else {
-					hint_ofs.y -= (minsize.y + row_height) - cache.line_spacing;
+					hint_ofs.y -= (minsize.y + row_height) - line_spacing;
 				}
 
 				draw_style_box(sb, Rect2(hint_ofs, minsize));
 
-				int line_spacing = 0;
+				int yofs = 0;
 				for (int i = 0; i < line_count; i++) {
 					const String &line = code_hint_lines[i];
 
 					int begin = 0;
 					int end = 0;
 					if (line.find(String::chr(0xFFFF)) != -1) {
-						begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), cache.font_size).x;
-						end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), cache.font_size).x;
+						begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), font_size).x;
+						end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), font_size).x;
 					}
 
-					Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent() + font_height * i + line_spacing);
+					Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent() + font_height * i + yofs);
 					round_ofs = round_ofs.round();
-					draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, cache.font_size, font_color);
+					draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, font_size, font_color);
 					if (end > 0) {
 						// Draw an underline for the currently edited function parameter.
 						const Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + line_spacing);
@@ -235,7 +241,7 @@ void CodeEdit::_notification(int p_what) {
 								Vector2(end - begin, font_height));
 						draw_rect(highlight_rect, font_color * Color(1, 1, 1, 0.2));
 					}
-					line_spacing += cache.line_spacing;
+					yofs += line_spacing;
 				}
 			}
 		} break;
@@ -270,7 +276,7 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					}
 				} break;
 				case MOUSE_BUTTON_LEFT: {
-					code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_row_height(), 0, code_completion_options.size() - 1);
+					code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_line_height(), 0, code_completion_options.size() - 1);
 					if (mb->is_double_click()) {
 						confirm_code_completion();
 					}
@@ -290,14 +296,15 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				mpos.x = get_size().x - mpos.x;
 			}
 
-			int line, col;
-			_get_mouse_pos(Point2i(mpos.x, mpos.y), line, col);
+			Point2i pos = get_line_column_at_pos(Point2i(mpos.x, mpos.y));
+			int line = pos.y;
+			int col = pos.x;
 
 			if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
 				if (is_line_folded(line)) {
-					int wrap_index = get_line_wrap_index_at_col(line, col);
-					if (wrap_index == times_line_wraps(line)) {
-						int eol_icon_width = cache.folded_eol_icon->get_width();
+					int wrap_index = get_line_wrap_index_at_column(line, col);
+					if (wrap_index == get_line_wrap_count(line)) {
+						int eol_icon_width = folded_eol_icon->get_width();
 						int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll();
 						if (mpos.x > left_margin && mpos.x <= left_margin + eol_icon_width + 3) {
 							unfold_line(line);
@@ -313,8 +320,10 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					if (is_layout_rtl()) {
 						mpos.x = get_size().x - mpos.x;
 					}
-					int line, col;
-					_get_mouse_pos(Point2i(mpos.x, mpos.y), line, col);
+
+					Point2i pos = get_line_column_at_pos(Point2i(mpos.x, mpos.y));
+					int line = pos.y;
+					int col = pos.x;
 
 					emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col);
 					return;
@@ -357,7 +366,7 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 #endif
 		if (symbol_lookup_on_click_enabled) {
 			if (k->is_pressed() && !is_dragging_cursor()) {
-				symbol_lookup_new_word = get_word_at_pos(_get_local_mouse_pos());
+				symbol_lookup_new_word = get_word_at_pos(get_local_mouse_pos());
 				if (symbol_lookup_new_word != symbol_lookup_word) {
 					emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
 				}
@@ -523,17 +532,18 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
 		return CURSOR_POINTING_HAND;
 	}
 
-	if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || get_line_count() == 0))) {
+	if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (!is_editable() && (!is_selecting_enabled() || get_line_count() == 0))) {
 		return CURSOR_ARROW;
 	}
 
-	int line, col;
-	_get_mouse_pos(p_pos, line, col);
+	Point2i pos = get_line_column_at_pos(p_pos);
+	int line = pos.y;
+	int col = pos.x;
 
 	if (is_line_folded(line)) {
-		int wrap_index = get_line_wrap_index_at_col(line, col);
-		if (wrap_index == times_line_wraps(line)) {
-			int eol_icon_width = cache.folded_eol_icon->get_width();
+		int wrap_index = get_line_wrap_index_at_column(line, col);
+		if (wrap_index == get_line_wrap_count(line)) {
+			int eol_icon_width = folded_eol_icon->get_width();
 			int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll();
 			if (p_pos.x > left_margin && p_pos.x <= left_margin + eol_icon_width + 3) {
 				return CURSOR_POINTING_HAND;
@@ -544,58 +554,118 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
 	return TextEdit::get_cursor_shape(p_pos);
 }
 
-void CodeEdit::handle_unicode_input(uint32_t p_unicode) {
-	bool had_selection = is_selection_active();
+/* Text manipulation */
+
+// Overridable actions
+void CodeEdit::_handle_unicode_input(const uint32_t p_unicode) {
+	bool had_selection = has_selection();
 	if (had_selection) {
 		begin_complex_operation();
 		delete_selection();
 	}
 
-	// Remove the old character if in insert mode and no selection.
-	if (is_insert_mode() && !had_selection) {
+	// Remove the old character if in overtype mode and no selection.
+	if (is_overtype_mode_enabled() && !had_selection) {
 		begin_complex_operation();
 
-		// Make sure we don't try and remove empty space.
-		if (cursor_get_column() < get_line(cursor_get_line()).length()) {
-			_remove_text(cursor_get_line(), cursor_get_column(), cursor_get_line(), cursor_get_column() + 1);
+		/* Make sure we don't try and remove empty space. */
+		if (get_caret_column() < get_line(get_caret_line()).length()) {
+			remove_text(get_caret_line(), get_caret_column(), get_caret_line(), get_caret_column() + 1);
 		}
 	}
 
 	const char32_t chr[2] = { (char32_t)p_unicode, 0 };
 
 	if (auto_brace_completion_enabled) {
-		int cl = cursor_get_line();
-		int cc = cursor_get_column();
+		int cl = get_caret_line();
+		int cc = get_caret_column();
 		int caret_move_offset = 1;
 
 		int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
 
 		if (has_string_delimiter(chr) && cc > 0 && _is_char(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
-			insert_text_at_cursor(chr);
+			insert_text_at_caret(chr);
 		} else if (cc < get_line(cl).length() && _is_char(get_line(cl)[cc])) {
-			insert_text_at_cursor(chr);
+			insert_text_at_caret(chr);
 		} else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
 			caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
 		} else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
-			insert_text_at_cursor(chr);
+			insert_text_at_caret(chr);
 		} else {
-			insert_text_at_cursor(chr);
+			insert_text_at_caret(chr);
 
 			int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
 			if (pre_brace_pair != -1) {
-				insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
+				insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
 			}
 		}
-		cursor_set_column(cc + caret_move_offset);
+		set_caret_column(cc + caret_move_offset);
 	} else {
-		insert_text_at_cursor(chr);
+		insert_text_at_caret(chr);
 	}
 
-	if ((is_insert_mode() && !had_selection) || (had_selection)) {
+	if ((is_overtype_mode_enabled() && !had_selection) || (had_selection)) {
 		end_complex_operation();
 	}
 }
 
+void CodeEdit::_backspace() {
+	if (!is_editable()) {
+		return;
+	}
+
+	int cc = get_caret_column();
+	int cl = get_caret_line();
+
+	if (cc == 0 && cl == 0) {
+		return;
+	}
+
+	if (has_selection()) {
+		delete_selection();
+		return;
+	}
+
+	if (cl > 0 && _is_line_hidden(cl - 1)) {
+		unfold_line(get_caret_line() - 1);
+	}
+
+	int prev_line = cc ? cl : cl - 1;
+	int prev_column = cc ? (cc - 1) : (get_line(cl - 1).length());
+
+	merge_gutters(cl, prev_line);
+
+	if (auto_brace_completion_enabled && cc > 0) {
+		int idx = _get_auto_brace_pair_open_at_pos(cl, cc);
+		if (idx != -1) {
+			prev_column = cc - auto_brace_completion_pairs[idx].open_key.length();
+
+			if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) {
+				remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
+			} else {
+				remove_text(prev_line, prev_column, cl, cc);
+			}
+			set_caret_line(prev_line, false, true);
+			set_caret_column(prev_column);
+			return;
+		}
+	}
+
+	// For space indentation we need to do a simple unindent if there are no chars to the left, acting in the
+	// same way as tabs.
+	if (indent_using_spaces && cc != 0) {
+		if (get_first_non_whitespace_column(cl) > cc) {
+			prev_column = cc - _calculate_spaces_till_next_left_indent(cc);
+			prev_line = cl;
+		}
+	}
+
+	remove_text(prev_line, prev_column, cl, cc);
+
+	set_caret_line(prev_line, false, true);
+	set_caret_column(prev_column);
+}
+
 /* Indent management */
 void CodeEdit::set_indent_size(const int p_size) {
 	ERR_FAIL_COND_MSG(p_size <= 0, "Indend size must be greater than 0.");
@@ -654,28 +724,28 @@ TypedArray<String> CodeEdit::get_auto_indent_prefixes() const {
 }
 
 void CodeEdit::do_indent() {
-	if (is_readonly()) {
+	if (!is_editable()) {
 		return;
 	}
 
-	if (is_selection_active()) {
+	if (has_selection()) {
 		indent_lines();
 		return;
 	}
 
 	if (!indent_using_spaces) {
-		insert_text_at_cursor("\t");
+		insert_text_at_caret("\t");
 		return;
 	}
 
-	int spaces_to_add = _calculate_spaces_till_next_right_indent(cursor_get_column());
+	int spaces_to_add = _calculate_spaces_till_next_right_indent(get_caret_column());
 	if (spaces_to_add > 0) {
-		insert_text_at_cursor(String(" ").repeat(spaces_to_add));
+		insert_text_at_caret(String(" ").repeat(spaces_to_add));
 	}
 }
 
 void CodeEdit::indent_lines() {
-	if (is_readonly()) {
+	if (!is_editable()) {
 		return;
 	}
 
@@ -685,9 +755,9 @@ void CodeEdit::indent_lines() {
 	/* Default is 1 for tab indentation.                                                   */
 	int selection_offset = 1;
 
-	int start_line = cursor_get_line();
+	int start_line = get_caret_line();
 	int end_line = start_line;
-	if (is_selection_active()) {
+	if (has_selection()) {
 		start_line = get_selection_from_line();
 		end_line = get_selection_to_line();
 
@@ -700,7 +770,7 @@ void CodeEdit::indent_lines() {
 
 	for (int i = start_line; i <= end_line; i++) {
 		const String line_text = get_line(i);
-		if (line_text.size() == 0 && is_selection_active()) {
+		if (line_text.size() == 0 && has_selection()) {
 			continue;
 		}
 
@@ -717,32 +787,32 @@ void CodeEdit::indent_lines() {
 	}
 
 	/* Fix selection and caret being off after shifting selection right.*/
-	if (is_selection_active()) {
+	if (has_selection()) {
 		select(start_line, get_selection_from_column() + selection_offset, get_selection_to_line(), get_selection_to_column() + selection_offset);
 	}
-	cursor_set_column(cursor_get_column() + selection_offset, false);
+	set_caret_column(get_caret_column() + selection_offset, false);
 
 	end_complex_operation();
 }
 
 void CodeEdit::do_unindent() {
-	if (is_readonly()) {
+	if (!is_editable()) {
 		return;
 	}
 
-	int cc = cursor_get_column();
+	int cc = get_caret_column();
 
-	if (is_selection_active() || cc <= 0) {
+	if (has_selection() || cc <= 0) {
 		unindent_lines();
 		return;
 	}
 
-	int cl = cursor_get_line();
+	int cl = get_caret_line();
 	const String &line = get_line(cl);
 
 	if (line[cc - 1] == '\t') {
-		_remove_text(cl, cc - 1, cl, cc);
-		cursor_set_column(MAX(0, cc - 1));
+		remove_text(cl, cc - 1, cl, cc);
+		set_caret_column(MAX(0, cc - 1));
 		return;
 	}
 
@@ -758,13 +828,13 @@ void CodeEdit::do_unindent() {
 				break;
 			}
 		}
-		_remove_text(cl, cc - spaces_to_remove, cl, cc);
-		cursor_set_column(MAX(0, cc - spaces_to_remove));
+		remove_text(cl, cc - spaces_to_remove, cl, cc);
+		set_caret_column(MAX(0, cc - spaces_to_remove));
 	}
 }
 
 void CodeEdit::unindent_lines() {
-	if (is_readonly()) {
+	if (!is_editable()) {
 		return;
 	}
 
@@ -775,11 +845,11 @@ void CodeEdit::unindent_lines() {
 	/* therefore we just remember initial values and at the end of the operation offset them by number of removed characters.   */
 	int removed_characters = 0;
 	int initial_selection_end_column = 0;
-	int initial_cursor_column = cursor_get_column();
+	int initial_cursor_column = get_caret_column();
 
-	int start_line = cursor_get_line();
+	int start_line = get_caret_line();
 	int end_line = start_line;
-	if (is_selection_active()) {
+	if (has_selection()) {
 		start_line = get_selection_from_line();
 		end_line = get_selection_to_line();
 
@@ -822,7 +892,7 @@ void CodeEdit::unindent_lines() {
 		}
 	}
 
-	if (is_selection_active()) {
+	if (has_selection()) {
 		/* Fix selection being off by one on the first line. */
 		if (first_line_edited) {
 			select(get_selection_from_line(), get_selection_from_column() - removed_characters, get_selection_to_line(), initial_selection_end_column);
@@ -833,7 +903,7 @@ void CodeEdit::unindent_lines() {
 			select(get_selection_from_line(), get_selection_from_column(), get_selection_to_line(), initial_selection_end_column - removed_characters);
 		}
 	}
-	cursor_set_column(initial_cursor_column - removed_characters, false);
+	set_caret_column(initial_cursor_column - removed_characters, false);
 
 	end_complex_operation();
 }
@@ -851,12 +921,12 @@ int CodeEdit::_calculate_spaces_till_next_right_indent(int p_column) const {
 }
 
 void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
-	if (is_readonly()) {
+	if (!is_editable()) {
 		return;
 	}
 
-	const int cc = cursor_get_column();
-	const int cl = cursor_get_line();
+	const int cc = get_caret_column();
+	const int cl = get_caret_line();
 	const String line = get_line(cl);
 
 	String ins = "\n";
@@ -932,86 +1002,29 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
 	if (!p_split_current_line) {
 		if (p_above) {
 			if (cl > 0) {
-				cursor_set_line(cl - 1, false);
-				cursor_set_column(get_line(cursor_get_line()).length());
+				set_caret_line(cl - 1, false);
+				set_caret_column(get_line(get_caret_line()).length());
 			} else {
-				cursor_set_column(0);
+				set_caret_column(0);
 				first_line = true;
 			}
 		} else {
-			cursor_set_column(line.length());
+			set_caret_column(line.length());
 		}
 	}
 
-	insert_text_at_cursor(ins);
+	insert_text_at_caret(ins);
 
 	if (first_line) {
-		cursor_set_line(0);
+		set_caret_line(0);
 	} else if (brace_indent) {
-		cursor_set_line(cursor_get_line() - 1, false);
-		cursor_set_column(get_line(cursor_get_line()).length());
+		set_caret_line(get_caret_line() - 1, false);
+		set_caret_column(get_line(get_caret_line()).length());
 	}
 
 	end_complex_operation();
 }
 
-void CodeEdit::backspace() {
-	if (is_readonly()) {
-		return;
-	}
-
-	int cc = cursor_get_column();
-	int cl = cursor_get_line();
-
-	if (cc == 0 && cl == 0) {
-		return;
-	}
-
-	if (is_selection_active()) {
-		delete_selection();
-		return;
-	}
-
-	if (cl > 0 && is_line_hidden(cl - 1)) {
-		unfold_line(cursor_get_line() - 1);
-	}
-
-	int prev_line = cc ? cl : cl - 1;
-	int prev_column = cc ? (cc - 1) : (get_line(cl - 1).length());
-
-	merge_gutters(cl, prev_line);
-
-	if (auto_brace_completion_enabled && cc > 0) {
-		int idx = _get_auto_brace_pair_open_at_pos(cl, cc);
-		if (idx != -1) {
-			prev_column = cc - auto_brace_completion_pairs[idx].open_key.length();
-
-			if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) {
-				_remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
-			} else {
-				_remove_text(prev_line, prev_column, cl, cc);
-			}
-			cursor_set_line(prev_line, false, true);
-			cursor_set_column(prev_column);
-			return;
-		}
-	}
-
-	/* For space indentation we need to do a simple unindent if there are no chars to the left, acting in the */
-	/* same way as tabs.                                                                                      */
-	if (indent_using_spaces && cc != 0) {
-		if (get_first_non_whitespace_column(cl) > cc) {
-			prev_column = cc - _calculate_spaces_till_next_left_indent(cc);
-			prev_line = cl;
-		}
-	}
-
-	_remove_text(prev_line, prev_column, cl, cc);
-
-	cursor_set_line(prev_line, false, true);
-	cursor_set_column(prev_column);
-}
-
 /* Auto brace completion */
 void CodeEdit::set_auto_brace_completion_enabled(bool p_enabled) {
 	auto_brace_completion_enabled = p_enabled;
@@ -1278,8 +1291,8 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2
 	String fc = TS->format_number(String::num(p_line + 1).lpad(line_number_digits, line_number_padding));
 	Ref<TextLine> tl;
 	tl.instantiate();
-	tl->add_string(fc, cache.font, cache.font_size);
-	int yofs = p_region.position.y + (get_row_height() - tl->get_size().y) / 2;
+	tl->add_string(fc, font, font_size);
+	int yofs = p_region.position.y + (get_line_height() - tl->get_size().y) / 2;
 	Color number_color = get_line_gutter_item_color(p_line, line_number_gutter);
 	if (number_color == Color(1, 1, 1)) {
 		number_color = line_number_color;
@@ -1319,7 +1332,7 @@ void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_regi
 /* Line Folding */
 void CodeEdit::set_line_folding_enabled(bool p_enabled) {
 	line_folding_enabled = p_enabled;
-	set_hiding_enabled(p_enabled);
+	_set_hiding_enabled(p_enabled);
 }
 
 bool CodeEdit::is_line_folding_enabled() const {
@@ -1336,7 +1349,7 @@ bool CodeEdit::can_fold_line(int p_line) const {
 		return false;
 	}
 
-	if (is_line_hidden(p_line) || is_line_folded(p_line)) {
+	if (_is_line_hidden(p_line) || is_line_folded(p_line)) {
 		return false;
 	}
 
@@ -1416,31 +1429,31 @@ void CodeEdit::fold_line(int p_line) {
 	}
 
 	for (int i = p_line + 1; i <= end_line; i++) {
-		set_line_as_hidden(i, true);
+		_set_line_as_hidden(i, true);
 	}
 
 	/* Fix selection. */
-	if (is_selection_active()) {
-		if (is_line_hidden(get_selection_from_line()) && is_line_hidden(get_selection_to_line())) {
+	if (has_selection()) {
+		if (_is_line_hidden(get_selection_from_line()) && _is_line_hidden(get_selection_to_line())) {
 			deselect();
-		} else if (is_line_hidden(get_selection_from_line())) {
+		} else if (_is_line_hidden(get_selection_from_line())) {
 			select(p_line, 9999, get_selection_to_line(), get_selection_to_column());
-		} else if (is_line_hidden(get_selection_to_line())) {
+		} else if (_is_line_hidden(get_selection_to_line())) {
 			select(get_selection_from_line(), get_selection_from_column(), p_line, 9999);
 		}
 	}
 
 	/* Reset caret. */
-	if (is_line_hidden(cursor_get_line())) {
-		cursor_set_line(p_line, false, false);
-		cursor_set_column(get_line(p_line).length(), false);
+	if (_is_line_hidden(get_caret_line())) {
+		set_caret_line(p_line, false, false);
+		set_caret_column(get_line(p_line).length(), false);
 	}
 	update();
 }
 
 void CodeEdit::unfold_line(int p_line) {
 	ERR_FAIL_INDEX(p_line, get_line_count());
-	if (!is_line_folded(p_line) && !is_line_hidden(p_line)) {
+	if (!is_line_folded(p_line) && !_is_line_hidden(p_line)) {
 		return;
 	}
 
@@ -1453,10 +1466,10 @@ void CodeEdit::unfold_line(int p_line) {
 	fold_start = is_line_folded(fold_start) ? fold_start : p_line;
 
 	for (int i = fold_start + 1; i < get_line_count(); i++) {
-		if (!is_line_hidden(i)) {
+		if (!_is_line_hidden(i)) {
 			break;
 		}
-		set_line_as_hidden(i, false);
+		_set_line_as_hidden(i, false);
 	}
 	update();
 }
@@ -1469,7 +1482,7 @@ void CodeEdit::fold_all_lines() {
 }
 
 void CodeEdit::unfold_all_lines() {
-	unhide_all_lines();
+	_unhide_all_lines();
 }
 
 void CodeEdit::toggle_foldable_line(int p_line) {
@@ -1483,7 +1496,7 @@ void CodeEdit::toggle_foldable_line(int p_line) {
 
 bool CodeEdit::is_line_folded(int p_line) const {
 	ERR_FAIL_INDEX_V(p_line, get_line_count(), false);
-	return p_line + 1 < get_line_count() && !is_line_hidden(p_line) && is_line_hidden(p_line + 1);
+	return p_line + 1 < get_line_count() && !_is_line_hidden(p_line) && _is_line_hidden(p_line + 1);
 }
 
 TypedArray<int> CodeEdit::get_folded_lines() const {
@@ -1707,11 +1720,11 @@ String CodeEdit::get_text_for_code_completion() const {
 	for (int i = 0; i < text_size; i++) {
 		String line = get_line(i);
 
-		if (i == cursor_get_line()) {
-			completion_text += line.substr(0, cursor_get_column());
+		if (i == get_caret_line()) {
+			completion_text += line.substr(0, get_caret_column());
 			/* Not unicode, represents the caret. */
 			completion_text += String::chr(0xFFFF);
-			completion_text += line.substr(cursor_get_column(), line.size());
+			completion_text += line.substr(get_caret_column(), line.size());
 		} else {
 			completion_text += line;
 		}
@@ -1758,10 +1771,10 @@ void CodeEdit::request_code_completion(bool p_force) {
 		return;
 	}
 
-	String line = get_line(cursor_get_line());
-	int ofs = CLAMP(cursor_get_column(), 0, line.length());
+	String line = get_line(get_caret_line());
+	int ofs = CLAMP(get_caret_column(), 0, line.length());
 
-	if (ofs > 0 && (is_in_string(cursor_get_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) {
+	if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) {
 		emit_signal(SNAME("request_code_completion"));
 	} else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[ofs - 2]))) {
 		emit_signal(SNAME("request_code_completion"));
@@ -1836,7 +1849,7 @@ void CodeEdit::set_code_completion_selected_index(int p_index) {
 }
 
 void CodeEdit::confirm_code_completion(bool p_replace) {
-	if (is_readonly() || !code_completion_active) {
+	if (!is_editable() || !code_completion_active) {
 		return;
 	}
 
@@ -1847,7 +1860,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
 	}
 	begin_complex_operation();
 
-	int caret_line = cursor_get_line();
+	int caret_line = get_caret_line();
 
 	const String &insert_text = code_completion_options[code_completion_current_selected].insert_text;
 	const String &display_text = code_completion_options[code_completion_current_selected].display;
@@ -1855,7 +1868,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
 	if (p_replace) {
 		/* Find end of current section */
 		const String line = get_line(caret_line);
-		int caret_col = cursor_get_column();
+		int caret_col = get_caret_column();
 		int caret_remove_line = caret_line;
 
 		bool merge_text = true;
@@ -1878,13 +1891,13 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
 		}
 
 		/* Replace. */
-		_remove_text(caret_line, cursor_get_column() - code_completion_base.length(), caret_remove_line, caret_col);
-		cursor_set_column(cursor_get_column() - code_completion_base.length(), false);
-		insert_text_at_cursor(insert_text);
+		remove_text(caret_line, get_caret_column() - code_completion_base.length(), caret_remove_line, caret_col);
+		set_caret_column(get_caret_column() - code_completion_base.length(), false);
+		insert_text_at_caret(insert_text);
 	} else {
 		/* Get first non-matching char. */
 		const String line = get_line(caret_line);
-		int caret_col = cursor_get_column();
+		int caret_col = get_caret_column();
 		int matching_chars = code_completion_base.length();
 		for (; matching_chars <= insert_text.length(); matching_chars++) {
 			if (caret_col >= line.length() || line[caret_col] != insert_text[matching_chars]) {
@@ -1894,41 +1907,41 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
 		}
 
 		/* Remove base completion text. */
-		_remove_text(caret_line, cursor_get_column() - code_completion_base.length(), caret_line, cursor_get_column());
-		cursor_set_column(cursor_get_column() - code_completion_base.length(), false);
+		remove_text(caret_line, get_caret_column() - code_completion_base.length(), caret_line, get_caret_column());
+		set_caret_column(get_caret_column() - code_completion_base.length(), false);
 
 		/* Merge with text. */
-		insert_text_at_cursor(insert_text.substr(0, code_completion_base.length()));
-		cursor_set_column(caret_col, false);
-		insert_text_at_cursor(insert_text.substr(matching_chars));
+		insert_text_at_caret(insert_text.substr(0, code_completion_base.length()));
+		set_caret_column(caret_col, false);
+		insert_text_at_caret(insert_text.substr(matching_chars));
 	}
 
 	/* Handle merging of symbols eg strings, brackets. */
 	const String line = get_line(caret_line);
-	char32_t next_char = line[cursor_get_column()];
+	char32_t next_char = line[get_caret_column()];
 	char32_t last_completion_char = insert_text[insert_text.length() - 1];
 	char32_t last_completion_char_display = display_text[display_text.length() - 1];
 
-	int pre_brace_pair = cursor_get_column() > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column()) : -1;
-	int post_brace_pair = cursor_get_column() < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column()) : -1;
+	int pre_brace_pair = get_caret_column() > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column()) : -1;
+	int post_brace_pair = get_caret_column() < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column()) : -1;
 
 	if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
-		_remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
+		remove_text(caret_line, get_caret_column(), caret_line, get_caret_column() + 1);
 	}
 
 	if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
-		_remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
+		remove_text(caret_line, get_caret_column(), caret_line, get_caret_column() + 1);
 	} else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
-		insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
-		cursor_set_column(cursor_get_column() - auto_brace_completion_pairs[pre_brace_pair].close_key.length());
+		insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
+		set_caret_column(get_caret_column() - auto_brace_completion_pairs[pre_brace_pair].close_key.length());
 	}
 
-	if (pre_brace_pair == -1 && post_brace_pair == -1 && cursor_get_column() > 0 && cursor_get_column() < get_line(caret_line).length()) {
-		pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column() + 1);
-		if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1)) {
-			_remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
-			if (_get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1) != pre_brace_pair) {
-				cursor_set_column(cursor_get_column() - 1);
+	if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column() > 0 && get_caret_column() < get_line(caret_line).length()) {
+		pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column() + 1);
+		if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
+			remove_text(caret_line, get_caret_column() - 2, caret_line, get_caret_column());
+			if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1) != pre_brace_pair) {
+				set_caret_column(get_caret_column() - 1);
 			}
 		}
 	}
@@ -1971,9 +1984,11 @@ bool CodeEdit::is_symbol_lookup_on_click_enabled() const {
 }
 
 String CodeEdit::get_text_for_symbol_lookup() {
-	int line, col;
-	Point2i mp = _get_local_mouse_pos();
-	_get_mouse_pos(mp, line, col);
+	Point2i mp = get_local_mouse_pos();
+
+	Point2i pos = get_line_column_at_pos(mp);
+	int line = pos.y;
+	int col = pos.x;
 
 	StringBuilder lookup_text;
 	const int text_size = get_line_count();
@@ -2289,8 +2304,8 @@ void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
 	if (p_gutter == line_number_gutter) {
 		set_selection_mode(TextEdit::SelectionMode::SELECTION_MODE_LINE, p_line, 0);
 		select(p_line, 0, p_line + 1, 0);
-		cursor_set_line(p_line + 1);
-		cursor_set_column(0);
+		set_caret_line(p_line + 1);
+		set_caret_column(0);
 		return;
 	}
 
@@ -2674,7 +2689,7 @@ void CodeEdit::_filter_code_completion_candidates() {
 			option.icon = completion_options[i].get("icon");
 			option.default_value = completion_options[i].get("default_value");
 
-			max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+			max_width = MAX(max_width, font->get_string_size(option.display).width);
 			code_completion_options.push_back(option);
 		}
 
@@ -2685,8 +2700,8 @@ void CodeEdit::_filter_code_completion_candidates() {
 		return;
 	}
 
-	const int caret_line = cursor_get_line();
-	const int caret_column = cursor_get_column();
+	const int caret_line = get_caret_line();
+	const int caret_column = get_caret_column();
 	const String line = get_line(caret_line);
 
 	if (caret_column > 0 && line[caret_column - 1] == '(' && !code_completion_forced) {
@@ -2778,7 +2793,7 @@ void CodeEdit::_filter_code_completion_candidates() {
 
 		if (string_to_complete.length() == 0) {
 			code_completion_options.push_back(option);
-			max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+			max_width = MAX(max_width, font->get_string_size(option.display).width);
 			continue;
 		}
 
@@ -2827,7 +2842,7 @@ void CodeEdit::_filter_code_completion_candidates() {
 			} else {
 				completion_options_subseq.push_back(option);
 			}
-			max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+			max_width = MAX(max_width, font->get_string_size(option.display).width);
 			/* Matched the whole subsequence in s_lower. */
 		} else if (!*ssq_lower) {
 			/* Finished matching in the first s.length() characters. */
@@ -2836,7 +2851,7 @@ void CodeEdit::_filter_code_completion_candidates() {
 			} else {
 				completion_options_subseq_casei.push_back(option);
 			}
-			max_width = MAX(max_width, cache.font->get_string_size(option.display).width);
+			max_width = MAX(max_width, font->get_string_size(option.display).width);
 		}
 	}
 
@@ -2874,7 +2889,7 @@ void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
 	while (lc /= 10) {
 		line_number_digits++;
 	}
-	set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0', 0, cache.font_size).width);
+	set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
 
 	int from_line = MIN(p_from_line, p_to_line);
 	int line_count = (p_to_line - p_from_line);

+ 14 - 3
scene/gui/code_edit.h

@@ -233,16 +233,29 @@ private:
 	String symbol_lookup_new_word = "";
 	String symbol_lookup_word = "";
 
+	/* Visual */
+	Ref<StyleBox> style_normal;
+
+	Ref<Font> font;
+	int font_size = 16;
+
+	int line_spacing = 1;
+
 protected:
 	void _gui_input(const Ref<InputEvent> &p_gui_input) override;
 	void _notification(int p_what);
 
 	static void _bind_methods();
 
+	/* Text manipulation */
+
+	// Overridable actions
+	virtual void _handle_unicode_input(const uint32_t p_unicode) override;
+	virtual void _backspace() override;
+
 public:
 	/* General overrides */
 	virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
-	virtual void handle_unicode_input(uint32_t p_unicode) override;
 
 	/* Indent management */
 	void set_indent_size(const int p_size);
@@ -263,8 +276,6 @@ public:
 	void indent_lines();
 	void unindent_lines();
 
-	virtual void backspace() override;
-
 	/* Auto brace completion */
 	void set_auto_brace_completion_enabled(bool p_enabled);
 	bool is_auto_brace_completion_enabled() const;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 155 - 397
scene/gui/text_edit.cpp


+ 523 - 422
scene/gui/text_edit.h

@@ -42,12 +42,13 @@ class TextEdit : public Control {
 	GDCLASS(TextEdit, Control);
 
 public:
-	enum GutterType {
-		GUTTER_TYPE_STRING,
-		GUTTER_TYPE_ICON,
-		GUTTER_TYPE_CUSTOM
+	/* Caret. */
+	enum CaretType {
+		CARET_TYPE_LINE,
+		CARET_TYPE_BLOCK
 	};
 
+	/* Selection */
 	enum SelectionMode {
 		SELECTION_MODE_NONE,
 		SELECTION_MODE_SHIFT,
@@ -56,6 +57,60 @@ public:
 		SELECTION_MODE_LINE
 	};
 
+	/* Line Wrapping.*/
+	enum LineWrappingMode {
+		LINE_WRAPPING_NONE,
+		LINE_WRAPPING_BOUNDARY
+	};
+
+	/* Gutters. */
+	enum GutterType {
+		GUTTER_TYPE_STRING,
+		GUTTER_TYPE_ICON,
+		GUTTER_TYPE_CUSTOM
+	};
+
+	/* Contex Menu. */
+	enum MenuItems {
+		MENU_CUT,
+		MENU_COPY,
+		MENU_PASTE,
+		MENU_CLEAR,
+		MENU_SELECT_ALL,
+		MENU_UNDO,
+		MENU_REDO,
+		MENU_DIR_INHERITED,
+		MENU_DIR_AUTO,
+		MENU_DIR_LTR,
+		MENU_DIR_RTL,
+		MENU_DISPLAY_UCC,
+		MENU_INSERT_LRM,
+		MENU_INSERT_RLM,
+		MENU_INSERT_LRE,
+		MENU_INSERT_RLE,
+		MENU_INSERT_LRO,
+		MENU_INSERT_RLO,
+		MENU_INSERT_PDF,
+		MENU_INSERT_ALM,
+		MENU_INSERT_LRI,
+		MENU_INSERT_RLI,
+		MENU_INSERT_FSI,
+		MENU_INSERT_PDI,
+		MENU_INSERT_ZWJ,
+		MENU_INSERT_ZWNJ,
+		MENU_INSERT_WJ,
+		MENU_INSERT_SHY,
+		MENU_MAX
+
+	};
+
+	/* Search. */
+	enum SearchFlags {
+		SEARCH_MATCH_CASE = 1,
+		SEARCH_WHOLE_WORDS = 2,
+		SEARCH_BACKWARDS = 4
+	};
+
 private:
 	struct GutterInfo {
 		GutterType type = GutterType::GUTTER_TYPE_STRING;
@@ -68,11 +123,6 @@ private:
 		ObjectID custom_draw_obj = ObjectID();
 		StringName custom_draw_callback;
 	};
-	Vector<GutterInfo> gutters;
-	int gutters_width = 0;
-	int gutter_padding = 0;
-
-	void _update_gutter_width();
 
 	class Text {
 	public:
@@ -121,7 +171,7 @@ private:
 		void set_font(const Ref<Font> &p_font);
 		void set_font_size(int p_font_size);
 		void set_font_features(const Dictionary &p_features);
-		void set_direction_and_language(TextServer::Direction p_direction, String p_language);
+		void set_direction_and_language(TextServer::Direction p_direction, const String &p_language);
 		void set_draw_control_chars(bool p_draw_control_chars);
 
 		int get_line_height(int p_line, int p_wrap_index) const;
@@ -159,7 +209,7 @@ private:
 		void set_line_gutter_text(int p_line, int p_gutter, const String &p_text) { text.write[p_line].gutters.write[p_gutter].text = p_text; }
 		const String &get_line_gutter_text(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].text; }
 
-		void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon) { text.write[p_line].gutters.write[p_gutter].icon = p_icon; }
+		void set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2D> &p_icon) { text.write[p_line].gutters.write[p_gutter].icon = p_icon; }
 		const Ref<Texture2D> &get_line_gutter_icon(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].icon; }
 
 		void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) { text.write[p_line].gutters.write[p_gutter].color = p_color; }
@@ -173,38 +223,48 @@ private:
 		const Color get_line_background_color(int p_line) const { return text[p_line].background_color; }
 	};
 
-	struct Cursor {
-		Point2 draw_pos;
-		bool visible = false;
-		int last_fit_x = 0;
-		int line = 0;
-		int column = 0; ///< cursor
-		int x_ofs = 0;
-		int line_ofs = 0;
-		int wrap_ofs = 0;
-	} cursor;
+	/* Text */
+	Text text;
 
-	struct Selection {
-		SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE;
-		int selecting_line = 0;
-		int selecting_column = 0;
-		int selected_word_beg = 0;
-		int selected_word_end = 0;
-		int selected_word_origin = 0;
-		bool selecting_text = false;
+	bool setting_text = false;
 
-		bool active = false;
+	// Text properties.
+	String ime_text = "";
+	Point2 ime_selection;
 
-		int from_line = 0;
-		int from_column = 0;
-		int to_line = 0;
-		int to_column = 0;
+	/* Initialise to opposite first, so we get past the early-out in set_editable. */
+	bool editable = false;
 
-		bool shiftclick_left = false;
-	} selection;
+	TextDirection text_direction = TEXT_DIRECTION_AUTO;
+	TextDirection input_direction = TEXT_DIRECTION_LTR;
 
-	Map<int, Dictionary> syntax_highlighting_cache;
+	Dictionary opentype_features;
+	String language = "";
+
+	Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+	Array st_args;
+
+	void _clear();
+	void _update_caches();
+
+	// User control.
+	bool overtype_mode = false;
+	bool context_menu_enabled = true;
+	bool shortcut_keys_enabled = true;
+	bool virtual_keyboard_enabled = true;
 
+	// Overridable actions
+	String cut_copy_line = "";
+
+	// Context menu.
+	PopupMenu *menu = nullptr;
+	PopupMenu *menu_dir = nullptr;
+	PopupMenu *menu_ctl = nullptr;
+
+	void _generate_context_menu();
+	int _get_menu_action_accelerator(const String &p_action);
+
+	/* Versioning */
 	struct TextOperation {
 		enum Type {
 			TYPE_NONE,
@@ -224,363 +284,303 @@ private:
 		bool chain_backward = false;
 	};
 
-	String ime_text;
-	Point2 ime_selection;
+	bool undo_enabled = true;
+	int undo_stack_max_size = 50;
 
-	TextOperation current_op;
+	bool next_operation_is_complex = false;
 
+	TextOperation current_op;
 	List<TextOperation> undo_stack;
 	List<TextOperation>::Element *undo_stack_pos = nullptr;
-	int undo_stack_max_size;
 
-	void _clear_redo();
-	void _do_text_op(const TextOperation &p_op, bool p_reverse);
-
-	//syntax coloring
-	Ref<SyntaxHighlighter> syntax_highlighter;
-	Set<String> keywords;
+	Timer *idle_detect;
 
-	Dictionary _get_line_syntax_highlighting(int p_line);
+	uint32_t version = 0;
+	uint32_t saved_version = 0;
 
-	bool setting_text = false;
+	void _push_current_op();
+	void _do_text_op(const TextOperation &p_op, bool p_reverse);
+	void _clear_redo();
 
-	// data
-	Text text;
+	/* Search */
+	Color search_result_color = Color(1, 1, 1);
+	Color search_result_border_color = Color(1, 1, 1);
 
-	Dictionary opentype_features;
-	String language;
-	TextDirection text_direction = TEXT_DIRECTION_AUTO;
-	TextDirection input_direction = TEXT_DIRECTION_LTR;
-	Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
-	Array st_args;
-	bool draw_control_chars = false;
+	String search_text = "";
+	uint32_t search_flags = 0;
 
-	uint32_t version = 0;
-	uint32_t saved_version = 0;
+	int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) const;
 
-	bool readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
+	/* Tooltip. */
+	Object *tooltip_obj = nullptr;
+	StringName tooltip_func;
+	Variant tooltip_ud;
 
-	Timer *caret_blink_timer;
-	bool caret_blink_enabled = false;
-	bool draw_caret = true;
-	bool window_has_focus = true;
-	bool block_caret = false;
-	bool right_click_moves_caret = true;
-	bool mid_grapheme_caret_enabled = false;
+	/* Mouse */
+	int _get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const;
 
-	bool wrap_enabled = false;
-	int wrap_at = 0;
-	int wrap_right_offset = 10;
+	/* Caret. */
+	struct Caret {
+		Point2 draw_pos;
+		bool visible = false;
+		int last_fit_x = 0;
+		int line = 0;
+		int column = 0;
+		int x_ofs = 0;
+		int line_ofs = 0;
+		int wrap_ofs = 0;
+	} caret;
 
-	bool first_draw = true;
-	bool setting_row = false;
-	bool draw_tabs = false;
-	bool draw_spaces = false;
-	bool override_selected_font_color = false;
-	bool cursor_changed_dirty = false;
-	bool text_changed_dirty = false;
-	bool undo_enabled = true;
-	bool hiding_enabled = false;
-	bool draw_minimap = false;
-	int minimap_width = 80;
-	Point2 minimap_char_size = Point2(1, 2);
-	int minimap_line_spacing = 1;
+	bool setting_caret_line = false;
+	bool caret_pos_dirty = false;
 
-	bool highlight_all_occurrences = false;
-	bool scroll_past_end_of_file_enabled = false;
-	bool highlight_current_line = false;
+	Color caret_color = Color(1, 1, 1);
+	Color caret_background_color = Color(0, 0, 0);
 
-	String cut_copy_line;
-	bool insert_mode = false;
-	bool select_identifiers_enabled = false;
+	CaretType caret_type = CaretType::CARET_TYPE_LINE;
 
-	bool smooth_scroll_enabled = false;
-	bool scrolling = false;
-	bool dragging_selection = false;
-	bool dragging_minimap = false;
-	bool can_drag_minimap = false;
-	bool minimap_clicked = false;
-	double minimap_scroll_ratio = 0.0;
-	double minimap_scroll_click_pos = 0.0;
-	float target_v_scroll = 0.0;
-	float v_scroll_speed = 80.0;
+	bool draw_caret = true;
 
-	String lookup_symbol_word;
+	bool caret_blink_enabled = false;
+	Timer *caret_blink_timer;
 
-	uint64_t last_dblclk = 0;
-	Vector2 last_dblclk_pos;
+	bool move_caret_on_right_click = true;
 
-	Timer *idle_detect;
-	Timer *click_select_held;
-	HScrollBar *h_scroll;
-	VScrollBar *v_scroll;
-	bool updating_scrolls = false;
+	bool caret_mid_grapheme_enabled = false;
 
-	Object *tooltip_obj = nullptr;
-	StringName tooltip_func;
-	Variant tooltip_ud;
+	void _emit_caret_changed();
 
-	bool next_operation_is_complex = false;
+	void _reset_caret_blink_timer();
+	void _toggle_draw_caret();
 
-	String search_text;
-	uint32_t search_flags = 0;
-	int search_result_line = 0;
-	int search_result_col = 0;
+	int _get_column_x_offset_for_line(int p_char, int p_line) const;
 
-	bool selecting_enabled = true;
+	/* Selection. */
+	struct Selection {
+		SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE;
+		int selecting_line = 0;
+		int selecting_column = 0;
+		int selected_word_beg = 0;
+		int selected_word_end = 0;
+		int selected_word_origin = 0;
+		bool selecting_text = false;
 
-	bool context_menu_enabled = true;
-	bool shortcut_keys_enabled = true;
-	bool virtual_keyboard_enabled = true;
+		bool active = false;
 
-	int get_visible_rows() const;
-	int get_total_visible_rows() const;
+		int from_line = 0;
+		int from_column = 0;
+		int to_line = 0;
+		int to_column = 0;
 
-	int _get_minimap_visible_rows() const;
+		bool shiftclick_left = false;
+	} selection;
 
-	void update_cursor_wrap_offset();
-	void _update_wrap_at(bool p_force = false);
-	Vector<String> get_wrap_rows_text(int p_line) const;
-	int get_cursor_wrap_index() const;
-	int get_char_count();
+	bool selecting_enabled = true;
 
-	double get_scroll_pos_for_line(int p_line, int p_wrap_index = 0) const;
-	void set_line_as_first_visible(int p_line, int p_wrap_index = 0);
-	void set_line_as_center_visible(int p_line, int p_wrap_index = 0);
-	void set_line_as_last_visible(int p_line, int p_wrap_index = 0);
-	int get_first_visible_line() const;
-	int get_last_full_visible_line() const;
-	int get_last_full_visible_line_wrap_index() const;
-	double get_visible_rows_offset() const;
-	double get_v_scroll_offset() const;
+	Color font_selected_color = Color(1, 1, 1);
+	Color selection_color = Color(1, 1, 1);
+	bool override_selected_font_color = false;
 
-	int get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const;
-	int get_column_x_offset_for_line(int p_char, int p_line) const;
+	bool dragging_selection = false;
 
-	void adjust_viewport_to_cursor();
-	double get_scroll_line_diff() const;
-	void _scroll_moved(double);
-	void _update_scrollbars();
-	void _v_scroll_input();
+	Timer *click_select_held;
+	uint64_t last_dblclk = 0;
+	Vector2 last_dblclk_pos;
 	void _click_selection_held();
 
 	void _update_selection_mode_pointer();
 	void _update_selection_mode_word();
 	void _update_selection_mode_line();
 
-	void _update_minimap_click();
-	void _update_minimap_drag();
-	void _scroll_up(real_t p_delta);
-	void _scroll_down(real_t p_delta);
-
 	void _pre_shift_selection();
 	void _post_shift_selection();
 
-	void _scroll_lines_up();
-	void _scroll_lines_down();
+	/* line wrapping. */
+	LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE;
 
-	//void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask);
-	Size2 get_minimum_size() const override;
-	int _get_control_height() const;
+	int wrap_at_column = 0;
+	int wrap_right_offset = 10;
 
-	int _get_menu_action_accelerator(const String &p_action);
+	void _update_wrap_at_column(bool p_force = false);
 
-	void _reset_caret_blink_timer();
-	void _toggle_draw_caret();
+	void _update_caret_wrap_offset();
 
-	void _update_caches();
-	void _cursor_changed_emit();
-	void _text_changed_emit();
+	/* Viewport. */
+	HScrollBar *h_scroll;
+	VScrollBar *v_scroll;
 
-	void _push_current_op();
+	bool scroll_past_end_of_file_enabled = false;
 
-	/* super internal api, undo/redo builds on it */
+	// Smooth scrolling.
+	bool smooth_scroll_enabled = false;
+	float target_v_scroll = 0.0;
+	float v_scroll_speed = 80.0;
 
-	void _base_insert_text(int p_line, int p_char, const String &p_text, int &r_end_line, int &r_end_column);
-	String _base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const;
-	void _base_remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
+	// Scrolling.
+	bool scrolling = false;
+	bool updating_scrolls = false;
 
-	int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column);
+	void _update_scrollbars();
+	int _get_control_height() const;
 
-	Dictionary _search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const;
+	void _v_scroll_input();
+	void _scroll_moved(double p_to_val);
 
-	PopupMenu *menu = nullptr;
-	PopupMenu *menu_dir = nullptr;
-	PopupMenu *menu_ctl = nullptr;
+	double _get_visible_lines_offset() const;
+	double _get_v_scroll_offset() const;
 
-	void _ensure_menu();
+	void _scroll_up(real_t p_delta);
+	void _scroll_down(real_t p_delta);
 
-	void _clear();
+	void _scroll_lines_up();
+	void _scroll_lines_down();
 
-	// Methods used in shortcuts
-	void _swap_current_input_direction();
-	void _new_line(bool p_split_current = true, bool p_above = false);
-	void _move_cursor_left(bool p_select, bool p_move_by_word = false);
-	void _move_cursor_right(bool p_select, bool p_move_by_word = false);
-	void _move_cursor_up(bool p_select);
-	void _move_cursor_down(bool p_select);
-	void _move_cursor_to_line_start(bool p_select);
-	void _move_cursor_to_line_end(bool p_select);
-	void _move_cursor_page_up(bool p_select);
-	void _move_cursor_page_down(bool p_select);
-	void _do_backspace(bool p_word = false, bool p_all_to_left = false);
-	void _delete(bool p_word = false, bool p_all_to_right = false);
-	void _move_cursor_document_start(bool p_select);
-	void _move_cursor_document_end(bool p_select);
+	// Minimap
+	bool draw_minimap = false;
 
-protected:
-	bool highlight_matching_braces_enabled = false;
+	int minimap_width = 80;
+	Point2 minimap_char_size = Point2(1, 2);
+	int minimap_line_spacing = 1;
 
-	struct Cache {
-		Ref<Texture2D> tab_icon;
-		Ref<Texture2D> space_icon;
-		Ref<Texture2D> folded_eol_icon;
-		Ref<StyleBox> style_normal;
-		Ref<StyleBox> style_focus;
-		Ref<StyleBox> style_readonly;
-		Ref<Font> font;
-		int font_size = 16;
-		int outline_size = 0;
-		Color outline_color;
-		Color caret_color;
-		Color caret_background_color;
-		Color font_color;
-		Color font_selected_color;
-		Color font_readonly_color;
-		Color selection_color;
-		Color code_folding_color;
-		Color current_line_color;
-		Color brace_mismatch_color;
-		Color word_highlighted_color;
-		Color search_result_color;
-		Color search_result_border_color;
-		Color background_color;
-
-		int line_spacing = 1;
-		int minimap_width = 0;
-	} cache;
+	// minimap scroll
+	bool minimap_clicked = false;
+	bool dragging_minimap = false;
+	bool can_drag_minimap = false;
 
-	virtual String get_tooltip(const Point2 &p_pos) const override;
+	double minimap_scroll_ratio = 0.0;
+	double minimap_scroll_click_pos = 0.0;
 
-	void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
-	void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
-	virtual void _gui_input(const Ref<InputEvent> &p_gui_input);
-	void _notification(int p_what);
+	void _update_minimap_click();
+	void _update_minimap_drag();
 
-	static void _bind_methods();
+	/* Gutters. */
+	Vector<GutterInfo> gutters;
+	int gutters_width = 0;
+	int gutter_padding = 0;
 
-	bool _set(const StringName &p_name, const Variant &p_value);
-	bool _get(const StringName &p_name, Variant &r_ret) const;
-	void _get_property_list(List<PropertyInfo> *p_list) const;
+	void _update_gutter_width();
 
-	void _set_symbol_lookup_word(const String &p_symbol);
+	/* Syntax highlighting. */
+	Ref<SyntaxHighlighter> syntax_highlighter;
+	Map<int, Dictionary> syntax_highlighting_cache;
 
-public:
-	/* Syntax Highlighting. */
-	Ref<SyntaxHighlighter> get_syntax_highlighter();
-	void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
+	Dictionary _get_line_syntax_highlighting(int p_line);
 
-	/* Gutters. */
-	void add_gutter(int p_at = -1);
-	void remove_gutter(int p_gutter);
-	int get_gutter_count() const;
+	/* Visual. */
+	Ref<StyleBox> style_normal;
+	Ref<StyleBox> style_focus;
+	Ref<StyleBox> style_readonly;
 
-	void set_gutter_name(int p_gutter, const String &p_name);
-	String get_gutter_name(int p_gutter) const;
+	Ref<Texture2D> tab_icon;
+	Ref<Texture2D> space_icon;
 
-	void set_gutter_type(int p_gutter, GutterType p_type);
-	GutterType get_gutter_type(int p_gutter) const;
+	Ref<Font> font;
+	int font_size = 16;
+	Color font_color = Color(1, 1, 1);
+	Color font_readonly_color = Color(1, 1, 1);
 
-	void set_gutter_width(int p_gutter, int p_width);
-	int get_gutter_width(int p_gutter) const;
-	int get_total_gutter_width() const;
+	int outline_size = 0;
+	Color outline_color = Color(1, 1, 1);
 
-	void set_gutter_draw(int p_gutter, bool p_draw);
-	bool is_gutter_drawn(int p_gutter) const;
+	int line_spacing = 1;
 
-	void set_gutter_clickable(int p_gutter, bool p_clickable);
-	bool is_gutter_clickable(int p_gutter) const;
+	Color background_color = Color(1, 1, 1);
+	Color current_line_color = Color(1, 1, 1);
+	Color word_highlighted_color = Color(1, 1, 1);
 
-	void set_gutter_overwritable(int p_gutter, bool p_overwritable);
-	bool is_gutter_overwritable(int p_gutter) const;
+	bool window_has_focus = true;
+	bool first_draw = true;
 
-	void merge_gutters(int p_from_line, int p_to_line);
+	bool highlight_current_line = false;
+	bool highlight_all_occurrences = false;
+	bool draw_control_chars = false;
+	bool draw_tabs = false;
+	bool draw_spaces = false;
 
-	void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback);
+	/*** Super internal Core API. Everything builds on it. ***/
+	bool text_changed_dirty = false;
+	void _text_changed_emit();
 
-	// Line gutters.
-	void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata);
-	Variant get_line_gutter_metadata(int p_line, int p_gutter) const;
+	void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
+	void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
 
-	void set_line_gutter_text(int p_line, int p_gutter, const String &p_text);
-	String get_line_gutter_text(int p_line, int p_gutter) const;
+	void _base_insert_text(int p_line, int p_char, const String &p_text, int &r_end_line, int &r_end_column);
+	String _base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const;
+	void _base_remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
 
-	void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon);
-	Ref<Texture2D> get_line_gutter_icon(int p_line, int p_gutter) const;
+	/* Input actions. */
+	void _swap_current_input_direction();
+	void _new_line(bool p_split_current = true, bool p_above = false);
+	void _move_caret_left(bool p_select, bool p_move_by_word = false);
+	void _move_caret_right(bool p_select, bool p_move_by_word = false);
+	void _move_caret_up(bool p_select);
+	void _move_caret_down(bool p_select);
+	void _move_caret_to_line_start(bool p_select);
+	void _move_caret_to_line_end(bool p_select);
+	void _move_caret_page_up(bool p_select);
+	void _move_caret_page_down(bool p_select);
+	void _do_backspace(bool p_word = false, bool p_all_to_left = false);
+	void _delete(bool p_word = false, bool p_all_to_right = false);
+	void _move_caret_document_start(bool p_select);
+	void _move_caret_document_end(bool p_select);
 
-	void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color);
-	Color get_line_gutter_item_color(int p_line, int p_gutter);
+protected:
+	void _notification(int p_what);
+	virtual void _gui_input(const Ref<InputEvent> &p_gui_input);
 
-	void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable);
-	bool is_line_gutter_clickable(int p_line, int p_gutter) const;
+	static void _bind_methods();
 
-	// Line style
-	void set_line_background_color(int p_line, const Color &p_color);
-	Color get_line_background_color(int p_line);
+	bool _set(const StringName &p_name, const Variant &p_value);
+	bool _get(const StringName &p_name, Variant &r_ret) const;
+	void _get_property_list(List<PropertyInfo> *p_list) const;
 
-	enum MenuItems {
-		MENU_CUT,
-		MENU_COPY,
-		MENU_PASTE,
-		MENU_CLEAR,
-		MENU_SELECT_ALL,
-		MENU_UNDO,
-		MENU_REDO,
-		MENU_DIR_INHERITED,
-		MENU_DIR_AUTO,
-		MENU_DIR_LTR,
-		MENU_DIR_RTL,
-		MENU_DISPLAY_UCC,
-		MENU_INSERT_LRM,
-		MENU_INSERT_RLM,
-		MENU_INSERT_LRE,
-		MENU_INSERT_RLE,
-		MENU_INSERT_LRO,
-		MENU_INSERT_RLO,
-		MENU_INSERT_PDF,
-		MENU_INSERT_ALM,
-		MENU_INSERT_LRI,
-		MENU_INSERT_RLI,
-		MENU_INSERT_FSI,
-		MENU_INSERT_PDI,
-		MENU_INSERT_ZWJ,
-		MENU_INSERT_ZWNJ,
-		MENU_INSERT_WJ,
-		MENU_INSERT_SHY,
-		MENU_MAX
+	/* Internal API for CodeEdit, pending public API. */
+	// brace matching
+	bool highlight_matching_braces_enabled = false;
+	Color brace_mismatch_color;
 
-	};
+	// Line hiding.
+	Color code_folding_color = Color(1, 1, 1);
+	Ref<Texture2D> folded_eol_icon;
 
-	enum SearchFlags {
-		SEARCH_MATCH_CASE = 1,
-		SEARCH_WHOLE_WORDS = 2,
-		SEARCH_BACKWARDS = 4
-	};
+	bool hiding_enabled = false;
 
-	virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+	void _set_hiding_enabled(bool p_enabled);
+	bool _is_hiding_enabled() const;
 
-	Point2 _get_local_mouse_pos() const;
-	void _get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const;
-	void _get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const;
-	bool is_dragging_cursor() const;
+	void _set_line_as_hidden(int p_line, bool p_hidden);
+	bool _is_line_hidden(int p_line) const;
 
-	//void delete_char();
-	//void delete_line();
+	void _unhide_all_lines();
 
-	void begin_complex_operation();
-	void end_complex_operation();
+	// Symbol lookup.
+	String lookup_symbol_word;
+	void _set_symbol_lookup_word(const String &p_symbol);
+
+	/* Text manipulation */
+
+	// Overridable actions
+	virtual void _handle_unicode_input(const uint32_t p_unicode);
+	virtual void _backspace();
+
+	virtual void _cut();
+	virtual void _copy();
+	virtual void _paste();
+
+public:
+	/* General overrides. */
+	virtual Size2 get_minimum_size() const override;
+	virtual bool is_text_field() const override;
+	virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+	virtual String get_tooltip(const Point2 &p_pos) const override;
+	void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
+
+	/* Text */
+	// Text properties.
+	bool has_ime_text() const;
 
-	bool is_insert_text_operation();
+	void set_editable(const bool p_editable);
+	bool is_editable() const;
 
 	void set_text_direction(TextDirection p_text_direction);
 	TextDirection get_text_direction() const;
@@ -592,185 +592,286 @@ public:
 	void set_language(const String &p_language);
 	String get_language() const;
 
-	void set_draw_control_chars(bool p_draw_control_chars);
-	bool get_draw_control_chars() const;
-
 	void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
 	Control::StructuredTextParser get_structured_text_bidi_override() const;
-
 	void set_structured_text_bidi_override_options(Array p_args);
 	Array get_structured_text_bidi_override_options() const;
 
-	void set_text(String p_text);
-	void insert_text_at_cursor(const String &p_text);
-	void insert_at(const String &p_text, int at);
+	void set_tab_size(const int p_size);
+	int get_tab_size() const;
+
+	// User controls
+	void set_overtype_mode_enabled(const bool p_enabled);
+	bool is_overtype_mode_enabled() const;
+
+	void set_context_menu_enabled(bool p_enable);
+	bool is_context_menu_enabled() const;
+
+	void set_shortcut_keys_enabled(bool p_enabled);
+	bool is_shortcut_keys_enabled() const;
+
+	void set_virtual_keyboard_enabled(bool p_enable);
+	bool is_virtual_keyboard_enabled() const;
+
+	// Text manipulation
+	void clear();
+
+	void set_text(const String &p_text);
+	String get_text() const;
 	int get_line_count() const;
-	int get_line_width(int p_line, int p_wrap_offset = -1) const;
-	int get_line_wrap_index_at_col(int p_line, int p_column) const;
-
-	void set_line_as_hidden(int p_line, bool p_hidden);
-	bool is_line_hidden(int p_line) const;
-	void unhide_all_lines();
-	int num_lines_from(int p_line_from, int visible_amount) const;
-	int num_lines_from_rows(int p_line_from, int p_wrap_index_from, int visible_amount, int &wrap_index) const;
-	int get_last_unhidden_line() const;
 
-	String get_text();
-	String get_line(int line) const;
-	bool has_ime_text() const;
-	void set_line(int line, String new_text);
-	int get_row_height() const;
+	void set_line(int p_line, const String &p_new_text);
+	String get_line(int p_line) const;
+
+	int get_line_width(int p_line, int p_wrap_index = -1) const;
+	int get_line_height() const;
 
 	int get_indent_level(int p_line) const;
 	int get_first_non_whitespace_column(int p_line) const;
 
-	inline void set_scroll_pass_end_of_file(bool p_enabled) {
-		scroll_past_end_of_file_enabled = p_enabled;
-		update();
-	}
+	void swap_lines(int p_from_line, int p_to_line);
 
-	void center_viewport_to_cursor();
+	void insert_line_at(int p_at, const String &p_text);
+	void insert_text_at_caret(const String &p_text);
 
-	void set_mid_grapheme_caret_enabled(const bool p_enabled);
-	bool get_mid_grapheme_caret_enabled() const;
+	void remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
 
-	void cursor_set_column(int p_col, bool p_adjust_viewport = true);
-	void cursor_set_line(int p_row, bool p_adjust_viewport = true, bool p_can_be_hidden = true, int p_wrap_index = 0);
+	int get_last_unhidden_line() const;
+	int get_next_visible_line_offset_from(int p_line_from, int p_visible_amount) const;
+	Point2i get_next_visible_line_index_offset_from(int p_line_from, int p_wrap_index_from, int p_visible_amount) const;
 
-	Point2 get_caret_draw_pos() const;
-	bool is_caret_visible() const;
-	int cursor_get_column() const;
-	int cursor_get_line() const;
-	Vector2i _get_cursor_pixel_pos(bool p_adjust_viewport = true);
+	// Overridable actions
+	void handle_unicode_input(const uint32_t p_unicode);
+	void backspace();
 
-	bool cursor_get_blink_enabled() const;
-	void cursor_set_blink_enabled(const bool p_enabled);
+	void cut();
+	void copy();
+	void paste();
 
-	float cursor_get_blink_speed() const;
-	void cursor_set_blink_speed(const float p_speed);
+	// Context menu.
+	PopupMenu *get_menu() const;
+	bool is_menu_visible() const;
+	void menu_option(int p_option);
 
-	void cursor_set_block_mode(const bool p_enable);
-	bool cursor_is_block_mode() const;
+	/* Versioning */
+	void begin_complex_operation();
+	void end_complex_operation();
 
-	void set_right_click_moves_caret(bool p_enable);
-	bool is_right_click_moving_caret() const;
+	void undo();
+	void redo();
+	void clear_undo_history();
 
-	SelectionMode get_selection_mode() const;
-	void set_selection_mode(SelectionMode p_mode, int p_line = -1, int p_column = -1);
-	int get_selection_line() const;
-	int get_selection_column() const;
+	bool is_insert_text_operation() const;
 
-	void set_readonly(bool p_readonly);
-	bool is_readonly() const;
+	void tag_saved_version();
 
-	void set_wrap_enabled(bool p_wrap_enabled);
-	bool is_wrap_enabled() const;
-	bool line_wraps(int line) const;
-	int times_line_wraps(int line) const;
+	uint32_t get_version() const;
+	uint32_t get_saved_version() const;
 
-	void clear();
+	/* Search */
+	void set_search_text(const String &p_search_text);
+	void set_search_flags(uint32_t p_flags);
 
-	void delete_selection();
+	Point2i search(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const;
+
+	/* Mouse */
+	Point2 get_local_mouse_pos() const;
+
+	String get_word_at_pos(const Vector2 &p_pos) const;
+
+	Point2i get_line_column_at_pos(const Point2i &p_pos) const;
+	int get_minimap_line_at_pos(const Point2i &p_pos) const;
+
+	bool is_dragging_cursor() const;
+
+	/* Caret */
+	void set_caret_type(CaretType p_type);
+	CaretType get_caret_type() const;
+
+	void set_caret_blink_enabled(const bool p_enabled);
+	bool is_caret_blink_enabled() const;
+
+	void set_caret_blink_speed(const float p_speed);
+	float get_caret_blink_speed() const;
+
+	void set_move_caret_on_right_click_enabled(const bool p_enable);
+	bool is_move_caret_on_right_click_enabled() const;
+
+	void set_caret_mid_grapheme_enabled(const bool p_enabled);
+	bool is_caret_mid_grapheme_enabled() const;
+
+	bool is_caret_visible() const;
+	Point2 get_caret_draw_pos() const;
+
+	void set_caret_line(int p_line, bool p_adjust_viewport = true, bool p_can_be_hidden = true, int p_wrap_index = 0);
+	int get_caret_line() const;
+
+	void set_caret_column(int p_col, bool p_adjust_viewport = true);
+	int get_caret_column() const;
+
+	int get_caret_wrap_index() const;
+
+	String get_word_under_caret() const;
+
+	/* Selection. */
+	void set_selecting_enabled(const bool p_enabled);
+	bool is_selecting_enabled() const;
+
+	void set_override_selected_font_color(bool p_override_selected_font_color);
+	bool is_overriding_selected_font_color() const;
+
+	void set_selection_mode(SelectionMode p_mode, int p_line = -1, int p_column = -1);
+	SelectionMode get_selection_mode() const;
 
-	virtual void handle_unicode_input(uint32_t p_unicode);
-	virtual void backspace();
-	void cut();
-	void copy();
-	void paste();
 	void select_all();
 	void select_word_under_caret();
 	void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
-	void deselect();
-	void swap_lines(int line1, int line2);
 
-	void set_search_text(const String &p_search_text);
-	void set_search_flags(uint32_t p_flags);
-	void set_current_search_result(int line, int col);
+	bool has_selection() const;
+
+	String get_selected_text() const;
+
+	int get_selection_line() const;
+	int get_selection_column() const;
 
-	void set_highlight_all_occurrences(const bool p_enabled);
-	bool is_highlight_all_occurrences_enabled() const;
-	bool is_selection_active() const;
 	int get_selection_from_line() const;
 	int get_selection_from_column() const;
 	int get_selection_to_line() const;
 	int get_selection_to_column() const;
-	String get_selection_text() const;
 
-	String get_word_under_cursor() const;
-	String get_word_at_pos(const Vector2 &p_pos) const;
+	void deselect();
+	void delete_selection();
 
-	bool search(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column, int &r_line, int &r_column) const;
+	/* line wrapping. */
+	void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode);
+	LineWrappingMode get_line_wrapping_mode() const;
 
-	void undo();
-	void redo();
-	void clear_undo_history();
+	bool is_line_wrapped(int p_line) const;
+	int get_line_wrap_count(int p_line) const;
+	int get_line_wrap_index_at_column(int p_line, int p_column) const;
 
-	void set_tab_size(const int p_size);
-	int get_tab_size() const;
-	void set_draw_tabs(bool p_draw);
-	bool is_drawing_tabs() const;
-	void set_draw_spaces(bool p_draw);
-	bool is_drawing_spaces() const;
-	void set_override_selected_font_color(bool p_override_selected_font_color);
-	bool is_overriding_selected_font_color() const;
+	Vector<String> get_line_wrapped_text(int p_line) const;
 
-	void set_insert_mode(bool p_enabled);
-	bool is_insert_mode() const;
+	/* Viewport. */
+	// Scrolling.
+	void set_smooth_scroll_enabled(const bool p_enable);
+	bool is_smooth_scroll_enabled() const;
+
+	void set_scroll_past_end_of_file_enabled(const bool p_enabled);
+	bool is_scroll_past_end_of_file_enabled() const;
 
-	double get_v_scroll() const;
 	void set_v_scroll(double p_scroll);
+	double get_v_scroll() const;
 
-	int get_h_scroll() const;
 	void set_h_scroll(int p_scroll);
-
-	void set_smooth_scroll_enabled(bool p_enable);
-	bool is_smooth_scroll_enabled() const;
+	int get_h_scroll() const;
 
 	void set_v_scroll_speed(float p_speed);
 	float get_v_scroll_speed() const;
 
-	uint32_t get_version() const;
-	uint32_t get_saved_version() const;
-	void tag_saved_version();
+	double get_scroll_pos_for_line(int p_line, int p_wrap_index = 0) const;
 
-	void menu_option(int p_option);
+	// Visible lines.
+	void set_line_as_first_visible(int p_line, int p_wrap_index = 0);
+	int get_first_visible_line() const;
 
-	void set_highlight_current_line(bool p_enabled);
-	bool is_highlight_current_line_enabled() const;
+	void set_line_as_center_visible(int p_line, int p_wrap_index = 0);
+
+	void set_line_as_last_visible(int p_line, int p_wrap_index = 0);
+	int get_last_full_visible_line() const;
+	int get_last_full_visible_line_wrap_index() const;
 
+	int get_visible_line_count() const;
+	int get_total_visible_line_count() const;
+
+	// Auto Adjust
+	void adjust_viewport_to_caret();
+	void center_viewport_to_caret();
+
+	// Minimap
 	void set_draw_minimap(bool p_draw);
 	bool is_drawing_minimap() const;
 
 	void set_minimap_width(int p_minimap_width);
 	int get_minimap_width() const;
 
-	void set_hiding_enabled(bool p_enabled);
-	bool is_hiding_enabled() const;
+	int get_minimap_visible_lines() const;
 
-	void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
+	/* Gutters. */
+	void add_gutter(int p_at = -1);
+	void remove_gutter(int p_gutter);
+	int get_gutter_count() const;
 
-	void set_context_menu_enabled(bool p_enable);
-	bool is_context_menu_enabled();
+	void set_gutter_name(int p_gutter, const String &p_name);
+	String get_gutter_name(int p_gutter) const;
 
-	void set_selecting_enabled(bool p_enabled);
-	bool is_selecting_enabled() const;
+	void set_gutter_type(int p_gutter, GutterType p_type);
+	GutterType get_gutter_type(int p_gutter) const;
 
-	void set_shortcut_keys_enabled(bool p_enabled);
-	bool is_shortcut_keys_enabled() const;
+	void set_gutter_width(int p_gutter, int p_width);
+	int get_gutter_width(int p_gutter) const;
+	int get_total_gutter_width() const;
 
-	void set_virtual_keyboard_enabled(bool p_enable);
-	bool is_virtual_keyboard_enabled() const;
+	void set_gutter_draw(int p_gutter, bool p_draw);
+	bool is_gutter_drawn(int p_gutter) const;
 
-	bool is_menu_visible() const;
-	PopupMenu *get_menu() const;
+	void set_gutter_clickable(int p_gutter, bool p_clickable);
+	bool is_gutter_clickable(int p_gutter) const;
+
+	void set_gutter_overwritable(int p_gutter, bool p_overwritable);
+	bool is_gutter_overwritable(int p_gutter) const;
+
+	void merge_gutters(int p_from_line, int p_to_line);
+
+	void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback);
+
+	// Line gutters.
+	void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata);
+	Variant get_line_gutter_metadata(int p_line, int p_gutter) const;
+
+	void set_line_gutter_text(int p_line, int p_gutter, const String &p_text);
+	String get_line_gutter_text(int p_line, int p_gutter) const;
+
+	void set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2D> &p_icon);
+	Ref<Texture2D> get_line_gutter_icon(int p_line, int p_gutter) const;
+
+	void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color);
+	Color get_line_gutter_item_color(int p_line, int p_gutter) const;
+
+	void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable);
+	bool is_line_gutter_clickable(int p_line, int p_gutter) const;
+
+	// Line style
+	void set_line_background_color(int p_line, const Color &p_color);
+	Color get_line_background_color(int p_line) const;
+
+	/* Syntax Highlighting. */
+	void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
+	Ref<SyntaxHighlighter> get_syntax_highlighter() const;
+
+	/* Visual. */
+	void set_highlight_current_line(bool p_enabled);
+	bool is_highlight_current_line_enabled() const;
+
+	void set_highlight_all_occurrences(const bool p_enabled);
+	bool is_highlight_all_occurrences_enabled() const;
+
+	void set_draw_control_chars(bool p_draw_control_chars);
+	bool get_draw_control_chars() const;
+
+	void set_draw_tabs(bool p_draw);
+	bool is_drawing_tabs() const;
+
+	void set_draw_spaces(bool p_draw);
+	bool is_drawing_spaces() const;
 
-	virtual bool is_text_field() const override;
 	TextEdit();
-	~TextEdit();
 };
 
-VARIANT_ENUM_CAST(TextEdit::GutterType);
+VARIANT_ENUM_CAST(TextEdit::CaretType);
+VARIANT_ENUM_CAST(TextEdit::LineWrappingMode);
 VARIANT_ENUM_CAST(TextEdit::SelectionMode);
+VARIANT_ENUM_CAST(TextEdit::GutterType);
 VARIANT_ENUM_CAST(TextEdit::MenuItems);
 VARIANT_ENUM_CAST(TextEdit::SearchFlags);
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä