Browse Source

Documentation search fixes

Updates rich_text_label so that the built-in documentation can be searched
Previously, it would only find the first result and would not select other results
Renames "_entered" functions to "_submitted"
Gregory Basile 4 years ago
parent
commit
8ab13f8ace
50 changed files with 219 additions and 133 deletions
  1. 7 1
      core/input/input_map.cpp
  2. 3 3
      doc/classes/Expression.xml
  3. 1 1
      doc/classes/LineEdit.xml
  4. 2 0
      doc/classes/ProjectSettings.xml
  5. 3 3
      doc/translations/classes.pot
  6. 1 1
      editor/action_map_editor.cpp
  7. 2 2
      editor/animation_track_editor.cpp
  8. 1 1
      editor/animation_track_editor.h
  9. 4 4
      editor/code_editor.cpp
  10. 2 2
      editor/code_editor.h
  11. 2 2
      editor/connections_dialog.cpp
  12. 1 1
      editor/connections_dialog.h
  13. 1 1
      editor/editor_audio_buses.cpp
  14. 3 3
      editor/editor_autoload_settings.cpp
  15. 1 1
      editor/editor_autoload_settings.h
  16. 4 4
      editor/editor_file_dialog.cpp
  17. 2 2
      editor/editor_file_dialog.h
  18. 3 6
      editor/editor_help.cpp
  19. 1 1
      editor/editor_help.h
  20. 3 3
      editor/editor_properties.cpp
  21. 1 1
      editor/editor_properties.h
  22. 3 3
      editor/editor_spin_slider.cpp
  23. 1 1
      editor/editor_spin_slider.h
  24. 1 1
      editor/filesystem_dock.cpp
  25. 4 4
      editor/find_in_files.cpp
  26. 2 2
      editor/find_in_files.h
  27. 2 2
      editor/groups_editor.cpp
  28. 1 1
      editor/plugins/animation_blend_tree_editor_plugin.cpp
  29. 1 1
      editor/plugins/animation_player_editor_plugin.cpp
  30. 1 1
      editor/plugins/animation_state_machine_editor.cpp
  31. 1 1
      editor/plugins/asset_library_editor_plugin.h
  32. 5 5
      editor/plugins/visual_shader_editor_plugin.cpp
  33. 1 1
      editor/plugins/visual_shader_editor_plugin.h
  34. 5 5
      editor/project_export.cpp
  35. 1 1
      editor/property_editor.cpp
  36. 6 6
      editor/script_create_dialog.cpp
  37. 1 1
      editor/script_create_dialog.h
  38. 3 3
      scene/gui/color_picker.cpp
  39. 1 1
      scene/gui/color_picker.h
  40. 2 2
      scene/gui/dialogs.cpp
  41. 1 1
      scene/gui/dialogs.h
  42. 5 5
      scene/gui/file_dialog.cpp
  43. 2 2
      scene/gui/file_dialog.h
  44. 4 4
      scene/gui/line_edit.cpp
  45. 106 26
      scene/gui/rich_text_label.cpp
  46. 2 1
      scene/gui/rich_text_label.h
  47. 4 4
      scene/gui/spin_box.cpp
  48. 1 1
      scene/gui/spin_box.h
  49. 3 3
      scene/gui/tree.cpp
  50. 1 1
      scene/gui/tree.h

+ 7 - 1
core/input/input_map.cpp

@@ -353,8 +353,9 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
     { "ui_text_scroll_down",                           TTRC("Scroll Down") },
     { "ui_text_scroll_down.OSX",                       TTRC("Scroll Down") },
     { "ui_text_select_all",                            TTRC("Select All") },
-    { "ui_text_select_word_under_caret",              TTRC("Select Word Under Caret") },
+    { "ui_text_select_word_under_caret",               TTRC("Select Word Under Caret") },
     { "ui_text_toggle_insert_mode",                    TTRC("Toggle Insert Mode") },
+    { "ui_text_submit",                                TTRC("Text Submitted") },
     { "ui_graph_duplicate",                            TTRC("Duplicate Nodes") },
     { "ui_graph_delete",                               TTRC("Delete Nodes") },
     { "ui_filedialog_up_one_level",                    TTRC("Go Up One Level") },
@@ -668,6 +669,11 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
 	inputs.push_back(InputEventKey::create_reference(KEY_MENU));
 	default_builtin_cache.insert("ui_menu", inputs);
 
+	inputs = List<Ref<InputEvent>>();
+	inputs.push_back(InputEventKey::create_reference(KEY_ENTER));
+	inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER));
+	default_builtin_cache.insert("ui_text_submit", inputs);
+
 	// ///// UI Graph Shortcuts /////
 
 	inputs = List<Ref<InputEvent>>();

+ 3 - 3
doc/classes/Expression.xml

@@ -12,9 +12,9 @@
 		var expression = Expression.new()
 
 		func _ready():
-		    $LineEdit.connect("text_entered", self, "_on_text_entered")
+		    $LineEdit.connect("text_submitted", self, "_on_text_submitted")
 
-		func _on_text_entered(command):
+		func _on_text_submitted(command):
 		    var error = expression.parse(command)
 		    if error != OK:
 		        print(expression.get_error_text())
@@ -28,7 +28,7 @@
 
 		public override void _Ready()
 		{
-		    GetNode("LineEdit").Connect("text_entered", this, nameof(OnTextEntered));
+		    GetNode("LineEdit").Connect("text_submitted", this, nameof(OnTextEntered));
 		}
 
 		private void OnTextEntered(string command)

+ 1 - 1
doc/classes/LineEdit.xml

@@ -248,7 +248,7 @@
 				Emitted when the text changes.
 			</description>
 		</signal>
-		<signal name="text_entered">
+		<signal name="text_submitted">
 			<argument index="0" name="new_text" type="String">
 			</argument>
 			<description>

+ 2 - 0
doc/classes/ProjectSettings.xml

@@ -739,6 +739,8 @@
 			If no selection is currently active, selects the word currently under the caret in text fields. If a selection is currently active, deselects the current selection.
 			[b]Note:[/b] Currently, this is only implemented in [TextEdit], not [LineEdit].
 		</member>
+		<member name="input/ui_text_submit" type="Dictionary" setter="" getter="">
+		</member>
 		<member name="input/ui_text_toggle_insert_mode" type="Dictionary" setter="" getter="">
 		</member>
 		<member name="input/ui_undo" type="Dictionary" setter="" getter="">

