1 /*
2 * Copyright (C) 2007 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
3 * 1998, 1999 Alex Roberts, Evan Lawrence
4 * 2000 2002 Chema Celorio, Paolo Maggi
5 * 2003 2005 Paolo Maggi
6 *
7 * Some funcs based in gedit-view.c file.
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29
30 #include "gtr-dirs.h"
31 #include "gtr-settings.h"
32 #include "gtr-utils.h"
33 #include "gtr-view.h"
34 #include "gtr-application.h"
35 #include "gtr-debug.h"
36
37 #include <glib.h>
38 #include <glib/gi18n.h>
39 #include <glib-object.h>
40 #include <gtk/gtk.h>
41
42 #include <gtksourceview/gtksource.h>
43 #include <dazzle.h>
44
45 #include <gspell/gspell.h>
46
47 /**
48 * Converts the language code to a complete language code with the country
49 * If the language contains the country code this returns a new allocated
50 * string copied from *lang*.
51 *
52 * In other case the code is duplicated by default:
53 *
54 * es -> es_ES
55 * pt -> pt_PT
56 */
57 static gchar*
get_default_lang(const gchar * lang)58 get_default_lang (const gchar *lang) {
59 gchar *up;
60 gchar *ret;
61
62 if (g_strrstr (lang, "_"))
63 {
64 return g_strdup (lang);
65 }
66
67 up = g_ascii_strup (lang, -1);
68 ret = g_strdup_printf ("%s_%s", lang, up);
69 g_free (up);
70
71 return ret;
72 }
73
74 static void
inline_spellcheck(GObject * object,GParamSpec * param,GtrView * view)75 inline_spellcheck (GObject *object,
76 GParamSpec *param,
77 GtrView *view)
78 {
79 GspellTextView *gspell_view;
80 gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view));
81 gspell_text_view_set_inline_spell_checking (gspell_view, TRUE);
82 }
83
84 typedef struct
85 {
86 GSettings *editor_settings;
87 GSettings *ui_settings;
88
89 GtkSourceBuffer *buffer;
90
91 guint search_flags;
92 gchar *search_text;
93
94 GspellChecker *spell;
95 GtkCssProvider *provider;
96 } GtrViewPrivate;
97
G_DEFINE_TYPE_WITH_PRIVATE(GtrView,gtr_view,GTK_SOURCE_TYPE_VIEW)98 G_DEFINE_TYPE_WITH_PRIVATE (GtrView, gtr_view, GTK_SOURCE_TYPE_VIEW)
99
100 static void
101 gtr_view_init (GtrView * view)
102 {
103 GtkSourceLanguageManager *lm;
104 GtkSourceLanguage *lang;
105 GPtrArray *dirs;
106 gchar **langs;
107 const gchar *const *temp;
108 gchar *ui_dir;
109 GtrViewPrivate *priv;
110
111 g_autofree char *font = NULL;
112
113 priv = gtr_view_get_instance_private (view);
114
115 priv->provider = gtk_css_provider_new ();
116 gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (view)),
117 GTK_STYLE_PROVIDER (priv->provider),
118 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
119
120 priv->spell = NULL;
121 priv->editor_settings = g_settings_new ("org.gnome.gtranslator.preferences.editor");
122 priv->ui_settings = g_settings_new ("org.gnome.gtranslator.preferences.ui");
123
124 lm = gtk_source_language_manager_new ();
125 dirs = g_ptr_array_new ();
126
127 for (temp = gtk_source_language_manager_get_search_path (lm);
128 temp != NULL && *temp != NULL; ++temp)
129 g_ptr_array_add (dirs, g_strdup (*temp));
130
131 ui_dir = g_build_filename (gtr_dirs_get_gtr_data_dir (), "ui", NULL);
132 g_ptr_array_add (dirs, ui_dir);
133 g_ptr_array_add (dirs, NULL);
134 langs = (gchar **) g_ptr_array_free (dirs, FALSE);
135
136 gtk_source_language_manager_set_search_path (lm, langs);
137 lang = gtk_source_language_manager_get_language (lm, "gtranslator");
138 g_strfreev (langs);
139
140 priv->buffer = gtk_source_buffer_new_with_language (lang);
141
142 gtk_text_view_set_buffer (GTK_TEXT_VIEW (view),
143 GTK_TEXT_BUFFER (priv->buffer));
144 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
145
146 /* Set syntax highlight according to preferences */
147 gtk_source_buffer_set_highlight_syntax (priv->buffer,
148 g_settings_get_boolean (priv->editor_settings,
149 GTR_SETTINGS_HIGHLIGHT_SYNTAX));
150
151 /* Set dot char according to preferences */
152 gtr_view_enable_visible_whitespace (view,
153 g_settings_get_boolean (priv->editor_settings,
154 GTR_SETTINGS_VISIBLE_WHITESPACE));
155
156 font = g_settings_get_string (priv->editor_settings, GTR_SETTINGS_FONT);
157 gtr_view_set_font (view, font);
158
159 /* Set scheme color according to preferences */
160 gtr_view_reload_scheme_color (view);
161 gtk_text_view_set_monospace (GTK_TEXT_VIEW (view), TRUE);
162 }
163
164 static void
gtr_view_dispose(GObject * object)165 gtr_view_dispose (GObject * object)
166 {
167 GtrView *view = GTR_VIEW (object);
168 GtrViewPrivate *priv;
169
170 priv = gtr_view_get_instance_private (view);
171
172 g_clear_object (&priv->editor_settings);
173 g_clear_object (&priv->ui_settings);
174 g_clear_object (&priv->spell);
175 g_object_unref (&priv->provider);
176
177 G_OBJECT_CLASS (gtr_view_parent_class)->dispose (object);
178 }
179
180 static void
gtr_view_class_init(GtrViewClass * klass)181 gtr_view_class_init (GtrViewClass * klass)
182 {
183 GObjectClass *object_class = G_OBJECT_CLASS (klass);
184
185 object_class->dispose = gtr_view_dispose;
186 }
187
188 /**
189 * gtr_view_new:
190 *
191 * Creates a new #GtrView. An empty default buffer will be created for you.
192 *
193 * Returns: a new #GtrView
194 */
195 GtkWidget *
gtr_view_new(void)196 gtr_view_new (void)
197 {
198 GtkWidget *view;
199
200 view = GTK_WIDGET (g_object_new (GTR_TYPE_VIEW, NULL));
201 return view;
202 }
203
204 /**
205 * gtr_view_get_selected_text:
206 * @view: a #GtrView
207 * @selected_text: it stores the text selected in the #GtrView
208 * @len: it stores the length of the @selected_text
209 *
210 * Gets the selected text region of the #GtrView
211 *
212 * Returns: TRUE if the @selected_text was got correctly.
213 */
214 gboolean
gtr_view_get_selected_text(GtrView * view,gchar ** selected_text,gint * len)215 gtr_view_get_selected_text (GtrView * view,
216 gchar ** selected_text, gint * len)
217 {
218 GtkTextIter start, end;
219 GtkTextBuffer *doc;
220
221 g_return_val_if_fail (selected_text != NULL, FALSE);
222 g_return_val_if_fail (*selected_text == NULL, FALSE);
223 g_return_val_if_fail (GTR_IS_VIEW (view), FALSE);
224
225 doc = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
226
227 if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end))
228 {
229 if (len != NULL)
230 len = 0;
231
232 return FALSE;
233 }
234
235 *selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE);
236
237 if (len != NULL)
238 *len = g_utf8_strlen (*selected_text, -1);
239
240 return TRUE;
241 }
242
243 void
gtr_view_set_language(GtrView * view,const gchar * lang)244 gtr_view_set_language (GtrView *view,
245 const gchar *lang)
246 {
247 GtrViewPrivate *priv = gtr_view_get_instance_private (view);
248 GList *langs = (GList *)gspell_language_get_available ();
249 gchar **lang_parts = NULL;
250 gboolean found = FALSE;
251 gchar *def_lang;
252
253 if (!lang || *lang == '\0')
254 return;
255
256 def_lang = get_default_lang (lang);
257
258 while (langs)
259 {
260 GspellLanguage *l = (GspellLanguage*) langs->data;
261 const gchar *code = gspell_language_get_code (l);
262 if (g_strcmp0 (def_lang, code) == 0)
263 {
264 gspell_checker_set_language (priv->spell, l);
265 // If we found the language exacly, we're finished
266 found = TRUE;
267 break;
268 }
269
270 langs = g_list_next (langs);
271 }
272
273 g_free (def_lang);
274
275 if (found)
276 return;
277
278 // Not found, trying again, but this time only with the first part of
279 // the language code
280
281 langs = (GList *)gspell_language_get_available ();
282 lang_parts = g_strsplit (lang, "_", 2);
283 while (langs)
284 {
285 GspellLanguage *l = (GspellLanguage*) langs->data;
286 const gchar *code = gspell_language_get_code (l);
287 gchar **parts = g_strsplit (code, "_", 2);
288 if (parts[0] && g_strcmp0 (parts[0], lang_parts[0]) == 0)
289 {
290 gspell_checker_set_language (priv->spell, l);
291 g_strfreev (parts);
292 found = TRUE;
293 break;
294 }
295 g_strfreev (parts);
296
297 langs = g_list_next (langs);
298 }
299 g_strfreev (lang_parts);
300
301 if (!found)
302 {
303 GspellTextView *gspell_view;
304 gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view));
305 gspell_text_view_set_inline_spell_checking (gspell_view, FALSE);
306 }
307 }
308
309 /**
310 * gtr_view_enable_spellcheck:
311 * @view: a #GtrView
312 * @enable: TRUE if you want enable the spellcheck
313 *
314 * Enables the spellcheck
315 **/
316 void
gtr_view_enable_spellcheck(GtrView * view,gboolean enable)317 gtr_view_enable_spellcheck (GtrView * view, gboolean enable)
318 {
319 GtrViewPrivate *priv;
320 GspellTextView *gspell_view;
321 GtkTextBuffer *gtk_buffer;
322 GspellTextBuffer *gspell_buffer;
323
324 priv = gtr_view_get_instance_private (view);
325
326 priv->spell = gspell_checker_new (NULL);
327 gtk_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
328 gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer (gtk_buffer);
329 gspell_text_buffer_set_spell_checker (gspell_buffer, priv->spell);
330
331 gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view));
332 gspell_text_view_set_inline_spell_checking (gspell_view, enable);
333 gspell_text_view_set_enable_language_menu (gspell_view, TRUE);
334
335 g_signal_connect (G_OBJECT (priv->spell), "notify::language",
336 G_CALLBACK (inline_spellcheck), view);
337 }
338
339 /**
340 * gtr_view_enable_visible_whitespace:
341 * @view: a #GtrView
342 * @enable: TRUE if you want to enable special chars for white spaces
343 *
344 * Enables special chars for white spaces including \n and \t
345 **/
346 void
gtr_view_enable_visible_whitespace(GtrView * view,gboolean enable)347 gtr_view_enable_visible_whitespace (GtrView * view, gboolean enable)
348 {
349 GtkSourceView *source;
350 GtkSourceSpaceDrawer *drawer;
351 GtkSourceBuffer *buffer;
352 GtkSourceLanguageManager *manager;
353 GtkSourceLanguage *lang;
354 const gchar * const * deflangs = NULL;
355 const gchar *langs[20] = {NULL};
356 gint i = 0;
357
358 g_return_if_fail (GTR_IS_VIEW (view));
359
360 manager = gtk_source_language_manager_get_default ();
361 deflangs = gtk_source_language_manager_get_search_path (manager);
362 langs[1] = deflangs[0];
363
364 while (deflangs[i] && i < 18) {
365 langs[i] = deflangs[i];
366 i++;
367 }
368 langs[i] = gtr_dirs_get_gtr_sourceview_dir ();
369
370 manager = gtk_source_language_manager_new ();
371 gtk_source_language_manager_set_search_path (manager, (gchar **)langs);
372 lang = gtk_source_language_manager_get_language (manager, "gtranslator");
373
374 source = GTK_SOURCE_VIEW (view);
375 drawer = gtk_source_view_get_space_drawer (source);
376 gtk_source_space_drawer_set_enable_matrix (drawer, TRUE);
377 buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
378 gtk_source_buffer_set_implicit_trailing_newline (buffer, FALSE);
379 gtk_source_buffer_set_language (buffer, lang);
380
381 gtk_source_buffer_set_highlight_syntax (buffer, TRUE);
382
383 if (enable)
384 gtk_source_space_drawer_set_types_for_locations (drawer,
385 GTK_SOURCE_SPACE_LOCATION_ALL,
386 GTK_SOURCE_SPACE_TYPE_ALL);
387 else
388 gtk_source_space_drawer_set_types_for_locations (drawer,
389 GTK_SOURCE_SPACE_LOCATION_NONE,
390 GTK_SOURCE_SPACE_TYPE_NONE);
391 }
392
393 /**
394 * gtr_view_cut_clipboard:
395 * @view: a #GtrView
396 *
397 * Copies the currently-selected text to a clipboard,
398 * then deletes said text if it's editable.
399 */
400 void
gtr_view_cut_clipboard(GtrView * view)401 gtr_view_cut_clipboard (GtrView * view)
402 {
403 GtkTextBuffer *buffer;
404 GtkClipboard *clipboard;
405
406 g_return_if_fail (GTR_IS_VIEW (view));
407
408 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
409 g_return_if_fail (buffer != NULL);
410
411 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
412 GDK_SELECTION_CLIPBOARD);
413
414 /* FIXME: what is default editability of a buffer? */
415 gtk_text_buffer_cut_clipboard (buffer,
416 clipboard,
417 gtk_text_view_get_editable (GTK_TEXT_VIEW
418 (view)));
419
420 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
421 gtk_text_buffer_get_insert (buffer),
422 0.0, FALSE, 0.0, 0.0);
423 }
424
425 /**
426 * gtr_view_copy_clipboard:
427 * @view: a #GtrView
428 *
429 * Copies the currently-selected text to a clipboard.
430 */
431 void
gtr_view_copy_clipboard(GtrView * view)432 gtr_view_copy_clipboard (GtrView * view)
433 {
434 GtkTextBuffer *buffer;
435 GtkClipboard *clipboard;
436
437 g_return_if_fail (GTR_IS_VIEW (view));
438
439 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
440 g_return_if_fail (buffer != NULL);
441
442 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
443 GDK_SELECTION_CLIPBOARD);
444
445 gtk_text_buffer_copy_clipboard (buffer, clipboard);
446
447 /* on copy do not scroll, we are already on screen */
448 }
449
450 /**
451 * gtr_view_paste_clipboard:
452 * @view: a #GtrView
453 *
454 * Pastes the contents of a clipboard at the insertion point,
455 * or at override_location.
456 */
457 void
gtr_view_paste_clipboard(GtrView * view)458 gtr_view_paste_clipboard (GtrView * view)
459 {
460 GtkTextBuffer *buffer;
461 GtkClipboard *clipboard;
462
463 g_return_if_fail (GTR_IS_VIEW (view));
464
465 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
466 g_return_if_fail (buffer != NULL);
467
468 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
469 GDK_SELECTION_CLIPBOARD);
470
471 /* FIXME: what is default editability of a buffer? */
472 gtk_text_buffer_paste_clipboard (buffer,
473 clipboard,
474 NULL,
475 gtk_text_view_get_editable (GTK_TEXT_VIEW
476 (view)));
477
478 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view),
479 gtk_text_buffer_get_insert (buffer),
480 0.0, FALSE, 0.0, 0.0);
481 }
482
483
484 /**
485 * gtr_view_set_search_text:
486 * @view: a #GtrView
487 * @text: the text to set for searching
488 * @flags: a #GtrSearchFlags
489 *
490 * Stores the text to search for in the @view with some specific @flags.
491 */
492 void
gtr_view_set_search_text(GtrView * view,const gchar * text,guint flags)493 gtr_view_set_search_text (GtrView * view, const gchar * text, guint flags)
494 {
495 GtrViewPrivate *priv;
496 gchar *converted_text;
497
498 g_return_if_fail (GTR_IS_VIEW (view));
499
500 priv = gtr_view_get_instance_private (view);
501 g_return_if_fail ((text == NULL) || (priv->search_text != text));
502 g_return_if_fail ((text == NULL) || g_utf8_validate (text, -1, NULL));
503
504 //gedit_debug_message (DEBUG_DOCUMENT, "text = %s", text);
505
506 if (text != NULL)
507 {
508 if (*text != '\0')
509 {
510 converted_text = gtr_utils_unescape_search_text (text);
511 }
512 else
513 {
514 converted_text = g_strdup ("");
515 }
516
517 g_free (priv->search_text);
518
519 priv->search_text = converted_text;
520 //priv->num_of_lines_search_text = compute_num_of_lines (priv->search_text);
521 //update_to_search_region = TRUE;
522 }
523
524 if (!GTR_SEARCH_IS_DONT_SET_FLAGS (flags))
525 {
526 /*if (priv->search_flags != flags)
527 update_to_search_region = TRUE; */
528
529 priv->search_flags = flags;
530
531 }
532
533 /*if (update_to_search_region)
534 {
535 GtkTextIter begin;
536 GtkTextIter end;
537
538 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc),
539 &begin,
540 &end);
541
542 to_search_region_range (doc,
543 &begin,
544 &end);
545 } */
546 }
547
548 /**
549 * gtr_view_get_search_text:
550 * @view: a #GtrView
551 * @flags: the #GtrSearchFlags of the stored text.
552 *
553 * Returns the text to search for it and the #GtrSearchFlags of that
554 * text.
555 *
556 * Returns: the text to search for it.
557 */
558 gchar *
gtr_view_get_search_text(GtrView * view,guint * flags)559 gtr_view_get_search_text (GtrView * view, guint * flags)
560 {
561 GtrViewPrivate *priv;
562
563 g_return_val_if_fail (GTR_IS_VIEW (view), NULL);
564
565 priv = gtr_view_get_instance_private (view);
566
567 if (flags != NULL)
568 *flags = priv->search_flags;
569
570 return gtr_utils_escape_search_text (priv->search_text);
571 }
572
573 /**
574 * gtr_view_get_can_search_again:
575 * @view: a #GtrView
576 *
577 * Returns: TRUE if it can search again
578 */
579 gboolean
gtr_view_get_can_search_again(GtrView * view)580 gtr_view_get_can_search_again (GtrView * view)
581 {
582 GtrViewPrivate *priv;
583
584 g_return_val_if_fail (GTR_IS_VIEW (view), FALSE);
585
586 priv = gtr_view_get_instance_private (view);
587 return ((priv->search_text != NULL) &&
588 (*priv->search_text != '\0'));
589 }
590
591 /**
592 * gtr_view_search_forward:
593 * @view: a #GtrView
594 * @start: start of search
595 * @end: bound for the search, or %NULL for the end of the buffer
596 * @match_start: return location for start of match, or %NULL
597 * @match_end: return location for end of match, or %NULL
598 *
599 * Searches forward for str. Any match is returned by setting match_start to the
600 * first character of the match and match_end to the first character after the match.
601 * The search will not continue past limit.
602 * Note that a search is a linear or O(n) operation, so you may wish to use limit
603 * to avoid locking up your UI on large buffers.
604 *
605 * Returns: whether a match was found
606 */
607 gboolean
gtr_view_search_forward(GtrView * view,const GtkTextIter * start,const GtkTextIter * end,GtkTextIter * match_start,GtkTextIter * match_end)608 gtr_view_search_forward (GtrView * view,
609 const GtkTextIter * start,
610 const GtkTextIter * end,
611 GtkTextIter * match_start, GtkTextIter * match_end)
612 {
613 GtkSourceBuffer *doc;
614 GtkTextIter iter;
615 GtkTextSearchFlags search_flags;
616 gboolean found = FALSE;
617 GtkTextIter m_start;
618 GtkTextIter m_end;
619 GtrViewPrivate *priv;
620
621 g_return_val_if_fail (GTR_IS_VIEW (view), FALSE);
622
623 doc = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
624
625 g_return_val_if_fail ((start == NULL) ||
626 (gtk_text_iter_get_buffer (start) ==
627 GTK_TEXT_BUFFER (doc)), FALSE);
628 g_return_val_if_fail ((end == NULL)
629 || (gtk_text_iter_get_buffer (end) ==
630 GTK_TEXT_BUFFER (doc)), FALSE);
631
632 priv = gtr_view_get_instance_private (view);
633
634 if (priv->search_text == NULL)
635 {
636 //gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n");
637 return FALSE;
638 }
639 /*else
640 gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); */
641
642 if (start == NULL)
643 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), &iter);
644 else
645 iter = *start;
646
647 search_flags = GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY;
648
649 if (!GTR_SEARCH_IS_CASE_SENSITIVE (priv->search_flags))
650 {
651 search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE;
652 }
653
654 while (!found)
655 {
656 found = gtk_text_iter_forward_search (&iter,
657 priv->search_text,
658 search_flags,
659 &m_start, &m_end, end);
660
661 if (found && GTR_SEARCH_IS_ENTIRE_WORD (priv->search_flags))
662 {
663 found = gtk_text_iter_starts_word (&m_start) &&
664 gtk_text_iter_ends_word (&m_end);
665
666 if (!found)
667 iter = m_end;
668 }
669 else
670 break;
671 }
672
673 if (found && (match_start != NULL))
674 *match_start = m_start;
675
676 if (found && (match_end != NULL))
677 *match_end = m_end;
678
679 return found;
680 }
681
682 /**
683 * gtr_view_search_backward:
684 * @view: a #GtrView
685 * @start: start of search
686 * @end: bound for the search, or %NULL for the end of the buffer
687 * @match_start: return location for start of match, or %NULL
688 * @match_end: return location for end of match, or %NULL
689 *
690 * Searches backward for str. Any match is returned by setting match_start to the
691 * first character of the match and match_end to the first character after the match.
692 * The search will not continue past limit.
693 * Note that a search is a linear or O(n) operation, so you may wish to use limit
694 * to avoid locking up your UI on large buffers.
695 *
696 * Returns: whether a match was found
697 */
698 gboolean
gtr_view_search_backward(GtrView * view,const GtkTextIter * start,const GtkTextIter * end,GtkTextIter * match_start,GtkTextIter * match_end)699 gtr_view_search_backward (GtrView * view,
700 const GtkTextIter * start,
701 const GtkTextIter * end,
702 GtkTextIter * match_start, GtkTextIter * match_end)
703 {
704 GtkSourceBuffer *doc;
705 GtkTextIter iter;
706 GtkTextSearchFlags search_flags;
707 gboolean found = FALSE;
708 GtkTextIter m_start;
709 GtkTextIter m_end;
710 GtrViewPrivate *priv;
711
712 g_return_val_if_fail (GTR_IS_VIEW (view), FALSE);
713
714 doc = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
715
716 g_return_val_if_fail ((start == NULL) ||
717 (gtk_text_iter_get_buffer (start) ==
718 GTK_TEXT_BUFFER (doc)), FALSE);
719 g_return_val_if_fail ((end == NULL)
720 || (gtk_text_iter_get_buffer (end) ==
721 GTK_TEXT_BUFFER (doc)), FALSE);
722
723 priv = gtr_view_get_instance_private (view);
724
725 if (priv->search_text == NULL)
726 {
727 //gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n");
728 return FALSE;
729 }
730 /*else
731 gedit_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); */
732
733 if (end == NULL)
734 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter);
735 else
736 iter = *end;
737
738 search_flags = GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY;
739
740 if (!GTR_SEARCH_IS_CASE_SENSITIVE (priv->search_flags))
741 {
742 search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE;
743 }
744
745 while (!found)
746 {
747 found = gtk_text_iter_backward_search (&iter,
748 priv->search_text,
749 search_flags,
750 &m_start, &m_end, start);
751
752 if (found && GTR_SEARCH_IS_ENTIRE_WORD (priv->search_flags))
753 {
754 found = gtk_text_iter_starts_word (&m_start) &&
755 gtk_text_iter_ends_word (&m_end);
756
757 if (!found)
758 iter = m_start;
759 }
760 else
761 break;
762 }
763
764 if (found && (match_start != NULL))
765 *match_start = m_start;
766
767 if (found && (match_end != NULL))
768 *match_end = m_end;
769
770 return found;
771 }
772
773 /**
774 * gtr_view_replace_all:
775 * @view: a #GtrView
776 * @find: the text to find
777 * @replace: the text to replace @find
778 * @flags: a #GtrSearchFlags
779 *
780 * Replaces all matches of @find with @replace and returns the number of
781 * replacements.
782 *
783 * Returns: the number of replacements made it.
784 */
785 gint
gtr_view_replace_all(GtrView * view,const gchar * find,const gchar * replace,guint flags)786 gtr_view_replace_all (GtrView * view,
787 const gchar * find, const gchar * replace, guint flags)
788 {
789 GtkTextIter iter;
790 GtkTextIter m_start;
791 GtkTextIter m_end;
792 GtkTextSearchFlags search_flags = 0;
793 GtrViewPrivate *priv;
794 gboolean found = TRUE;
795 gint cont = 0;
796 gchar *search_text;
797 gchar *replace_text;
798 gint replace_text_len;
799 GtkTextBuffer *buffer;
800
801 g_return_val_if_fail (GTR_IS_VIEW (view), 0);
802
803 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
804
805 priv = gtr_view_get_instance_private (view);
806
807 g_return_val_if_fail (replace != NULL, 0);
808 g_return_val_if_fail ((find != NULL)
809 || (priv->search_text != NULL), 0);
810
811 if (find == NULL)
812 search_text = g_strdup (priv->search_text);
813 else
814 search_text = gtr_utils_unescape_search_text (find);
815
816 replace_text = gtr_utils_unescape_search_text (replace);
817
818 gtk_text_buffer_get_start_iter (buffer, &iter);
819
820 search_flags = GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY;
821
822 if (!GTR_SEARCH_IS_CASE_SENSITIVE (flags))
823 {
824 search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE;
825 }
826
827 replace_text_len = strlen (replace_text);
828
829 /* disable cursor_moved emission until the end of the
830 * replace_all so that we don't spend all the time
831 * updating the position in the statusbar
832 */
833 //priv->stop_cursor_moved_emission = TRUE;
834
835 gtk_text_buffer_begin_user_action (buffer);
836
837 do
838 {
839 found = gtk_text_iter_forward_search (&iter,
840 search_text,
841 search_flags,
842 &m_start, &m_end, NULL);
843
844 if (found && GTR_SEARCH_IS_ENTIRE_WORD (flags))
845 {
846 gboolean word;
847
848 word = gtk_text_iter_starts_word (&m_start) &&
849 gtk_text_iter_ends_word (&m_end);
850
851 if (!word)
852 {
853 iter = m_end;
854 continue;
855 }
856 }
857
858 if (found)
859 {
860 ++cont;
861
862 gtk_text_buffer_delete (buffer, &m_start, &m_end);
863 gtk_text_buffer_insert (buffer,
864 &m_start, replace_text, replace_text_len);
865
866 iter = m_start;
867 }
868
869 }
870 while (found);
871
872 gtk_text_buffer_end_user_action (buffer);
873
874 /* re-enable cursor_moved emission and notify
875 * the current position
876 */
877 //priv->stop_cursor_moved_emission = FALSE;
878 //emit_cursor_moved (GTK_SOURCE_BUFFER(buffer));
879
880 g_free (search_text);
881 g_free (replace_text);
882
883 return cont;
884 }
885
886 /**
887 * gtr_view_reload_scheme_color:
888 * @view: a #GtrView
889 *
890 * Reloads the gtksourceview scheme color. Neccessary when the scheme color
891 * changes.
892 */
893 void
gtr_view_reload_scheme_color(GtrView * view)894 gtr_view_reload_scheme_color (GtrView * view)
895 {
896 GtkSourceBuffer *buf;
897 GtkSourceStyleScheme *scheme;
898 GtkSourceStyleSchemeManager *manager;
899 GtrViewPrivate *priv;
900 gchar *scheme_id;
901
902 priv = gtr_view_get_instance_private (view);
903
904 buf = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
905 manager = gtk_source_style_scheme_manager_get_default ();
906
907 scheme_id = g_settings_get_string (priv->ui_settings,
908 GTR_SETTINGS_COLOR_SCHEME);
909 scheme = gtk_source_style_scheme_manager_get_scheme (manager, scheme_id);
910 g_free (scheme_id);
911
912 gtk_source_buffer_set_style_scheme (buf, scheme);
913 }
914
915 void
gtr_view_set_font(GtrView * view,char * font)916 gtr_view_set_font (GtrView *view, char *font)
917 {
918 PangoFontDescription *font_desc = NULL;
919 g_autofree char *str = NULL;
920 g_autofree char *css = NULL;
921 GtrViewPrivate *priv = gtr_view_get_instance_private (view);
922 g_autoptr (GtkWidget) button = gtk_font_button_new ();
923
924 gtk_font_chooser_set_font (GTK_FONT_CHOOSER (button), font);
925 font_desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (button));
926 str = dzl_pango_font_description_to_css (font_desc);
927 css = g_strdup_printf ("textview { %s }", str ?: "");
928
929 gtk_css_provider_load_from_data (priv->provider, css, -1, NULL);
930
931 pango_font_description_free (font_desc);
932 }
933