Blame src/terminal-search-popover.c

Packit Service 3bdf47
/*
Packit Service 3bdf47
 * Copyright © 2015 Christian Persch
Packit Service 3bdf47
 * Copyright © 2005 Paolo Maggi
Packit Service 3bdf47
 * Copyright © 2010 Red Hat (Red Hat author: Behdad Esfahbod)
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * This program is free software: you can redistribute it and/or modify
Packit Service 3bdf47
 * it under the terms of the GNU General Public License as published by
Packit Service 3bdf47
 * the Free Software Foundation, either version 3 of the License, or
Packit Service 3bdf47
 * (at your option) any later version.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * This program is distributed in the hope that it will be useful,
Packit Service 3bdf47
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 3bdf47
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 3bdf47
 * GNU General Public License for more details.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * You should have received a copy of the GNU General Public License
Packit Service 3bdf47
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 3bdf47
 */
Packit Service 3bdf47
Packit Service 3bdf47
#include "config.h"
Packit Service 3bdf47
Packit Service 3bdf47
#include <glib.h>
Packit Service 3bdf47
#include <glib/gi18n.h>
Packit Service 3bdf47
#include <gtk/gtk.h>
Packit Service 3bdf47
Packit Service 3bdf47
#include "terminal-pcre2.h"
Packit Service 3bdf47
#include "terminal-search-popover.h"
Packit Service 3bdf47
#include "terminal-intl.h"
Packit Service 3bdf47
#include "terminal-window.h"
Packit Service 3bdf47
#include "terminal-app.h"
Packit Service 3bdf47
#include "terminal-libgsystem.h"
Packit Service 3bdf47
Packit Service 3bdf47
typedef struct _TerminalSearchPopoverPrivate TerminalSearchPopoverPrivate;
Packit Service 3bdf47
Packit Service 3bdf47
struct _TerminalSearchPopover
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkWindow parent_instance;
Packit Service 3bdf47
};
Packit Service 3bdf47
Packit Service 3bdf47
struct _TerminalSearchPopoverClass
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkWindowClass parent_class;
Packit Service 3bdf47
Packit Service 3bdf47
  /* Signals */
Packit Service 3bdf47
  void (* search) (TerminalSearchPopover *popover,
Packit Service 3bdf47
                   gboolean backward);
Packit Service 3bdf47
};
Packit Service 3bdf47
Packit Service 3bdf47
struct _TerminalSearchPopoverPrivate
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkWidget *search_entry;
Packit Service 3bdf47
  GtkWidget *search_prev_button;
Packit Service 3bdf47
  GtkWidget *search_next_button;
Packit Service 3bdf47
  GtkWidget *reveal_button;
Packit Service 3bdf47
  GtkWidget *close_button;
Packit Service 3bdf47
  GtkWidget *revealer;
Packit Service 3bdf47
  GtkWidget *match_case_checkbutton;
Packit Service 3bdf47
  GtkWidget *entire_word_checkbutton;
Packit Service 3bdf47
  GtkWidget *regex_checkbutton;
Packit Service 3bdf47
  GtkWidget *wrap_around_checkbutton;
Packit Service 3bdf47
Packit Service 3bdf47
  gboolean search_text_changed;
Packit Service 3bdf47
Packit Service 3bdf47
  /* Cached regex */
Packit Service 3bdf47
  gboolean regex_caseless;
Packit Service 3bdf47
  char *regex_pattern;
Packit Service 3bdf47
  VteRegex *regex;
