thunar-usagebars/plugins/thunar-sbr/thunar-sbr-replace-renamer.c
4aiman e969f94310 thunar 4.20.2 upstream
Tree of tag thunar-4.20.2 (commit 11a519f) from https://gitlab.xfce.org/xfce/thunar.
Upstream history is not included here to keep the repository small.
2026-11-03 22:42:48 +03:00

814 lines
26 KiB
C

/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_PCRE2
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#endif
#include <libxfce4util/libxfce4util.h>
#include <thunar-sbr/thunar-sbr-replace-renamer.h>
/* Property identifiers */
enum
{
PROP_0,
PROP_CASE_SENSITIVE,
PROP_PATTERN,
PROP_REPLACEMENT,
PROP_REGEXP,
};
static void
thunar_sbr_replace_renamer_finalize (GObject *object);
static void
thunar_sbr_replace_renamer_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void
thunar_sbr_replace_renamer_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void
thunar_sbr_replace_renamer_realize (GtkWidget *widget);
static gchar *
thunar_sbr_replace_renamer_process (ThunarxRenamer *renamer,
ThunarxFileInfo *file,
const gchar *text,
guint idx);
#ifdef HAVE_PCRE2
static gchar *
thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer,
const gchar *text);
static void
thunar_sbr_replace_renamer_pcre_update (ThunarSbrReplaceRenamer *replace_renamer);
#endif
struct _ThunarSbrReplaceRenamerClass
{
ThunarxRenamerClass __parent__;
};
struct _ThunarSbrReplaceRenamer
{
ThunarxRenamer __parent__;
GtkWidget *pattern_entry;
gboolean case_sensitive;
gboolean regexp;
gchar *pattern;
gchar *replacement;
/* TRUE if PCRE is available and supports UTF-8 */
gint utf8_regexp_supported;
/* PCRE compiled pattern */
#ifdef HAVE_PCRE2
pcre2_code *pcre_pattern;
gint pcre_capture_count;
#endif
};
THUNARX_DEFINE_TYPE (ThunarSbrReplaceRenamer, thunar_sbr_replace_renamer, THUNARX_TYPE_RENAMER);
static void
thunar_sbr_replace_renamer_class_init (ThunarSbrReplaceRenamerClass *klass)
{
ThunarxRenamerClass *thunarxrenamer_class;
GtkWidgetClass *gtkwidget_class;
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = thunar_sbr_replace_renamer_finalize;
gobject_class->get_property = thunar_sbr_replace_renamer_get_property;
gobject_class->set_property = thunar_sbr_replace_renamer_set_property;
gtkwidget_class = GTK_WIDGET_CLASS (klass);
gtkwidget_class->realize = thunar_sbr_replace_renamer_realize;
thunarxrenamer_class = THUNARX_RENAMER_CLASS (klass);
thunarxrenamer_class->process = thunar_sbr_replace_renamer_process;
/**
* ThunarSbrReplaceRenamer:case-sensitive:
*
* Whether to use case sensitive search and replace.
**/
g_object_class_install_property (gobject_class,
PROP_CASE_SENSITIVE,
g_param_spec_boolean ("case-sensitive",
"case-sensitive",
"case-sensitive",
FALSE,
G_PARAM_READWRITE));
/**
* ThunarSbrReplaceRenamer:pattern:
*
* The search pattern.
**/
g_object_class_install_property (gobject_class,
PROP_PATTERN,
g_param_spec_string ("pattern",
"pattern",
"pattern",
NULL,
G_PARAM_READWRITE));
/**
* ThunarSbrReplaceRenamer:replacement:
*
* The replacement text.
**/
g_object_class_install_property (gobject_class,
PROP_REPLACEMENT,
g_param_spec_string ("replacement",
"replacement",
"replacement",
NULL,
G_PARAM_READWRITE));
/**
* ThunarSbrReplaceRenamer:regexp:
*
* Whether to use regular expressions.
**/
g_object_class_install_property (gobject_class,
PROP_REGEXP,
g_param_spec_boolean ("regexp",
"regexp",
"regexp",
FALSE,
G_PARAM_READWRITE));
}
static void
thunar_sbr_replace_renamer_init (ThunarSbrReplaceRenamer *replace_renamer)
{
AtkRelationSet *relations;
AtkRelation *relation;
AtkObject *object;
GtkWidget *grid;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *button;
uint32_t pcre2_compiled_widths;
replace_renamer->utf8_regexp_supported = FALSE;
#ifdef HAVE_PCRE2
/* check if PCRE supports UTF-8 */
if (pcre2_config (PCRE2_CONFIG_COMPILED_WIDTHS, &pcre2_compiled_widths) >= 0)
{
/* bit0 indicates 8-bit support. bit1 and bit2 indicate 16-bit and 32-bit support respectively. */
if ((pcre2_compiled_widths & (1 << 0)) != 0)
replace_renamer->utf8_regexp_supported = TRUE;
}
#endif
grid = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
gtk_box_pack_start (GTK_BOX (replace_renamer), grid, FALSE, FALSE, 0);
gtk_widget_show (grid);
label = gtk_label_new_with_mnemonic (_("_Search For:"));
gtk_label_set_xalign (GTK_LABEL (label), 1.0f);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
gtk_widget_show (label);
replace_renamer->pattern_entry = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (replace_renamer->pattern_entry), TRUE);
g_object_bind_property (G_OBJECT (replace_renamer->pattern_entry), "text", G_OBJECT (replace_renamer), "pattern", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, _("Enter the text to search for in the file names."));
gtk_widget_set_hexpand (replace_renamer->pattern_entry, TRUE);
gtk_grid_attach (GTK_GRID (grid), replace_renamer->pattern_entry, 1, 0, 1, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), replace_renamer->pattern_entry);
gtk_widget_show (replace_renamer->pattern_entry);
/* set Atk label relation for the entry */
object = gtk_widget_get_accessible (replace_renamer->pattern_entry);
relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
atk_relation_set_add (relations, relation);
g_object_unref (G_OBJECT (relation));
g_object_unref (relations);
button = gtk_check_button_new_with_mnemonic (_("Regular _Expression"));
g_object_bind_property (G_OBJECT (button), "active", G_OBJECT (replace_renamer), "regexp", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_widget_set_tooltip_text (button, _("If you enable this option, the pattern will be treated as a regular expression and "
"matched using the Perl-compatible regular expressions (PCRE). Check the documentation "
"for details about the regular expression syntax."));
gtk_grid_attach (GTK_GRID (grid), button, 2, 0, 1, 1);
gtk_widget_set_sensitive (button, replace_renamer->utf8_regexp_supported);
gtk_widget_show (button);
label = gtk_label_new_with_mnemonic (_("Replace _With:"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
gtk_widget_show (label);
entry = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
g_object_bind_property (G_OBJECT (entry), "text", G_OBJECT (replace_renamer), "replacement", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_widget_set_tooltip_text (entry, _("Enter the text that should be used as replacement for the pattern above."));
gtk_widget_set_hexpand (entry, TRUE);
gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
gtk_widget_show (entry);
/* set Atk label relation for the entry */
object = gtk_widget_get_accessible (entry);
relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
atk_relation_set_add (relations, relation);
g_object_unref (G_OBJECT (relation));
g_object_unref (relations);
button = gtk_check_button_new_with_mnemonic (_("C_ase Sensitive Search"));
g_object_bind_property (G_OBJECT (button), "active", G_OBJECT (replace_renamer), "case-sensitive", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_widget_set_tooltip_text (button, _("If you enable this option, the pattern will be searched in a case-sensitive manner. "
"The default is to use a case-insensitive search."));
gtk_grid_attach (GTK_GRID (grid), button, 2, 1, 1, 1);
gtk_widget_show (button);
}
static void
thunar_sbr_replace_renamer_finalize (GObject *object)
{
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
/* release the PCRE pattern (if any) */
#ifdef HAVE_PCRE2
if (G_UNLIKELY (replace_renamer->pcre_pattern != NULL))
pcre2_code_free (replace_renamer->pcre_pattern);
#endif
/* release the strings */
g_free (replace_renamer->replacement);
g_free (replace_renamer->pattern);
(*G_OBJECT_CLASS (thunar_sbr_replace_renamer_parent_class)->finalize) (object);
}
static void
thunar_sbr_replace_renamer_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
switch (prop_id)
{
case PROP_CASE_SENSITIVE:
g_value_set_boolean (value, thunar_sbr_replace_renamer_get_case_sensitive (replace_renamer));
break;
case PROP_PATTERN:
g_value_set_string (value, thunar_sbr_replace_renamer_get_pattern (replace_renamer));
break;
case PROP_REPLACEMENT:
g_value_set_string (value, thunar_sbr_replace_renamer_get_replacement (replace_renamer));
break;
case PROP_REGEXP:
g_value_set_boolean (value, thunar_sbr_replace_renamer_get_regexp (replace_renamer));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
thunar_sbr_replace_renamer_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (object);
switch (prop_id)
{
case PROP_CASE_SENSITIVE:
thunar_sbr_replace_renamer_set_case_sensitive (replace_renamer, g_value_get_boolean (value));
break;
case PROP_PATTERN:
thunar_sbr_replace_renamer_set_pattern (replace_renamer, g_value_get_string (value));
break;
case PROP_REPLACEMENT:
thunar_sbr_replace_renamer_set_replacement (replace_renamer, g_value_get_string (value));
break;
case PROP_REGEXP:
thunar_sbr_replace_renamer_set_regexp (replace_renamer, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
thunar_sbr_replace_renamer_realize (GtkWidget *widget)
{
/* realize the widget */
(*GTK_WIDGET_CLASS (thunar_sbr_replace_renamer_parent_class)->realize) (widget);
#ifdef HAVE_PCRE2
/* update the PCRE pattern */
thunar_sbr_replace_renamer_pcre_update (THUNAR_SBR_REPLACE_RENAMER (widget));
#endif
}
static gchar *
tsrr_replace (const gchar *text,
const gchar *pattern,
const gchar *replacement,
gboolean case_sensitive)
{
const gchar *p;
const gchar *t;
gunichar pc;
gunichar tc;
GString *result = g_string_sized_new (32);
while (*text != '\0')
{
/* compare the pattern to this part of the text */
for (p = pattern, t = text; *p != '\0' && *t != '\0'; p = g_utf8_next_char (p), t = g_utf8_next_char (t))
{
/* determine the next unichars */
pc = g_utf8_get_char (p);
tc = g_utf8_get_char (t);
/* check if the chars don't match */
if (pc != tc && (case_sensitive || g_unichar_toupper (pc) != g_unichar_toupper (tc)))
break;
}
/* check if the pattern matches */
if (G_UNLIKELY (*p == '\0'))
{
/* append the replacement to the result... */
g_string_append (result, replacement);
/* ...and skip to the text after the pattern */
text = t;
}
else
{
/* just append the text char */
g_string_append_unichar (result, g_utf8_get_char (text));
text = g_utf8_next_char (text);
}
}
return g_string_free (result, FALSE);
}
static gchar *
thunar_sbr_replace_renamer_process (ThunarxRenamer *renamer,
ThunarxFileInfo *file,
const gchar *text,
guint idx)
{
ThunarSbrReplaceRenamer *replace_renamer = THUNAR_SBR_REPLACE_RENAMER (renamer);
/* nothing to replace if we don't have a pattern */
if (G_UNLIKELY (replace_renamer->pattern == NULL || *replace_renamer->pattern == '\0'))
return g_strdup (text);
/* check if we should use regular expression */
if (G_UNLIKELY (replace_renamer->regexp))
{
#ifdef HAVE_PCRE2
/* check if the pattern failed to compile */
if (G_UNLIKELY (replace_renamer->pcre_pattern == NULL))
return g_strdup (text);
/* just execute the pattern */
return thunar_sbr_replace_renamer_pcre_exec (replace_renamer, text);
#endif
}
/* perform the replace operation */
return tsrr_replace (text, replace_renamer->pattern, replace_renamer->replacement, replace_renamer->case_sensitive);
}
#ifdef HAVE_PCRE2
static gchar *
thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer,
const gchar *subject)
{
GString *result;
int error;
PCRE2_SIZE erroffset;
gchar output[1024];
pcre2_code *compiled_pattern;
PCRE2_SIZE outlen;
int n_substitutions; /* number of substitutions that were carried out */
result = g_string_sized_new (32);
compiled_pattern = pcre2_compile_8 ((PCRE2_SPTR) replace_renamer->pattern,
PCRE2_ZERO_TERMINATED,
0,
&error,
&erroffset,
0);
if (compiled_pattern == NULL)
return g_strdup (subject);
pcre2_jit_compile (compiled_pattern, PCRE2_JIT_COMPLETE);
outlen = sizeof (output) / sizeof (PCRE2_UCHAR);
n_substitutions = pcre2_substitute (compiled_pattern,
(PCRE2_SPTR) subject,
PCRE2_ZERO_TERMINATED,
0,
PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_EXTENDED,
0,
0,
(PCRE2_SPTR) replace_renamer->replacement,
PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR *) output,
&outlen);
if (n_substitutions < 0)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message (error, buffer, sizeof (buffer));
g_warning ("PCRE2 substitution failed at offset %d: %s\n", (int) erroffset, buffer);
return g_strdup (subject);
}
pcre2_code_free (compiled_pattern);
for (size_t i = 0; i < outlen; i++)
g_string_append_c (result, output[i]);
return g_string_free (result, FALSE);
}
static void
thunar_sbr_replace_renamer_pcre_update (ThunarSbrReplaceRenamer *replace_renamer)
{
const gchar *error_message = NULL;
gchar *tooltip;
gchar *message;
glong offset;
gint error_offset = -1;
int error;
PCRE2_SIZE erroffset;
/* pre-compile the pattern if regexp is enabled */
if (G_UNLIKELY (replace_renamer->regexp))
{
/* release the previous pattern (if any) */
if (G_LIKELY (replace_renamer->pcre_pattern != NULL))
pcre2_code_free (replace_renamer->pcre_pattern);
/* try to compile the new pattern */
replace_renamer->pcre_pattern = pcre2_compile ((PCRE2_SPTR) replace_renamer->pattern, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, 0);
if (replace_renamer->pcre_pattern == NULL)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message (error, buffer, sizeof (buffer));
g_warning ("PCRE2 compilation failed at offset %d: %s\n", (int) erroffset, buffer);
}
}
/* check if there was an error compiling the pattern */
if (G_UNLIKELY (error_message != NULL))
{
/* convert the message to UTF-8 */
message = g_locale_to_utf8 (error_message, -1, NULL, NULL, NULL);
if (G_LIKELY (message != NULL))
{
/* determine the UTF-8 char offset */
offset = g_utf8_pointer_to_offset (replace_renamer->pattern, replace_renamer->pattern + error_offset);
/* setup a tooltip with the error message */
tooltip = g_strdup_printf (_("Invalid regular expression, at character position %ld: %s"), offset, message);
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, tooltip);
g_free (tooltip);
}
g_free (message);
/* check if the entry is realized */
if (gtk_widget_get_realized (replace_renamer->pattern_entry))
{
/* highlight invalid input by using theme-specific colors */
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (replace_renamer->pattern_entry)), "error");
}
}
else
{
/* check if the entry is realized */
if (gtk_widget_get_realized (replace_renamer->pattern_entry))
{
/* stop highlight of invalid input if any */
gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (replace_renamer->pattern_entry)), "error");
}
/* reset to default tooltip */
gtk_widget_set_tooltip_text (replace_renamer->pattern_entry, _("Enter the text to search for in the file names."));
}
}
#endif
/**
* thunar_sbr_replace_renamer_new:
*
* Allocates a new #ThunarSbrReplaceRenamer instance.
*
* Return value: the newly allocated #ThunarSbrReplaceRenamer.
**/
ThunarSbrReplaceRenamer *
thunar_sbr_replace_renamer_new (void)
{
return g_object_new (THUNAR_SBR_TYPE_REPLACE_RENAMER,
"name", _("Search & Replace"),
NULL);
}
/**
* thunar_sbr_replace_renamer_get_case_sensitive:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
*
* Returns %TRUE if @replace_renamer<!---->s search should
* be case sensitive.
*
* Return value: %TRUE if @replace_renamer is case sensitive.
**/
gboolean
thunar_sbr_replace_renamer_get_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer)
{
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), FALSE);
return replace_renamer->case_sensitive;
}
/**
* thunar_sbr_replace_renamer_set_case_sensitive:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
* @case_sensitive : %TRUE to use case sensitive search.
*
* If @case_sensitive is %TRUE the search of @replace_renamer
* will be case sensitive.
**/
void
thunar_sbr_replace_renamer_set_case_sensitive (ThunarSbrReplaceRenamer *replace_renamer,
gboolean case_sensitive)
{
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
/* normalize the value */
case_sensitive = !!case_sensitive;
/* check if we have a new setting */
if (G_LIKELY (replace_renamer->case_sensitive != case_sensitive))
{
/* apply the new value */
replace_renamer->case_sensitive = case_sensitive;
#ifdef HAVE_PCRE2
/* pre-compile the pattern */
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
#endif
/* update the renamer */
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
/* notify listeners */
g_object_notify (G_OBJECT (replace_renamer), "case-sensitive");
}
}
/**
* thunar_sbr_replace_renamer_get_pattern:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
*
* Returns the search pattern for @replace_renamer.
*
* Return value: the search pattern for @replace_renamer.
**/
const gchar *
thunar_sbr_replace_renamer_get_pattern (ThunarSbrReplaceRenamer *replace_renamer)
{
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), NULL);
return replace_renamer->pattern;
}
/**
* thunar_sbr_replace_renamer_set_pattern:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
* @pattern : the new pattern for @replace_renamer.
*
* Sets the search pattern of @replace_renamer to @pattern.
**/
void
thunar_sbr_replace_renamer_set_pattern (ThunarSbrReplaceRenamer *replace_renamer,
const gchar *pattern)
{
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
g_return_if_fail (g_utf8_validate (pattern, -1, NULL));
/* check if we have a new pattern */
if (g_strcmp0 (replace_renamer->pattern, pattern) != 0)
{
/* apply the new value */
g_free (replace_renamer->pattern);
replace_renamer->pattern = g_strdup (pattern);
#ifdef HAVE_PCRE2
/* pre-compile the pattern */
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
#endif
/* update the renamer */
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
/* notify listeners */
g_object_notify (G_OBJECT (replace_renamer), "pattern");
}
}
/**
* thunar_sbr_replace_renamer_get_regexp:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
*
* Returns %TRUE if @replace_renamer should use a regular
* expression.
*
* Return value: %TRUE if @replace_renamer uses a regexp.
**/
gboolean
thunar_sbr_replace_renamer_get_regexp (ThunarSbrReplaceRenamer *replace_renamer)
{
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), FALSE);
return replace_renamer->regexp;
}
/**
* thunar_sbr_replace_renamer_set_regexp:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
* @regexp : %TRUE to use regular expressions.
*
* If @regexp is %TRUE a regular expression should be used
* for @replace_renamer.
**/
void
thunar_sbr_replace_renamer_set_regexp (ThunarSbrReplaceRenamer *replace_renamer,
gboolean regexp)
{
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
/* normalize the value */
regexp = (!!regexp && replace_renamer->utf8_regexp_supported);
/* check if we have a new value */
if (G_LIKELY (replace_renamer->regexp != regexp))
{
/* apply the new value */
replace_renamer->regexp = regexp;
#ifdef HAVE_PCRE2
/* pre-compile the pattern */
thunar_sbr_replace_renamer_pcre_update (replace_renamer);
#endif
/* update the renamer */
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
/* notify listeners */
g_object_notify (G_OBJECT (replace_renamer), "regexp");
}
}
/**
* thunar_sbr_replace_renamer_get_replacement:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
*
* Returns the replacement for the @replace_renamer.
*
* Return value: the replacement for @replace_renamer.
**/
const gchar *
thunar_sbr_replace_renamer_get_replacement (ThunarSbrReplaceRenamer *replace_renamer)
{
g_return_val_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer), NULL);
return replace_renamer->replacement;
}
/**
* thunar_sbr_replace_renamer_set_replacement:
* @replace_renamer : a #ThunarSbrReplaceRenamer.
* @replacement : the new replacement.
*
* Sets the replacement of @replace_renamer to @replacement.
**/
void
thunar_sbr_replace_renamer_set_replacement (ThunarSbrReplaceRenamer *replace_renamer,
const gchar *replacement)
{
g_return_if_fail (THUNAR_SBR_IS_REPLACE_RENAMER (replace_renamer));
g_return_if_fail (g_utf8_validate (replacement, -1, NULL));
/* check if we have a new replacement */
if (g_strcmp0 (replace_renamer->replacement, replacement) != 0)
{
/* apply the setting */
g_free (replace_renamer->replacement);
replace_renamer->replacement = g_strdup (replacement);
/* update the renamer */
thunarx_renamer_changed (THUNARX_RENAMER (replace_renamer));
/* notify listeners */
g_object_notify (G_OBJECT (replace_renamer), "replacement");
}
}