+ 3 - 3
doc/translations/classes.pot

@@ -20685,9 +20685,9 @@ msgid ""
 "onready var expression = Expression.new()\n"
 "\n"
 "func _ready():\n"
-"    $LineEdit.connect(\"text_entered\", self, \"_on_text_entered\")\n"
+"    $LineEdit.connect(\"text_submitted\", self, \"_on_text_submitted\")\n"
 "\n"
-"func _on_text_entered(command):\n"
+"func _on_text_submitted(command):\n"
 "    var error = expression.parse(command, [])\n"
 "    if error != OK:\n"
 "        print(expression.get_error_text())\n"
@@ -33187,7 +33187,7 @@ msgid ""
 "Examples:\n"
 "[codeblock]\n"
 "connect(\"pressed\", self, \"_on_Button_pressed\") # BaseButton signal\n"
-"connect(\"text_entered\", self, \"_on_LineEdit_text_entered\") # LineEdit "
+"connect(\"text_submitted\", self, \"_on_LineEdit_text_submitted\") # LineEdit "
 "signal\n"
 "connect(\"hit\", self, \"_on_Player_hit\", [ weapon_type, damage ]) # User-"
 "defined signal\n"

+ 1 - 1
editor/action_map_editor.cpp

@@ -1106,7 +1106,7 @@ ActionMapEditor::ActionMapEditor() {
 	add_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	add_edit->set_placeholder(TTR("Add New Action"));
 	add_edit->set_clear_button_enabled(true);
-	add_edit->connect("text_entered", callable_mp(this, &ActionMapEditor::_add_action));
+	add_edit->connect("text_submitted", callable_mp(this, &ActionMapEditor::_add_action));
 	add_hbox->add_child(add_edit);
 
 	Button *add_button = memnew(Button);

+ 2 - 2
editor/animation_track_editor.cpp

@@ -2380,7 +2380,7 @@ void AnimationTrackEdit::_zoom_changed() {
 	play_position->update();
 }
 
-void AnimationTrackEdit::_path_entered(const String &p_text) {
+void AnimationTrackEdit::_path_submitted(const String &p_text) {
 	undo_redo->create_action(TTR("Change Track Path"));
 	undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text);
 	undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track));
@@ -2755,7 +2755,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
 			path = memnew(LineEdit);
 			path_popup->add_child(path);
 			path->set_anchors_and_offsets_preset(PRESET_WIDE);
-			path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered));
+			path->connect("text_submitted", callable_mp(this, &AnimationTrackEdit::_path_submitted));
 		}
 
 		path->set_text(animation->track_get_path(track));

+ 1 - 1
editor/animation_track_editor.h