Packit Service 3bdf47
};
Packit Service 3bdf47
Packit Service 3bdf47
enum {
Packit Service 3bdf47
  PROP_0,
Packit Service 3bdf47
  PROP_REGEX,
Packit Service 3bdf47
  PROP_WRAP_AROUND,
Packit Service 3bdf47
  LAST_PROP
Packit Service 3bdf47
};
Packit Service 3bdf47
Packit Service 3bdf47
enum {
Packit Service 3bdf47
  SEARCH,
Packit Service 3bdf47
  LAST_SIGNAL
Packit Service 3bdf47
};
Packit Service 3bdf47
Packit Service 3bdf47
static guint signals[LAST_SIGNAL];
Packit Service 3bdf47
static GParamSpec *pspecs[LAST_PROP];
Packit Service 3bdf47
static GtkListStore *history_store;
Packit Service 3bdf47
Packit Service 3bdf47
G_DEFINE_TYPE_WITH_PRIVATE (TerminalSearchPopover, terminal_search_popover, GTK_TYPE_WINDOW)
Packit Service 3bdf47
Packit Service 3bdf47
#define PRIV(obj) ((TerminalSearchPopoverPrivate *) terminal_search_popover_get_instance_private ((TerminalSearchPopover *)(obj)))
Packit Service 3bdf47
Packit Service 3bdf47
/* history */
Packit Service 3bdf47
Packit Service 3bdf47
#define HISTORY_MIN_ITEM_LEN (3)
Packit Service 3bdf47
#define HISTORY_LENGTH (10)
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
history_enabled (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gboolean enabled;
Packit Service 3bdf47
Packit Service 3bdf47
  /* not quite an exact setting for this, but close enough… */
Packit Service 3bdf47
  g_object_get (gtk_settings_get_default (), "gtk-recent-files-enabled", &enabled, NULL);
Packit Service 3bdf47
  if (!enabled)
Packit Service 3bdf47
    return FALSE;
Packit Service 3bdf47
Packit Service 3bdf47
  if (history_store == NULL) {
Packit Service 3bdf47
    history_store = gtk_list_store_new (1, G_TYPE_STRING);
Packit Service 3bdf47
    g_object_set_data_full (G_OBJECT (terminal_app_get ()), "search-history-store",
Packit Service 3bdf47
                            history_store, (GDestroyNotify) g_object_unref);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  return TRUE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
history_remove_item (const char  *text)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkTreeModel *model = GTK_TREE_MODEL (history_store);
Packit Service 3bdf47
  GtkTreeIter iter;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!gtk_tree_model_get_iter_first (model, &iter))
Packit Service 3bdf47
    return FALSE;
Packit Service 3bdf47
Packit Service 3bdf47
  do {
Packit Service 3bdf47
    gs_free gchar *item_text;
Packit Service 3bdf47
Packit Service 3bdf47
    gtk_tree_model_get (model, &iter, 0, &item_text, -1);
Packit Service 3bdf47
Packit Service 3bdf47
    if (item_text != NULL && strcmp (item_text, text) == 0) {
Packit Service 3bdf47
      gtk_list_store_remove (history_store, &iter);
Packit Service 3bdf47
      return TRUE;
Packit Service 3bdf47
    }
Packit Service 3bdf47
  } while (gtk_tree_model_iter_next (model, &iter));
Packit Service 3bdf47
Packit Service 3bdf47
  return FALSE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
history_clamp (int max)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkTreePath *path;
Packit Service 3bdf47
  GtkTreeIter iter;
Packit Service 3bdf47
Packit Service 3bdf47
  /* -1 because TreePath counts from 0 */
Packit Service 3bdf47
  path = gtk_tree_path_new_from_indices (max - 1, -1);
Packit Service 3bdf47
Packit Service 3bdf47
  if (gtk_tree_model_get_iter (GTK_TREE_MODEL (history_store), &iter, path))
Packit Service 3bdf47
    while (1)
Packit Service 3bdf47
      if (!gtk_list_store_remove (history_store, &iter))
Packit Service 3bdf47
	break;
Packit Service 3bdf47
Packit Service 3bdf47
  gtk_tree_path_free (path);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
history_insert_item (const char *text)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkTreeIter iter;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!history_enabled () || text == NULL)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  if (g_utf8_strlen (text, -1) <= HISTORY_MIN_ITEM_LEN)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  /* remove the text from the store if it was already
Packit Service 3bdf47
   * present. If it wasn't, clamp to max history - 1
Packit Service 3bdf47
   * before inserting the new row, otherwise appending
Packit Service 3bdf47
   * would not work */
