1 /*
2  * marker-prefs.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 <gtk/gtk.h>
23 #include <gtksourceview/gtksource.h>
24 #include <gtkspell/gtkspell.h>
25 
26 #include <dirent.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "marker.h"
31 #include "marker-widget.h"
32 #include "marker-string.h"
33 #include "marker-window.h"
34 
35 #include "marker-prefs.h"
36 
37 MarkerPrefs prefs;
38 
39 gboolean
marker_prefs_get_use_dark_theme()40 marker_prefs_get_use_dark_theme()
41 {
42   return g_settings_get_boolean(prefs.window_settings, "enable-dark-mode");
43 }
44 
45 void
marker_prefs_set_use_dark_theme(gboolean state)46 marker_prefs_set_use_dark_theme(gboolean state)
47 {
48   g_settings_set_boolean(prefs.window_settings, "enable-dark-mode", state);
49 }
50 
51 gboolean
marker_prefs_get_use_syntax_theme()52 marker_prefs_get_use_syntax_theme()
53 {
54   return g_settings_get_boolean(prefs.editor_settings, "enable-syntax-theme");
55 }
56 
57 void
marker_prefs_set_use_syntax_theme(gboolean state)58 marker_prefs_set_use_syntax_theme(gboolean state)
59 {
60   g_settings_set_boolean(prefs.editor_settings, "enable-syntax-theme", state);
61 }
62 
63 char*
marker_prefs_get_css_theme()64 marker_prefs_get_css_theme()
65 {
66   return g_settings_get_string(prefs.preview_settings, "css-theme");
67 }
68 
69 void
marker_prefs_set_css_theme(const char * theme)70 marker_prefs_set_css_theme(const char* theme)
71 {
72   g_settings_set_string(prefs.preview_settings, "css-theme", theme);
73 }
74 
75 gboolean
marker_prefs_get_use_css_theme()76 marker_prefs_get_use_css_theme()
77 {
78   return g_settings_get_boolean(prefs.preview_settings, "css-toggle");
79 }
80 
81 void
marker_prefs_set_use_css_theme(gboolean state)82 marker_prefs_set_use_css_theme(gboolean state)
83 {
84   g_settings_set_boolean(prefs.preview_settings, "css-toggle", state);
85 }
86 
87 char*
marker_prefs_get_highlight_theme()88 marker_prefs_get_highlight_theme()
89 {
90   return g_settings_get_string(prefs.preview_settings, "highlight-theme");
91 }
92 
93 
94 void
marker_prefs_set_highlight_theme(const char * theme)95 marker_prefs_set_highlight_theme(const char* theme)
96 {
97   g_settings_set_string(prefs.preview_settings, "highlight-theme", theme);
98 }
99 
100 gboolean
marker_prefs_get_use_mathjs()101 marker_prefs_get_use_mathjs()
102 {
103   return g_settings_get_boolean(prefs.preview_settings, "mathjs-toggle");
104 }
105 
106 void
marker_prefs_set_use_mathjs(gboolean state)107 marker_prefs_set_use_mathjs(gboolean state)
108 {
109   g_settings_set_boolean(prefs.preview_settings, "mathjs-toggle", state);
110 }
111 
112 gdouble
makrer_prefs_get_zoom_level()113 makrer_prefs_get_zoom_level()
114 {
115   return  g_settings_get_double(prefs.preview_settings, "preview-zoom-level");
116 }
117 
118 void
marker_prefs_set_zoom_level(gdouble val)119 marker_prefs_set_zoom_level(gdouble val)
120 {
121   g_settings_set_double(prefs.preview_settings, "preview-zoom-level", val);
122 }
123 
124 gboolean
marker_prefs_get_use_mermaid()125 marker_prefs_get_use_mermaid()
126 {
127   return g_settings_get_boolean(prefs.preview_settings, "mermaid-toggle");
128 }
129 
130 void
marker_prefs_set_use_mermaid(gboolean state)131 marker_prefs_set_use_mermaid(gboolean state)
132 {
133   g_settings_set_boolean(prefs.preview_settings, "mermaid-toggle", state);
134 }
135 
136 gboolean
marker_prefs_get_use_charter()137 marker_prefs_get_use_charter()
138 {
139   return g_settings_get_boolean(prefs.preview_settings, "charter-toggle");
140 }
141 
142 void
marker_prefs_set_use_charter(gboolean state)143 marker_prefs_set_use_charter(gboolean state)
144 {
145   g_settings_set_boolean(prefs.preview_settings, "charter-toggle", state);
146 }
147 
148 gboolean
marker_prefs_get_use_highlight()149 marker_prefs_get_use_highlight()
150 {
151   return g_settings_get_boolean(prefs.preview_settings, "highlight-toggle");
152 }
153 
154 void
marker_prefs_set_use_highlight(gboolean state)155 marker_prefs_set_use_highlight(gboolean state)
156 {
157   g_settings_set_boolean(prefs.preview_settings, "highlight-toggle", state);
158 }
159 
160 char*
marker_prefs_get_syntax_theme()161 marker_prefs_get_syntax_theme()
162 {
163   return g_settings_get_string(prefs.editor_settings, "syntax-theme");
164 }
165 
166 void
marker_prefs_set_syntax_theme(const char * theme)167 marker_prefs_set_syntax_theme(const char* theme)
168 {
169   g_settings_set_string(prefs.editor_settings, "syntax-theme", theme);
170 }
171 
172 guint
marker_prefs_get_right_margin_position()173 marker_prefs_get_right_margin_position()
174 {
175   return g_settings_get_uint(prefs.editor_settings, "show-right-margin-position");
176 }
177 
178 void
marker_prefs_set_right_margin_position(guint position)179 marker_prefs_set_right_margin_position(guint position)
180 {
181   g_settings_set_uint(prefs.editor_settings, "show-right-margin-position", position);
182 }
183 
184 gboolean
marker_prefs_get_replace_tabs()185 marker_prefs_get_replace_tabs()
186 {
187   return  g_settings_get_boolean(prefs.editor_settings, "replace-tabs");
188 }
189 
190 void
marker_prefs_set_replace_tabs(gboolean state)191 marker_prefs_set_replace_tabs(gboolean state)
192 {
193    g_settings_set_boolean(prefs.editor_settings, "replace-tabs", state);
194 }
195 
196 guint
marker_prefs_get_tab_width()197 marker_prefs_get_tab_width()
198 {
199   return g_settings_get_uint(prefs.editor_settings, "tab-width");
200 }
201 
202 void
marker_prefs_set_tab_width(guint width)203 marker_prefs_set_tab_width(guint width)
204 {
205   g_settings_set_uint(prefs.editor_settings, "tab-width", width);
206 }
207 
208 gboolean
marker_prefs_get_auto_indent()209 marker_prefs_get_auto_indent()
210 {
211   return g_settings_get_boolean(prefs.editor_settings, "auto-indent");
212 }
213 
214 void
marker_prefs_set_auto_indent(gboolean state)215 marker_prefs_set_auto_indent(gboolean state)
216 {
217   g_settings_set_boolean(prefs.editor_settings, "auto-indent", state);
218 }
219 
220 gboolean
marker_prefs_get_show_spaces(void)221 marker_prefs_get_show_spaces (void)
222 {
223   return g_settings_get_boolean(prefs.editor_settings, "show-spaces");
224 }
225 
226 void
marker_prefs_set_show_spaces(gboolean state)227 marker_prefs_set_show_spaces (gboolean state)
228 {
229   g_settings_set_boolean(prefs.editor_settings, "show-spaces", state);
230 }
231 
232 gboolean
marker_prefs_get_spell_check()233 marker_prefs_get_spell_check()
234 {
235   return g_settings_get_boolean(prefs.editor_settings, "spell-check");
236 }
237 
238 void
marker_prefs_set_spell_check(gboolean state)239 marker_prefs_set_spell_check(gboolean state)
240 {
241   g_settings_set_boolean(prefs.editor_settings, "spell-check", state);
242 }
243 
244 gchar*
marker_prefs_get_spell_check_language()245 marker_prefs_get_spell_check_language()
246 {
247   return g_settings_get_string(prefs.editor_settings, "spell-check-lang");
248 }
249 
250 void
marker_prefs_set_spell_check_language(const char * lang)251 marker_prefs_set_spell_check_language(const char* lang)
252 {
253   g_settings_set_string(prefs.editor_settings, "spell-check-lang", lang);
254 }
255 
256 gboolean
marker_prefs_get_show_line_numbers()257 marker_prefs_get_show_line_numbers()
258 {
259   return g_settings_get_boolean(prefs.editor_settings, "show-line-numbers");
260 }
261 
262 void
marker_prefs_set_show_line_numbers(gboolean state)263 marker_prefs_set_show_line_numbers(gboolean state)
264 {
265   g_settings_set_boolean(prefs.editor_settings, "show-line-numbers", state);
266 }
267 
268 gboolean
marker_prefs_get_highlight_current_line()269 marker_prefs_get_highlight_current_line()
270 {
271   return g_settings_get_boolean(prefs.editor_settings, "highlight-current-line");
272 }
273 
274 void
marker_prefs_set_highlight_current_line(gboolean state)275 marker_prefs_set_highlight_current_line(gboolean state)
276 {
277   g_settings_set_boolean(prefs.editor_settings, "highlight-current-line", state);
278 }
279 
280 gboolean
marker_prefs_get_wrap_text()281 marker_prefs_get_wrap_text()
282 {
283   return g_settings_get_boolean(prefs.editor_settings, "wrap-text");
284 }
285 
286 void
marker_prefs_set_wrap_text(gboolean state)287 marker_prefs_set_wrap_text(gboolean state)
288 {
289   g_settings_set_boolean(prefs.editor_settings, "wrap-text", state);
290 }
291 
292 gboolean
marker_prefs_get_show_right_margin()293 marker_prefs_get_show_right_margin()
294 {
295   return g_settings_get_boolean(prefs.editor_settings, "show-right-margin");
296 }
297 
298 void
marker_prefs_set_show_right_margin(gboolean state)299 marker_prefs_set_show_right_margin(gboolean state)
300 {
301   g_settings_set_boolean(prefs.editor_settings, "show-right-margin", state);
302 }
303 
304 MarkerViewMode
marker_prefs_get_default_view_mode()305 marker_prefs_get_default_view_mode()
306 {
307   return g_settings_get_enum(prefs.window_settings, "view-mode");
308 }
309 
310 void
marker_prefs_set_default_view_mode(MarkerViewMode view_mode)311 marker_prefs_set_default_view_mode(MarkerViewMode view_mode)
312 {
313   g_settings_set_enum(prefs.window_settings, "view-mode", view_mode);
314 }
315 
316 
317 MarkerMathBackEnd
marker_prefs_get_math_backend(void)318 marker_prefs_get_math_backend (void)
319 {
320   return g_settings_get_enum(prefs.preview_settings, "math-backend");
321 }
322 
323 void
marker_prefs_set_math_backend(MarkerMathBackEnd backend)324 marker_prefs_set_math_backend (MarkerMathBackEnd   backend)
325 {
326   g_settings_set_enum(prefs.preview_settings, "math-backend", backend);
327 }
328 
329 GList*
marker_prefs_get_available_stylesheets()330 marker_prefs_get_available_stylesheets()
331 {
332   GList* list = NULL;
333   char* list_item;
334 
335   DIR* dir;
336   struct dirent* ent;
337   char* filename;
338   if ((dir = opendir(STYLES_DIR)) != NULL)
339   {
340     while ((ent = readdir(dir)) != NULL)
341     {
342       filename = ent->d_name;
343       if (marker_string_ends_with(filename, ".css"))
344       {
345         list_item = marker_string_alloc(filename);
346         list = g_list_prepend(list, list_item);
347       }
348     }
349   }
350   closedir(dir);
351 
352   return list;
353 }
354 
355 GList*
marker_prefs_get_available_highlight_themes()356 marker_prefs_get_available_highlight_themes()
357 {
358   GList* list = NULL;
359   char* list_item;
360 
361   DIR* dir;
362   struct dirent* ent;
363   char* filename;
364 
365   if ((dir = opendir(HIGHLIGHT_STYLES_DIR)) != NULL)
366   {
367     while ((ent = readdir(dir)) != NULL)
368     {
369       filename = ent->d_name;
370 
371       if (marker_string_ends_with(filename, ".css"))
372       {
373         list_item = marker_string_filename_get_name_noext(filename);
374         list = g_list_prepend(list, list_item);
375       }
376     }
377   }
378   closedir(dir);
379 
380   return list;
381 }
382 
383 GList*
marker_prefs_get_available_languages()384 marker_prefs_get_available_languages()
385 {
386   GList* list = gtk_spell_checker_get_language_list ();
387   return list;
388 }
389 
390 GList*
marker_prefs_get_available_syntax_themes()391 marker_prefs_get_available_syntax_themes()
392 {
393   GList* list = NULL;
394 
395   GtkSourceStyleSchemeManager* style_manager =
396     gtk_source_style_scheme_manager_get_default();
397   const gchar * const * ids =
398     gtk_source_style_scheme_manager_get_scheme_ids(style_manager);
399 
400   for (int i = 0; ids[i] != NULL; ++i)
401   {
402     const gchar* id = ids[i];
403     char* item = marker_string_alloc(id);
404     list = g_list_prepend(list, item);
405   }
406 
407   return list;
408 }
409 
410 static void
update_editors()411 update_editors ()
412 {
413   GtkApplication *app = marker_get_app();
414   GList *windows = gtk_application_get_windows(app);
415   for (GList *item = windows; item != NULL; item = item->next)
416   {
417     if (MARKER_IS_WINDOW(item->data))
418     {
419       MarkerWindow *window = item->data;
420       MarkerEditor *editor = marker_window_get_active_editor (window);
421       marker_editor_apply_prefs (editor);
422     }
423   }
424 }
425 
426 static void
refresh_preview()427 refresh_preview ()
428 {
429   GtkApplication *app = marker_get_app();
430   GList *windows = gtk_application_get_windows(app);
431   for (GList *item = windows; item != NULL; item = item->next)
432   {
433     if (MARKER_IS_WINDOW(item->data))
434     {
435       MarkerWindow *window = item->data;
436       marker_window_refresh_all_preview(window);
437     }
438   }
439 }
440 
441 static void
show_line_numbers_toggled(GtkToggleButton * button,gpointer user_data)442 show_line_numbers_toggled(GtkToggleButton* button,
443                           gpointer         user_data)
444 {
445   gboolean state = gtk_toggle_button_get_active(button);
446   marker_prefs_set_show_line_numbers(state);
447   update_editors ();
448 }
449 
450 static void
editor_syntax_toggled(GtkToggleButton * button,gpointer user_data)451 editor_syntax_toggled(GtkToggleButton* button,
452                       gpointer         user_data)
453 {
454   gboolean state = gtk_toggle_button_get_active(button);
455   marker_prefs_set_use_syntax_theme(state);
456 
457   marker_prefs_set_use_highlight(state);
458   if (user_data)
459   {
460     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
461   }
462 
463   update_editors ();
464 }
465 
466 static void
css_toggled(GtkToggleButton * button,gpointer user_data)467 css_toggled(GtkToggleButton* button,
468             gpointer         user_data)
469 {
470   gboolean state = gtk_toggle_button_get_active(button);
471   marker_prefs_set_use_css_theme(state);
472 
473   if (user_data)
474   {
475     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
476   }
477 
478   refresh_preview();
479 }
480 
481 static void
highlight_current_line_toggled(GtkToggleButton * button,gpointer user_data)482 highlight_current_line_toggled(GtkToggleButton* button,
483                                gpointer         user_data)
484 {
485   gboolean state = gtk_toggle_button_get_active(button);
486   marker_prefs_set_highlight_current_line(state);
487   update_editors ();
488 }
489 
490 static void
enable_mathjs_toggled(GtkToggleButton * button,gpointer user_data)491 enable_mathjs_toggled(GtkToggleButton* button,
492                        gpointer         user_data)
493 {
494   gboolean state = gtk_toggle_button_get_active(button);
495   marker_prefs_set_use_mathjs(state);
496   if (user_data)
497     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
498   refresh_preview();
499 }
500 
501 static void
enable_mermaid_toggled(GtkToggleButton * button,gpointer user_data)502 enable_mermaid_toggled(GtkToggleButton* button,
503                        gpointer         user_data)
504 {
505   gboolean state = gtk_toggle_button_get_active(button);
506   marker_prefs_set_use_mermaid(state);
507   refresh_preview();
508 }
509 
510 static void
enable_charter_toggled(GtkToggleButton * button,gpointer user_data)511 enable_charter_toggled(GtkToggleButton* button,
512                        gpointer         user_data)
513 {
514   gboolean state = gtk_toggle_button_get_active(button);
515   marker_prefs_set_use_charter(state);
516   refresh_preview();
517 }
518 
519 static void
wrap_text_toggled(GtkToggleButton * button,gpointer user_data)520 wrap_text_toggled(GtkToggleButton* button,
521                   gpointer         user_data)
522 {
523   gboolean state = gtk_toggle_button_get_active(button);
524   marker_prefs_set_wrap_text(state);
525   update_editors ();
526 }
527 
528 static void
show_spaces_toggled(GtkToggleButton * button,gpointer user_data)529 show_spaces_toggled(GtkToggleButton* button,
530                     gpointer         user_data)
531 {
532   gboolean state = gtk_toggle_button_get_active(button);
533   marker_prefs_set_show_spaces(state);
534   update_editors ();
535 }
536 
537 static void
enable_dark_mode_toggled(GtkToggleButton * button,gpointer user_data)538 enable_dark_mode_toggled(GtkToggleButton* button,
539                          gpointer         user_data)
540 {
541   gboolean state = gtk_toggle_button_get_active(button);
542   marker_prefs_set_use_dark_theme(state);
543   g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", state, NULL);
544 }
545 
546 static void
auto_indent_toggled(GtkToggleButton * button,gpointer user_data)547 auto_indent_toggled(GtkToggleButton* button,
548                     gpointer         user_data)
549 {
550   gboolean state = gtk_toggle_button_get_active(button);
551   marker_prefs_set_auto_indent(state);
552   update_editors ();
553 }
554 
555 static void
spell_lang_chosen(GtkComboBox * combo_box,gpointer user_data)556 spell_lang_chosen(GtkComboBox* combo_box,
557               gpointer     user_data)
558 {
559   char* choice = marker_widget_combo_box_get_active_str(combo_box);
560   marker_prefs_set_spell_check_language(choice);
561   update_editors ();
562 }
563 
564 static void
spell_check_toggled(GtkToggleButton * button,gpointer user_data)565 spell_check_toggled(GtkToggleButton* button,
566                      gpointer         user_data)
567 {
568   gboolean state = gtk_toggle_button_get_active(button);
569   marker_prefs_set_spell_check(state);
570 
571   if (user_data)
572   {
573     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
574   }
575 
576   update_editors ();
577 }
578 
579 static void
replace_tabs_toggled(GtkToggleButton * button,gpointer user_data)580 replace_tabs_toggled(GtkToggleButton* button,
581                      gpointer         user_data)
582 {
583   gboolean state = gtk_toggle_button_get_active(button);
584   marker_prefs_set_replace_tabs(state);
585   update_editors ();
586 }
587 
588 static void
tab_width_value_changed(GtkSpinButton * spin_button,gpointer user_data)589 tab_width_value_changed(GtkSpinButton *spin_button,
590                         gpointer       user_data)
591 {
592   guint value = gtk_spin_button_get_value_as_int (spin_button);
593   marker_prefs_set_tab_width(value);
594   update_editors ();
595 }
596 
597 static void
right_margin_position_value_changed(GtkSpinButton * spin_button,gpointer user_data)598 right_margin_position_value_changed(GtkSpinButton* spin_button,
599                                     gpointer       user_data)
600 {
601   guint value = gtk_spin_button_get_value_as_int(spin_button);
602   marker_prefs_set_right_margin_position(value);
603   update_editors ();
604 }
605 
606 static void
show_right_margin_toggled(GtkToggleButton * button,gpointer user_data)607 show_right_margin_toggled(GtkToggleButton* button,
608                           gpointer         user_data)
609 {
610   gboolean state = gtk_toggle_button_get_active(button);
611   marker_prefs_set_show_right_margin(state);
612 
613   if (user_data)
614   {
615     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
616   }
617 
618   update_editors ();
619 }
620 
621 static void
syntax_chosen(GtkComboBox * combo_box,gpointer user_data)622 syntax_chosen(GtkComboBox* combo_box,
623               gpointer     user_data)
624 {
625   g_autofree gchar* choice = marker_widget_combo_box_get_active_str(combo_box);
626   marker_prefs_set_syntax_theme (choice);
627   update_editors ();
628 }
629 
630 static void
css_chosen(GtkComboBox * combo_box,gpointer user_data)631 css_chosen(GtkComboBox* combo_box,
632            gpointer     user_data)
633 {
634   char* choice = marker_widget_combo_box_get_active_str(combo_box);
635 
636   marker_prefs_set_css_theme(choice);
637 
638   free(choice);
639   refresh_preview();
640 }
641 
642 static void
highlight_css_chosen(GtkComboBox * combo_box,gpointer user_data)643 highlight_css_chosen(GtkComboBox* combo_box,
644                      gpointer     user_data)
645 {
646   char* choice = marker_widget_combo_box_get_active_str(combo_box);
647   marker_prefs_set_highlight_theme(choice);
648 
649   free(choice);
650 
651   refresh_preview();
652 }
653 
654 static void
code_highlight_toggled(GtkToggleButton * button,gpointer user_data)655 code_highlight_toggled(GtkToggleButton* button,
656                        gpointer user_data)
657 {
658   gboolean state = gtk_toggle_button_get_active(button);
659   marker_prefs_set_use_highlight(state);
660 
661   if (user_data)
662   {
663     gtk_widget_set_sensitive(GTK_WIDGET(user_data), state);
664   }
665 
666   refresh_preview();
667 }
668 
669 static void
default_view_mode_chosen(GtkComboBox * combo_box,gpointer user_data)670 default_view_mode_chosen(GtkComboBox* combo_box,
671                          gpointer     user_data)
672 {
673   MarkerViewMode mode = gtk_combo_box_get_active(combo_box);
674   marker_prefs_set_default_view_mode(mode);
675 }
676 
677 static void
math_backend_changed(GtkComboBox * combo_box,gpointer user_data)678 math_backend_changed (GtkComboBox* combo_box,
679                          gpointer     user_data)
680 {
681   MarkerMathBackEnd backend = gtk_combo_box_get_active(combo_box);
682   marker_prefs_set_math_backend(backend);
683   refresh_preview();
684 }
685 
686 void
marker_prefs_show_window()687 marker_prefs_show_window()
688 {
689   GtkBuilder* builder =
690     gtk_builder_new_from_resource(
691       "/com/github/fabiocolacio/marker/ui/marker-prefs-window.ui");
692 
693   GList *list = NULL;
694   GtkComboBox* combo_box;
695   GtkToggleButton* check_button;
696   GtkSpinButton* spin_button;
697 
698   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "syntax_chooser"));
699   list = marker_prefs_get_available_syntax_themes();
700   marker_widget_populate_combo_box_with_strings(combo_box, list);
701   char* syntax = marker_prefs_get_syntax_theme();
702   marker_widget_combo_box_set_active_str(combo_box,syntax, g_list_length(list));
703   gtk_widget_set_sensitive(GTK_WIDGET(combo_box), marker_prefs_get_use_highlight());
704   g_free(syntax);
705   g_list_free_full(list, free);
706   list = NULL;
707 
708   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "css_chooser"));
709   list = marker_prefs_get_available_stylesheets();
710   marker_widget_populate_combo_box_with_strings(combo_box, list);
711   char* css = marker_prefs_get_css_theme();
712   char* css_filename = marker_string_filename_get_name(css);
713   marker_widget_combo_box_set_active_str(combo_box, css_filename, g_list_length(list));
714   gtk_widget_set_sensitive(GTK_WIDGET(combo_box), marker_prefs_get_use_css_theme());
715   free(css_filename);
716   g_free(css);
717   g_list_free_full(list, free);
718   list = NULL;
719 
720   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "highlight_css_chooser"));
721   list = marker_prefs_get_available_highlight_themes();
722   marker_widget_populate_combo_box_with_strings(combo_box, list);
723   char* theme = marker_prefs_get_highlight_theme();
724   marker_widget_combo_box_set_active_str(combo_box, theme, g_list_length(list));
725   gtk_widget_set_sensitive(GTK_WIDGET(combo_box), marker_prefs_get_use_highlight());
726   g_free(theme);
727   g_list_free_full(list, free);
728   list = NULL;
729 
730   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "view_mode_chooser"));
731   GtkCellRenderer* cell_renderer = gtk_cell_renderer_text_new();
732   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), cell_renderer, TRUE);
733   gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box),
734                                  cell_renderer,
735                                  "text", 0,
736                                  NULL);
737   gtk_combo_box_set_active(combo_box, marker_prefs_get_default_view_mode());
738 
739   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "math_backends_combo"));
740   cell_renderer = gtk_cell_renderer_text_new();
741   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), cell_renderer, TRUE);
742   gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box),
743                                  cell_renderer,
744                                  "text", 0,
745                                  NULL);
746   gtk_combo_box_set_active(combo_box, marker_prefs_get_math_backend());
747   gtk_widget_set_sensitive(GTK_WIDGET(combo_box), marker_prefs_get_use_mathjs());
748 
749   combo_box = GTK_COMBO_BOX(gtk_builder_get_object(builder, "spell_lang_chooser"));
750   list = marker_prefs_get_available_languages();
751   marker_widget_populate_combo_box_with_strings(combo_box, list);
752   char* lang = marker_prefs_get_spell_check_language();
753   marker_widget_combo_box_set_active_str(combo_box, lang, g_list_length(list));
754   gtk_widget_set_sensitive(GTK_WIDGET(combo_box), marker_prefs_get_spell_check());
755   g_free(lang);
756   g_list_free_full(list, free);
757   list = NULL;
758 
759   check_button =
760     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "editor_syntax_check_button"));
761   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_highlight());
762 
763   check_button =
764     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "css_check_button"));
765   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_css_theme());
766 
767   check_button =
768     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "editor_syntax_check_button"));
769   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_syntax_theme());
770 
771   check_button =
772     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "mathjs_check_button"));
773   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_mathjs());
774 
775   check_button =
776     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "mermaid_check_button"));
777   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_mermaid());
778 
779   check_button =
780     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "charter_check_button"));
781   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_charter());
782 
783   check_button =
784     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "code_highlight_check_button"));
785   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_highlight());
786 
787   check_button =
788     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "show_line_numbers_check_button"));
789   gtk_toggle_button_set_active(check_button, marker_prefs_get_show_line_numbers());
790 
791   check_button =
792     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "show_right_margin_check_button"));
793   gtk_toggle_button_set_active(check_button, marker_prefs_get_show_right_margin());
794 
795   check_button =
796     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "wrap_text_check_button"));
797   gtk_toggle_button_set_active(check_button, marker_prefs_get_wrap_text());
798 
799   check_button =
800     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "show_spaces_check_button"));
801   gtk_toggle_button_set_active(check_button, marker_prefs_get_show_spaces());
802 
803   check_button =
804     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "highlight_current_line_check_button"));
805   gtk_toggle_button_set_active(check_button, marker_prefs_get_highlight_current_line());
806 
807   check_button =
808     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "auto_indent_check_button"));
809   gtk_toggle_button_set_active(check_button, marker_prefs_get_auto_indent());
810 
811   check_button =
812     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "replace_tabs_check_button"));
813   gtk_toggle_button_set_active(check_button, marker_prefs_get_replace_tabs());
814 
815   check_button =
816     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "spell_check_check_button"));
817   gtk_toggle_button_set_active(check_button, marker_prefs_get_spell_check());
818 
819   check_button =
820     GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "enable_dark_mode_check_button"));
821   gtk_toggle_button_set_active(check_button, marker_prefs_get_use_dark_theme());
822 
823   spin_button =
824     GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "right_margin_position_spin_button"));
825   gtk_widget_set_sensitive(GTK_WIDGET(spin_button), marker_prefs_get_show_right_margin());
826   gtk_spin_button_set_range(spin_button, 1, 1000);
827   gtk_spin_button_set_increments(spin_button, 1, 0);
828   gtk_spin_button_set_value(spin_button, marker_prefs_get_right_margin_position());
829 
830   spin_button =
831     GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "tab_width_spin_button"));
832   gtk_spin_button_set_range(spin_button, 1, 12);
833   gtk_spin_button_set_increments(spin_button, 1, 0);
834   gtk_spin_button_set_value(spin_button, marker_prefs_get_tab_width());
835 
836   GtkWindow* window = GTK_WINDOW(gtk_builder_get_object(builder, "prefs_win"));
837 	gtk_widget_show_all(GTK_WIDGET(window));
838   gtk_window_present(window);
839 
840 
841   gtk_builder_add_callback_symbol(builder,
842                                   "syntax_chosen",
843                                   G_CALLBACK(syntax_chosen));
844   gtk_builder_add_callback_symbol(builder,
845                                   "editor_syntax_toggled",
846                                   G_CALLBACK(editor_syntax_toggled));
847   gtk_builder_add_callback_symbol(builder,
848                                   "css_chosen",
849                                   G_CALLBACK(css_chosen));
850   gtk_builder_add_callback_symbol(builder,
851                                   "css_toggled",
852                                   G_CALLBACK(css_toggled));
853   gtk_builder_add_callback_symbol(builder,
854                                   "highlight_css_chosen",
855                                   G_CALLBACK(highlight_css_chosen));
856   gtk_builder_add_callback_symbol(builder,
857                                   "code_highlight_toggled",
858                                   G_CALLBACK(code_highlight_toggled));
859   gtk_builder_add_callback_symbol(builder,
860                                   "default_view_mode_chosen",
861                                   G_CALLBACK(default_view_mode_chosen));
862   gtk_builder_add_callback_symbol(builder,
863                                   "math_backends_combo_changed_cb",
864                                   G_CALLBACK(math_backend_changed));
865   gtk_builder_add_callback_symbol(builder,
866                                   "show_line_numbers_toggled",
867                                   G_CALLBACK(show_line_numbers_toggled));
868   gtk_builder_add_callback_symbol(builder,
869                                   "highlight_current_line_toggled",
870                                   G_CALLBACK(highlight_current_line_toggled));
871   gtk_builder_add_callback_symbol(builder,
872                                   "replace_tabs_toggled",
873                                   G_CALLBACK(replace_tabs_toggled));
874   gtk_builder_add_callback_symbol(builder,
875                                   "auto_indent_toggled",
876                                   G_CALLBACK(auto_indent_toggled));
877   gtk_builder_add_callback_symbol(builder,
878                                   "spell_check_toggled",
879                                   G_CALLBACK(spell_check_toggled));
880   gtk_builder_add_callback_symbol(builder,
881                                   "spell_lang_chosen",
882                                   G_CALLBACK(spell_lang_chosen));
883   gtk_builder_add_callback_symbol(builder,
884                                   "tab_width_value_changed",
885                                   G_CALLBACK(tab_width_value_changed));
886   gtk_builder_add_callback_symbol(builder,
887                                   "right_margin_position_value_changed",
888                                   G_CALLBACK(right_margin_position_value_changed));
889   gtk_builder_add_callback_symbol(builder,
890                                   "enable_mathjs_toggled",
891                                   G_CALLBACK(enable_mathjs_toggled));
892   gtk_builder_add_callback_symbol(builder,
893                                   "enable_mermaid_toggled",
894                                   G_CALLBACK(enable_mermaid_toggled));
895   gtk_builder_add_callback_symbol(builder,
896                                   "wrap_text_toggled",
897                                   G_CALLBACK(wrap_text_toggled));
898   gtk_builder_add_callback_symbol(builder,
899                                   "show_spaces_toggled",
900                                   G_CALLBACK(show_spaces_toggled));
901   gtk_builder_add_callback_symbol(builder,
902                                   "show_right_margin_toggled",
903                                   G_CALLBACK(show_right_margin_toggled));
904   gtk_builder_add_callback_symbol(builder,
905                                   "enable_dark_mode_toggled",
906                                   G_CALLBACK(enable_dark_mode_toggled));
907   gtk_builder_add_callback_symbol(builder,
908                                   "editor_syntax_toggled",
909                                   G_CALLBACK(editor_syntax_toggled));
910   gtk_builder_add_callback_symbol(builder,
911                                   "enable_charter_toggled",
912                                   G_CALLBACK(enable_charter_toggled));
913   gtk_builder_connect_signals(builder, NULL);
914 
915   g_object_unref(builder);
916 }
917 
918 void
marker_prefs_load()919 marker_prefs_load()
920 {
921   prefs.editor_settings =
922     g_settings_new("com.github.fabiocolacio.marker.preferences.editor");
923   prefs.preview_settings =
924     g_settings_new("com.github.fabiocolacio.marker.preferences.preview");
925   prefs.window_settings =
926     g_settings_new("com.github.fabiocolacio.marker.preferences.window");
927 }
928 
929