@@ -177,7 +177,7 @@ class AnimationTrackEdit : public Control {
 
 	void _menu_selected(int p_index);
 
-	void _path_entered(const String &p_text);
+	void _path_submitted(const String &p_text);
 	void _play_position_draw();
 	bool _is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const;
 

+ 4 - 4
editor/code_editor.cpp

@@ -539,7 +539,7 @@ void FindReplaceBar::_search_text_changed(const String &p_text) {
 	search_current();
 }
 
-void FindReplaceBar::_search_text_entered(const String &p_text) {
+void FindReplaceBar::_search_text_submitted(const String &p_text) {
 	if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
 		search_prev();
 	} else {
@@ -547,7 +547,7 @@ void FindReplaceBar::_search_text_entered(const String &p_text) {
 	}
 }
 
-void FindReplaceBar::_replace_text_entered(const String &p_text) {
+void FindReplaceBar::_replace_text_submitted(const String &p_text) {
 	if (selection_only->is_pressed() && text_editor->is_selection_active()) {
 		_replace_all();
 		_hide_bar();
@@ -643,7 +643,7 @@ FindReplaceBar::FindReplaceBar() {
 	vbc_lineedit->add_child(search_text);
 	search_text->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
 	search_text->connect("text_changed", callable_mp(this, &FindReplaceBar::_search_text_changed));
-	search_text->connect("text_entered", callable_mp(this, &FindReplaceBar::_search_text_entered));
+	search_text->connect("text_submitted", callable_mp(this, &FindReplaceBar::_search_text_submitted));
 
 	matches_label = memnew(Label);
 	hbc_button_search->add_child(matches_label);
@@ -677,7 +677,7 @@ FindReplaceBar::FindReplaceBar() {
 	replace_text = memnew(LineEdit);
 	vbc_lineedit->add_child(replace_text);
 	replace_text->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
-	replace_text->connect("text_entered", callable_mp(this, &FindReplaceBar::_replace_text_entered));
+	replace_text->connect("text_submitted", callable_mp(this, &FindReplaceBar::_replace_text_submitted));
 
 	replace = memnew(Button);
 	hbc_button_replace->add_child(replace);

+ 2 - 2
editor/code_editor.h

@@ -99,8 +99,8 @@ class FindReplaceBar : public HBoxContainer {
 	void _editor_text_changed();
 	void _search_options_changed(bool p_pressed);
 	void _search_text_changed(const String &p_text);
-	void _search_text_entered(const String &p_text);
-	void _replace_text_entered(const String &p_text);
+	void _search_text_submitted(const String &p_text);
+	void _replace_text_submitted(const String &p_text);
 	void _update_size();
 
 protected:

+ 2 - 2
editor/connections_dialog.cpp

@@ -146,7 +146,7 @@ void ConnectDialog::_item_activated() {
 	_ok_pressed(); // From AcceptDialog.
 }
 
-void ConnectDialog::_text_entered(const String &p_text) {
+void ConnectDialog::_text_submitted(const String &p_text) {
 	_ok_pressed(); // From AcceptDialog.
 }
 
@@ -471,7 +471,7 @@ ConnectDialog::ConnectDialog() {
 
 	dst_method = memnew(LineEdit);
 	dst_method->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	dst_method->connect("text_entered", callable_mp(this, &ConnectDialog::_text_entered));
+	dst_method->connect("text_submitted", callable_mp(this, &ConnectDialog::_text_submitted));
 	dstm_hb->add_child(dst_method);
 
 	advanced = memnew(CheckButton);

+ 1 - 1
editor/connections_dialog.h

@@ -105,7 +105,7 @@ private:
 	void ok_pressed() override;
 	void _cancel_pressed();
 	void _item_activated();
-	void _text_entered(const String &_text);
+	void _text_submitted(const String &_text);
 	void _tree_node_selected();
 	void _add_bind();
 	void _remove_bind();

+ 1 - 1
editor/editor_audio_buses.cpp

@@ -782,7 +782,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
 	set_v_size_flags(SIZE_EXPAND_FILL);
 
 	track_name = memnew(LineEdit);
-	track_name->connect("text_entered", callable_mp(this, &EditorAudioBus::_name_changed));
+	track_name->connect("text_submitted", callable_mp(this, &EditorAudioBus::_name_changed));
 	track_name->connect("focus_exited", callable_mp(this, &EditorAudioBus::_name_focus_exit));
 	vb->add_child(track_name);
 

+ 3 - 3
editor/editor_autoload_settings.cpp

@@ -327,7 +327,7 @@ void EditorAutoloadSettings::_autoload_file_callback(const String &p_path) {
 	add_autoload->set_disabled(false);
 }
 
-void EditorAutoloadSettings::_autoload_text_entered(const String p_name) {
+void EditorAutoloadSettings::_autoload_text_submitted(const String p_name) {
 	if (autoload_add_path->get_text() != "" && _autoload_name_is_valid(p_name, nullptr)) {
 		_autoload_add();
 	}
@@ -859,7 +859,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
 
 	autoload_add_name = memnew(LineEdit);
 	autoload_add_name->set_h_size_flags(SIZE_EXPAND_FILL);
-	autoload_add_name->connect("text_entered", callable_mp(this, &EditorAutoloadSettings::_autoload_text_entered));
+	autoload_add_name->connect("text_submitted", callable_mp(this, &EditorAutoloadSettings::_autoload_text_submitted));
 	autoload_add_name->connect("text_changed", callable_mp(this, &EditorAutoloadSettings::_autoload_text_changed));
 	hbc->add_child(autoload_add_name);
 
@@ -916,7 +916,7 @@ EditorAutoloadSettings::~EditorAutoloadSettings() {
 
 void EditorAutoloadSettings::_set_autoload_add_path(const String &p_text) {
 	autoload_add_path->set_text(p_text);
-	autoload_add_path->emit_signal("text_entered", p_text);
+	autoload_add_path->emit_signal("text_submitted", p_text);
 }
 
 void EditorAutoloadSettings::_browse_autoload_add_path() {

+ 1 - 1
editor/editor_autoload_settings.h

@@ -81,7 +81,7 @@ class EditorAutoloadSettings : public VBoxContainer {
 	void _autoload_button_pressed(Object *p_item, int p_column, int p_button);
 	void _autoload_activated();
 	void _autoload_path_text_changed(const String p_path);
-	void _autoload_text_entered(const String p_name);
+	void _autoload_text_submitted(const String p_name);
 	void _autoload_text_changed(const String p_name);
 	void _autoload_open(const String &fpath);
 	void _autoload_file_callback(const String &p_path);

+ 4 - 4
editor/editor_file_dialog.cpp

@@ -230,14 +230,14 @@ void EditorFileDialog::update_dir() {
 	}
 }
 
-void EditorFileDialog::_dir_entered(String p_dir) {
+void EditorFileDialog::_dir_submitted(String p_dir) {
 	dir_access->change_dir(p_dir);
 	invalidate();
 	update_dir();
 	_push_history();
 }
 
-void EditorFileDialog::_file_entered(const String &p_file) {
+void EditorFileDialog::_file_submitted(const String &p_file) {
 	_action_pressed();
 }
 
@@ -1676,8 +1676,8 @@ EditorFileDialog::EditorFileDialog() {
 	item_list->connect("multi_selected", callable_mp(this, &EditorFileDialog::_multi_selected), varray(), CONNECT_DEFERRED);
 	item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected), varray());
 	item_list->connect("nothing_selected", callable_mp(this, &EditorFileDialog::_items_clear_selection));
-	dir->connect("text_entered", callable_mp(this, &EditorFileDialog::_dir_entered));
-	file->connect("text_entered", callable_mp(this, &EditorFileDialog::_file_entered));
+	dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted));
+	file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted));
 	filter->connect("item_selected", callable_mp(this, &EditorFileDialog::_filter_selected));
 
 	confirm_save = memnew(ConfirmationDialog);

+ 2 - 2
editor/editor_file_dialog.h

@@ -167,8 +167,8 @@ private:
 	void _item_menu_id_pressed(int p_option);
 
 	void _select_drive(int p_idx);
-	void _dir_entered(String p_dir);
-	void _file_entered(const String &p_file);
+	void _dir_submitted(String p_dir);
+	void _file_submitted(const String &p_file);
 	void _action_pressed();
 	void _save_confirm_pressed();
 	void _cancel_pressed();

+ 3 - 6
editor/editor_help.cpp

@@ -1761,7 +1761,7 @@ FindBar::FindBar() {
 	search_text->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
 	search_text->set_h_size_flags(SIZE_EXPAND_FILL);
 	search_text->connect("text_changed", callable_mp(this, &FindBar::_search_text_changed));
-	search_text->connect("text_entered", callable_mp(this, &FindBar::_search_text_entered));
+	search_text->connect("text_submitted", callable_mp(this, &FindBar::_search_text_submitted));
 
 	matches_label = memnew(Label);
 	add_child(matches_label);
@@ -1849,9 +1849,6 @@ bool FindBar::_search(bool p_search_previous) {
 	bool keep = prev_search == stext;
 
 	bool ret = rich_text_label->search(stext, keep, p_search_previous);
-	if (!ret) {
-		ret = rich_text_label->search(stext, false, p_search_previous);
-	}
 
 	prev_search = stext;
 
@@ -1878,7 +1875,7 @@ void FindBar::_update_results_count() {
 	int from_pos = 0;
 
 	while (true) {
-		int pos = full_text.find(searched, from_pos);
+		int pos = full_text.findn(searched, from_pos);
 		if (pos == -1) {
 			break;
 		}
@@ -1935,7 +1932,7 @@ void FindBar::_search_text_changed(const String &p_text) {
 	search_next();
 }
 
-void FindBar::_search_text_entered(const String &p_text) {
+void FindBar::_search_text_submitted(const String &p_text) {
 	if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
 		search_prev();
 	} else {

+ 1 - 1
editor/editor_help.h

@@ -61,7 +61,7 @@ class FindBar : public HBoxContainer {
 	void _hide_bar();
 
 	void _search_text_changed(const String &p_text);
-	void _search_text_entered(const String &p_text);
+	void _search_text_submitted(const String &p_text);
 
 	void _update_results_count();
 	void _update_matches_label();

+ 3 - 3
editor/editor_properties.cpp

@@ -51,7 +51,7 @@ EditorPropertyNil::EditorPropertyNil() {
 
 ///////////////////// TEXT /////////////////////////
 
-void EditorPropertyText::_text_entered(const String &p_string) {
+void EditorPropertyText::_text_submitted(const String &p_string) {
 	if (updating) {
 		return;
 	}
@@ -100,7 +100,7 @@ EditorPropertyText::EditorPropertyText() {
 	add_child(text);
 	add_focusable(text);
 	text->connect("text_changed", callable_mp(this, &EditorPropertyText::_text_changed));
-	text->connect("text_entered", callable_mp(this, &EditorPropertyText::_text_entered));
+	text->connect("text_submitted", callable_mp(this, &EditorPropertyText::_text_submitted));
 
 	string_name = false;
 	updating = false;
@@ -297,7 +297,7 @@ EditorPropertyPath::EditorPropertyPath() {
 	path = memnew(LineEdit);
 	path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
 	path_hb->add_child(path);
-	path->connect("text_entered", callable_mp(this, &EditorPropertyPath::_path_selected));
+	path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected));
 	path->connect("focus_exited", callable_mp(this, &EditorPropertyPath::_path_focus_exited));
 	path->set_h_size_flags(SIZE_EXPAND_FILL);
 

+ 1 - 1
editor/editor_properties.h

@@ -56,7 +56,7 @@ class EditorPropertyText : public EditorProperty {
 	bool updating;
 	bool string_name;
 	void _text_changed(const String &p_string);
-	void _text_entered(const String &p_string);
+	void _text_submitted(const String &p_string);
 
 protected:
 	static void _bind_methods();

+ 3 - 3
editor/editor_spin_slider.cpp

@@ -386,8 +386,8 @@ void EditorSpinSlider::_evaluate_input_text() {
 	set_value(v);
 }
 
-//text_entered signal
-void EditorSpinSlider::_value_input_entered(const String &p_text) {
+//text_submitted signal
+void EditorSpinSlider::_value_input_submitted(const String &p_text) {
 	value_input_just_closed = true;
 	value_input_popup->hide();
 }
@@ -510,7 +510,7 @@ EditorSpinSlider::EditorSpinSlider() {
 	value_input_popup->set_wrap_controls(true);
 	value_input->set_anchors_and_offsets_preset(PRESET_WIDE);
 	value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
-	value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered));
+	value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
 	value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
 	value_input_just_closed = false;
 	hide_slider = false;

+ 1 - 1
editor/editor_spin_slider.h

@@ -68,7 +68,7 @@ class EditorSpinSlider : public Range {
 
 	void _grabber_gui_input(const Ref<InputEvent> &p_event);
 	void _value_input_closed();
-	void _value_input_entered(const String &);
+	void _value_input_submitted(const String &);
 	void _value_focus_exited();
 	bool hide_slider;
 	bool flat;

+ 1 - 1
editor/filesystem_dock.cpp

@@ -365,7 +365,7 @@ void FileSystemDock::_notification(int p_what) {
 			file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option));
 			tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option));
 
-			current_path->connect("text_entered", callable_mp(this, &FileSystemDock::_navigate_to_path), make_binds(false));
+			current_path->connect("text_submitted", callable_mp(this, &FileSystemDock::_navigate_to_path), make_binds(false));
 
 			always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
 

+ 4 - 4
editor/find_in_files.cpp

@@ -311,7 +311,7 @@ FindInFilesDialog::FindInFilesDialog() {
 	_search_text_line_edit = memnew(LineEdit);
 	_search_text_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	_search_text_line_edit->connect("text_changed", callable_mp(this, &FindInFilesDialog::_on_search_text_modified));
-	_search_text_line_edit->connect("text_entered", callable_mp(this, &FindInFilesDialog::_on_search_text_entered));
+	_search_text_line_edit->connect("text_submitted", callable_mp(this, &FindInFilesDialog::_on_search_text_submitted));
 	gc->add_child(_search_text_line_edit);
 
 	_replace_label = memnew(Label);
@@ -321,7 +321,7 @@ FindInFilesDialog::FindInFilesDialog() {
 
 	_replace_text_line_edit = memnew(LineEdit);
 	_replace_text_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	_replace_text_line_edit->connect("text_entered", callable_mp(this, &FindInFilesDialog::_on_replace_text_entered));
+	_replace_text_line_edit->connect("text_submitted", callable_mp(this, &FindInFilesDialog::_on_replace_text_submitted));
 	_replace_text_line_edit->hide();
 	gc->add_child(_replace_text_line_edit);
 
@@ -503,7 +503,7 @@ void FindInFilesDialog::_on_search_text_modified(String text) {
 	_replace_button->set_disabled(get_search_text().is_empty());
 }
 
-void FindInFilesDialog::_on_search_text_entered(String text) {
+void FindInFilesDialog::_on_search_text_submitted(String text) {
 	// This allows to trigger a global search without leaving the keyboard
 	if (!_find_button->is_disabled()) {
 		if (_mode == SEARCH_MODE) {
@@ -518,7 +518,7 @@ void FindInFilesDialog::_on_search_text_entered(String text) {
 	}
 }
 
-void FindInFilesDialog::_on_replace_text_entered(String text) {
+void FindInFilesDialog::_on_replace_text_submitted(String text) {
 	// This allows to trigger a global search without leaving the keyboard
 	if (!_replace_button->is_disabled()) {
 		if (_mode == REPLACE_MODE) {

+ 2 - 2
editor/find_in_files.h

@@ -128,8 +128,8 @@ private:
 	void _on_folder_button_pressed();
 	void _on_folder_selected(String path);
 	void _on_search_text_modified(String text);
-	void _on_search_text_entered(String text);
-	void _on_replace_text_entered(String text);
+	void _on_search_text_submitted(String text);
+	void _on_replace_text_submitted(String text);
 
 	FindInFilesMode _mode;
 	LineEdit *_search_text_line_edit;

+ 2 - 2
editor/groups_editor.cpp

@@ -446,7 +446,7 @@ GroupDialog::GroupDialog() {
 	add_group_text = memnew(LineEdit);
 	chbc->add_child(add_group_text);
 	add_group_text->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	add_group_text->connect("text_entered", callable_mp(this, &GroupDialog::_add_group_pressed));
+	add_group_text->connect("text_submitted", callable_mp(this, &GroupDialog::_add_group_pressed));
 
 	Button *add_group_button = memnew(Button);
 	add_group_button->set_text(TTR("Add"));
@@ -689,7 +689,7 @@ GroupsEditor::GroupsEditor() {
 	group_name = memnew(LineEdit);
 	group_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	hbc->add_child(group_name);
-	group_name->connect("text_entered", callable_mp(this, &GroupsEditor::_add_group));
+	group_name->connect("text_submitted", callable_mp(this, &GroupsEditor::_add_group));
 
 	add = memnew(Button);
 	add->set_text(TTR("Add"));

+ 1 - 1
editor/plugins/animation_blend_tree_editor_plugin.cpp

@@ -139,7 +139,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
 			name->set_expand_to_text_length_enabled(true);
 			node->add_child(name);
 			node->set_slot(0, false, 0, Color(), true, 0, get_theme_color("font_color", "Label"));
-			name->connect("text_entered", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED);
+			name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED);
 			name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED);
 			base = 1;
 			node->set_show_close_button(true);

+ 1 - 1
editor/plugins/animation_player_editor_plugin.cpp

@@ -1694,7 +1694,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
 
 	file->connect("file_selected", callable_mp(this, &AnimationPlayerEditor::_dialog_action));
 	frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false));
-	scale->connect("text_entered", callable_mp(this, &AnimationPlayerEditor::_scale_changed));
+	scale->connect("text_submitted", callable_mp(this, &AnimationPlayerEditor::_scale_changed));
 
 	renaming = false;
 	last_active = false;

+ 1 - 1
editor/plugins/animation_state_machine_editor.cpp

@@ -1329,7 +1329,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
 	name_edit = memnew(LineEdit);
 	name_edit_popup->add_child(name_edit);
 	name_edit->set_anchors_and_offsets_preset(PRESET_WIDE);
-	name_edit->connect("text_entered", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited));
+	name_edit->connect("text_submitted", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited));
 	name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out));
 
 	open_file = memnew(EditorFileDialog);

+ 1 - 1
editor/plugins/asset_library_editor_plugin.h

@@ -282,7 +282,7 @@ class EditorAssetLibrary : public PanelContainer {
 	void _search(int p_page = 0);
 	void _rerun_search(int p_ignore);
 	void _search_text_changed(const String &p_text = "");
-	void _search_text_entered(const String &p_text = "");
+	void _search_text_submitted(const String &p_text = "");
 	void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = "");
 	void _http_request_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
 	void _http_download_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);

+ 5 - 5
editor/plugins/visual_shader_editor_plugin.cpp

@@ -432,7 +432,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
 		register_uniform_name(p_id, uniform_name);
 		uniform_name->set_text(uniform->get_uniform_name());
 		node->add_child(uniform_name);
-		uniform_name->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_uniform_line_edit_changed), varray(p_id));
+		uniform_name->connect("text_submitted", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_uniform_line_edit_changed), varray(p_id));
 		uniform_name->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_uniform_line_edit_focus_out), varray(uniform_name, p_id));
 
 		if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
@@ -666,7 +666,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
 					name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
 					name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 					name_box->set_text(name_left);
-					name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
+					name_box->connect("text_submitted", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
 					name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false), CONNECT_DEFERRED);
 
 					Button *remove_btn = memnew(Button);
@@ -707,7 +707,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
 					name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
 					name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 					name_box->set_text(name_right);
-					name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
+					name_box->connect("text_submitted", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
 					name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true), CONNECT_DEFERRED);
 
 					OptionButton *type_box = memnew(OptionButton);
@@ -1855,7 +1855,7 @@ void VisualShaderEditor::_comment_title_text_changed(const String &p_new_text) {
 	comment_title_change_popup->set_size(Size2(-1, -1));
 }
 
-void VisualShaderEditor::_comment_title_text_entered(const String &p_new_text) {
+void VisualShaderEditor::_comment_title_text_submitted(const String &p_new_text) {
 	comment_title_change_popup->hide();
 }
 
@@ -3944,7 +3944,7 @@ VisualShaderEditor::VisualShaderEditor() {
 	comment_title_change_edit = memnew(LineEdit);
 	comment_title_change_edit->set_expand_to_text_length_enabled(true);
 	comment_title_change_edit->connect("text_changed", callable_mp(this, &VisualShaderEditor::_comment_title_text_changed));
-	comment_title_change_edit->connect("text_entered", callable_mp(this, &VisualShaderEditor::_comment_title_text_entered));
+	comment_title_change_edit->connect("text_submitted", callable_mp(this, &VisualShaderEditor::_comment_title_text_submitted));
 	comment_title_change_popup->add_child(comment_title_change_edit);
 	comment_title_change_edit->set_size(Size2(-1, -1));
 	comment_title_change_popup->set_size(Size2(-1, -1));

+ 1 - 1
editor/plugins/visual_shader_editor_plugin.h

@@ -358,7 +358,7 @@ class VisualShaderEditor : public VBoxContainer {
 	void _comment_title_popup_hide();
 	void _comment_title_popup_focus_out();
 	void _comment_title_text_changed(const String &p_new_text);
-	void _comment_title_text_entered(const String &p_new_text);
+	void _comment_title_text_submitted(const String &p_new_text);
 
 	void _comment_desc_popup_show(const Point2 &p_position, int p_node_id);
 	void _comment_desc_popup_hide();

+ 5 - 5
editor/project_export.cpp

@@ -871,10 +871,10 @@ void ProjectExportDialog::_validate_export_path(const String &p_path) {
 
 	if (invalid_path) {
 		export_project->get_ok_button()->set_disabled(true);
-		export_project->get_line_edit()->disconnect("text_entered", Callable(export_project, "_file_entered"));
+		export_project->get_line_edit()->disconnect("text_submitted", Callable(export_project, "_file_submitted"));
 	} else {
 		export_project->get_ok_button()->set_disabled(false);
-		export_project->get_line_edit()->connect("text_entered", Callable(export_project, "_file_entered"));
+		export_project->get_line_edit()->connect("text_submitted", Callable(export_project, "_file_submitted"));
 	}
 }
 
@@ -905,10 +905,10 @@ void ProjectExportDialog::_export_project() {
 	// Ensure that signal is connected if previous attempt left it disconnected
 	// with _validate_export_path.
 	// FIXME: This is a hack, we should instead change EditorFileDialog to allow
-	// disabling validation by the "text_entered" signal.
-	if (!export_project->get_line_edit()->is_connected("text_entered", Callable(export_project, "_file_entered"))) {
+	// disabling validation by the "text_submitted" signal.
+	if (!export_project->get_line_edit()->is_connected("text_submitted", Callable(export_project, "_file_submitted"))) {
 		export_project->get_ok_button()->set_disabled(false);
-		export_project->get_line_edit()->connect("text_entered", Callable(export_project, "_file_entered"));
+		export_project->get_line_edit()->connect("text_submitted", Callable(export_project, "_file_submitted"));
 	}
 
 	export_project->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);

+ 1 - 1
editor/property_editor.cpp

@@ -1781,7 +1781,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
 		value_hboxes[hbox_idx]->add_child(value_editor[i]);
 		value_editor[i]->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 		value_editor[i]->hide();
-		value_editor[i]->connect("text_entered", callable_mp(this, &CustomPropertyEditor::_modified));
+		value_editor[i]->connect("text_submitted", callable_mp(this, &CustomPropertyEditor::_modified));
 		value_editor[i]->connect("focus_entered", callable_mp(this, &CustomPropertyEditor::_focus_enter));
 		value_editor[i]->connect("focus_exited", callable_mp(this, &CustomPropertyEditor::_focus_exit));
 	}

+ 6 - 6
editor/script_create_dialog.cpp

@@ -602,7 +602,7 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
 	_update_dialog();
 }
 
-void ScriptCreateDialog::_path_entered(const String &p_path) {
+void ScriptCreateDialog::_path_submitted(const String &p_path) {
 	ok_pressed();
 }
 
@@ -731,13 +731,13 @@ void ScriptCreateDialog::_update_dialog() {
 
 	get_ok_button()->set_disabled(!script_ok);
 
-	Callable entered_call = callable_mp(this, &ScriptCreateDialog::_path_entered);
+	Callable entered_call = callable_mp(this, &ScriptCreateDialog::_path_submitted);
 	if (script_ok) {
-		if (!file_path->is_connected("text_entered", entered_call)) {
-			file_path->connect("text_entered", entered_call);
+		if (!file_path->is_connected("text_submitted", entered_call)) {
+			file_path->connect("text_submitted", entered_call);
 		}
-	} else if (file_path->is_connected("text_entered", entered_call)) {
-		file_path->disconnect("text_entered", entered_call);
+	} else if (file_path->is_connected("text_submitted", entered_call)) {
+		file_path->disconnect("text_submitted", entered_call);
 	}
 }
 

+ 1 - 1
editor/script_create_dialog.h

@@ -105,7 +105,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
 	void _path_hbox_sorted();
 	bool _can_be_built_in();
 	void _path_changed(const String &p_path = String());
-	void _path_entered(const String &p_path = String());
+	void _path_submitted(const String &p_path = String());
 	void _lang_changed(int l = 0);
 	void _built_in_pressed();
 	bool _validate_parent(const String &p_string);

+ 3 - 3
scene/gui/color_picker.cpp

@@ -289,7 +289,7 @@ void ColorPicker::_value_changed(double) {
 	emit_signal("color_changed", color);
 }
 
-void ColorPicker::_html_entered(const String &p_html) {
+void ColorPicker::_html_submitted(const String &p_html) {
 	if (updating || text_is_constructor || !c_text->is_visible()) {
 		return;
 	}
@@ -1041,7 +1041,7 @@ void ColorPicker::_html_focus_exit() {
 	if (c_text->get_menu()->is_visible()) {
 		return;
 	}
-	_html_entered(c_text->get_text());
+	_html_submitted(c_text->get_text());
 	_focus_exit();
 }
 
@@ -1204,7 +1204,7 @@ ColorPicker::ColorPicker() :
 
 	hhb->add_child(c_text);
 	c_text->set_h_size_flags(SIZE_EXPAND_FILL);
-	c_text->connect("text_entered", callable_mp(this, &ColorPicker::_html_entered));
+	c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
 	c_text->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
 	c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit));
 

+ 1 - 1
scene/gui/color_picker.h

@@ -104,7 +104,7 @@ private:
 	float v = 0.0;
 	Color last_hsv;
 
-	void _html_entered(const String &p_html);
+	void _html_submitted(const String &p_html);
 	void _value_changed(double);
 	void _update_controls();
 	void _update_color(bool p_update_sliders = true);

+ 2 - 2
scene/gui/dialogs.cpp

@@ -97,7 +97,7 @@ void AcceptDialog::_notification(int p_what) {
 	}
 }
 
-void AcceptDialog::_text_entered(const String &p_text) {
+void AcceptDialog::_text_submitted(const String &p_text) {
 	_ok_pressed();
 }
 
@@ -159,7 +159,7 @@ void AcceptDialog::register_text_enter(Control *p_line_edit) {
 	ERR_FAIL_NULL(p_line_edit);
 	LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
 	if (line_edit) {
-		line_edit->connect("text_entered", callable_mp(this, &AcceptDialog::_text_entered));
+		line_edit->connect("text_submitted", callable_mp(this, &AcceptDialog::_text_submitted));
 	}
 }
 

+ 1 - 1
scene/gui/dialogs.h

@@ -69,7 +69,7 @@ protected:
 	virtual void custom_action(const String &) {}
 
 	// Not private since used by derived classes signal.
-	void _text_entered(const String &p_text);
+	void _text_submitted(const String &p_text);
 	void _ok_pressed();
 	void _cancel_pressed();
 

+ 5 - 5
scene/gui/file_dialog.cpp

@@ -116,7 +116,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
 					invalidate();
 				} break;
 				case KEY_BACKSPACE: {
-					_dir_entered("..");
+					_dir_submitted("..");
 				} break;
 				default: {
 					handled = false;
@@ -156,7 +156,7 @@ void FileDialog::update_dir() {
 	deselect_all();
 }
 
-void FileDialog::_dir_entered(String p_dir) {
+void FileDialog::_dir_submitted(String p_dir) {
 	dir_access->change_dir(p_dir);
 	file->set_text("");
 	invalidate();
@@ -164,7 +164,7 @@ void FileDialog::_dir_entered(String p_dir) {
 	_push_history();
 }
 
-void FileDialog::_file_entered(const String &p_file) {
+void FileDialog::_file_submitted(const String &p_file) {
 	_action_pressed();
 }
 
@@ -1020,8 +1020,8 @@ FileDialog::FileDialog() {
 	tree->connect("cell_selected", callable_mp(this, &FileDialog::_tree_selected), varray(), CONNECT_DEFERRED);
 	tree->connect("item_activated", callable_mp(this, &FileDialog::_tree_item_activated), varray());
 	tree->connect("nothing_selected", callable_mp(this, &FileDialog::deselect_all));
-	dir->connect("text_entered", callable_mp(this, &FileDialog::_dir_entered));
-	file->connect("text_entered", callable_mp(this, &FileDialog::_file_entered));
+	dir->connect("text_submitted", callable_mp(this, &FileDialog::_dir_submitted));
+	file->connect("text_submitted", callable_mp(this, &FileDialog::_file_submitted));
 	filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected));
 
 	confirm_save = memnew(ConfirmationDialog);

+ 2 - 2
scene/gui/file_dialog.h

@@ -118,8 +118,8 @@ private:
 
 	void _select_drive(int p_idx);
 	void _tree_item_activated();
-	void _dir_entered(String p_dir);
-	void _file_entered(const String &p_file);
+	void _dir_submitted(String p_dir);
+	void _file_submitted(const String &p_file);
 	void _action_pressed();
 	void _save_confirm_pressed();
 	void _cancel_pressed();

+ 4 - 4
scene/gui/line_edit.cpp

@@ -357,9 +357,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 			}
 		}
 
-		// Default is ENTER, KP_ENTER. Cannot use ui_accept as default includes SPACE
-		if (k->is_action("ui_text_newline", true)) {
-			emit_signal("text_entered", text);
+		// Default is ENTER and KP_ENTER. Cannot use ui_accept as default includes SPACE
+		if (k->is_action("ui_text_submit", false)) {
+			emit_signal("text_submitted", text);
 			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
 				DisplayServer::get_singleton()->virtual_keyboard_hide();
 			}
@@ -2159,7 +2159,7 @@ void LineEdit::_bind_methods() {
 
 	ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
 	ADD_SIGNAL(MethodInfo("text_change_rejected"));
-	ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
+	ADD_SIGNAL(MethodInfo("text_submitted", PropertyInfo(Variant::STRING, "new_text")));
 
 	BIND_ENUM_CONSTANT(ALIGN_LEFT);
 	BIND_ENUM_CONSTANT(ALIGN_CENTER);

+ 106 - 26
scene/gui/rich_text_label.cpp

@@ -3452,7 +3452,30 @@ void RichTextLabel::set_selection_enabled(bool p_enabled) {
 	}
 }
 
-bool RichTextLabel::_search_line(ItemFrame *p_frame, int p_line, const String &p_string, Item *p_from, Item *p_to) {
+bool RichTextLabel::_search_table(ItemTable *p_table, List<Item *>::Element *p_from, const String &p_string, bool p_reverse_search) {
+	List<Item *>::Element *E = p_from;
+	while (E != nullptr) {
+		ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
+		ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+		if (p_reverse_search) {
+			for (int i = frame->lines.size() - 1; i >= 0; i--) {
+				if (_search_line(frame, i, p_string, -1, p_reverse_search)) {
+					return true;
+				}
+			}
+		} else {
+			for (int i = 0; i < frame->lines.size(); i++) {
+				if (_search_line(frame, i, p_string, 0, p_reverse_search)) {
+					return true;
+				}
+			}
+		}
+		E = p_reverse_search ? E->prev() : E->next();
+	}
+	return false;
+}
+
+bool RichTextLabel::_search_line(ItemFrame *p_frame, int p_line, const String &p_string, int p_char_idx, bool p_reverse_search) {
 	ERR_FAIL_COND_V(p_frame == nullptr, false);
 	ERR_FAIL_COND_V(p_line < 0 || p_line >= p_frame->lines.size(), false);
 
@@ -3474,24 +3497,23 @@ bool RichTextLabel::_search_line(ItemFrame *p_frame, int p_line, const String &p
 			} break;
 			case ITEM_TABLE: {
 				ItemTable *table = static_cast<ItemTable *>(it);
-				int idx = 0;
-				for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
-					ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
-					ItemFrame *frame = static_cast<ItemFrame *>(E->get());
-
-					for (int i = 0; i < frame->lines.size(); i++) {
-						if (_search_line(frame, i, p_string, p_from, p_to)) {
-							return true;
-						}
-					}
-					idx++;
+				List<Item *>::Element *E = p_reverse_search ? table->subitems.back() : table->subitems.front();
+				if (_search_table(table, E, p_string, p_reverse_search)) {
+					return true;
 				}
 			} break;
 			default:
 				break;
 		}
 	}
-	int sp = text.findn(p_string, 0);
+
+	int sp = -1;
+	if (p_reverse_search) {
+		sp = text.rfindn(p_string, p_char_idx);
+	} else {
+		sp = text.findn(p_string, p_char_idx);
+	}
+
 	if (sp != -1) {
 		selection.from_frame = p_frame;
 		selection.from_line = p_line;
@@ -3499,8 +3521,8 @@ bool RichTextLabel::_search_line(ItemFrame *p_frame, int p_line, const String &p
 		selection.from_char = sp;
 		selection.to_frame = p_frame;
 		selection.to_line = p_line;
-		selection.to_item = _get_item_at_pos(l.from, it_to, sp + p_string.length() - 1);
-		selection.to_char = sp + p_string.length() - 1;
+		selection.to_item = _get_item_at_pos(l.from, it_to, sp + p_string.length());
+		selection.to_char = sp + p_string.length();
 		selection.active = true;
 		return true;
 	}
@@ -3511,23 +3533,81 @@ bool RichTextLabel::_search_line(ItemFrame *p_frame, int p_line, const String &p
 bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p_search_previous) {
 	ERR_FAIL_COND_V(!selection.enabled, false);
 
+	if (p_string.size() == 0) {
+		selection.active = false;
+		return false;
+	}
+
+	int char_idx = p_search_previous ? -1 : 0;
+	int current_line = 0;
+	int ending_line = main->lines.size() - 1;
 	if (p_from_selection && selection.active) {
-		for (int i = 0; i < main->lines.size(); i++) {
-			if (_search_line(main, i, p_string, selection.from_item, selection.to_item)) {
-				update();
-				return true;
-			}
+		// First check to see if other results exist in current line
+		char_idx = p_search_previous ? selection.from_char - 1 : selection.to_char;
+		if (!(p_search_previous && char_idx < 0) &&
+				_search_line(selection.from_frame, selection.from_line, p_string, char_idx, p_search_previous)) {
+			scroll_to_line(selection.from_frame->line + selection.from_line);
+			update();
+			return true;
 		}
-	} else {
-		for (int i = 0; i < main->lines.size(); i++) {
-			if (_search_line(main, i, p_string, nullptr, nullptr)) {
-				update();
-				return true;
+		char_idx = p_search_previous ? -1 : 0;
+
+		// Next, check to see if the current search result is in a table
+		if (selection.from_frame->parent != nullptr && selection.from_frame->parent->type == ITEM_TABLE) {
+			// Find last search result in table
+			ItemTable *parent_table = static_cast<ItemTable *>(selection.from_frame->parent);
+			List<Item *>::Element *parent_element = p_search_previous ? parent_table->subitems.back() : parent_table->subitems.front();
+
+			while (parent_element->get() != selection.from_frame) {
+				parent_element = p_search_previous ? parent_element->prev() : parent_element->next();
+				ERR_FAIL_COND_V(parent_element == nullptr, false);
+			}
+
+			// Search remainder of table
+			if (!(p_search_previous && parent_element == parent_table->subitems.front()) &&
+					parent_element != parent_table->subitems.back()) {
+				parent_element = p_search_previous ? parent_element->prev() : parent_element->next(); // Don't want to search current item
+				ERR_FAIL_COND_V(parent_element == nullptr, false);
+
+				// Search for next element
+				if (_search_table(parent_table, parent_element, p_string, p_search_previous)) {
+					scroll_to_line(selection.from_frame->line + selection.from_line);
+					update();
+					return true;
+				}
 			}
 		}
+
+		ending_line = selection.from_frame->line + selection.from_line;
+		current_line = p_search_previous ? ending_line - 1 : ending_line + 1;
+	} else if (p_search_previous) {
+		current_line = ending_line;
+		ending_line = 0;
 	}
 
-	return false;
+	// Search remainder of the file
+	while (current_line != ending_line) {
+		// Wrap around
+		if (current_line < 0) {
+			current_line = main->lines.size() - 1;
+		} else if (current_line >= main->lines.size()) {
+			current_line = 0;
+		}
+
+		if (_search_line(main, current_line, p_string, char_idx, p_search_previous)) {
+			scroll_to_line(current_line);
+			update();
+			return true;
+		}
+		p_search_previous ? current_line-- : current_line++;
+	}
+
+	if (p_from_selection && selection.active) {
+		// Check contents of selection
+		return _search_line(main, current_line, p_string, char_idx, p_search_previous);
+	} else {
+		return false;
+	}
 }
 
 String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p_selection) const {

+ 2 - 1
scene/gui/rich_text_label.h

@@ -392,7 +392,8 @@ private:
 	void _find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool *r_outside = nullptr);
 
 	String _get_line_text(ItemFrame *p_frame, int p_line, Selection p_sel) const;
-	bool _search_line(ItemFrame *p_frame, int p_line, const String &p_string, Item *p_from, Item *p_to);
+	bool _search_line(ItemFrame *p_frame, int p_line, const String &p_string, int p_char_idx, bool p_reverse_search);
+	bool _search_table(ItemTable *p_table, List<Item *>::Element *p_from, const String &p_string, bool p_reverse_search);
 
 	void _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, int *r_char_offset);
 	void _resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width);

+ 4 - 4
scene/gui/spin_box.cpp

@@ -50,7 +50,7 @@ void SpinBox::_value_changed(double) {
 	line_edit->set_text(value);
 }
 
-void SpinBox::_text_entered(const String &p_string) {
+void SpinBox::_text_submitted(const String &p_string) {
 	Ref<Expression> expr;
 	expr.instance();
 
@@ -172,7 +172,7 @@ void SpinBox::_line_edit_focus_exit() {
 		return;
 	}
 
-	_text_entered(line_edit->get_text());
+	_text_submitted(line_edit->get_text());
 }
 
 inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
@@ -251,7 +251,7 @@ bool SpinBox::is_editable() const {
 }
 
 void SpinBox::apply() {
-	_text_entered(line_edit->get_text());
+	_text_submitted(line_edit->get_text());
 }
 
 void SpinBox::_bind_methods() {
@@ -283,7 +283,7 @@ SpinBox::SpinBox() {
 	line_edit->set_align(LineEdit::ALIGN_LEFT);
 
 	//connect("value_changed",this,"_value_changed");
-	line_edit->connect("text_entered", callable_mp(this, &SpinBox::_text_entered), Vector<Variant>(), CONNECT_DEFERRED);
+	line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), Vector<Variant>(), CONNECT_DEFERRED);
 	line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), Vector<Variant>(), CONNECT_DEFERRED);
 	line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input));
 

+ 1 - 1
scene/gui/spin_box.h

@@ -45,7 +45,7 @@ class SpinBox : public Range {
 	void _range_click_timeout();
 	void _release_mouse();
 
-	void _text_entered(const String &p_string);
+	void _text_submitted(const String &p_string);
 	virtual void _value_changed(double) override;
 	String prefix;
 	String suffix;

+ 3 - 3
scene/gui/tree.cpp

@@ -2451,10 +2451,10 @@ void Tree::_text_editor_modal_close() {
 		return;
 	}
 
-	_text_editor_enter(text_editor->get_text());
+	_text_editor_submit(text_editor->get_text());
 }
 
-void Tree::_text_editor_enter(String p_text) {
+void Tree::_text_editor_submit(String p_text) {
 	popup_editor->hide();
 
 	if (!popup_edited_item) {
@@ -4554,7 +4554,7 @@ Tree::Tree() {
 
 	h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
 	v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
-	text_editor->connect("text_entered", callable_mp(this, &Tree::_text_editor_enter));
+	text_editor->connect("text_submitted", callable_mp(this, &Tree::_text_editor_submit));
 	popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_modal_close));
 	popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select));
 	value_editor->connect("value_changed", callable_mp(this, &Tree::value_editor_changed));

+ 1 - 1
scene/gui/tree.h

@@ -449,7 +449,7 @@ private:
 	int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
 	void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
 	int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
-	void _text_editor_enter(String p_text);
+	void _text_editor_submit(String p_text);
 	void _text_editor_modal_close();
 	void value_editor_changed(double p_value);