diff options
author | Christian Persch <chpe@src.gnome.org> | 2022-12-20 22:11:56 +0100 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2022-12-20 22:11:56 +0100 |
commit | 2ee2495486e3266ab0037daad0b1cf220bd254b0 (patch) | |
tree | 05b28d51d9064b8006547ad32b4e8f57dd0630ff | |
parent | 8d74fb84e2031a5f3373ef07f7862b0e49966a87 (diff) | |
download | vte-2ee2495486e3266ab0037daad0b1cf220bd254b0.tar.gz |
widget: Add API to get text as HTML
Based on a patch by Lex Bailey <gitcommit@lexbailey.me>.
Fixes: https://gitlab.gnome.org/GNOME/vte/-/issues/2589
-rw-r--r-- | src/glib-glue.hh | 16 | ||||
-rw-r--r-- | src/vte/vteterminal.h | 17 | ||||
-rw-r--r-- | src/vtegtk.cc | 147 |
3 files changed, 156 insertions, 24 deletions
diff --git a/src/glib-glue.hh b/src/glib-glue.hh index c7839cfc..b3a97858 100644 --- a/src/glib-glue.hh +++ b/src/glib-glue.hh @@ -278,8 +278,24 @@ bool set_error_from_exception(GError** error namespace vte { +VTE_DECLARE_FREEABLE(GArray, g_array_unref); VTE_DECLARE_FREEABLE(GBytes, g_bytes_unref); VTE_DECLARE_FREEABLE(GOptionContext, g_option_context_free); +VTE_DECLARE_FREEABLE(GString, g_autoptr_cleanup_gstring_free); VTE_DECLARE_FREEABLE(GVariant, g_variant_unref); } // namespace vte + +namespace vte::glib { + +inline char* +release_to_string(vte::Freeable<GString> str, + gsize* length = nullptr) noexcept +{ + if (length) + *length = str.get()->len; + + return g_string_free(str.release(), false); +} + +} // namespace vte::glib diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h index 688f3aa0..90aae937 100644 --- a/src/vte/vteterminal.h +++ b/src/vte/vteterminal.h @@ -360,7 +360,12 @@ gboolean vte_terminal_get_has_selection(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_PUBLIC char* vte_terminal_get_text_selected(VteTerminal* terminal, - VteFormat format) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1); + VteFormat format) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC; + +_VTE_PUBLIC +char* vte_terminal_get_text_selected_full(VteTerminal* terminal, + VteFormat format, + gsize* length) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC; /* Set what happens when the user strikes backspace or delete. */ _VTE_PUBLIC @@ -414,6 +419,16 @@ char *vte_terminal_get_text_range(VteTerminal *terminal, VteSelectionFunc is_selected, gpointer user_data, GArray *attributes) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC; + +_VTE_PUBLIC +char* vte_terminal_get_text_range_format(VteTerminal* terminal, + VteFormat format, + long start_row, + long start_col, + long end_row, + long end_col, + gsize* length) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC; + _VTE_PUBLIC void vte_terminal_get_cursor_position(VteTerminal *terminal, glong *column, diff --git a/src/vtegtk.cc b/src/vtegtk.cc index f9265712..20cac974 100644 --- a/src/vtegtk.cc +++ b/src/vtegtk.cc @@ -95,6 +95,18 @@ struct _VteTerminalClassPrivate { GtkStyleProvider *style_provider; }; +template<> +constexpr bool check_enum_value<VteFormat>(VteFormat value) noexcept +{ + switch (value) { + case VTE_FORMAT_TEXT: + case VTE_FORMAT_HTML: + return true; + default: + return false; + } +} + #if VTE_GTK == 4 static void @@ -2774,7 +2786,7 @@ vte_terminal_copy_clipboard_format(VteTerminal *terminal, try { g_return_if_fail(VTE_IS_TERMINAL(terminal)); - g_return_if_fail(format == VTE_FORMAT_TEXT || format == VTE_FORMAT_HTML); + g_return_if_fail(check_enum_value(format)); WIDGET(terminal)->copy(vte::platform::ClipboardType::CLIPBOARD, clipboard_format_from_vte(format)); @@ -4401,8 +4413,9 @@ vte_terminal_get_text_include_trailing_spaces(VteTerminal *terminal, * This method is unaware of BiDi. The columns passed in @start_col and @end_row, * and returned in @attributes are logical columns. * - * Note: since 0.68, passing a non-%NULL @array parameter is deprecated. Starting with - * 0.72, passing a non-%NULL @array parameter will make this function itself return %NULL. + * Since 0.68, passing a non-%NULL @array parameter is deprecated. + * Since 0.72, passing a non-%NULL @array parameter will make this function + * itself return %NULL. * * Returns: (transfer full) (nullable): a newly allocated text string, or %NULL. */ @@ -4417,17 +4430,78 @@ vte_terminal_get_text_range(VteTerminal *terminal, GArray *attributes) noexcept try { - g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL); warn_if_callback(is_selected); warn_if_attributes(attributes); - auto text = IMPL(terminal)->get_text(start_row, start_col, - end_row, end_col, - false /* block */, - true /* wrap */, - attributes); - if (text == nullptr) + if (is_selected || attributes) return nullptr; - return (char*)g_string_free(text, FALSE); + + return vte_terminal_get_text_range_format(terminal, + VTE_FORMAT_TEXT, + start_row, + start_col, + end_row, + end_col, + nullptr); +} +catch (...) +{ + vte::log_exception(); + return nullptr; +} + +/** + * vte_terminal_get_text_range_format: + * @terminal: a #VteTerminal + * @format: the #VteFormat to use + * @start_row: the first row of the range + * @start_col: the first column of the range + * @end_row: the last row of the range + * @end_col: the last column of the range + * + * Returns the specified range of text in the specified format. + * + * Returns: (transfer full) (nullable): a newly allocated string, or %NULL. + * + * Since: 0.72 + */ +char* +vte_terminal_get_text_range_format(VteTerminal *terminal, + VteFormat format, + long start_row, + long start_col, + long end_row, + long end_col, + gsize* length) noexcept +try +{ + g_return_val_if_fail(VTE_IS_TERMINAL(terminal), nullptr); + g_return_val_if_fail(check_enum_value(format), nullptr); + + if (length) + *length = 0; + + auto attributes = vte::Freeable<GArray>{}; + if (format == VTE_FORMAT_HTML) + attributes = vte::take_freeable(g_array_new(false, + true, + sizeof(struct _VteCharAttributes))); + + auto const impl = IMPL(terminal); + auto text = vte::take_freeable(impl->get_text(start_row, + start_col, + end_row, + end_col, + false, + true, + attributes.get())); + if (!text) + return nullptr; + + if (format == VTE_FORMAT_HTML) + text = vte::take_freeable(impl->attributes_to_html(text.get(), + attributes.get())); + + return vte::glib::release_to_string(std::move(text), length); } catch (...) { @@ -5774,7 +5848,7 @@ catch (...) * @format: the #VteFormat to use * * Gets the currently selected text in the format specified by @format. - * Note that currently, only %VTE_FORMAT_TEXT is supported. + * Since 0.72, this function also supports %VTE_FORMAT_HTML format.xg * * Returns: (transfer full) (nullable): a newly allocated string containing the selected text, or %NULL if there is no selection or the format is not supported * @@ -5785,20 +5859,47 @@ vte_terminal_get_text_selected(VteTerminal* terminal, VteFormat format) noexcept try { - g_return_val_if_fail(VTE_IS_TERMINAL(terminal), nullptr); + return vte_terminal_get_text_selected_full(terminal, + format, + nullptr); +} +catch (...) +{ + vte::log_exception(); + return nullptr; +} - if (format != VTE_FORMAT_TEXT) - return nullptr; +/** + * vte_terminal_get_text_selected_full: + * @terminal: a #VteTerminal + * @format: the #VteFormat to use + * @length: (optional) (default 0) (out): a pointer to a #gsize to store the string length + * + * Gets the currently selected text in the format specified by @format. + * + * Returns: (transfer full) (nullable): a newly allocated string containing the selected text, or %NULL if there is no selection or the format is not supported + * + * Since: 0.72 + */ +char* +vte_terminal_get_text_selected_full(VteTerminal* terminal, + VteFormat format, + gsize* length) noexcept +try +{ + if (length) + *length = 0; + + g_return_val_if_fail(VTE_IS_TERMINAL(terminal), nullptr); auto const selection = IMPL(terminal)->m_selection_resolved; - return vte_terminal_get_text_range(terminal, - selection.start_row(), - selection.start_column(), - selection.last_row(), - selection.end_column(), - nullptr, - nullptr, - nullptr); + return vte_terminal_get_text_range_format(terminal, + format, + selection.start_row(), + selection.start_column(), + selection.last_row(), + selection.end_column(), + length); } catch (...) { |