Packit Service 3bdf47
  if (!history_remove_item (text))
Packit Service 3bdf47
    history_clamp (HISTORY_LENGTH - 1);
Packit Service 3bdf47
Packit Service 3bdf47
  gtk_list_store_insert_with_values (history_store, &iter, 0,
Packit Service 3bdf47
                                     0, text,
Packit Service 3bdf47
                                     -1);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/* helper functions */
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
update_sensitivity (TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
  gboolean can_search;
Packit Service 3bdf47
Packit Service 3bdf47
  can_search = priv->regex != NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  gtk_widget_set_sensitive (priv->search_prev_button, can_search);
Packit Service 3bdf47
  gtk_widget_set_sensitive (priv->search_next_button, can_search);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
perform_search (TerminalSearchPopover *popover,
Packit Service 3bdf47
                gboolean backward)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  if (priv->regex == NULL)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  /* Add to search history */
Packit Service 3bdf47
  if (priv->search_text_changed) {
Packit Service 3bdf47
    const char *search_text;
Packit Service 3bdf47
Packit Service 3bdf47
    search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
Packit Service 3bdf47
    history_insert_item (search_text);
Packit Service 3bdf47
Packit Service 3bdf47
    priv->search_text_changed = FALSE;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_emit (popover, signals[SEARCH], 0, backward);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
#if GTK_CHECK_VERSION (3, 16, 0)
Packit Service 3bdf47
static void
Packit Service 3bdf47
previous_match_cb (GtkWidget *widget,
Packit Service 3bdf47
                  TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  perform_search (popover, TRUE);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
next_match_cb (GtkWidget *widget,
Packit Service 3bdf47
               TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  perform_search (popover, FALSE);
Packit Service 3bdf47
}
Packit Service 3bdf47
#endif /* GTK+ 3.16 */
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
close_clicked_cb (GtkWidget *widget,
Packit Service 3bdf47
                  GtkWidget *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gtk_widget_hide (popover);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
search_button_clicked_cb (GtkWidget *button,
Packit Service 3bdf47
                          TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  perform_search (popover, button == priv->search_prev_button);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
key_press_cb (GtkWidget *popover,
Packit Service 3bdf47
              GdkEventKey *event,
Packit Service 3bdf47
              gpointer user_data G_GNUC_UNUSED)
Packit Service 3bdf47
{
Packit Service 3bdf47
  if (event->keyval == GDK_KEY_Escape) {
Packit Service 3bdf47
    gtk_widget_hide (popover);
Packit Service 3bdf47
    return TRUE;
Packit Service 3bdf47
  }
Packit Service 3bdf47
  return FALSE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
update_regex (TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
  const char *search_text;
Packit Service 3bdf47
  gboolean caseless;
Packit Service 3bdf47
  gs_free char *pattern;
Packit Service 3bdf47
  gs_free_error GError *error = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
Packit Service 3bdf47
Packit Service 3bdf47
  caseless = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->match_case_checkbutton));
Packit Service 3bdf47
Packit Service 3bdf47
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->regex_checkbutton))) {
Packit Service 3bdf47
    pattern = g_strdup (search_text);
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    pattern = g_regex_escape_string (search_text, -1);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->entire_word_checkbutton))) {
Packit Service 3bdf47
    char *new_pattern;
Packit Service 3bdf47
    new_pattern = g_strdup_printf ("\\b%s\\b", pattern);
Packit Service 3bdf47
    g_free (pattern);
Packit Service 3bdf47
    pattern = new_pattern;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  if (priv->regex_caseless == caseless &&
Packit Service 3bdf47
      g_strcmp0 (priv->regex_pattern, pattern) == 0)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  if (priv->regex) {
Packit Service 3bdf47
    vte_regex_unref (priv->regex);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  g_clear_pointer (&priv->regex_pattern, g_free);
Packit Service 3bdf47
Packit Service 3bdf47
  /* FIXME: if comping the regex fails, show the error message somewhere */
Packit Service 3bdf47
  if (search_text[0] != '\0') {
Packit Service 3bdf47
    guint32 compile_flags;
Packit Service 3bdf47
Packit Service 3bdf47
    compile_flags = PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_MULTILINE;
Packit Service 3bdf47
    if (caseless)
Packit Service 3bdf47
      compile_flags |= PCRE2_CASELESS;
Packit Service 3bdf47
Packit Service 3bdf47
    priv->regex = vte_regex_new_for_search (pattern, -1, compile_flags, &error);
Packit Service 3bdf47
    if (priv->regex != NULL &&
Packit Service 3bdf47
        (!vte_regex_jit (priv->regex, PCRE2_JIT_COMPLETE, NULL) ||
Packit Service 3bdf47
         !vte_regex_jit (priv->regex, PCRE2_JIT_PARTIAL_SOFT, NULL))) {
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
    if (priv->regex != NULL)
Packit Service 3bdf47
      gs_transfer_out_value (&priv->regex_pattern, &pattern);
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    priv->regex = NULL;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  priv->regex_caseless = caseless;
Packit Service 3bdf47
Packit Service 3bdf47
  update_sensitivity (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_object_notify_by_pspec (G_OBJECT (popover), pspecs[PROP_REGEX]);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
search_text_changed_cb (GtkToggleButton *button,
Packit Service 3bdf47
                        TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  update_regex (popover);
Packit Service 3bdf47
  priv->search_text_changed = TRUE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
search_parameters_changed_cb (GtkToggleButton *button,
Packit Service 3bdf47
                              TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  update_regex (popover);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
wrap_around_toggled_cb (GtkToggleButton *button,
Packit Service 3bdf47
                        TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  g_object_notify_by_pspec (G_OBJECT (popover), pspecs[PROP_WRAP_AROUND]);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/* public functions */
Packit Service 3bdf47
Packit Service 3bdf47
/* Class implementation */
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
terminal_search_popover_init (TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
  GtkWidget *widget = GTK_WIDGET (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  priv->regex_pattern = 0;
Packit Service 3bdf47
  priv->regex_caseless = TRUE;
Packit Service 3bdf47
Packit Service 3bdf47
  gtk_widget_init_template (widget);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Make the search entry reasonably wide */
Packit Service 3bdf47
  gtk_widget_set_size_request (priv->search_entry, 300, -1);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Add entry completion with history */
Packit Service 3bdf47
#if 0
Packit Service 3bdf47
  g_object_set (G_OBJECT (priv->search_entry),
Packit Service 3bdf47
		"model", history_store,
Packit Service 3bdf47
		"entry-text-column", 0,
Packit Service 3bdf47
		NULL);
Packit Service 3bdf47
#endif
Packit Service 3bdf47
Packit Service 3bdf47
  if (history_enabled ()) {
Packit Service 3bdf47
    gs_unref_object GtkEntryCompletion *completion;
Packit Service 3bdf47
Packit Service 3bdf47
    completion = gtk_entry_completion_new ();
Packit Service 3bdf47
    gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (history_store));
Packit Service 3bdf47
    gtk_entry_completion_set_text_column (completion, 0);
Packit Service 3bdf47
    gtk_entry_completion_set_minimum_key_length (completion, HISTORY_MIN_ITEM_LEN);
Packit Service 3bdf47
    gtk_entry_completion_set_popup_completion (completion, FALSE);
Packit Service 3bdf47
    gtk_entry_completion_set_inline_completion (completion, TRUE);
Packit Service 3bdf47
    gtk_entry_set_completion (GTK_ENTRY (priv->search_entry), completion);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
#if 0 // GTK_CHECK_VERSION (3, 17, 2)
Packit Service 3bdf47
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Packit Service 3bdf47
  gtk_popover_set_default_widget (GTK_POPOVER (popover), priv->search_prev_button);
Packit Service 3bdf47
  G_GNUC_END_IGNORE_DEPRECATIONS
Packit Service 3bdf47
#else
Packit Service 3bdf47
  gtk_window_set_default (GTK_WINDOW (popover), priv->search_prev_button);
Packit Service 3bdf47
#endif
Packit Service 3bdf47
Packit Service 3bdf47
#if GTK_CHECK_VERSION (3, 16, 0)
Packit Service 3bdf47
  g_signal_connect (priv->search_entry, "previous-match", G_CALLBACK (previous_match_cb), popover);
Packit Service 3bdf47
  g_signal_connect (priv->search_entry, "next-match", G_CALLBACK (next_match_cb), popover);
Packit Service 3bdf47
#endif
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (priv->search_prev_button, "clicked", G_CALLBACK (search_button_clicked_cb), popover);
Packit Service 3bdf47
  g_signal_connect (priv->search_next_button, "clicked", G_CALLBACK (search_button_clicked_cb), popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (priv->close_button, "clicked", G_CALLBACK (close_clicked_cb), popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_object_bind_property (priv->reveal_button, "active",
Packit Service 3bdf47
                          priv->revealer, "reveal-child",
Packit Service 3bdf47
                          G_BINDING_DEFAULT);
Packit Service 3bdf47
Packit Service 3bdf47
  update_sensitivity (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (priv->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), popover);
Packit Service 3bdf47
  g_signal_connect (priv->match_case_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
Packit Service 3bdf47
  g_signal_connect (priv->entire_word_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
Packit Service 3bdf47
  g_signal_connect (priv->regex_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (priv->wrap_around_checkbutton, "toggled", G_CALLBACK (wrap_around_toggled_cb), popover);
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (popover, "key-press-event", G_CALLBACK (key_press_cb), NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
terminal_search_popover_finalize (GObject *object)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (object);
Packit Service 3bdf47
  TerminalSearchPopoverPrivate *priv = PRIV (popover);
Packit Service 3bdf47
Packit Service 3bdf47
  if (priv->regex) {
Packit Service 3bdf47
    vte_regex_unref (priv->regex);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  g_free (priv->regex_pattern);
Packit Service 3bdf47
Packit Service 3bdf47
  G_OBJECT_CLASS (terminal_search_popover_parent_class)->finalize (object);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
terminal_search_popover_get_property (GObject *object,
Packit Service 3bdf47
                                      guint prop_id,
Packit Service 3bdf47
                                      GValue *value,
Packit Service 3bdf47
                                      GParamSpec *pspec)
Packit Service 3bdf47
{
Packit Service 3bdf47
  TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (object);
Packit Service 3bdf47
Packit Service 3bdf47
  switch (prop_id) {
Packit Service 3bdf47
  case PROP_REGEX:
Packit Service 3bdf47
    g_value_set_boxed (value, terminal_search_popover_get_regex (popover));
Packit Service 3bdf47
    break;
Packit Service 3bdf47
  case PROP_WRAP_AROUND:
Packit Service 3bdf47
    g_value_set_boolean (value, terminal_search_popover_get_wrap_around (popover));
Packit Service 3bdf47
    break;
Packit Service 3bdf47
  default:
Packit Service 3bdf47
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service 3bdf47
    break;
Packit Service 3bdf47
  }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
terminal_search_popover_set_property (GObject *object,
Packit Service 3bdf47
                                      guint prop_id,
Packit Service 3bdf47
                                      const GValue *value,
Packit Service 3bdf47
                                      GParamSpec *pspec)
Packit Service 3bdf47
{
Packit Service 3bdf47
  switch (prop_id) {
Packit Service 3bdf47
  case PROP_REGEX:
Packit Service 3bdf47
  case PROP_WRAP_AROUND:
Packit Service 3bdf47
    /* not writable */
Packit Service 3bdf47
    break;
Packit Service 3bdf47
  default:
Packit Service 3bdf47
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service 3bdf47
      break;
Packit Service 3bdf47
  }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
terminal_search_popover_class_init (TerminalSearchPopoverClass *klass)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit Service 3bdf47
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
Packit Service 3bdf47
Packit Service 3bdf47
  gobject_class->finalize = terminal_search_popover_finalize;
Packit Service 3bdf47
  gobject_class->get_property = terminal_search_popover_get_property;
Packit Service 3bdf47
  gobject_class->set_property = terminal_search_popover_set_property;
Packit Service 3bdf47
Packit Service 3bdf47
  signals[SEARCH] =
Packit Service 3bdf47
    g_signal_new (I_("search"),
Packit Service 3bdf47
                  G_OBJECT_CLASS_TYPE (gobject_class),
Packit Service 3bdf47
                  G_SIGNAL_RUN_LAST,
Packit Service 3bdf47
                  G_STRUCT_OFFSET (TerminalSearchPopoverClass, search),
Packit Service 3bdf47
                  NULL, NULL,
Packit Service 3bdf47
                  g_cclosure_marshal_VOID__BOOLEAN,
Packit Service 3bdf47
                  G_TYPE_NONE,
Packit Service 3bdf47
                  1,
Packit Service 3bdf47
                  G_TYPE_BOOLEAN);
Packit Service 3bdf47
Packit Service 3bdf47
  pspecs[PROP_REGEX] =
Packit Service 3bdf47
    g_param_spec_boxed ("regex", NULL, NULL,
Packit Service 3bdf47
                        VTE_TYPE_REGEX,
Packit Service 3bdf47
                        G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
Packit Service 3bdf47
Packit Service 3bdf47
  pspecs[PROP_WRAP_AROUND] =
Packit Service 3bdf47
    g_param_spec_boolean ("wrap-around", NULL, NULL,
Packit Service 3bdf47
                          FALSE,
Packit Service 3bdf47
                          G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
Packit Service 3bdf47
Packit Service 3bdf47
  g_object_class_install_properties (gobject_class, G_N_ELEMENTS (pspecs), pspecs);
Packit Service 3bdf47
Packit Service 3bdf47
  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/terminal/ui/search-popover.ui");
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_entry);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_prev_button);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, search_next_button);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, reveal_button);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, close_button);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, revealer);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, match_case_checkbutton);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, entire_word_checkbutton);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, regex_checkbutton);
Packit Service 3bdf47
  gtk_widget_class_bind_template_child_private (widget_class, TerminalSearchPopover, wrap_around_checkbutton);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/* public API */
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_search_popover_new:
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: a new #TerminalSearchPopover
Packit Service 3bdf47
 */
Packit Service 3bdf47
TerminalSearchPopover *
Packit Service 3bdf47
terminal_search_popover_new (GtkWidget *relative_to_widget)
Packit Service 3bdf47
{
Packit Service 3bdf47
  return g_object_new (TERMINAL_TYPE_SEARCH_POPOVER,
Packit Service 3bdf47
#if 0
Packit Service 3bdf47
                       "relative-to", relative_to_widget,
Packit Service 3bdf47
#else
Packit Service 3bdf47
                       "transient-for", gtk_widget_get_toplevel (relative_to_widget),
Packit Service 3bdf47
#endif
Packit Service 3bdf47
                       NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_search_popover_get_regex:
Packit Service 3bdf47
 * @popover: a #TerminalSearchPopover
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer none): the search regex, or %NULL
Packit Service 3bdf47
 */
Packit Service 3bdf47
VteRegex *
Packit Service 3bdf47
terminal_search_popover_get_regex (TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  g_return_val_if_fail (TERMINAL_IS_SEARCH_POPOVER (popover), NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  return PRIV (popover)->regex;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_search_popover_get_wrap_around:
Packit Service 3bdf47
 * @popover: a #TerminalSearchPopover
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer none): whether search should wrap around
Packit Service 3bdf47
 */
Packit Service 3bdf47
gboolean
Packit Service 3bdf47
terminal_search_popover_get_wrap_around (TerminalSearchPopover *popover)
Packit Service 3bdf47
{
Packit Service 3bdf47
  g_return_val_if_fail (TERMINAL_IS_SEARCH_POPOVER (popover), FALSE);
Packit Service 3bdf47
Packit Service 3bdf47
  return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (PRIV (popover)->wrap_around_checkbutton));
Packit Service 3bdf47
}