[vte/wip/regex-builtins: 2/3] lib: Rework how vte stores the match and search regexes
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/regex-builtins: 2/3] lib: Rework how vte stores the match and search regexes
- Date: Sat, 11 May 2019 09:29:19 +0000 (UTC)
commit 91b34406f92b48969e22ecaa4b0fba5f3b5fc066
Author: Christian Persch <chpe src gnome org>
Date: Sat May 11 11:28:46 2019 +0200
lib: Rework how vte stores the match and search regexes
src/refptr.hh | 50 ++++++
src/regex.cc | 3 +-
src/vte.cc | 431 ++++++++++++------------------------------------
src/vtegtk.cc | 44 ++---
src/vteinternal.hh | 133 +++++++++++----
src/vteregex.cc | 23 +--
src/vteregexinternal.hh | 19 ++-
src/widget.cc | 51 +++++-
src/widget.hh | 19 ++-
9 files changed, 350 insertions(+), 423 deletions(-)
---
diff --git a/src/refptr.hh b/src/refptr.hh
index ae7a96dd..666d061c 100644
--- a/src/refptr.hh
+++ b/src/refptr.hh
@@ -34,5 +34,55 @@ public:
RefPtr(T* obj = nullptr) : base_type{obj, &g_object_unref} { }
};
+template<typename T>
+RefPtr<T>
+make_ref(T* obj)
+{
+ if (obj)
+ g_object_ref(obj);
+ return {obj};
+}
+
+template<typename T>
+RefPtr<T>
+take_ref(T* obj)
+{
+ return {obj};
+}
+
} // namespace glib
+
+namespace base {
+
+template<class T>
+class Unreffer {
+public:
+ void operator()(T* obj) const
+ {
+ if (obj)
+ obj->unref();
+ }
+};
+
+template<class T>
+using RefPtr = std::unique_ptr<T, Unreffer<T>>;
+
+template<class T>
+RefPtr<T>
+make_ref(T* obj)
+{
+ if (obj)
+ obj->ref();
+ return RefPtr<T>{obj};
+}
+
+template<class T>
+RefPtr<T>
+take_ref(T* obj)
+{
+ return RefPtr<T>{obj};
+}
+
+} // namespace base
+
} // namespace vte
diff --git a/src/regex.cc b/src/regex.cc
index 5be07a46..7d6ec2b3 100644
--- a/src/regex.cc
+++ b/src/regex.cc
@@ -21,7 +21,6 @@
#include "vte/vteenums.h"
#include "vte/vteregex.h"
-
#include <cassert>
namespace vte {
@@ -32,7 +31,7 @@ static bool
set_gerror_from_pcre_error(int errcode,
GError **error)
{
- PCRE2_UCHAR8 buf[128];
+ PCRE2_UCHAR8 buf[256];
int n = pcre2_get_error_message_8(errcode, buf, sizeof(buf));
assert(n >= 0);
g_set_error_literal(error, VTE_REGEX_ERROR, errcode, (char const*)buf);
diff --git a/src/vte.cc b/src/vte.cc
index 0e799cef..e0930bd2 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -796,205 +796,24 @@ Terminal::match_contents_refresh()
m_match_attributes = array;
}
-static void
-regex_match_clear_cursor (struct vte_match_regex *regex)
-{
- switch (regex->cursor_mode) {
- case VTE_REGEX_CURSOR_GDKCURSOR:
- if (regex->cursor.cursor != NULL) {
- g_object_unref(regex->cursor.cursor);
- regex->cursor.cursor = NULL;
- }
- break;
- case VTE_REGEX_CURSOR_GDKCURSORTYPE:
- break;
- case VTE_REGEX_CURSOR_NAME:
- g_free (regex->cursor.cursor_name);
- regex->cursor.cursor_name = NULL;
- break;
- default:
- g_assert_not_reached ();
- return;
- }
-}
-
-static void
-regex_and_flags_clear(struct vte_regex_and_flags *regex)
-{
- if (regex->regex) {
- vte_regex_unref(regex->regex);
- regex->regex = nullptr;
- }
-}
-
-static void
-regex_match_clear (struct vte_match_regex *regex)
-{
- regex_and_flags_clear(®ex->regex);
- regex_match_clear_cursor(regex);
-
- regex->tag = -1;
-}
-
-void
-Terminal::set_cursor_from_regex_match(struct vte_match_regex *regex)
-{
- GdkCursor *gdk_cursor = nullptr;
-
- if (!widget_realized())
- return;
-
- switch (regex->cursor_mode) {
- case VTE_REGEX_CURSOR_GDKCURSOR:
- if (regex->cursor.cursor != NULL &&
- gdk_cursor_get_display(regex->cursor.cursor) ==
gtk_widget_get_display(m_widget)) {
- gdk_cursor = (GdkCursor *)g_object_ref(regex->cursor.cursor);
- }
- break;
- case VTE_REGEX_CURSOR_GDKCURSORTYPE:
- gdk_cursor = gdk_cursor_new_for_display(gtk_widget_get_display(m_widget),
regex->cursor.cursor_type);
- break;
- case VTE_REGEX_CURSOR_NAME:
- gdk_cursor = gdk_cursor_new_from_name(gtk_widget_get_display(m_widget),
regex->cursor.cursor_name);
- break;
- default:
- g_assert_not_reached ();
- return;
- }
-
- m_real_widget->set_cursor(gdk_cursor);
-
- if (gdk_cursor)
- g_object_unref(gdk_cursor);
-}
-
void
Terminal::regex_match_remove_all()
{
- struct vte_match_regex *regex;
- guint i;
-
- for (i = 0; i < m_match_regexes->len; i++) {
- regex = &g_array_index(m_match_regexes,
- struct vte_match_regex,
- i);
- /* Unless this is a hole, clean it up. */
- if (regex->tag >= 0) {
- regex_match_clear (regex);
- }
- }
- g_array_set_size(m_match_regexes, 0);
+ auto& match_regexes = match_regexes_writable();
+ match_regexes.clear();
+ match_regexes.shrink_to_fit();
match_hilite_clear();
}
void
-Terminal::regex_match_remove(int tag)
+Terminal::regex_match_remove(int tag) noexcept
{
- struct vte_match_regex *regex;
-
- if (m_match_regexes->len > (guint)tag) {
- /* The tag is an index, so find the corresponding struct. */
- regex = &g_array_index(m_match_regexes,
- struct vte_match_regex,
- tag);
- /* If it's already been removed, return. */
- if (regex->tag < 0) {
- return;
- }
- /* Remove this item and leave a hole in its place. */
- regex_match_clear (regex);
- }
- match_hilite_clear();
-}
-
-int
-Terminal::regex_match_add(struct vte_match_regex *new_regex_match)
-{
- struct vte_match_regex *regex_match;
- guint ret, len;
-
- /* Search for a hole. */
- len = m_match_regexes->len;
- for (ret = 0; ret < len; ret++) {
- regex_match = &g_array_index(m_match_regexes,
- struct vte_match_regex,
- ret);
- if (regex_match->tag == -1) {
- break;
- }
- }
-
- /* Set the tag to the insertion point. */
- new_regex_match->tag = ret;
-
- if (ret < len) {
- /* Overwrite. */
- g_array_index(m_match_regexes,
- struct vte_match_regex,
- ret) = *new_regex_match;
- } else {
- /* Append. */
- g_array_append_vals(m_match_regexes, new_regex_match, 1);
- }
-
- /* FIXMEchpe: match_hilite_clear() so we can redo the highlighting with the new regex added? */
-
- return ret;
-}
-
-struct vte_match_regex *
-Terminal::regex_match_get(int tag)
-{
- if ((guint)tag >= m_match_regexes->len)
- return nullptr;
-
- return &g_array_index(m_match_regexes, struct vte_match_regex, tag);
-}
-
-void
-Terminal::regex_match_set_cursor(int tag,
- GdkCursor *gdk_cursor)
-{
- struct vte_match_regex *regex = regex_match_get(tag);
- if (regex == nullptr)
- return;
-
- regex_match_clear_cursor(regex);
- regex->cursor_mode = VTE_REGEX_CURSOR_GDKCURSOR;
- regex->cursor.cursor = gdk_cursor ? (GdkCursor *)g_object_ref(gdk_cursor) : NULL;
-
- match_hilite_clear();
-}
-
-void
-Terminal::regex_match_set_cursor(int tag,
- GdkCursorType cursor_type)
-{
- struct vte_match_regex *regex = regex_match_get(tag);
- if (regex == nullptr)
- return;
-
- regex_match_clear_cursor(regex);
- regex->cursor_mode = VTE_REGEX_CURSOR_GDKCURSORTYPE;
- regex->cursor.cursor_type = cursor_type;
-
- match_hilite_clear();
-}
-
-void
-Terminal::regex_match_set_cursor(int tag,
- char const* cursor_name)
-{
- struct vte_match_regex *regex = regex_match_get(tag);
- if (regex == nullptr)
+ auto i = regex_match_get_iter(tag);
+ if (i == std::end(m_match_regexes))
return;
- regex_match_clear_cursor(regex);
- regex->cursor_mode = VTE_REGEX_CURSOR_NAME;
- regex->cursor.cursor_name = g_strdup (cursor_name);
-
- match_hilite_clear();
+ match_regexes_writable().erase(i);
}
/*
@@ -1140,19 +959,18 @@ Terminal::create_match_context()
}
bool
-Terminal::match_check_pcre(
- pcre2_match_data_8 *match_data,
- pcre2_match_context_8 *match_context,
- VteRegex *regex,
- guint32 match_flags,
- gsize sattr,
- gsize eattr,
- gsize offset,
- char **result_ptr,
- gsize *start,
- gsize *end,
- gsize *sblank_ptr,
- gsize *eblank_ptr)
+Terminal::match_check_pcre(pcre2_match_data_8 *match_data,
+ pcre2_match_context_8 *match_context,
+ vte::base::Regex const* regex,
+ uint32_t match_flags,
+ gsize sattr,
+ gsize eattr,
+ gsize offset,
+ char **result_ptr,
+ gsize *start,
+ gsize *end,
+ gsize *sblank_ptr,
+ gsize *eblank_ptr)
{
int (* match_fn) (const pcre2_code_8 *,
PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE, uint32_t,
@@ -1162,7 +980,7 @@ Terminal::match_check_pcre(
const char *line;
int r = 0;
- if (_vte_regex_get_jited(regex))
+ if (regex->jited())
match_fn = pcre2_jit_match_8;
else
match_fn = pcre2_match_8;
@@ -1180,7 +998,7 @@ Terminal::match_check_pcre(
pcre2_set_offset_limit_8(match_context, eattr);
position = sattr;
while (position < eattr &&
- ((r = match_fn(_vte_regex_get_pcre(regex),
+ ((r = match_fn(regex->code(),
(PCRE2_SPTR8)line, line_length, /* subject, length */
position, /* start offset */
match_flags |
@@ -1260,17 +1078,14 @@ Terminal::match_check_pcre(
char *
Terminal::match_check_internal_pcre(vte::grid::column_t column,
- vte::grid::row_t row,
- int *tag,
- gsize *start,
- gsize *end)
+ vte::grid::row_t row,
+ MatchRegex const** match,
+ size_t* start,
+ size_t* end)
{
- struct vte_match_regex *regex;
- guint i;
gsize offset, sattr, eattr, start_blank, end_blank;
pcre2_match_data_8 *match_data;
pcre2_match_context_8 *match_context;
- char *dingu_match = nullptr;
_vte_debug_print(VTE_DEBUG_REGEX,
"Checking for pcre match at (%ld,%ld).\n", row, column);
@@ -1286,26 +1101,19 @@ Terminal::match_check_internal_pcre(vte::grid::column_t column,
match_data = pcre2_match_data_create_8(256 /* should be plenty */, NULL /* general context */);
/* Now iterate over each regex we need to match against. */
- for (i = 0; i < m_match_regexes->len; i++) {
+ char* dingu_match{nullptr};
+ for (auto const& rem : m_match_regexes) {
gsize sblank, eblank;
- regex = &g_array_index(m_match_regexes,
- struct vte_match_regex,
- i);
- /* Skip holes. */
- if (regex->tag < 0) {
- continue;
- }
-
if (match_check_pcre(match_data, match_context,
- regex->regex.regex,
- regex->regex.match_flags,
+ rem.regex(),
+ rem.match_flags(),
sattr, eattr, offset,
&dingu_match,
start, end,
&sblank, &eblank)) {
- _vte_debug_print(VTE_DEBUG_REGEX, "Matched dingu with tag %d\n", regex->tag);
- *tag = regex->tag;
+ _vte_debug_print(VTE_DEBUG_REGEX, "Matched dingu with tag %d\n", rem.tag());
+ *match = std::addressof(rem);
break;
}
@@ -1323,6 +1131,7 @@ Terminal::match_check_internal_pcre(vte::grid::column_t column,
*/
*start = start_blank;
*end = end_blank - 1;
+ *match = nullptr;
_VTE_DEBUG_IF(VTE_DEBUG_REGEX) {
struct _VteCharAttributes *_sattr, *_eattr;
@@ -1349,69 +1158,69 @@ Terminal::match_check_internal_pcre(vte::grid::column_t column,
* @terminal:
* @column:
* @row:
- * @tag: (out):
+ * @match: (out):
* @start: (out):
* @end: (out):
*
- * Checks m_match_contents for dingu matches, and returns the tag, start, and
- * end of the match in @tag, @start, @end. If no match occurs, @tag will be set to
- * -1, and if they are nonzero, @start and @end mark the smallest span in the @row
+ * Checks m_match_contents for dingu matches, and returns the start, and
+ * end of the match in @start, @end, and the matched regex in @match.
+ * If no match occurs, @match will be set to %nullptr,
+ * and if they are nonzero, @start and @end mark the smallest span in the @row
* in which none of the dingus match.
*
- * Returns: (transfer full): the matched string, or %NULL
+ * Returns: (transfer full): the matched string, or %nullptr
*/
char *
Terminal::match_check_internal(vte::grid::column_t column,
- vte::grid::row_t row,
- int *tag,
- gsize *start,
- gsize *end)
+ vte::grid::row_t row,
+ MatchRegex const** match,
+ size_t* start,
+ size_t* end)
{
if (m_match_contents == nullptr) {
match_contents_refresh();
}
- g_assert(tag != NULL);
- g_assert(start != NULL);
- g_assert(end != NULL);
+ assert(match != nullptr);
+ assert(start != nullptr);
+ assert(end != nullptr);
- *tag = -1;
+ *match = nullptr;
*start = 0;
*end = 0;
- return match_check_internal_pcre(column, row, tag, start, end);
+ return match_check_internal_pcre(column, row, match, start, end);
}
-char *
+char*
Terminal::regex_match_check(vte::grid::column_t column,
- vte::grid::row_t row,
- int *tag)
+ vte::grid::row_t row,
+ int* tag)
{
- char *ret;
-
long delta = m_screen->scroll_delta;
_vte_debug_print(VTE_DEBUG_EVENTS | VTE_DEBUG_REGEX,
"Checking for match at (%ld,%ld).\n",
row, column);
+
+ char* ret{nullptr};
+ Terminal::MatchRegex const* match{nullptr};
+
if (m_match_span.contains(row + delta, column)) {
- if (tag) {
- *tag = m_match_tag;
- }
- ret = m_match != NULL ?
- g_strdup (m_match) :
- NULL;
+ match = regex_match_current(); /* may be nullptr */
+ ret = g_strdup(m_match);
} else {
gsize start, end;
- int ltag;
- ret = match_check_internal(
- column, row + delta,
- tag ? tag : <ag,
- &start, &end);
+ ret = match_check_internal(column, row + delta,
+ &match,
+ &start, &end);
}
_VTE_DEBUG_IF(VTE_DEBUG_EVENTS | VTE_DEBUG_REGEX) {
if (ret != NULL) g_printerr("Matched `%s'.\n", ret);
}
+ if (tag != nullptr)
+ *tag = (match != nullptr) ? match->tag() : -1;
+
return ret;
}
@@ -1673,8 +1482,8 @@ Terminal::hyperlink_check(GdkEvent *event)
}
char *
-Terminal::regex_match_check(GdkEvent *event,
- int *tag)
+Terminal::regex_match_check(GdkEvent* event,
+ int *tag)
{
long col, row;
if (!rowcol_from_event(event, &col, &row))
@@ -1687,10 +1496,10 @@ Terminal::regex_match_check(GdkEvent *event,
bool
Terminal::regex_match_check_extra(GdkEvent *event,
- VteRegex **regexes,
- gsize n_regexes,
- guint32 match_flags,
- char **matches)
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches)
{
gsize offset, sattr, eattr;
pcre2_match_data_8 *match_data;
@@ -1699,9 +1508,9 @@ Terminal::regex_match_check_extra(GdkEvent *event,
long col, row;
guint i;
- g_assert(event);
- g_assert(regexes != nullptr || n_regexes == 0);
- g_assert(matches != nullptr);
+ assert(event);
+ assert(regexes != nullptr || n_regexes == 0);
+ assert(matches != nullptr);
if (!rowcol_from_event(event, &col, &row))
return false;
@@ -1723,8 +1532,7 @@ Terminal::regex_match_check_extra(GdkEvent *event,
g_return_val_if_fail(regexes[i] != nullptr, false);
- if (match_check_pcre(
- match_data, match_context,
+ if (match_check_pcre(match_data, match_context,
regexes[i], match_flags,
sattr, eattr, offset,
&match_string,
@@ -2137,26 +1945,22 @@ Terminal::apply_mouse_cursor()
if (m_hyperlink_hover_idx != 0) {
_vte_debug_print(VTE_DEBUG_CURSOR,
"Setting hyperlink mouse cursor.\n");
- m_real_widget->set_cursor(vte::platform::Widget::Cursor::eHyperlink);
- } else if ((guint)m_match_tag < m_match_regexes->len) {
- struct vte_match_regex *regex =
- &g_array_index(m_match_regexes,
- struct vte_match_regex,
- m_match_tag);
- set_cursor_from_regex_match(regex);
+ m_real_widget->set_cursor(vte::platform::Widget::CursorType::eHyperlink);
+ } else if (regex_match_has_current()) {
+ m_real_widget->set_cursor(regex_match_current()->cursor());
} else if (m_mouse_tracking_mode) {
_vte_debug_print(VTE_DEBUG_CURSOR,
"Setting mousing cursor.\n");
- m_real_widget->set_cursor(vte::platform::Widget::Cursor::eMousing);
+ m_real_widget->set_cursor(vte::platform::Widget::CursorType::eMousing);
} else {
_vte_debug_print(VTE_DEBUG_CURSOR,
"Setting default mouse cursor.\n");
- m_real_widget->set_cursor(vte::platform::Widget::Cursor::eDefault);
+ m_real_widget->set_cursor(vte::platform::Widget::CursorType::eDefault);
}
} else {
_vte_debug_print(VTE_DEBUG_CURSOR,
"Setting to invisible cursor.\n");
- m_real_widget->set_cursor(vte::platform::Widget::Cursor::eInvisible);
+ m_real_widget->set_cursor(vte::platform::Widget::CursorType::eInvisible);
}
}
@@ -5826,7 +5630,7 @@ Terminal::hyperlink_hilite_update()
/* Underlining hyperlinks has precedence over regex matches. So when the hovered hyperlink changes,
* the regex match might need to become or stop being underlined. */
- if (m_match != nullptr)
+ if (regex_match_has_current())
invalidate_match_span();
apply_mouse_cursor();
@@ -5842,16 +5646,14 @@ Terminal::hyperlink_hilite_update()
void
Terminal::match_hilite_clear()
{
- if (m_match != nullptr)
+ if (regex_match_has_current())
invalidate_match_span();
m_match_span.clear();
- m_match_tag = -1;
+ m_match_current = nullptr;
- if (m_match != nullptr) {
- g_free (m_match);
- m_match = nullptr;
- }
+ g_free(m_match);
+ m_match = nullptr;
}
void
@@ -5888,7 +5690,7 @@ Terminal::match_hilite_update()
!(m_mouse_autohide && m_mouse_cursor_autohidden) &&
!m_selecting;
if (!do_check_hilite) {
- if (m_match != nullptr)
+ if (regex_match_has_current())
match_hilite_clear();
return;
}
@@ -5905,7 +5707,7 @@ Terminal::match_hilite_update()
gsize start, end;
auto new_match = match_check_internal(col,
row,
- &m_match_tag,
+ &m_match_current,
&start,
&end);
@@ -7837,16 +7639,9 @@ Terminal::Terminal(vte::platform::Widget* w,
save_cursor(&m_alternate_screen);
/* Matching data. */
- m_match_regexes = g_array_new(FALSE, TRUE,
- sizeof(struct vte_match_regex));
- m_match_tag = -1;
- m_match_span.clear();
+ m_match_span.clear(); // FIXMEchpe unnecessary
match_hilite_clear(); // FIXMEchpe unnecessary
- /* Search data */
- m_search_regex.regex = nullptr;
- m_search_regex.match_flags = 0;
-
/* Rendering data */
m_draw = _vte_draw_new();
@@ -8079,9 +7874,7 @@ Terminal::~Terminal()
/* Make sure not to change selection while in destruction. See issue vte#89. */
m_changing_selection = true;
- struct vte_match_regex *regex;
int sel;
- guint i;
terminate_child();
set_pty(nullptr, false /* don't process remaining data */);
@@ -8108,21 +7901,7 @@ Terminal::~Terminal()
g_array_free(m_match_attributes, TRUE);
}
g_free(m_match_contents);
- if (m_match_regexes != NULL) {
- for (i = 0; i < m_match_regexes->len; i++) {
- regex = &g_array_index(m_match_regexes,
- struct vte_match_regex,
- i);
- /* Skip holes. */
- if (regex->tag < 0) {
- continue;
- }
- regex_match_clear(regex);
- }
- g_array_free(m_match_regexes, TRUE);
- }
- regex_and_flags_clear(&m_search_regex);
if (m_search_attrs)
g_array_free (m_search_attrs, TRUE);
@@ -8897,7 +8676,7 @@ Terminal::draw_rows(VteScreen *screen_,
determine_colors(cell, selected, &nfore, &nback, &ndeco);
nhilite = (nhyperlink && cell->attr.hyperlink_idx == m_hyperlink_hover_idx) ||
- (!nhyperlink && m_match != nullptr && m_match_span.contains(row, col));
+ (!nhyperlink && regex_match_has_current() && m_match_span.contains(row,
col));
/* See if it no longer fits the run. */
if (item_count > 0 &&
@@ -10597,23 +10376,15 @@ Terminal::write_contents_sync (GOutputStream *stream,
* Sets the regex to search for. Unsets the search regex when passed %nullptr.
*/
bool
-Terminal::search_set_regex (VteRegex *regex,
- guint32 flags)
+Terminal::search_set_regex (vte::base::RefPtr<vte::base::Regex>&& regex,
+ uint32_t flags)
{
- struct vte_regex_and_flags *rx;
-
- rx = &m_search_regex;
-
- if (rx->regex == regex &&
- rx->match_flags == flags)
+ if (regex == m_search_regex &&
+ flags == m_search_regex_match_flags)
return false;
- regex_and_flags_clear(rx);
-
- if (regex != nullptr) {
- rx->regex = vte_regex_ref(regex);
- rx->match_flags = flags;
- }
+ m_search_regex = std::move(regex);
+ m_search_regex_match_flags = flags;
invalidate_all();
@@ -10632,10 +10403,10 @@ Terminal::search_set_wrap_around(bool wrap)
bool
Terminal::search_rows(pcre2_match_context_8 *match_context,
- pcre2_match_data_8 *match_data,
- vte::grid::row_t start_row,
- vte::grid::row_t end_row,
- bool backward)
+ pcre2_match_data_8 *match_data,
+ vte::grid::row_t start_row,
+ vte::grid::row_t end_row,
+ bool backward)
{
int start, end;
long start_col, end_col;
@@ -10655,15 +10426,15 @@ Terminal::search_rows(pcre2_match_context_8 *match_context,
gsize *ovector, so, eo;
int r;
- if (_vte_regex_get_jited(m_search_regex.regex))
+ if (m_search_regex->jited())
match_fn = pcre2_jit_match_8;
else
match_fn = pcre2_match_8;
- r = match_fn(_vte_regex_get_pcre(m_search_regex.regex),
+ r = match_fn(m_search_regex->code(),
(PCRE2_SPTR8)row_text->str, row_text->len , /* subject, length */
0, /* start offset */
- m_search_regex.match_flags |
+ m_search_regex_match_flags |
PCRE2_NO_UTF_CHECK | PCRE2_NOTEMPTY | PCRE2_PARTIAL_SOFT /* FIXME: HARD? */,
match_data,
match_context);
@@ -10774,7 +10545,7 @@ Terminal::search_find (bool backward)
vte::grid::row_t last_start_row, last_end_row;
bool match_found = true;
- if (m_search_regex.regex == nullptr)
+ if (!m_search_regex)
return false;
/* TODO
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index bbaac158..3243e10a 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -1954,21 +1954,16 @@ vte_terminal_match_add_regex(VteTerminal *terminal,
VteRegex *regex,
guint32 flags)
{
- struct vte_match_regex new_regex_match;
-
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
g_return_val_if_fail(regex != NULL, -1);
g_return_val_if_fail(_vte_regex_has_purpose(regex, vte::base::Regex::Purpose::eMatch), -1);
g_warn_if_fail(_vte_regex_has_multiline_compile_flag(regex));
auto impl = IMPL(terminal);
-
- new_regex_match.regex.regex = vte_regex_ref(regex);
- new_regex_match.regex.match_flags = flags;
- new_regex_match.cursor_mode = VTE_REGEX_CURSOR_GDKCURSORTYPE;
- new_regex_match.cursor.cursor_type = VTE_DEFAULT_CURSOR;
-
- return impl->regex_match_add(&new_regex_match);
+ return impl->regex_match_add(vte::base::make_ref(regex_from_wrapper(regex)),
+ flags,
+ VTE_DEFAULT_CURSOR,
+ impl->regex_match_next_tag()).tag();
}
/**
@@ -2089,7 +2084,11 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
}
g_return_val_if_fail(matches != NULL, FALSE);
- return IMPL(terminal)->regex_match_check_extra(event, regexes, n_regexes, match_flags, matches);
+ return IMPL(terminal)->regex_match_check_extra(event,
+ regex_array_from_wrappers(regexes),
+ n_regexes,
+ match_flags,
+ matches);
}
/**
@@ -2142,7 +2141,10 @@ vte_terminal_match_set_cursor(VteTerminal *terminal,
GdkCursor *cursor)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- IMPL(terminal)->regex_match_set_cursor(tag, cursor);
+ g_return_if_fail(tag >= 0);
+ auto rem = IMPL(terminal)->regex_match_get(tag);
+ if (rem)
+ rem->set_cursor(vte::glib::make_ref<GdkCursor>(cursor));
}
/**
@@ -2162,7 +2164,10 @@ vte_terminal_match_set_cursor_type(VteTerminal *terminal,
GdkCursorType cursor_type)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- IMPL(terminal)->regex_match_set_cursor(tag, cursor_type);
+ g_return_if_fail(tag >= 0);
+ auto rem = IMPL(terminal)->regex_match_get(tag);
+ if (rem)
+ rem->set_cursor(cursor_type);
}
/**
@@ -2180,10 +2185,12 @@ vte_terminal_match_set_cursor_name(VteTerminal *terminal,
const char *cursor_name)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- IMPL(terminal)->regex_match_set_cursor(tag, cursor_name);
+ g_return_if_fail(tag >= 0);
+ auto rem = IMPL(terminal)->regex_match_get(tag);
+ if (rem)
+ rem->set_cursor(cursor_name);
}
-
/**
* vte_terminal_match_remove:
* @terminal: a #VteTerminal
@@ -2197,7 +2204,7 @@ void
vte_terminal_match_remove(VteTerminal *terminal, int tag)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
- g_return_if_fail(tag != -1);
+ g_return_if_fail(tag >= 0);
IMPL(terminal)->regex_match_remove(tag);
}
@@ -2266,7 +2273,7 @@ vte_terminal_search_set_regex (VteTerminal *terminal,
g_return_if_fail(regex == nullptr || _vte_regex_has_purpose(regex,
vte::base::Regex::Purpose::eSearch));
g_warn_if_fail(regex == nullptr || _vte_regex_has_multiline_compile_flag(regex));
- IMPL(terminal)->search_set_regex(regex, flags);
+ IMPL(terminal)->search_set_regex(vte::base::make_ref(regex_from_wrapper(regex)), flags);
}
/**
@@ -2280,10 +2287,9 @@ vte_terminal_search_set_regex (VteTerminal *terminal,
VteRegex *
vte_terminal_search_get_regex(VteTerminal *terminal)
{
- g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), nullptr);
- auto impl = IMPL(terminal);
- return impl->m_search_regex.regex;
+ return wrapper_from_regex(IMPL(terminal)->search_regex());
}
/**
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 9010b9b0..8ebd99c9 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -41,6 +41,7 @@
#include <list>
#include <queue>
#include <string>
+#include <variant>
#include <vector>
typedef enum {
@@ -86,22 +87,21 @@ enum {
VTE_SGR_COLOR_SPEC_LEGACY = 5
};
-struct vte_regex_and_flags {
- VteRegex *regex;
- guint32 match_flags;
-};
+namespace vte {
+namespace platform {
-/* A match regex, with a tag. */
-struct vte_match_regex {
- gint tag;
- struct vte_regex_and_flags regex;
- VteRegexCursorMode cursor_mode;
- union {
- GdkCursor *cursor;
- char *cursor_name;
- GdkCursorType cursor_type;
- } cursor;
-};
+/*
+ * Cursor:
+ *
+ * Holds a platform cursor. This is either a named cursor (string),
+ * a reference to a GdkCursor*, or a cursor type.
+ */
+using Cursor = std::variant<std::string,
+ vte::glib::RefPtr<GdkCursor>,
+ GdkCursorType>;
+
+} // namespace platform
+} // namespace vte
typedef enum _VteCharacterReplacement {
VTE_CHARACTER_REPLACEMENT_NONE,
@@ -465,11 +465,81 @@ public:
double m_mouse_smooth_scroll_delta{0.0};
/* State variables for handling match checks. */
+ int m_match_regex_next_tag{0};
+ auto regex_match_next_tag() noexcept { return m_match_regex_next_tag++; }
+
+ class MatchRegex {
+ public:
+ MatchRegex() = default;
+ MatchRegex(MatchRegex&&) = default;
+ MatchRegex& operator= (MatchRegex&&) = default;
+
+ MatchRegex(MatchRegex const&) = delete;
+ MatchRegex& operator= (MatchRegex const&) = delete;
+
+ MatchRegex(vte::base::RefPtr<vte::base::Regex>&& regex,
+ uint32_t match_flags,
+ vte::platform::Cursor&& cursor,
+ int tag = -1)
+ : m_regex{std::move(regex)},
+ m_match_flags{match_flags},
+ m_cursor{std::move(cursor)},
+ m_tag{tag}
+ {
+ }
+
+ auto regex() const noexcept { return m_regex.get(); }
+ auto match_flags() const noexcept { return m_match_flags; }
+ auto const& cursor() const noexcept { return m_cursor; }
+ auto tag() const noexcept { return m_tag; }
+
+ void set_cursor(vte::platform::Cursor&& cursor) { m_cursor = std::move(cursor); }
+
+ private:
+ vte::base::RefPtr<vte::base::Regex> m_regex{};
+ uint32_t m_match_flags{0};
+ vte::platform::Cursor m_cursor{VTE_DEFAULT_CURSOR};
+ int m_tag{-1};
+ };
+
+ MatchRegex const* m_match_current{nullptr};
+ bool regex_match_has_current() const noexcept { return m_match_current != nullptr; }
+ auto const* regex_match_current() const noexcept { return m_match_current; }
+
+ std::vector<MatchRegex> m_match_regexes{};
+
+ // m_match_current points into m_match_regex, so every write access to
+ // m_match_regex must go through this function that clears m_current_match
+ auto& match_regexes_writable() noexcept
+ {
+ match_hilite_clear();
+ return m_match_regexes;
+ }
+
+ auto regex_match_get_iter(int tag) noexcept
+ {
+ return std::find_if(std::begin(m_match_regexes), std::end(m_match_regexes),
+ [tag](MatchRegex const& rem) { return rem.tag() == tag; });
+ }
+
+ MatchRegex* regex_match_get(int tag) noexcept
+ {
+ auto i = regex_match_get_iter(tag);
+ if (i == std::end(m_match_regexes))
+ return nullptr;
+
+ return std::addressof(*i);
+ }
+
+ template<class... Args>
+ auto& regex_match_add(Args&&... args)
+ {
+ return match_regexes_writable().emplace_back(std::forward<Args>(args)...);
+ }
+
char* m_match_contents;
GArray* m_match_attributes;
- GArray* m_match_regexes;
char* m_match;
- int m_match_tag;
/* If m_match non-null, then m_match_span contains the region of the match.
* If m_match is null, and m_match_span is not .empty(), then it contains
* the minimal region around the last checked coordinates that don't contain
@@ -478,7 +548,8 @@ public:
vte::grid::span m_match_span;
/* Search data. */
- struct vte_regex_and_flags m_search_regex;
+ vte::base::RefPtr<vte::base::Regex> m_search_regex{};
+ uint32_t m_search_regex_match_flags{0};
gboolean m_search_wrap_around;
GArray* m_search_attrs; /* Cache attrs */
@@ -996,7 +1067,6 @@ public:
void match_contents_clear();
void match_contents_refresh();
- void set_cursor_from_regex_match(struct vte_match_regex *regex);
void match_hilite_clear();
void match_hilite_update();
@@ -1006,14 +1076,12 @@ public:
char *hyperlink_check(GdkEvent *event);
- bool regex_match_check_extra(GdkEvent *event,
- VteRegex **regexes,
- gsize n_regexes,
- guint32 match_flags,
- char **matches);
+ bool regex_match_check_extra(GdkEvent* event,
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches);
- int regex_match_add(struct vte_match_regex *new_regex_match);
- struct vte_match_regex *regex_match_get(int tag);
char *regex_match_check(vte::grid::column_t column,
vte::grid::row_t row,
int *tag);
@@ -1036,8 +1104,8 @@ public:
pcre2_match_context_8 *create_match_context();
bool match_check_pcre(pcre2_match_data_8 *match_data,
pcre2_match_context_8 *match_context,
- VteRegex *regex,
- guint32 match_flags,
+ vte::base::Regex const* regex,
+ uint32_t match_flags,
gsize sattr,
gsize eattr,
gsize offset,
@@ -1048,13 +1116,13 @@ public:
gsize *eblank_ptr);
char *match_check_internal_pcre(vte::grid::column_t column,
vte::grid::row_t row,
- int *tag,
+ MatchRegex const** match,
gsize *start,
gsize *end);
char *match_check_internal(vte::grid::column_t column,
vte::grid::row_t row,
- int *tag,
+ MatchRegex const** match,
gsize *start,
gsize *end);
@@ -1072,8 +1140,9 @@ public:
void feed_focus_event_initial();
void maybe_feed_focus_event(bool in);
- bool search_set_regex (VteRegex *regex,
- guint32 flags);
+ bool search_set_regex(vte::base::RefPtr<vte::base::Regex>&& regex,
+ uint32_t flags) noexcept;
+ auto search_regex() const noexcept { return m_search_regex.get(); }
bool search_rows(pcre2_match_context_8 *match_context,
pcre2_match_data_8 *match_data,
diff --git a/src/vteregex.cc b/src/vteregex.cc
index 75f33e7b..d95c77aa 100644
--- a/src/vteregex.cc
+++ b/src/vteregex.cc
@@ -32,8 +32,7 @@
#include "regex.hh"
#include "vteregexinternal.hh"
-#define WRAPPER(impl) (reinterpret_cast<VteRegex*>(impl))
-#define IMPL(wrapper) (reinterpret_cast<vte::base::Regex*>(wrapper))
+#define IMPL(wrapper) (regex_from_wrapper(wrapper))
/* GRegex translation */
@@ -87,7 +86,7 @@ vte_regex_ref(VteRegex *regex)
{
g_return_val_if_fail(regex != nullptr, nullptr);
- return WRAPPER(IMPL(regex)->ref());
+ return wrapper_from_regex(IMPL(regex)->ref());
}
/**
@@ -115,7 +114,7 @@ vte_regex_new(vte::base::Regex::Purpose purpose,
uint32_t flags,
GError** error)
{
- return WRAPPER(vte::base::Regex::compile(purpose, pattern, pattern_length, flags, error));
+ return wrapper_from_regex(vte::base::Regex::compile(purpose, pattern, pattern_length, flags, error));
}
VteRegex*
@@ -269,22 +268,6 @@ _vte_regex_has_purpose(VteRegex *regex,
return IMPL(regex)->has_purpose(purpose);
}
-const pcre2_code_8 *
-_vte_regex_get_pcre(VteRegex* regex)
-{
- g_return_val_if_fail(regex != nullptr, nullptr);
-
- return IMPL(regex)->code();
-}
-
-bool
-_vte_regex_get_jited(VteRegex *regex)
-{
- g_return_val_if_fail(regex != nullptr, false);
-
- return IMPL(regex)->jited();
-}
-
bool
_vte_regex_has_multiline_compile_flag(VteRegex *regex)
{
diff --git a/src/vteregexinternal.hh b/src/vteregexinternal.hh
index d5b744ec..ac4e675d 100644
--- a/src/vteregexinternal.hh
+++ b/src/vteregexinternal.hh
@@ -19,15 +19,26 @@
#include "regex.hh"
+static inline auto wrapper_from_regex(vte::base::Regex* regex)
+{
+ return reinterpret_cast<VteRegex*>(regex);
+}
+
+static inline auto regex_from_wrapper(VteRegex* regex)
+{
+ return reinterpret_cast<vte::base::Regex*>(regex);
+}
+
+static inline auto regex_array_from_wrappers(VteRegex** regexes)
+{
+ return const_cast<vte::base::Regex const**>(reinterpret_cast<vte::base::Regex**>(regexes));
+}
+
bool _vte_regex_has_purpose(VteRegex* regex,
vte::base::Regex::Purpose purpose);
-bool _vte_regex_get_jited(VteRegex* regex);
-
bool _vte_regex_has_multiline_compile_flag(VteRegex* regex);
-const pcre2_code_8 *_vte_regex_get_pcre(VteRegex* regex);
-
/* GRegex translation */
VteRegex* _vte_regex_new_gregex(vte::base::Regex::Purpose purpose,
GRegex* gregex);
diff --git a/src/widget.cc b/src/widget.cc
index 331ddba9..6334f6af 100644
--- a/src/widget.cc
+++ b/src/widget.cc
@@ -121,10 +121,47 @@ Widget::beep() noexcept
gdk_window_beep(gtk_widget_get_window(m_widget));
}
-GdkCursor*
+vte::glib::RefPtr<GdkCursor>
Widget::create_cursor(GdkCursorType cursor_type) const noexcept
{
- return gdk_cursor_new_for_display(gtk_widget_get_display(m_widget), cursor_type);
+ return vte::glib::take_ref(gdk_cursor_new_for_display(gtk_widget_get_display(m_widget), cursor_type));
+}
+
+void
+Widget::set_cursor(GdkCursor* cursor) noexcept
+{
+ gdk_window_set_cursor(m_event_window, cursor);
+}
+
+void
+Widget::set_cursor(Cursor const& cursor) noexcept
+{
+ if (!realized())
+ return;
+
+ auto display = gtk_widget_get_display(m_widget);
+ GdkCursor* gdk_cursor{nullptr};
+ switch (cursor.index()) {
+ case 0:
+ gdk_cursor = gdk_cursor_new_from_name(display, std::get<0>(cursor).c_str());
+ break;
+ case 1:
+ gdk_cursor = std::get<1>(cursor).get();
+ if (gdk_cursor != nullptr &&
+ gdk_cursor_get_display(gdk_cursor) == display) {
+ g_object_ref(gdk_cursor);
+ } else {
+ gdk_cursor = nullptr;
+ }
+ break;
+ case 2:
+ gdk_cursor = gdk_cursor_new_for_display(display, std::get<2>(cursor));
+ break;
+ }
+
+ set_cursor(gdk_cursor);
+ if (gdk_cursor)
+ g_object_unref(gdk_cursor);
}
void
@@ -308,13 +345,13 @@ Widget::settings_changed() noexcept
}
void
-Widget::set_cursor(Cursor type) noexcept
+Widget::set_cursor(CursorType type) noexcept
{
switch (type) {
- case Cursor::eDefault: return set_cursor(m_default_cursor.get());
- case Cursor::eInvisible: return set_cursor(m_invisible_cursor.get());
- case Cursor::eMousing: return set_cursor(m_mousing_cursor.get());
- case Cursor::eHyperlink: return set_cursor(m_hyperlink_cursor.get());
+ case CursorType::eDefault: return set_cursor(m_default_cursor.get());
+ case CursorType::eInvisible: return set_cursor(m_invisible_cursor.get());
+ case CursorType::eMousing: return set_cursor(m_mousing_cursor.get());
+ case CursorType::eHyperlink: return set_cursor(m_hyperlink_cursor.get());
}
}
diff --git a/src/widget.hh b/src/widget.hh
index 932f7f91..6338cb70 100644
--- a/src/widget.hh
+++ b/src/widget.hh
@@ -18,6 +18,8 @@
#pragma once
#include <memory>
+#include <string>
+#include <variant>
#include "vteterminal.h"
#include "vteinternal.hh"
@@ -27,8 +29,10 @@
namespace vte {
namespace terminal {
+
class Terminal;
-}
+
+} // namespace terminal
namespace platform {
@@ -106,7 +110,7 @@ public:
protected:
- enum class Cursor {
+ enum class CursorType {
eDefault,
eInvisible,
eMousing,
@@ -120,14 +124,11 @@ protected:
return gtk_widget_get_realized(m_widget);
}
- GdkCursor *create_cursor(GdkCursorType cursor_type) const noexcept;
-
- void set_cursor(Cursor type) noexcept;
+ vte::glib::RefPtr<GdkCursor> create_cursor(GdkCursorType cursor_type) const noexcept;
- void set_cursor(GdkCursor* cursor) noexcept
- {
- gdk_window_set_cursor(m_event_window, cursor);
- }
+ void set_cursor(CursorType type) noexcept;
+ void set_cursor(GdkCursor* cursor) noexcept;
+ void set_cursor(Cursor const& cursor) noexcept;
bool im_filter_keypress(GdkEventKey* event) noexcept;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]