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 /* gretl.c : main for gretl */
21
22 #include "gretl.h"
23 #include "gretl_func.h"
24 #include "gretl_xml.h"
25 #include "libset.h"
26 #include "uservar.h"
27
28 #include "treeutils.h"
29 #include "ssheet.h"
30 #include "console.h"
31 #include "session.h"
32 #include "database.h"
33 #include "datafiles.h"
34 #include "cmdstack.h"
35 #include "filelists.h"
36 #include "toolbar.h"
37 #include "menustate.h"
38 #include "fileselect.h"
39 #include "filters.h"
40 #include "calculator.h"
41 #include "fnsave.h"
42 #include "winstack.h"
43 #include "datawiz.h"
44 #include "varinfo.h"
45 #include "dlgutils.h"
46 #include "fncall.h"
47 #include "selector.h"
48 #include "guiprint.h"
49 #include "tabwin.h"
50 #include "gpt_control.h"
51 #include "gretl_ipc.h"
52
53 #ifndef G_OS_WIN32
54 # include <unistd.h>
55 # include <sys/types.h>
56 # include "../pixmaps/gretl.xpm" /* program icon for X */
57 #else
58 # include <windows.h>
59 # include "gretlwin32.h"
60 #endif
61
62 #ifdef MAC_INTEGRATION
63 # include <gtkosxapplication.h>
64 #endif
65
66 #define GUI_DEBUG 0
67 #define WIN32_DEBUG 0
68
69 #if GUI_DEBUG
70 # include "version.h"
71 # include "build.h"
72 #endif
73
74 #if defined(OS_OSX) && defined(PKGBUILD)
75 # define ALT_MAC_STARTUP
76 #endif
77
78 /* update.c */
79 extern int update_query (void);
80
81 /* functions private to gretl.c */
82 static void make_main_window (void);
83
84 static gboolean main_popup_handler (GtkWidget *w, GdkEventButton *event,
85 gpointer data);
86 static GtkWidget *make_main_menu (void);
87 static void start_R_callback (void);
88 static void auto_store (void);
89 static void restore_sample_callback (void);
90 static void show_sample_callback (void);
91 static void mdata_select_all (void);
92 static void mdata_select_list (void);
93 static int gui_query_stop (void);
94 static void mdata_handle_paste (void);
95
96 #ifdef MAC_INTEGRATION
97 static GtkUIManager *add_mac_menu (void);
98 static void finish_mac_ui (GtkUIManager *mgr);
99 #endif
100
101 GtkTargetEntry gretl_drag_targets[] = {
102 { "text/uri-list", 0, GRETL_FILENAME },
103 { "db_series_ptr", GTK_TARGET_SAME_APP, GRETL_DBSERIES_PTR },
104 { "model_ptr", GTK_TARGET_SAME_APP, GRETL_MODEL_PTR },
105 { "remote_db_ptr", GTK_TARGET_SAME_APP, GRETL_REMOTE_DB_PTR },
106 { "remote_pkg_ptr", GTK_TARGET_SAME_APP, GRETL_REMOTE_FNPKG_PTR },
107 { "graph_file", GTK_TARGET_SAME_APP, GRETL_GRAPH_FILE }
108 };
109
110 static void
111 mdata_handle_drag (GtkWidget *widget,
112 GdkDragContext *dc,
113 gint x,
114 gint y,
115 GtkSelectionData *data,
116 guint info,
117 guint time,
118 gpointer p);
119
120 static char *optdb, *optwebdb, *optpkg;
121 static int optrun, opteng, optbasque, optdump, optver;
122 #ifdef G_OS_WIN32
123 static int optdebug;
124 #endif
125 #ifdef GRETL_OPEN_HANDLER
126 static int optnew;
127 static int optsingle;
128 #endif
129
130 static gchar *param_msg =
131 N_("\nYou may supply the name of a data or script file on the command line");
132
133 static GOptionEntry options[] = {
134 { "run", 'r', 0, G_OPTION_ARG_NONE, &optrun,
135 N_("open a script file on startup"), NULL },
136 { "db", 'd', 0, G_OPTION_ARG_STRING, &optdb,
137 N_("open a database on startup"), "DATABASE" },
138 { "webdb", 'w', 0, G_OPTION_ARG_STRING, &optwebdb,
139 N_("open a remote (web) database on startup"), "REMOTE_DB" },
140 { "pkg", 'p', 0, G_OPTION_ARG_STRING, &optpkg,
141 N_("open (edit) a function package on startup"), "FUNCPKG" },
142 { "english", 'e', 0, G_OPTION_ARG_NONE, &opteng,
143 N_("force use of English"), NULL },
144 { "basque", 'q', 0, G_OPTION_ARG_NONE, &optbasque,
145 N_("force use of Basque"), NULL },
146 { "dump", 'c', 0, G_OPTION_ARG_NONE, &optdump,
147 N_("dump gretl configuration to file"), NULL },
148 #ifdef G_OS_WIN32
149 { "debug", 'b', 0, G_OPTION_ARG_NONE, &optdebug,
150 N_("send debugging info to console"), NULL },
151 #endif
152 { "version", 'v', 0, G_OPTION_ARG_NONE, &optver,
153 N_("print version information"), NULL },
154 #ifdef GRETL_OPEN_HANDLER
155 { "new", 'n', 0, G_OPTION_ARG_NONE, &optnew,
156 N_("start a new gretl instance unconditionally"), NULL },
157 { "single", 's', 0, G_OPTION_ARG_NONE, &optsingle,
158 N_("reuse an existing gretl instance unconditionally"), NULL },
159 #endif
160 { NULL, '\0', 0, 0, NULL, NULL, NULL },
161 };
162
163 windata_t *mdata;
164 DATASET *dataset;
165 MODEL *model;
166
167 char datafile[MAXLEN];
168 char scriptfile[MAXLEN];
169
170 int data_status, orig_vars;
171 float gui_scale;
172
173 /* defaults for some options */
174 int winsize = FALSE;
175 int main_x = -1;
176 int main_y = -1;
177 int mainwin_width = 520;
178 int mainwin_height = 420;
179
180 #if defined(G_OS_WIN32)
181 char calculator[MAXSTR] = "calc.exe";
182 char latex[MAXSTR] = "pdflatex.exe";
183 char Rcommand[MAXSTR] = "RGui.exe";
184 #elif defined(OS_OSX)
185 char calculator[MAXSTR] = "/Applications/Calculator.app/Contents/MacOS/Calculator";
186 char latex[MAXSTR] = "pdflatex";
187 char Rcommand[MAXSTR] = "/Applications/R.app/Contents/MacOS/R";
188 #else
189 char Browser[MAXSTR] = "mozilla";
190 char calculator[MAXSTR] = "xcalc";
191 char latex[MAXSTR] = "pdflatex";
192 char viewpdf[MAXSTR] = "acroread";
193 char viewps[MAXSTR] = "gv";
194 char Rcommand[MAXSTR] = "xterm -e R";
195 #endif
196
197 static char tryfile[MAXLEN];
198
set_tryfile(const char * fname)199 void set_tryfile (const char *fname)
200 {
201 tryfile[0] = '\0';
202 strncat(tryfile, fname, MAXLEN - 1);
203 }
204
get_tryfile(void)205 char *get_tryfile (void)
206 {
207 return tryfile;
208 }
209
clear_tryfile(void)210 void clear_tryfile (void)
211 {
212 tryfile[0] = '\0';
213 }
214
tryfile_is_set(void)215 int tryfile_is_set (void)
216 {
217 return tryfile[0] != '\0';
218 }
219
spreadsheet_edit(void)220 static void spreadsheet_edit (void)
221 {
222 show_spreadsheet(SHEET_EDIT_VARLIST);
223 }
224
varinfo_callback(void)225 static void varinfo_callback (void)
226 {
227 varinfo_dialog(mdata->active_var);
228 }
229
tdisagg_callback(void)230 static void tdisagg_callback (void)
231 {
232 tdisagg_dialog(mdata->active_var);
233 }
234
bds_callback(void)235 static void bds_callback (void)
236 {
237 bdstest_dialog(mdata->active_var, NULL);
238 }
239
prefs_dialog_callback(void)240 static void prefs_dialog_callback (void)
241 {
242 preferences_dialog(0, NULL, mdata->main);
243 }
244
open_script_callback(void)245 static void open_script_callback (void)
246 {
247 file_selector(OPEN_SCRIPT, FSEL_DATA_NONE, NULL);
248 }
249
open_session_callback(void)250 static void open_session_callback (void)
251 {
252 file_selector(OPEN_SESSION, FSEL_DATA_NONE, NULL);
253 }
254
edit_spec_callback(GtkAction * action,gpointer p)255 static void edit_spec_callback (GtkAction *action, gpointer p)
256 {
257 file_selector(OPEN_SPEC, FSEL_DATA_NONE, NULL);
258 }
259
upload_package_callback(GtkAction * action,gpointer p)260 static void upload_package_callback (GtkAction *action, gpointer p)
261 {
262 file_selector(UPLOAD_PKG, FSEL_DATA_NONE, NULL);
263 }
264
new_matrix_callback(GtkAction * action,gpointer p)265 static void new_matrix_callback (GtkAction *action, gpointer p)
266 {
267 gui_new_matrix(mdata->main);
268 }
269
pc_change_callback(GtkAction * action,gpointer p)270 static void pc_change_callback (GtkAction *action, gpointer p)
271 {
272 const char *s = gtk_action_get_name(action);
273 int idxvals = !strcmp(s, "idxvals");
274
275 if (mdata_selection_count() == 1) {
276 single_percent_change_dialog(mdata->active_var, idxvals);
277 } else {
278 multi_percent_change_dialog(idxvals);
279 }
280 }
281
new_gfn_callback(GtkAction * action,gpointer p)282 static void new_gfn_callback (GtkAction *action, gpointer p)
283 {
284 start_new_function_package(NULL, p);
285 }
286
email_data(gpointer p,guint u,GtkWidget * w)287 static void email_data (gpointer p, guint u, GtkWidget *w)
288 {
289 char gdttmp[FILENAME_MAX];
290 char *title = NULL;
291 int err;
292
293 /* We need to handle the cases where (a) we have unsaved
294 data or (b) the dataset is saved as a binary file. To
295 do this we write out a temporary copy of the current
296 dataset (gzipped XML).
297 */
298
299 if (*datafile != '\0') {
300 const char *base = path_last_element(datafile);
301 int len = strcspn(base, ".");
302
303 if (len > 0) {
304 title = g_strndup(base, len);
305 }
306 }
307
308 if (title == NULL) {
309 sprintf(gdttmp, "%suntitled.gdt", gretl_dotdir());
310 } else {
311 sprintf(gdttmp, "%s%s.gdt", gretl_dotdir(), title);
312 g_free(title);
313 }
314
315 err = gretl_write_gdt(gdttmp, NULL, dataset, OPT_Z, 0);
316 if (!err) {
317 send_attachment(gdttmp);
318 }
319 gretl_remove(gdttmp);
320 }
321
noalloc(void)322 static void noalloc (void)
323 {
324 fputs("Out of memory!\n", stderr);
325 exit(EXIT_FAILURE);
326 }
327
script_type(const char * fname)328 static int script_type (const char *fname)
329 {
330 if (has_suffix(fname, ".inp")) {
331 return EDIT_HANSL;
332 } else if (has_suffix(fname, ".R")) {
333 return EDIT_R;
334 } else if (has_suffix(fname, ".plt") ||
335 has_suffix(fname, ".gp")) {
336 return EDIT_GP;
337 } else if (has_suffix(fname, ".ox")) {
338 return EDIT_OX;
339 } else if (has_suffix(fname, ".m")) {
340 return EDIT_OCTAVE;
341 } else if (has_suffix(fname, ".py")) {
342 return EDIT_PYTHON;
343 } else if (has_suffix(fname, ".jl")) {
344 return EDIT_JULIA;
345 } else if (has_suffix(fname, ".do")) {
346 return EDIT_STATA;
347 } else if (has_suffix(fname, ".mod")) {
348 return EDIT_DYNARE;
349 } else if (has_suffix(fname, ".lp")) {
350 return EDIT_LPSOLVE;
351 } else {
352 return 0;
353 }
354 }
355
maybe_fix_dbname(char * dbname)356 static void maybe_fix_dbname (char *dbname)
357 {
358 int err;
359
360 if (strstr(dbname, ".bin") == NULL &&
361 strstr(dbname, ".rat") == NULL &&
362 strstr(dbname, ".RAT") == NULL &&
363 strstr(dbname, ".bn7") == NULL) {
364 strcat(dbname, ".bin");
365 }
366
367 err = gretl_test_fopen(dbname, "rb");
368
369 if (err && !g_path_is_absolute(dbname)) {
370 gchar *tmp = g_build_filename(gretl_home(), "db",
371 dbname, NULL);
372
373 err = gretl_test_fopen(tmp, "rb");
374 if (!err) {
375 strcpy(dbname, tmp);
376 }
377 g_free(tmp);
378 }
379 }
380
381 #if !defined(ENABLE_NLS)
382
real_nls_init(void)383 static void real_nls_init (void)
384 {
385 return;
386 }
387
388 #elif defined(G_OS_WIN32) && defined(PKGBUILD)
389
real_nls_init(void)390 static void real_nls_init (void)
391 {
392 char localedir[MAXSTR];
393
394 gretl_build_path(localedir, gretl_home(), "locale", NULL);
395 record_win32_locale(setlocale(LC_ALL, ""));
396 bindtextdomain(PACKAGE, localedir);
397 textdomain(PACKAGE);
398 bind_textdomain_codeset(PACKAGE, "UTF-8");
399 }
400
401 #elif defined(OS_OSX)
402
403 #define LOCALE_CHECK 1
404
405 #if LOCALE_CHECK
406
407 #include <CoreFoundation/CoreFoundation.h>
408
409 /* Use this to check what we get from setlocale() ? */
410
macos_check_locale(void)411 static void macos_check_locale (void)
412 {
413 CFLocaleRef cfloc = CFLocaleCopyCurrent();
414 CFStringRef cfprop;
415 const char *s;
416
417 cfprop = (CFStringRef) CFLocaleGetValue(cfloc, kCFLocaleIdentifier);
418 s = CFStringGetCStringPtr(cfprop, kCFStringEncodingASCII);
419 if (s != NULL) {
420 fprintf(stderr, "macos_check_locale: CF gave ID '%s'\n", s);
421 }
422
423 CFRelease(cfloc);
424 }
425
426 #endif /* LOCALE_CHECK */
427
real_nls_init(void)428 static void real_nls_init (void)
429 {
430 char *gretlhome = getenv("GRETL_HOME");
431 char localedir[MAXSTR];
432 char *p;
433
434 if (gretlhome == NULL) {
435 return;
436 }
437
438 strcpy(localedir, gretlhome);
439 p = strstr(localedir, "share/gretl");
440 if (p != NULL) {
441 strcpy(p, "share/locale");
442 }
443
444 p = setlocale(LC_ALL, "");
445 fprintf(stderr, "NLS init: setlocale() gave '%s'\n", p);
446 #if LOCALE_CHECK
447 macos_check_locale();
448 #endif
449 bindtextdomain(PACKAGE, localedir);
450 textdomain(PACKAGE);
451 bind_textdomain_codeset(PACKAGE, "UTF-8");
452 }
453
454 #else /* end OS X specific code */
455
456 /* regular *nix treatment of NLS -- also applies
457 for non-package MSYS2 build on Windows */
458
real_nls_init(void)459 static void real_nls_init (void)
460 {
461 setlocale(LC_ALL, "");
462 bindtextdomain(PACKAGE, LOCALEDIR);
463 textdomain(PACKAGE);
464 bind_textdomain_codeset(PACKAGE, "UTF-8");
465 }
466
467 #endif /* NLS init variants */
468
gui_nls_init(void)469 void gui_nls_init (void)
470 {
471 char *mylang = getenv("GRETL_LANG");
472
473 if (mylang != NULL) {
474 if (!g_ascii_strcasecmp(mylang, "english") ||
475 !g_ascii_strcasecmp(mylang, "C")) {
476 /* don't set up translation */
477 return;
478 }
479 }
480
481 real_nls_init();
482 }
483
record_filearg(char * targ,const char * src)484 static void record_filearg (char *targ, const char *src)
485 {
486 if (*src == '.') {
487 gchar *cdir = g_get_current_dir();
488 gchar *tmp = g_build_filename(cdir, src, NULL);
489
490 strcpy(targ, tmp);
491 g_free(cdir);
492 g_free(tmp);
493 } else {
494 strcpy(targ, src);
495 }
496 }
497
498 #if !defined(G_OS_WIN32) && GTK_MAJOR_VERSION == 3
499
500 /* cut out annoying runtime spew from GLib-GObject
501 warning about deprecated stuff
502 */
503
logtrap(const gchar * domain,GLogLevelFlags level,const gchar * msg,gpointer p)504 static void logtrap (const gchar *domain,
505 GLogLevelFlags level,
506 const gchar *msg,
507 gpointer p)
508 {
509 if (strstr(msg, "deprecat") == NULL) {
510 g_log_default_handler(domain, level, msg, p);
511 }
512 }
513
quell_glib_spew(void)514 static void quell_glib_spew (void)
515 {
516 g_log_set_handler("GLib-GObject", G_LOG_LEVEL_WARNING,
517 (GLogFunc) logtrap, NULL);
518 }
519
520 #endif
521
522 #ifdef MAC_INTEGRATION
523
524 static GtkosxApplication *MacApp;
525
app_should_quit_cb(GtkosxApplication * App,gpointer p)526 static gboolean app_should_quit_cb (GtkosxApplication *App, gpointer p)
527 {
528 /* return exit_check(); */
529 return FALSE;
530 }
531
app_will_quit_cb(GtkosxApplication * App,gpointer p)532 static void app_will_quit_cb (GtkosxApplication *App, gpointer p)
533 {
534 gtk_main_quit();
535 }
536
app_open_file_cb(GtkosxApplication * app,gchar * path,gpointer p)537 static gboolean app_open_file_cb (GtkosxApplication *app,
538 gchar *path, gpointer p)
539 {
540 if (path != NULL) {
541 if (!strcmp(tryfile, path)) {
542 /* we're already on it? */
543 return TRUE;
544 }
545 set_tryfile(path);
546 return open_tryfile();
547 } else {
548 clear_tryfile();
549 return TRUE;
550 }
551 }
552
install_mac_signals(GtkosxApplication * App)553 static void install_mac_signals (GtkosxApplication *App)
554 {
555 g_signal_connect(App, "NSApplicationBlockTermination",
556 G_CALLBACK(app_should_quit_cb), NULL);
557 g_signal_connect(App, "NSApplicationWillTerminate",
558 G_CALLBACK(app_will_quit_cb), NULL);
559 g_signal_connect(App, "NSApplicationOpenFile",
560 G_CALLBACK(app_open_file_cb), NULL);
561 }
562
563 #endif /* MAC_INTEGRATION */
564
565 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
566
protect_against_ubuntu(void)567 static void protect_against_ubuntu (void)
568 {
569 FILE *fp = fopen("/etc/os-release", "r");
570
571 if (fp != NULL) {
572 char line[80];
573
574 while (fgets(line, sizeof line, fp)) {
575 if (strstr(line, "buntu")) {
576 setenv("UBUNTU_MENUPROXY", "0", 1);
577 break;
578 }
579 }
580 fclose(fp);
581 }
582 }
583
584 #endif /* end Linux-specific */
585
586 /* callback from within potentially lengthy libgretl
587 operations: try to avoid having the GUI become
588 totally unresponsive
589 */
590
gui_show_activity(void)591 static void gui_show_activity (void)
592 {
593 while (gtk_events_pending()) {
594 gtk_main_iteration();
595 }
596 }
597
598 #ifdef GRETL_OPEN_HANDLER
599
absolutize_path(const char * fname)600 static gchar *absolutize_path (const char *fname)
601 {
602 gchar *ret;
603
604 if (*fname == '\0' || *fname == '~' || g_path_is_absolute(fname)) {
605 ret = g_strdup(fname);
606 } else {
607 gchar *dirname = g_get_current_dir();
608
609 ret = g_build_filename(dirname, fname, NULL);
610 g_free(dirname);
611 }
612
613 return ret;
614 }
615
maybe_hand_off(char * filearg,char * auxname)616 static gboolean maybe_hand_off (char *filearg, char *auxname)
617 {
618 long gpid = gretl_prior_instance();
619 gboolean ret = FALSE;
620
621 /* Is there an already-running gretl instance? If so
622 we'll ask whether or not to start a new instance,
623 unless we got @optsingle, which says to reuse the
624 existing one.
625 */
626
627 if (gpid > 0) {
628 gint resp = GRETL_NO;
629
630 if (!optsingle) {
631 resp = no_yes_dialog("gretl", _("Start a new gretl instance?"));
632 }
633
634 if (resp != GRETL_YES) {
635 /* try hand-off to prior gretl instance */
636 char *fname = filearg;
637 gchar *abspath;
638
639 if (*fname == '\0') {
640 fname = tryfile_is_set() ? tryfile : auxname;
641 }
642 abspath = absolutize_path(fname);
643 ret = forward_open_request(gpid, abspath);
644 g_free(abspath);
645 }
646 }
647
648 return ret;
649 }
650
651 #endif /* GRETL_OPEN_HANDLER */
652
653 #ifdef G_OS_WIN32
654
655 /* The point of the following special code: when gretl is
656 invoked by the OS (via double-click on a file associated
657 with gretl in the registry) the command-line may contain
658 a "mixed language" filename that is not representable in
659 the locale Code Page. Such a filename will appear in
660 mangled form in the argv array, and we need to call on
661 Windows APIs to get a UTF-16 version of this array.
662 */
663
alt_gtk_init(int * pargc,char *** pargv,char * filearg,GError ** popterr)664 static void alt_gtk_init (int *pargc,
665 char ***pargv,
666 char *filearg,
667 GError **popterr)
668 {
669 int argc_w = 0;
670 int initted = 0;
671 LPWSTR *argv_w;
672
673 /* get args as UTF-16 */
674 argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
675
676 if (argv_w != NULL) {
677 gchar **argv_u8 = calloc(argc_w, sizeof *argv_u8);
678 gchar **origp = argv_u8; /* for use with g_free */
679 int n_u8 = argc_w;
680 int i, uerr = 0;
681
682 /* for GTK, convert args to UTF-8 */
683 for (i=0; i<argc_w && !uerr; i++) {
684 argv_u8[i] = g_utf16_to_utf8(argv_w[i], -1, NULL, NULL, NULL);
685 if (argv_u8[i] == NULL) {
686 uerr = 1;
687 }
688 }
689 if (!uerr) {
690 gtk_init_with_args(&argc_w, &argv_u8, _(param_msg),
691 options, "gretl", popterr);
692 if (argc_w > 1 && *filearg == '\0') {
693 strncat(filearg, argv_u8[1], MAXLEN - 1);
694 }
695 *pargc = argc_w; /* update (residual) arg count */
696 initted = 1;
697 }
698 /* clean up */
699 for (i=0; i<n_u8; i++) {
700 g_free(origp[i]);
701 }
702 g_free(origp);
703 LocalFree(argv_w);
704 }
705
706 if (!initted) {
707 /* try fallback? */
708 gtk_init_with_args(pargc, pargv, _(param_msg), options,
709 "gretl", popterr);
710 }
711 }
712
713 #endif /* G_OS_WIN32 */
714
715 #ifdef ALT_MAC_STARTUP
716
717 #include "osx_env.c"
718
719 #endif /* specific to Mac package */
720
have_data(void)721 static int have_data (void)
722 {
723 return dataset != NULL && dataset->v > 0;
724 }
725
main(int argc,char ** argv)726 int main (int argc, char **argv)
727 {
728 char auxname[MAXLEN];
729 char filearg[MAXLEN];
730 GError *opterr = NULL;
731
732 #if defined(G_OS_WIN32)
733 /* this must come before NLS initialization */
734 win32_set_gretldir();
735 #elif defined(ALT_MAC_STARTUP)
736 osx_setup_paths();
737 #elif !defined(OS_OSX)
738 /* Linux-specific */
739 protect_against_ubuntu();
740 #endif
741
742 gui_nls_init();
743
744 *tryfile = '\0';
745 *scriptfile = '\0';
746 *datafile = '\0';
747 *auxname = '\0';
748 *filearg = '\0';
749
750 #if GUI_DEBUG
751 fprintf(stderr, "starting gretl %s, build date %s\n", GRETL_VERSION,
752 BUILD_DATE);
753 #endif
754
755 #ifdef G_OS_WIN32
756 alt_gtk_init(&argc, &argv, filearg, &opterr);
757 #else
758 gtk_init_with_args(&argc, &argv, _(param_msg), options, "gretl", &opterr);
759 #endif
760 if (opterr != NULL) {
761 g_print("%s\n", opterr->message);
762 exit(EXIT_FAILURE);
763 }
764
765 #ifdef MAC_INTEGRATION
766 MacApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
767 install_mac_signals(MacApp);
768 gtkosx_application_set_use_quartz_accelerators(MacApp, FALSE);
769 #endif
770
771 #ifdef G_OS_WIN32
772 /* let's call this before doing libgretl_init */
773 # if WIN32_DEBUG
774 gretl_win32_debug_init(1);
775 # else
776 gretl_win32_debug_init(optdebug);
777 # endif
778 #elif GTK_MAJOR_VERSION == 3
779 quell_glib_spew();
780 #endif
781
782 libgretl_init();
783 gretl_set_gui_mode();
784
785 #ifdef G_OS_WIN32
786 gretl_win32_init(optdebug);
787 #else
788 gretl_config_init();
789 #endif
790
791 if (optver) {
792 gui_logo(NULL);
793 exit(EXIT_SUCCESS);
794 } else if (optdump) {
795 dump_rc();
796 exit(EXIT_SUCCESS);
797 } else if (optdb != NULL) {
798 strncat(auxname, optdb, MAXLEN - 1);
799 maybe_fix_dbname(auxname);
800 } else if (optwebdb != NULL) {
801 strncat(auxname, optwebdb, MAXLEN - 1);
802 } else if (optpkg != NULL) {
803 strncat(auxname, optpkg, MAXLEN - 1);
804 }
805
806 if (opteng) {
807 force_language(LANG_C);
808 force_english_help();
809 } else if (optbasque) {
810 force_language(LANG_EU);
811 }
812
813 #if GUI_DEBUG
814 fprintf(stderr, "finished option processing\n");
815 #endif
816
817 /* set libgretl callbacks */
818 set_workdir_callback(gui_set_working_dir);
819 set_show_activity_func(gui_show_activity);
820 set_query_stop_func(gui_query_stop);
821 set_gui_model_list_callback(get_or_send_gui_models);
822 gui_exec_callback_init(); /* see library.c */
823
824 /* allocate dataset struct */
825 dataset = datainfo_new();
826 if (dataset == NULL) {
827 noalloc();
828 }
829
830 /* allocate memory for models */
831 model = allocate_working_model();
832 if (model == NULL) {
833 noalloc();
834 }
835
836 library_command_init();
837 helpfile_init();
838 session_init();
839 init_fileptrs();
840
841 if (argc > 1 && *filearg == '\0') {
842 /* If we have a residual unhandled command-line argument,
843 it should be the name of a file to be opened.
844 */
845 strncat(filearg, argv[1], MAXLEN - 1);
846 }
847
848 #ifdef GRETL_OPEN_HANDLER
849 if (!optnew && maybe_hand_off(filearg, auxname)) {
850 fflush(stderr);
851 exit(EXIT_SUCCESS);
852 }
853 #endif
854
855 #if GUI_DEBUG
856 fprintf(stderr, "finished miscellaneous init functions\n");
857 #endif
858
859 if (argc > 1) {
860 /* Record what is presumably a filename argument
861 given on the command line (by now any options will
862 have been extracted from the @argv array).
863 */
864 record_filearg(tryfile, filearg);
865 }
866
867 #if GUI_DEBUG
868 fprintf(stderr, "about to build GUI...\n");
869 #endif
870
871 #if defined(G_OS_WIN32)
872 set_up_windows_look();
873 #elif defined(OS_OSX) && defined(HAVE_MAC_THEMES)
874 set_up_mac_look();
875 #endif
876
877 #ifdef GRETL_PID_FILE
878 write_pid_to_file();
879 atexit(delete_pid_from_file);
880 #endif
881
882 /* create the GUI */
883 set_fixed_font(NULL, 1);
884 gretl_stock_icons_init();
885 #if GUI_DEBUG
886 fprintf(stderr, " done gretl_stock_icons_init\n");
887 #endif
888 make_main_window();
889
890 #if GUI_DEBUG
891 fprintf(stderr, " done make_main_window\n");
892 #endif
893
894 add_files_to_menus();
895
896 #if GUI_DEBUG
897 fprintf(stderr, " done add_files_to_menus\n");
898 #endif
899
900 session_menu_state(FALSE);
901 restore_sample_state(FALSE);
902 dataset_menubar_state(FALSE);
903
904 #if GUI_DEBUG
905 fprintf(stderr, "done setting GUI state\n");
906 #endif
907
908 if (tryfile_is_set()) {
909 open_tryfile();
910 }
911
912 /* try opening specified database or package */
913 if (optdb != NULL) {
914 open_named_db_index(auxname);
915 } else if (optwebdb != NULL) {
916 open_named_remote_db_index(auxname);
917 } else if (optpkg != NULL) {
918 edit_specified_package(auxname);
919 }
920
921 #ifdef GRETL_OPEN_HANDLER
922 install_open_handler();
923 #endif
924
925 #if GUI_DEBUG
926 fprintf(stderr, "calling gtk_main()\n");
927 #endif
928
929 /* Enter the event loop */
930 gtk_main();
931
932 /* clean up before exiting */
933 free_session(1);
934
935 destroy_working_model(model);
936
937 library_command_free();
938 libgretl_cleanup();
939
940 if (data_status) {
941 destroy_dataset(dataset);
942 }
943
944 destroy_file_collections();
945 destroy_gui_package_info();
946 free_command_stack();
947
948 #ifdef MAC_INTEGRATION
949 g_object_unref(MacApp);
950 #endif
951
952 return EXIT_SUCCESS;
953 }
954
check_varmenu_state(GtkTreeSelection * select,gpointer p)955 static void check_varmenu_state (GtkTreeSelection *select, gpointer p)
956 {
957 if (mdata->ui != NULL) {
958 int vnum = 0;
959 int sc = tree_selection_count(select, &vnum);
960
961 if (sc == 1 && vnum > 0) {
962 mdata->active_var = vnum;
963 maybe_reset_varinfo_dialog();
964 }
965
966 variable_menu_state(sc == 1);
967 }
968 }
969
970 /* if a keystroke (e.g. page up) would take us to row 0, countermand
971 this and go to row 1 instead
972 */
973
mdata_avoid_zero(GtkTreeView * view,gpointer p)974 static void mdata_avoid_zero (GtkTreeView *view, gpointer p)
975 {
976 GtkTreePath *path = NULL;
977 int i;
978
979 gtk_tree_view_get_cursor(view, &path, NULL);
980
981 if (path != NULL) {
982 i = gtk_tree_path_get_indices(path)[0];
983 if (i == 0) {
984 GtkTreePath *newp;
985
986 newp = gtk_tree_path_new_from_indices(1, -1);
987 gtk_tree_view_set_cursor(view, newp, NULL, FALSE);
988 gtk_tree_path_free(newp);
989 }
990 gtk_tree_path_free(path);
991 }
992 }
993
is_control_key(guint k)994 int is_control_key (guint k)
995 {
996 if (k == GDK_Control_L || k == GDK_Control_R) {
997 return 1;
998 } else if (k == GDK_Meta_L || k == GDK_Meta_R) {
999 return 1;
1000 } else if (k == GDK_Alt_L || k == GDK_Alt_R) {
1001 return 1;
1002 } else if (k == GDK_Escape) {
1003 return 1;
1004 } else {
1005 return 0;
1006 }
1007 }
1008
1009 /* keystrokes recognized in the main gretl window */
1010
catch_mdata_key(GtkWidget * w,GdkEventKey * event,windata_t * vwin)1011 static gint catch_mdata_key (GtkWidget *w, GdkEventKey *event,
1012 windata_t *vwin)
1013 {
1014 int Ctrl = (event->state & GDK_CONTROL_MASK);
1015 int Alt = (event->state & GDK_MOD1_MASK);
1016 int k = event->keyval;
1017
1018 if (is_control_key(event->keyval)) {
1019 return FALSE;
1020 }
1021
1022 if (Ctrl && k == GDK_v) {
1023 /* Ctrl-V for paste */
1024 mdata_handle_paste();
1025 return TRUE;
1026 } else if (swallow && Ctrl && (k == GDK_Page_Down || k == GDK_Tab)) {
1027 gretl_console();
1028 return TRUE;
1029 }
1030
1031 #ifdef OS_OSX
1032 if (Ctrl && k == GDK_F2) {
1033 /* Ctrl-F2 for menubar */
1034 GtkWidget *menu;
1035
1036 menu = gtk_ui_manager_get_widget(mdata->ui, "/menubar");
1037 if (menu != NULL) {
1038 gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), TRUE);
1039 }
1040 return TRUE;
1041 } else if (cmd_key(event)) {
1042 if (k == GDK_v) {
1043 mdata_handle_paste();
1044 return TRUE;
1045 } else if (k == GDK_comma) {
1046 /* comand-, = preferences */
1047 prefs_dialog_callback();
1048 return TRUE;
1049 }
1050 }
1051 if (Alt && k == alt_x_key) {
1052 /* alt-x -> approx. equals */
1053 k = GDK_x;
1054 }
1055 #endif
1056
1057 if (k == GDK_F1) {
1058 /* invoke help */
1059 display_text_help(NULL);
1060 return TRUE;
1061 } else if (k == GDK_g) {
1062 /* invoke genr */
1063 genr_callback();
1064 return TRUE;
1065 } else if (k == GDK_c) {
1066 /* launch the console */
1067 gretl_console();
1068 return TRUE;
1069 } else if (Alt) {
1070 if (k == GDK_x) {
1071 /* Alt-x: invoke command minibuffer */
1072 minibuf_callback();
1073 return TRUE;
1074 }
1075 }
1076
1077 if (dataset->v == 0) {
1078 goto suppress;
1079 }
1080
1081 if (k == GDK_r) {
1082 refresh_data();
1083 return TRUE;
1084 }
1085
1086 if (k == GDK_Return /* display variable(s) */
1087 || k == GDK_Delete /* delete variable(s) */
1088 || k == GDK_e || k == GDK_F2 /* edit variable's info */
1089 || k == GDK_t /* graph variable */
1090 ) {
1091 int selcount, vnum = 0;
1092
1093 selcount = vwin_selection_count(mdata, &vnum);
1094
1095 if (selcount == 1 && vnum != 0) {
1096 mdata->active_var = vnum;
1097 if (k == GDK_e || k == GDK_F2) {
1098 varinfo_dialog(mdata->active_var);
1099 } else if (k == GDK_t) {
1100 do_graph_var(mdata->active_var);
1101 } else if (k == GDK_Return) {
1102 display_var();
1103 } else if (k == GDK_Delete) {
1104 delete_single_var(mdata->active_var);
1105 }
1106 } else if (selcount > 1) {
1107 if (k == GDK_Delete) {
1108 delete_selected_vars();
1109 } else if (k == GDK_Return) {
1110 display_selected();
1111 }
1112 }
1113
1114 return TRUE;
1115 }
1116
1117 suppress:
1118
1119 /* suppress echo of useless keystrokes */
1120 if (k != GDK_Up && k != GDK_Down &&
1121 k != GDK_Page_Up && k != GDK_Page_Down &&
1122 k != GDK_Home && k != GDK_End) {
1123 return TRUE;
1124 }
1125
1126 return FALSE;
1127 }
1128
series_get_parent_iter(int pv,GtkTreeIter * parent)1129 static int series_get_parent_iter (int pv, GtkTreeIter *parent)
1130 {
1131 GtkTreeModel *model =
1132 gtk_tree_view_get_model(GTK_TREE_VIEW(mdata->listbox));
1133 GtkTreeIter iter;
1134 gchar *idstr;
1135 int ret = 0;
1136
1137 if (!gtk_tree_model_get_iter_first(model, &iter)) {
1138 return 0;
1139 }
1140
1141 while (1) {
1142 gtk_tree_model_get(model, &iter, 0, &idstr, -1);
1143 if (atoi(idstr) == pv) {
1144 *parent = iter;
1145 ret = 1;
1146 }
1147 g_free(idstr);
1148 if (ret || !gtk_tree_model_iter_next(model, &iter)) {
1149 break;
1150 }
1151 }
1152
1153 return ret;
1154 }
1155
mdata_select_all(void)1156 static void mdata_select_all (void)
1157 {
1158 GtkTreeSelection *select;
1159
1160 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(mdata->listbox));
1161 gtk_tree_selection_select_all(select);
1162 }
1163
get_line_pos(GtkTreeModel * mod)1164 static int get_line_pos (GtkTreeModel *mod)
1165 {
1166 GtkTreeIter iter;
1167 gchar *idstr;
1168 int i = 1, pos = 0;
1169
1170 if (gtk_tree_model_get_iter_first(mod, &iter)) {
1171 while (gtk_tree_model_iter_next(mod, &iter)) {
1172 gtk_tree_model_get(mod, &iter, 0, &idstr, -1);
1173 if (idstr != NULL && atoi(idstr) == mdata->active_var) {
1174 pos = i;
1175 }
1176 g_free(idstr);
1177 if (pos) {
1178 break;
1179 }
1180 i++;
1181 }
1182 }
1183
1184 return pos;
1185 }
1186
panel_dummy_first_sibling(const char * s,gretlopt opt)1187 static int panel_dummy_first_sibling (const char *s, gretlopt opt)
1188 {
1189 int i;
1190
1191 if (sscanf(s, "%d", &i) == 1 && i > 1) {
1192 char numstr[16];
1193
1194 sprintf(numstr, "%d", i);
1195 if (strlen(s) == strlen(numstr)) {
1196 if (opt == OPT_T) {
1197 return current_series_index(dataset, "dt_1");
1198 } else {
1199 return current_series_index(dataset, "du_1");
1200 }
1201 }
1202 }
1203
1204 return 0;
1205 }
1206
get_lag_or_dummy_parent(int v)1207 static int get_lag_or_dummy_parent (int v)
1208 {
1209 const char *vname = dataset->varname[v];
1210 int pv = 0;
1211
1212 if (series_get_lag(dataset, v) != 0) {
1213 pv = series_get_parent_id(dataset, v);
1214 } else if (series_get_transform(dataset, v) == DUMMIFY) {
1215 pv = series_get_parent_id(dataset, v);
1216 } else if (!strncmp(vname, "dt_", 3)) {
1217 pv = panel_dummy_first_sibling(vname + 3, OPT_T);
1218 } else if (!strncmp(vname, "du_", 3)) {
1219 pv = panel_dummy_first_sibling(vname + 3, OPT_U);
1220 }
1221
1222 if (pv < 0 || pv >= dataset->v) {
1223 pv = 0;
1224 }
1225
1226 return pv;
1227 }
1228
1229 /* populate the list of series in the main gretl window */
1230
populate_varlist(void)1231 void populate_varlist (void)
1232 {
1233 static gint check_connected;
1234 static gint click_connected;
1235 GtkTreeView *view = GTK_TREE_VIEW(mdata->listbox);
1236 GtkTreeModel *model = gtk_tree_view_get_model(view);
1237 GtkTreeStore *store = GTK_TREE_STORE(model);
1238 GtkTreeSelection *select;
1239 GtkTreeIter iter;
1240 char id[12];
1241 int i, pos = 0;
1242
1243 if (store != NULL) {
1244 /* record line position? */
1245 pos = get_line_pos(model);
1246 }
1247
1248 gtk_tree_store_clear(store);
1249 gtk_tree_model_get_iter_first(model, &iter);
1250
1251 for (i=0; i<dataset->v; i++) {
1252 const char *vlabel;
1253 int pv = 0;
1254
1255 if (series_is_hidden(dataset, i)) {
1256 continue;
1257 }
1258
1259 vlabel = series_get_label(dataset, i);
1260
1261 if (i > 0) {
1262 pv = get_lag_or_dummy_parent(i);
1263 }
1264
1265 if (pv > 0) {
1266 GtkTreeIter child_iter, parent_iter;
1267
1268 if (series_get_parent_iter(pv, &parent_iter)) {
1269 gtk_tree_store_insert_before(store, &child_iter,
1270 &parent_iter, NULL);
1271 sprintf(id, "%d", i);
1272 gtk_tree_store_set(store, &child_iter,
1273 0, id,
1274 1, dataset->varname[i],
1275 2, vlabel == NULL ? "" : vlabel,
1276 -1);
1277 } else {
1278 pv = 0;
1279 }
1280 }
1281
1282 if (pv == 0) {
1283 gtk_tree_store_append(store, &iter, NULL);
1284 sprintf(id, "%d", i);
1285 gtk_tree_store_set(store, &iter,
1286 0, id,
1287 1, dataset->varname[i],
1288 2, vlabel == NULL ? "" : vlabel,
1289 -1);
1290 }
1291 }
1292
1293 gtk_tree_model_get_iter_first(model, &iter);
1294
1295 if (pos == 0) {
1296 /* no saved position */
1297 pos = 1;
1298 gtk_tree_model_iter_next(model, &iter);
1299 } else {
1300 /* try to return to previous position */
1301 GtkTreeIter last;
1302
1303 i = 1;
1304 while (1) {
1305 last = iter;
1306 if (!gtk_tree_model_iter_next(model, &iter)) {
1307 /* reached the end! */
1308 iter = last;
1309 break;
1310 } else if (i == pos) {
1311 /* found previous position */
1312 break;
1313 }
1314 i++;
1315 }
1316 pos = i;
1317 }
1318
1319 mdata->active_var = pos;
1320 select = gtk_tree_view_get_selection(view);
1321 gtk_tree_selection_select_iter(select, &iter);
1322
1323 if (dataset->v > 1) {
1324 GtkTreePath *path;
1325
1326 sprintf(id, "%d", pos);
1327 path = gtk_tree_path_new_from_string(id);
1328 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1329 gtk_tree_path_free(path);
1330 }
1331
1332 if (!check_connected) {
1333 g_signal_connect(G_OBJECT(select), "changed",
1334 G_CALLBACK(check_varmenu_state),
1335 mdata);
1336 g_signal_connect(G_OBJECT(mdata->listbox), "cursor-changed",
1337 G_CALLBACK(mdata_avoid_zero),
1338 NULL);
1339 check_connected = 1;
1340 }
1341
1342 if (!click_connected) {
1343 g_signal_connect(G_OBJECT(mdata->listbox), "button-press-event",
1344 G_CALLBACK(main_popup_handler),
1345 mdata);
1346 g_signal_connect(G_OBJECT(mdata->listbox), "button-press-event",
1347 G_CALLBACK(main_varclick),
1348 mdata);
1349 click_connected = 1;
1350 }
1351
1352 variable_menu_state(TRUE);
1353 }
1354
mdata_select_last_var(void)1355 void mdata_select_last_var (void)
1356 {
1357 GtkTreeIter iter, last;
1358 GtkTreeView *view;
1359 GtkTreeModel *model;
1360 GtkTreeSelection *select;
1361
1362 view = GTK_TREE_VIEW(mdata->listbox);
1363 model = gtk_tree_view_get_model(view);
1364 gtk_tree_model_get_iter_first(model, &iter);
1365
1366 while (1) {
1367 last = iter;
1368 if (!gtk_tree_model_iter_next(model, &iter)) {
1369 iter = last;
1370 break;
1371 }
1372 }
1373
1374 select = gtk_tree_view_get_selection(view);
1375 gtk_tree_selection_unselect_all(select);
1376 gtk_tree_selection_select_iter(select, &iter);
1377 }
1378
real_select_list(const int * list)1379 static void real_select_list (const int *list)
1380 {
1381 GtkTreeIter iter;
1382 GtkTreeView *view;
1383 GtkTreeModel *model;
1384 GtkTreeSelection *select;
1385 gchar *idstr;
1386 int nsel = 0;
1387
1388 view = GTK_TREE_VIEW(mdata->listbox);
1389 model = gtk_tree_view_get_model(view);
1390 select = gtk_tree_view_get_selection(view);
1391 gtk_tree_selection_unselect_all(select);
1392
1393 gtk_tree_model_get_iter_first(model, &iter);
1394
1395 while (nsel < list[0]) {
1396 if (!gtk_tree_model_iter_next(model, &iter)) {
1397 break;
1398 }
1399 gtk_tree_model_get(model, &iter, 0, &idstr, -1);
1400 if (in_gretl_list(list, atoi(idstr))) {
1401 gtk_tree_selection_select_iter(select, &iter);
1402 nsel++;
1403 }
1404 g_free(idstr);
1405 }
1406 }
1407
mdata_select_list(void)1408 static void mdata_select_list (void)
1409 {
1410 if (n_user_lists() == 0) {
1411 warnbox(_("No lists are currently defined"));
1412 return;
1413 } else {
1414 char lname[32];
1415 int resp;
1416
1417 resp = select_list_dialog(lname);
1418
1419 if (!canceled(resp)) {
1420 int *list = get_list_by_name(lname);
1421
1422 if (list != NULL) {
1423 real_select_list(list);
1424 }
1425 }
1426 }
1427 }
1428
clear_varlist(GtkWidget * widget)1429 void clear_varlist (GtkWidget *widget)
1430 {
1431 GtkTreeModel *model;
1432
1433 model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1434
1435 if (GTK_IS_TREE_STORE(model)) {
1436 gtk_tree_store_clear(GTK_TREE_STORE(model));
1437 } else if (GTK_IS_LIST_STORE(model)) {
1438 gtk_list_store_clear(GTK_LIST_STORE(model));
1439 }
1440 }
1441
get_gui_scale(void)1442 static float get_gui_scale (void)
1443 {
1444 GtkSettings *settings = gtk_settings_get_default();
1445 float scale = 1.0;
1446
1447 if (settings != NULL) {
1448 gchar *fontname = NULL;
1449 int fsize;
1450
1451 g_object_get(G_OBJECT(settings), "gtk-font-name", &fontname, NULL);
1452
1453 if (fontname != NULL) {
1454 if (sscanf(fontname, "%*s %d", &fsize) == 1) {
1455 if (fsize > 10 && fsize < 100) {
1456 scale = fsize / 10.0;
1457 }
1458 }
1459 g_free(fontname);
1460 }
1461 }
1462
1463 return scale;
1464 }
1465
1466 static gboolean
mainwin_config(GtkWidget * w,GdkEventConfigure * event,gpointer p)1467 mainwin_config (GtkWidget *w, GdkEventConfigure *event, gpointer p)
1468 {
1469 mainwin_width = event->width;
1470 mainwin_height = event->height;
1471
1472 gdk_window_get_root_origin(gtk_widget_get_window(mdata->main),
1473 &main_x, &main_y);
1474
1475 return FALSE;
1476 }
1477
1478 /* scale up the main window if it seems to be too tiny in relation to
1479 the screen dimensions
1480 */
1481
set_main_window_scale(void)1482 static void set_main_window_scale (void)
1483 {
1484 GdkScreen *s = gdk_screen_get_default();
1485
1486 if (s != NULL) {
1487 int w = gdk_screen_get_width(s);
1488 int h = gdk_screen_get_height(s);
1489 double aspect = 1.25;
1490 double hfac = 2.10;
1491
1492 if (mainwin_height < h / hfac) {
1493 mainwin_height = h / hfac;
1494 if ((double) w / h > 1.35) {
1495 /* widescreen */
1496 aspect = 1.4;
1497 }
1498 w = aspect * mainwin_height;
1499 if (mainwin_width < w) {
1500 mainwin_width = w;
1501 }
1502 }
1503 }
1504 }
1505
show_link_cursor(GtkWidget * w,gpointer p)1506 void show_link_cursor (GtkWidget *w, gpointer p)
1507 {
1508 GdkWindow *window = gtk_widget_get_window(w);
1509 GdkCursor *c = gdk_cursor_new(GDK_HAND2);
1510
1511 if (c != NULL) {
1512 gdk_window_set_cursor(window, c);
1513 gdk_cursor_unref(c);
1514 }
1515 }
1516
mainwin_get_vwin_insertion(void)1517 int mainwin_get_vwin_insertion (void)
1518 {
1519 int ins = -1;
1520
1521 if (mdata->hpanes1 != NULL) {
1522 if (gtk_paned_get_child2(GTK_PANED(mdata->hpanes1)) == NULL) {
1523 ins = 1;
1524 } else if (mdata->hpanes2 != NULL) {
1525 if (gtk_paned_get_child1(GTK_PANED(mdata->hpanes2)) == NULL) {
1526 ins = 2;
1527 } else if (gtk_paned_get_child2(GTK_PANED(mdata->hpanes2)) == NULL) {
1528 ins = 3;
1529 }
1530 }
1531 }
1532
1533 return ins;
1534 }
1535
mainwin_insert_vwin(windata_t * vwin)1536 int mainwin_insert_vwin (windata_t *vwin)
1537 {
1538 int ret = 0;
1539
1540 if (vwin == NULL) {
1541 return ret;
1542 }
1543 if (gtk_paned_get_child2(GTK_PANED(mdata->hpanes1)) == NULL) {
1544 gtk_paned_add2(GTK_PANED(mdata->hpanes1), vwin->vbox);
1545 gtk_paned_set_position(GTK_PANED(mdata->hpanes1), mainwin_width/2);
1546 ret = 1;
1547 } else if (mdata->hpanes2 != NULL) {
1548 GtkWidget *vp = gtk_widget_get_parent(mdata->hpanes2);
1549
1550 fprintf(stderr, "HERE hpanes2\n");
1551 if (gtk_paned_get_child1(GTK_PANED(mdata->hpanes2)) == NULL) {
1552 gtk_paned_add1(GTK_PANED(mdata->hpanes2), vwin->vbox);
1553 fprintf(stderr, " add child 1\n");
1554 ret = 2;
1555 } else if (gtk_paned_get_child2(GTK_PANED(mdata->hpanes2)) == NULL) {
1556 gtk_paned_add2(GTK_PANED(mdata->hpanes2), vwin->vbox);
1557 fprintf(stderr, " add child 2\n");
1558 gtk_paned_set_position(GTK_PANED(mdata->hpanes2), mainwin_width/2);
1559 ret = 3;
1560 }
1561 if (ret) {
1562 gtk_paned_set_position(GTK_PANED(vp), mainwin_height/2);
1563 }
1564 }
1565
1566 return ret;
1567 }
1568
gretl_show_console(void)1569 static void gretl_show_console (void)
1570 {
1571 if (swallow) {
1572 mainwin_insert_vwin(gretl_console());
1573 } else {
1574 gretl_console();
1575 }
1576 }
1577
make_main_window(void)1578 static void make_main_window (void)
1579 {
1580 #ifdef MAC_INTEGRATION
1581 GtkUIManager *mac_mgr = NULL;
1582 #endif
1583 GtkWidget *box, *dlabel;
1584 GtkWidget *hbox, *ebox;
1585 GtkWidget *wlabel = NULL;
1586 const char *titles[] = {
1587 N_("ID #"),
1588 N_("Variable name"),
1589 N_("Descriptive label")
1590 };
1591 GType types[] = {
1592 G_TYPE_STRING,
1593 G_TYPE_STRING,
1594 G_TYPE_STRING
1595 };
1596
1597 mdata = gretl_viewer_new(MAINWIN, "gretl", NULL);
1598 if (mdata == NULL) {
1599 noalloc();
1600 }
1601
1602 gui_scale = get_gui_scale();
1603 #if GUI_DEBUG
1604 fprintf(stderr, " gui_scale = %g\n", (double) gui_scale);
1605 #endif
1606
1607 if (!winsize || mainwin_width <= 200 || mainwin_height <= 200) {
1608 /* set default window size */
1609 mainwin_width = 650 * gui_scale;
1610 mainwin_height = 460 * gui_scale;
1611 if (swallow) {
1612 mainwin_width *= 1.6;
1613 }
1614 set_main_window_scale();
1615 }
1616
1617 g_signal_connect(G_OBJECT(mdata->main), "configure-event",
1618 G_CALLBACK(mainwin_config), NULL);
1619 g_signal_connect(G_OBJECT(mdata->main), "delete-event",
1620 G_CALLBACK(exit_check), NULL);
1621 g_signal_connect(G_OBJECT(mdata->main), "destroy",
1622 G_CALLBACK(gtk_main_quit), NULL);
1623
1624 gtk_window_set_default_size(GTK_WINDOW(mdata->main),
1625 mainwin_width, mainwin_height);
1626
1627 mdata->mbar = make_main_menu();
1628 if (mdata->mbar == NULL) {
1629 exit(EXIT_FAILURE);
1630 }
1631
1632 #if GUI_DEBUG
1633 fprintf(stderr, " got past make_main_menu()\n");
1634 #endif
1635
1636 /* put the main menu bar in place */
1637 if (swallow) {
1638 box = g_object_get_data(G_OBJECT(mdata->main), "topbox");
1639 gtk_box_pack_start(GTK_BOX(box), mdata->mbar, TRUE, TRUE, 0);
1640 } else {
1641 box = gtk_hbox_new(FALSE, 0);
1642 gtk_box_pack_start(GTK_BOX(box), mdata->mbar, TRUE, TRUE, 0);
1643 gtk_box_pack_start(GTK_BOX(mdata->vbox), box, FALSE, FALSE, 0);
1644 }
1645
1646 #ifdef MAC_INTEGRATION
1647 mac_mgr = add_mac_menu();
1648 #endif
1649
1650 /* this will hold the list of variables */
1651 box = gtk_vbox_new(FALSE, 0);
1652
1653 /* label for name of datafile */
1654 dlabel = gtk_label_new(_(" No datafile loaded "));
1655 g_object_set_data(G_OBJECT(mdata->main), "dlabel", dlabel);
1656
1657 /* label for working directory */
1658 hbox = gtk_hbox_new(FALSE, 5);
1659 ebox = gtk_event_box_new();
1660 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1661 gtk_box_pack_start(GTK_BOX(hbox), dlabel, FALSE, FALSE, 0);
1662 wlabel = gtk_label_new("");
1663 gtk_widget_set_tooltip_text(wlabel, _("Working directory: "
1664 "click to configure"));
1665 g_object_set_data(G_OBJECT(mdata->main), "wlabel", wlabel);
1666 gtk_container_add(GTK_CONTAINER(ebox), wlabel);
1667 gtk_box_pack_end(GTK_BOX(hbox), ebox, FALSE, FALSE, 5);
1668 g_signal_connect(ebox, "button-press-event",
1669 G_CALLBACK(workdir_dialog1), NULL);
1670 g_signal_connect(ebox, "enter-notify-event",
1671 G_CALLBACK(show_link_cursor), NULL);
1672
1673 #if GUI_DEBUG
1674 fprintf(stderr, " adding main-window listbox...\n");
1675 #endif
1676
1677 vwin_add_list_box(mdata, GTK_BOX(box), 3, 0, types, titles, 1);
1678
1679 gtk_drag_dest_set(mdata->listbox,
1680 GTK_DEST_DEFAULT_ALL,
1681 gretl_drag_targets, 2,
1682 GDK_ACTION_COPY);
1683 g_signal_connect(G_OBJECT(mdata->listbox), "drag-data-received",
1684 G_CALLBACK(mdata_handle_drag),
1685 NULL);
1686 g_signal_connect(G_OBJECT(mdata->listbox), "key-press-event",
1687 G_CALLBACK(catch_mdata_key),
1688 mdata);
1689
1690 gtk_box_pack_start(GTK_BOX(mdata->vbox), box, TRUE, TRUE, 0);
1691 mdata->status = gtk_label_new("");
1692 gtk_box_pack_start(GTK_BOX(mdata->vbox), mdata->status, FALSE, TRUE, 0);
1693
1694 #if GUI_DEBUG
1695 fprintf(stderr, " finalizing main window...\n");
1696 #endif
1697
1698 /* put stuff into list box, activate menus */
1699 if (have_data()) {
1700 populate_varlist();
1701 }
1702
1703 #if GUI_DEBUG
1704 fprintf(stderr, " step 1 done\n");
1705 #endif
1706
1707 /* set a proportional font for menus, etc. */
1708 set_app_font(NULL, 1);
1709
1710 #if GUI_DEBUG
1711 fprintf(stderr, " set_app_font done\n");
1712 #endif
1713
1714 vwin_add_winlist(mdata);
1715 add_mainwin_toolbar(mdata->vbox);
1716
1717 #if GUI_DEBUG
1718 fprintf(stderr, " add_mainwin_toolbar done\n");
1719 #endif
1720
1721 if (swallow) {
1722 gretl_show_console();
1723 }
1724
1725 gtk_widget_show_all(mdata->main);
1726
1727 #ifdef MAC_INTEGRATION
1728 if (mac_mgr != NULL) {
1729 finish_mac_ui(mac_mgr);
1730 }
1731 #endif
1732
1733 #if GUI_DEBUG
1734 fprintf(stderr, " gtk_widget_show_all done\n");
1735 #endif
1736
1737 if (winsize && main_x >= 0 && main_y >= 0) {
1738 gtk_window_move(GTK_WINDOW(mdata->main), main_x, main_y);
1739 }
1740
1741 if (wlabel != NULL) {
1742 set_workdir_label();
1743 }
1744
1745 #if GUI_DEBUG
1746 fprintf(stderr, " possible window_move done\n");
1747 #endif
1748 }
1749
1750 #ifdef OS_OSX
1751 # define CTRL_ALL "<meta>A"
1752 # define HELPKEY "<meta>question"
1753 #else
1754 # define CTRL_ALL "<control>A"
1755 # define HELPKEY NULL
1756 #endif
1757
1758 GtkActionEntry main_entries[] = {
1759 /* File */
1760 { "File", NULL, N_("_File"), NULL, NULL, NULL },
1761 { "OpenDataMenu", NULL, N_("_Open data"), NULL, NULL, NULL },
1762 { "OpenData", GTK_STOCK_OPEN, N_("_User file..."), NULL, NULL, G_CALLBACK(open_data) },
1763 { "DisplayDataFiles", GTK_STOCK_OPEN, N_("_Sample file..."), "", NULL, G_CALLBACK(show_files) },
1764 { "AppendData", NULL, N_("_Append data..."), NULL, NULL, G_CALLBACK(open_data) },
1765 { "SaveData", GTK_STOCK_SAVE, N_("_Save data"), NULL, NULL, G_CALLBACK(auto_store) },
1766 { "SaveDataAs", GTK_STOCK_SAVE_AS, N_("Save data _as..."), NULL, NULL, G_CALLBACK(fsave_callback) },
1767 { "ExportData", NULL, N_("_Export data..."), NULL, NULL, G_CALLBACK(fsave_callback) },
1768 { "MailData", GRETL_STOCK_MAIL, N_("Send To..."), NULL, NULL, G_CALLBACK(email_data) },
1769 { "NewData", GTK_STOCK_NEW, N_("_New data set"), NULL, NULL, G_CALLBACK(newdata_callback) },
1770 { "ClearData", GTK_STOCK_CLEAR, N_("C_lear data set"), NULL, NULL, G_CALLBACK(verify_clear_data) },
1771
1772 { "WorkingDir", NULL, N_("_Working directory..."), NULL, NULL, G_CALLBACK(workdir_dialog0) },
1773 { "ScriptFiles", NULL, N_("_Script files"), NULL, NULL, NULL },
1774 { "OpenScript", GTK_STOCK_OPEN, N_("_User file..."), "", NULL, G_CALLBACK(open_script_callback) },
1775 { "DisplayScripts", GTK_STOCK_OPEN, N_("_Example scripts..."), "", NULL, G_CALLBACK(show_files) },
1776 { "NewScript", GTK_STOCK_NEW, N_("_New script"), "", NULL, NULL },
1777 { "GretlScript", NULL, N_("gretl script"), NULL, NULL, G_CALLBACK(new_script_callback) },
1778 { "GnuplotScript", NULL, N_("gnuplot script"), NULL, NULL, G_CALLBACK(new_script_callback) },
1779 { "RScript", NULL, N_("R script"), NULL, NULL, G_CALLBACK(new_script_callback) },
1780 { "OctaveScript", NULL, N_("Octave script"), NULL, NULL, G_CALLBACK(new_script_callback) },
1781 { "PyScript", NULL, N_("Python script"), NULL, NULL, G_CALLBACK(new_script_callback) },
1782 { "JuliaScript", NULL, N_("Julia program"), NULL, NULL, G_CALLBACK(new_script_callback) },
1783 { "OxScript", NULL, N_("Ox program"), NULL, NULL, G_CALLBACK(new_script_callback) },
1784 { "StataScript", NULL, N_("Stata program"), NULL, NULL, G_CALLBACK(new_script_callback) },
1785 { "lpsolveScript", NULL, N_("lpsolve program"), NULL, NULL, G_CALLBACK(new_script_callback) },
1786
1787 { "SessionFiles", NULL, N_("_Session files"), NULL, NULL, NULL },
1788 { "OpenSession", GTK_STOCK_OPEN, N_("_Open session..."), "", NULL, G_CALLBACK(open_session_callback) },
1789 { "SaveSession", GTK_STOCK_SAVE, N_("_Save session"), "", NULL,
1790 G_CALLBACK(save_session_callback) },
1791 { "SaveSessionAs", GTK_STOCK_SAVE_AS, N_("Save session _as..."), NULL, NULL,
1792 G_CALLBACK(save_session_callback) },
1793
1794 { "Databases", NULL, N_("_Databases"), NULL, NULL, NULL },
1795 { "NativeDB", GTK_STOCK_OPEN, N_("_Gretl native..."), "", NULL, G_CALLBACK(show_files) },
1796 { "RATSDB", GTK_STOCK_OPEN, N_("_RATS 4..."), "", NULL, G_CALLBACK(open_data) },
1797 { "PcGiveDB", GTK_STOCK_OPEN, N_("_PcGive..."), "", NULL, G_CALLBACK(open_data) },
1798 { "RemoteDB", GTK_STOCK_NETWORK, N_("On database _server..."), NULL, NULL, G_CALLBACK(show_files) },
1799 { "DBnomics", GRETL_STOCK_DBN, "DB.NOMICS", NULL, NULL, NULL }, /* DB\u00B7NOMICS ? */
1800 { "DBNbrowse", NULL, N_("Browse..."), NULL, NULL, G_CALLBACK(show_files) },
1801 { "DBNseries", NULL, N_("Specific series..."), NULL, NULL, G_CALLBACK(dbnomics_specific_series) },
1802
1803 { "Packages", NULL, N_("_Function packages"), NULL, NULL, NULL },
1804 { "LocalGfn", GTK_STOCK_OPEN, N_("On _local machine..."), "", NULL, G_CALLBACK(show_files) },
1805 { "RemoteGfn", GTK_STOCK_NETWORK, N_("On _server..."), NULL, NULL, G_CALLBACK(show_files) },
1806 { "EditGfn", GTK_STOCK_EDIT, N_("Edit package..."), NULL, NULL, G_CALLBACK(edit_gfn_callback) },
1807 { "NewGfn", GTK_STOCK_NEW, N_("_New package"), "", NULL, G_CALLBACK(new_gfn_callback) },
1808 { "UploadGfn", GTK_STOCK_NETWORK, N_("_Upload package..."), "", NULL, G_CALLBACK(upload_package_callback) },
1809 { "EditSpec", GTK_STOCK_EDIT, N_("Edit spec file..."), NULL, NULL, G_CALLBACK(edit_spec_callback) },
1810 { "AddonResources", NULL, N_("_Resource from addon"), NULL, NULL, NULL },
1811
1812 { "Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK(menu_exit_check)},
1813
1814 /* Tools */
1815 { "Tools", NULL, N_("_Tools"), NULL, NULL, NULL },
1816 { "Preferences", NULL, N_("_Preferences"), NULL, NULL, NULL },
1817 { "PrefsGeneral", GTK_STOCK_PREFERENCES, N_("_General..."), NULL, NULL,
1818 G_CALLBACK(prefs_dialog_callback) },
1819 { "FontScale", GTK_STOCK_ZOOM_IN, N_("Font _scale..."), NULL, NULL,
1820 G_CALLBACK(font_scale_selector) },
1821 { "FixedFont", GTK_STOCK_SELECT_FONT, N_("Monospaced _font..."), NULL, NULL,
1822 G_CALLBACK(font_selector) },
1823 { "MenuFont", GTK_STOCK_SELECT_FONT, N_("_Menu font..."), NULL, NULL,
1824 G_CALLBACK(font_selector) },
1825 { "StatsTables", NULL, N_("_Statistical tables"), NULL, NULL, G_CALLBACK(stats_calculator) },
1826 { "PValues", NULL, N_("_P-value finder"), NULL, NULL, G_CALLBACK(stats_calculator) },
1827 { "DistGraphs", NULL, N_("_Distribution graphs"), NULL, NULL, G_CALLBACK(stats_calculator) },
1828 { "PlotCurve", NULL, N_("_Plot a curve"), NULL, NULL, G_CALLBACK(stats_calculator) },
1829 { "TestStats", NULL, N_("_Test statistic calculator"), NULL, NULL, G_CALLBACK(stats_calculator) },
1830 { "NonparamTests", NULL, N_("_Nonparametric tests"), NULL, NULL, G_CALLBACK(stats_calculator) },
1831 { "SetSeed", NULL, N_("_Seed for random numbers"), NULL, NULL, G_CALLBACK(rand_seed_dialog) },
1832 { "CommandLog", NULL, N_("_Command log"), NULL, NULL, G_CALLBACK(view_command_log) },
1833 { "ShowConsole", NULL, N_("_Gretl console"), NULL, NULL, G_CALLBACK(gretl_show_console) },
1834 { "Gnuplot", NULL, N_("_Gnuplot"), NULL, NULL, G_CALLBACK(launch_gnuplot_interactive) },
1835 { "StartR", NULL, N_("Start GNU _R"), NULL, NULL, G_CALLBACK(start_R_callback) },
1836 { "NistTest", NULL, N_("_NIST test suite"), NULL, NULL, NULL },
1837 { "NistBasic", NULL, N_("_Basic"), NULL, NULL, G_CALLBACK(do_nistcheck) },
1838 { "NistVerbose", NULL, N_("_Verbose"), NULL, NULL, G_CALLBACK(do_nistcheck) },
1839 { "NistVVerbose", NULL, N_("V_ery verbose"), NULL, NULL, G_CALLBACK(do_nistcheck) },
1840
1841 /* Data */
1842 { "Data", NULL, N_("_Data"), NULL, NULL, NULL },
1843 { "DataSelectAll", NULL, N_("Select _all"), CTRL_ALL, NULL, G_CALLBACK(mdata_select_all) },
1844 { "DefineList", NULL, N_("Define or edit _list..."), NULL, NULL, G_CALLBACK(gui_define_list) },
1845 { "SelectList", NULL, N_("_Set selection from list..."), NULL, NULL, G_CALLBACK(mdata_select_list) },
1846 { "DisplayValues", NULL, N_("_Display values"), NULL, NULL, G_CALLBACK(display_selected) },
1847 { "EditValues", NULL, N_("_Edit values"), NULL, NULL, G_CALLBACK(spreadsheet_edit) },
1848 { "AddObs", NULL, N_("_Add observations..."), NULL, NULL, G_CALLBACK(do_add_obs) },
1849 { "RemoveObs", NULL, N_("_Remove extra observations"), NULL, NULL, G_CALLBACK(do_remove_obs) },
1850 { "DataInfo", NULL, N_("_Dataset info"), NULL, NULL, G_CALLBACK(dataset_info) },
1851 { "DataMarkers", NULL, N_("_Observation markers..."), NULL, NULL, G_CALLBACK(markers_callback) },
1852 { "VarLabels", NULL, N_("_Variable labels..."), NULL, NULL, G_CALLBACK(labels_callback) },
1853 { "DataStructure", NULL, N_("Dataset _structure..."), NULL, NULL, G_CALLBACK(data_structure_dialog) },
1854 { "DataCompact", NULL, N_("_Compact data..."), NULL, NULL, G_CALLBACK(do_compact_data_set) },
1855 { "DataExpand", NULL, N_("_Expand data..."), NULL, NULL, G_CALLBACK(do_expand_data_set) },
1856 { "DataTranspose", NULL, N_("_Transpose data..."), NULL, NULL, G_CALLBACK(gui_transpose_data) },
1857 { "DataSort", NULL, N_("_Sort data..."), NULL, NULL, G_CALLBACK(gui_sort_data) },
1858 { "GSETMISS", NULL, N_("Set missing _value code..."), NULL, NULL, G_CALLBACK(gretl_callback) },
1859
1860 /* View */
1861 { "View", NULL, N_("_View"), NULL, NULL, NULL },
1862 { "IconView", NULL, N_("_Icon view"), NULL, NULL, G_CALLBACK(view_session) },
1863 { "GraphVars", NULL, N_("_Graph specified vars"), NULL, NULL, NULL },
1864 { "TSPlot", NULL, N_("_Time series plot..."), NULL, NULL, G_CALLBACK(selector_callback) },
1865 { "ScatterPlot", NULL, N_("X-Y _scatter..."), NULL, NULL, G_CALLBACK(selector_callback) },
1866 { "ImpulsePlot", NULL, N_("X-Y with _impulses..."), NULL, NULL, G_CALLBACK(selector_callback) },
1867 { "FactorPlot", NULL, N_("X-Y with _factor separation..."), NULL, NULL, G_CALLBACK(selector_callback) },
1868 { "FrischPlot", NULL, N_("X-Y with _control..."), NULL, NULL, G_CALLBACK(selector_callback) },
1869 { "GR_BOX", NULL, N_("_Boxplots..."), NULL, NULL, G_CALLBACK(selector_callback) },
1870 { "GR_FBOX", NULL, N_("_Factorized boxplot..."), NULL, NULL, G_CALLBACK(selector_callback) },
1871 { "GR_QQ", NULL, N_("_Q-Q plot..."), NULL, NULL, G_CALLBACK(selector_callback) },
1872 { "ThreeDPlot", NULL, N_("_3D plot..."), NULL, NULL, G_CALLBACK(selector_callback) },
1873 { "MapPlot", NULL, N_("_Display map"), NULL, NULL, G_CALLBACK(map_plot_callback) },
1874 { "MultiPlots", NULL, N_("_Multiple graphs"), NULL, NULL, NULL },
1875 { "MultiXY", NULL, N_("X-Y _scatters..."), NULL, NULL, G_CALLBACK(selector_callback) },
1876 { "MultiTS", NULL, N_("_Time series..."), NULL, NULL, G_CALLBACK(selector_callback) },
1877 { "summary", NULL, N_("_Summary statistics"), NULL, NULL, G_CALLBACK(menu_op_action) },
1878 { "corr", NULL, N_("_Correlation matrix"), NULL, NULL, G_CALLBACK(menu_op_action) },
1879 { "xtab", NULL, N_("Cross _Tabulation"), NULL, NULL, G_CALLBACK(menu_op_action) },
1880 { "pca", NULL, N_("_Principal components"), NULL, NULL, G_CALLBACK(menu_op_action) },
1881 { "mahal", NULL, N_("_Mahalanobis distances"), NULL, NULL, G_CALLBACK(menu_op_action) },
1882 { "xcorrgm", NULL, N_("C_ross-correlogram"), NULL, NULL, G_CALLBACK(xcorrgm_callback) },
1883
1884 /* Add */
1885 { "Add", NULL, N_("_Add"), NULL, NULL, NULL },
1886 { "logs", NULL, N_("_Logs of selected variables"), NULL, NULL, G_CALLBACK(logs_etc_callback) },
1887 { "square", NULL, N_("_Squares of selected variables"), NULL, NULL, G_CALLBACK(logs_etc_callback) },
1888 { "lags", NULL, N_("_Lags of selected variables"), NULL, NULL, G_CALLBACK(logs_etc_callback) },
1889 { "diff", NULL, N_("_First differences of selected variables"), NULL, NULL,
1890 G_CALLBACK(logs_etc_callback) },
1891 { "ldiff", NULL, N_("_Log differences of selected variables"), NULL, NULL,
1892 G_CALLBACK(logs_etc_callback) },
1893 { "sdiff", NULL, N_("_Seasonal differences of selected variables"), NULL, NULL,
1894 G_CALLBACK(logs_etc_callback) },
1895 { "pcdiff", NULL, N_("_Percentage change of selected variables"), NULL, NULL,
1896 G_CALLBACK(pc_change_callback) },
1897 { "idxvals", NULL, N_("_100-based indices of selected variables"), NULL, NULL,
1898 G_CALLBACK(pc_change_callback) },
1899 { "stdize", NULL, N_("_Standardize selected variables"), NULL, NULL,
1900 G_CALLBACK(logs_etc_callback) },
1901 { "AddIndex", NULL, N_("_Index variable"), NULL, NULL, G_CALLBACK(add_index) },
1902 { "AddTime", NULL, N_("_Time trend"), NULL, NULL, G_CALLBACK(add_index) },
1903 { "AddUnit", NULL, N_("_Panel unit index"), NULL, NULL, G_CALLBACK(add_index) },
1904 { "AddRandom", NULL, N_("_Random variable..."), NULL, NULL, G_CALLBACK(stats_calculator) },
1905 { "PeriodDums", NULL, N_("_Periodic dummies"), NULL, NULL, G_CALLBACK(add_dummies) },
1906 { "UnitDums", NULL, N_("_Unit dummies"), NULL, NULL, G_CALLBACK(add_dummies) },
1907 { "TimeDums", NULL, N_("_Time dummies"), NULL, NULL, G_CALLBACK(add_dummies) },
1908 { "RangeDum", NULL, N_("_Observation range dummy"), NULL, NULL, G_CALLBACK(range_dummy_dialog) },
1909 { "dummify", NULL, N_("Dummies for _discrete variable..."), NULL, NULL,
1910 G_CALLBACK(add_dummies) },
1911 { "NewMatrix", NULL, N_("_Define matrix..."), NULL, NULL, G_CALLBACK(new_matrix_callback) },
1912
1913 /* Sample */
1914 { "Sample", NULL, N_("_Sample"), NULL, NULL, NULL },
1915 { "SMPL", NULL, N_("_Set range..."), NULL, NULL, G_CALLBACK(sample_range_dialog) },
1916 { "FullRange", NULL, N_("_Restore full range"), NULL, NULL, G_CALLBACK(restore_sample_callback) },
1917 { "ShowSample", NULL, N_("_Show status"), NULL, NULL, G_CALLBACK(show_sample_callback) },
1918 { "SMPLBOOL", NULL, N_("_Restrict, based on criterion..."), NULL, NULL,
1919 G_CALLBACK(sample_restrict_dialog) },
1920 { "SMPLRAND", NULL, N_("R_andom sub-sample..."), NULL, NULL, G_CALLBACK(sample_range_dialog) },
1921 { "SampleWReplace", NULL, N_("_Resample with replacement..."), NULL, NULL,
1922 G_CALLBACK(gui_resample_data) },
1923 { "DropMissing", NULL, N_("Drop observations with _missing values..."), NULL, NULL,
1924 G_CALLBACK(drop_missing_data) },
1925 { "PermaSample", NULL, N_("Make current subsample permanent..."), NULL, NULL,
1926 G_CALLBACK(perma_sample_callback) },
1927 { "CountMissing", NULL, N_("_Count missing values"), NULL, NULL, G_CALLBACK(count_missing) },
1928
1929 /* Variable */
1930 { "Variable", NULL, N_("_Variable"), NULL, NULL, NULL },
1931 { "VarDisplay", NULL, N_("_Display values"), NULL, NULL, G_CALLBACK(display_var) },
1932 { "VarSummary", NULL, N_("_Summary statistics"), NULL, NULL, G_CALLBACK(menu_op_action) },
1933 { "normtest", NULL, N_("_Normality test"), NULL, NULL, G_CALLBACK(menu_op_action) },
1934 { "FreqDist", NULL, N_("_Frequency distribution..."), NULL, NULL, G_CALLBACK(do_freq_dist) },
1935 { "Density", NULL, N_("Estimated _density plot..."), NULL, NULL, G_CALLBACK(do_kernel) },
1936 { "boxplot", NULL, N_("_Boxplot"), NULL, NULL, G_CALLBACK(boxplot_callback) },
1937 { "qqplot", NULL, N_("Normal _Q-Q plot..."), NULL, NULL, G_CALLBACK(do_qqplot) },
1938 { "Gini", NULL, N_("_Gini coefficient"), NULL, NULL, G_CALLBACK(do_gini) },
1939 { "rmplot", NULL, N_("_Range-mean graph"), NULL, NULL, G_CALLBACK(do_range_mean) },
1940 { "VarTSPlot", NULL, N_("_Time series plot"), NULL, NULL, G_CALLBACK(ts_plot_callback) },
1941 { "PanPlot", NULL, N_("_Panel plot..."), NULL, NULL, G_CALLBACK(ts_plot_callback) },
1942 { "URTests", NULL, N_("_Unit root tests"), NULL, NULL, NULL },
1943 { "adf", NULL, N_("_Augmented Dickey-Fuller test"), NULL, NULL, G_CALLBACK(ur_callback) },
1944 { "dfgls", NULL, N_("ADF-GLS test"), NULL, NULL, G_CALLBACK(ur_callback) },
1945 { "kpss", NULL, N_("_KPSS test"), NULL, NULL, G_CALLBACK(ur_callback) },
1946 { "levinlin", NULL, N_("_Levin-Lin-Chu test"), NULL, NULL, G_CALLBACK(ur_callback) },
1947 { "fractint", NULL, N_("_Fractional integration"), NULL, NULL, G_CALLBACK(do_fractint) },
1948 { "corrgm", NULL, N_("_Correlogram"), NULL, NULL, G_CALLBACK(do_corrgm) },
1949 { "pergm", NULL, N_("_Periodogram"), NULL, NULL, G_CALLBACK(do_pergm) },
1950 { "Filter", NULL, N_("_Filter"), NULL, NULL, NULL },
1951 { "FilterSMA", NULL, N_("_Simple moving average"), NULL, NULL, G_CALLBACK(filter_callback) },
1952 { "FilterEMA", NULL, N_("_Exponential moving average"), NULL, NULL, G_CALLBACK(filter_callback) },
1953 { "FilterHP", NULL, N_("_Hodrick-Prescott"), NULL, NULL, G_CALLBACK(filter_callback) },
1954 { "FilterBK", NULL, N_("_Baxter-King"), NULL, NULL, G_CALLBACK(filter_callback) },
1955 { "FilterBW", NULL, N_("_Butterworth"), NULL, NULL, G_CALLBACK(filter_callback) },
1956 { "FilterPoly", NULL, N_("_Polynomial trend"), NULL, NULL, G_CALLBACK(filter_callback) },
1957 { "FilterFD", NULL, N_("_Fractional difference"), NULL, NULL, G_CALLBACK(filter_callback) },
1958 #ifdef HAVE_X12A
1959 { "X12A", NULL, N_("_X-12-ARIMA analysis"), NULL, NULL, G_CALLBACK(do_tramo_x12a) },
1960 #endif
1961 #ifdef HAVE_TRAMO
1962 { "Tramo", NULL, N_("_TRAMO analysis"), NULL, NULL, G_CALLBACK(do_tramo_x12a) },
1963 #endif
1964 { "Hurst", NULL, N_("_Hurst exponent"), NULL, NULL, G_CALLBACK(do_hurst) },
1965 { "BDS", NULL, N_("BDS nonlinearity test"), NULL, NULL, G_CALLBACK(bds_callback) },
1966 { "tdisagg", NULL, N_("Disaggregate..."), NULL, NULL, G_CALLBACK(tdisagg_callback) },
1967 { "EditAttrs", NULL, N_("_Edit attributes"), NULL, NULL, G_CALLBACK(varinfo_callback) },
1968 { "VSETMISS", NULL, N_("Set missing _value code..."), NULL, NULL, G_CALLBACK(gretl_callback) },
1969 { "GENR", NULL, N_("Define _new variable..."), NULL, NULL, G_CALLBACK(gretl_callback) },
1970
1971 /* Model */
1972 { "Model", NULL, N_("_Model"), NULL, NULL, NULL },
1973 { "ols", NULL, N_("_Ordinary Least Squares"), NULL, NULL, G_CALLBACK(model_callback) },
1974 { "ivreg", NULL, N_("_Instrumental variables"), NULL, NULL, NULL },
1975 { "tsls", NULL, N_("_Two-Stage Least Squares"), NULL, NULL, G_CALLBACK(model_callback) },
1976 { "iv-liml", NULL, N_("_LIML"), NULL, NULL, G_CALLBACK(model_callback) },
1977 { "iv-gmm", NULL, N_("_GMM"), NULL, NULL, G_CALLBACK(model_callback) },
1978 { "LinearModels", NULL, N_("Other _linear models"), NULL, NULL, NULL },
1979 { "wls", NULL, N_("_Weighted Least Squares"), NULL, NULL, G_CALLBACK(model_callback) },
1980 { "hsk", NULL, N_("H_eteroskedasticity corrected"), NULL, NULL, G_CALLBACK(model_callback) },
1981 { "regls", NULL, N_("_Regularized least squares"), NULL, NULL, G_CALLBACK(model_callback) },
1982 { "mpols", NULL, N_("High _precision OLS"), NULL, NULL, G_CALLBACK(model_callback) },
1983 { "anova", NULL, N_("ANOVA"), NULL, NULL, G_CALLBACK(model_callback) },
1984 { "TSModels", NULL, N_("_Univariate time series"), NULL, NULL, NULL },
1985 { "arima", NULL, N_("ARI_MA"), NULL, NULL, G_CALLBACK(model_callback) },
1986 { "garch", NULL, N_("_GARCH"), NULL, NULL, G_CALLBACK(model_callback) },
1987 { "midasreg", NULL, "MIDAS", NULL, NULL, G_CALLBACK(model_callback) },
1988 { "AR-GLS", NULL, N_("_AR errors (GLS)"), NULL, NULL, NULL },
1989 { "ar1", NULL, N_("_AR(1)"), NULL, NULL, G_CALLBACK(model_callback) },
1990 { "ar", NULL, N_("_AR (general)"), NULL, NULL, G_CALLBACK(model_callback) },
1991 { "TSMulti", NULL, N_("_Multivariate time series"), NULL, NULL, NULL },
1992 { "var", NULL, N_("_Vector Autoregression"), NULL, NULL, G_CALLBACK(selector_callback) },
1993 { "VLAGSEL", NULL, N_("VAR _lag selection"), NULL, NULL, G_CALLBACK(selector_callback) },
1994 { "vecm", NULL, N_("V_ECM"), NULL, NULL, G_CALLBACK(selector_callback) },
1995 { "coint2", NULL, N_("Cointegration test (_Johansen)"), NULL, NULL, G_CALLBACK(selector_callback) },
1996 { "coint", NULL, N_("Cointegration test (_Engle-Granger)"), NULL, NULL, G_CALLBACK(selector_callback) },
1997 { "PanelModels", NULL, N_("_Panel"), NULL, NULL, NULL },
1998 { "panel", NULL, N_("_Fixed or random effects"), NULL, NULL, G_CALLBACK(model_callback) },
1999 { "PANEL_WLS", NULL, N_("_Weighted least squares"), NULL, NULL, G_CALLBACK(model_callback) },
2000 { "PANEL_B", NULL, N_("_Between model"), NULL, NULL, G_CALLBACK(model_callback) },
2001 { "dpanel", NULL, N_("_Dynamic panel model"), NULL, NULL, G_CALLBACK(model_callback) },
2002 { "FE_LOGISTIC", NULL, N_("FE logistic"), NULL, NULL, G_CALLBACK(model_callback) },
2003 { "LimdepModels", NULL, N_("_Limited dependent variable"), NULL, NULL, NULL },
2004 { "logit", NULL, N_("_Logit"), NULL, NULL, NULL },
2005 { "blogit", NULL, N_("_Binary"), NULL, NULL, G_CALLBACK(model_callback) },
2006 { "ologit", NULL, N_("_Ordered"), NULL, NULL, G_CALLBACK(model_callback) },
2007 { "mlogit", NULL, N_("_Multinomial"), NULL, NULL, G_CALLBACK(model_callback) },
2008 { "probit", NULL, N_("_Probit"), NULL, NULL, NULL },
2009 { "bprobit", NULL, N_("_Binary"), NULL, NULL, G_CALLBACK(model_callback) },
2010 { "oprobit", NULL, N_("_Ordered"), NULL, NULL, G_CALLBACK(model_callback) },
2011 { "biprobit", NULL, N_("Bi_variate"), NULL, NULL, G_CALLBACK(model_callback) },
2012 { "reprobit", NULL, N_("_Random effects"), NULL, NULL, G_CALLBACK(model_callback) },
2013 { "tobit", NULL, N_("To_bit"), NULL, NULL, G_CALLBACK(model_callback) },
2014 { "heckit", NULL, N_("_Heckit"), NULL, NULL, G_CALLBACK(model_callback) },
2015 { "countmod", NULL, N_("_Count data"), NULL, NULL, G_CALLBACK(model_callback) },
2016 { "duration", NULL, N_("_Duration data"), NULL, NULL, G_CALLBACK(model_callback) },
2017 { "logistic", NULL, N_("Lo_gistic"), NULL, NULL, G_CALLBACK(model_callback) },
2018 { "intreg", NULL, N_("_Interval regression"), NULL, NULL, G_CALLBACK(model_callback) },
2019 { "RobustModels", NULL, N_("_Robust estimation"), NULL, NULL, NULL },
2020 { "lad", NULL, N_("Least _Absolute Deviation"), NULL, NULL, G_CALLBACK(model_callback) },
2021 { "quantreg", NULL, N_("_Quantile regression"), NULL, NULL, G_CALLBACK(model_callback) },
2022 { "loess", NULL, N_("_Loess"), NULL, NULL, G_CALLBACK(selector_callback) },
2023 { "nadarwat", NULL, N_("_Nadaraya-Watson"), NULL, NULL, G_CALLBACK(selector_callback) },
2024 { "nls", NULL, N_("_Nonlinear Least Squares"), NULL, NULL, G_CALLBACK(gretl_callback) },
2025 { "mle", NULL, N_("_Maximum likelihood"), NULL, NULL, G_CALLBACK(gretl_callback) },
2026 { "gmm", NULL, N_("_GMM"), NULL, NULL, G_CALLBACK(gretl_callback) },
2027 { "system", NULL, N_("_Simultaneous equations"), NULL, NULL, G_CALLBACK(gretl_callback) },
2028
2029 /* Help */
2030 { "Help", NULL, N_("_Help"), NULL, NULL, NULL },
2031 { "TextCmdRef", GTK_STOCK_HELP, N_("_Command reference"), HELPKEY, NULL, G_CALLBACK(display_text_help) },
2032 { "FuncRef", GTK_STOCK_HELP, N_("_Function reference"), "", NULL, G_CALLBACK(display_text_help) },
2033 { "PkgHelp", GTK_STOCK_HELP, N_("_Packages"), "", NULL, G_CALLBACK(display_text_help) },
2034 { "UserGuide", GRETL_STOCK_PDF, N_("_User's guide"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2035 { "PDFCmdRef", GRETL_STOCK_PDF, N_("_Command reference"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2036 { "KbdRef", GRETL_STOCK_PDF, N_("_Keyboard shortcuts"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2037 { "Primer", GRETL_STOCK_PDF, N_("_Hansl primer"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2038 { "Pkgbook", GRETL_STOCK_PDF, N_("_Function package guide"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2039 { "gretlMPI", GRETL_STOCK_PDF, N_("_gretl + MPI"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2040 { "gretlSVM", GRETL_STOCK_PDF, N_("_gretl + SVM"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2041 { "gretlDBN", GRETL_STOCK_PDF, N_("_gretl + DB.NOMICS"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2042 { "GeoplotDoc", GRETL_STOCK_PDF, N_("Creating maps"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2043 { "LpsolveDoc", GRETL_STOCK_PDF, N_("Linear programming"), NULL, NULL, G_CALLBACK(display_pdf_help) },
2044 { "UpdateCheck", GTK_STOCK_NETWORK, N_("Check for _updates"), NULL, NULL, G_CALLBACK(update_query) },
2045 { "SFAddons", NULL, N_("Check for _addons"), NULL, NULL, G_CALLBACK(show_files) },
2046 { "About", GTK_STOCK_ABOUT, N_("_About gretl"), NULL, NULL, G_CALLBACK(about_dialog) }
2047 };
2048
count_substrings(gchar ** S)2049 static int count_substrings (gchar **S)
2050 {
2051 int i, n = 0;
2052
2053 for (i=0; S[i] != NULL; i++) {
2054 if (S[i][0] != '\0') {
2055 n++;
2056 }
2057 }
2058
2059 return n;
2060 }
2061
2062 /* Given an "internal" menu path, as in gretlmain.xml (with up
2063 to three slash-separated components), return its user-visible
2064 counterpart, translated and with mnemonics stripped.
2065 */
2066
main_menu_user_string(const gchar * mpath)2067 static gchar *main_menu_user_string (const gchar *mpath)
2068 {
2069 gchar *ret = NULL;
2070 gchar **S;
2071
2072 if (mpath == NULL) {
2073 return NULL;
2074 }
2075
2076 if (!strncmp(mpath, "/menubar/", 9)) {
2077 mpath += 8;
2078 } else if (!strncmp(mpath, "MAINWIN/", 8)) {
2079 mpath += 8;
2080 } else if (*mpath == '/') {
2081 mpath += 1;
2082 } else if (!strncmp(mpath, "MODELWIN/", 9)) {
2083 /* this @mpath is model-window only */
2084 return NULL;
2085 }
2086
2087 S = g_strsplit(mpath, "/", 0);
2088
2089 if (S != NULL && S[0] != NULL) {
2090 const gchar *p[3] = {NULL, NULL, NULL};
2091 int nmain = G_N_ELEMENTS(main_entries);
2092 int i, j, ns = count_substrings(S);
2093 int matched = 0;
2094
2095 for (i=0; i<nmain && !p[0]; i++) {
2096 if (main_entries[i].callback == NULL &&
2097 !strcmp(S[0], main_entries[i].name)) {
2098 p[0] = main_entries[i].label;
2099 matched++;
2100 if (S[1] != NULL) {
2101 for (j=i+1; j<nmain && !p[1]; j++) {
2102 if (main_entries[j].callback == NULL &&
2103 !strcmp(S[1], main_entries[j].name)) {
2104 p[1] = main_entries[j].label;
2105 matched++;
2106 }
2107 }
2108 if (S[2] != NULL) {
2109 for (j=i+1; j<nmain && !p[2]; j++) {
2110 if (main_entries[j].callback == NULL &&
2111 !strcmp(S[2], main_entries[j].name)) {
2112 p[2] = main_entries[j].label;
2113 matched++;
2114 }
2115 }
2116 }
2117 }
2118 }
2119 }
2120 if (matched < ns) {
2121 fprintf(stderr, "Invalid menu path '%s' (matched = %d)\n", mpath, matched);
2122 } else if (p[2] != NULL) {
2123 ret = g_strdup_printf("%s/%s/%s", _(p[0]), _(p[1]), _(p[2]));
2124 } else if (p[1] != NULL) {
2125 ret = g_strdup_printf("%s/%s", _(p[0]), _(p[1]));
2126 } else if (p[0] != NULL) {
2127 ret = g_strdup_printf("%s", _(p[0]));
2128 }
2129 }
2130
2131 g_strfreev(S);
2132
2133 if (ret != NULL) {
2134 gretl_delchar('_', ret);
2135 }
2136
2137 return ret;
2138 }
2139
user_friendly_menu_path(const char * mpath,gboolean modelwin)2140 gchar *user_friendly_menu_path (const char *mpath,
2141 gboolean modelwin)
2142 {
2143 gchar *ret = NULL;
2144
2145 if (modelwin) {
2146 if (!strcmp(mpath, "Analysis")) {
2147 ret = g_strdup(_("_Analysis"));
2148 gretl_delchar('_', ret);
2149 } else {
2150 ret = g_strdup(_(mpath));
2151 }
2152 } else {
2153 ret = main_menu_user_string(mpath);
2154 }
2155
2156 return ret;
2157 }
2158
add_conditional_items(windata_t * vwin)2159 static void add_conditional_items (windata_t *vwin)
2160 {
2161 GtkUIManager *ui = vwin->ui;
2162 int add_appfont = 1;
2163
2164 if (add_appfont) {
2165 gtk_ui_manager_add_ui(ui, gtk_ui_manager_new_merge_id(ui),
2166 "/menubar/Tools/Preferences",
2167 N_("_Menu font..."),
2168 "MenuFont",
2169 GTK_UI_MANAGER_MENUITEM,
2170 FALSE);
2171 }
2172
2173 #ifdef HAVE_X12A
2174 gtk_ui_manager_add_ui(ui, gtk_ui_manager_new_merge_id(ui),
2175 "/menubar/Variable/X12A",
2176 N_("_X-12-ARIMA analysis"),
2177 "X12A",
2178 GTK_UI_MANAGER_MENUITEM,
2179 FALSE);
2180 #endif
2181
2182 #ifdef HAVE_TRAMO
2183 gtk_ui_manager_add_ui(ui, gtk_ui_manager_new_merge_id(ui),
2184 "/menubar/Variable/Tramo",
2185 N_("_TRAMO analysis"),
2186 "Tramo",
2187 GTK_UI_MANAGER_MENUITEM,
2188 FALSE);
2189 #endif
2190
2191 maybe_add_packages_to_menus(vwin);
2192 }
2193
2194 /* retrieve the XML description of the main window menus */
2195
get_main_ui(void)2196 static gchar *get_main_ui (void)
2197 {
2198 gchar *main_ui = NULL;
2199 gchar *fname;
2200 int err;
2201
2202 fname = g_strdup_printf("%sui%cgretlmain.xml", gretl_home(), SLASH);
2203 err = gretl_file_get_contents(fname, &main_ui, NULL);
2204 g_free(fname);
2205
2206 return err ? NULL : main_ui;
2207 }
2208
2209 #ifdef MAC_INTEGRATION
2210
new_gretl_instance(GtkAction * action,gpointer data)2211 static void new_gretl_instance (GtkAction *action, gpointer data)
2212 {
2213 char *topdir = getenv("GTK_DATA_PREFIX");
2214
2215 if (topdir != NULL) {
2216 gchar *cmd;
2217
2218 cmd = g_strdup_printf("open -n %s/../../../Gretl.app", topdir);
2219 system(cmd);
2220 g_free(cmd);
2221 }
2222 }
2223
mac_minimize(GtkAction * action,gpointer data)2224 static void mac_minimize (GtkAction *action, gpointer data)
2225 {
2226 if (data != NULL) {
2227 gtk_window_iconify(GTK_WINDOW(data));
2228 }
2229 }
2230
2231 static GtkActionEntry mac_entries[] = {
2232 { "FileMenu", NULL, "_File", NULL, NULL, NULL },
2233 { "NewInstanceAction", NULL, "_New gretl instance", NULL, NULL,
2234 G_CALLBACK(new_gretl_instance)},
2235 };
2236
2237 const gchar *mac_ui =
2238 "<ui>"
2239 " <menubar>"
2240 " <menu name='File' action='FileMenu'>"
2241 " <menuitem name='NewInstance' action='NewInstanceAction'/>"
2242 " </menu>"
2243 " </menubar>"
2244 "</ui>";
2245
add_mac_menu(void)2246 static GtkUIManager *add_mac_menu (void)
2247 {
2248 GtkUIManager *mgr;
2249 GtkActionGroup *actions;
2250 GtkWidget *menu;
2251 GtkAccelGroup *accel_group;
2252 GError *error = NULL;
2253
2254 mgr = gtk_ui_manager_new();
2255 actions = gtk_action_group_new("MacActions");
2256 gtk_action_group_set_translation_domain(actions, "gretl");
2257 gtk_action_group_add_actions(actions, mac_entries,
2258 G_N_ELEMENTS(mac_entries),
2259 mdata->main);
2260 gtk_ui_manager_insert_action_group(mgr, actions, 0);
2261 g_object_unref(actions);
2262
2263 if (!gtk_ui_manager_add_ui_from_string(mgr, mac_ui, -1, &error)) {
2264 g_message("building mac menu failed: %s", error->message);
2265 g_error_free(error);
2266 }
2267
2268 menu = gtk_ui_manager_get_widget(mgr, "/menubar/");
2269 g_object_ref_sink(menu);
2270
2271 return mgr;
2272 }
2273
2274 /* add minimal top-of-screen gretl menu */
2275
finish_mac_ui(GtkUIManager * mac_mgr)2276 static void finish_mac_ui (GtkUIManager *mac_mgr)
2277 {
2278 GtkWidget *menu;
2279
2280 menu = gtk_ui_manager_get_widget(mac_mgr, "/menubar");
2281 if (menu != NULL) {
2282 /* @menu needs a gtk window toplevel */
2283 gtk_box_pack_end(GTK_BOX(mdata->vbox), menu, FALSE, FALSE, 0);
2284 gtk_widget_hide(menu);
2285 gtkosx_application_set_menu_bar(MacApp, GTK_MENU_SHELL(menu));
2286 }
2287 gtkosx_application_set_use_quartz_accelerators(MacApp, FALSE);
2288 gtkosx_application_ready(MacApp);
2289 }
2290
2291 #endif /* MAC_INTEGRATION */
2292
make_main_menu(void)2293 static GtkWidget *make_main_menu (void)
2294 {
2295 GtkWidget *menu = NULL;
2296 GtkActionGroup *actions;
2297 gchar *main_ui = NULL;
2298 GError *error = NULL;
2299
2300 main_ui = get_main_ui();
2301 #if GUI_DEBUG
2302 fprintf(stderr, " main_ui = %p\n", (void *) main_ui);
2303 #endif
2304 if (main_ui == NULL) {
2305 return NULL;
2306 }
2307
2308 mdata->ui = gtk_ui_manager_new();
2309 actions = gtk_action_group_new("Actions");
2310 gtk_action_group_set_translation_domain(actions, "gretl");
2311 gtk_action_group_add_actions(actions, main_entries,
2312 G_N_ELEMENTS(main_entries), mdata);
2313 gtk_ui_manager_insert_action_group(mdata->ui, actions, 0);
2314 g_object_unref(actions);
2315
2316 gtk_window_add_accel_group(GTK_WINDOW(mdata->main),
2317 gtk_ui_manager_get_accel_group(mdata->ui));
2318
2319 if (!gtk_ui_manager_add_ui_from_string(mdata->ui, main_ui, -1, &error)) {
2320 g_message("building menus failed: %s", error->message);
2321 g_error_free(error);
2322 } else {
2323 #if GUI_DEBUG
2324 fprintf(stderr, " adding conditional menu items...\n");
2325 #endif
2326 add_conditional_items(mdata);
2327 #if GUI_DEBUG
2328 fprintf(stderr, " conditional items done\n");
2329 #endif
2330 menu = gtk_ui_manager_get_widget(mdata->ui, "/menubar");
2331 if (menu == NULL) {
2332 fprintf(stderr, "/menubar widget is NULL!\n");
2333 } else {
2334 GtkWidget *dataitem;
2335
2336 dataitem = gtk_ui_manager_get_widget(mdata->ui, "/menubar/Data");
2337 if (dataitem == NULL) {
2338 fprintf(stderr, "/menubar/Data widget is NULL!\n");
2339 menu = NULL;
2340 } else {
2341 g_signal_connect(G_OBJECT(dataitem), "activate",
2342 G_CALLBACK(check_var_labels_state), mdata);
2343 }
2344 }
2345 }
2346
2347 g_free(main_ui);
2348
2349 return menu;
2350 }
2351
name_new_list(GtkWidget * widget,dialog_t * dlg)2352 static void name_new_list (GtkWidget *widget, dialog_t *dlg)
2353 {
2354 char *lname = (char *) edit_dialog_get_data(dlg);
2355 const gchar *buf = edit_dialog_get_text(dlg);
2356
2357 if (buf == NULL || gui_validate_varname(buf, GRETL_TYPE_LIST, NULL)) {
2358 return;
2359 }
2360
2361 strncat(lname, buf, VNAMELEN - 1);
2362 edit_dialog_close(dlg);
2363 }
2364
real_make_mainwin_list(const int * list,const char * lname)2365 static void real_make_mainwin_list (const int *list,
2366 const char *lname)
2367 {
2368 int err = remember_list(list, lname, NULL);
2369 char *lstr = NULL;
2370
2371 if (err) {
2372 gui_errmsg(err);
2373 } else {
2374 lstr = gretl_list_to_string(list, dataset, &err);
2375 }
2376
2377 if (lstr != NULL) {
2378 /* record to command log */
2379 lib_command_sprintf("list %s =%s", lname, lstr);
2380 record_command_verbatim();
2381 free(lstr);
2382 }
2383 }
2384
2385 /* respond to "Define list", selected from main window
2386 right-click popup menu when two or more series are
2387 selected
2388 */
2389
make_list_from_main(void)2390 void make_list_from_main (void)
2391 {
2392 int *list = main_window_selection_as_list();
2393
2394 if (list != NULL) {
2395 char lname[VNAMELEN];
2396 int cancel = 0;
2397 gchar *msg;
2398
2399 *lname = '\0';
2400 msg = g_strdup_printf("%s\n (%s%s%s)",
2401 _("Enter name for list of series"),
2402 dataset->varname[list[1]],
2403 (list[0] == 2)? " " : " ... ",
2404 dataset->varname[list[list[0]]]);
2405
2406 blocking_edit_dialog(0, _("gretl: name list"), msg,
2407 NULL, name_new_list, lname,
2408 VARCLICK_NONE, mdata->main,
2409 &cancel);
2410 g_free(msg);
2411
2412 if (!cancel && *lname != '\0') {
2413 real_make_mainwin_list(list, lname);
2414 }
2415
2416 free(list);
2417 }
2418 }
2419
gui_restore_sample(DATASET * dset)2420 int gui_restore_sample (DATASET *dset)
2421 {
2422 int err = 0;
2423
2424 if (dset != NULL && dset->Z != NULL) {
2425 err = restore_full_sample(dset, NULL);
2426 if (err) {
2427 gui_errmsg(err);
2428 } else {
2429 restore_sample_state(FALSE);
2430 mark_session_changed();
2431 }
2432 }
2433
2434 return err;
2435 }
2436
restore_sample_callback(void)2437 static void restore_sample_callback (void)
2438 {
2439 int err = gui_restore_sample(dataset);
2440
2441 if (!err) {
2442 set_sample_label(dataset);
2443 lib_command_strcpy("smpl --full");
2444 record_command_verbatim();
2445 }
2446 }
2447
show_sample_callback(void)2448 static void show_sample_callback (void)
2449 {
2450 char *buf;
2451 PRN *prn;
2452
2453 if (bufopen(&prn)) {
2454 return;
2455 }
2456
2457 pprintf(prn, "%s\n\n", _("sample status"));
2458 print_sample_status(dataset, prn);
2459 buf = gretl_print_steal_buffer(prn);
2460 infobox(buf);
2461 free(buf);
2462 gretl_print_destroy(prn);
2463 }
2464
start_R_callback(void)2465 static void start_R_callback (void)
2466 {
2467 start_R(NULL, 1, 1);
2468 }
2469
2470 #ifndef G_OS_WIN32
2471
gretl_fork(const char * progvar,const char * arg,const char * opt)2472 int gretl_fork (const char *progvar, const char *arg,
2473 const char *opt)
2474 {
2475 const char *prog = NULL;
2476 gchar *argv[4] = {NULL, NULL, NULL, NULL};
2477 GError *err = NULL;
2478 gboolean run;
2479
2480 #ifdef OS_OSX
2481 if (!strcmp(progvar, "calculator")) {
2482 prog = calculator;
2483 }
2484 #else
2485 if (!strcmp(progvar, "Browser")) {
2486 prog = Browser;
2487 } else if (!strcmp(progvar, "calculator")) {
2488 prog = calculator;
2489 } else if (!strcmp(progvar, "viewpdf")) {
2490 prog = viewpdf;
2491 } else if (!strcmp(progvar, "viewps")) {
2492 prog = viewps;
2493 } else {
2494 prog = progvar;
2495 }
2496 #endif
2497
2498 if (prog == NULL) {
2499 errbox_printf("Internal error: variable %s is undefined", progvar);
2500 return 1;
2501 }
2502
2503 argv[0] = g_strdup(prog);
2504
2505 if (opt != NULL) {
2506 argv[1] = g_strdup(arg);
2507 argv[2] = g_strdup(opt);
2508 } else if (arg != NULL) {
2509 argv[1] = g_strdup(arg);
2510 }
2511
2512 run = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
2513 NULL, NULL, NULL, &err);
2514
2515 if (err != NULL) {
2516 errbox(err->message);
2517 if (err->domain == G_SPAWN_ERROR &&
2518 err->code == G_SPAWN_ERROR_NOENT) {
2519 preferences_dialog(TAB_PROGS, progvar, mdata->main);
2520 }
2521 g_error_free(err);
2522 }
2523
2524 g_free(argv[0]);
2525 g_free(argv[1]);
2526 g_free(argv[2]);
2527
2528 return !run;
2529 }
2530
2531 #endif
2532
2533 /* Icon handling for X11 */
2534
2535 #ifndef G_OS_WIN32
2536
set_wm_icon(GtkWidget * w)2537 void set_wm_icon (GtkWidget *w)
2538 {
2539 GdkPixbuf *icon = gdk_pixbuf_new_from_xpm_data(gretl_xpm);
2540
2541 # ifdef MAC_INTEGRATION
2542 if (icon != NULL) {
2543 gtkosx_application_set_dock_icon_pixbuf(MacApp, icon);
2544 gtk_window_set_icon(GTK_WINDOW(w), icon);
2545 g_object_unref(icon);
2546 }
2547 # else
2548 if (icon != NULL) {
2549 gtk_window_set_icon(GTK_WINDOW(w), icon);
2550 g_object_unref(icon);
2551 }
2552 # endif
2553 }
2554
2555 #endif /* !G_OS_WIN32 */
2556
has_db_suffix(const char * fname)2557 static int has_db_suffix (const char *fname)
2558 {
2559 return has_suffix(fname, ".bin") ||
2560 has_suffix(fname, ".rat") ||
2561 has_suffix(fname, ".bn7");
2562 }
2563
2564 /* Drag 'n' drop: respond to data dropped into the main window */
2565
2566 static void
mdata_handle_drag(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,gpointer p)2567 mdata_handle_drag (GtkWidget *widget,
2568 GdkDragContext *context,
2569 gint x,
2570 gint y,
2571 GtkSelectionData *data,
2572 guint info,
2573 guint time,
2574 gpointer p)
2575 {
2576 const guchar *seldata = NULL;
2577 gchar *dfname;
2578 char tmp[MAXLEN];
2579 int pos, skip = 5;
2580
2581 if (data != NULL) {
2582 seldata = gtk_selection_data_get_data(data);
2583 }
2584
2585 /* handle drag of pointer from database window */
2586 if (info == GRETL_DBSERIES_PTR && data != NULL) {
2587 drag_import_db_series();
2588 return;
2589 }
2590
2591 if (info != GRETL_FILENAME) {
2592 return;
2593 }
2594
2595 /* ignore the wrong sort of data */
2596 if (data == NULL || (dfname = (gchar *) seldata) == NULL ||
2597 strlen(dfname) <= 5 || strncmp(dfname, "file:", 5)) {
2598 return;
2599 }
2600
2601 if (strncmp(dfname, "file://", 7) == 0) skip = 7;
2602 #ifdef G_OS_WIN32
2603 if (strncmp(dfname, "file:///", 8) == 0) skip = 8;
2604 #endif
2605
2606 /* there may be multiple files: we ignore all but the first */
2607 *tmp = 0;
2608 if ((pos = gretl_charpos('\r', dfname)) > 0 ||
2609 (pos = gretl_charpos('\n', dfname) > 0)) {
2610 strncat(tmp, dfname + skip, pos - skip);
2611 } else {
2612 strcat(tmp, dfname + skip);
2613 }
2614
2615 /* handle spaces and such then transcribe */
2616 unescape_url(tmp);
2617 set_tryfile(tmp);
2618
2619 open_tryfile();
2620 }
2621
open_tryfile(void)2622 gboolean open_tryfile (void)
2623 {
2624 gboolean ret = FALSE;
2625 int ftype = 0;
2626
2627 if (has_db_suffix(tryfile)) {
2628 ret = open_named_db_index(tryfile);
2629 } else if (has_suffix(tryfile, ".gretl") &&
2630 gretl_is_pkzip_file(tryfile)) {
2631 ret = verify_open_session();
2632 } else if ((ftype = script_type(tryfile))) {
2633 ret = do_open_script(ftype);
2634 } else if (has_suffix(tryfile, ".gfn") &&
2635 gretl_is_xml_file(tryfile)) {
2636 ret = edit_specified_package(tryfile);
2637 } else {
2638 ret = verify_open_data(NULL, 0);
2639 }
2640
2641 return ret;
2642 }
2643
2644 /* the callback for Save Data (Ctrl-S) in main window */
2645
auto_store(void)2646 static void auto_store (void)
2647 {
2648 if (data_status & SESSION_DATA) {
2649 /* the data file is embedded in a session file */
2650 save_session_dataset();
2651 } else {
2652 /* ensure there's no stale selection around */
2653 set_selector_storelist(NULL);
2654 if ((data_status & USER_DATA) && has_native_data_suffix(datafile)) {
2655 /* bypass filename selection */
2656 do_store(datafile, AUTO_SAVE_DATA, NULL);
2657 } else {
2658 file_selector(SAVE_DATA, FSEL_DATA_NONE, NULL);
2659 }
2660 }
2661 }
2662
mdata_text_received(GtkClipboard * cb,const gchar * text,gpointer data)2663 static void mdata_text_received (GtkClipboard *cb,
2664 const gchar *text,
2665 gpointer data)
2666 {
2667 if (text != NULL) {
2668 char fullname[FILENAME_MAX];
2669 PRN *prn = NULL;
2670 int append = 0;
2671 int err, resp;
2672
2673 resp = paste_data_dialog(&append);
2674 if (canceled(resp)) {
2675 return;
2676 }
2677
2678 err = user_fopen(CLIPTEMP, fullname, &prn);
2679
2680 if (!err) {
2681 int ci = append ? APPEND_DATA : OPEN_DATA;
2682
2683 pputs(prn, text);
2684 gretl_print_destroy(prn);
2685 set_tryfile(fullname);
2686 do_open_data(NULL, ci);
2687 gretl_remove(fullname);
2688 }
2689 }
2690 }
2691
mdata_handle_paste(void)2692 static void mdata_handle_paste (void)
2693 {
2694 static GtkClipboard *cb;
2695
2696 if (cb == NULL) {
2697 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
2698 }
2699
2700 gtk_clipboard_request_text(cb, mdata_text_received, NULL);
2701 }
2702
mdata_selection_count(void)2703 int mdata_selection_count (void)
2704 {
2705 return vwin_selection_count(mdata, NULL);
2706 }
2707
mdata_active_var(void)2708 int mdata_active_var (void)
2709 {
2710 int selcount, v = 0;
2711
2712 selcount = vwin_selection_count(mdata, &v);
2713
2714 if (selcount == 1 && v != 0) {
2715 mdata->active_var = v;
2716 } else {
2717 mdata->active_var = 0;
2718 }
2719
2720 return mdata->active_var;
2721 }
2722
2723 static gboolean
main_popup_handler(GtkWidget * w,GdkEventButton * event,gpointer data)2724 main_popup_handler (GtkWidget *w, GdkEventButton *event, gpointer data)
2725 {
2726 if (right_click(event)) {
2727 /* ignore all but right-clicks */
2728 int selvar = 0;
2729 int selcount = vwin_selection_count(mdata, &selvar);
2730
2731 if (mdata->popup) {
2732 gtk_widget_destroy(mdata->popup);
2733 mdata->popup = NULL;
2734 }
2735
2736 if (selcount == 1) {
2737 mdata->popup = build_var_popup(selvar);
2738 } else if (selcount > 1) {
2739 mdata->popup = build_selection_popup();
2740 }
2741
2742 if (mdata->popup != NULL) {
2743 gtk_menu_popup(GTK_MENU(mdata->popup), NULL, NULL, NULL, NULL,
2744 event->button, event->time);
2745 g_signal_connect(G_OBJECT(mdata->popup), "destroy",
2746 G_CALLBACK(gtk_widget_destroyed),
2747 &mdata->popup);
2748 }
2749
2750 return TRUE;
2751 }
2752
2753 return FALSE;
2754 }
2755
script_stopper(int set)2756 static int script_stopper (int set)
2757 {
2758 static int stop;
2759 int ret = 0;
2760
2761 if (set) {
2762 /* set the stop signal */
2763 stop = 1;
2764 } else if (stop) {
2765 ret = 1;
2766 stop = 0;
2767 }
2768
2769 return ret;
2770 }
2771
gui_query_stop(void)2772 static int gui_query_stop (void)
2773 {
2774 return script_stopper(0);
2775 }
2776
2777 /* callback from "stop" button in script output viewer */
2778
do_stop_script(GtkWidget * w,windata_t * vwin)2779 void do_stop_script (GtkWidget *w, windata_t *vwin)
2780 {
2781 script_stopper(1);
2782 }
2783