1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "gretl.h"
21 #include "version.h"
22 #include "filelists.h"
23 #include "gretl_www.h"
24 #include "dlgutils.h"
25 #include "fileselect.h"
26 #include "menustate.h"
27 #include "session.h"
28 #include "textbuf.h"
29 #include "ssheet.h"
30 #include "selector.h"
31 #include "gpt_control.h"
32 #include "tabwin.h"
33 #include "build.h"
34 #include "addons_utils.h"
35
36 #ifdef HAVE_GTKSV_COMPLETION
37 # include "completions.h"
38 #endif
39
40 #include "libset.h"
41 #include "texprint.h"
42 #include "uservar.h"
43 #include "gretl_foreign.h"
44
45 #include <unistd.h>
46 #include <sys/types.h>
47 #include <dirent.h>
48
49 #if GTK_MAJOR_VERSION == 3
50 # define HAVE_GTK_FONT_CHOOSER 1
51 #else
52 # define HAVE_GTK_FONT_CHOOSER 0
53 #endif
54
55 #ifdef G_OS_WIN32
56 # include <windows.h>
57 # include "gretlwin32.h"
58 #endif
59
60 #if HAVE_GTK_FONT_CHOOSER
61 # include "fontfilter.h"
62 #else
63 # include "gtkfontselhack.h"
64 #endif
65
66 #if defined(OS_OSX) && defined(HAVE_MAC_THEMES)
67 # define MAC_THEMING
68 #endif
69
70 static char rcfile[FILENAME_MAX];
71 static char http_proxy[128];
72 static int use_proxy;
73
74 static ConfigPaths paths;
75
76 static void make_prefs_tab (GtkWidget *notebook, int tab, int console);
77 static void apply_prefs_changes (GtkWidget *widget, GtkWidget *parent);
78
79 #ifndef G_OS_WIN32
80 static int read_gretlrc (void);
81 #endif
82
83 /* font handling */
84
85 static int tmpfontscale;
86 static char system_appfont[64];
87
88 #if defined(G_OS_WIN32)
89 static char fixedfontname[MAXLEN] = "Courier New 10";
90 static char default_fixedfont[64] = "Courier New 10";
91 #elif defined(OS_OSX)
92 static char fixedfontname[MAXLEN] = "Menlo 13";
93 static char default_fixedfont[64] = "Menlo 13";
94 #else
95 static char fixedfontname[MAXLEN] = "monospace 10";
96 static char default_fixedfont[64] = "monospace 10";
97 #endif
98
99 #if defined(G_OS_WIN32)
100 static char appfontname[MAXLEN] = "";
101 #elif defined(OS_OSX)
102 static char appfontname[MAXLEN] = "Lucida Grande 13";
103 #else
104 static char appfontname[MAXLEN] = "sans 10";
105 #endif
106
107 PangoFontDescription *fixed_font;
108
109 /* end font handling */
110
111 int swallow = 0;
112
113 static int usecwd;
114 static int shellok;
115 static int manpref;
116 static int robust_z;
117 static int autoicon = 1;
118 static int session_prompt = 1;
119 static int keep_folder = 1;
120 static int tabbed_editor = 1;
121 static int tabbed_models = 0;
122 static int auto_collect = 0;
123
124 static int script_output_policy;
125 static char datapage[24] = "Gretl";
126 static char scriptpage[24] = "Gretl";
127 static char author_mail[32];
128 static char sview_style[32] = "classic";
129 static char graph_theme[24] = "dark2";
130 static char gpcolors[18];
131
132 static int hc_by_default;
133 static char langpref[32];
134 static char hc_xsect[5] = "HC1";
135 static char hc_tseri[5] = "HAC";
136 static char hc_panel[9] = "Arellano";
137 static char hc_garch[5] = "QML";
138
139 #ifdef HAVE_MPI
140 # ifdef G_OS_WIN32
141 static char mpi_pref[8] = "MS-MPI";
142 # else
143 static char mpi_pref[8] = "OpenMPI";
144 # endif
145 #endif
146
147 static int lcnumeric = 1;
148 static double graph_scale = 1.0;
149 static int icon_sizing = ICON_SIZE_AUTO;
150
151 #if defined(MAC_THEMING)
152 static char themepref[12] = "Adwaita";
153 #elif defined(G_OS_WIN32)
154 static char themepref[12] = "Windows-10";
155 #endif
156
157 /* model table display variables */
158 static int modtab_colheads;
159 static gboolean modtab_tstats;
160 static gboolean modtab_pvalues;
161 static gboolean modtab_asterisks = TRUE;
162 static int modtab_digits = 4;
163 static gboolean modtab_decimals;
164
165 typedef enum {
166 USERSET = 1 << 0, /* user-level variable */
167 BOOLSET = 1 << 1, /* boolean value (user) */
168 INTSET = 1 << 2, /* integer value (user) */
169 FLOATSET = 1 << 3, /* floating point value (user) */
170 LISTSET = 1 << 4, /* user selection from fixed menu */
171 RADIOSET = 1 << 5, /* user int, from fixed menu */
172 INVISET = 1 << 6, /* not visible in preferences dialog */
173 FIXSET = 1 << 7, /* setting fixed by admin (Windows network use) */
174 MACHSET = 1 << 8, /* "local machine" setting */
175 BROWSER = 1 << 9, /* wants "Browse" button */
176 RESTART = 1 << 10, /* needs program restart to take effect */
177 GOTSET = 1 << 11, /* dynamic: already found a setting */
178 SKIPSET = 1 << 12, /* for string value, skip empty value */
179 SPINSET = 1 << 13 /* integer value: represented by spin-button */
180 } rcflags;
181
182 typedef struct {
183 char *key; /* config file variable name */
184 char *description; /* string shown in the preferences dialog */
185 char *link; /* in case of radio button pair, alternate string */
186 void *var; /* pointer to variable */
187 rcflags flags; /* see above */
188 int len; /* storage size for string variable (also see Note) */
189 short tab; /* which tab (if any) does the item fall under? */
190 GtkWidget *widget;
191 } RCVAR;
192
193 /* Note: actually "len" above is overloaded: if an rc_var is of
194 type BOOLSET and not part of a radio group, then a non-zero value
195 for len will link the var's toggle button with the sensitivity of
196 the preceding rc_var's entry field. For example, the "use_proxy"
197 button controls the sensitivity of the "http_proxy" entry widget.
198 */
199
200 RCVAR rc_vars[] = {
201 { "gretldir", N_("Main gretl directory"), NULL, paths.gretldir,
202 MACHSET | BROWSER, sizeof paths.gretldir, TAB_MAIN, NULL },
203 { "workdir", N_("User's gretl directory"), NULL, paths.workdir,
204 INVISET, sizeof paths.workdir, TAB_MAIN, NULL },
205 #ifndef G_OS_WIN32
206 { "winsize", N_("Remember main window size"), NULL, &winsize,
207 BOOLSET, 0, TAB_MAIN, NULL },
208 #endif
209 #ifdef ENABLE_NLS
210 { "lcnumeric", N_("Use locale setting for decimal point"), NULL, &lcnumeric,
211 BOOLSET | RESTART, 0, TAB_MAIN, NULL },
212 #endif
213 #if defined(MAC_THEMING) || defined(G_OS_WIN32)
214 { "themepref", N_("Theme preference"), NULL, themepref,
215 LISTSET | RESTART, 12, TAB_MAIN, NULL },
216 #endif
217 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
218 { "browser", N_("Web browser"), NULL, Browser,
219 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
220 #endif
221 { "shellok", N_("Allow shell commands"), NULL, &shellok,
222 BOOLSET, 0, TAB_MAIN, NULL },
223 { "autoicon", N_("Show icon view automatically"), NULL, &autoicon,
224 BOOLSET, 0, TAB_MAIN, NULL },
225 { "tabmodels", N_("Model viewer uses tabs"), NULL, &tabbed_models,
226 BOOLSET, 0, TAB_MAIN, NULL },
227 { "session_prompt", N_("Prompt to save session"), NULL, &session_prompt,
228 BOOLSET, 0, TAB_MAIN, NULL },
229 { "collect_plots", N_("Enable collecting plots"), NULL, &auto_collect,
230 BOOLSET, 0, TAB_MAIN, NULL },
231 { "swallow_console", N_("Main window includes console"), NULL, &swallow,
232 BOOLSET | RESTART, 0, TAB_MAIN, NULL },
233 { "icon_sizing", N_("Toolbar icon size"), NULL, &icon_sizing,
234 LISTSET | INTSET | RESTART, 0, TAB_MAIN, NULL },
235 { "usecwd", N_("Set working directory from shell"), NULL, &usecwd,
236 INVISET | BOOLSET | RESTART, 0, TAB_NONE, NULL },
237 { "keepfolder", N_("File selector remembers folder"), NULL, &keep_folder,
238 INVISET | BOOLSET, 0, TAB_NONE, NULL },
239 #ifdef ENABLE_NLS
240 { "langpref", N_("Language preference"), NULL, langpref,
241 LISTSET | RESTART, 32, TAB_MAIN, NULL },
242 #endif
243 { "graph_scale", N_("Default graph scale"), NULL, &graph_scale,
244 LISTSET | FLOATSET, 0, TAB_MAIN, NULL },
245 { "graph_theme", N_("Graph theme"), NULL, graph_theme,
246 LISTSET, sizeof graph_theme, TAB_MAIN, NULL },
247 #if !defined(G_OS_WIN32) || !defined(PKGBUILD)
248 { "gnuplot", N_("Command to launch gnuplot"), NULL, paths.gnuplot,
249 MACHSET | BROWSER, MAXLEN, TAB_PROGS, NULL },
250 #endif
251 { "Rcommand", N_("Command to launch GNU R"), NULL, Rcommand,
252 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
253 #ifdef G_OS_WIN32
254 { "Rbin", N_("Path to R.exe"), NULL, paths.rbinpath,
255 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
256 #endif
257 { "latex", N_("Command to compile TeX files"), NULL, latex,
258 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
259 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
260 { "viewps", N_("Command to view postscript files"), NULL, viewps,
261 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
262 { "viewpdf", N_("Command to view PDF files"), NULL, viewpdf,
263 MACHSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
264 #endif
265 { "calculator", N_("Calculator"), NULL, calculator,
266 USERSET | BROWSER, MAXSTR, TAB_PROGS, NULL },
267 #ifdef HAVE_X12A
268 { "x12a", N_("Path to x12arima (or x13)"), NULL, paths.x12a,
269 MACHSET | BROWSER, sizeof paths.x12a, TAB_PROGS, NULL },
270 #endif
271 #ifdef HAVE_TRAMO
272 { "tramo", N_("Path to tramo"), NULL, paths.tramo,
273 MACHSET | BROWSER, sizeof paths.tramo, TAB_PROGS, NULL},
274 #endif
275 #ifdef USE_RLIB
276 { "Rlib", N_("Path to R library"), NULL, paths.rlibpath,
277 MACHSET | BROWSER, sizeof paths.rlibpath, TAB_PROGS, NULL},
278 #endif
279 { "ox", N_("Path to oxl executable"), NULL, paths.oxlpath,
280 MACHSET | BROWSER, sizeof paths.oxlpath, TAB_PROGS, NULL},
281 { "octave", N_("Path to octave executable"), NULL, paths.octpath,
282 MACHSET | BROWSER, sizeof paths.octpath, TAB_PROGS, NULL},
283 { "stata", N_("Path to Stata executable"), NULL, paths.statapath,
284 MACHSET | BROWSER, sizeof paths.statapath, TAB_PROGS, NULL},
285 { "python", N_("Path to Python executable"), NULL, paths.pypath,
286 MACHSET | BROWSER, sizeof paths.pypath, TAB_PROGS, NULL},
287 { "julia", N_("Path to Julia executable"), NULL, paths.jlpath,
288 MACHSET | BROWSER, sizeof paths.jlpath, TAB_PROGS, NULL},
289 #ifndef PKGBUILD
290 { "lpsolve", N_("Path to lpsolve library"), NULL, paths.lppath,
291 MACHSET | BROWSER, sizeof paths.lppath, TAB_PROGS, NULL},
292 #endif
293 #ifdef HAVE_MPI
294 { "mpiexec", N_("Path to mpiexec"), NULL, paths.mpiexec,
295 MACHSET | BROWSER, sizeof paths.mpiexec, TAB_MPI, NULL},
296 { "mpi_hosts", N_("Path to MPI hosts file"), NULL, paths.mpi_hosts,
297 MACHSET | BROWSER, sizeof paths.mpi_hosts, TAB_MPI, NULL},
298 { "mpi_pref", N_("Installed MPI variant"), NULL, mpi_pref,
299 LISTSET, 8, TAB_MPI, NULL},
300 #endif
301 { "dbproxy", N_("HTTP proxy"), NULL, http_proxy,
302 USERSET, sizeof http_proxy, TAB_NET, NULL },
303 { "useproxy", N_("Use HTTP proxy"), NULL, &use_proxy,
304 BOOLSET, 1, TAB_NET, NULL },
305 { "Fixed_font", N_("Monospaced font"), NULL, fixedfontname,
306 USERSET, sizeof fixedfontname, TAB_NONE, NULL },
307 { "App_font", N_("Menu font"), NULL, appfontname,
308 USERSET, sizeof appfontname, TAB_NONE, NULL },
309 { "DataPage", "Default data page", NULL, datapage,
310 INVISET, sizeof datapage, TAB_NONE, NULL },
311 { "ScriptPage", "Default script page", NULL, scriptpage,
312 INVISET, sizeof scriptpage, TAB_NONE, NULL },
313 { "Png_font", N_("PNG graph font"), NULL, paths.pngfont,
314 INVISET, sizeof paths.pngfont, TAB_NONE, NULL },
315 { "Gp_extra_colors", N_("Gnuplot extra colors"), NULL, gpcolors,
316 INVISET, sizeof gpcolors, TAB_NONE, NULL },
317 { "tabwidth", N_("Number of spaces per tab"), NULL, &tabwidth,
318 INTSET | SPINSET, 0, TAB_EDITOR, NULL },
319 { "smarttab", N_("\"Smart\" Tab and Enter"), NULL, &smarttab,
320 BOOLSET, 0, TAB_EDITOR, NULL },
321 { "script_line_numbers", N_("Show line numbers"), NULL, &script_line_numbers,
322 BOOLSET, 0, TAB_EDITOR, NULL },
323 { "tabedit", N_("Script editor uses tabs"), NULL, &tabbed_editor,
324 BOOLSET, 0, TAB_EDITOR, NULL },
325 #ifdef HAVE_GTKSV_COMPLETION
326 { "hansl_completion", N_("Auto-completion"), NULL, &hansl_completion,
327 LISTSET | INTSET, 0, TAB_EDITOR, NULL },
328 { "console_completion", N_("Auto-completion"), NULL, &console_completion,
329 LISTSET | INTSET | INVISET, 0, TAB_EDITOR, NULL },
330 #endif
331 { "script_auto_bracket", N_("Enable auto-brackets"), NULL, &script_auto_bracket,
332 BOOLSET, 0, TAB_EDITOR, NULL },
333 { "sview_style", N_("Highlighting style"), NULL, &sview_style,
334 LISTSET, sizeof sview_style, TAB_EDITOR, NULL },
335 { "main_width", "main window width", NULL, &mainwin_width,
336 INVISET | INTSET, 0, TAB_NONE, NULL },
337 { "main_height", "main window height", NULL, &mainwin_height,
338 INVISET | INTSET, 0, TAB_NONE, NULL },
339 { "main_x", "main window x position", NULL, &main_x,
340 INVISET | INTSET, 0, TAB_NONE, NULL },
341 { "main_y", "main window y position", NULL, &main_y,
342 INVISET | INTSET, 0, TAB_NONE, NULL },
343 { "script_output_policy", "stickiness of output", NULL, &script_output_policy,
344 INVISET | INTSET, 0, TAB_NONE, NULL },
345 { "HC_by_default", N_("Use robust covariance matrix by default"), NULL,
346 &hc_by_default, BOOLSET, 0, TAB_VCV, NULL },
347 { "robust_z", N_("Use the normal distribution for robust p-values"), NULL,
348 &robust_z, BOOLSET, 0, TAB_VCV, NULL },
349 { "HC_xsect", N_("For cross-sectional data"), NULL, hc_xsect,
350 LISTSET, 5, TAB_VCV, NULL },
351 { "HC_tseri", N_("For time-series data"), NULL, hc_tseri,
352 LISTSET, 5, TAB_VCV, NULL },
353 { "HC_panel", N_("For panel data"), NULL, hc_panel,
354 LISTSET, 9, TAB_VCV, NULL },
355 { "HC_garch", N_("For GARCH estimation"), NULL, hc_garch,
356 LISTSET, 5, TAB_VCV, NULL },
357 { "manpref", N_("PDF manual preference"), NULL, &manpref,
358 LISTSET | INTSET, 0, TAB_MAIN, NULL },
359 { "modtab_colheads", "Model table column heads", NULL, &modtab_colheads,
360 INVISET | INTSET, 0, TAB_NONE, NULL },
361 { "modtab_tstats", "Model table t-ratios", NULL, &modtab_tstats,
362 INVISET | BOOLSET, 0, TAB_NONE, NULL },
363 { "modtab_pvalues", "Model table p-values", NULL, &modtab_pvalues,
364 INVISET | BOOLSET, 0, TAB_NONE, NULL },
365 { "modtab_asterisks", "Model table asterisks", NULL, &modtab_asterisks,
366 INVISET | BOOLSET, 0, TAB_NONE, NULL },
367 { "modtab_digits", "Model table digits", NULL, &modtab_digits,
368 INVISET | INTSET, 0, TAB_NONE, NULL },
369 { "modtab_decimals", "Model table decimal places", NULL, &modtab_decimals,
370 INVISET | INTSET, 0, TAB_NONE, NULL },
371 { "author_mail", "Package author email", NULL, &author_mail,
372 INVISET | SKIPSET, sizeof author_mail, TAB_NONE, NULL },
373 { NULL, NULL, NULL, NULL, 0, 0, TAB_NONE, NULL }
374 };
375
376 /* accessor functions */
377
using_hc_by_default(void)378 int using_hc_by_default (void)
379 {
380 return hc_by_default;
381 }
382
get_manpref(void)383 int get_manpref (void)
384 {
385 return manpref;
386 }
387
set_datapage(const char * str)388 void set_datapage (const char *str)
389 {
390 strcpy(datapage, str);
391 }
392
set_scriptpage(const char * str)393 void set_scriptpage (const char *str)
394 {
395 strcpy(scriptpage, str);
396 }
397
get_datapage(void)398 const char *get_datapage (void)
399 {
400 return datapage;
401 }
402
get_scriptpage(void)403 const char *get_scriptpage (void)
404 {
405 return scriptpage;
406 }
407
set_author_mail(const char * s)408 void set_author_mail (const char *s)
409 {
410 if (s != NULL && strlen(s) < sizeof author_mail) {
411 strcpy(author_mail, s);
412 } else {
413 author_mail[0] = '\0';
414 }
415 }
416
get_author_mail(void)417 const char *get_author_mail (void)
418 {
419 return author_mail;
420 }
421
get_sourceview_style(void)422 const char *get_sourceview_style (void)
423 {
424 return sview_style;
425 }
426
autoicon_on(void)427 int autoicon_on (void)
428 {
429 if (dataset != NULL && dataset->v > 0) {
430 return autoicon;
431 } else if (n_user_matrices() > 0) {
432 return autoicon;
433 } else if (n_user_bundles() > 0) {
434 return autoicon;
435 } else {
436 return 0;
437 }
438 }
439
get_icon_sizing(void)440 int get_icon_sizing (void)
441 {
442 return icon_sizing;
443 }
444
use_tabbed_editor(void)445 int use_tabbed_editor (void)
446 {
447 return tabbed_editor;
448 }
449
use_tabbed_model_viewer(void)450 int use_tabbed_model_viewer (void)
451 {
452 return tabbed_models;
453 }
454
session_prompt_on(void)455 int session_prompt_on (void)
456 {
457 return session_prompt;
458 }
459
set_session_prompt(int val)460 void set_session_prompt (int val)
461 {
462 session_prompt = val;
463 }
464
get_keep_folder(void)465 int get_keep_folder (void)
466 {
467 return keep_folder;
468 }
469
set_script_output_policy(int p,windata_t * vwin)470 void set_script_output_policy (int p, windata_t *vwin)
471 {
472 script_output_policy = p;
473
474 if (script_output_policy < 0 ||
475 script_output_policy > OUTPUT_POLICY_NEW_WINDOW) {
476 /* invalid setting */
477 script_output_policy = OUTPUT_POLICY_REPLACE;
478 }
479
480 set_reuseable_output_window(p, vwin);
481 }
482
get_script_output_policy(void)483 int get_script_output_policy (void)
484 {
485 return script_output_policy;
486 }
487
get_model_table_prefs(int * colheads,int * use_tstats,int * do_pvals,int * do_asts,int * figs,char * fmt)488 void get_model_table_prefs (int *colheads,
489 int *use_tstats,
490 int *do_pvals,
491 int *do_asts,
492 int *figs,
493 char *fmt)
494 {
495 *colheads = modtab_colheads;
496 *use_tstats = modtab_tstats;
497 *do_pvals = modtab_pvalues;
498 *do_asts = modtab_asterisks;
499 *figs = modtab_digits;
500 *fmt = modtab_decimals ? 'f' : 'g';
501 }
502
set_model_table_prefs(int colheads,int use_tstats,int do_pvals,int do_asts,int figs,char fmt)503 void set_model_table_prefs (int colheads,
504 int use_tstats,
505 int do_pvals,
506 int do_asts,
507 int figs,
508 char fmt)
509 {
510 modtab_colheads = colheads;
511 modtab_tstats = use_tstats;
512 modtab_pvalues = do_pvals;
513 modtab_asterisks = do_asts;
514 modtab_digits = figs;
515 modtab_decimals = (fmt == 'f')? 1 : 0;
516 }
517
518 static gretlopt update_paths_opt = OPT_NONE;
519
force_english_help(void)520 void force_english_help (void)
521 {
522 update_paths_opt |= OPT_N;
523 gretl_update_paths(&paths, update_paths_opt);
524 }
525
fontname_get_size(const char * fontname)526 static int fontname_get_size (const char *fontname)
527 {
528 char *p = strrchr(fontname, ' ');
529
530 return (p != NULL)? atoi(p+1) : 10;
531 }
532
fontname_set_size(char * fontname,int size)533 static void fontname_set_size (char *fontname, int size)
534 {
535 char *p = strrchr(fontname, ' ');
536
537 if (p != NULL) {
538 sprintf(p, " %d", size);
539 }
540 }
541
font_is_changed(const char * f_new,const char * f_old)542 static int font_is_changed (const char *f_new,
543 const char *f_old)
544 {
545 if (strcmp(f_new, f_old)) {
546 return 1;
547 } else if (tmpfontscale > 0 &&
548 fontname_get_size(f_new) != tmpfontscale) {
549 return 1;
550 } else {
551 return 0;
552 }
553 }
554
set_fixed_font(const char * fontname,int remember)555 void set_fixed_font (const char *fontname, int remember)
556 {
557 if (fontname == NULL) {
558 /* initial set-up */
559 fixed_font = pango_font_description_from_string(fixedfontname);
560 } else if (font_is_changed(fontname, fixedfontname)) {
561 /* changed via the GUI */
562 if (fixed_font != NULL) {
563 pango_font_description_free(fixed_font);
564 }
565 fixed_font = pango_font_description_from_string(fontname);
566 if (remember) {
567 strcpy(fixedfontname, fontname);
568 }
569 infobox(_("This change will apply to newly opened windows"));
570 }
571 }
572
update_persistent_graph_font(void)573 void update_persistent_graph_font (void)
574 {
575 strcpy(paths.pngfont, gretl_png_font());
576 }
577
get_app_fontname(void)578 const char *get_app_fontname (void)
579 {
580 return appfontname;
581 }
582
get_fixed_fontname(void)583 const char *get_fixed_fontname (void)
584 {
585 return fixedfontname;
586 }
587
record_system_appfont(GtkSettings * settings,gchar ** pfont)588 static void record_system_appfont (GtkSettings *settings,
589 gchar **pfont)
590 {
591 g_object_get(G_OBJECT(settings), "gtk-font-name", pfont, NULL);
592 #if defined(G_OS_WIN32)
593 get_default_windows_app_font(system_appfont);
594 #else
595 if (*pfont != NULL) {
596 strcpy(system_appfont, *pfont);
597 } else {
598 # if defined(OS_OSX)
599 strcpy(system_appfont, "Lucida Grande 13");
600 # else
601 strcpy(system_appfont, "sans 10");
602 # endif
603 }
604 #endif
605 }
606
607 #ifdef G_OS_WIN32
608
win32_set_font(const char * fontname,GtkSettings * settings)609 static void win32_set_font (const char *fontname,
610 GtkSettings *settings)
611 {
612 gchar *rc;
613
614 rc = g_strdup_printf("style \"myfont\" {\n"
615 " font_name = \"%s\"\n}\n"
616 "widget_class \"*\" style \"myfont\"\n"
617 "gtk-font-name = \"%s\"\n",
618 fontname, fontname);
619 gtk_rc_parse_string(rc);
620 g_object_set(G_OBJECT(settings), "gtk-font-name", fontname, NULL);
621 g_free(rc);
622 }
623
624 #endif
625
set_app_font(const char * fontname,int remember)626 void set_app_font (const char *fontname, int remember)
627 {
628 static int default_recorded;
629 GtkSettings *settings;
630 gchar *deffont = NULL;
631
632 #if 0
633 fprintf(stderr, "set_app_font: fontname='%s', remember=%d, "
634 "appfontname='%s'\n", fontname, remember, appfontname);
635 #endif
636
637 if (fontname != NULL && *fontname == '\0') {
638 return;
639 }
640
641 settings = gtk_settings_get_default();
642
643 /* not font-related but, dammit, we want these! */
644 g_object_set(G_OBJECT(settings), "gtk-menu-images", TRUE, NULL);
645
646 if (!default_recorded) {
647 record_system_appfont(settings, &deffont);
648 #if 0
649 fprintf(stderr, "record app font default: system '%s', gtk '%s'\n",
650 system_appfont, deffont);
651 #endif
652 default_recorded = 1;
653 }
654
655 #ifdef G_OS_WIN32
656 if (fontname == NULL && *appfontname == '\0') {
657 /* as we're called at initial startup from gretl.c */
658 strcpy(appfontname, system_appfont);
659 }
660 #endif
661
662 /* check for nothing else to be done */
663 if (deffont != NULL) {
664 const char *test = fontname ? fontname : appfontname;
665 int noop = 0;
666
667 if (!font_is_changed(test, deffont)) {
668 noop = 1;
669 }
670 g_free(deffont);
671 if (noop) {
672 return;
673 }
674 }
675
676 if (fontname == NULL) {
677 /* just loading @appfontname (pre-checked) */
678 #ifdef G_OS_WIN32
679 win32_set_font(appfontname, settings);
680 #else
681 g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
682 #endif
683 } else {
684 /* loading a user-specified font: check that it works */
685 GtkWidget *w;
686 PangoFontDescription *pfd;
687 PangoContext *pc;
688 PangoFont *font;
689
690 w = gtk_label_new("text");
691 pfd = pango_font_description_from_string(fontname);
692 pc = gtk_widget_get_pango_context(w);
693 font = pango_context_load_font(pc, pfd);
694
695 if (font != NULL) {
696 /* OK, found it */
697 if (remember) {
698 strcpy(appfontname, fontname);
699 }
700 #ifdef G_OS_WIN32
701 win32_set_font(fontname, settings);
702 #else
703 g_object_set(G_OBJECT(settings), "gtk-font-name", fontname, NULL);
704 #endif
705 g_object_unref(font);
706 }
707
708 gtk_widget_destroy(w);
709 pango_font_description_free(pfd);
710 }
711 }
712
write_OK(gchar * dirname)713 static int write_OK (gchar *dirname)
714 {
715 int ok = 0;
716
717 if (gretl_mkdir(dirname) == 0) {
718 gchar *test = g_strdup_printf("%s%c%s", dirname, SLASH, "wtest");
719
720 if (test != NULL) {
721 ok = (gretl_test_fopen(test, "w") == 0);
722 g_free(test);
723 }
724 }
725
726 return ok;
727 }
728
set_gretl_startdir(void)729 void set_gretl_startdir (void)
730 {
731 if (usecwd) {
732 char *test = getenv("GRETL_STARTDIR");
733 gchar *startdir = NULL;
734
735 /* the environment variable check is mostly for the macOS
736 package */
737
738 if (test != NULL) {
739 startdir = g_strdup(test);
740 } else {
741 startdir = g_get_current_dir();
742 }
743
744 if (startdir != NULL) {
745 int err = gretl_set_path_by_name("workdir", startdir);
746
747 if (err) {
748 fprintf(stderr, "%s\n", gretl_errmsg_get());
749 } else {
750 fprintf(stderr, "working dir = '%s'\n", startdir);
751 }
752 g_free(startdir);
753 }
754 }
755 }
756
get_pkg_save_dir(char * dirname,int action)757 static void get_pkg_save_dir (char *dirname, int action)
758 {
759
760 const char *subdir = NULL;
761 int try_sysdir = 1;
762 int ok = 0;
763
764 if (action == SAVE_FUNCTIONS) {
765 subdir = "functions";
766 } else if (action == SAVE_DATA_PKG) {
767 subdir = "data";
768 } else if (action == SAVE_REMOTE_DB) {
769 subdir = "db";
770 } else {
771 return;
772 }
773
774 #ifdef G_OS_WIN32
775 try_sysdir = 0;
776 #endif
777
778 if (try_sysdir) {
779 /* try 'system' location first */
780 sprintf(dirname, "%s%s", gretl_home(), subdir);
781 ok = write_OK(dirname);
782 }
783
784 if (!ok) {
785 /* go to user's dotdir */
786 sprintf(dirname, "%s%s", gretl_dotdir(), subdir);
787 ok = write_OK(dirname);
788 }
789
790 if (!ok) {
791 *dirname = '\0';
792 }
793 }
794
get_default_dir_for_action(char * s,int action)795 void get_default_dir_for_action (char *s, int action)
796 {
797 *s = '\0';
798
799 if (action == SAVE_FUNCTIONS ||
800 action == SAVE_DATA_PKG ||
801 action == SAVE_REMOTE_DB) {
802 get_pkg_save_dir(s, action);
803 } else {
804 strcpy(s, gretl_workdir());
805 }
806
807 slash_terminate(s);
808 }
809
810 #ifdef G_OS_WIN32
get_reg_base(const char * key)811 static const char *get_reg_base (const char *key)
812 {
813 if (!strncmp(key, "x12a", 4)) {
814 return "x12arima";
815 } else if (!strncmp(key, "tramo", 5)) {
816 return "tramo";
817 } else {
818 return "gretl";
819 }
820 }
821 #endif
822
823 #ifdef OS_OSX
824
alt_ok(const char * prog)825 static int alt_ok (const char *prog)
826 {
827 char *p, test[MAXSTR];
828 int tr = strstr(prog, "tramo") != NULL;
829 int ok;
830
831 strcpy(test, gretl_home());
832 p = strstr(test, "share/gretl");
833 if (p != NULL) {
834 *p = 0;
835 }
836
837 if (tr) {
838 strcat(test, "tramo/tramo");
839 } else {
840 strcat(test, "x12arima/x12a");
841 }
842
843 ok = check_for_program(test);
844
845 if (ok) {
846 if (tr) {
847 strcpy(paths.tramo, test);
848 } else {
849 strcpy(paths.x12a, test);
850 }
851 }
852
853 return ok;
854 }
855
856 #endif
857
858 #ifdef HAVE_TRAMO
859
860 #define tramo_ts(d) ((d)->structure == TIME_SERIES && \
861 (d->pd == 1 || d->pd == 4 || d->pd == 12))
862
863 static int tramo_ok = 0;
864
get_tramo_ok(void)865 int get_tramo_ok (void)
866 {
867 return tramo_ok && tramo_ts(dataset);
868 }
869
set_tramo_status(void)870 static void set_tramo_status (void)
871 {
872 const char *tramodir = gretl_tramo_dir();
873 int gui_up = (mdata != NULL);
874 int ok = 0;
875
876 if (*tramodir != '\0') {
877 const char *tramo = gretl_tramo();
878
879 ok = check_for_program(tramo);
880 # ifdef OS_OSX
881 if (!ok) {
882 ok = alt_ok(tramo);
883 }
884 # endif
885 }
886
887 if (tramo_ok && !ok && gui_up) {
888 warnbox_printf("Invalid path for %s", "TRAMO");
889 }
890
891 tramo_ok = ok;
892
893 if (gui_up) {
894 flip(mdata->ui, "/menubar/Variable/Tramo", get_tramo_ok());
895 }
896 }
897
898 #endif /* HAVE_TRAMO */
899
900 #ifdef HAVE_X12A
901
902 #define x12_ts(d) ((d)->structure == TIME_SERIES && \
903 (d->pd == 4 || d->pd == 12))
904
905 static int x12a_ok = 0;
906
get_x12a_ok(void)907 int get_x12a_ok (void)
908 {
909 return x12a_ok && x12_ts(dataset);
910 }
911
set_x12a_status(void)912 static void set_x12a_status (void)
913 {
914 const char *x12adir = gretl_x12_arima_dir();
915 int gui_up = (mdata != NULL);
916 int ok = 0;
917
918 if (*x12adir != '\0') {
919 const char *x12a = gretl_x12_arima();
920
921 ok = check_for_program(x12a);
922 # ifdef OS_OSX
923 if (!ok) {
924 ok = alt_ok(x12a);
925 }
926 # endif
927 }
928
929 if (x12a_ok && !ok && gui_up) {
930 warnbox_printf("Invalid path for %s", "X-12-ARIMA");
931 }
932
933 x12a_ok = ok;
934
935 if (gui_up) {
936 flip(mdata->ui, "/menubar/Variable/X12A",
937 get_x12a_ok());
938 }
939 }
940
941 #endif /* HAVE_X12A */
942
943 #ifndef G_OS_WIN32
944
root_check(void)945 static void root_check (void)
946 {
947 if (getuid() == 0) {
948 int resp;
949
950 resp = yes_no_dialog("gretl", _("You seem to be running gretl "
951 "as root. Do you really want to do this?"),
952 NULL);
953 if (resp == GRETL_NO) {
954 exit(EXIT_FAILURE);
955 }
956 }
957 }
958
gretl_config_init(void)959 int gretl_config_init (void)
960 {
961 int err = 0;
962
963 get_gretl_rc_path(rcfile);
964 err = read_gretlrc();
965 set_gretl_startdir();
966 root_check();
967
968 return err;
969 }
970
971 #endif /* !G_OS_WIN32 */
972
highlight_preferences_entry(const char * vname)973 static void highlight_preferences_entry (const char *vname)
974 {
975 GtkWidget *w;
976 int i;
977
978 for (i=0; rc_vars[i].key != NULL; i++) {
979 if (!strcmp(vname, rc_vars[i].key)) {
980 w = rc_vars[i].widget;
981 if (w != NULL && GTK_IS_ENTRY(w)) {
982 gtk_editable_select_region(GTK_EDITABLE(w), 0, -1);
983 gtk_widget_grab_focus(w);
984 }
985 break;
986 }
987 }
988 }
989
preferences_dialog_canceled(GtkWidget * w,int * c)990 static void preferences_dialog_canceled (GtkWidget *w, int *c)
991 {
992 *c = 1;
993 }
994
page_has_help(int p)995 static int page_has_help (int p)
996 {
997 return p == TAB_EDITOR || p == TAB_VCV;
998 }
999
sensitize_prefs_help(GtkNotebook * book,gpointer arg1,guint newpg,GtkWidget * button)1000 static void sensitize_prefs_help (GtkNotebook *book,
1001 gpointer arg1,
1002 guint newpg,
1003 GtkWidget *button)
1004 {
1005 gtk_widget_set_sensitive(button, page_has_help(newpg + 1));
1006 }
1007
show_prefs_help(GtkWidget * w,GtkWidget * notebook)1008 static void show_prefs_help (GtkWidget *w, GtkWidget *notebook)
1009 {
1010 gint page;
1011
1012 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
1013
1014 if (page + 1 == TAB_EDITOR) {
1015 show_gui_help(EDITOR);
1016 } else if (page + 1 == TAB_VCV) {
1017 show_gui_help(HCCME);
1018 }
1019 }
1020
1021 /* To record state of preferences dialogs, and avoid opening
1022 both the 'global' one and the one specific to the console
1023 simultaneously, which would lead to bad effects.
1024 */
1025 static GtkWidget *all_prefs;
1026 static GtkWidget *console_prefs;
1027
preferences_dialog_destroyed(GtkWidget * w,GtkWidget ** pw)1028 static void preferences_dialog_destroyed (GtkWidget *w,
1029 GtkWidget **pw)
1030 {
1031 int i;
1032
1033 for (i=0; rc_vars[i].key != NULL; i++) {
1034 rc_vars[i].widget = NULL;
1035 }
1036 if (pw != NULL) {
1037 *pw = NULL;
1038 }
1039 }
1040
preferences_dialog(int page,const char * varname,GtkWidget * parent)1041 int preferences_dialog (int page, const char *varname, GtkWidget *parent)
1042 {
1043 GtkWidget *dialog = all_prefs;
1044 GtkWidget *notebook;
1045 GtkWidget *button;
1046 GtkWidget *hbox;
1047 GtkWidget *vbox;
1048 int canceled = 0;
1049
1050 if (dialog != NULL) {
1051 gtk_window_present(GTK_WINDOW(dialog));
1052 return 0;
1053 } else if (console_prefs != NULL) {
1054 gtk_widget_destroy(console_prefs);
1055 }
1056
1057 dialog = gretl_dialog_new(_("gretl: preferences"), parent,
1058 GRETL_DLG_RESIZE | GRETL_DLG_BLOCK);
1059 all_prefs = dialog;
1060 #if GTK_MAJOR_VERSION < 3
1061 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
1062 #endif
1063 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1064 gtk_box_set_spacing(GTK_BOX(vbox), 2);
1065
1066 g_signal_connect(G_OBJECT(dialog), "destroy",
1067 G_CALLBACK(preferences_dialog_destroyed),
1068 &all_prefs);
1069
1070 notebook = gtk_notebook_new();
1071 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
1072
1073 make_prefs_tab(notebook, TAB_MAIN, 0);
1074 make_prefs_tab(notebook, TAB_PROGS, 0);
1075 make_prefs_tab(notebook, TAB_EDITOR, 0);
1076 make_prefs_tab(notebook, TAB_NET, 0);
1077 make_prefs_tab(notebook, TAB_VCV, 0);
1078 #ifdef HAVE_MPI
1079 make_prefs_tab(notebook, TAB_MPI, 0);
1080 #endif
1081
1082 hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
1083
1084 /* Apply button */
1085 button = apply_button(hbox);
1086 g_signal_connect(G_OBJECT(button), "clicked",
1087 G_CALLBACK(apply_prefs_changes), parent);
1088 gtk_widget_grab_default(button);
1089
1090 /* Cancel button */
1091 button = cancel_button(hbox);
1092 g_signal_connect(G_OBJECT(button), "clicked",
1093 G_CALLBACK(preferences_dialog_canceled),
1094 &canceled);
1095 g_signal_connect(G_OBJECT(button), "clicked",
1096 G_CALLBACK(delete_widget),
1097 dialog);
1098
1099 /* OK button */
1100 button = ok_button(hbox);
1101 g_signal_connect(G_OBJECT(button), "clicked",
1102 G_CALLBACK(apply_prefs_changes), parent);
1103 g_signal_connect(G_OBJECT(button), "clicked",
1104 G_CALLBACK(delete_widget),
1105 dialog);
1106
1107 /* Help button */
1108 button = context_help_button(hbox, -1);
1109 g_signal_connect(G_OBJECT(button), "clicked",
1110 G_CALLBACK(show_prefs_help),
1111 notebook);
1112 gtk_widget_set_sensitive(button, page_has_help(page));
1113 g_signal_connect(G_OBJECT(notebook), "switch-page",
1114 G_CALLBACK(sensitize_prefs_help),
1115 button);
1116
1117 if (page > 1 && page < TAB_MAX) {
1118 page--;
1119 /* "show" the target page first (see GtkNoteBook API doc) */
1120 gtk_widget_show(gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page));
1121 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page);
1122 }
1123
1124 if (varname != NULL) {
1125 highlight_preferences_entry(varname);
1126 }
1127
1128 gtk_widget_show_all(dialog);
1129
1130 return canceled;
1131 }
1132
refocus_console(GtkWidget * widget,GtkWidget * caller)1133 static void refocus_console (GtkWidget *widget, GtkWidget *caller)
1134 {
1135 gtk_widget_grab_focus(caller);
1136 }
1137
console_prefs_dialog(GtkWidget * caller)1138 int console_prefs_dialog (GtkWidget *caller)
1139 {
1140 GtkWidget *dialog = console_prefs;
1141 GtkWidget *parent;
1142 GtkWidget *button;
1143 GtkWidget *hbox;
1144 GtkWidget *vbox;
1145 int canceled = 0;
1146
1147 if (dialog != NULL) {
1148 gtk_window_present(GTK_WINDOW(dialog));
1149 } else if (all_prefs != NULL) {
1150 gtk_widget_destroy(all_prefs);
1151 }
1152
1153 parent = swallow ? mdata->main : caller;
1154 dialog = gretl_dialog_new(_("gretl: preferences"), parent,
1155 GRETL_DLG_RESIZE | GRETL_DLG_BLOCK);
1156 console_prefs = dialog;
1157 #if GTK_MAJOR_VERSION < 3
1158 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
1159 #endif
1160 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1161 gtk_box_set_spacing(GTK_BOX(vbox), 2);
1162
1163 if (swallow) {
1164 g_signal_connect(G_OBJECT(dialog), "destroy",
1165 G_CALLBACK(refocus_console),
1166 caller);
1167 }
1168 g_signal_connect(G_OBJECT(dialog), "destroy",
1169 G_CALLBACK(preferences_dialog_destroyed),
1170 &console_prefs);
1171
1172 make_prefs_tab(vbox, TAB_EDITOR, 1);
1173
1174 hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
1175
1176 /* Cancel button */
1177 button = cancel_button(hbox);
1178 g_signal_connect(G_OBJECT(button), "clicked",
1179 G_CALLBACK(preferences_dialog_canceled),
1180 &canceled);
1181 g_signal_connect(G_OBJECT(button), "clicked",
1182 G_CALLBACK(delete_widget),
1183 dialog);
1184
1185 /* OK button */
1186 button = ok_button(hbox);
1187 g_signal_connect(G_OBJECT(button), "clicked",
1188 G_CALLBACK(apply_prefs_changes), caller);
1189 g_signal_connect(G_OBJECT(button), "clicked",
1190 G_CALLBACK(delete_widget),
1191 dialog);
1192
1193 gtk_widget_show_all(dialog);
1194
1195 return canceled;
1196 }
1197
flip_sensitive(GtkWidget * w,gpointer data)1198 static void flip_sensitive (GtkWidget *w, gpointer data)
1199 {
1200 GtkWidget *entry = GTK_WIDGET(data);
1201
1202 gtk_widget_set_sensitive(entry, button_is_active(w));
1203 }
1204
set_path_callback(char * setvar,char * setting)1205 void set_path_callback (char *setvar, char *setting)
1206 {
1207 int i = 0;
1208
1209 while (rc_vars[i].key != NULL) {
1210 if (rc_vars[i].var == (void *) setvar) {
1211 /* FIXME: utf-8 issues here? */
1212 if (rc_vars[i].widget != NULL) {
1213 gtk_entry_set_text(GTK_ENTRY(rc_vars[i].widget),
1214 setting);
1215 }
1216 break;
1217 }
1218 i++;
1219 }
1220 }
1221
browse_button_callback(GtkWidget * w,RCVAR * rc)1222 static void browse_button_callback (GtkWidget *w, RCVAR *rc)
1223 {
1224 GtkWidget *parent = g_object_get_data(G_OBJECT(w), "parent");
1225 int code = SET_PROG;
1226
1227 #ifdef HAVE_MPI
1228 if (!strcmp(rc->key, "mpi_hosts")) {
1229 file_selector_with_parent(SET_OTHER, FSEL_DATA_MISC, rc->var, parent);
1230 return;
1231 }
1232 #endif
1233
1234 if (strstr(rc->description, "directory") != NULL) {
1235 code = SET_DIR;
1236 }
1237
1238 file_selector_with_parent(code, FSEL_DATA_MISC, rc->var, parent);
1239 }
1240
make_path_browse_button(RCVAR * rc,GtkWidget * w)1241 static GtkWidget *make_path_browse_button (RCVAR *rc, GtkWidget *w)
1242 {
1243 GtkWidget *top = gtk_widget_get_toplevel(w);
1244 GtkWidget *b;
1245
1246 b = gtk_button_new_with_label(_("Browse..."));
1247 g_object_set_data(G_OBJECT(b), "parent", top);
1248 g_signal_connect(G_OBJECT(b), "clicked",
1249 G_CALLBACK(browse_button_callback),
1250 rc);
1251 return b;
1252 }
1253
try_switch_locale(GtkComboBox * box,gpointer p)1254 static gboolean try_switch_locale (GtkComboBox *box, gpointer p)
1255 {
1256 static int lasterr;
1257 gchar *langstr;
1258 int err;
1259
1260 if (lasterr) {
1261 lasterr = 0;
1262 return FALSE;
1263 }
1264
1265 langstr = combo_box_get_active_text(box);
1266 err = test_locale(langstr);
1267 g_free(langstr);
1268
1269 if (err) {
1270 lasterr = err;
1271 gui_errmsg(err);
1272 gretl_error_clear();
1273 gtk_combo_box_set_active(box, 0);
1274 }
1275
1276 return FALSE;
1277 }
1278
try_switch_style(GtkComboBox * box,GtkWidget * text)1279 static gboolean try_switch_style (GtkComboBox *box, GtkWidget *text)
1280 {
1281 gchar *style = combo_box_get_active_text(box);
1282
1283 set_style_for_textview(text, style);
1284 g_free(style);
1285
1286 return FALSE;
1287 }
1288
embed_style_sampler(GtkWidget * vbox)1289 static GtkWidget *embed_style_sampler (GtkWidget *vbox)
1290 {
1291 GtkWidget *hbox, *text;
1292
1293 hbox = gtk_hbox_new(TRUE, 5);
1294 text = create_sample_source(sview_style);
1295 gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, FALSE, 0);
1296 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 15);
1297
1298 return text;
1299 }
1300
1301 static const char *hc_strs[] = {
1302 "HC0", "HC1", "HC2", "HC3", "HC3a", "HAC"
1303 };
1304
get_list_setting_strings(void * var,int * n)1305 static const char **get_list_setting_strings (void *var, int *n)
1306 {
1307 static const char *hc_panel_strs[] = {
1308 "Arellano", "PCSE"
1309 };
1310 static const char *garch_strs[] = {
1311 "QML", "BW"
1312 };
1313 static const char *manpref_strs[] = {
1314 N_("English (US letter paper)"),
1315 N_("English (A4 paper)"),
1316 N_("Translation, if available")
1317 };
1318 #ifdef HAVE_GTKSV_COMPLETION
1319 static const char *completion_strs[] = {
1320 N_("none"),
1321 N_("automatic, as you type"),
1322 N_("on demand, via Tab")
1323 };
1324 #endif
1325 static const char *icon_sizing_strs[] = {
1326 N_("Automatic"),
1327 N_("small"),
1328 N_("medium")
1329 };
1330 const char **strs = NULL;
1331
1332 *n = 0;
1333
1334 if (var == hc_xsect || var == hc_tseri) {
1335 strs = hc_strs;
1336 *n = sizeof hc_strs / sizeof hc_strs[0];
1337 if (var == hc_xsect) *n -= 1;
1338 } else if (var == hc_panel) {
1339 strs = hc_panel_strs;
1340 *n = sizeof hc_panel_strs / sizeof hc_panel_strs[0];
1341 } else if (var == hc_garch) {
1342 strs = garch_strs;
1343 *n = sizeof garch_strs / sizeof garch_strs[0];
1344 } else if (var == &manpref) {
1345 strs = manpref_strs;
1346 *n = sizeof manpref_strs / sizeof manpref_strs[0];
1347 #ifdef HAVE_GTKSV_COMPLETION
1348 } else if (var == &hansl_completion || var == &console_completion) {
1349 strs = completion_strs;
1350 *n = sizeof completion_strs / sizeof completion_strs[0];
1351 #endif
1352 } else if (var == &icon_sizing) {
1353 strs = icon_sizing_strs;
1354 *n = sizeof icon_sizing_strs / sizeof icon_sizing_strs[0];
1355 } else if (var == sview_style) {
1356 strs = get_sourceview_style_ids(n);
1357 } else if (var == graph_theme) {
1358 strs = get_graph_theme_ids(n);
1359 }
1360
1361 #ifdef HAVE_MPI
1362 else if (var == mpi_pref) {
1363 # ifdef G_OS_WIN32
1364 static const char *mpi_strs[] = {
1365 "MS-MPI" /* FIXME? */
1366 };
1367 # else
1368 static const char *mpi_strs[] = {
1369 "OpenMPI", "MPICH"
1370 };
1371 #endif
1372
1373 strs = mpi_strs;
1374 *n = sizeof mpi_strs / sizeof mpi_strs[0];
1375 }
1376 #endif
1377
1378 #if defined(MAC_THEMING)
1379 else if (var == themepref) {
1380 static const char *theme_strs[] = {
1381 "Adwaita", "Clearlooks", "Lion-like", "Raleigh"
1382 };
1383
1384 strs = theme_strs;
1385 *n = sizeof theme_strs / sizeof theme_strs[0];
1386 }
1387 #elif defined(G_OS_WIN32) && GTK_MAJOR_VERSION < 3
1388 else if (var == themepref) {
1389 static const char *theme_strs[] = {
1390 "Windows-10", "MS-Windows", "Clearlooks", "Raleigh"
1391 };
1392
1393 strs = theme_strs;
1394 *n = sizeof theme_strs / sizeof theme_strs[0];
1395 }
1396 #elif defined(G_OS_WIN32) && GTK_MAJOR_VERSION == 3
1397 else if (var == themepref) {
1398 static const char *theme_strs[] = {
1399 "Windows 10", "Windows 7", "Adwaita"
1400 };
1401
1402 strs = theme_strs;
1403 *n = sizeof theme_strs / sizeof theme_strs[0];
1404 }
1405 #endif
1406
1407 return strs;
1408 }
1409
get_radio_setting_strings(void * var,int * n)1410 static const char **get_radio_setting_strings (void *var, int *n)
1411 {
1412 /* unused at present, but may be activated again at
1413 some point? */
1414 *n = 0;
1415 return NULL;
1416 }
1417
get_default_hc_string(int ci)1418 const char *get_default_hc_string (int ci)
1419 {
1420 if (ci == GARCH) {
1421 int k = libset_get_int(GARCH_ALT_VCV);
1422
1423 return (k == ML_BW)? "BW" : "QML";
1424 } else if (!robust_conf(ci)) {
1425 return "QML";
1426 } else {
1427 int xsect = dataset_is_cross_section(dataset);
1428 int tseries = dataset_is_time_series(dataset);
1429
1430 if (tseries && libset_get_bool(FORCE_HC)) {
1431 xsect = 1;
1432 } else if (ci == VAR) {
1433 xsect = 1;
1434 }
1435
1436 if (xsect) {
1437 return hc_strs[libset_get_int(HC_VERSION)];
1438 } else if (tseries) {
1439 /* (and not forced to an HC variant) */
1440 return "HAC";
1441 } else {
1442 /* panel */
1443 return libset_get_bool(USE_PCSE) ? "PCSE" : "Arellano";
1444 }
1445 }
1446 }
1447
non_console_var(void * ptr)1448 static int non_console_var (void *ptr)
1449 {
1450 #ifdef HAVE_GTKSV_COMPLETION
1451 return (ptr == &smarttab || ptr == &script_line_numbers ||
1452 ptr == &tabbed_editor || ptr == &tabwidth ||
1453 ptr == &hansl_completion);
1454 #else
1455 return (ptr == &smarttab || ptr == &script_line_numbers ||
1456 ptr == &tabbed_editor || ptr == &tabwidth);
1457 #endif
1458 }
1459
console_only(void * ptr)1460 static int console_only (void *ptr)
1461 {
1462 #ifdef HAVE_GTKSV_COMPLETION
1463 return (ptr == &console_completion);
1464 #else
1465 return 0;
1466 #endif
1467 }
1468
1469 static void
get_table_sizes(int page,int * n_str,int * n_bool,int * n_browse,int * n_list,int console)1470 get_table_sizes (int page, int *n_str, int *n_bool, int *n_browse,
1471 int *n_list, int console)
1472 {
1473 int i;
1474
1475 for (i=0; rc_vars[i].key != NULL; i++) {
1476 if (rc_vars[i].tab == page) {
1477 if (console && non_console_var(rc_vars[i].var)) {
1478 continue;
1479 } else if (!console && console_only(rc_vars[i].var)) {
1480 continue;
1481 }
1482 if (rc_vars[i].flags & BROWSER) {
1483 *n_browse += 1;
1484 } else if (rc_vars[i].flags & LISTSET) {
1485 *n_list += 1;
1486 } else if (rc_vars[i].flags & SPINSET) {
1487 *n_list += 1;
1488 }
1489 if (rc_vars[i].flags & BOOLSET) {
1490 *n_bool += 1;
1491 } else if (rc_vars[i].flags & RADIOSET) {
1492 *n_bool += 1;
1493 } else if (!(rc_vars[i].flags & INVISET)) {
1494 *n_str += 1;
1495 }
1496 }
1497 }
1498 }
1499
radio_change_value(GtkWidget * w,int * v)1500 static void radio_change_value (GtkWidget *w, int *v)
1501 {
1502 if (button_is_active(w)) {
1503 gint i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "action"));
1504
1505 *v = i;
1506 }
1507 }
1508
table_attach_fixed(GtkTable * table,GtkWidget * child,guint left,guint right,guint top,guint bottom)1509 static void table_attach_fixed (GtkTable *table,
1510 GtkWidget *child,
1511 guint left, guint right,
1512 guint top, guint bottom)
1513 {
1514 gtk_table_attach(table, child, left, right, top, bottom,
1515 0, 0, 0, 0);
1516 }
1517
themes_page(GtkButton * button,gpointer p)1518 static void themes_page (GtkButton *button, gpointer p)
1519 {
1520 if (browser_open("http://ricardo.ecn.wfu.edu/pub/gretl/plots/")) {
1521 errbox("Failed to open URL");
1522 }
1523 }
1524
add_themes_examples_button(GtkWidget * hbox)1525 static void add_themes_examples_button (GtkWidget *hbox)
1526 {
1527 GtkWidget *b;
1528
1529 b = gtk_button_new_with_label(_("Examples"));
1530 gtk_box_pack_start(GTK_BOX(hbox), b, FALSE, FALSE, 5);
1531 g_signal_connect(G_OBJECT(b), "clicked",
1532 G_CALLBACK(themes_page), NULL);
1533 }
1534
scroller_page(GtkWidget * vbox)1535 static GtkWidget *scroller_page (GtkWidget *vbox)
1536 {
1537 GtkWidget *scroller;
1538
1539 scroller = gtk_scrolled_window_new(NULL, NULL);
1540 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
1541 GTK_POLICY_NEVER,
1542 GTK_POLICY_AUTOMATIC);
1543 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroller),
1544 vbox);
1545 return scroller;
1546 }
1547
make_prefs_tab(GtkWidget * notebook,int tab,int console)1548 static void make_prefs_tab (GtkWidget *notebook, int tab,
1549 int console)
1550 {
1551 GtkWidget *b_table = NULL, *s_table = NULL;
1552 GtkWidget *l_table = NULL;
1553 GtkWidget *vbox, *w = NULL;
1554 GtkWidget *page;
1555 int s_len = 1, b_len = 0, l_len = 1;
1556 int s_cols, b_cols = 0, l_cols = 0;
1557 int b_col = 0;
1558 int n_str = 0;
1559 int n_bool = 0;
1560 int n_browse = 0;
1561 int n_list = 0;
1562 RCVAR *rc;
1563 int i;
1564
1565 if (console) {
1566 vbox = notebook; /* not really a notebook! */
1567 } else {
1568 vbox = gtk_vbox_new(FALSE, 0);
1569 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1570
1571 if (tab == TAB_MAIN) {
1572 w = gtk_label_new(_("General"));
1573 } else if (tab == TAB_PROGS) {
1574 w = gtk_label_new(_("Programs"));
1575 } else if (tab == TAB_EDITOR) {
1576 w = gtk_label_new(_("Editor"));
1577 } else if (tab == TAB_NET) {
1578 w = gtk_label_new(_("Network"));
1579 } else if (tab == TAB_VCV) {
1580 w = gtk_label_new(_("HCCME"));
1581 #ifdef HAVE_MPI
1582 } else if (tab == TAB_MPI) {
1583 w = gtk_label_new(_("MPI"));
1584 #endif
1585 }
1586 if (tab == TAB_PROGS) {
1587 page = scroller_page(vbox);
1588 } else {
1589 page = vbox;
1590 }
1591
1592 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, w);
1593 }
1594
1595 get_table_sizes(tab, &n_str, &n_bool, &n_browse, &n_list, console);
1596
1597 s_cols = (n_browse > 0)? 3 : 2;
1598
1599 if (tab == TAB_VCV && n_list > 0) {
1600 /* VCV tab -- put the list entries first, right aligned */
1601 l_cols = 2;
1602 l_table = gtk_table_new(l_len, l_cols, FALSE);
1603 gtk_table_set_row_spacings(GTK_TABLE(l_table), 5);
1604 gtk_table_set_col_spacings(GTK_TABLE(l_table), 5);
1605 gtk_box_pack_start(GTK_BOX(vbox), l_table, FALSE, FALSE, 0);
1606 }
1607
1608 if (n_str > 0) {
1609 s_table = gtk_table_new(s_len, s_cols, FALSE);
1610 gtk_table_set_row_spacings(GTK_TABLE(s_table), 5);
1611 gtk_table_set_col_spacings(GTK_TABLE(s_table), 5);
1612 gtk_box_pack_start(GTK_BOX(vbox), s_table, FALSE, FALSE, 0);
1613 }
1614
1615 if (n_bool > 0) {
1616 b_cols = 2;
1617 b_table = gtk_table_new(1, b_cols, FALSE);
1618 gtk_table_set_row_spacings(GTK_TABLE(b_table), 5);
1619 gtk_table_set_col_spacings(GTK_TABLE(b_table), 5);
1620 gtk_box_pack_start(GTK_BOX(vbox), b_table, FALSE, FALSE, 10);
1621 }
1622
1623 if (tab != TAB_VCV && n_list > 0) {
1624 /* non-VCV tab -- list entries come last, and we
1625 use an hbox to pack them left */
1626 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1627
1628 l_cols = 2;
1629 l_table = gtk_table_new(l_len, l_cols, FALSE);
1630 gtk_table_set_row_spacings(GTK_TABLE(l_table), 10);
1631 gtk_table_set_col_spacings(GTK_TABLE(l_table), 10);
1632 gtk_box_pack_start(GTK_BOX(hbox), l_table, FALSE, FALSE, 5);
1633 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1634 }
1635
1636 for (i=0; rc_vars[i].key != NULL; i++) {
1637 rc = &rc_vars[i];
1638
1639 if (rc->tab != tab) {
1640 /* the item is not on this page */
1641 continue;
1642 } else if (console && non_console_var(rc->var)) {
1643 rc->widget = NULL;
1644 continue;
1645 } else if (!console && console_only(rc->var)) {
1646 rc->widget = NULL;
1647 continue;
1648 }
1649
1650 if ((rc->flags & BOOLSET) && rc->link == NULL) {
1651 /* simple boolean variable (check box) */
1652 int rcval = *(int *) (rc->var);
1653
1654 rc->widget = gtk_check_button_new_with_label(_(rc->description));
1655 gtk_table_attach_defaults(GTK_TABLE (b_table), rc->widget,
1656 b_col, b_col + 1, b_len, b_len + 1);
1657
1658 if (rcval) {
1659 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rc->widget), TRUE);
1660 } else {
1661 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rc->widget), FALSE);
1662 }
1663
1664 /* special case: link between toggle and preceding entry */
1665 if (rc->len && !(rc->flags & FIXSET)) {
1666 gtk_widget_set_sensitive(rc_vars[i-1].widget,
1667 button_is_active(rc->widget));
1668 g_signal_connect(G_OBJECT(rc->widget), "clicked",
1669 G_CALLBACK(flip_sensitive),
1670 rc_vars[i-1].widget);
1671 }
1672
1673 b_col++;
1674
1675 if (tab == TAB_VCV || b_col == 2) {
1676 /* boolean strings under TAB_VCV are too long to
1677 appear column-wise
1678 */
1679 b_col = 0;
1680 b_len++;
1681 gtk_table_resize(GTK_TABLE(b_table), b_len + 1, 2);
1682 }
1683
1684 if (rc->flags & FIXSET) {
1685 gtk_widget_set_sensitive(rc->widget, FALSE);
1686 if (rc->len) {
1687 gtk_widget_set_sensitive(rc_vars[i-1].widget, FALSE);
1688 }
1689 }
1690 } else if (rc->flags & BOOLSET) {
1691 /* radio-button dichotomy */
1692 int rcval = *(int *) (rc->var);
1693 GtkWidget *button;
1694 GSList *group = NULL;
1695
1696 /* do we have some padding to do? */
1697 if (b_col == 1) {
1698 w = gtk_label_new(" ");
1699 gtk_table_attach_defaults(GTK_TABLE(b_table), w,
1700 b_col, b_col + 1,
1701 b_len, b_len + 1);
1702 b_col = 0;
1703 b_len++;
1704 gtk_table_resize(GTK_TABLE(b_table), b_len + 1, 2);
1705 }
1706
1707 b_len += 3;
1708 gtk_table_resize(GTK_TABLE(b_table), b_len + 1, 2);
1709
1710 /* separator for the group? */
1711 w = gtk_hseparator_new();
1712 gtk_table_attach_defaults(GTK_TABLE(b_table), w,
1713 b_col, b_col + 1,
1714 b_len - 3, b_len - 2);
1715
1716 /* then a first button */
1717 button = gtk_radio_button_new_with_label(group, _(rc->link));
1718 gtk_table_attach_defaults(GTK_TABLE(b_table), button,
1719 b_col, b_col + 1,
1720 b_len - 2, b_len - 1);
1721 if (!rcval) {
1722 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
1723 }
1724
1725 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1726
1727 /* and a second button */
1728 rc->widget = gtk_radio_button_new_with_label(group,
1729 _(rc->description));
1730 gtk_table_attach_defaults(GTK_TABLE(b_table), rc->widget,
1731 b_col, b_col + 1,
1732 b_len - 1, b_len);
1733 if (rcval) {
1734 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rc->widget), TRUE);
1735 }
1736
1737 if (rc->flags & FIXSET) {
1738 gtk_widget_set_sensitive(button, FALSE);
1739 gtk_widget_set_sensitive(rc->widget, FALSE);
1740 }
1741 } else if (rc->flags & RADIOSET) {
1742 int nopt, j, rcval = *(int *) (rc->var);
1743 int rcol;
1744 GtkWidget *b;
1745 GSList *group = NULL;
1746 const char **strs;
1747
1748 if (b_len > 0) {
1749 /* there are buttons above: add a separator and
1750 make this section full-width */
1751 rcol = b_cols;
1752 b_len++;
1753 w = gtk_hseparator_new();
1754 gtk_table_attach_defaults(GTK_TABLE(b_table), w,
1755 0, rcol, b_len - 1, b_len);
1756 } else {
1757 rcol = b_col + 1;
1758 }
1759
1760 b_len++;
1761 b = gtk_label_new(_(rc->description));
1762 gtk_table_attach_defaults(GTK_TABLE(b_table), b,
1763 b_col, rcol,
1764 b_len - 1, b_len);
1765
1766 strs = get_radio_setting_strings(rc->var, &nopt);
1767
1768 for (j=0; j<nopt; j++) {
1769 b_len++;
1770 gtk_table_resize(GTK_TABLE(b_table), b_len, 2);
1771 b = gtk_radio_button_new_with_label(group, _(strs[j]));
1772 gtk_table_attach_defaults(GTK_TABLE(b_table), b,
1773 b_col, rcol,
1774 b_len - 1, b_len);
1775 g_object_set_data(G_OBJECT(b), "action",
1776 GINT_TO_POINTER(j));
1777 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), j == rcval);
1778 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b));
1779 g_signal_connect(G_OBJECT(b), "clicked",
1780 G_CALLBACK(radio_change_value),
1781 rc->var);
1782 }
1783 } else if (rc->flags & LISTSET) {
1784 int langs = rc->var == langpref;
1785 int gtheme = rc->var == graph_theme;
1786 int j, active = 0;
1787
1788 l_len++;
1789
1790 gtk_table_resize(GTK_TABLE(l_table), l_len, l_cols);
1791 w = gtk_label_new(_(rc->description));
1792 if (tab == TAB_MAIN) {
1793 gtk_misc_set_alignment(GTK_MISC(w), 0.0, 0.5);
1794 } else {
1795 gtk_misc_set_alignment(GTK_MISC(w), 1.0, 0.5);
1796 }
1797 gtk_table_attach_defaults(GTK_TABLE(l_table),
1798 w, 0, 1, l_len - 1, l_len);
1799
1800 rc->widget = gtk_combo_box_text_new();
1801
1802 if (tab == TAB_MAIN) {
1803 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1804
1805 gtk_box_pack_start(GTK_BOX(hbox), rc->widget, FALSE, FALSE, 5);
1806 if (gtheme) {
1807 add_themes_examples_button(hbox);
1808 }
1809 gtk_table_attach(GTK_TABLE(l_table), hbox,
1810 1, 2, l_len - 1, l_len,
1811 GTK_EXPAND | GTK_FILL, 0, 0, 0);
1812 } else {
1813 gtk_table_attach(GTK_TABLE(l_table), rc->widget,
1814 1, 2, l_len - 1, l_len,
1815 0, 0, 0, 0);
1816 }
1817
1818 if (rc->flags & FLOATSET) {
1819 /* special: graph scale */
1820 double scale, *xvar = (double *) rc->var;
1821 char numstr[4];
1822
1823 j = 0;
1824 while (get_graph_scale(j, &scale)) {
1825 sprintf(numstr, "%.1f", scale);
1826 combo_box_append_text(rc->widget, numstr);
1827 if (scale == *xvar) {
1828 active = j;
1829 }
1830 j++;
1831 }
1832 } else if (langs) {
1833 char *strvar = (char *) rc->var;
1834 const char *str;
1835 int jj = 0;
1836
1837 for (j=LANG_AUTO; j<LANG_MAX; j++) {
1838 str = lang_string_from_id(j);
1839 if (str != NULL) {
1840 combo_box_append_text(rc->widget, str);
1841 if (!strcmp(str, strvar)) {
1842 active = jj;
1843 }
1844 jj++;
1845 }
1846 }
1847 } else {
1848 char *strvar = NULL;
1849 int *intvar = NULL;
1850 const char **strs;
1851 int nopt;
1852
1853 if (rc->flags & INTSET) {
1854 intvar = (int *) rc->var;
1855 } else {
1856 strvar = (char *) rc->var;
1857 }
1858
1859 strs = get_list_setting_strings(rc->var, &nopt);
1860 for (j=0; j<nopt; j++) {
1861 combo_box_append_text(rc->widget, _(strs[j]));
1862 if (strvar != NULL && !strcmp(strs[j], strvar)) {
1863 active = j;
1864 } else if (intvar != NULL && j == *intvar) {
1865 active = j;
1866 }
1867 }
1868 }
1869 if (tab == TAB_VCV) {
1870 int ww = get_string_width("XXArellanoXXXXX");
1871
1872 gtk_widget_set_size_request(rc->widget, ww, -1);
1873 }
1874 gtk_combo_box_set_active(GTK_COMBO_BOX(rc->widget), active);
1875 if (langs) {
1876 g_signal_connect(G_OBJECT(rc->widget), "changed",
1877 G_CALLBACK(try_switch_locale),
1878 NULL);
1879 } else if (rc->var == &sview_style) {
1880 GtkWidget *sampler;
1881
1882 sampler = embed_style_sampler(vbox);
1883 g_signal_connect(G_OBJECT(rc->widget), "changed",
1884 G_CALLBACK(try_switch_style),
1885 sampler);
1886 }
1887 } else if (rc->flags & SPINSET) {
1888 int *intvar = (int *) rc->var;
1889
1890 l_len++;
1891
1892 gtk_table_resize(GTK_TABLE(l_table), l_len, l_cols);
1893 w = gtk_label_new(_(rc->description));
1894 gtk_misc_set_alignment(GTK_MISC(w), 1, 0.5);
1895 gtk_table_attach_defaults(GTK_TABLE(l_table),
1896 w, 0, 1, l_len - 1, l_len);
1897
1898 /* for now, this is specific to tab-spaces */
1899 rc->widget = gtk_spin_button_new_with_range(2, 8, 1);
1900 gtk_spin_button_set_value(GTK_SPIN_BUTTON(rc->widget), *intvar);
1901 gtk_table_attach_defaults(GTK_TABLE(l_table),
1902 rc->widget, 1, 2, l_len - 1, l_len);
1903 } else if (!(rc->flags & INVISET)) {
1904 /* visible string variable */
1905 char *strvar = (char *) rc->var;
1906
1907 s_len++;
1908
1909 gtk_table_resize(GTK_TABLE(s_table), s_len, s_cols);
1910 w = gtk_label_new(_(rc->description));
1911 gtk_misc_set_alignment(GTK_MISC(w), 1, 0.5);
1912 gtk_table_attach_defaults(GTK_TABLE(s_table), w,
1913 0, 1, s_len - 1, s_len);
1914
1915 rc->widget = gtk_entry_new();
1916 gtk_table_attach_defaults(GTK_TABLE(s_table),
1917 rc->widget, 1, 2, s_len - 1, s_len);
1918 gtk_entry_set_text(GTK_ENTRY(rc->widget), strvar);
1919
1920 if (rc->flags & BROWSER) {
1921 /* add path browse button */
1922 w = make_path_browse_button(rc, notebook);
1923 table_attach_fixed(GTK_TABLE(s_table), w,
1924 2, 3, s_len - 1, s_len);
1925 }
1926
1927 if (rc->flags & FIXSET) {
1928 gtk_widget_set_sensitive(rc->widget, FALSE);
1929 gtk_widget_set_sensitive(w, FALSE);
1930 }
1931 }
1932 }
1933 }
1934
set_gp_colors(void)1935 static void set_gp_colors (void)
1936 {
1937 const char *s = gpcolors;
1938 char cstr[2][8];
1939
1940 *cstr[0] = *cstr[1] = '\0';
1941
1942 if (sscanf(s, "%7s %7s", cstr[0], cstr[1]) == 2) {
1943 set_graph_color_from_string(0, cstr[0]);
1944 set_graph_color_from_string(1, cstr[1]);
1945 }
1946 }
1947
set_gp_scale(void)1948 static void set_gp_scale (void)
1949 {
1950 gnuplot_png_set_default_scale(graph_scale);
1951 }
1952
set_gp_theme(void)1953 static void set_gp_theme (void)
1954 {
1955 set_plotstyle(graph_theme);
1956 }
1957
1958 #if defined(HAVE_TRAMO) || defined(HAVE_X12A)
1959
maybe_revise_tramo_x12a_status(void)1960 static void maybe_revise_tramo_x12a_status (void)
1961 {
1962 # ifdef HAVE_TRAMO
1963 if (strcmp(paths.tramo, gretl_tramo())) {
1964 set_tramo_status();
1965 }
1966 # endif
1967
1968 # ifdef HAVE_X12A
1969 if (strcmp(paths.x12a, gretl_x12_arima())) {
1970 set_x12a_status();
1971 }
1972 # endif
1973 }
1974
1975 #endif
1976
flag_changed(RCVAR * rcvar,int * changed)1977 static void flag_changed (RCVAR *rcvar, int *changed)
1978 {
1979 if (rcvar->flags & RESTART) {
1980 *changed = 2;
1981 } else if (*changed == 0) {
1982 *changed = 1;
1983 }
1984 }
1985
rcvar_set_int(RCVAR * rcvar,int ival,int * changed)1986 static void rcvar_set_int (RCVAR *rcvar, int ival, int *changed)
1987 {
1988 int *intvar = (int *) rcvar->var;
1989
1990 if (ival != *intvar) {
1991 flag_changed(rcvar, changed);
1992 *intvar = ival;
1993 }
1994 }
1995
blank_ok(RCVAR * rcvar)1996 static int blank_ok (RCVAR *rcvar)
1997 {
1998 if (!strcmp(rcvar->key, "mpi_hosts")) {
1999 return 1;
2000 } else if (!strcmp(rcvar->key, "dbproxy")) {
2001 return 1;
2002 } else {
2003 return 0;
2004 }
2005 }
2006
rcvar_set_string(RCVAR * rcvar,const char * sval,int * changed)2007 static void rcvar_set_string (RCVAR *rcvar, const char *sval, int *changed)
2008 {
2009 char *strvar = (char *) rcvar->var;
2010
2011 if (sval == NULL && blank_ok(rcvar)) {
2012 /* allow "blanking out" of the item */
2013 if (*strvar != '\0') {
2014 flag_changed(rcvar, changed);
2015 *strvar = '\0';
2016 }
2017 return;
2018 }
2019
2020 if (sval != NULL && *sval != '\0' && strcmp(sval, strvar)) {
2021 flag_changed(rcvar, changed);
2022 *strvar = '\0';
2023 strncat(strvar, sval, rcvar->len - 1);
2024 }
2025 }
2026
rcvar_set_double(RCVAR * rcvar,const char * sval,int * changed)2027 static void rcvar_set_double (RCVAR *rcvar, const char *sval, int *changed)
2028 {
2029 double *xvar = (double *) rcvar->var;
2030
2031 if (sval != NULL && *sval != '\0') {
2032 double xval = atof(sval);
2033
2034 if (xval != *xvar) {
2035 flag_changed(rcvar, changed);
2036 *xvar = xval;
2037 }
2038 }
2039 }
2040
restart_message(void)2041 static void restart_message (void)
2042 {
2043 infobox(_("This change will take effect when you restart gretl"));
2044 }
2045
2046 /* Register and react to changes from the main Preferences dialog
2047 or the console-specific preferences.
2048 */
2049
apply_prefs_changes(GtkWidget * widget,GtkWidget * parent)2050 static void apply_prefs_changes (GtkWidget *widget, GtkWidget *parent)
2051 {
2052 RCVAR *rcvar;
2053 GtkWidget *w;
2054 int changed = 0;
2055 int i;
2056
2057 for (i=0; rc_vars[i].key != NULL; i++) {
2058 rcvar = &rc_vars[i];
2059 w = rcvar->widget;
2060 if (w == NULL) {
2061 continue;
2062 }
2063 if (rcvar->flags & BOOLSET) {
2064 int bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
2065
2066 rcvar_set_int(rcvar, bval, &changed);
2067 } else if (rcvar->flags & SPINSET) {
2068 int ival = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w));
2069
2070 rcvar_set_int(rcvar, ival, &changed);
2071 } else if (rcvar->flags & (USERSET | MACHSET)) {
2072 gchar *sval = entry_box_get_trimmed_text(w);
2073
2074 rcvar_set_string(rcvar, sval, &changed);
2075 g_free(sval);
2076 } else if (rcvar->flags & LISTSET) {
2077 GtkComboBox *box = GTK_COMBO_BOX(w);
2078
2079 if (rcvar->flags & INTSET) {
2080 int ival = gtk_combo_box_get_active(box);
2081
2082 rcvar_set_int(rcvar, ival, &changed);
2083 } else {
2084 gchar *sval = combo_box_get_active_text(box);
2085
2086 if (rcvar->flags & FLOATSET) {
2087 rcvar_set_double(rcvar, sval, &changed);
2088 } else {
2089 rcvar_set_string(rcvar, sval, &changed);
2090 }
2091 g_free(sval);
2092 }
2093 }
2094 }
2095
2096 if (changed > 1) {
2097 restart_message();
2098 }
2099
2100 #if defined(HAVE_TRAMO) || defined(HAVE_X12A)
2101 maybe_revise_tramo_x12a_status();
2102 #endif
2103
2104 #ifdef HAVE_MPI
2105 set_mpi_variant(mpi_pref);
2106 #endif
2107
2108 if (use_proxy && *http_proxy == '\0') {
2109 /* fix inconsistency */
2110 use_proxy = 0;
2111 }
2112
2113 /* update graphing info */
2114 gnuplot_png_set_default_scale(graph_scale);
2115 set_plotstyle(graph_theme);
2116
2117 write_rc(OPT_NONE); /* note: calls gretl_update_paths */
2118
2119 /* register these settings for the current session using
2120 the "libset" apparatus
2121 */
2122 libset_set_bool(SHELL_OK, shellok);
2123 libset_set_bool(ROBUST_Z, robust_z);
2124 set_xsect_hccme(hc_xsect);
2125 set_tseries_hccme(hc_tseri);
2126 set_panel_hccme(hc_panel);
2127 set_garch_alt_vcv(hc_garch);
2128
2129 selector_register_hc_choice();
2130
2131 if (parent != NULL) {
2132 windata_t *vwin = window_get_active_vwin(parent);
2133
2134 if (vwin != NULL && vwin->sbuf != NULL) {
2135 /* called from sourceview window or tab, or console */
2136 update_script_editor_options(vwin);
2137 }
2138 }
2139
2140 gretl_www_init(http_proxy, use_proxy);
2141 }
2142
boolvar_to_str(void * b,char * s)2143 static void boolvar_to_str (void *b, char *s)
2144 {
2145 if (*(int *) b) {
2146 strcpy(s, "true");
2147 } else {
2148 strcpy(s, "false");
2149 }
2150 }
2151
2152 /* non-static because also called from dialogs.c on exit */
2153
write_rc(gretlopt opt)2154 int write_rc (gretlopt opt)
2155 {
2156 RCVAR *rcvar;
2157 FILE *fp;
2158 char val[6];
2159 char *strvar;
2160 int i;
2161
2162 fp = gretl_fopen(rcfile, "w");
2163 if (fp == NULL) {
2164 file_write_errbox(rcfile);
2165 return E_FOPEN;
2166 }
2167
2168 fprintf(fp, "# gretl config file\n");
2169 fputs("# build date\n", fp);
2170 fprintf(fp, "build_date = %s\n", BUILD_DATE);
2171
2172 for (i=0; rc_vars[i].var != NULL; i++) {
2173 rcvar = &rc_vars[i];
2174 #ifdef G_OS_WIN32
2175 /* let the registry or gretlnet.txt handle this */
2176 if (!strcmp(rcvar->key, "gretldir")) {
2177 continue;
2178 }
2179 #endif
2180 if (rcvar->flags & SKIPSET) {
2181 /* don't bother writing out an empty entry */
2182 strvar = (char *) rcvar->var;
2183 if (*strvar == '\0') {
2184 continue;
2185 }
2186 }
2187 fprintf(fp, "# %s\n", rcvar->description);
2188 if (rcvar->flags & BOOLSET) {
2189 boolvar_to_str(rcvar->var, val);
2190 fprintf(fp, "%s = %s\n", rcvar->key, val);
2191 } else if (rcvar->flags & INTSET) {
2192 fprintf(fp, "%s = %d\n", rcvar->key, *(int *) rcvar->var);
2193 } else if (rcvar->flags & FLOATSET) {
2194 gretl_push_c_numeric_locale();
2195 fprintf(fp, "%s = %g\n", rcvar->key, *(double *) rcvar->var);
2196 gretl_pop_c_numeric_locale();
2197 } else {
2198 strvar = (char *) rcvar->var;
2199 fprintf(fp, "%s = %s\n", rcvar->key, strvar);
2200 }
2201 }
2202
2203 rc_save_file_lists(fp);
2204 fclose(fp);
2205
2206 if (!(opt & OPT_N)) {
2207 gretl_update_paths(&paths, update_paths_opt);
2208 }
2209
2210 return 0;
2211 }
2212
sync_path_from_lib(const char * path_id)2213 void sync_path_from_lib (const char *path_id)
2214 {
2215 if (!strcmp(path_id, "tramo")) {
2216 strcpy(paths.tramo, gretl_tramo());
2217 write_rc(OPT_N);
2218 restart_message();
2219 } else if (!strcmp(path_id, "x12a")) {
2220 strcpy(paths.x12a, gretl_x12_arima());
2221 write_rc(OPT_N);
2222 restart_message();
2223 } else {
2224 fprintf(stderr, "sync_path_from_lib: '%s' ??\n", path_id);
2225 }
2226 }
2227
str_to_boolvar(const char * s,void * b)2228 static void str_to_boolvar (const char *s, void *b)
2229 {
2230 int *bvar = (int *) b;
2231
2232 if (s == NULL) return;
2233
2234 if (strcmp(s, "true") == 0 || strcmp(s, "1") == 0) {
2235 *bvar = TRUE;
2236 } else {
2237 *bvar = FALSE;
2238 }
2239 }
2240
str_to_int(const char * s,void * b)2241 static void str_to_int (const char *s, void *b)
2242 {
2243 int *ivar = (int *) b;
2244
2245 if (s == NULL) return;
2246
2247 if (sscanf(s, "%d", ivar) != 1) {
2248 if (!strcmp(s, "true")) {
2249 /* remedy for ex-boolean */
2250 *ivar = 1;
2251 } else {
2252 *ivar = 0;
2253 }
2254 }
2255 }
2256
str_to_double(const char * s,void * b)2257 static void str_to_double (const char *s, void *b)
2258 {
2259 double *xvar = (double *) b;
2260
2261 if (s != NULL && *s != '\0') {
2262 *xvar = dot_atof(s);
2263 }
2264 }
2265
2266 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
2267
maybe_fix_viewpdf(void)2268 static void maybe_fix_viewpdf (void)
2269 {
2270 gchar *prog = NULL;
2271 const gchar *viewers[] = {
2272 "xpdf",
2273 "acroread",
2274 "evince",
2275 "kpdf",
2276 "gpdf",
2277 NULL
2278 };
2279 int i;
2280
2281 prog = g_find_program_in_path(viewpdf);
2282
2283 if (prog != NULL) {
2284 g_free(prog);
2285 } else {
2286 for (i=0; viewers[i] != NULL; i++) {
2287 if (strcmp(viewers[i], viewpdf)) {
2288 prog = g_find_program_in_path(viewers[i]);
2289 if (prog != NULL) {
2290 strcpy(viewpdf, viewers[i]);
2291 g_free(prog);
2292 break;
2293 }
2294 }
2295 }
2296 }
2297 }
2298
2299 #endif
2300
2301 /* The various things we need to do after reading gretl's
2302 configuration info -- or perhaps after failing to do so.
2303 We do this only at start-up time. This function is
2304 called by the config-file reading function, either
2305 read_gretlrc() or on MS Windows, read_win32_config().
2306 */
2307
common_read_rc_setup(int updated)2308 static int common_read_rc_setup (int updated)
2309 {
2310 int langid = 0;
2311 int err = 0;
2312
2313 libset_set_bool(SHELL_OK, shellok);
2314 libset_set_bool(USE_CWD, usecwd);
2315 libset_set_bool(ROBUST_Z, robust_z);
2316 set_gp_colors();
2317 set_gp_scale();
2318
2319 set_xsect_hccme(hc_xsect);
2320 set_tseries_hccme(hc_tseri);
2321 set_panel_hccme(hc_panel);
2322 set_garch_alt_vcv(hc_garch);
2323
2324 err = gretl_set_paths(&paths);
2325 if (err) {
2326 /* tell the user, then turn off the special alarm */
2327 gui_errmsg(err);
2328 set_gretl_alarm(0);
2329 }
2330
2331 gretl_www_init(http_proxy, use_proxy);
2332 set_tex_use_pdf(latex);
2333 set_gp_theme();
2334
2335 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
2336 maybe_fix_viewpdf();
2337 #endif
2338
2339 #ifdef HAVE_TRAMO
2340 set_tramo_status();
2341 #endif
2342
2343 #ifdef HAVE_X12A
2344 set_x12a_status();
2345 # endif
2346
2347 langid = lang_id_from_name(langpref);
2348 #ifdef G_OS_WIN32
2349 fprintf(stderr, "rc_setup: langpref='%s', langid=%d, lcnumeric=%d\n",
2350 langpref, langid, lcnumeric);
2351 #endif
2352 force_language(langid);
2353 if (langid == LANG_C) {
2354 force_english_help();
2355 }
2356 set_lcnumeric(langid, lcnumeric);
2357
2358 if (updated) {
2359 update_addons_index(NULL);
2360 }
2361
2362 return err;
2363 }
2364
2365 /* On reading from text rc file, look up the key in the "key = value"
2366 line we just read, and set the value of the associated variable.
2367 */
2368
find_and_set_rc_var(const char * key,const char * val)2369 static void find_and_set_rc_var (const char *key, const char *val)
2370 {
2371 RCVAR *rcvar;
2372 char *strvar;
2373 int i;
2374
2375 for (i=0; rc_vars[i].key != NULL; i++) {
2376 rcvar = &rc_vars[i];
2377 if (!strcmp(key, rcvar->key)) {
2378 if (!(rcvar->flags & FIXSET)) {
2379 if (rcvar->flags & BOOLSET) {
2380 str_to_boolvar(val, rcvar->var);
2381 if (!strcmp(key, "collect_plots")) {
2382 /* special: set to "auto" */
2383 libset_set_int(PLOT_COLLECT, 1);
2384 }
2385 } else if (rcvar->flags & INTSET) {
2386 str_to_int(val, rcvar->var);
2387 } else if (rcvar->flags & FLOATSET) {
2388 str_to_double(val, rcvar->var);
2389 } else {
2390 strvar = (char *) rcvar->var;
2391 *strvar = '\0';
2392 strncat(strvar, val, rcvar->len - 1);
2393 }
2394 rcvar->flags |= GOTSET;
2395 }
2396 break;
2397 }
2398 }
2399 }
2400
2401 #ifdef G_OS_WIN32
2402
maybe_get_network_settings(void)2403 static int maybe_get_network_settings (void)
2404 {
2405 const char *netfile;
2406 FILE *fp;
2407 char *strvar;
2408 int gotnet = 0;
2409
2410 netfile = get_gretlnet_filename();
2411 if (netfile == NULL) {
2412 return 0;
2413 }
2414
2415 fp = gretl_fopen(netfile, "r");
2416
2417 if (fp != NULL) {
2418 char line[MAXLEN], key[32], linevar[MAXLEN];
2419 int j, calldrive = tolower(netfile[0]);
2420
2421 while (fgets(line, MAXLEN, fp)) {
2422 int gotvar = 0;
2423 char *p = line;
2424
2425 while (isspace(*p)) p++;
2426 if (*p == '#') continue;
2427
2428 if (sscanf(p, "%31s", key) == 1) {
2429 strcpy(linevar, p + strlen(key) + 3);
2430 gretl_strstrip(linevar);
2431 gotvar = 0;
2432 for (j=0; rc_vars[j].key != NULL; j++) {
2433 if (!strcmp(key, rc_vars[j].key)) {
2434 if (rc_vars[j].flags & BOOLSET) {
2435 str_to_boolvar(linevar, rc_vars[j].var);
2436 } else if (rc_vars[j].flags & INTSET) {
2437 str_to_int(linevar, rc_vars[j].var);
2438 } else {
2439 if (!strcmp(key, "gretldir") &&
2440 tolower(linevar[0]) != calldrive) {
2441 gotnet = 0;
2442 goto network_quit;
2443 } else {
2444 strvar = (char *) rc_vars[j].var;
2445 *strvar = '\0';
2446 strncat(strvar, linevar, rc_vars[j].len - 1);
2447 }
2448 }
2449 rc_vars[j].flags |= FIXSET;
2450 gotvar = gotnet = 1;
2451 }
2452 if (gotvar) break;
2453 }
2454 }
2455 }
2456 network_quit:
2457 fclose(fp);
2458 }
2459
2460 return gotnet;
2461 }
2462
2463 /* Try reading user settings from .gretl2rc in appdata directory: if
2464 this succeeds it will pre-empt reading from the registry --
2465 except that we'll respect the registry entry (or perhaps
2466 argv[0] at startup) for gretldir.
2467 */
2468
win32_read_gretlrc(int * updated)2469 static void win32_read_gretlrc (int *updated)
2470 {
2471 char line[MAXLEN], key[32], linevar[MAXLEN];
2472 int got_recent = 0;
2473 FILE *fp;
2474
2475 if (*rcfile == '\0') {
2476 /* shouldn't happen */
2477 return;
2478 }
2479
2480 fp = gretl_fopen(rcfile, "r");
2481
2482 #if 1
2483 fprintf(stderr, "rcfile: '%s' (%s)\n", rcfile,
2484 fp == NULL ? "not found" : "found");
2485 #endif
2486
2487 if (fp == NULL) {
2488 /* not necessarily an error: may be starting from scratch */
2489 return;
2490 }
2491
2492 while (fgets(line, sizeof line, fp) != NULL) {
2493 if (line[0] == '#') {
2494 continue;
2495 }
2496 if (!strncmp(line, "recent", 6)) {
2497 got_recent = 1;
2498 break;
2499 }
2500 if (sscanf(line, "%s", key) == 1) {
2501 /* note: don't take gretldir from here */
2502 if (strcmp(key, "gretldir")) {
2503 strcpy(linevar, line + strlen(key) + 3);
2504 gretl_strstrip(linevar);
2505 if (*linevar != '\0') {
2506 if (!strcmp(key, "build_date")) {
2507 *updated = gretl_is_updated(linevar);
2508 } else if (!strcmp(key, "userdir")) {
2509 /* legacy */
2510 find_and_set_rc_var("workdir", linevar);
2511 } else {
2512 find_and_set_rc_var(key, linevar);
2513 }
2514 }
2515 }
2516 }
2517 }
2518
2519 if (got_recent) {
2520 rc_read_file_lists(fp, line);
2521 }
2522
2523 fclose(fp);
2524 }
2525
2526 /* This function is not static since it is called from
2527 gretl_win32_init() in gretlwin32.c
2528 */
2529
read_win32_config(int debug)2530 int read_win32_config (int debug)
2531 {
2532 RCVAR *rcvar;
2533 char value[MAXSTR];
2534 char *appdata;
2535 char *strvar;
2536 int updated = 0;
2537 int i, err = 0;
2538
2539 if (chinese_locale()) {
2540 strcpy(fixedfontname, "NSimSun 10");
2541 strcpy(default_fixedfont, "NSimSun 10");
2542 } else if (japanese_locale()) {
2543 strcpy(fixedfontname, "MS Gothic 10");
2544 strcpy(default_fixedfont, "MS Gothic 10");
2545 }
2546
2547 rcfile[0] = '\0';
2548
2549 #ifndef PKGBUILD
2550 /* try "HOME" first */
2551 if (rcfile[0] == '\0') {
2552 char *home = getenv("HOME");
2553
2554 if (home != NULL) {
2555 strcpy(rcfile, home);
2556 slash_terminate(rcfile);
2557 strcat(rcfile, ".gretl2rc");
2558 }
2559 }
2560 #endif
2561
2562 if (rcfile[0] == '\0') {
2563 appdata = appdata_path();
2564 if (appdata != NULL) {
2565 sprintf(rcfile, "%s\\gretl\\.gretl2rc", appdata);
2566 free(appdata);
2567 }
2568 }
2569
2570 /* see if we have a gretlnet.txt in place, and if so,
2571 read config from it */
2572 maybe_get_network_settings();
2573
2574 /* read from user config file */
2575 win32_read_gretlrc(&updated);
2576
2577 /* now read from registry for a few items, if they're
2578 not already set */
2579
2580 for (i=0; rc_vars[i].key != NULL; i++) {
2581 int regerr = 0;
2582
2583 rcvar = &rc_vars[i];
2584
2585 if (rcvar->flags & (FIXSET | GOTSET)) {
2586 /* already set via gretlnet.txt or user rcfile */
2587 continue;
2588 }
2589
2590 *value = '\0';
2591
2592 /* note: by now we have already determined gretldir as
2593 best we can; don't overwrite its setting
2594 */
2595 if ((rcvar->flags & MACHSET) && strcmp(rcvar->key, "gretldir")) {
2596 regerr = read_reg_val(HKEY_LOCAL_MACHINE,
2597 get_reg_base(rcvar->key),
2598 rcvar->key,
2599 value);
2600 }
2601
2602 if (debug && *value != '\0') {
2603 fprintf(stderr, "reg: err = %d, '%s' -> '%s'\n", regerr, rcvar->key,
2604 value);
2605 }
2606
2607 if (!regerr && *value != '\0') {
2608 /* replace defaults only if we actually got something */
2609 if (rcvar->flags & BOOLSET) {
2610 str_to_boolvar(value, rcvar->var);
2611 } else if (rcvar->flags & INTSET) {
2612 str_to_int(value, rcvar->var);
2613 } else {
2614 strvar = (char *) rcvar->var;
2615 *strvar = '\0';
2616 strncat(strvar, value, rcvar->len - 1);
2617 }
2618 }
2619 }
2620
2621 err = common_read_rc_setup(updated);
2622
2623 if (debug) {
2624 fprintf(stderr, "read_win32_config: returning %d\n", err);
2625 }
2626
2627 return err;
2628 }
2629
2630 #else /* end of win32 version, now plain GTK */
2631
2632 /* Note: even if we fail to read the rc file, we should still do
2633 common_read_rc_setup(), since that will establish defaults for
2634 basic paths, etc., and give gretl a chance of running OK.
2635 */
2636
read_gretlrc(void)2637 static int read_gretlrc (void)
2638 {
2639 FILE *fp = gretl_fopen(rcfile, "r");
2640 int updated = 0;
2641
2642 if (fp == NULL) {
2643 fprintf(stderr, "Couldn't read %s\n", rcfile);
2644 } else {
2645 char line[MAXLEN], key[32], linevar[MAXLEN];
2646 int got_recent = 0;
2647
2648 while (fgets(line, sizeof line, fp)) {
2649 if (*line == '#') {
2650 continue;
2651 }
2652 if (!strncmp(line, "recent", 6)) {
2653 got_recent = 1;
2654 break;
2655 }
2656 if (sscanf(line, "%31s", key) == 1) {
2657 *linevar = '\0';
2658 strncat(linevar, line + strlen(key) + 3, MAXLEN-1);
2659 gretl_strstrip(linevar);
2660 if (*linevar != '\0') {
2661 if (!strcmp(key, "userdir")) {
2662 find_and_set_rc_var("workdir", linevar);
2663 } else if (!strcmp(key, "build_date")) {
2664 updated = gretl_is_updated(linevar);
2665 } else {
2666 find_and_set_rc_var(key, linevar);
2667 }
2668 }
2669 }
2670 }
2671
2672 if (got_recent) {
2673 rc_read_file_lists(fp, line);
2674 }
2675
2676 fclose(fp);
2677 }
2678
2679 return common_read_rc_setup(updated);
2680 }
2681
2682 #endif /* end of non-Windows versions */
2683
fontsel_code(GtkAction * action)2684 static int fontsel_code (GtkAction *action)
2685 {
2686 const gchar *s = gtk_action_get_name(action);
2687
2688 if (!strcmp(s, "MenuFont")) {
2689 return APP_FONT_SELECTION;
2690 } else {
2691 return FIXED_FONT_SELECTION;
2692 }
2693 }
2694
2695 /* font selection via GtkFontChooser */
2696
2697 #if HAVE_GTK_FONT_CHOOSER
2698
latin_font_filter(PangoFontFamily * family,PangoFontFace * face,gpointer data)2699 gboolean latin_font_filter (PangoFontFamily *family,
2700 PangoFontFace *face,
2701 gpointer data)
2702 {
2703 const char *facename = pango_font_face_get_face_name(face);
2704
2705 if (strstr(facename, "Italic") || strstr(facename, "Bold")) {
2706 return FALSE;
2707 } else {
2708 return validate_single_font(family, FONT_FILTER_LATIN);
2709 }
2710 }
2711
mono_font_filter(PangoFontFamily * family,PangoFontFace * face,gpointer data)2712 gboolean mono_font_filter (PangoFontFamily *family,
2713 PangoFontFace *face,
2714 gpointer data)
2715 {
2716 const char *facename = pango_font_face_get_face_name(face);
2717
2718 if (strstr(facename, "Italic") || strstr(facename, "Bold") ||
2719 strstr(facename, "Oblique")) {
2720 return FALSE;
2721 } else {
2722 return validate_single_font(family, FONT_FILTER_LATIN_MONO);
2723 }
2724 }
2725
close_font_chooser(GtkWidget * w,GtkFontChooser * fc)2726 static void close_font_chooser (GtkWidget *w, GtkFontChooser *fc)
2727 {
2728 gretl_font_filter_cleanup();
2729 gtk_widget_destroy(GTK_WIDGET(fc));
2730 }
2731
font_selection_ok(GtkWidget * w,GtkFontChooser * fc)2732 static void font_selection_ok (GtkWidget *w, GtkFontChooser *fc)
2733 {
2734 gchar *fontname = gtk_font_chooser_get_font(fc);
2735
2736 gtk_widget_hide(GTK_WIDGET(fc));
2737
2738 if (fontname != NULL && *fontname != '\0') {
2739 int mono = widget_get_int(fc, "mono");
2740
2741 if (mono) {
2742 set_fixed_font(fontname, 1);
2743 } else {
2744 set_app_font(fontname, 1);
2745 }
2746 write_rc(OPT_NONE);
2747 }
2748
2749 g_free(fontname);
2750 gretl_font_filter_cleanup();
2751 gtk_widget_destroy(GTK_WIDGET(fc));
2752 }
2753
font_selection_reset(GtkWidget * w,GtkFontChooser * fc)2754 static void font_selection_reset (GtkWidget *w, GtkFontChooser *fc)
2755 {
2756 int mono = widget_get_int(fc, "mono");
2757
2758 gtk_widget_hide(GTK_WIDGET(fc));
2759
2760 if (mono) {
2761 set_fixed_font(default_fixedfont, 1);
2762 } else {
2763 set_app_font(system_appfont, 1);
2764 }
2765 write_rc(OPT_NONE);
2766
2767 gretl_font_filter_cleanup();
2768 gtk_widget_destroy(GTK_WIDGET(fc));
2769 }
2770
chooser_font_selector(GtkAction * action)2771 static void chooser_font_selector (GtkAction *action)
2772 {
2773 static GtkWidget *fc = NULL;
2774 GtkFontFilterFunc filter;
2775 GtkWidget *hbox, *button;
2776 int which = fontsel_code(action);
2777 char *title = NULL;
2778 const char *fontname = NULL;
2779 int err = 0;
2780
2781 if (fc != NULL) {
2782 gtk_window_present(GTK_WINDOW(fc));
2783 return;
2784 }
2785
2786 if (which == FIXED_FONT_SELECTION) {
2787 title = _("Font for gretl output windows");
2788 filter = (GtkFontFilterFunc) &mono_font_filter;
2789 fontname = fixedfontname;
2790 } else if (which == APP_FONT_SELECTION) {
2791 title = _("Font for menus and labels");
2792 filter = (GtkFontFilterFunc) &latin_font_filter;
2793 fontname = appfontname;
2794 }
2795
2796 err = gretl_font_filter_init();
2797 if (err) {
2798 errbox("Failed to initialize font filter");
2799 return;
2800 }
2801
2802 fc = gtk_font_chooser_dialog_new(title, GTK_WINDOW(mdata->main));
2803 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(fc),
2804 fontname);
2805 gtk_font_chooser_set_filter_func(GTK_FONT_CHOOSER(fc),
2806 filter, NULL, NULL);
2807 gtk_window_set_position(GTK_WINDOW(fc), GTK_WIN_POS_MOUSE);
2808
2809 if (which == FIXED_FONT_SELECTION) {
2810 widget_set_int(fc, "mono", 1);
2811 }
2812
2813 g_signal_connect(G_OBJECT(fc), "destroy",
2814 G_CALLBACK(gtk_widget_destroyed),
2815 &fc);
2816
2817 button = gtk_dialog_get_widget_for_response(GTK_DIALOG(fc),
2818 GTK_RESPONSE_OK);
2819 if (button != NULL) {
2820 g_signal_connect(G_OBJECT(button), "clicked",
2821 G_CALLBACK(font_selection_ok),
2822 fc);
2823 }
2824
2825 button = gtk_dialog_get_widget_for_response(GTK_DIALOG(fc),
2826 GTK_RESPONSE_CANCEL);
2827 if (button != NULL) {
2828 g_signal_connect(G_OBJECT(button), "clicked",
2829 G_CALLBACK(close_font_chooser),
2830 fc);
2831 }
2832
2833 hbox = gtk_dialog_get_action_area(GTK_DIALOG(fc));
2834 button = gtk_button_new_with_label(_("Reset to default"));
2835 g_signal_connect(G_OBJECT(button), "clicked",
2836 G_CALLBACK(font_selection_reset), fc);
2837 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
2838 gtk_box_reorder_child(GTK_BOX(hbox), button, 0);
2839
2840 gtk_widget_show_all(fc);
2841 }
2842
2843 #else /* GTK, not using GtkFontChooser */
2844
font_selection_ok(GtkWidget * w,GtkFontselHackDialog * fs)2845 static void font_selection_ok (GtkWidget *w, GtkFontselHackDialog *fs)
2846 {
2847 gchar *fontname;
2848
2849 fontname = gtk_fontsel_hack_dialog_get_font_name(fs);
2850 gtk_widget_hide(GTK_WIDGET(fs));
2851
2852 if (fontname != NULL && *fontname != '\0') {
2853 int filter = gtk_fontsel_hack_dialog_get_filter(fs);
2854
2855 if (filter == FONT_HACK_LATIN_MONO) {
2856 set_fixed_font(fontname, 1);
2857 } else if (filter == FONT_HACK_LATIN) {
2858 set_app_font(fontname, 1);
2859 }
2860 write_rc(OPT_NONE);
2861 }
2862
2863 g_free(fontname);
2864 gtk_widget_destroy(GTK_WIDGET(fs));
2865 }
2866
font_selection_reset(GtkWidget * w,GtkFontselHackDialog * fs)2867 static void font_selection_reset (GtkWidget *w, GtkFontselHackDialog *fs)
2868 {
2869 int filter = gtk_fontsel_hack_dialog_get_filter(fs);
2870
2871 gtk_widget_hide(GTK_WIDGET(fs));
2872
2873 if (filter == FONT_HACK_LATIN_MONO) {
2874 set_fixed_font(default_fixedfont, 1);
2875 } else if (filter == FONT_HACK_LATIN) {
2876 set_app_font(system_appfont, 1);
2877 }
2878 write_rc(OPT_NONE);
2879
2880 gtk_widget_destroy(GTK_WIDGET(fs));
2881 }
2882
gtk2_font_selector(GtkAction * action)2883 static void gtk2_font_selector (GtkAction *action)
2884 {
2885 static GtkWidget *fontsel = NULL;
2886 GtkWidget *hbox, *button;
2887 int filter, which = fontsel_code(action);
2888 char *title = NULL;
2889 const char *fontname = NULL;
2890
2891 if (fontsel != NULL) {
2892 gtk_window_present(GTK_WINDOW(fontsel));
2893 return;
2894 }
2895
2896 if (which == FIXED_FONT_SELECTION) {
2897 title = _("Font for gretl output windows");
2898 filter = FONT_HACK_LATIN_MONO;
2899 fontname = fixedfontname;
2900 } else if (which == APP_FONT_SELECTION) {
2901 title = _("Font for menus and labels");
2902 filter = FONT_HACK_LATIN;
2903 fontname = appfontname;
2904 }
2905
2906 fontsel = gtk_fontsel_hack_dialog_new(title);
2907
2908 gtk_fontsel_hack_dialog_set_filter(GTK_FONTSEL_HACK_DIALOG(fontsel),
2909 filter);
2910 gtk_fontsel_hack_dialog_set_font_name(GTK_FONTSEL_HACK_DIALOG(fontsel),
2911 fontname);
2912
2913 gtk_window_set_position(GTK_WINDOW(fontsel), GTK_WIN_POS_MOUSE);
2914
2915 hbox = gtk_dialog_get_action_area(GTK_DIALOG(fontsel));
2916 button = gtk_button_new_with_label(_("Reset to default"));
2917 g_signal_connect(G_OBJECT(button), "clicked",
2918 G_CALLBACK(font_selection_reset),
2919 fontsel);
2920 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
2921 gtk_box_reorder_child(GTK_BOX(hbox), button, 0);
2922 gtk_widget_show(button);
2923 gtk_widget_show(hbox);
2924
2925 g_signal_connect(G_OBJECT(fontsel), "destroy",
2926 G_CALLBACK(gtk_widget_destroyed),
2927 &fontsel);
2928 g_signal_connect(G_OBJECT(gtk_fontsel_hack_dialog_ok_button(fontsel)),
2929 "clicked", G_CALLBACK(font_selection_ok),
2930 fontsel);
2931 g_signal_connect(G_OBJECT(gtk_fontsel_hack_dialog_cancel_button(fontsel)),
2932 "clicked", G_CALLBACK(delete_widget),
2933 fontsel);
2934
2935 gtk_widget_show(fontsel);
2936 }
2937
2938 #endif /* end font-selection dialog variants */
2939
font_selector(GtkAction * action)2940 void font_selector (GtkAction *action)
2941 {
2942 #if HAVE_GTK_FONT_CHOOSER
2943 chooser_font_selector(action);
2944 #else
2945 gtk2_font_selector(action);
2946 #endif
2947 }
2948
impose_font_scale(int scale,int remember)2949 static void impose_font_scale (int scale, int remember)
2950 {
2951 char fontname[64];
2952
2953 strcpy(fontname, fixedfontname);
2954 fontname_set_size(fontname, scale);
2955 set_fixed_font(fontname, remember);
2956
2957 #ifdef G_OS_WIN32
2958 if (*appfontname == '\0') {
2959 get_default_windows_app_font(appfontname);
2960 }
2961 #endif
2962
2963 strcpy(fontname, appfontname);
2964 fontname_set_size(fontname, scale);
2965 set_app_font(fontname, remember);
2966 }
2967
2968 #define FSCALE_DEFAULT 99
2969
set_fscale_default(GtkWidget * w,int * resp)2970 static void set_fscale_default (GtkWidget *w, int *resp)
2971 {
2972 GtkWidget *dlg = g_object_get_data(G_OBJECT(w), "dlg");
2973
2974 *resp = FSCALE_DEFAULT;
2975 gtk_widget_destroy(dlg);
2976 }
2977
font_scale_selector(GtkAction * action)2978 void font_scale_selector (GtkAction *action)
2979 {
2980 const char *opt = N_("Remember this setting");
2981 GtkWidget *dlg, *hbox, *button;
2982 int fscale = tmpfontscale;
2983 int remember = 0;
2984 int resp = GRETL_CANCEL;
2985
2986 if (fscale == 0) {
2987 fscale = fontname_get_size(fixedfontname);
2988 }
2989
2990 dlg = build_checks_dialog(_("gretl: font scale"), NULL,
2991 &opt,
2992 1, &remember,
2993 0, 0,
2994 0, NULL,
2995 &fscale, _("Scale for monospaced and menu fonts"),
2996 8, 24,
2997 0, mdata->main,
2998 &resp);
2999
3000 hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
3001 button = gtk_button_new_with_label(_("Reset to default"));
3002 g_object_set_data(G_OBJECT(button), "dlg", dlg);
3003 g_signal_connect(G_OBJECT(button), "clicked",
3004 G_CALLBACK(set_fscale_default), &resp);
3005 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
3006 gtk_box_reorder_child(GTK_BOX(hbox), button, 0);
3007
3008 gtk_widget_show_all(dlg);
3009
3010 if (resp == GRETL_CANCEL) {
3011 return;
3012 } else if (resp == FSCALE_DEFAULT) {
3013 set_fixed_font(default_fixedfont, 1);
3014 set_app_font(system_appfont, 1);
3015 write_rc(OPT_NONE);
3016 } else if (fscale > 0) {
3017 impose_font_scale(fscale, remember);
3018 tmpfontscale = fscale;
3019 }
3020 }
3021
update_persistent_graph_colors(void)3022 void update_persistent_graph_colors (void)
3023 {
3024 print_palette_string(gpcolors);
3025 }
3026
dump_rc(void)3027 void dump_rc (void)
3028 {
3029 char dumper[MAXLEN];
3030 const char *hname;
3031 GDir *test;
3032 FILE *fp;
3033 char *tmp;
3034 char val[6];
3035 int i;
3036
3037 sprintf(dumper, "%sconfig-dump.txt", gretl_workdir());
3038
3039 fp = gretl_fopen(dumper, "w");
3040 if (fp == NULL) {
3041 file_write_errbox(dumper);
3042 return;
3043 }
3044
3045 fprintf(fp, "gretl version %s\n", GRETL_VERSION);
3046 fprintf(fp, "built with GTK %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
3047 GTK_MICRO_VERSION);
3048
3049 tmp = getenv("HOME");
3050 if (tmp != NULL) {
3051 fprintf(fp, "HOME='%s'\n", tmp);
3052 } else {
3053 fputs("HOME not set\n", fp);
3054 }
3055
3056 for (i=0; rc_vars[i].var != NULL; i++) {
3057 fprintf(fp, "# %s\n", rc_vars[i].description);
3058 if (rc_vars[i].flags & BOOLSET) {
3059 boolvar_to_str(rc_vars[i].var, val);
3060 fprintf(fp, "%s = %s\n", rc_vars[i].key, val);
3061 } else if (rc_vars[i].flags & INTSET) {
3062 fprintf(fp, "%s = %d\n", rc_vars[i].key, *(int *) rc_vars[i].var);
3063 } else {
3064 fprintf(fp, "%s = %s\n", rc_vars[i].key, (char *) rc_vars[i].var);
3065 }
3066 }
3067
3068 hname = gretl_home();
3069 test = gretl_opendir(hname);
3070
3071 if (test != NULL) {
3072 fprintf(fp, "Directory '%s' exists, OK\n", hname);
3073 g_dir_close(test);
3074 } else {
3075 fprintf(fp, "Directory '%s' does not exist\n", hname);
3076 }
3077
3078 printf("Config info written to %s\n", dumper);
3079
3080 fclose(fp);
3081 }
3082
gui_set_working_dir(char * dirname)3083 int gui_set_working_dir (char *dirname)
3084 {
3085 int err = gretl_set_path_by_name("workdir", dirname);
3086
3087 if (err) {
3088 gui_errmsg(err);
3089 delete_from_filelist(FILE_LIST_WDIR, dirname);
3090 } else {
3091 mkfilelist(FILE_LIST_WDIR, dirname, 0);
3092 set_workdir_label();
3093 }
3094
3095 return err;
3096 }
3097
3098 struct wdir_setter {
3099 GtkWidget *dialog;
3100 GtkWidget *wdir_combo;
3101 GtkWidget *cwd_radio;
3102 GtkWidget *keep_radio;
3103 GtkWidget *ok_button;
3104 };
3105
3106 /* callback from the file selector */
3107
set_working_dir_callback(GtkWidget * w,char * path)3108 void set_working_dir_callback (GtkWidget *w, char *path)
3109 {
3110 set_combo_box_default_text(GTK_COMBO_BOX(w), path);
3111 }
3112
wdir_browse_callback(GtkWidget * w,struct wdir_setter * wset)3113 static void wdir_browse_callback (GtkWidget *w, struct wdir_setter *wset)
3114 {
3115 GtkWidget *combo = wset->wdir_combo;
3116
3117 file_selector_with_parent(SET_WDIR, FSEL_DATA_MISC, combo,
3118 wset->dialog);
3119 }
3120
open_wdir(GtkButton * b,gpointer p)3121 static void open_wdir (GtkButton *b, gpointer p)
3122 {
3123 #if defined(G_OS_WIN32)
3124 win32_open_file(gretl_workdir());
3125 #elif defined(OS_OSX)
3126 osx_open_file(gretl_workdir());
3127 #else
3128 gretl_fork("xdg-open", gretl_workdir(), NULL);
3129 #endif
3130 }
3131
3132 static void
add_wdir_content(GtkWidget * dialog,struct wdir_setter * wset)3133 add_wdir_content (GtkWidget *dialog, struct wdir_setter *wset)
3134 {
3135 GtkWidget *hbox, *vbox, *w = NULL;
3136 GtkWidget *entry;
3137 GSList *group = NULL;
3138 GList *list = NULL;
3139 gchar *deflt;
3140
3141 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
3142 list = get_working_dir_list();
3143
3144 hbox = gtk_hbox_new(FALSE, 5);
3145 w = gtk_label_new(_("Working directory:"));
3146 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3147
3148 deflt = g_strdup(gretl_workdir());
3149 trim_slash(deflt);
3150
3151 /* combo + browse button for current working dir */
3152 w = combo_box_text_new_with_entry();
3153 gtk_container_add(GTK_CONTAINER(hbox), w);
3154 set_combo_box_strings_from_list(w, list);
3155 if (deflt != NULL) {
3156 set_combo_box_default_text(GTK_COMBO_BOX(w), deflt);
3157 }
3158 entry = gtk_bin_get_child(GTK_BIN(w));
3159 gtk_entry_set_width_chars(GTK_ENTRY(entry), 32);
3160 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
3161 wset->wdir_combo = w;
3162 w = gtk_button_new_with_label(_("Browse..."));
3163 g_signal_connect(G_OBJECT(w), "clicked",
3164 G_CALLBACK(wdir_browse_callback), wset);
3165 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3166 gtk_box_pack_start(GTK_BOX(vbox), hbox, 0, 0, 5);
3167
3168 vbox_add_hsep(vbox);
3169
3170 hbox = gtk_hbox_new(FALSE, 5);
3171 w = gtk_label_new(_("On start-up, gretl should use:"));
3172 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3173 gtk_box_pack_start(GTK_BOX(vbox), hbox, 0, 0, 5);
3174
3175 /* radio 1 for "next time" */
3176 hbox = gtk_hbox_new(FALSE, 5);
3177 w = gtk_radio_button_new_with_label(group,
3178 _("the directory selected above"));
3179 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(w));
3180 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3181 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3182
3183 /* radio 2 for "next time" */
3184 hbox = gtk_hbox_new(FALSE, 5);
3185 w = gtk_radio_button_new_with_label(group, _("the current directory "
3186 "as determined via the shell"));
3187 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), usecwd);
3188 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3189 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3190 wset->cwd_radio = w;
3191
3192 vbox_add_hsep(vbox);
3193
3194 hbox = gtk_hbox_new(FALSE, 5);
3195 w = gtk_label_new(_("The file selection dialog should:"));
3196 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3197 gtk_box_pack_start(GTK_BOX(vbox), hbox, 0, 0, 5);
3198
3199 /* radio 1 for "remember folder" */
3200 hbox = gtk_hbox_new(FALSE, 5);
3201 w = gtk_radio_button_new_with_label(NULL,
3202 _("remember the last-opened folder"));
3203 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(w));
3204 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3205 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3206 wset->keep_radio = w;
3207
3208 /* radio 2 for "remember folder" */
3209 hbox = gtk_hbox_new(FALSE, 5);
3210 w = gtk_radio_button_new_with_label(group, _("always start in the "
3211 "working directory"));
3212 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), !keep_folder);
3213 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3214 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3215
3216 /* button to open working directory via OS */
3217 vbox_add_hsep(vbox);
3218 hbox = gtk_hbox_new(FALSE, 5);
3219 w = gtk_button_new_with_label(_("Open working directory"));
3220 gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5);
3221 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3222 g_signal_connect(w, "clicked", G_CALLBACK(open_wdir), NULL);
3223
3224 g_list_free(list);
3225 g_free(deflt);
3226 }
3227
3228 static void
apply_wdir_changes(GtkWidget * w,struct wdir_setter * wset)3229 apply_wdir_changes (GtkWidget *w, struct wdir_setter *wset)
3230 {
3231 char tmp[MAXLEN];
3232 gchar *str;
3233 int err;
3234
3235 str = combo_box_get_active_text(GTK_COMBO_BOX(wset->wdir_combo));
3236 *tmp = '\0';
3237 if (str != NULL) {
3238 strncat(tmp, str, MAXLEN - 2);
3239 g_free(str);
3240 }
3241
3242 err = gretl_set_path_by_name("workdir", tmp);
3243
3244 if (err) {
3245 gui_errmsg(err);
3246 delete_from_filelist(FILE_LIST_WDIR, tmp);
3247 } else {
3248 /* sync with "local copy" */
3249 strcpy(paths.workdir, gretl_workdir());
3250 mkfilelist(FILE_LIST_WDIR, tmp, 0);
3251 }
3252
3253 usecwd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wset->cwd_radio));
3254 keep_folder = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wset->keep_radio));
3255
3256 if (!err) {
3257 if (w == wset->ok_button) {
3258 gtk_widget_destroy(wset->dialog);
3259 }
3260 set_workdir_label();
3261 }
3262 }
3263
workdir_dialog(int from_wlabel)3264 static void workdir_dialog (int from_wlabel)
3265 {
3266 static GtkWidget *dialog;
3267 struct wdir_setter wset;
3268 GtkWidget *button;
3269 GtkWidget *hbox, *vbox;
3270
3271 if (dialog != NULL) {
3272 gtk_window_present(GTK_WINDOW(dialog));
3273 return;
3274 }
3275
3276 dialog = gretl_dialog_new(_("gretl: working directory"),
3277 mdata->main, GRETL_DLG_BLOCK | GRETL_DLG_RESIZE);
3278
3279 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
3280 gtk_box_set_spacing(GTK_BOX(vbox), 5);
3281 g_signal_connect(G_OBJECT(dialog), "destroy",
3282 G_CALLBACK(gtk_widget_destroyed),
3283 &dialog);
3284
3285 wset.dialog = dialog;
3286 add_wdir_content(dialog, &wset);
3287
3288 hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
3289
3290 button = apply_button(hbox);
3291 g_signal_connect(G_OBJECT(button), "clicked",
3292 G_CALLBACK(apply_wdir_changes), &wset);
3293
3294 button = cancel_button(hbox);
3295 g_signal_connect(G_OBJECT(button), "clicked",
3296 G_CALLBACK(delete_widget),
3297 dialog);
3298
3299 wset.ok_button = button = ok_button(hbox);
3300 gtk_widget_grab_default(button);
3301 g_signal_connect(G_OBJECT(button), "clicked",
3302 G_CALLBACK(apply_wdir_changes), &wset);
3303
3304 context_help_button(hbox, WORKDIR);
3305
3306 gtk_widget_show_all(dialog);
3307 }
3308
workdir_dialog0(void)3309 void workdir_dialog0 (void)
3310 {
3311 workdir_dialog(0);
3312 }
3313
workdir_dialog1(void)3314 void workdir_dialog1 (void)
3315 {
3316 workdir_dialog(1);
3317 }
3318
3319 #if defined(MAC_THEMING)
3320
set_up_mac_look(void)3321 void set_up_mac_look (void)
3322 {
3323 if (!strcmp(themepref, "Adwaita") ||
3324 !strcmp(themepref, "Clearlooks") ||
3325 !strcmp(themepref, "Lion-like")) {
3326 char *topdir = getenv("GTK_DATA_PREFIX");
3327 gchar *gtkrc;
3328
3329 if (topdir != NULL) {
3330 gtkrc = g_strdup_printf("%s/share/themes/%s/gtk-2.0/gtkrc",
3331 topdir, themepref);
3332 gtk_rc_parse(gtkrc);
3333 g_free(gtkrc);
3334 } else {
3335 #if defined(GTK_PREFIX)
3336 /* go with the build-time prefix */
3337 gtkrc = g_strdup_printf("%s/share/themes/%s/gtk-2.0/gtkrc",
3338 GTK_PREFIX, themepref);
3339 #else
3340 /* hard-wired? */
3341 const char *path = "/Library/Frameworks/gretl-dev.framework/Resources";
3342
3343 gtkrc = g_strdup_printf("%s/share/themes/%s/gtk-2.0/gtkrc",
3344 path, themepref);
3345 #endif
3346 gtk_rc_parse(gtkrc);
3347 g_free(gtkrc);
3348 }
3349 }
3350 }
3351
3352 #elif defined (G_OS_WIN32) && GTK_MAJOR_VERSION < 3
3353
set_up_windows_look(void)3354 void set_up_windows_look (void)
3355 {
3356 if (!strcmp(themepref, "Windows-10") ||
3357 !strcmp(themepref, "MS-Windows") ||
3358 !strcmp(themepref, "Clearlooks")) {
3359 const char *prefix;
3360 char sl[2] = {0};
3361 gchar *gtkrc;
3362 size_t n;
3363 int needslash;
3364
3365 # ifdef PKGBUILD
3366 prefix = gretl_home();
3367 # else
3368 prefix = GTK_PREFIX; /* defined at build-time */
3369 # endif
3370 n = strlen(prefix);
3371 needslash = (prefix[n-1] != '\\' && prefix[n-1] != '/');
3372 sl[0] = strchr(prefix, '/') ? '/' : '\\';
3373 gtkrc = g_strdup_printf("%s%sshare%sthemes%s%s%sgtk-2.0%sgtkrc",
3374 prefix, (needslash)? sl : "", sl, sl,
3375 themepref, sl, sl);
3376 fprintf(stderr, "gtkrc = '%s'\n", gtkrc);
3377 gtk_rc_parse(gtkrc);
3378 g_free(gtkrc);
3379 } else {
3380 GtkSettings *settings = gtk_settings_get_default();
3381
3382 g_object_set(G_OBJECT(settings), "gtk-theme-name", "Raleigh", NULL);
3383 }
3384 }
3385
set_wimp_preferred(int s)3386 void set_wimp_preferred (int s)
3387 {
3388 if (s) {
3389 strcpy(themepref, "Windows-10");
3390 } else {
3391 strcpy(themepref, "Clearlooks");
3392 }
3393 }
3394
3395 #elif defined (G_OS_WIN32) && GTK_MAJOR_VERSION == 3
3396
set_up_windows_look(void)3397 void set_up_windows_look (void)
3398 {
3399 GtkSettings *settings = gtk_settings_get_default();
3400 char theme_name[16];
3401
3402 if (!strcmp(themepref, "Windows 10")) {
3403 strcpy(theme_name, "Windows-10");
3404 } else if (!strcmp(themepref, "Windows 7")) {
3405 strcpy(theme_name, "win32");
3406 } else {
3407 strcpy(theme_name, themepref);
3408 }
3409
3410 g_object_set(G_OBJECT(settings), "gtk-theme-name", theme_name, NULL);
3411 }
3412
3413 #endif
3414