1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
2 /* gtksourcesearchsettings.c
3 * This file is part of GtkSourceView
4 *
5 * Copyright (C) 2013 - Sébastien Wilmet <swilmet@gnome.org>
6 *
7 * GtkSourceView is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * GtkSourceView is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "gtksourcesearchsettings.h"
27 #include "gtksourceview-i18n.h"
28
29 /**
30 * SECTION:searchsettings
31 * @Short_description: Search settings
32 * @Title: GtkSourceSearchSettings
33 * @See_also: #GtkSourceSearchContext
34 *
35 * A #GtkSourceSearchSettings object represents the settings of a search. The
36 * search settings can be associated with one or several
37 * #GtkSourceSearchContext<!-- -->s.
38 */
39
40 enum
41 {
42 PROP_0,
43 PROP_SEARCH_TEXT,
44 PROP_CASE_SENSITIVE,
45 PROP_AT_WORD_BOUNDARIES,
46 PROP_WRAP_AROUND,
47 PROP_REGEX_ENABLED
48 };
49
50 struct _GtkSourceSearchSettingsPrivate
51 {
52 gchar *search_text;
53 guint case_sensitive : 1;
54 guint at_word_boundaries : 1;
55 guint wrap_around : 1;
56 guint regex_enabled : 1;
57 };
58
G_DEFINE_TYPE_WITH_PRIVATE(GtkSourceSearchSettings,gtk_source_search_settings,G_TYPE_OBJECT)59 G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceSearchSettings, gtk_source_search_settings, G_TYPE_OBJECT)
60
61 static void
62 gtk_source_search_settings_finalize (GObject *object)
63 {
64 GtkSourceSearchSettings *settings = GTK_SOURCE_SEARCH_SETTINGS (object);
65
66 g_free (settings->priv->search_text);
67
68 G_OBJECT_CLASS (gtk_source_search_settings_parent_class)->finalize (object);
69 }
70
71 static void
gtk_source_search_settings_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)72 gtk_source_search_settings_get_property (GObject *object,
73 guint prop_id,
74 GValue *value,
75 GParamSpec *pspec)
76 {
77 GtkSourceSearchSettings *settings;
78
79 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (object));
80
81 settings = GTK_SOURCE_SEARCH_SETTINGS (object);
82
83 switch (prop_id)
84 {
85 case PROP_SEARCH_TEXT:
86 g_value_set_string (value, settings->priv->search_text);
87 break;
88
89 case PROP_CASE_SENSITIVE:
90 g_value_set_boolean (value, settings->priv->case_sensitive);
91 break;
92
93 case PROP_AT_WORD_BOUNDARIES:
94 g_value_set_boolean (value, settings->priv->at_word_boundaries);
95 break;
96
97 case PROP_WRAP_AROUND:
98 g_value_set_boolean (value, settings->priv->wrap_around);
99 break;
100
101 case PROP_REGEX_ENABLED:
102 g_value_set_boolean (value, settings->priv->regex_enabled);
103 break;
104
105 default:
106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
107 break;
108 }
109 }
110
111 static void
gtk_source_search_settings_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)112 gtk_source_search_settings_set_property (GObject *object,
113 guint prop_id,
114 const GValue *value,
115 GParamSpec *pspec)
116 {
117 GtkSourceSearchSettings *settings;
118
119 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (object));
120
121 settings = GTK_SOURCE_SEARCH_SETTINGS (object);
122
123 switch (prop_id)
124 {
125 case PROP_SEARCH_TEXT:
126 gtk_source_search_settings_set_search_text (settings, g_value_get_string (value));
127 break;
128
129 case PROP_CASE_SENSITIVE:
130 settings->priv->case_sensitive = g_value_get_boolean (value);
131 break;
132
133 case PROP_AT_WORD_BOUNDARIES:
134 settings->priv->at_word_boundaries = g_value_get_boolean (value);
135 break;
136
137 case PROP_WRAP_AROUND:
138 settings->priv->wrap_around = g_value_get_boolean (value);
139 break;
140
141 case PROP_REGEX_ENABLED:
142 settings->priv->regex_enabled = g_value_get_boolean (value);
143 break;
144
145 default:
146 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147 break;
148 }
149 }
150
151 static void
gtk_source_search_settings_class_init(GtkSourceSearchSettingsClass * klass)152 gtk_source_search_settings_class_init (GtkSourceSearchSettingsClass *klass)
153 {
154 GObjectClass *object_class = G_OBJECT_CLASS (klass);
155
156 object_class->finalize = gtk_source_search_settings_finalize;
157 object_class->get_property = gtk_source_search_settings_get_property;
158 object_class->set_property = gtk_source_search_settings_set_property;
159
160 /**
161 * GtkSourceSearchSettings:search-text:
162 *
163 * A search string, or %NULL if the search is disabled. If the regular
164 * expression search is enabled, #GtkSourceSearchSettings:search-text is
165 * the pattern.
166 *
167 * Since: 3.10
168 */
169 g_object_class_install_property (object_class,
170 PROP_SEARCH_TEXT,
171 g_param_spec_string ("search-text",
172 "Search text",
173 "The text to search",
174 NULL,
175 G_PARAM_READWRITE |
176 G_PARAM_CONSTRUCT |
177 G_PARAM_STATIC_STRINGS));
178
179 /**
180 * GtkSourceSearchSettings:case-sensitive:
181 *
182 * Whether the search is case sensitive.
183 *
184 * Since: 3.10
185 */
186 g_object_class_install_property (object_class,
187 PROP_CASE_SENSITIVE,
188 g_param_spec_boolean ("case-sensitive",
189 "Case sensitive",
190 "Case sensitive",
191 FALSE,
192 G_PARAM_READWRITE |
193 G_PARAM_CONSTRUCT |
194 G_PARAM_STATIC_STRINGS));
195
196 /**
197 * GtkSourceSearchSettings:at-word-boundaries:
198 *
199 * If %TRUE, a search match must start and end a word. The match can
200 * span multiple words.
201 *
202 * Since: 3.10
203 */
204 g_object_class_install_property (object_class,
205 PROP_AT_WORD_BOUNDARIES,
206 g_param_spec_boolean ("at-word-boundaries",
207 "At word boundaries",
208 "Search at word boundaries",
209 FALSE,
210 G_PARAM_READWRITE |
211 G_PARAM_CONSTRUCT |
212 G_PARAM_STATIC_STRINGS));
213
214 /**
215 * GtkSourceSearchSettings:wrap-around:
216 *
217 * For a forward search, continue at the beginning of the buffer if no
218 * search occurrence is found. For a backward search, continue at the
219 * end of the buffer.
220 *
221 * Since: 3.10
222 */
223 g_object_class_install_property (object_class,
224 PROP_WRAP_AROUND,
225 g_param_spec_boolean ("wrap-around",
226 "Wrap around",
227 "Wrap around",
228 FALSE,
229 G_PARAM_READWRITE |
230 G_PARAM_CONSTRUCT |
231 G_PARAM_STATIC_STRINGS));
232
233 /**
234 * GtkSourceSearchSettings:regex-enabled:
235 *
236 * Search by regular expressions with
237 * #GtkSourceSearchSettings:search-text as the pattern.
238 *
239 * Since: 3.10
240 */
241 g_object_class_install_property (object_class,
242 PROP_REGEX_ENABLED,
243 g_param_spec_boolean ("regex-enabled",
244 "Regex enabled",
245 "Whether to search by regular expression",
246 FALSE,
247 G_PARAM_READWRITE |
248 G_PARAM_CONSTRUCT |
249 G_PARAM_STATIC_STRINGS));
250 }
251
252 static void
gtk_source_search_settings_init(GtkSourceSearchSettings * self)253 gtk_source_search_settings_init (GtkSourceSearchSettings *self)
254 {
255 self->priv = gtk_source_search_settings_get_instance_private (self);
256 }
257
258 /**
259 * gtk_source_search_settings_new:
260 *
261 * Creates a new search settings object.
262 *
263 * Returns: a new search settings object.
264 * Since: 3.10
265 */
266 GtkSourceSearchSettings *
gtk_source_search_settings_new(void)267 gtk_source_search_settings_new (void)
268 {
269 return g_object_new (GTK_SOURCE_TYPE_SEARCH_SETTINGS, NULL);
270 }
271
272 /**
273 * gtk_source_search_settings_set_search_text:
274 * @settings: a #GtkSourceSearchSettings.
275 * @search_text: (nullable): the nul-terminated text to search, or %NULL to disable the search.
276 *
277 * Sets the text to search. If @search_text is %NULL or is empty, the search
278 * will be disabled. A copy of @search_text will be made, so you can safely free
279 * @search_text after a call to this function.
280 *
281 * You may be interested to call gtk_source_utils_unescape_search_text() before
282 * this function.
283 *
284 * Since: 3.10
285 */
286 void
gtk_source_search_settings_set_search_text(GtkSourceSearchSettings * settings,const gchar * search_text)287 gtk_source_search_settings_set_search_text (GtkSourceSearchSettings *settings,
288 const gchar *search_text)
289 {
290 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings));
291 g_return_if_fail (search_text == NULL || g_utf8_validate (search_text, -1, NULL));
292
293 if ((settings->priv->search_text == NULL &&
294 (search_text == NULL || search_text[0] == '\0')) ||
295 g_strcmp0 (settings->priv->search_text, search_text) == 0)
296 {
297 return;
298 }
299
300 g_free (settings->priv->search_text);
301
302 if (search_text == NULL || search_text[0] == '\0')
303 {
304 settings->priv->search_text = NULL;
305 }
306 else
307 {
308 settings->priv->search_text = g_strdup (search_text);
309 }
310
311 g_object_notify (G_OBJECT (settings), "search-text");
312 }
313
314 /**
315 * gtk_source_search_settings_get_search_text:
316 * @settings: a #GtkSourceSearchSettings.
317 *
318 * Gets the text to search. The return value must not be freed.
319 *
320 * You may be interested to call gtk_source_utils_escape_search_text() after
321 * this function.
322 *
323 * Returns: (nullable): the text to search, or %NULL if the search is disabled.
324 * Since: 3.10
325 */
326 const gchar *
gtk_source_search_settings_get_search_text(GtkSourceSearchSettings * settings)327 gtk_source_search_settings_get_search_text (GtkSourceSearchSettings *settings)
328 {
329 g_return_val_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings), NULL);
330
331 return settings->priv->search_text;
332 }
333
334 /**
335 * gtk_source_search_settings_set_case_sensitive:
336 * @settings: a #GtkSourceSearchSettings.
337 * @case_sensitive: the setting.
338 *
339 * Enables or disables the case sensitivity for the search.
340 *
341 * Since: 3.10
342 */
343 void
gtk_source_search_settings_set_case_sensitive(GtkSourceSearchSettings * settings,gboolean case_sensitive)344 gtk_source_search_settings_set_case_sensitive (GtkSourceSearchSettings *settings,
345 gboolean case_sensitive)
346 {
347 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings));
348
349 case_sensitive = case_sensitive != FALSE;
350
351 if (settings->priv->case_sensitive != case_sensitive)
352 {
353 settings->priv->case_sensitive = case_sensitive;
354 g_object_notify (G_OBJECT (settings), "case-sensitive");
355 }
356 }
357
358 /**
359 * gtk_source_search_settings_get_case_sensitive:
360 * @settings: a #GtkSourceSearchSettings.
361 *
362 * Returns: whether the search is case sensitive.
363 * Since: 3.10
364 */
365 gboolean
gtk_source_search_settings_get_case_sensitive(GtkSourceSearchSettings * settings)366 gtk_source_search_settings_get_case_sensitive (GtkSourceSearchSettings *settings)
367 {
368 g_return_val_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings), FALSE);
369
370 return settings->priv->case_sensitive;
371 }
372
373 /**
374 * gtk_source_search_settings_set_at_word_boundaries:
375 * @settings: a #GtkSourceSearchSettings.
376 * @at_word_boundaries: the setting.
377 *
378 * Change whether the search is done at word boundaries. If @at_word_boundaries
379 * is %TRUE, a search match must start and end a word. The match can span
380 * multiple words. See also gtk_text_iter_starts_word() and
381 * gtk_text_iter_ends_word().
382 *
383 * Since: 3.10
384 */
385 void
gtk_source_search_settings_set_at_word_boundaries(GtkSourceSearchSettings * settings,gboolean at_word_boundaries)386 gtk_source_search_settings_set_at_word_boundaries (GtkSourceSearchSettings *settings,
387 gboolean at_word_boundaries)
388 {
389 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings));
390
391 at_word_boundaries = at_word_boundaries != FALSE;
392
393 if (settings->priv->at_word_boundaries != at_word_boundaries)
394 {
395 settings->priv->at_word_boundaries = at_word_boundaries;
396 g_object_notify (G_OBJECT (settings), "at-word-boundaries");
397 }
398 }
399
400 /**
401 * gtk_source_search_settings_get_at_word_boundaries:
402 * @settings: a #GtkSourceSearchSettings.
403 *
404 * Returns: whether to search at word boundaries.
405 * Since: 3.10
406 */
407 gboolean
gtk_source_search_settings_get_at_word_boundaries(GtkSourceSearchSettings * settings)408 gtk_source_search_settings_get_at_word_boundaries (GtkSourceSearchSettings *settings)
409 {
410 g_return_val_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings), FALSE);
411
412 return settings->priv->at_word_boundaries;
413 }
414
415 /**
416 * gtk_source_search_settings_set_wrap_around:
417 * @settings: a #GtkSourceSearchSettings.
418 * @wrap_around: the setting.
419 *
420 * Enables or disables the wrap around search. If @wrap_around is %TRUE, the
421 * forward search continues at the beginning of the buffer if no search
422 * occurrences are found. Similarly, the backward search continues to search at
423 * the end of the buffer.
424 *
425 * Since: 3.10
426 */
427 void
gtk_source_search_settings_set_wrap_around(GtkSourceSearchSettings * settings,gboolean wrap_around)428 gtk_source_search_settings_set_wrap_around (GtkSourceSearchSettings *settings,
429 gboolean wrap_around)
430 {
431 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings));
432
433 wrap_around = wrap_around != FALSE;
434
435 if (settings->priv->wrap_around != wrap_around)
436 {
437 settings->priv->wrap_around = wrap_around;
438 g_object_notify (G_OBJECT (settings), "wrap-around");
439 }
440 }
441
442 /**
443 * gtk_source_search_settings_get_wrap_around:
444 * @settings: a #GtkSourceSearchSettings.
445 *
446 * Returns: whether to wrap around the search.
447 * Since: 3.10
448 */
449 gboolean
gtk_source_search_settings_get_wrap_around(GtkSourceSearchSettings * settings)450 gtk_source_search_settings_get_wrap_around (GtkSourceSearchSettings *settings)
451 {
452 g_return_val_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings), FALSE);
453
454 return settings->priv->wrap_around;
455 }
456
457 /**
458 * gtk_source_search_settings_set_regex_enabled:
459 * @settings: a #GtkSourceSearchSettings.
460 * @regex_enabled: the setting.
461 *
462 * Enables or disables whether to search by regular expressions.
463 * If enabled, the #GtkSourceSearchSettings:search-text property contains the
464 * pattern of the regular expression.
465 *
466 * #GtkSourceSearchContext uses #GRegex when regex search is enabled. See the
467 * [Regular expression syntax](https://developer.gnome.org/glib/stable/glib-regex-syntax.html)
468 * page in the GLib reference manual.
469 *
470 * Since: 3.10
471 */
472 void
gtk_source_search_settings_set_regex_enabled(GtkSourceSearchSettings * settings,gboolean regex_enabled)473 gtk_source_search_settings_set_regex_enabled (GtkSourceSearchSettings *settings,
474 gboolean regex_enabled)
475 {
476 g_return_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings));
477
478 regex_enabled = regex_enabled != FALSE;
479
480 if (settings->priv->regex_enabled != regex_enabled)
481 {
482 settings->priv->regex_enabled = regex_enabled;
483 g_object_notify (G_OBJECT (settings), "regex-enabled");
484 }
485 }
486
487 /**
488 * gtk_source_search_settings_get_regex_enabled:
489 * @settings: a #GtkSourceSearchSettings.
490 *
491 * Returns: whether to search by regular expressions.
492 * Since: 3.10
493 */
494 gboolean
gtk_source_search_settings_get_regex_enabled(GtkSourceSearchSettings * settings)495 gtk_source_search_settings_get_regex_enabled (GtkSourceSearchSettings *settings)
496 {
497 g_return_val_if_fail (GTK_SOURCE_IS_SEARCH_SETTINGS (settings), FALSE);
498
499 return settings->priv->regex_enabled;
500 }
501