1 /*
2  * marker-editor.c
3  *
4  * Copyright (C) 2017 - 2018 Fabio Colacio
5  *
6  * Marker is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * Marker is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with Marker; see the file LICENSE.md. If not,
18  * see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include <string.h>
23 
24 #include <locale.h>
25 #include <glib/gi18n.h>
26 
27 #include "marker-prefs.h"
28 #include "marker-string.h"
29 
30 #include "marker-editor.h"
31 
32 struct _MarkerEditor
33 {
34   GtkBox                parent_instance;
35 
36   GFile                *file;
37   GFileMonitor         *file_monitor;
38   gchar*                title;
39   gboolean              unsaved_changes;
40 
41   GtkPaned             *paned;
42   GtkBox               *vbox;
43   GtkSearchEntry       *search_entry;
44   GtkSearchBar         *search_bar;
45   MarkerPreview        *preview;
46   MarkerSourceView     *source_view;
47   GtkScrolledWindow    *source_scroll;
48   MarkerViewMode        view_mode;
49 
50   gboolean              search_active;
51   gboolean              needs_refresh;
52   guint                 timer_id;
53 
54   GtkTextIter          *text_iter;
55 };
56 
57 G_DEFINE_TYPE (MarkerEditor, marker_editor, GTK_TYPE_BOX);
58 
59 static void
emit_signal_title_changed(MarkerEditor * editor)60 emit_signal_title_changed (MarkerEditor *editor)
61 {
62   g_autofree gchar *title = marker_editor_get_title (editor);
63   g_autofree gchar *raw_title = marker_editor_get_raw_title(editor);
64   g_signal_emit_by_name (editor, "title-changed", title, raw_title);
65 }
66 
67 static void
emit_signal_subtitle_changed(MarkerEditor * editor)68 emit_signal_subtitle_changed (MarkerEditor *editor)
69 {
70   g_autofree gchar *subtitle = marker_editor_get_subtitle (editor);
71   g_signal_emit_by_name (editor, "subtitle-changed", subtitle);
72 }
73 
74 static gboolean
refresh_timeout_cb(gpointer user_data)75 refresh_timeout_cb (gpointer user_data)
76 {
77   MarkerEditor *editor = user_data;
78   if (editor->needs_refresh)
79     marker_editor_refresh_preview (editor);
80   return G_SOURCE_CONTINUE;
81 }
82 
83 static gboolean
file_changed_cb(GFileMonitor * monior,GFile * file,GFile * other_file,GFileMonitorEvent event_type,gpointer user_data)84 file_changed_cb (GFileMonitor      *monior,
85                  GFile             *file,
86                  GFile             *other_file,
87                  GFileMonitorEvent  event_type,
88                  gpointer           user_data)
89 {
90   MarkerEditor * editor = MARKER_EDITOR(user_data);
91   g_assert (MARKER_IS_EDITOR (editor));
92   if (file) {
93     g_autofree gchar *file_contents = NULL;
94     gsize file_size = 0;
95     GError *err = NULL;
96 
97     g_file_load_contents (file, NULL, &file_contents, &file_size, NULL, &err);
98 
99     if (err)
100     {
101       g_error_free (err);
102     }
103     else
104     {
105       MarkerSourceView *source_view = editor->source_view;
106       GtkSourceBuffer *buffer =
107         GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
108       gtk_source_buffer_begin_not_undoable_action (buffer);
109       marker_source_view_set_text (source_view, file_contents, file_size);
110       gtk_source_buffer_end_not_undoable_action (buffer);
111     }
112 
113     editor->unsaved_changes = FALSE;
114 
115   }
116   return G_SOURCE_CONTINUE;
117 }
118 
119 static void
buffer_changed_cb(GtkTextBuffer * buffer,gpointer user_data)120 buffer_changed_cb (GtkTextBuffer *buffer,
121                    gpointer user_data)
122 {
123   MarkerEditor *editor = user_data;
124   if (editor->view_mode != PREVIEW_ONLY_MODE) {
125     editor->unsaved_changes = TRUE;
126   }
127   editor->needs_refresh = TRUE;
128   if (editor->text_iter) {
129     editor->text_iter = NULL;
130   }
131   emit_signal_title_changed (editor);
132 }
133 
134 static gboolean
preview_window_closed_cb(GtkWindow * preview_window,GdkEvent * event,gpointer user_data)135 preview_window_closed_cb (GtkWindow *preview_window,
136                           GdkEvent  *event,
137                           gpointer   user_data)
138 {
139   GtkWidget *preview = user_data;
140   g_object_ref (preview);
141   gtk_container_remove (GTK_CONTAINER (preview_window), preview);
142   gtk_widget_destroy (GTK_WIDGET (preview_window));
143   return TRUE;
144 }
145 
146 static void
search_text_changed(GtkEntry * entry,MarkerEditor * editor)147 search_text_changed (GtkEntry         *entry,
148                      MarkerEditor     *editor)
149 {
150   GtkSourceSearchContext* context = marker_source_get_search_context(editor->source_view);
151   GtkSourceSearchSettings * settings = gtk_source_search_context_get_settings(context);
152   gtk_source_search_settings_set_search_text(settings, gtk_entry_get_text(entry));
153 }
154 
155 static void
search_next(GtkEntry * entry,MarkerEditor * editor)156 search_next     (GtkEntry         *entry,
157                  MarkerEditor     *editor)
158 {
159   GtkSourceSearchContext* context = marker_source_get_search_context(editor->source_view);
160   GtkTextBuffer * buffer = GTK_TEXT_BUFFER(gtk_source_search_context_get_buffer(context));
161 
162   GtkTextIter *iter;
163   GtkTextIter close;
164 
165   gtk_text_buffer_get_end_iter(buffer, &close);
166 
167   if (editor->text_iter)
168   {
169     iter = editor->text_iter;
170     if (gtk_text_iter_compare(iter, &close) == 0)
171     {
172       gtk_text_buffer_get_start_iter(buffer, iter);
173     }
174   } else {
175     GtkTextIter tmp;
176     iter = &tmp;
177     gtk_text_buffer_get_start_iter(buffer, iter);
178   }
179 
180 
181   /** TODO use async forward instead **/
182   GtkTextIter start;
183   GtkTextIter end;
184   gtk_text_buffer_get_start_iter(buffer, &start);
185   gtk_text_buffer_get_start_iter(buffer, &end);
186 
187   gtk_source_search_context_forward2(context, iter, &start, &end, NULL);
188 
189   if (gtk_text_iter_compare(&start, &end) != 0){
190     gtk_text_buffer_select_range(buffer, &start, &end);
191     gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(editor->source_view), &start, 0, TRUE, 0, 0);
192     editor->text_iter = gtk_text_iter_copy(&end);
193   } else {
194     gtk_text_buffer_get_start_iter(buffer, &start);
195     editor->text_iter = gtk_text_iter_copy(&start);
196   }
197 }
198 
199 
200 static void
search_previous(GtkEntry * entry,MarkerEditor * editor)201 search_previous     (GtkEntry         *entry,
202                      MarkerEditor     *editor)
203 {
204 
205   GtkSourceSearchContext* context = marker_source_get_search_context(editor->source_view);
206   GtkTextBuffer * buffer = GTK_TEXT_BUFFER(gtk_source_search_context_get_buffer(context));
207 
208   GtkTextIter *iter;
209   GtkTextIter close;
210 
211   gtk_text_buffer_get_start_iter(buffer, &close);
212 
213   if (editor->text_iter)
214   {
215     iter = editor->text_iter;
216     if (gtk_text_iter_compare(iter, &close) == 0)
217     {
218       gtk_text_buffer_get_end_iter(buffer, iter);
219     }
220   } else {
221     GtkTextIter tmp;
222     iter = &tmp;
223     gtk_text_buffer_get_start_iter(buffer,iter);
224   }
225 
226   /** TODO use async forward instead **/
227   GtkTextIter start;
228   GtkTextIter end;
229   gtk_text_buffer_get_start_iter(buffer, &start);
230   gtk_text_buffer_get_start_iter(buffer, &end);
231 
232   gtk_source_search_context_backward2(context, iter, &start, &end, NULL);
233 
234   if (gtk_text_iter_compare(&start, &end) != 0){
235     gtk_text_buffer_select_range(buffer, &start, &end);
236     gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(editor->source_view), &start, 0, TRUE, 0, 0);
237     editor->text_iter = gtk_text_iter_copy(&start);
238   } else {
239     gtk_text_buffer_get_end_iter(buffer, &start);
240     editor->text_iter = gtk_text_iter_copy(&start);
241   }
242 }
243 
244 static void
marker_editor_init(MarkerEditor * editor)245 marker_editor_init (MarkerEditor *editor)
246 {
247   editor->file = NULL;
248   editor->title = g_strdup(_("Untitled.md"));
249   editor->unsaved_changes = FALSE;
250   editor->search_active = FALSE;
251   editor->text_iter = NULL;
252 
253   editor->paned = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
254   editor->vbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
255 
256   /** SEARCH TOOL BAR **/
257   editor->search_entry = GTK_SEARCH_ENTRY(gtk_search_entry_new());
258 
259   GtkSearchBar * sbar = GTK_SEARCH_BAR(gtk_search_bar_new());
260   editor->search_bar = sbar;
261 
262   gtk_container_add(GTK_CONTAINER(sbar), GTK_WIDGET(editor->search_entry));
263 
264   gtk_box_pack_start(editor->vbox, GTK_WIDGET(sbar), FALSE, TRUE, 0);
265 
266   gtk_widget_show_all(GTK_WIDGET(sbar));
267 
268   gtk_search_bar_set_search_mode(sbar, FALSE);
269   gtk_search_bar_set_show_close_button(sbar, TRUE);
270 
271   g_signal_connect(editor->search_entry,
272                    "search-changed",
273                    G_CALLBACK(search_text_changed),
274                    editor);
275 
276   g_signal_connect(editor->search_entry,
277                    "activate",
278                    G_CALLBACK(search_next),
279                    editor);
280 
281   g_signal_connect(editor->search_entry,
282                    "next-match",
283                    G_CALLBACK(search_next),
284                    editor);
285 
286 
287   g_signal_connect(editor->search_entry,
288                    "previous-match",
289                    G_CALLBACK(search_previous),
290                    editor);
291   /** DONE **/
292 
293   gtk_paned_set_position (editor->paned, 450);
294   gtk_widget_show (GTK_WIDGET (editor->paned));
295   gtk_box_pack_start (GTK_BOX (editor), GTK_WIDGET (editor->paned), TRUE, TRUE, 0);
296 
297   editor->preview = marker_preview_new ();
298   gtk_widget_show (GTK_WIDGET (editor->preview));
299 
300   editor->source_view = marker_source_view_new ();
301   gtk_widget_show (GTK_WIDGET (editor->source_view));
302   editor->source_scroll = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
303   gtk_widget_show (GTK_WIDGET (editor->source_scroll));
304   gtk_container_add (GTK_CONTAINER (editor->source_scroll), GTK_WIDGET (editor->source_view));
305   GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->source_view));
306   g_signal_connect (buffer, "changed", G_CALLBACK (buffer_changed_cb), editor);
307 
308   gtk_box_pack_end(editor->vbox, GTK_WIDGET(editor->source_scroll), TRUE, TRUE, 0);
309   gtk_widget_show(GTK_WIDGET (editor->vbox));
310   gtk_widget_show(GTK_WIDGET (editor->search_entry));
311 
312   editor->view_mode = marker_prefs_get_default_view_mode ();
313   editor->needs_refresh = FALSE;
314 
315   marker_editor_set_view_mode (editor, editor->view_mode);
316   gtk_widget_show (GTK_WIDGET (editor));
317 
318   editor->timer_id = g_timeout_add (20, refresh_timeout_cb, editor);
319 
320   marker_editor_apply_prefs (editor);
321 }
322 
323 static void
marker_editor_class_init(MarkerEditorClass * class)324 marker_editor_class_init (MarkerEditorClass *class)
325 {
326   g_signal_new ("title-changed",
327                 G_TYPE_FROM_CLASS (class),
328                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
329                 0, NULL, NULL, NULL,
330                 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
331 
332   g_signal_new ("subtitle-changed",
333                 G_TYPE_FROM_CLASS (class),
334                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
335                 0, NULL, NULL, NULL,
336                 G_TYPE_NONE, 1, G_TYPE_STRING);
337 }
338 
339 MarkerEditor *
marker_editor_new(void)340 marker_editor_new (void)
341 {
342   return g_object_new (MARKER_TYPE_EDITOR,
343                        "orientation", GTK_ORIENTATION_VERTICAL,
344                        "spacing",     0,
345                        NULL);
346 }
347 
348 MarkerEditor *
marker_editor_new_from_file(GFile * file)349 marker_editor_new_from_file (GFile *file)
350 {
351   MarkerEditor *editor = g_object_new (MARKER_TYPE_EDITOR,
352                                        "orientation", GTK_ORIENTATION_VERTICAL,
353                                        "spacing", 0, NULL);
354   marker_editor_open_file (editor, file);
355   return editor;
356 }
357 
358 void
marker_editor_refresh_preview(MarkerEditor * editor)359 marker_editor_refresh_preview (MarkerEditor *editor)
360 {
361   g_assert (MARKER_IS_EDITOR (editor));
362 
363   editor->needs_refresh = FALSE;
364 
365   g_autofree gchar *markdown = marker_source_view_get_text (editor->source_view, false);
366   int cursor = marker_source_view_get_cursor_position(editor->source_view);
367 
368   const char* css_theme = (marker_prefs_get_use_css_theme()) ? marker_prefs_get_css_theme() : NULL;
369   g_autofree gchar *uri = (G_IS_FILE(editor->file)) ? g_file_get_path(editor->file) : NULL;
370 
371   marker_preview_render_markdown(editor->preview, markdown, css_theme, uri, cursor);
372 }
373 
374 MarkerViewMode
marker_editor_get_view_mode(MarkerEditor * editor)375 marker_editor_get_view_mode (MarkerEditor *editor)
376 {
377   g_assert (MARKER_IS_EDITOR (editor));
378   return editor->view_mode;
379 }
380 
381 void
marker_editor_set_view_mode(MarkerEditor * editor,MarkerViewMode view_mode)382 marker_editor_set_view_mode (MarkerEditor   *editor,
383                              MarkerViewMode  view_mode)
384 {
385   g_assert (MARKER_IS_EDITOR (editor));
386 
387   if (editor->view_mode  != view_mode){
388     if (view_mode == PREVIEW_ONLY_MODE && editor->file)
389     {
390       editor->file_monitor = g_file_monitor_file(editor->file, G_FILE_MONITOR_NONE, NULL, NULL);
391       g_signal_connect(editor->file_monitor, "changed", G_CALLBACK(file_changed_cb), editor);
392 
393     } else if (editor->view_mode == PREVIEW_ONLY_MODE && editor->file)
394     {
395       g_file_monitor_cancel(editor->file_monitor);
396     }
397   }
398   editor->view_mode = view_mode;
399 
400   GtkWidget * const paned = GTK_WIDGET (editor->paned);
401   GtkWidget * const preview = GTK_WIDGET (editor->preview);
402   GtkWidget * const source_scroll = GTK_WIDGET (editor->vbox);
403   GtkContainer *parent;
404 
405   parent = GTK_CONTAINER (gtk_widget_get_parent (preview));
406   if (parent)
407   {
408     g_object_ref (preview);
409     gtk_container_remove (parent, preview);
410 
411     if (GTK_IS_WINDOW (parent))
412     {
413       gtk_widget_destroy (GTK_WIDGET (parent));
414     }
415   }
416 
417   parent = GTK_CONTAINER (gtk_widget_get_parent (source_scroll));
418   if (parent)
419   {
420     g_object_ref (source_scroll);
421     gtk_container_remove (parent, source_scroll);
422   }
423 
424   switch (view_mode)
425   {
426     case EDITOR_ONLY_MODE:
427       gtk_paned_add1 (GTK_PANED (paned), source_scroll);
428       gtk_widget_grab_focus (GTK_WIDGET (editor->source_view));
429       break;
430 
431     case PREVIEW_ONLY_MODE:
432       gtk_paned_add2 (GTK_PANED (paned), preview);
433       gtk_widget_grab_focus (GTK_WIDGET (preview));
434       break;
435 
436     case DUAL_PANE_MODE:
437       gtk_paned_add1 (GTK_PANED (paned), source_scroll);
438       gtk_paned_add2 (GTK_PANED (paned), preview);
439       gtk_widget_grab_focus (GTK_WIDGET (editor->source_view));
440       break;
441 
442     case DUAL_WINDOW_MODE:
443       gtk_paned_add1(GTK_PANED(paned), source_scroll);
444 
445       GtkWindow *preview_window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
446       g_signal_connect(preview_window, "delete-event", G_CALLBACK (preview_window_closed_cb), preview);
447       gtk_container_add (GTK_CONTAINER (preview_window), preview);
448       gtk_window_set_title (preview_window, "Preview");
449       gtk_window_set_default_size (preview_window, 500, 600);
450       gtk_widget_show_all (GTK_WIDGET (preview_window));
451       gtk_widget_grab_focus (GTK_WIDGET (editor->source_view));
452       break;
453   }
454 
455 }
456 
457 void
marker_editor_open_file(MarkerEditor * editor,GFile * file)458 marker_editor_open_file (MarkerEditor *editor,
459                         GFile        *file)
460 {
461   g_assert (MARKER_IS_EDITOR (editor));
462 
463   if (G_IS_FILE (editor->file))
464     g_object_unref (editor->file);
465 
466   editor->file = file;
467   editor->title = g_file_get_basename(file);
468   editor->needs_refresh = TRUE;
469 
470   g_autofree gchar *file_contents = NULL;
471   gsize file_size = 0;
472   GError *err = NULL;
473 
474   g_file_load_contents (file, NULL, &file_contents, &file_size, NULL, &err);
475 
476   if (err)
477   {
478     g_error_free (err);
479   }
480   else
481   {
482     MarkerSourceView *source_view = editor->source_view;
483     GtkSourceBuffer *buffer =
484       GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
485     gtk_source_buffer_begin_not_undoable_action (buffer);
486     marker_source_view_set_text (source_view, file_contents, file_size);
487     gtk_source_buffer_end_not_undoable_action (buffer);
488   }
489 
490   editor->unsaved_changes = FALSE;
491 
492   emit_signal_title_changed (editor);
493   emit_signal_subtitle_changed (editor);
494 }
495 
496 void
marker_editor_save_file(MarkerEditor * editor)497 marker_editor_save_file (MarkerEditor *editor)
498 {
499   g_assert (MARKER_IS_EDITOR (editor));
500   g_return_if_fail (G_IS_FILE (editor->file));
501 
502   g_autofree gchar *filepath = g_file_get_path (editor->file);
503 
504   FILE *fp = fopen (filepath, "w");
505 
506   if (fp)
507   {
508     g_autofree gchar *buffer = marker_source_view_get_text (editor->source_view, false);
509     fputs (buffer, fp);
510     fclose (fp);
511   }
512 
513   editor->unsaved_changes = FALSE;
514   emit_signal_title_changed (editor);
515 }
516 
517 void
marker_editor_save_file_as(MarkerEditor * editor,GFile * file)518 marker_editor_save_file_as (MarkerEditor *editor,
519                             GFile        *file)
520 {
521   g_assert (MARKER_IS_EDITOR (editor));
522 
523   if (G_IS_FILE (editor->file))
524   {
525     g_object_unref (editor->file);
526   }
527   editor->title = g_file_get_basename(file);
528   editor->file = file;
529   marker_editor_save_file (editor);
530   emit_signal_subtitle_changed (editor);
531 }
532 
533 GFile *
marker_editor_get_file(MarkerEditor * editor)534 marker_editor_get_file (MarkerEditor *editor)
535 {
536   g_assert (MARKER_IS_EDITOR (editor));
537   if (G_IS_FILE (editor->file))
538   {
539     return editor->file;
540   }
541   return NULL;
542 }
543 
544 gboolean
marker_editor_has_unsaved_changes(MarkerEditor * editor)545 marker_editor_has_unsaved_changes (MarkerEditor *editor)
546 {
547   g_assert (MARKER_IS_EDITOR (editor));
548   return editor->unsaved_changes;
549 }
550 
551 gchar *
marker_editor_get_title(MarkerEditor * editor)552 marker_editor_get_title (MarkerEditor *editor)
553 {
554   g_assert (MARKER_IS_EDITOR (editor));
555 
556   gchar *title = NULL;
557 
558   if (marker_editor_has_unsaved_changes (editor))
559   {
560     title = g_strdup_printf ("*%s", editor->title);
561   }
562   else
563   {
564     title = g_strdup(editor->title);
565   }
566 
567   return title;
568 }
569 
570 gchar *
marker_editor_get_raw_title(MarkerEditor * editor)571 marker_editor_get_raw_title (MarkerEditor *editor)
572 {
573   g_assert(MARKER_IS_EDITOR(editor));
574   return g_strdup(editor->title);
575 }
576 
577 gchar *
marker_editor_get_subtitle(MarkerEditor * editor)578 marker_editor_get_subtitle (MarkerEditor *editor)
579 {
580   g_assert (MARKER_IS_EDITOR (editor));
581 
582   gchar *subtitle = NULL;
583   GFile *file = marker_editor_get_file (editor);
584 
585   if (G_IS_FILE (file))
586   {
587     g_autofree gchar *path = g_file_get_path (file);
588     subtitle = marker_string_filename_get_path (path);
589   }
590 
591   return subtitle;
592 }
593 
594 MarkerPreview *
marker_editor_get_preview(MarkerEditor * editor)595 marker_editor_get_preview (MarkerEditor *editor)
596 {
597   g_assert (MARKER_IS_EDITOR (editor));
598   return editor->preview;
599 }
600 
601 MarkerSourceView *
marker_editor_get_source_view(MarkerEditor * editor)602 marker_editor_get_source_view (MarkerEditor *editor)
603 {
604   g_assert (MARKER_IS_EDITOR (editor));
605   return editor->source_view;
606 }
607 
608 void
marker_editor_apply_prefs(MarkerEditor * editor)609 marker_editor_apply_prefs (MarkerEditor *editor)
610 {
611   g_assert (MARKER_IS_EDITOR (editor));
612 
613   GtkSourceView * const source_view = GTK_SOURCE_VIEW (marker_editor_get_source_view (editor));
614 
615   gboolean state;
616 
617   state = marker_prefs_get_show_line_numbers ();
618   gtk_source_view_set_show_line_numbers (source_view, state);
619 
620   state = marker_prefs_get_wrap_text ();
621   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (source_view), (state) ? GTK_WRAP_WORD : GTK_WRAP_NONE );
622 
623   state = marker_prefs_get_show_right_margin ();
624   gtk_source_view_set_show_right_margin (source_view, state);
625 
626   guint position = marker_prefs_get_right_margin_position ();
627   gtk_source_view_set_right_margin_position (source_view, position);
628 
629   state = marker_prefs_get_spell_check ();
630   marker_source_view_set_spell_check (MARKER_SOURCE_VIEW (source_view), state);
631 
632   g_autofree gchar *lang = marker_prefs_get_spell_check_language ();
633   marker_source_view_set_spell_check_lang (MARKER_SOURCE_VIEW (source_view), lang);
634 
635   state = marker_prefs_get_highlight_current_line ();
636   gtk_source_view_set_highlight_current_line (source_view, state);
637 
638   GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
639   state = marker_prefs_get_use_syntax_theme ();
640   gtk_source_buffer_set_highlight_syntax(buffer, state);
641 
642   g_autofree gchar *theme = marker_prefs_get_syntax_theme ();
643   marker_source_view_set_syntax_theme (MARKER_SOURCE_VIEW (source_view), theme);
644 
645   state = marker_prefs_get_auto_indent ();
646   gtk_source_view_set_auto_indent (source_view, state);
647 
648   state = marker_prefs_get_replace_tabs ();
649   gtk_source_view_set_insert_spaces_instead_of_tabs (source_view, state);
650 
651   state = marker_prefs_get_show_spaces();
652   GtkSourceSpaceDrawer * space_drawer = gtk_source_view_get_space_drawer(source_view);
653   if (state) {
654     gtk_source_space_drawer_set_types_for_locations(space_drawer, GTK_SOURCE_SPACE_LOCATION_ALL,
655                                                     GTK_SOURCE_SPACE_TYPE_NBSP |
656                                                     GTK_SOURCE_SPACE_TYPE_SPACE |
657                                                     GTK_SOURCE_SPACE_TYPE_TAB);
658   }
659   gtk_source_space_drawer_set_enable_matrix(space_drawer, state);
660 
661   guint tab_width = marker_prefs_get_tab_width ();
662   gtk_source_view_set_indent_width (source_view, tab_width);
663 }
664 
665 
666 void
marker_editor_closing(MarkerEditor * editor)667 marker_editor_closing(MarkerEditor       *editor)
668 {
669   g_source_remove (editor->timer_id);
670   editor->needs_refresh = FALSE;
671 }
672 
673 gboolean
marker_editor_rename_file(MarkerEditor * editor,gchar * name)674 marker_editor_rename_file (MarkerEditor *editor,
675                            gchar*        name)
676 {
677   if (G_IS_FILE (editor->file))
678   {
679     /** Get new path **/
680     gchar * parent = marker_editor_get_subtitle(editor);
681     gchar * path =  g_strdup_printf("%s/%s",
682                     parent,
683                     name);
684 
685     /** Delete old file **/
686     g_file_delete(editor->file,
687                   NULL,
688                   NULL);
689 
690     /** Save file in new destination **/
691     GFile * file = g_file_new_for_path(path);
692     marker_editor_save_file_as(editor, file);
693     g_free(parent);
694     g_free(path);
695   }else {
696     /** Just change the title... **/
697     editor->title = name;
698   }
699   return TRUE;
700 }
701 
702 
703 void
marker_editor_toggle_search_bar(MarkerEditor * editor)704 marker_editor_toggle_search_bar (MarkerEditor       *editor)
705 {
706   if (!editor->search_active){
707     editor->search_active = TRUE;
708   } else {
709     gtk_entry_set_text(GTK_ENTRY(editor->search_entry), "");
710     if (editor->text_iter)
711     {
712       g_free(editor->text_iter);
713       editor->text_iter = NULL;
714     }
715   }
716 
717   gtk_search_bar_set_search_mode (editor->search_bar, editor->search_active);
718 }
719 
720 GtkSearchBar*
marker_editor_get_search_bar(MarkerEditor * editor)721 marker_editor_get_search_bar (MarkerEditor       *editor)
722 {
723   return editor->search_bar;
724 }
725