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