1 /*
2 * prefs.c
3 *
4 * Copyright 2012 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <errno.h>
25 #include <string.h>
26
27 #include "common.h"
28
29 gchar *pref_gdb_executable;
30 gboolean pref_gdb_async_mode;
31 #ifndef G_OS_UNIX
32 gboolean pref_async_break_bugs;
33 #endif
34 gboolean pref_var_update_bug;
35
36 gboolean pref_auto_view_source;
37 gboolean pref_keep_exec_point;
38 gint pref_visual_beep_length;
39 #ifdef G_OS_UNIX
40 gboolean pref_debug_console_vte;
41 #endif
42
43 gint pref_sci_marker_first;
44 static gint pref_sci_marker_1st;
45 gint pref_sci_caret_policy;
46 gint pref_sci_caret_slop;
47 gboolean pref_unmark_current_line;
48
49 gboolean pref_scope_goto_cursor;
50 gboolean pref_seek_with_navqueue;
51 gint pref_panel_tab_pos;
52 gint pref_show_recent_items;
53 gint pref_show_toolbar_items;
54
55 gint pref_tooltips_fail_action;
56 gint pref_tooltips_send_delay;
57 gint pref_tooltips_length;
58
59 gint pref_memory_bytes_per_line;
60 gchar *pref_memory_font;
61
62 #ifdef G_OS_UNIX
63 static gboolean pref_terminal_save_pos;
64 gboolean pref_terminal_padding;
65 gint pref_terminal_window_x;
66 gint pref_terminal_window_y;
67 gint pref_terminal_width;
68 gint pref_terminal_height;
69 #endif /* G_OS_UNIX */
70
71 gboolean pref_vte_blinken;
72 gchar *pref_vte_emulation;
73 gchar *pref_vte_font;
74 gint pref_vte_scrollback;
75
76 #if !GTK_CHECK_VERSION(3, 14, 0)
77 GdkColor pref_vte_colour_fore;
78 GdkColor pref_vte_colour_back;
79 #else
80 GdkRGBA pref_vte_colour_fore;
81 GdkRGBA pref_vte_colour_back;
82 #endif
83
84 typedef struct _MarkerStyle
85 {
86 const gchar *name;
87 gint mark;
88 gint fore;
89 gint back;
90 gint alpha;
91 gint default_mark;
92 const gchar *default_fore;
93 const gchar *default_back;
94 guint default_alpha;
95 } MarkerStyle;
96
97 #define MARKER_COUNT 3
98
99 static MarkerStyle pref_marker_styles[MARKER_COUNT] =
100 {
101 { "disabled_break", 0, 0, 0, 0, SC_MARK_CIRCLE, "#008000", "#C0E0D0", 256 },
102 { "enabled_break", 0, 0, 0, 0, SC_MARK_CIRCLE, "#000080", "#C0D0F0", 256 },
103 { "execution_line", 0, 0, 0, 0, SC_MARK_SHORTARROW, "#808000", "#F0F090", 256 }
104 };
105
prefs_apply(GeanyDocument * doc)106 void prefs_apply(GeanyDocument *doc)
107 {
108 gint i;
109 ScintillaObject *sci = doc->editor->sci;
110 MarkerStyle *style = pref_marker_styles;
111
112 for (i = pref_sci_marker_first; i < pref_sci_marker_first + MARKER_COUNT; i++, style++)
113 {
114 scintilla_send_message(sci, SCI_MARKERDEFINE, i, style->mark);
115 scintilla_send_message(sci, SCI_MARKERSETFORE, i, style->fore);
116 scintilla_send_message(sci, SCI_MARKERSETBACK, i, style->back);
117 scintilla_send_message(sci, SCI_MARKERSETALPHA, i, style->alpha);
118 }
119 }
120
121 static StashGroup *scope_group;
122 static StashGroup *terminal_group;
123 static StashGroup *marker_group[MARKER_COUNT];
124
load_scope_prefs(GKeyFile * config)125 static void load_scope_prefs(GKeyFile *config)
126 {
127 guint i;
128 MarkerStyle *style = pref_marker_styles;
129
130 stash_group_load_from_key_file(scope_group, config);
131 stash_group_load_from_key_file(terminal_group, config);
132
133 for (i = 0; i < MARKER_COUNT; i++, style++)
134 {
135 gchar *tmp_string;
136
137 stash_group_load_from_key_file(marker_group[i], config);
138 tmp_string = utils_get_setting_string(config, style->name, "fore",
139 style->default_fore);
140 style->fore = utils_parse_sci_color(tmp_string);
141 g_free(tmp_string);
142 tmp_string = utils_get_setting_string(config, style->name, "back",
143 style->default_back);
144 style->back = utils_parse_sci_color(tmp_string);
145 g_free(tmp_string);
146 }
147 }
148
149 static const char *obsolete_prefs[] = { "gdb_buffer_length", "gdb_wait_death",
150 "gdb_send_interval", NULL };
151
save_scope_prefs(GKeyFile * config)152 static void save_scope_prefs(GKeyFile *config)
153 {
154 guint i;
155 MarkerStyle *style = pref_marker_styles;
156
157 stash_group_save_to_key_file(scope_group, config);
158 stash_group_save_to_key_file(terminal_group, config);
159
160 for (i = 0; i < MARKER_COUNT; i++, style++)
161 {
162 gchar *tmp_string;
163
164 stash_group_save_to_key_file(marker_group[i], config);
165 tmp_string = g_strdup_printf("#%02X%02X%02X", style->fore & 0xFF,
166 (style->fore >> 8) & 0xFF, style->fore >> 16);
167 g_key_file_set_string(config, style->name, "fore", tmp_string);
168 g_free(tmp_string);
169 tmp_string = g_strdup_printf("#%02X%02X%02X", style->back & 0xFF,
170 (style->back >> 8) & 0xFF, style->back >> 16);
171 g_key_file_set_string(config, style->name, "back", tmp_string);
172 g_free(tmp_string);
173 }
174
175 for (i = 0; obsolete_prefs[i]; i++)
176 g_key_file_remove_key(config, "scope", obsolete_prefs[i], NULL);
177 }
178
prefs_configure(void)179 static void prefs_configure(void)
180 {
181 static const char *const view_source_items[] =
182 {
183 "thread_view_source",
184 "break_view_source",
185 "stack_separator1",
186 "stack_view_source",
187 NULL
188 };
189
190 const char *const *p;
191 guint i;
192
193 for (p = view_source_items; *p; p++)
194 gtk_widget_set_visible(get_widget(*p), !pref_auto_view_source);
195
196 foreach_document(i)
197 prefs_apply(documents[i]);
198
199 configure_panel();
200 }
201
prefs_file_name(void)202 char *prefs_file_name(void)
203 {
204 return g_build_filename(geany->app->configdir, "plugins", "scope", "scope.conf", NULL);
205 }
206
on_document_save(G_GNUC_UNUSED GObject * obj,GeanyDocument * doc,G_GNUC_UNUSED gpointer gdata)207 static void on_document_save(G_GNUC_UNUSED GObject *obj, GeanyDocument *doc,
208 G_GNUC_UNUSED gpointer gdata)
209 {
210 char *configfile = prefs_file_name();
211
212 if (doc->real_path && !utils_filenamecmp(doc->real_path, configfile))
213 {
214 GKeyFile *config = g_key_file_new();
215
216 g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL);
217 load_scope_prefs(config);
218 prefs_configure();
219 configure_toolbar();
220 g_key_file_free(config);
221 }
222 g_free(configfile);
223 }
224
225 static GtkWidget *config_item;
226
prefs_init(void)227 void prefs_init(void)
228 {
229 guint i;
230 MarkerStyle *style = pref_marker_styles;
231 StashGroup *group;
232 char *configdir = g_build_filename(geany->app->configdir, "plugins", "scope", NULL);
233 char *configfile = prefs_file_name();
234 GKeyFile *config = g_key_file_new();
235 gboolean obsolete = FALSE;
236
237 group = stash_group_new("scope");
238 stash_group_add_string(group, &pref_gdb_executable, "gdb_executable", "gdb");
239 stash_group_add_boolean(group, &pref_gdb_async_mode, "gdb_async_mode", FALSE);
240 #ifndef G_OS_UNIX
241 stash_group_add_boolean(group, &pref_async_break_bugs, "async_break_bugs", TRUE);
242 #endif
243 stash_group_add_boolean(group, &pref_var_update_bug, "var_update_bug", TRUE);
244 stash_group_add_boolean(group, &pref_auto_view_source, "auto_view_source", FALSE);
245 stash_group_add_boolean(group, &pref_keep_exec_point, "keep_exec_point", FALSE);
246 stash_group_add_integer(group, &pref_visual_beep_length, "visual_beep_length", 25);
247 #ifdef G_OS_UNIX
248 stash_group_add_boolean(group, &pref_debug_console_vte, "debug_console_vte", TRUE);
249 #endif
250 stash_group_add_integer(group, &pref_sci_marker_1st, "sci_marker_first", 17);
251 stash_group_add_integer(group, &pref_sci_caret_policy, "sci_caret_policy", CARET_SLOP |
252 CARET_JUMPS | CARET_EVEN);
253 stash_group_add_integer(group, &pref_sci_caret_slop, "sci_caret_slop", 3);
254 stash_group_add_boolean(group, &pref_unmark_current_line, "unmark_current_line", FALSE);
255 stash_group_add_boolean(group, &pref_scope_goto_cursor, "scope_run_to_cursor", FALSE);
256 stash_group_add_boolean(group, &pref_seek_with_navqueue, "seek_with_navqueue", FALSE);
257 stash_group_add_integer(group, &pref_panel_tab_pos, "panel_tab_pos", GTK_POS_TOP);
258 stash_group_add_integer(group, &pref_show_recent_items, "show_recent_items", 10);
259 stash_group_add_integer(group, &pref_show_toolbar_items, "show_toolbar_items", 0xFF);
260 stash_group_add_integer(group, &pref_tooltips_fail_action, "tooltips_fail_action", 0);
261 stash_group_add_integer(group, &pref_tooltips_send_delay, "tooltips_send_delay", 25);
262 stash_group_add_integer(group, &pref_tooltips_length, "tooltips_length", 2048);
263 stash_group_add_integer(group, &pref_memory_bytes_per_line, "memory_line_bytes", 16);
264 stash_group_add_string(group, &pref_memory_font, "memory_font", "");
265 scope_group = group;
266
267 config_item = ui_add_config_file_menu_item(configfile, NULL, NULL);
268 plugin_signal_connect(geany_plugin, NULL, "document-save", FALSE,
269 G_CALLBACK(on_document_save), NULL);
270
271 group = stash_group_new("terminal");
272 #ifdef G_OS_UNIX
273 stash_group_add_boolean(group, &pref_terminal_save_pos, "save_pos", TRUE);
274 stash_group_add_boolean(group, &pref_terminal_padding, "padding", TRUE);
275 stash_group_add_integer(group, &pref_terminal_window_x, "window_x", 70);
276 stash_group_add_integer(group, &pref_terminal_window_y, "window_y", 50);
277 stash_group_add_integer(group, &pref_terminal_width, "width", 640);
278 stash_group_add_integer(group, &pref_terminal_height, "height", 480);
279 #endif /* G_OS_UNIX */
280 terminal_group = group;
281
282 for (i = 0; i < MARKER_COUNT; i++, style++)
283 {
284 group = stash_group_new(style->name);
285 stash_group_add_integer(group, &style->mark, "mark", style->default_mark);
286 stash_group_add_integer(group, &style->alpha, "alpha", style->default_alpha);
287 marker_group[i] = group;
288 }
289
290 g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL);
291 load_scope_prefs(config);
292
293 for (i = 0; obsolete_prefs[i]; i++)
294 {
295 GError *gerror = NULL;
296
297 g_key_file_get_integer(config, "scope", obsolete_prefs[i], &gerror);
298
299 if (gerror)
300 {
301 g_error_free(gerror);
302 gerror = NULL;
303 }
304 else
305 {
306 obsolete = TRUE;
307 break;
308 }
309 }
310
311 pref_sci_marker_first = pref_sci_marker_1st;
312 prefs_configure();
313 program_load_config(config);
314
315 if (obsolete || !g_file_test(configfile, G_FILE_TEST_IS_REGULAR))
316 {
317 gint error = utils_mkdir(configdir, TRUE);
318
319 if (error)
320 msgwin_status_add(_("Scope: %s: %s."), configdir, g_strerror(error));
321 else
322 {
323 save_scope_prefs(config);
324 if (utils_key_file_write_to_file(config, configfile))
325 msgwin_status_add(_("Scope: created configuration file."));
326 }
327 }
328
329 g_key_file_free(config);
330 g_free(configfile);
331 g_free(configdir);
332 }
333
prefs_finalize(void)334 void prefs_finalize(void)
335 {
336 guint i;
337
338 #ifdef G_OS_UNIX
339 if (pref_terminal_save_pos)
340 {
341 char *configfile = prefs_file_name();
342 stash_group_save_to_file(terminal_group, configfile, G_KEY_FILE_KEEP_COMMENTS);
343 g_free(configfile);
344 }
345
346 g_free(pref_vte_font);
347 g_free(pref_vte_emulation);
348 #endif /* G_OS_UNIX */
349
350 gtk_widget_destroy(config_item);
351 utils_stash_group_free(scope_group);
352 utils_stash_group_free(terminal_group);
353 for (i = 0; i < MARKER_COUNT; i++)
354 utils_stash_group_free(marker_group[i]);
355 }
356