[vte] regex: Translate GRegex to PCRE2



commit 00f252725c1eb1c5dc65fd9901221523418e18be
Author: Christian Persch <chpe gnome org>
Date:   Thu Aug 4 17:51:44 2016 +0200

    regex: Translate GRegex to PCRE2
    
    Instead of duplicating all internal functions to deal with either
    a PCRE2 regex or a GRegex, just translate the GRegex to PCRE2 in
    the API entry points.

 src/vte.cc              |  344 +++--------------------------------------------
 src/vtegtk.cc           |   72 ++++------
 src/vteinternal.hh      |   42 +------
 src/vteregex.cc         |   90 ++++++++++++
 src/vteregexinternal.hh |    6 +
 5 files changed, 149 insertions(+), 405 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index d3ff12a..0348b3b 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1052,14 +1052,10 @@ regex_match_clear_cursor (struct vte_match_regex *regex)
 static void
 regex_and_flags_clear(struct vte_regex_and_flags *regex)
 {
-        if (regex->mode == VTE_REGEX_PCRE2) {
-                vte_regex_unref(regex->pcre.regex);
-                regex->pcre.regex = NULL;
-        } else if (regex->mode == VTE_REGEX_GREGEX) {
-                g_regex_unref(regex->gregex.regex);
-                regex->gregex.regex = NULL;
+        if (regex->regex) {
+                vte_regex_unref(regex->regex);
+                regex->regex = nullptr;
         }
-        regex->mode = VTE_REGEX_UNDECIDED;
 }
 
 static void
@@ -1155,9 +1151,6 @@ VteTerminalPrivate::regex_match_add(struct vte_match_regex *new_regex_match)
         struct vte_match_regex *regex_match;
         guint ret, len;
 
-        g_assert(m_match_regex_mode == VTE_REGEX_UNDECIDED || m_match_regex_mode == 
new_regex_match->regex.mode);
-        m_match_regex_mode = new_regex_match->regex.mode;
-
         /* Search for a hole. */
         len = m_match_regexes->len;
         for (ret = 0; ret < len; ret++) {
@@ -1545,11 +1538,9 @@ VteTerminalPrivate::match_check_internal_pcre(vte::grid::column_t column,
                        continue;
                }
 
-                g_assert_cmpint(regex->regex.mode, ==, VTE_REGEX_PCRE2);
-
                 if (match_check_pcre(match_data, match_context,
-                                     regex->regex.pcre.regex,
-                                     regex->regex.pcre.match_flags,
+                                     regex->regex.regex,
+                                     regex->regex.match_flags,
                                      sattr, eattr, offset,
                                      &dingu_match,
                                      start, end,
@@ -1597,178 +1588,6 @@ VteTerminalPrivate::match_check_internal_pcre(vte::grid::column_t column,
 
 #endif /* WITH_PCRE2 */
 
-bool
-VteTerminalPrivate::match_check_gregex(GRegex *regex,
-                   GRegexMatchFlags match_flags,
-                   gsize sattr,
-                   gsize eattr,
-                   gsize offset,
-                   char **result_ptr,
-                   gsize *start,
-                   gsize *end,
-                   gsize *sblank_ptr,
-                   gsize *eblank_ptr)
-{
-        GMatchInfo *match_info;
-        const char *line;
-        gsize line_length;
-        gint sblank = G_MININT, eblank = G_MAXINT;
-
-        line = m_match_contents;
-        line_length = eattr;
-
-        /* We'll only match the first item in the buffer which
-         * matches, so we'll have to skip each match until we
-         * stop getting matches. */
-        if (!g_regex_match_full(regex,
-                                line, line_length, /* subject, length */
-                                sattr, /* start position */
-                                match_flags,
-                                &match_info,
-                                NULL)) {
-                g_match_info_free(match_info);
-                return FALSE;
-        }
-
-        while (g_match_info_matches(match_info)) {
-                gint ko = offset;
-                gint rm_so, rm_eo;
-
-                if (g_match_info_fetch_pos (match_info, 0, &rm_so, &rm_eo)) {
-                        /* The offsets should be "sane". */
-                        g_assert(rm_so < (int)eattr);
-                        g_assert(rm_eo <= (int)eattr);
-                        _VTE_DEBUG_IF(VTE_DEBUG_REGEX) {
-                                gchar *result;
-                                struct _VteCharAttributes *_sattr, *_eattr;
-                                result = g_strndup(line + rm_so, rm_eo - rm_so);
-                                _sattr = &g_array_index(m_match_attributes,
-                                                       struct _VteCharAttributes,
-                                                       rm_so);
-                                _eattr = &g_array_index(m_match_attributes,
-                                                       struct _VteCharAttributes,
-                                                       rm_eo - 1);
-                                g_printerr("Match `%s' from %d(%ld,%ld) to %d(%ld,%ld) (%" G_GSIZE_FORMAT 
").\n",
-                                           result,
-                                           rm_so,
-                                           _sattr->column,
-                                           _sattr->row,
-                                           rm_eo - 1,
-                                           _eattr->column,
-                                           _eattr->row,
-                                           offset);
-                                g_free(result);
-
-                        }
-                        /* If the pointer is in this substring,
-                         * then we're done. */
-                        if (ko >= rm_so && ko < rm_eo) {
-                                *start = rm_so;
-                                *end = rm_eo - 1;
-                                *result_ptr = g_match_info_fetch(match_info, 0);
-
-                                g_match_info_free(match_info);
-                                return true;
-                        }
-
-                        if (ko >= rm_eo && rm_eo > sblank) {
-                                sblank = rm_eo;
-                        }
-                        if (ko < rm_so && rm_so < eblank) {
-                                eblank = rm_so;
-                        }
-                }
-
-                g_match_info_next(match_info, NULL);
-        }
-
-        g_match_info_free(match_info);
-
-        *sblank_ptr = sblank;
-        *eblank_ptr = eblank;
-        return false;
-}
-
-char *
-VteTerminalPrivate::match_check_internal_gregex(vte::grid::column_t column,
-                                                vte::grid::row_t row,
-                                                int *tag,
-                                                gsize *start,
-                                                gsize *end)
-{
-        guint i;
-       struct vte_match_regex *regex = nullptr;
-       gsize sattr, eattr, offset, start_blank, end_blank;
-        char *dingu_match = nullptr;
-
-       _vte_debug_print(VTE_DEBUG_REGEX,
-                         "Checking for gregex match at (%ld,%ld).\n", row, column);
-
-        if (!match_rowcol_to_offset(column, row,
-                                    &offset, &sattr, &eattr))
-                return nullptr;
-
-       start_blank = sattr;
-       end_blank = eattr;
-
-       /* Now iterate over each regex we need to match against. */
-       for (i = 0; i < m_match_regexes->len; i++) {
-                gsize sblank = 0, eblank = G_MAXSIZE;
-
-               regex = &g_array_index(m_match_regexes,
-                                      struct vte_match_regex,
-                                      i);
-               /* Skip holes. */
-               if (regex->tag < 0) {
-                       continue;
-               }
-
-                g_assert_cmpint(regex->regex.mode, ==, VTE_REGEX_GREGEX);
-
-                if (match_check_gregex(regex->regex.gregex.regex,
-                                       regex->regex.gregex.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);
-                        set_cursor_from_regex_match(regex);
-                        *tag = regex->tag;
-                        break;
-                }
-
-                if (sblank > start_blank) {
-                        start_blank = sblank;
-                }
-                if (eblank < end_blank) {
-                        end_blank = eblank;
-                }
-       }
-
-        if (dingu_match == nullptr) {
-                /* If we get here, there was no dingu match.
-                 * Record smallest span where none of the dingus match.
-                 */
-                *start = start_blank;
-                *end = end_blank - 1;
-
-                _VTE_DEBUG_IF(VTE_DEBUG_REGEX) {
-                        struct _VteCharAttributes *_sattr, *_eattr;
-                        _sattr = &g_array_index(m_match_attributes,
-                                                struct _VteCharAttributes,
-                                                start_blank);
-                        _eattr = &g_array_index(m_match_attributes,
-                                                struct _VteCharAttributes,
-                                                end_blank - 1);
-                        g_printerr("No-match region from %" G_GSIZE_FORMAT "(%ld,%ld) to %" G_GSIZE_FORMAT 
"(%ld,%ld)\n",
-                                   start_blank, _sattr->column, _sattr->row,
-                                   end_blank - 1, _eattr->column, _eattr->row);
-                }
-        }
-
-       return dingu_match;
-}
-
 /*
  * vte_terminal_match_check_internal:
  * @terminal:
@@ -1805,13 +1624,10 @@ VteTerminalPrivate::match_check_internal(vte::grid::column_t column,
         *end = 0;
 
 #ifdef WITH_PCRE2
-        if (G_LIKELY(m_match_regex_mode == VTE_REGEX_PCRE2))
-                return match_check_internal_pcre(column, row, tag, start, end);
-#endif
-        if (m_match_regex_mode == VTE_REGEX_GREGEX)
-                return match_check_internal_gregex(column, row, tag, start, end);
-
+        return match_check_internal_pcre(column, row, tag, start, end);
+#else
         return nullptr;
+#endif
 }
 
 char *
@@ -2071,55 +1887,6 @@ VteTerminalPrivate::regex_match_check_extra(GdkEvent *event,
 #endif
 }
 
-bool
-VteTerminalPrivate::regex_match_check_extra(GdkEvent *event,
-                                            GRegex **regexes,
-                                            gsize n_regexes,
-                                            GRegexMatchFlags match_flags,
-                                            char **matches)
-{
-       gsize offset, sattr, eattr;
-        gboolean any_matches = FALSE;
-        long col, row;
-        guint i;
-
-        g_assert(event);
-        g_assert(regexes != nullptr || n_regexes == 0);
-        g_assert(matches != nullptr);
-
-        if (!rowcol_from_event(event, &col, &row))
-                return false;
-
-       if (m_match_contents == nullptr) {
-               match_contents_refresh();
-       }
-
-        if (!match_rowcol_to_offset(col, row,
-                                    &offset, &sattr, &eattr))
-                return false;
-
-        for (i = 0; i < n_regexes; i++) {
-                gsize start, end, sblank, eblank;
-                char *match_string;
-
-                g_return_val_if_fail(regexes[i] != nullptr, FALSE);
-
-                if (match_check_gregex(
-                                       regexes[i], match_flags,
-                                       sattr, eattr, offset,
-                                       &match_string,
-                                       &start, &end,
-                                       &sblank, &eblank)) {
-                        _vte_debug_print(VTE_DEBUG_REGEX, "Matched gregex with text: %s\n", match_string);
-                        matches[i] = match_string;
-                        any_matches = true;
-                } else
-                        matches[i] = nullptr;
-        }
-
-        return any_matches;
-}
-
 /* Emit an adjustment changed signal on our adjustment object. */
 void
 VteTerminalPrivate::emit_adjustment_changed()
@@ -8116,7 +7883,6 @@ VteTerminalPrivate::VteTerminalPrivate(VteTerminal *t) :
         save_cursor(&m_alternate_screen);
 
        /* Matching data. */
-        m_match_regex_mode = VTE_REGEX_UNDECIDED;
        m_match_regexes = g_array_new(FALSE, TRUE,
                                         sizeof(struct vte_match_regex));
         m_match_tag = -1;
@@ -8124,7 +7890,8 @@ VteTerminalPrivate::VteTerminalPrivate(VteTerminal *t) :
        match_hilite_clear(); // FIXMEchpe unnecessary
 
         /* Search data */
-        m_search_regex.mode = VTE_REGEX_UNDECIDED;
+        m_search_regex.regex = nullptr;
+        m_search_regex.match_flags = 0;
 
        /* Rendering data */
        m_draw = _vte_draw_new();
@@ -10979,17 +10746,15 @@ VteTerminalPrivate::search_set_regex (VteRegex *regex,
 
         rx = &m_search_regex;
 
-        if (rx->mode == VTE_REGEX_PCRE2 &&
-            rx->pcre.regex == regex &&
-            rx->pcre.match_flags == flags)
+        if (rx->regex == regex &&
+            rx->match_flags == flags)
                 return false;
 
         regex_and_flags_clear(rx);
 
-        if (regex != NULL) {
-                rx->mode = VTE_REGEX_PCRE2;
-                rx->pcre.regex = vte_regex_ref(regex);
-                rx->pcre.match_flags = flags;
+        if (regex != nullptr) {
+                rx->regex = vte_regex_ref(regex);
+                rx->match_flags = flags;
         }
 
        invalidate_all();
@@ -10999,37 +10764,6 @@ VteTerminalPrivate::search_set_regex (VteRegex *regex,
 
 #endif /* WITH_PCRE2 */
 
-/*
- * VteTerminalPrivate::search_set_gregex:
- * @gregex: (allow-none): a #GRegex, or %nullptr
- * @gflags: flags from #GRegexMatchFlags
- *
- * Sets the #GRegex regex to search for. Unsets the search regex when passed %nullptr.
- */
-bool
-VteTerminalPrivate::search_set_gregex(GRegex *gregex,
-                                      GRegexMatchFlags gflags)
-{
-        struct vte_regex_and_flags *rx = &m_search_regex;
-
-        if (rx->mode == VTE_REGEX_GREGEX &&
-            rx->gregex.regex == gregex &&
-            rx->gregex.match_flags == gflags)
-                return false;
-
-        regex_and_flags_clear(rx);
-
-        if (gregex != NULL) {
-                rx->mode = VTE_REGEX_GREGEX;
-                rx->gregex.regex = g_regex_ref(gregex);
-                rx->gregex.match_flags = gflags;
-        }
-
-       invalidate_all();
-
-        return true;
-}
-
 bool
 VteTerminalPrivate::search_set_wrap_around(bool wrap)
 {
@@ -11069,22 +10803,21 @@ VteTerminalPrivate::search_rows(
                             &row_text_length);
 
 #ifdef WITH_PCRE2
-        if (G_LIKELY(m_search_regex.mode == VTE_REGEX_PCRE2)) {
                 int (* match_fn) (const pcre2_code_8 *,
                                   PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE, uint32_t,
                                   pcre2_match_data_8 *, pcre2_match_context_8 *);
                 gsize *ovector, so, eo;
                 int r;
 
-                if (_vte_regex_get_jited(m_search_regex.pcre.regex))
+                if (_vte_regex_get_jited(m_search_regex.regex))
                         match_fn = pcre2_jit_match_8;
                 else
                         match_fn = pcre2_match_8;
 
-                r = match_fn(_vte_regex_get_pcre(m_search_regex.pcre.regex),
+                r = match_fn(_vte_regex_get_pcre(m_search_regex.regex),
                              (PCRE2_SPTR8)row_text, row_text_length , /* subject, length */
                              0, /* start offset */
-                             m_search_regex.pcre.match_flags |
+                             m_search_regex.match_flags |
                              PCRE2_NO_UTF_CHECK | PCRE2_NOTEMPTY | PCRE2_PARTIAL_SOFT /* FIXME: HARD? */,
                              match_data,
                              match_context);
@@ -11104,37 +10837,9 @@ VteTerminalPrivate::search_rows(
                 start = so;
                 end = eo;
                 word = g_strndup(row_text, end - start);
-        } else
+#else
+                return false;
 #endif /* WITH_PCRE2 */
-        {
-                GMatchInfo *match_info;
-                GError *error = NULL;
-
-                g_assert_cmpint(m_search_regex.mode, ==, VTE_REGEX_GREGEX);
-
-                g_regex_match_full (m_search_regex.gregex.regex, row_text, row_text_length, 0,
-                                    (GRegexMatchFlags)(m_search_regex.gregex.match_flags | 
G_REGEX_MATCH_NOTEMPTY),
-                                    &match_info, &error);
-                if (error) {
-                        g_printerr ("Error while matching: %s\n", error->message);
-                        g_error_free (error);
-                        g_match_info_free (match_info);
-                        g_free (row_text);
-                        return false;
-                }
-
-                if (!g_match_info_matches (match_info)) {
-                        g_match_info_free (match_info);
-                        g_free (row_text);
-                        return false;
-                }
-
-                word = g_match_info_fetch (match_info, 0);
-                /* This gives us the offset in the buffer */
-                g_match_info_fetch_pos (match_info, 0, &start, &end);
-
-                g_match_info_free (match_info);
-        }
 
        /* Fetch text again, with attributes */
        g_free (row_text);
@@ -11237,19 +10942,14 @@ VteTerminalPrivate::search_find (bool backward)
         pcre2_match_data_8 *match_data = nullptr;
 #endif
 
-       if (m_search_regex.mode == VTE_REGEX_UNDECIDED)
-               return false;
-
        /* TODO
         * Currently We only find one result per extended line, and ignore columns
         * Moreover, the whole search thing is implemented very inefficiently.
         */
 
 #ifdef WITH_PCRE2
-        if (G_LIKELY(m_search_regex.mode == VTE_REGEX_PCRE2)) {
-                match_context = create_match_context();
-                match_data = pcre2_match_data_create_8(256 /* should be plenty */, nullptr /* general 
context */);
-        }
+        match_context = create_match_context();
+        match_data = pcre2_match_data_create_8(256 /* should be plenty */, nullptr /* general context */);
 #endif
 
        buffer_start_row = _vte_ring_delta (m_screen->row_data);
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 944ab1c..d875a95 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -1692,7 +1692,7 @@ vte_terminal_paste_primary(VteTerminal *terminal)
  * this expression, the text will be highlighted.
  *
  * Returns: an integer associated with this expression, or -1 if @gregex could not be
- *   transformed into a #VteRegex or @flags were incompatible
+ *   transformed into a #VteRegex or @gflags were incompatible
  *
  * Deprecated: 0.46: Use vte_terminal_match_add_regex() or vte_terminal_match_add_regex_full() instead.
  */
@@ -1701,24 +1701,17 @@ vte_terminal_match_add_gregex(VteTerminal *terminal,
                               GRegex *gregex,
                               GRegexMatchFlags gflags)
 {
-       struct vte_match_regex new_regex_match;
-
-        g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
         g_return_val_if_fail(gregex != NULL, -1);
-
-        auto impl = IMPL(terminal);
-        /* Can't mix GRegex and PCRE2 */
-        g_return_val_if_fail(impl->m_match_regex_mode != VTE_REGEX_PCRE2, -1);
-
         g_warn_if_fail(g_regex_get_compile_flags(gregex) & G_REGEX_MULTILINE);
 
-        new_regex_match.regex.mode = VTE_REGEX_GREGEX;
-        new_regex_match.regex.gregex.regex = g_regex_ref(gregex);
-        new_regex_match.regex.gregex.match_flags = gflags;
-        new_regex_match.cursor_mode = VTE_REGEX_CURSOR_GDKCURSORTYPE;
-        new_regex_match.cursor.cursor_type = VTE_DEFAULT_CURSOR;
+        auto regex = _vte_regex_new_gregex(VteRegexPurpose::match, gregex);
+        if (regex == NULL)
+                return -1;
 
-        return impl->regex_match_add(&new_regex_match);
+        auto rv = vte_terminal_match_add_regex(terminal, regex,
+                                               _vte_regex_translate_gregex_match_flags(gflags));
+        vte_regex_unref(regex);
+        return rv;
 }
 
 /**
@@ -1747,12 +1740,9 @@ vte_terminal_match_add_regex(VteTerminal *terminal,
         g_return_val_if_fail(_vte_regex_has_purpose(regex, VteRegexPurpose::match), -1);
 
         auto impl = IMPL(terminal);
-        /* Can't mix GRegex and PCRE2 */
-        g_return_val_if_fail(impl->m_match_regex_mode != VTE_REGEX_GREGEX, -1);
 
-        new_regex_match.regex.mode = VTE_REGEX_PCRE2;
-        new_regex_match.regex.pcre.regex = vte_regex_ref(regex);
-        new_regex_match.regex.pcre.match_flags = flags;
+        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;
 
@@ -1863,12 +1853,9 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
  * @match_flags: the #GRegexMatchFlags to use when matching the regexes
  * @matches: (out caller-allocates) (array length=n_regexes): a location to store the matches
  *
- * Checks each regex in @regexes if the text in and around the position of
- * the event matches the regular expressions.  If a match exists, the matched
- * text is stored in @matches at the position of the regex in @regexes; otherwise
- * %NULL is stored there.
+ * This function does nothing.
  *
- * Returns: %TRUE iff any of the regexes produced a match
+ * Returns: %FALSE
  *
  * Since: 0.44
  * Deprecated: 0.46: Use vte_terminal_event_check_regex_simple() instead.
@@ -1886,7 +1873,7 @@ vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
         g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
         g_return_val_if_fail(matches != NULL, FALSE);
 
-        return IMPL(terminal)->regex_match_check_extra(event, regexes, n_regexes, match_flags, matches);
+        return FALSE;
 }
 
 /**
@@ -1983,7 +1970,7 @@ vte_terminal_match_remove_all(VteTerminal *terminal)
  * @terminal: a #VteTerminal
  *
  * Searches the previous string matching the search regex set with
- * vte_terminal_search_set_gregex().
+ * vte_terminal_search_set_regex().
  *
  * Returns: %TRUE if a match was found
  */
@@ -1999,7 +1986,7 @@ vte_terminal_search_find_previous (VteTerminal *terminal)
  * @terminal: a #VteTerminal
  *
  * Searches the next string matching the search regex set with
- * vte_terminal_search_set_gregex().
+ * vte_terminal_search_set_regex().
  *
  * Returns: %TRUE if a match was found
  */
@@ -2047,10 +2034,7 @@ vte_terminal_search_get_regex(VteTerminal *terminal)
        g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
 
         auto impl = IMPL(terminal);
-        if (G_LIKELY(impl->m_search_regex.mode == VTE_REGEX_PCRE2))
-                return impl->m_search_regex.pcre.regex;
-        else
-                return NULL;
+        return impl->m_search_regex.regex;
 }
 
 /**
@@ -2068,16 +2052,22 @@ vte_terminal_search_set_gregex (VteTerminal *terminal,
                                GRegex      *gregex,
                                 GRegexMatchFlags gflags)
 {
-        g_return_if_fail(VTE_IS_TERMINAL(terminal));
+        VteRegex *regex = nullptr;
+        if (gregex)
+                regex = _vte_regex_new_gregex(VteRegexPurpose::search, gregex);
+
+        vte_terminal_search_set_regex(terminal, regex,
+                                      _vte_regex_translate_gregex_match_flags(gflags));
 
-        IMPL(terminal)->search_set_gregex(gregex, gflags);
+        if (regex)
+                vte_regex_unref(regex);
 }
 
 /**
  * vte_terminal_search_get_gregex:
  * @terminal: a #VteTerminal
  *
- * Returns: (transfer none): the search #GRegex regex set in @terminal, or %NULL
+ * Returns: (transfer none): %NULL
  *
  * Deprecated: 0.46: use vte_terminal_search_get_regex() instead.
  */
@@ -2086,11 +2076,7 @@ vte_terminal_search_get_gregex (VteTerminal *terminal)
 {
        g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
 
-        auto impl = IMPL(terminal);
-        if (G_LIKELY(impl->m_search_regex.mode == VTE_REGEX_GREGEX))
-                return impl->m_search_regex.gregex.regex;
-        else
-                return NULL;
+        return NULL;
 }
 
 /**
@@ -2305,7 +2291,7 @@ vte_terminal_spawn_sync(VteTerminal *terminal,
 /**
  * vte_terminal_feed:
  * @terminal: a #VteTerminal
- * @data: (array length=length) (element-type guint8): a string in the terminal's current encoding
+ * @data: (array length=length) (element-type guint8) (allow-none): a string in the terminal's current 
encoding
  * @length: the length of the string, or -1 to use the full length or a nul-terminated string
  *
  * Interprets @data as if it were data received from a child process.  This
@@ -2326,7 +2312,7 @@ vte_terminal_feed(VteTerminal *terminal,
 /**
  * vte_terminal_feed_child:
  * @terminal: a #VteTerminal
- * @text: data to send to the child
+ * @text: (element-type utf8) (allow-none): data to send to the child
  * @length: length of @text in bytes, or -1 if @text is NUL-terminated
  *
  * Sends a block of UTF-8 text to the child as if it were entered by the user
@@ -2346,7 +2332,7 @@ vte_terminal_feed_child(VteTerminal *terminal,
 /**
  * vte_terminal_feed_child_binary:
  * @terminal: a #VteTerminal
- * @data: data to send to the child
+ * @data: (array length=length) (element-type guint8) (allow-none): data to send to the child
  * @length: length of @data
  *
  * Sends a block of binary data to the child.
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 7292c33..a5f1bbe 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -32,12 +32,6 @@
 #endif
 
 typedef enum {
-        VTE_REGEX_UNDECIDED,
-        VTE_REGEX_PCRE2,
-        VTE_REGEX_GREGEX
-} VteRegexMode;
-
-typedef enum {
         VTE_REGEX_CURSOR_GDKCURSOR,
         VTE_REGEX_CURSOR_GDKCURSORTYPE,
         VTE_REGEX_CURSOR_NAME
@@ -54,17 +48,8 @@ typedef enum {
 } MouseTrackingMode;
 
 struct vte_regex_and_flags {
-        VteRegexMode mode;
-        union { /* switched on @mode */
-                struct {
-                        VteRegex *regex;
-                        guint32 match_flags;
-                } pcre;
-                struct {
-                        GRegex *regex;
-                        GRegexMatchFlags match_flags;
-                } gregex;
-        };
+        VteRegex *regex;
+        guint32 match_flags;
 };
 
 /* A match regex, with a tag. */
@@ -451,7 +436,6 @@ public:
        /* State variables for handling match checks. */
         char* m_match_contents;
         GArray* m_match_attributes;
-        VteRegexMode m_match_regex_mode;
         GArray* m_match_regexes;
         char* m_match;
         int m_match_tag;
@@ -979,11 +963,6 @@ public:
                                      gsize n_regexes,
                                      guint32 match_flags,
                                      char **matches);
-        bool regex_match_check_extra(GdkEvent *event,
-                                     GRegex **regexes,
-                                     gsize n_regexes,
-                                     GRegexMatchFlags match_flags,
-                                     char **matches);
 
         int regex_match_add(struct vte_match_regex *new_regex_match);
         struct vte_match_regex *regex_match_get(int tag);
@@ -1025,21 +1004,6 @@ public:
                                         gsize *start,
                                         gsize *end);
 #endif
-        bool match_check_gregex(GRegex *regex,
-                                GRegexMatchFlags match_flags,
-                                gsize sattr,
-                                gsize eattr,
-                                gsize offset,
-                                char **result,
-                                gsize *start,
-                                gsize *end,
-                                gsize *sblank_ptr,
-                                gsize *eblank_ptr);
-        char *match_check_internal_gregex(vte::grid::column_t column,
-                                          vte::grid::row_t row,
-                                          int *tag,
-                                          gsize *start,
-                                          gsize *end);
 
         char *match_check_internal(vte::grid::column_t column,
                                    vte::grid::row_t row,
@@ -1065,8 +1029,6 @@ public:
         bool search_set_regex (VteRegex *regex,
                                guint32 flags);
 #endif
-        bool search_set_gregex (GRegex *gregex,
-                                GRegexMatchFlags gflags);
 
         bool search_rows(
 #ifdef WITH_PCRE2
diff --git a/src/vteregex.cc b/src/vteregex.cc
index 672bf02..d6b6a29 100644
--- a/src/vteregex.cc
+++ b/src/vteregex.cc
@@ -52,6 +52,35 @@ struct _VteRegex {
 #define DEFAULT_MATCH_OPTIONS (0)
 #endif /* WITH_PCRE2 */
 
+/* GRegex translation */
+
+typedef struct {
+        guint32 gflag;
+        guint32 pflag;
+} FlagTranslation;
+
+static void
+translate_flags(FlagTranslation const* const table,
+                gsize table_len,
+                guint32 *gflagsptr /* inout */,
+                guint32 *pflagsptr /* inout */)
+{
+        auto gflags = *gflagsptr;
+        auto pflags = *pflagsptr;
+        for (guint i = 0; i < table_len; i++) {
+                auto gflag = table[i].gflag;
+                if ((gflags & gflag) == gflag) {
+                        pflags |= table[i].pflag;
+                        gflags &= ~gflag;
+                }
+        }
+
+        *gflagsptr = gflags;
+        *pflagsptr = pflags;
+}
+
+/* internal */
+
 #ifdef WITH_PCRE2
 
 static VteRegex *
@@ -194,6 +223,67 @@ vte_regex_new(VteRegexPurpose purpose,
 #endif /* WITH_PCRE2 */
 }
 
+VteRegex *
+_vte_regex_new_gregex(VteRegexPurpose purpose,
+                      GRegex *gregex)
+{
+        g_return_val_if_fail(gregex != NULL, NULL);
+
+        guint32 pflags = 0;
+
+#ifdef WITH_PCRE2
+        static FlagTranslation const table[] = {
+                { G_REGEX_CASELESS,        PCRE2_CASELESS        },
+                { G_REGEX_MULTILINE,       PCRE2_MULTILINE       },
+                { G_REGEX_DOTALL,          PCRE2_DOTALL          },
+                { G_REGEX_EXTENDED,        PCRE2_EXTENDED        },
+                { G_REGEX_ANCHORED,        PCRE2_ANCHORED        },
+                { G_REGEX_DOLLAR_ENDONLY,  PCRE2_DOLLAR_ENDONLY  },
+                { G_REGEX_UNGREEDY,        PCRE2_UNGREEDY        },
+                { G_REGEX_NO_AUTO_CAPTURE, PCRE2_NO_AUTO_CAPTURE },
+                { G_REGEX_OPTIMIZE,        0                     }, /* accepted but unused */
+                { G_REGEX_FIRSTLINE,       PCRE2_FIRSTLINE       },
+                { G_REGEX_DUPNAMES,        PCRE2_DUPNAMES        }
+        };
+
+        guint32 gflags = g_regex_get_compile_flags(gregex);
+        translate_flags(table, G_N_ELEMENTS(table), &gflags, &pflags);
+
+        if (gflags != 0) {
+                g_warning("Incompatible GRegex compile flags left untranslated: %08x", gflags);
+        }
+#endif
+
+        GError *err = nullptr;
+        auto regex = vte_regex_new(purpose, g_regex_get_pattern(gregex), -1, pflags, &err);
+        if (regex == NULL) {
+                g_warning("Failed to translated GRegex: %s", err->message);
+                g_error_free(err);
+        }
+        return regex;
+}
+
+guint32
+_vte_regex_translate_gregex_match_flags(GRegexMatchFlags flags)
+{
+        static FlagTranslation const table[] = {
+                { G_REGEX_MATCH_ANCHORED,         PCRE2_ANCHORED         },
+                { G_REGEX_MATCH_NOTBOL,           PCRE2_NOTBOL           },
+                { G_REGEX_MATCH_NOTEOL,           PCRE2_NOTEOL           },
+                { G_REGEX_MATCH_NOTEMPTY,         PCRE2_NOTEMPTY         },
+                { G_REGEX_MATCH_NOTEMPTY_ATSTART, PCRE2_NOTEMPTY_ATSTART }
+        };
+
+        guint32 gflags = flags;
+        guint32 pflags = 0;
+        translate_flags(table, G_N_ELEMENTS(table), &gflags, &pflags);
+        if (gflags != 0) {
+                g_warning("Incompatible GRegex match flags left untranslated: %08x", gflags);
+        }
+
+        return pflags;
+}
+
 /**
  * vte_regex_new_for_match:
  * @pattern: a regex pattern string
diff --git a/src/vteregexinternal.hh b/src/vteregexinternal.hh
index 88fb848..eaf42dc 100644
--- a/src/vteregexinternal.hh
+++ b/src/vteregexinternal.hh
@@ -30,3 +30,9 @@ gboolean _vte_regex_get_jited(VteRegex *regex);
 #ifdef WITH_PCRE2
 const pcre2_code_8 *_vte_regex_get_pcre (VteRegex *regex);
 #endif
+
+/* GRegex translation */
+VteRegex *_vte_regex_new_gregex(VteRegexPurpose purpose,
+                                GRegex *gregex);
+
+guint32 _vte_regex_translate_gregex_match_flags(GRegexMatchFlags flags);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]