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 "var.h"
22 #include "johansen.h"
23 #include "varprint.h"
24 #include "forecast.h"
25 #include "objstack.h"
26 #include "gretl_xml.h"
27 #include "gretl_func.h"
28 #include "system.h"
29 #include "matrix_extra.h"
30 #include "bootstrap.h"
31 #include "gretl_foreign.h"
32 #include "gretl_typemap.h"
33 #include "uservar.h"
34 #include "gretl_string_table.h"
35 #include "gretl_panel.h"
36 #include "csvdata.h"
37 #include "kalman.h"
38 #include "libset.h"
39
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <errno.h>
43
44 #include "model_table.h"
45 #include "series_view.h"
46 #include "session.h"
47 #include "textbuf.h"
48 #include "textutil.h"
49 #include "cmdstack.h"
50 #include "filelists.h"
51 #include "menustate.h"
52 #include "dlgutils.h"
53 #include "ssheet.h"
54 #include "datafiles.h"
55 #include "gpt_control.h"
56 #include "fileselect.h"
57 #include "toolbar.h"
58 #include "winstack.h"
59 #include "fnsave.h"
60 #include "datawiz.h"
61 #include "selector.h"
62 #include "guiprint.h"
63 #include "fncall.h"
64 #include "tabwin.h"
65 #include "join-gui.h"
66 #include "gretl_ipc.h"
67
68 #ifdef G_OS_WIN32
69 # include <windows.h>
70 # include "gretlwin32.h"
71 #endif
72
73 static void set_up_model_view_menu (windata_t *vwin);
74 static void add_system_menu_items (windata_t *vwin, int role);
75 static void add_x12_output_menu_item (windata_t *vwin);
76 static gint check_model_menu (GtkWidget *w, GdkEventButton *eb,
77 gpointer data);
78 static gint check_VAR_menu (GtkWidget *w, GdkEventButton *eb,
79 gpointer data);
80 static void model_copy_callback (GtkAction *action, gpointer p);
81 static int set_sample_from_model (void *ptr, int role);
82 static gboolean maybe_set_sample_from_model (windata_t *vwin);
83
close_model(GtkAction * action,gpointer data)84 static void close_model (GtkAction *action, gpointer data)
85 {
86 windata_t *vwin = (windata_t *) data;
87
88 gretl_viewer_destroy(vwin);
89 }
90
arma_by_x12a(const MODEL * pmod)91 static int arma_by_x12a (const MODEL *pmod)
92 {
93 int ret = 0;
94
95 if (pmod->ci == ARMA) {
96 int acode = gretl_model_get_int(pmod, "arma_flags");
97
98 if (acode & ARMA_X12A) {
99 ret = 1;
100 }
101 }
102
103 return ret;
104 }
105
latex_is_ok(void)106 int latex_is_ok (void)
107 {
108 static int latex_ok = -1;
109
110 if (latex_ok == -1) {
111 latex_ok = check_for_program(latex);
112 }
113
114 return latex_ok;
115 }
116
model_output_save(GtkAction * action,gpointer p)117 static void model_output_save (GtkAction *action, gpointer p)
118 {
119 copy_format_dialog((windata_t *) p, W_SAVE);
120 }
121
122 static gretlopt tex_eqn_opt;
123
set_tex_eqn_opt(GtkRadioAction * action)124 static void set_tex_eqn_opt (GtkRadioAction *action)
125 {
126 int v = gtk_radio_action_get_current_value(action);
127
128 tex_eqn_opt = (v)? OPT_T : OPT_NONE;
129 }
130
get_tex_eqn_opt(void)131 gretlopt get_tex_eqn_opt (void)
132 {
133 return tex_eqn_opt;
134 }
135
model_get_t1_t2(void * ptr,int role,int * t1,int * t2)136 static int model_get_t1_t2 (void *ptr, int role, int *t1, int *t2)
137 {
138 int err = 0;
139
140 if (role == VIEW_MODEL) {
141 MODEL *pmod = ptr;
142
143 *t1 = pmod->smpl.t1;
144 *t2 = pmod->smpl.t2;
145 } else if (role == VAR || role == VECM) {
146 GRETL_VAR *var = ptr;
147
148 err = gretl_var_get_sample(var, t1, t2);
149 } else if (role == SYSTEM) {
150 equation_system *sys = ptr;
151
152 err = gretl_system_get_sample(sys, t1, t2);
153 }
154
155 return err;
156 }
157
158 /* Called from menu in model window, but not necessarily
159 a single-equation model */
160
model_revise_callback(GtkAction * action,gpointer p)161 static void model_revise_callback (GtkAction *action, gpointer p)
162 {
163 windata_t *vwin = (windata_t *) p;
164 int ok = 1, t1 = 0, t2 = 0;
165 int err = 0;
166
167 if (vwin->role == VIEW_MODEL) {
168 MODEL *pmod = vwin->data;
169
170 err = model_sample_problem(pmod, dataset);
171 }
172
173 if (!err) {
174 err = model_get_t1_t2(vwin->data, vwin->role, &t1, &t2);
175 }
176
177 if (!err && (t1 != dataset->t1 || t2 != dataset->t2)) {
178 ok = maybe_set_sample_from_model(vwin);
179 }
180
181 if (ok) {
182 selector_from_model(vwin);
183 }
184 }
185
gretl_window_title(const char * s)186 gchar *gretl_window_title (const char *s)
187 {
188 if (s != NULL) {
189 return g_strdup_printf("gretl: %s", s);
190 } else {
191 return g_strdup("gretl: untitled");
192 }
193 }
194
text_eqn_callback(GtkAction * action,gpointer p)195 static void text_eqn_callback (GtkAction *action, gpointer p)
196 {
197 windata_t *vwin = (windata_t *) p;
198 MODEL *pmod = vwin->data;
199 PRN *prn;
200 int err;
201
202 if (bufopen(&prn)) {
203 return;
204 }
205
206 err = text_print_equation(pmod, dataset, OPT_NONE, prn);
207
208 if (err) {
209 gui_errmsg(err);
210 } else {
211 gchar *title = gretl_window_title(_("equation"));
212
213 view_buffer_with_parent(vwin, prn, 78, 200, title, PRINT, NULL);
214 g_free(title);
215 }
216 }
217
218 static GtkActionEntry model_items[] = {
219 { "File", NULL, N_("_File"), NULL, NULL, NULL },
220 { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save as..."), NULL, NULL, G_CALLBACK(model_output_save) },
221 { "SaveAsIcon", NULL, N_("Save to session as _icon"), NULL, NULL, G_CALLBACK(model_add_as_icon) },
222 { "SaveAndClose", NULL, N_("Save as icon and cl_ose"), NULL, NULL, G_CALLBACK(model_add_as_icon) },
223 { "Print", GTK_STOCK_PRINT, N_("_Print..."), NULL, NULL, G_CALLBACK(window_print) },
224 { "TextEqn", NULL, N_("View as equation"), NULL, NULL, G_CALLBACK(text_eqn_callback) },
225 { "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(close_model) },
226 { "Edit", NULL, N_("_Edit"), NULL, NULL, NULL },
227 { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL, NULL, G_CALLBACK(model_copy_callback) },
228 { "Revise", GTK_STOCK_EDIT, N_("_Modify model..."), NULL, NULL,
229 G_CALLBACK(model_revise_callback) },
230 #if 0
231 { "Restore", NULL, N_("_Restore model sample"), NULL, NULL, G_CALLBACK(model_sample_callback) },
232 #endif
233 { "Tests", NULL, N_("_Tests"), NULL, NULL, NULL },
234 { "Save", NULL, N_("_Save"), NULL, NULL, NULL },
235 { "Graphs", NULL, N_("_Graphs"), NULL, NULL, NULL },
236 { "ResidPlot", NULL, N_("_Residual plot"), NULL, NULL, NULL },
237 { "FittedActualPlot", NULL, N_("_Fitted, actual plot"), NULL, NULL, NULL },
238 { "Analysis", NULL, N_("_Analysis"), NULL, NULL, NULL },
239 { "DisplayAFR", NULL, N_("_Display actual, fitted, residual"), NULL, NULL,
240 G_CALLBACK(display_fit_resid) },
241 { "Forecasts", NULL, N_("_Forecasts..."), NULL, NULL, G_CALLBACK(gui_do_forecast) },
242 { "ConfIntervals", NULL, N_("_Confidence intervals for coefficients"), NULL, NULL,
243 G_CALLBACK(do_coeff_intervals) },
244 { "ConfEllipse", NULL, N_("Confidence _ellipse..."), NULL, NULL, G_CALLBACK(selector_callback) },
245 { "Covariance", NULL, N_("Coefficient covariance _matrix"), NULL, NULL, G_CALLBACK(do_outcovmx) },
246 { "Collinearity", NULL, N_("_Collinearity"), NULL, NULL, G_CALLBACK(do_collin) },
247 { "Leverage", NULL, N_("_Influential observations"), NULL, NULL, G_CALLBACK(do_leverage) },
248 { "ANOVA", NULL, N_("_ANOVA"), NULL, NULL, G_CALLBACK(do_anova) },
249 { "Bootstrap", NULL, N_("_Bootstrap..."), NULL, NULL, G_CALLBACK(do_bootstrap) }
250 };
251
252 static GtkActionEntry model_test_items[] = {
253 { "omit", NULL, N_("_Omit variables"), NULL, NULL, G_CALLBACK(selector_callback) },
254 { "add", NULL, N_("_Add variables"), NULL, NULL, G_CALLBACK(selector_callback) },
255 { "coeffsum", NULL, N_("_Sum of coefficients"), NULL, NULL, G_CALLBACK(selector_callback) },
256 { "restrict", NULL, N_("_Linear restrictions"), NULL, NULL, G_CALLBACK(gretl_callback) },
257 { "modtest:s", NULL, N_("Non-linearity (s_quares)"), NULL, NULL, G_CALLBACK(do_modtest) },
258 { "modtest:l", NULL, N_("Non-linearity (_logs)"), NULL, NULL, G_CALLBACK(do_modtest) },
259 { "reset", NULL, N_("_Ramsey's RESET"), NULL, NULL, G_CALLBACK(do_reset) },
260 { "Hsk", NULL, N_("_Heteroskedasticity"), NULL, NULL, NULL },
261 { "modtest:n", NULL, N_("_Normality of residual"), NULL, NULL, G_CALLBACK(do_resid_freq) },
262 { "chow", NULL, N_("_Chow test"), NULL, NULL, G_CALLBACK(do_chow_cusum) },
263 { "modtest:a", NULL, N_("_Autocorrelation"), NULL, NULL, G_CALLBACK(do_autocorr) },
264 { "dwpval", NULL, N_("_Durbin-Watson p-value"), NULL, NULL, G_CALLBACK(do_dwpval) },
265 { "modtest:h", NULL, N_("A_RCH"), NULL, NULL, G_CALLBACK(do_arch) },
266 { "bds", NULL, N_("Non-linearity (_BDS)"), NULL, NULL, G_CALLBACK(do_resid_freq) },
267 { "qlrtest", NULL, N_("_QLR test"), NULL, NULL, G_CALLBACK(do_chow_cusum) },
268 { "cusum", NULL, N_("_CUSUM test"), NULL, NULL, G_CALLBACK(do_chow_cusum) },
269 { "cusum:r", NULL, N_("CUSUM_SQ test"), NULL, NULL, G_CALLBACK(do_chow_cusum) },
270 { "modtest:c", NULL, N_("_Common factor"), NULL, NULL, G_CALLBACK(do_modtest) },
271 { "modtest:d", NULL, N_("_Cross-sectional dependence"), NULL, NULL, G_CALLBACK(do_modtest) },
272 { "panspec", NULL, N_("_Panel specification"), NULL, NULL, G_CALLBACK(do_panel_tests) }
273 };
274
275 static GtkActionEntry base_hsk_items[] = {
276 { "White", NULL, N_("White's test"), NULL, NULL, G_CALLBACK(do_modtest) },
277 { "WhiteSquares", NULL, N_("White's test (squares only)"), NULL, NULL, G_CALLBACK(do_modtest) },
278 { "BreuschPagan", NULL, "Breusch-Pagan", NULL, NULL, G_CALLBACK(do_modtest) },
279 { "Koenker", NULL, "Koenker", NULL, NULL, G_CALLBACK(do_modtest) }
280 };
281
282 static GtkActionEntry panel_hsk_items[] = {
283 { "White", NULL, N_("White's test"), NULL, NULL, G_CALLBACK(do_modtest) },
284 { "Groupwise", NULL, N_("_groupwise"), NULL, NULL, G_CALLBACK(do_modtest) }
285 };
286
287 static GtkActionEntry ivreg_hsk_items[] = {
288 { "White", NULL, N_("Pesaran-Taylor test"), NULL, NULL, G_CALLBACK(do_modtest) }
289 };
290
291 const gchar *model_tex_ui =
292 "<ui>"
293 " <menubar>"
294 " <menu action='LaTeX'>"
295 " <menu action='TeXView'>"
296 " <menuitem action='TabView'/>"
297 " <menuitem action='EqnView'/>"
298 " </menu>"
299 " <menu action='TeXCopy'>"
300 " <menuitem action='TabCopy'/>"
301 " <menuitem action='EqnCopy'/>"
302 " </menu>"
303 " <menu action='TeXSave'>"
304 " <menuitem action='TabSave'/>"
305 " <menuitem action='EqnSave'/>"
306 " </menu>"
307 " <menu action='EqnOpts'>"
308 " <menuitem action='TeXstderrs'/>"
309 " <menuitem action='TeXtratios'/>"
310 " </menu>"
311 " <menuitem action='TabOpts'/>"
312 " </menu>"
313 " </menubar>"
314 "</ui>";
315
316 const gchar *missing_tex_ui =
317 "<ui>"
318 " <menubar>"
319 " <menu action='LaTeX'>"
320 " <menuitem action='notex'/>"
321 " </menu>"
322 " </menubar>"
323 "</ui>";
324
325 static GtkActionEntry model_tex_items[] = {
326 { "LaTeX", NULL, N_("_LaTeX"), NULL, NULL, NULL },
327 { "TeXView", NULL, N_("_View"), NULL, NULL, NULL },
328 { "TabView", NULL, N_("_Tabular"), NULL, NULL, G_CALLBACK(model_tex_view) },
329 { "EqnView", NULL, N_("_Equation"), NULL, NULL, G_CALLBACK(model_tex_view) },
330 { "TeXCopy", NULL, N_("_Copy"), NULL, NULL, NULL },
331 { "TabCopy", NULL, N_("_Tabular"), NULL, NULL, G_CALLBACK(model_tex_copy) },
332 { "EqnCopy", NULL, N_("_Equation"), NULL, NULL, G_CALLBACK(model_tex_copy) },
333 { "TeXSave", NULL, N_("_Save"), NULL, NULL, NULL },
334 { "TabSave", NULL, N_("_Tabular"), NULL, NULL, G_CALLBACK(model_tex_save) },
335 { "EqnSave", NULL, N_("_Equation"), NULL, NULL, G_CALLBACK(model_tex_save) },
336 { "EqnOpts", NULL, N_("_Equation options"), NULL, NULL, NULL },
337 { "TabOpts", NULL, N_("_Tabular options..."), NULL, NULL, G_CALLBACK(tex_format_dialog) }
338 };
339
340 static GtkRadioActionEntry tex_eqn_items[] = {
341 { "TeXstderrs", NULL, N_("Show _standard errors"), NULL, NULL, 0 },
342 { "TeXtratios", NULL, N_("Show _t-ratios"), NULL, NULL, 1 },
343 };
344
345 static GtkActionEntry missing_tex_items[] = {
346 { "LaTeX", NULL, N_("_LaTeX"), NULL, NULL, NULL },
347 { "notex", NULL, "No TeX", NULL, NULL, G_CALLBACK(dummy_call) }
348 };
349
350 static GtkActionEntry system_items[] = {
351 { "File", NULL, N_("_File"), NULL, NULL, NULL },
352 { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save as..."), NULL, NULL, G_CALLBACK(model_output_save) },
353 { "SaveAsIcon", NULL, N_("Save to session as _icon"), NULL, NULL, G_CALLBACK(model_add_as_icon) },
354 { "SaveAndClose", NULL, N_("Save as icon and cl_ose"), NULL, NULL, G_CALLBACK(model_add_as_icon) },
355 { "Print", GTK_STOCK_PRINT, N_("_Print..."), NULL, NULL, G_CALLBACK(window_print) },
356 { "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(close_model) },
357 { "Edit", NULL, N_("_Edit"), NULL, NULL, NULL },
358 { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL, NULL, G_CALLBACK(model_copy_callback) },
359 { "Revise", GTK_STOCK_EDIT, N_("_Revise specification..."), NULL, NULL,
360 G_CALLBACK(model_revise_callback) },
361 { "Save", NULL, N_("_Save"), NULL, NULL, NULL },
362 { "Tests", NULL, N_("_Tests"), NULL, NULL, NULL },
363 { "Graphs", NULL, N_("_Graphs"), NULL, NULL, NULL },
364 { "Analysis", NULL, N_("_Analysis"), NULL, NULL, NULL },
365 { "Forecasts", NULL, N_("_Forecasts"), NULL, NULL, NULL },
366 };
367
368 static gint n_system_items = G_N_ELEMENTS(system_items);
369
370 static GtkActionEntry sys_tex_items[] = {
371 { "LaTeX", NULL, N_("_LaTeX"), NULL, NULL, NULL },
372 { "TeXView", NULL, N_("_View"), NULL, NULL, G_CALLBACK(model_tex_view) },
373 { "TeXCopy", NULL, N_("_Copy"), NULL, NULL, G_CALLBACK(model_tex_copy) },
374 { "TeXSave", NULL, N_("_Save"), NULL, NULL, G_CALLBACK(model_tex_save) },
375 };
376
377 static const gchar *sys_ui =
378 "<ui>"
379 " <menubar>"
380 " <menu action='File'>"
381 " <menuitem action='SaveAs'/>"
382 " <menuitem action='SaveAsIcon'/>"
383 " <menuitem action='SaveAndClose'/>"
384 " <menuitem action='Print'/>"
385 " <menuitem action='Close'/>"
386 " </menu>"
387 " <menu action='Edit'>"
388 " <menuitem action='Copy'/>"
389 " <menuitem action='Revise'/>"
390 " </menu>"
391 " <menu action='Tests'/>"
392 " <menu action='Save'/>"
393 " <menu action='Graphs'/>"
394 " <menu action='Analysis'>"
395 " <menu action='Forecasts'/>"
396 " </menu>"
397 " </menubar>"
398 "</ui>";
399
model_copy_callback(GtkAction * action,gpointer p)400 static void model_copy_callback (GtkAction *action, gpointer p)
401 {
402 copy_format_dialog((windata_t *) p, W_COPY);
403 }
404
copyfile(const char * src,const char * dest)405 int copyfile (const char *src, const char *dest)
406 {
407 FILE *srcfd, *destfd;
408 char buf[GRETL_BUFSIZE];
409 size_t n;
410
411 if (!strcmp(src, dest)) {
412 return 0;
413 }
414
415 if ((srcfd = gretl_fopen(src, "rb")) == NULL) {
416 file_read_errbox(src);
417 return E_FOPEN;
418 }
419
420 if ((destfd = gretl_fopen(dest, "wb")) == NULL) {
421 file_write_errbox(dest);
422 fclose(srcfd);
423 return E_FOPEN;
424 }
425
426 while ((n = fread(buf, 1, sizeof buf, srcfd)) > 0) {
427 fwrite(buf, 1, n, destfd);
428 }
429
430 fclose(srcfd);
431 fclose(destfd);
432
433 return 0;
434 }
435
gretl_tempfile_open(char * fname)436 FILE *gretl_tempfile_open (char *fname)
437 {
438 FILE *fp;
439
440 strcat(fname, ".XXXXXX");
441 fp = gretl_mktemp(fname, "w+");
442
443 if (fp == NULL) {
444 errbox(_("Couldn't open temp file"));
445 }
446
447 return fp;
448 }
449
delete_file(GtkWidget * widget,char * fname)450 static void delete_file (GtkWidget *widget, char *fname)
451 {
452 gretl_remove(fname);
453 g_free(fname);
454 }
455
delete_widget(GtkWidget * widget,gpointer data)456 void delete_widget (GtkWidget *widget, gpointer data)
457 {
458 gtk_widget_destroy(GTK_WIDGET(data));
459 }
460
set_wait_cursor(GdkWindow ** pcwin)461 void set_wait_cursor (GdkWindow **pcwin)
462 {
463 GdkDisplay *disp = gdk_display_get_default();
464 GdkWindow *w;
465
466 if (*pcwin == NULL) {
467 gint x, y;
468
469 *pcwin = w = gdk_display_get_window_at_pointer(disp, &x, &y);
470 } else {
471 w = *pcwin;
472 }
473
474 if (w != NULL) {
475 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
476
477 if (cursor != NULL) {
478 gdk_window_set_cursor(w, cursor);
479 gdk_display_sync(disp);
480 gdk_cursor_unref(cursor);
481 }
482 }
483 }
484
unset_wait_cursor(GdkWindow * cwin)485 void unset_wait_cursor (GdkWindow *cwin)
486 {
487 if (cwin != NULL) {
488 gdk_window_set_cursor(cwin, NULL);
489 }
490 }
491
not_space(gunichar c,gpointer p)492 static gboolean not_space (gunichar c, gpointer p)
493 {
494 return !g_unichar_isspace(c);
495 }
496
vwin_subselection_present(windata_t * vwin)497 int vwin_subselection_present (windata_t *vwin)
498 {
499 GtkTextIter selstart, selend;
500 GtkTextBuffer *buf;
501 int ret = 0;
502
503 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
504
505 if (gtk_text_buffer_get_selection_bounds(buf, &selstart, &selend)) {
506 GtkTextIter start, end;
507
508 gtk_text_buffer_get_bounds(buf, &start, &end);
509 if (gtk_text_iter_equal(&selstart, &start) &&
510 gtk_text_iter_equal(&selend, &end)) {
511 ret = 0;
512 } else {
513 gtk_text_iter_forward_find_char(&start, not_space,
514 NULL, &selstart);
515 gtk_text_iter_backward_find_char(&end, not_space,
516 NULL, &selend);
517 if (!gtk_text_iter_equal(&selstart, &start) ||
518 !gtk_text_iter_equal(&selend, &end)) {
519 ret = 1;
520 }
521 }
522 }
523
524 return ret;
525 }
526
vwin_is_editing(windata_t * vwin)527 int vwin_is_editing (windata_t *vwin)
528 {
529 if (vwin != NULL && vwin->text != NULL) {
530 return gtk_text_view_get_editable(GTK_TEXT_VIEW(vwin->text));
531 } else {
532 return 0;
533 }
534 }
535
vwin_copy_callback(GtkWidget * w,windata_t * vwin)536 gboolean vwin_copy_callback (GtkWidget *w, windata_t *vwin)
537 {
538 if (vwin_subselection_present(vwin)) {
539 window_copy(vwin, GRETL_FORMAT_SELECTION);
540 } else if (vwin_is_editing(vwin)) {
541 window_copy(vwin, GRETL_FORMAT_TXT);
542 } else {
543 copy_format_dialog(vwin, W_COPY);
544 }
545
546 return TRUE;
547 }
548
numeric_keyval(guint key)549 static int numeric_keyval (guint key)
550 {
551 if (key >= GDK_1 && key <= GDK_9) {
552 return key - GDK_0;
553 } else if (key >= GDK_KP_1 && key <= GDK_KP_9) {
554 return key - GDK_KP_0;
555 } else {
556 return 0;
557 }
558 }
559
560 #define nav_key(k) (k==GDK_Up || k==GDK_Down || \
561 k==GDK_Page_Up || k==GDK_Page_Down || \
562 k==GDK_End || k==GDK_Begin || k==GDK_Home)
563
jump_to_finder(guint keyval,windata_t * vwin)564 static gint jump_to_finder (guint keyval, windata_t *vwin)
565 {
566 if (!nav_key(keyval)) {
567 gchar *letter = gdk_keyval_name(keyval);
568
569 if (letter != NULL) {
570 /* snap to search box */
571 gtk_widget_grab_focus(vwin->finder);
572 gtk_entry_set_text(GTK_ENTRY(vwin->finder), letter);
573 gtk_editable_set_position(GTK_EDITABLE(vwin->finder), -1);
574 return TRUE; /* handled */
575 }
576 }
577
578 return FALSE;
579 }
580
vwin_select_all(windata_t * vwin)581 static void vwin_select_all (windata_t *vwin)
582 {
583 if (vwin != NULL && vwin->text != NULL) {
584 GtkTextBuffer *tbuf;
585
586 tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
587
588 if (tbuf != NULL) {
589 GtkTextIter start, end;
590
591 gtk_text_buffer_get_start_iter(tbuf, &start);
592 gtk_text_buffer_get_end_iter(tbuf, &end);
593 gtk_text_buffer_select_range(tbuf, &start, &end);
594 }
595 }
596 }
597
598 /* GDK_KEY_A 0x041 .. GDK_KEY_Z 0x05a
599 GDK_KEY_a 0x061 .. GDK_KEY_z 0x07a
600 */
601
602 struct greek_map {
603 guint key; /* Latin letter key */
604 guint grk; /* "corresponding" Greek letter */
605 };
606
607 static struct greek_map greek_keys[] = {
608 { GDK_A, 0x91 }, /* alpha */
609 { GDK_B, 0x92 }, /* beta */
610 { GDK_C, 0xa7 }, /* chi */
611 { GDK_D, 0x94 }, /* delta */
612 { GDK_E, 0x95 }, /* epsilon */
613 { GDK_F, 0xa6 }, /* phi */
614 { GDK_G, 0x93 }, /* gamma */
615 { GDK_H, 0x97 }, /* eta */
616 { GDK_I, 0x99 }, /* iota */
617 { GDK_J, 0xa8 }, /* psi */
618 { GDK_K, 0x9a }, /* kappa */
619 { GDK_L, 0x9b }, /* lambda */
620 { GDK_M, 0x9c }, /* mu */
621 { GDK_N, 0x9d }, /* nu */
622 { GDK_O, 0x9f }, /* omicron */
623 { GDK_P, 0xa0 }, /* pi */
624 { GDK_Q, 0x98 }, /* theta */
625 { GDK_R, 0xa1 }, /* rho */
626 { GDK_S, 0xa3 }, /* sigma */
627 { GDK_T, 0xa4 }, /* tau */
628 { GDK_U, 0xa5 }, /* upsilon */
629 { GDK_V, 0x9d }, /* nu (again) */
630 { GDK_W, 0xa9 }, /* omega */
631 { GDK_X, 0x9e }, /* xi */
632 { GDK_Y, 0xa5 }, /* upsilon (again) */
633 { GDK_Z, 0x96 } /* zeta */
634 };
635
636 /* Note: exclude Greek capital letters that are indistinguishable from
637 Latin caps.
638 */
639
640 #define ok_greek_cap(k) (k == GDK_D || k == GDK_F || k == GDK_G || \
641 k == GDK_J || k == GDK_L || k == GDK_P || \
642 k == GDK_Q || k == GDK_S || k == GDK_U || \
643 k == GDK_W || k == GDK_X || k == GDK_Y)
644
maybe_insert_greek(guint key,windata_t * vwin)645 static int maybe_insert_greek (guint key, windata_t *vwin)
646 {
647 guint lc = 0, ukey = 0;
648
649 if (key >= GDK_a && key <= GDK_z) {
650 ukey = gdk_keyval_to_upper(key);
651 lc = 1;
652 } else if (key >= GDK_A && key <= GDK_Z) {
653 if (ok_greek_cap(key)) {
654 ukey = key;
655 } else {
656 /* insert the look-alike? */
657 textview_insert_text(vwin->text, gdk_keyval_name(key));
658 return 1;
659 }
660 }
661
662 if (ukey > 0) {
663 int i, n = G_N_ELEMENTS(greek_keys);
664 unsigned char g, ins[3] = {0};
665
666 for (i=0; i<n; i++) {
667 if (ukey == greek_keys[i].key) {
668 g = greek_keys[i].grk;
669 if (lc) {
670 ins[0] = g > 0x9f ? 0xCF : 0xCE;
671 ins[1] = g > 0x9f ? g - 0x20 : g + 0x20;
672 } else {
673 ins[0] = 0xCE;
674 ins[1] = g;
675 }
676 textview_insert_text(vwin->text, (char *) ins);
677 return 1;
678 }
679 }
680 }
681
682 return 0;
683 }
684
685 /* Signal attached to editor/viewer windows. Note that @w is
686 generally the top-level GtkWidget vwin->main; exceptions
687 are (a) tabbed windows, where @w is the embedding window,
688 and (b) help windows, where @w is the text area.
689 */
690
catch_viewer_key(GtkWidget * w,GdkEventKey * event,windata_t * vwin)691 gint catch_viewer_key (GtkWidget *w, GdkEventKey *event,
692 windata_t *vwin)
693 {
694 int Ctrl = (event->state & GDK_CONTROL_MASK);
695 int Alt = (event->state & GDK_MOD1_MASK);
696 guint upkey = event->keyval;
697 int editing = vwin_is_editing(vwin);
698 int console = vwin->role == CONSOLE;
699
700 if (vwin_is_busy(vwin)) {
701 return TRUE;
702 }
703
704 #if 0
705 fprintf(stderr, "HERE catch_viewer_key\n"
706 " editing=%d, console=%d, Ctrl=%d, Alt=%d, key=%s\n",
707 editing, console, Ctrl, Alt, gdk_keyval_name(upkey));
708 #endif
709
710 if (editing && Alt && !Ctrl) {
711 /* "Alt" specials for editor */
712 if (maybe_insert_greek(upkey, vwin)) {
713 return TRUE;
714 } else if (upkey == GDK_minus) {
715 textview_insert_text(vwin->text, "~");
716 return TRUE;
717 }
718 }
719
720 if (is_control_key(event->keyval)) {
721 return FALSE;
722 }
723
724 if (!gdk_keyval_is_upper(event->keyval)) {
725 upkey = gdk_keyval_to_upper(event->keyval);
726 }
727
728 #ifdef OS_OSX
729 if (!Ctrl && cmd_key(event)) {
730 /* treat Command as Ctrl */
731 Ctrl = 1;
732 }
733 #endif
734
735 if (Ctrl && !Alt) {
736 if (upkey == GDK_F) {
737 text_find(NULL, vwin);
738 return TRUE;
739 } else if (upkey == GDK_G) {
740 text_find_again(NULL, vwin);
741 return TRUE;
742 } else if (upkey == GDK_C) {
743 /* Ctrl-C: copy */
744 return vwin_copy_callback(NULL, vwin);
745 } else if (editing && !console) {
746 /* note that the standard Ctrl-key sequences for editing
747 are handled by GTK, so we only need to put our own
748 "specials" here
749 */
750 if (upkey == GDK_H) {
751 text_replace(NULL, vwin);
752 return TRUE;
753 } else if (upkey == GDK_S) {
754 /* Ctrl-S: save */
755 vwin_save_callback(NULL, vwin);
756 return TRUE;
757 } else if (upkey == GDK_Q || upkey == GDK_W) {
758 if (!window_is_tab(vwin)) {
759 /* Ctrl-Q or Ctrl-W, quit: but not for tabbed windows */
760 if (vwin_content_changed(vwin)) {
761 /* conditional: we have unsaved changes */
762 if (query_save_text(NULL, NULL, vwin) == FALSE) {
763 gtk_widget_destroy(w);
764 }
765 } else {
766 /* unconditional */
767 gtk_widget_destroy(w);
768 }
769 return TRUE;
770 }
771 } else if (upkey == GDK_T && window_is_tab(vwin)) {
772 /* Ctrl-T: open new tab */
773 do_new_script(vwin->role, NULL);
774 return TRUE;
775 }
776 }
777 if (window_is_tab(vwin)) {
778 /* note: still conditional on Ctrl */
779 if (upkey == GDK_greater || upkey == GDK_less ||
780 upkey == GDK_Page_Up || upkey == GDK_Page_Down) {
781 tabwin_navigate(vwin, upkey);
782 return TRUE;
783 }
784 } else if (upkey == GDK_Q || upkey == GDK_W) {
785 gtk_widget_destroy(vwin->main);
786 return TRUE;
787 }
788 } else if (Alt && !console) {
789 if (upkey == GDK_C && vwin->role == SCRIPT_OUT) {
790 cascade_session_windows();
791 return TRUE;
792 } else if (window_is_tab(vwin)) {
793 int k = numeric_keyval(upkey);
794
795 if (k > 0) {
796 tabwin_navigate(vwin, k);
797 return TRUE;
798 }
799 }
800 }
801
802 if (editing || (vwin->finder != NULL && gtk_widget_has_focus(vwin->finder))) {
803 /* we set up "special" responses to some plain keystrokes
804 below: this won't do if we're in editing/typing mode
805 */
806 return FALSE;
807 }
808
809 if (!event->state && vwin->finder != NULL && GTK_IS_ENTRY(vwin->finder)) {
810 if (jump_to_finder(event->keyval, vwin)) {
811 /* FIXME is this really wanted? */
812 return TRUE;
813 }
814 }
815
816 if (!Alt) {
817 if (upkey == GDK_A && Ctrl) {
818 vwin_select_all(vwin);
819 return TRUE;
820 } else if (upkey == GDK_Q || (upkey == GDK_W && Ctrl)) {
821 if (w == vwin->main) {
822 gtk_widget_destroy(w);
823 }
824 } else if (upkey == GDK_S && data_status && vwin->role == VIEW_MODEL) {
825 model_add_as_icon(NULL, vwin);
826 }
827 }
828
829 return FALSE;
830 }
831
nomem(void)832 void nomem (void)
833 {
834 errbox(_("Out of memory!"));
835 }
836
mymalloc(size_t size)837 void *mymalloc (size_t size)
838 {
839 void *mem;
840
841 if ((mem = malloc(size)) == NULL) {
842 nomem();
843 }
844
845 return mem;
846 }
847
myrealloc(void * ptr,size_t size)848 void *myrealloc (void *ptr, size_t size)
849 {
850 void *mem;
851
852 if ((mem = realloc(ptr, size)) == NULL) {
853 nomem();
854 }
855
856 return mem;
857 }
858
mark_dataset_as_modified(void)859 void mark_dataset_as_modified (void)
860 {
861 data_status |= MODIFIED_DATA;
862 set_sample_label(dataset);
863
864 if (session_file_is_open()) {
865 mark_session_changed();
866 }
867 }
868
path_last_slash_const(const char * path)869 const char *path_last_slash_const (const char *path)
870 {
871 return (const char *) strrslash(path);
872 }
873
gretl_basename(char * dest,const char * src,int addscore)874 char *gretl_basename (char *dest, const char *src, int addscore)
875 {
876 const char *p = path_last_slash_const(src);
877 const char *s = (p != NULL)? p + 1 : src;
878
879 if (dest == NULL) {
880 /* allocate return value */
881 size_t len = strlen(s) + 1;
882
883 dest = calloc(len, 1);
884 addscore = 0;
885 }
886
887 if (dest != NULL) {
888 strcpy(dest, s);
889 }
890
891 if (addscore) {
892 /* double any underscores in @dest */
893 char mod[MAXSTR];
894 int n = strlen(dest);
895 int i, j = 0;
896
897 for (i=0; i<=n; i++) {
898 if (dest[i] == '_') {
899 mod[j++] = '_';
900 }
901 mod[j++] = dest[i];
902 }
903 strcpy(dest, mod);
904 }
905
906 return dest;
907 }
908
gui_record_data_opening(const char * fname,const int * list)909 static void gui_record_data_opening (const char *fname,
910 const int *list)
911 {
912 const char *recname = (fname != NULL)? fname : datafile;
913
914 if (data_status & BOOK_DATA) {
915 /* don't print the (platform-dependent) full
916 path to a datafile packaged with gretl
917 */
918 char basename[MAXSTR];
919
920 gretl_basename(basename, recname, 0);
921 lib_command_sprintf("open %s", basename);
922 } else if (strchr(recname, ' ') != NULL) {
923 lib_command_sprintf("open \"%s\"", recname);
924 } else {
925 lib_command_sprintf("open %s", recname);
926 }
927
928 if (list != NULL && list[0] == 3) {
929 /* record spreadsheet parameters */
930 char parm[32];
931
932 if (list[1] > 1) {
933 sprintf(parm, " --sheet=%d", list[1]);
934 lib_command_strcat(parm);
935 }
936 if (list[2] > 0) {
937 sprintf(parm, " --coloffset=%d", list[2]);
938 lib_command_strcat(parm);
939 }
940 if (list[3] > 0) {
941 sprintf(parm, " --rowoffset=%d", list[3]);
942 lib_command_strcat(parm);
943 }
944 }
945
946 record_command_verbatim();
947
948 if (*datafile != '\0') {
949 mkfilelist(FILE_LIST_DATA, datafile, 0);
950 }
951 }
952
953 #define file_opened(f) (f == DATAFILE_OPENED || \
954 f == OPENED_VIA_CLI || \
955 f == OPENED_VIA_SESSION)
956
real_register_data(int flag,const char * user_fname,const int * list)957 static void real_register_data (int flag, const char *user_fname,
958 const int *list)
959 {
960 /* basic accounting */
961 data_status |= HAVE_DATA;
962 orig_vars = dataset->v;
963
964 /* set appropriate data_status bits */
965 if (file_opened(flag)) {
966 if (!(data_status & IMPORT_DATA)) {
967 /* we opened a native data file */
968 if (has_system_prefix(datafile, DATA_SEARCH)) {
969 data_status |= BOOK_DATA;
970 data_status &= ~USER_DATA;
971 } else {
972 data_status &= ~BOOK_DATA;
973 data_status |= USER_DATA;
974 }
975 if (is_gzipped(datafile)) {
976 data_status |= GZIPPED_DATA;
977 } else {
978 data_status &= ~GZIPPED_DATA;
979 }
980 if (flag == OPENED_VIA_SESSION) {
981 data_status |= SESSION_DATA;
982 } else {
983 data_status &= ~SESSION_DATA;
984 }
985 }
986 } else {
987 /* we modified the current dataset somehow */
988 data_status |= GUI_DATA;
989 mark_dataset_as_modified();
990 }
991
992 /* sync main window with datafile */
993 if (mdata != NULL) {
994 populate_varlist();
995 set_sample_label(dataset);
996 dataset_menubar_state(TRUE);
997 session_menu_state(TRUE);
998 }
999
1000 /* Record the opening of the data file in the GUI recent files
1001 list and command log; note that we don't do this if the file
1002 was opened via script or console, or if it was opened as a
1003 side effect of re-opening a saved session. And we can't do
1004 it if the data file was opened via the initial command line,
1005 and the gretl GUI is not yet built.
1006 */
1007 if (mdata != NULL && flag == DATAFILE_OPENED) {
1008 gui_record_data_opening(user_fname, list);
1009 }
1010
1011 if (mdata != NULL) {
1012 if (flag != OPENED_VIA_CLI) {
1013 /* focus the data window */
1014 gtk_widget_grab_focus(mdata->listbox);
1015 }
1016 /* invalidate "remove extra obs" menu item */
1017 drop_obs_state(FALSE);
1018 }
1019 }
1020
register_data(int flag)1021 void register_data (int flag)
1022 {
1023 real_register_data(flag, NULL, NULL);
1024 }
1025
register_startup_data(const char * fname)1026 void register_startup_data (const char *fname)
1027 {
1028 real_register_data(DATAFILE_OPENED, fname, NULL);
1029 }
1030
maybe_offer_daily_options(void)1031 static void maybe_offer_daily_options (void)
1032 {
1033 gretlopt purge_opt = 0;
1034 PRN *prn = NULL;
1035
1036 bufopen(&prn);
1037
1038 if (prn != NULL) {
1039 int chk = analyse_daily_import(dataset, prn);
1040 const char *buf = NULL;
1041 int resp;
1042
1043 if (chk > 0) {
1044 buf = gretl_print_get_buffer(prn);
1045 }
1046
1047 if (chk == 1) {
1048 const char *opts[] = {
1049 N_("Leave the dataset as it is"),
1050 N_("Delete the weekend rows")
1051 };
1052
1053 resp = radio_dialog("gretl", _(buf), opts, 2,
1054 1, DAILY_PURGE, NULL);
1055 if (resp == 1) {
1056 purge_opt = OPT_W;
1057 }
1058 } else if (chk == 2) {
1059 const char *opts[] = {
1060 N_("Leave the dataset as it is"),
1061 N_("Delete the weekend rows"),
1062 N_("Delete all blank rows")
1063 };
1064
1065 resp = radio_dialog("gretl", _(buf), opts, 3,
1066 2, DAILY_PURGE, NULL);
1067 if (resp == 1) {
1068 purge_opt = OPT_W;
1069 } else if (resp == 2) {
1070 purge_opt = OPT_A;
1071 }
1072 } else if (chk == 3) {
1073 const char *opts[] = {
1074 N_("Leave the dataset as it is"),
1075 N_("Delete all blank rows")
1076 };
1077
1078 resp = radio_dialog("gretl", _(buf), opts, 2,
1079 1, DAILY_PURGE, NULL);
1080 if (resp == 1) {
1081 purge_opt = OPT_A;
1082 }
1083 }
1084
1085 gretl_print_destroy(prn);
1086 }
1087
1088 if (purge_opt) {
1089 purge_opt |= OPT_T;
1090 bool_subsample(NULL, purge_opt, NULL);
1091 }
1092 }
1093
finalize_data_open(const char * fname,int ftype,int import,int append,const int * list)1094 static void finalize_data_open (const char *fname, int ftype,
1095 int import, int append,
1096 const int *list)
1097 {
1098 if (import) {
1099 if (ftype == GRETL_CSV || ftype == GRETL_DTA ||
1100 ftype == GRETL_SAV || ftype == GRETL_SAS ||
1101 ftype == GRETL_XLSX || ftype == GRETL_ODS ||
1102 ftype == GRETL_GNUMERIC || ftype == GRETL_XLS) {
1103 maybe_display_string_table();
1104 }
1105 data_status |= IMPORT_DATA;
1106 }
1107
1108 if (append) {
1109 register_data(DATA_APPENDED);
1110 return;
1111 }
1112
1113 if (strstr(fname, CLIPTEMP)) {
1114 real_register_data(DATA_PASTED, NULL, list);
1115 } else {
1116 if (fname != datafile) {
1117 strcpy(datafile, fname);
1118 }
1119 real_register_data(DATAFILE_OPENED, NULL, list);
1120 }
1121
1122 if (import && !dataset_is_time_series(dataset) &&
1123 !dataset_is_panel(dataset) && ftype != GRETL_MAP &&
1124 mdata != NULL) {
1125 int resp;
1126
1127 resp = yes_no_dialog(_("gretl: open data"),
1128 _("The imported data have been interpreted as undated\n"
1129 "(cross-sectional). Do you want to give the data a\n"
1130 "time-series or panel interpretation?"),
1131 NULL);
1132 if (resp == GRETL_YES) {
1133 data_structure_dialog();
1134 }
1135 } else if (import && dated_daily_data(dataset) &&
1136 !dataset->markers) {
1137 maybe_offer_daily_options();
1138 }
1139 }
1140
datafile_missing(const char * fname)1141 static int datafile_missing (const char *fname)
1142 {
1143 FILE *fp = gretl_fopen(fname, "r");
1144 int err = 0;
1145
1146 if (fp == NULL) {
1147 delete_from_filelist(FILE_LIST_DATA, fname);
1148 file_read_errbox(fname);
1149 err = E_FOPEN;
1150 } else {
1151 fclose(fp);
1152 }
1153
1154 return err;
1155 }
1156
1157 /* below: get data of a sort that requires an import plugin */
1158
get_imported_data(char * fname,int ftype,int append)1159 int get_imported_data (char *fname, int ftype, int append)
1160 {
1161 PRN *prn = NULL;
1162 int list[4] = {3, 0, 0, 0};
1163 int *plist = NULL;
1164 int (*ss_importer) (const char *, int *, char *, DATASET *,
1165 gretlopt, PRN *);
1166 int (*misc_importer) (const char *, DATASET *,
1167 gretlopt, PRN *);
1168 int err = 0;
1169
1170 if (datafile_missing(fname)) {
1171 return E_FOPEN;
1172 }
1173
1174 import_na_init();
1175 ss_importer = NULL;
1176 misc_importer = NULL;
1177
1178 if (ftype == GRETL_XLS) {
1179 ss_importer = gui_get_plugin_function("xls_get_data");
1180 plist = list;
1181 } else if (ftype == GRETL_XLSX) {
1182 ss_importer = gui_get_plugin_function("xlsx_get_data");
1183 plist = list;
1184 } else if (ftype == GRETL_GNUMERIC) {
1185 ss_importer = gui_get_plugin_function("gnumeric_get_data");
1186 plist = list;
1187 } else if (ftype == GRETL_ODS) {
1188 ss_importer = gui_get_plugin_function("ods_get_data");
1189 plist = list;
1190 } else if (ftype == GRETL_DTA) {
1191 misc_importer = gui_get_plugin_function("dta_get_data");
1192 } else if (ftype == GRETL_SAV) {
1193 misc_importer = gui_get_plugin_function("sav_get_data");
1194 } else if (ftype == GRETL_SAS) {
1195 misc_importer = gui_get_plugin_function("xport_get_data");
1196 } else if (ftype == GRETL_JMULTI) {
1197 misc_importer = gui_get_plugin_function("jmulti_get_data");
1198 } else if (ftype == GRETL_WF1) {
1199 misc_importer = gui_get_plugin_function("wf1_get_data");
1200 } else if (ftype == GRETL_MAP) {
1201 misc_importer = gui_get_plugin_function("map_get_data");
1202 } else {
1203 errbox(_("Unrecognized data type"));
1204 err = 1;
1205 goto bailout;
1206 }
1207
1208 if (!err && ss_importer == NULL && misc_importer == NULL) {
1209 /* failed to open plugin */
1210 err = 1;
1211 goto bailout;
1212 }
1213
1214 if (bufopen(&prn)) {
1215 err = 1;
1216 goto bailout;
1217 }
1218
1219 /* call the actual importer function */
1220 if (SPREADSHEET_IMPORT(ftype)) {
1221 err = (*ss_importer)(fname, plist, NULL, dataset,
1222 OPT_G, prn);
1223 } else {
1224 err = (*misc_importer)(fname, dataset, OPT_G, prn);
1225 }
1226
1227 if (err == -1) {
1228 fprintf(stderr, "data import canceled\n");
1229 err = E_CANCEL;
1230 goto bailout;
1231 } else {
1232 const char *buf = gretl_print_get_buffer(prn);
1233
1234 if (err) {
1235 if (buf != NULL && *buf != '\0') {
1236 errbox(buf);
1237 } else {
1238 gui_errmsg(err);
1239 }
1240 if (err == E_FOPEN) {
1241 delete_from_filelist(FILE_LIST_DATA, fname);
1242 }
1243 } else {
1244 /* Do we want to be showing this? There's no error
1245 but it might look sort of scary!
1246 */
1247 #if 0 /* masked out 2020-07-11 */
1248 if (buf != NULL && *buf != '\0') {
1249 infobox(buf);
1250 }
1251 #endif
1252 finalize_data_open(fname, ftype, 1, append, plist);
1253 }
1254 }
1255
1256 bailout:
1257
1258 gretl_print_destroy(prn);
1259
1260 return err;
1261 }
1262
1263 /* get "CSV" (or more generally, ASCII) data or GNU octave data:
1264 plugin is not required
1265 */
1266
get_csv_data(char * fname,int ftype,int append)1267 static int get_csv_data (char *fname, int ftype, int append)
1268 {
1269 windata_t *vwin;
1270 PRN *prn;
1271 gchar *title = NULL;
1272 gretlopt opt = OPT_NONE;
1273 int err = 0;
1274
1275 if (datafile_missing(fname)) {
1276 return E_FOPEN;
1277 }
1278
1279 if (ftype == GRETL_CSV) {
1280 const char *msg =
1281 N_("Usually gretl tries to interpret the first column of a CSV\n"
1282 "data file as containing observation information (for example,\n"
1283 "dates), if the column heading looks suitable.\n\n"
1284 "Do you want to force gretl to treat the first column as just\n"
1285 "an ordinary data series (regardless of the column heading)?");
1286
1287 if (no_yes_dialog(NULL, _(msg)) == GRETL_YES) {
1288 opt = OPT_A;
1289 }
1290 }
1291
1292 if (bufopen(&prn)) {
1293 return 1;
1294 }
1295
1296 if (ftype == GRETL_OCTAVE) {
1297 err = import_other(fname, ftype, dataset, opt, prn);
1298 title = g_strdup_printf(_("gretl: import %s data"), "Octave");
1299 } else {
1300 err = import_csv(fname, dataset, opt, prn);
1301 title = g_strdup_printf(_("gretl: import %s data"), "CSV");
1302 }
1303
1304 /* show details regarding the import */
1305 vwin = view_buffer(prn, 78, 350, title, IMPORT, NULL);
1306 gtk_window_set_transient_for(GTK_WINDOW(vwin->main),
1307 GTK_WINDOW(mdata->main));
1308 g_free(title);
1309
1310 if (err) {
1311 delete_from_filelist(FILE_LIST_DATA, fname);
1312 } else {
1313 finalize_data_open(fname, ftype, 1, append, NULL);
1314 }
1315
1316 return err;
1317 }
1318
get_native_data(char * fname,int ftype,int append,windata_t * fwin)1319 static int get_native_data (char *fname, int ftype, int append,
1320 windata_t *fwin)
1321 {
1322 PRN *prn = NULL;
1323 char *buf = NULL;
1324 int err;
1325
1326 if (bufopen(&prn)) {
1327 return 1;
1328 }
1329
1330 if (ftype == GRETL_XML_DATA) {
1331 err = gretl_read_gdt(fname, dataset, OPT_B, prn);
1332 } else {
1333 err = gretl_get_data(fname, dataset, OPT_NONE, prn);
1334 }
1335
1336 buf = gretl_print_steal_buffer(prn);
1337 gretl_print_destroy(prn);
1338
1339 if (fwin != NULL) {
1340 /* close the files browser window that launched the query */
1341 gtk_widget_destroy(fwin->main);
1342 }
1343
1344 if (err) {
1345 if (err == E_FOPEN) {
1346 file_read_errbox(fname);
1347 } else if (buf != NULL && *buf != '\0') {
1348 errbox(buf);
1349 } else {
1350 gui_errmsg(err);
1351 }
1352 delete_from_filelist(FILE_LIST_DATA, fname);
1353 } else {
1354 #if 0
1355 if (check_gretl_warning()) {
1356 gui_warnmsg(0);
1357 }
1358 #endif
1359 finalize_data_open(fname, ftype, 0, append, NULL);
1360 if (append) {
1361 infobox(_("Data appended OK\n"));
1362 }
1363 fputs(buf, stderr);
1364 }
1365
1366 free(buf);
1367
1368 return err;
1369 }
1370
maybe_use_join(void)1371 static int maybe_use_join (void)
1372 {
1373 const char *opts[] = {
1374 N_("simple append"),
1375 N_("\"join\" (advanced)")
1376 };
1377
1378 return radio_dialog(_("gretl: append data"), NULL,
1379 opts, 2, 0, 0, NULL);
1380 }
1381
1382 /* The gretl.c variable @tryfile will contain the name
1383 of the data file to be opened.
1384 */
1385
do_open_data(windata_t * fwin,int code)1386 gboolean do_open_data (windata_t *fwin, int code)
1387 {
1388 int append = (code == APPEND_DATA);
1389 char *fname = get_tryfile();
1390 char tmp[MAXLEN];
1391 GretlFileType ftype;
1392 int use_join = 0;
1393 int err = 0;
1394
1395 if (g_path_is_absolute(fname)) {
1396 strcpy(tmp, fname);
1397 ftype = data_file_type_from_name(tmp);
1398 } else {
1399 strcpy(tmp, fname);
1400 ftype = detect_filetype(tmp, OPT_P);
1401 }
1402
1403 /* destroy the current data set, etc., unless we're
1404 explicitly appending */
1405 if (!append) {
1406 close_session(OPT_NONE); /* FIXME opt? */
1407 }
1408
1409 if (append && (ftype == GRETL_CSV || ftype == GRETL_XML_DATA ||
1410 ftype == GRETL_BINARY_DATA)) {
1411 use_join = maybe_use_join();
1412 if (use_join < 0) {
1413 /* canceled */
1414 return 0;
1415 }
1416 }
1417
1418 if (use_join) {
1419 err = gui_join_data(tmp, ftype);
1420 } else if (ftype == GRETL_CSV || ftype == GRETL_OCTAVE) {
1421 err = get_csv_data(tmp, ftype, append);
1422 } else if (SPREADSHEET_IMPORT(ftype) || OTHER_IMPORT(ftype)) {
1423 err = get_imported_data(tmp, ftype, append);
1424 } else {
1425 err = get_native_data(tmp, ftype, append, fwin);
1426 }
1427
1428 return !err;
1429 }
1430
1431 /* give user choice of not opening selected datafile, if there's
1432 already a datafile open */
1433
verify_open_data(windata_t * vwin,int code)1434 gboolean verify_open_data (windata_t *vwin, int code)
1435 {
1436 if (dataset_locked()) {
1437 return FALSE;
1438 }
1439
1440 if (data_status) {
1441 int resp =
1442 yes_no_dialog(_("gretl: open data"),
1443 _("Opening a new data file will automatically\n"
1444 "close the current one. Any unsaved work\n"
1445 "will be lost. Proceed to open data file?"),
1446 vwin_toplevel(vwin));
1447
1448 if (resp != GRETL_YES) {
1449 return FALSE;
1450 }
1451 }
1452
1453 return do_open_data(vwin, code);
1454 }
1455
1456 /* give user choice of not opening session file, if there's already a
1457 datafile open */
1458
verify_open_session(void)1459 gboolean verify_open_session (void)
1460 {
1461 char *fname = get_tryfile();
1462
1463 if (!gretl_is_pkzip_file(fname)) {
1464 /* not a zipped session file */
1465 return do_open_script(EDIT_HANSL);
1466 }
1467
1468 if (data_status) {
1469 int resp =
1470 yes_no_dialog(_("gretl: open session"),
1471 _("Opening a new session file will automatically\n"
1472 "close the current session. Any unsaved work\n"
1473 "will be lost. Proceed to open session file?"),
1474 NULL);
1475
1476 if (resp != GRETL_YES) {
1477 return FALSE;
1478 }
1479 }
1480
1481 return do_open_session();
1482 }
1483
mark_vwin_content_changed(windata_t * vwin)1484 void mark_vwin_content_changed (windata_t *vwin)
1485 {
1486 if (vwin->active_var == 0) {
1487 GtkWidget *w = g_object_get_data(G_OBJECT(vwin->mbar), "save_button");
1488
1489 if (w != NULL) {
1490 gtk_widget_set_sensitive(w, TRUE);
1491 }
1492 vwin->flags |= VWIN_CONTENT_CHANGED;
1493 if (window_is_tab(vwin)) {
1494 tabwin_tab_set_status(vwin);
1495 }
1496 }
1497 }
1498
mark_vwin_content_saved(windata_t * vwin)1499 void mark_vwin_content_saved (windata_t *vwin)
1500 {
1501 GtkWidget *w = g_object_get_data(G_OBJECT(vwin->mbar), "save_button");
1502
1503 if (w != NULL) {
1504 gtk_widget_set_sensitive(w, FALSE);
1505 }
1506
1507 vwin->flags &= ~VWIN_CONTENT_CHANGED;
1508 if (window_is_tab(vwin)) {
1509 tabwin_tab_set_status(vwin);
1510 }
1511
1512 w = g_object_get_data(G_OBJECT(vwin->mbar), "save_as_button");
1513 if (w != NULL) {
1514 gtk_widget_set_sensitive(w, TRUE);
1515 }
1516 }
1517
1518 /* save content function for an editor window that is hooked
1519 up to a given text buffer rather than in the business of
1520 saving to file
1521 */
1522
buf_edit_save(GtkWidget * w,windata_t * vwin)1523 static void buf_edit_save (GtkWidget *w, windata_t *vwin)
1524 {
1525 char **pbuf = (char **) vwin->data;
1526 gchar *text;
1527
1528 text = textview_get_text(vwin->text);
1529
1530 if (text == NULL || *text == '\0') {
1531 errbox(_("Buffer is empty"));
1532 g_free(text);
1533 return;
1534 }
1535
1536 /* swap the edited text into the buffer */
1537 free(*pbuf);
1538 *pbuf = text;
1539
1540 if (vwin->role == EDIT_HEADER) {
1541 mark_vwin_content_saved(vwin);
1542 mark_dataset_as_modified();
1543 } else if (vwin->role == EDIT_NOTES) {
1544 mark_vwin_content_saved(vwin);
1545 mark_session_changed();
1546 }
1547 }
1548
file_edit_save(GtkWidget * w,windata_t * vwin)1549 static void file_edit_save (GtkWidget *w, windata_t *vwin)
1550 {
1551 if (vwin->role == EDIT_PKG_SAMPLE) {
1552 /* function package editor, sample script window */
1553 update_sample_script(vwin);
1554 } else if (vwin->role == EDIT_PKG_CODE) {
1555 /* function package editor, function code window */
1556 update_func_code(vwin);
1557 } else if (vwin->role == EDIT_PKG_HELP ||
1558 vwin->role == EDIT_PKG_GHLP) {
1559 /* function package editor, help text window */
1560 update_gfn_help_text(vwin);
1561 } else if (*vwin->fname == '\0' || strstr(vwin->fname, "script_tmp")) {
1562 /* no real filename is available yet */
1563 if (vwin->role == EDIT_HANSL) {
1564 file_selector(SAVE_SCRIPT, FSEL_DATA_VWIN, vwin);
1565 } else if (vwin->role == EDIT_GP) {
1566 file_selector(SAVE_GP_CMDS, FSEL_DATA_VWIN, vwin);
1567 } else if (vwin->role == EDIT_R) {
1568 file_selector(SAVE_R_CMDS, FSEL_DATA_VWIN, vwin);
1569 } else if (vwin->role == EDIT_OX) {
1570 file_selector(SAVE_OX_CMDS, FSEL_DATA_VWIN, vwin);
1571 } else if (vwin->role == EDIT_OCTAVE) {
1572 file_selector(SAVE_OCTAVE_CMDS, FSEL_DATA_VWIN, vwin);
1573 } else if (vwin->role == EDIT_PYTHON) {
1574 file_selector(SAVE_PYTHON_CMDS, FSEL_DATA_VWIN, vwin);
1575 } else if (vwin->role == EDIT_JULIA) {
1576 file_selector(SAVE_JULIA_CODE, FSEL_DATA_VWIN, vwin);
1577 } else if (vwin->role == EDIT_STATA) {
1578 file_selector(SAVE_STATA_CMDS, FSEL_DATA_VWIN, vwin);
1579 } else if (vwin->role == EDIT_DYNARE) {
1580 file_selector(SAVE_DYNARE_CODE, FSEL_DATA_VWIN, vwin);
1581 } else if (vwin->role == EDIT_LPSOLVE) {
1582 file_selector(SAVE_LPSOLVE_CODE, FSEL_DATA_VWIN, vwin);
1583 } else if (vwin->role == CONSOLE) {
1584 file_selector(SAVE_CONSOLE, FSEL_DATA_VWIN, vwin);
1585 }
1586 } else if ((vwin->flags & VWIN_SESSION_GRAPH) &&
1587 vwin->role == EDIT_GP) {
1588 /* "auto-save" of session graph file */
1589 gchar *text = textview_get_text(vwin->text);
1590
1591 dump_plot_buffer(text, vwin->fname, 0, NULL);
1592 g_free(text);
1593 mark_vwin_content_saved(vwin);
1594 mark_session_changed();
1595 } else {
1596 FILE *fp = gretl_fopen(vwin->fname, "wb");
1597
1598 if (fp == NULL) {
1599 file_write_errbox(vwin->fname);
1600 } else {
1601 gchar *text = textview_get_text(vwin->text);
1602
1603 system_print_buf(text, fp);
1604 fclose(fp);
1605 g_free(text);
1606 mark_vwin_content_saved(vwin);
1607 }
1608 }
1609 }
1610
vwin_save_callback(GtkWidget * w,windata_t * vwin)1611 void vwin_save_callback (GtkWidget *w, windata_t *vwin)
1612 {
1613 if (vwin_editing_buffer(vwin->role)) {
1614 buf_edit_save(w, vwin);
1615 } else {
1616 file_edit_save(w, vwin);
1617 }
1618 }
1619
1620 /* Hook up child and parent viewers: this is used to help organize the
1621 window list menu (with, e.g., model-related output windows being
1622 marked as children of the model window itself). It's also used for
1623 some more specialized cases, such as marking a script output window
1624 as child of the originating script window.
1625 */
1626
vwin_add_child(windata_t * parent,windata_t * child)1627 void vwin_add_child (windata_t *parent, windata_t *child)
1628 {
1629 int n = parent->n_gretl_children;
1630 int i, done = 0, err = 0;
1631
1632 for (i=0; i<n; i++) {
1633 if (parent->gretl_children[i] == NULL) {
1634 /* reuse a vacant slot */
1635 parent->gretl_children[i] = child;
1636 done = 1;
1637 break;
1638 }
1639 }
1640
1641 if (!done) {
1642 windata_t **children;
1643
1644 children = myrealloc(parent->gretl_children, (n + 1) * sizeof *children);
1645
1646 if (children != NULL) {
1647 parent->gretl_children = children;
1648 parent->gretl_children[n] = child;
1649 parent->n_gretl_children += 1;
1650 } else {
1651 err = 1;
1652 }
1653 }
1654
1655 if (!err) {
1656 child->gretl_parent = parent;
1657 }
1658 }
1659
vwin_nullify_child(windata_t * parent,windata_t * child)1660 static void vwin_nullify_child (windata_t *parent, windata_t *child)
1661 {
1662 int i;
1663
1664 for (i=0; i<parent->n_gretl_children; i++) {
1665 if (child == parent->gretl_children[i]) {
1666 parent->gretl_children[i] = NULL;
1667 }
1668 }
1669 }
1670
vwin_first_child(windata_t * vwin)1671 windata_t *vwin_first_child (windata_t *vwin)
1672 {
1673 int i;
1674
1675 for (i=0; i<vwin->n_gretl_children; i++) {
1676 if (vwin->gretl_children[i] != NULL) {
1677 return vwin->gretl_children[i];
1678 }
1679 }
1680
1681 return NULL;
1682 }
1683
free_windata(GtkWidget * w,gpointer data)1684 void free_windata (GtkWidget *w, gpointer data)
1685 {
1686 windata_t *vwin = (windata_t *) data;
1687
1688 #if 0
1689 fprintf(stderr, "free_windata: vwin %p, gtk_window %p, role %d\n",
1690 data, (void *) vwin->main, vwin->role);
1691 #endif
1692
1693 if (vwin != NULL) {
1694 /* notify parent, if any, that child is gone */
1695 if (vwin->gretl_parent != NULL) {
1696 vwin_nullify_child(vwin->gretl_parent, vwin);
1697 }
1698
1699 /* notify children, if any, that parent is gone */
1700 if (vwin->n_gretl_children > 0) {
1701 int i;
1702
1703 for (i=0; i<vwin->n_gretl_children; i++) {
1704 if (vwin->gretl_children[i] != NULL) {
1705 vwin->gretl_children[i]->gretl_parent = NULL;
1706 }
1707 }
1708 free(vwin->gretl_children);
1709 }
1710
1711 /* menu stuff */
1712 if (vwin->popup != NULL) {
1713 gtk_widget_destroy(vwin->popup);
1714 }
1715 if (vwin->ui != NULL) {
1716 g_object_unref(vwin->ui);
1717 }
1718
1719 /* toolbar popups? */
1720 if (vwin->mbar != NULL) {
1721 vwin_free_toolbar_popups(vwin);
1722 }
1723
1724 /* tabbed toolbar */
1725 if (window_is_tab(vwin) && vwin->mbar != NULL) {
1726 g_object_unref(vwin->mbar);
1727 }
1728
1729 /* data specific to certain windows */
1730 if (vwin->role == SUMMARY) {
1731 free_summary(vwin->data);
1732 } else if (vwin->role == CORR || vwin->role == PCA ||
1733 vwin->role == COVAR) {
1734 free_vmatrix(vwin->data);
1735 } else if (vwin->role == FCAST || vwin->role == AFR) {
1736 free_fit_resid(vwin->data);
1737 } else if (vwin->role == COEFFINT) {
1738 free_coeff_intervals(vwin->data);
1739 } else if (vwin->role == VIEW_SERIES) {
1740 free_series_view(vwin->data);
1741 } else if (vwin->role == VIEW_MODEL) {
1742 gretl_object_unref(vwin->data, GRETL_OBJ_EQN);
1743 } else if (vwin->role == VAR || vwin->role == VECM) {
1744 gretl_object_unref(vwin->data, GRETL_OBJ_VAR);
1745 } else if (vwin->role == LEVERAGE) {
1746 gretl_matrix_free(vwin->data);
1747 } else if (vwin->role == MAHAL) {
1748 free_mahal_dist(vwin->data);
1749 } else if (vwin->role == XTAB) {
1750 free_xtab(vwin->data);
1751 } else if (vwin->role == COINT2) {
1752 gretl_VAR_free(vwin->data);
1753 } else if (vwin->role == SYSTEM) {
1754 gretl_object_unref(vwin->data, GRETL_OBJ_SYS);
1755 } else if (vwin->flags & VWIN_MULTI_SERIES) {
1756 free_series_view(vwin->data);
1757 } else if (help_role(vwin->role)) {
1758 g_free(vwin->data); /* help file text */
1759 } else if (vwin->role == VIEW_BUNDLE ||
1760 vwin->role == VIEW_DBNOMICS) {
1761 if (!get_user_var_by_data(vwin->data)) {
1762 gretl_bundle_destroy(vwin->data);
1763 }
1764 } else if (vwin->role == LOESS || vwin->role == NADARWAT) {
1765 gretl_bundle_destroy(vwin->data);
1766 }
1767
1768 if (window_delete_filename(vwin)) {
1769 /* there's a temporary file associated */
1770 gretl_remove(vwin->fname);
1771 }
1772
1773 free(vwin);
1774 }
1775 }
1776
text_popup_handler(GtkWidget * w,GdkEventButton * event,gpointer p)1777 gboolean text_popup_handler (GtkWidget *w, GdkEventButton *event, gpointer p)
1778 {
1779 if (right_click(event)) {
1780 windata_t *vwin = (windata_t *) p;
1781
1782 if (vwin->popup != NULL) {
1783 gtk_widget_destroy(vwin->popup);
1784 vwin->popup = NULL;
1785 }
1786
1787 vwin->popup = build_text_popup(vwin);
1788
1789 if (vwin->popup != NULL) {
1790 gtk_menu_popup(GTK_MENU(vwin->popup), NULL, NULL, NULL, NULL,
1791 event->button, event->time);
1792 g_signal_connect(G_OBJECT(vwin->popup), "destroy",
1793 G_CALLBACK(gtk_widget_destroyed),
1794 &vwin->popup);
1795 }
1796
1797 return TRUE;
1798 }
1799
1800 return FALSE;
1801 }
1802
title_from_filename(const char * fname,int role,gboolean prepend)1803 gchar *title_from_filename (const char *fname,
1804 int role,
1805 gboolean prepend)
1806 {
1807 gchar *base, *title = NULL;
1808
1809 base = g_path_get_basename(fname);
1810
1811 if (!strcmp(base, "session.inp") || !strncmp(base, "script_tmp.", 11)) {
1812 if (role == EDIT_GP) {
1813 title = g_strdup(_("gretl: edit plot commands"));
1814 } else if (role == EDIT_R) {
1815 title = g_strdup(_("gretl: edit R script"));
1816 } else if (role == EDIT_OX) {
1817 title = g_strdup(_("gretl: edit Ox program"));
1818 } else if (role == EDIT_OCTAVE) {
1819 title = g_strdup(_("gretl: edit Octave script"));
1820 } else if (role == EDIT_PYTHON) {
1821 title = g_strdup(_("gretl: edit Python script"));
1822 } else if (role == EDIT_JULIA) {
1823 title = g_strdup(_("gretl: edit Julia program"));
1824 } else if (role == EDIT_STATA) {
1825 title = g_strdup(_("gretl: edit Stata program"));
1826 } else if (role == EDIT_DYNARE) {
1827 title = g_strdup(_("gretl: edit Dynare script"));
1828 } else if (role == EDIT_LPSOLVE) {
1829 title = g_strdup(_("gretl: edit lpsolve script"));
1830 } else if (role == EDIT_SPEC) {
1831 title = g_strdup(_("gretl: edit package spec file"));
1832 } else {
1833 title = g_strdup(_("gretl: untitled"));
1834 }
1835 } else if (prepend) {
1836 title = g_strdup_printf("gretl: %s", base);
1837 } else {
1838 title = base;
1839 base = NULL; /* don't free */
1840 }
1841
1842 g_free(base);
1843
1844 return title;
1845 }
1846
1847 /* called when replacing a script in (non-tabbed) script
1848 editor, via the editor's "Open" button */
1849
vwin_set_filename(windata_t * vwin,const char * fname)1850 void vwin_set_filename (windata_t *vwin, const char *fname)
1851 {
1852 gchar *title = title_from_filename(fname, vwin->role, TRUE);
1853
1854 gtk_window_set_title(GTK_WINDOW(vwin->main), title);
1855 g_free(title);
1856 strcpy(vwin->fname, fname);
1857 }
1858
script_output_title(void)1859 static gchar *script_output_title (void)
1860 {
1861 int n = get_script_output_number();
1862
1863 if (n > 0) {
1864 return g_strdup_printf(_("gretl: script output %d"), n+1);
1865 } else {
1866 return g_strdup(_("gretl: script output"));
1867 }
1868 }
1869
title_from_data(gpointer data)1870 static gchar *title_from_data (gpointer data)
1871 {
1872 gretl_bundle *b = data;
1873 const char *s = gretl_bundle_get_creator(b);
1874
1875 if (s != NULL) {
1876 return g_strdup_printf("gretl: %s bundle", s);
1877 } else {
1878 return NULL;
1879 }
1880 }
1881
make_viewer_title(int role,const char * fname,gpointer data)1882 static gchar *make_viewer_title (int role, const char *fname,
1883 gpointer data)
1884 {
1885 gchar *title = NULL;
1886
1887 switch (role) {
1888 case CMD_HELP:
1889 title = g_strdup(_("gretl: command reference")); break;
1890 case GUI_HELP:
1891 title = g_strdup(_("gretl: help")); break;
1892 case FUNC_HELP:
1893 title = g_strdup(_("gretl: function reference")); break;
1894 case CMD_HELP_EN:
1895 title = g_strdup("gretl: command reference"); break;
1896 case GUI_HELP_EN:
1897 title = g_strdup("gretl: help"); break;
1898 case FUNC_HELP_EN:
1899 title = g_strdup("gretl: function reference"); break;
1900 case VIEW_LOG:
1901 title = g_strdup(_("gretl: command log")); break;
1902 case EDIT_HANSL:
1903 case VIEW_SCRIPT:
1904 case VIEW_FILE:
1905 case VIEW_CODEBOOK:
1906 case VIEW_DOC:
1907 case EDIT_GP:
1908 case EDIT_R:
1909 case EDIT_OX:
1910 case EDIT_OCTAVE:
1911 case EDIT_PYTHON:
1912 case EDIT_JULIA:
1913 case EDIT_STATA:
1914 case EDIT_DYNARE:
1915 case EDIT_LPSOLVE:
1916 case EDIT_SPEC:
1917 title = title_from_filename(fname, role, TRUE);
1918 break;
1919 case EDIT_NOTES:
1920 title = g_strdup(_("gretl: session notes")); break;
1921 case SCRIPT_OUT:
1922 case FNCALL_OUT:
1923 title = script_output_title();
1924 break;
1925 case VIEW_DATA:
1926 title = g_strdup(_("gretl: display data")); break;
1927 case VIEW_BUNDLE:
1928 title = title_from_data(data);
1929 break;
1930 default:
1931 break;
1932 }
1933
1934 return title;
1935 }
1936
content_changed(GtkWidget * w,windata_t * vwin)1937 static void content_changed (GtkWidget *w, windata_t *vwin)
1938 {
1939 mark_vwin_content_changed(vwin);
1940 }
1941
attach_content_changed_signal(windata_t * vwin)1942 static void attach_content_changed_signal (windata_t *vwin)
1943 {
1944 GtkTextBuffer *tbuf;
1945
1946 tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
1947 g_signal_connect(G_OBJECT(tbuf), "changed",
1948 G_CALLBACK(content_changed), vwin);
1949 }
1950
1951 #define viewing_source(r) (r == VIEW_PKG_CODE || \
1952 r == EDIT_PKG_CODE || \
1953 r == VIEW_LOG || \
1954 r == EDIT_PKG_SAMPLE || \
1955 r == VIEW_PKG_SAMPLE)
1956
view_buffer_insert_text(windata_t * vwin,PRN * prn)1957 static void view_buffer_insert_text (windata_t *vwin, PRN *prn)
1958 {
1959 if (prn != NULL) {
1960 const char *buf = gretl_print_get_trimmed_buffer(prn);
1961 gchar *bconv = NULL;
1962
1963 if (!g_utf8_validate(buf, -1, NULL)) {
1964 gsize bytes;
1965
1966 bconv = g_locale_to_utf8(buf, -1, NULL, &bytes, NULL);
1967 if (bconv != NULL) {
1968 buf = (const char *) bconv;
1969 }
1970 }
1971
1972 if (viewing_source(vwin->role)) {
1973 sourceview_insert_buffer(vwin, buf);
1974 } else if (vwin->role == SCRIPT_OUT) {
1975 textview_set_text_colorized(vwin->text, buf);
1976 } else if (vwin->role == BUILD_PKG) {
1977 textview_set_text_report(vwin->text, buf);
1978 } else if (vwin->role == VIEW_DBSEARCH) {
1979 textview_set_text_dbsearch(vwin, buf);
1980 } else {
1981 textview_set_text(vwin->text, buf);
1982 }
1983
1984 g_free(bconv);
1985 }
1986 }
1987
1988 /* for use with reuseable script output window */
1989 static windata_t *script_out_viewer;
1990
nullify_script_out(GtkWidget * w,windata_t ** pvwin)1991 static gboolean nullify_script_out (GtkWidget *w, windata_t **pvwin)
1992 {
1993 *pvwin = NULL;
1994 return FALSE;
1995 }
1996
set_reuseable_output_window(int policy,windata_t * vwin)1997 void set_reuseable_output_window (int policy, windata_t *vwin)
1998 {
1999 if (policy == OUTPUT_POLICY_NEW_WINDOW) {
2000 script_out_viewer = NULL;
2001 } else {
2002 script_out_viewer = vwin;
2003 g_signal_connect(G_OBJECT(vwin->main), "destroy",
2004 G_CALLBACK(nullify_script_out),
2005 &script_out_viewer);
2006 }
2007 }
2008
reuse_script_out(windata_t * vwin,PRN * prn)2009 static windata_t *reuse_script_out (windata_t *vwin, PRN *prn)
2010 {
2011 int policy = get_script_output_policy();
2012 GtkTextBuffer *buf;
2013 const char *newtext;
2014
2015 newtext = gretl_print_get_buffer(prn);
2016 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
2017
2018 if (policy == OUTPUT_POLICY_APPEND) {
2019 GtkTextMark *mark;
2020 GtkTextIter iter;
2021
2022 gtk_text_buffer_get_end_iter(buf, &iter);
2023 mark = gtk_text_buffer_create_mark(buf, NULL, &iter, TRUE);
2024 textview_append_text_colorized(vwin->text, newtext, 1);
2025 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(vwin->text),
2026 mark, 0.0, TRUE, 0, 0.05);
2027 gtk_text_buffer_delete_mark(buf, mark);
2028 } else {
2029 /* replace previous content */
2030 gtk_text_buffer_set_text(buf, "", -1);
2031 textview_set_text_colorized(vwin->text, newtext);
2032 cursor_to_top(vwin);
2033 }
2034
2035 gretl_print_destroy(prn);
2036 gtk_window_present(GTK_WINDOW(vwin->main));
2037
2038 return vwin;
2039 }
2040
vwin_add_closer(windata_t * vwin)2041 static void vwin_add_closer (windata_t *vwin)
2042 {
2043 GtkWidget *b;
2044
2045 b = gtk_button_new_with_label(_("Close"));
2046 g_signal_connect(G_OBJECT(b), "clicked",
2047 G_CALLBACK(delete_widget), vwin->main);
2048 gtk_widget_show(b);
2049 gtk_box_pack_end(GTK_BOX(vwin->vbox), b, FALSE, FALSE, 0);
2050 }
2051
set_model_save_state(windata_t * vwin,gboolean s)2052 void set_model_save_state (windata_t *vwin, gboolean s)
2053 {
2054 flip(vwin->ui, "/menubar/File/SaveAsIcon", s);
2055 flip(vwin->ui, "/menubar/File/SaveAndClose", s);
2056 }
2057
2058 windata_t *
view_buffer_with_parent(windata_t * parent,PRN * prn,int hsize,int vsize,const char * title,int role,gpointer data)2059 view_buffer_with_parent (windata_t *parent, PRN *prn,
2060 int hsize, int vsize,
2061 const char *title, int role,
2062 gpointer data)
2063 {
2064 int width = 0, nlines = 0;
2065 windata_t *vwin;
2066
2067 if (role == SCRIPT_OUT && script_out_viewer != NULL) {
2068 return reuse_script_out(script_out_viewer, prn);
2069 }
2070
2071 if (title != NULL) {
2072 vwin = gretl_viewer_new_with_parent(parent, role, title,
2073 data);
2074 } else {
2075 gchar *tmp = make_viewer_title(role, NULL, data);
2076
2077 vwin = gretl_viewer_new_with_parent(parent, role, tmp,
2078 data);
2079 g_free(tmp);
2080 }
2081
2082 if (vwin == NULL) {
2083 return NULL;
2084 }
2085
2086 if (role == VAR || role == VECM || role == SYSTEM) {
2087 /* special case: use a text-based menu bar */
2088 vwin_add_ui(vwin, system_items, n_system_items, sys_ui);
2089 set_model_save_state(vwin, !is_session_model(vwin->data));
2090 add_system_menu_items(vwin, role);
2091 vwin_pack_toolbar(vwin);
2092 if (role == VAR || role == VECM) {
2093 g_signal_connect(G_OBJECT(vwin->mbar), "button-press-event",
2094 G_CALLBACK(check_VAR_menu), vwin);
2095 }
2096 gretl_object_ref(data, (role == SYSTEM)? GRETL_OBJ_SYS : GRETL_OBJ_VAR);
2097 } else if (role == VIEW_PKG_CODE ||
2098 role == VIEW_PKG_SAMPLE ||
2099 role == VIEW_LOG ||
2100 role == VIEW_DBSEARCH ||
2101 role == VIEW_MODELTABLE) {
2102 vwin_add_viewbar(vwin, 0);
2103 } else if (role == EDIT_PKG_CODE ||
2104 role == EDIT_PKG_SAMPLE ||
2105 role == EDIT_PKG_HELP ||
2106 role == EDIT_PKG_GHLP) {
2107 vwin_add_viewbar(vwin, VIEWBAR_EDITABLE);
2108 } else if (role == IMPORT || role == BUILD_PKG) {
2109 vwin_add_closer(vwin);
2110 } else {
2111 vwin_add_viewbar(vwin, VIEWBAR_HAS_TEXT);
2112 }
2113
2114 if (role != VIEW_PKG_CODE &&
2115 role != EDIT_PKG_CODE &&
2116 role != VIEW_PKG_SAMPLE &&
2117 role != VIEW_LOG &&
2118 role != EDIT_PKG_HELP &&
2119 role != EDIT_PKG_GHLP &&
2120 role != SCRIPT_OUT) {
2121 gretl_print_get_size(prn, &width, &nlines);
2122 if (width > 0 && width + 2 < hsize) {
2123 hsize = width + 2;
2124 }
2125 }
2126
2127 if (role == VIEW_PKG_CODE || role == VIEW_PKG_SAMPLE || role == VIEW_LOG) {
2128 create_source(vwin, hsize, vsize, FALSE);
2129 } else if (role == EDIT_PKG_CODE || role == EDIT_PKG_SAMPLE) {
2130 create_source(vwin, hsize, vsize, TRUE);
2131 } else if (role == EDIT_PKG_HELP || role == EDIT_PKG_GHLP) {
2132 /* editable text */
2133 create_text(vwin, hsize, vsize, nlines, TRUE);
2134 } else {
2135 /* non-editable text */
2136 create_text(vwin, hsize, vsize, nlines, FALSE);
2137 }
2138
2139 text_table_setup(vwin->vbox, vwin->text);
2140
2141 if (role == SCRIPT_OUT) {
2142 if (data != NULL) {
2143 /* partial output window for script */
2144 vwin_add_child((windata_t *) data, vwin);
2145 /* define "top-hbox" here? */
2146 }
2147 g_signal_connect(G_OBJECT(vwin->main), "destroy",
2148 G_CALLBACK(nullify_script_out),
2149 &script_out_viewer);
2150 script_out_viewer = vwin;
2151 }
2152
2153 /* insert and then free the text buffer */
2154 view_buffer_insert_text(vwin, prn);
2155 gretl_print_destroy(prn);
2156
2157 g_signal_connect(G_OBJECT(vwin->main), "key-press-event",
2158 G_CALLBACK(catch_viewer_key), vwin);
2159
2160 gtk_widget_show(vwin->vbox);
2161 gtk_widget_show(vwin->main);
2162
2163 if (role == EDIT_PKG_CODE || role == EDIT_PKG_SAMPLE ||
2164 role == EDIT_PKG_HELP || role == EDIT_PKG_GHLP) {
2165 attach_content_changed_signal(vwin);
2166 g_signal_connect(G_OBJECT(vwin->main), "delete-event",
2167 G_CALLBACK(query_save_text), vwin);
2168 } else if (role == SUMMARY) {
2169 widget_set_int(vwin->text, "digits", get_gretl_digits());
2170 }
2171
2172 if (role == BUILD_PKG) {
2173 scroll_to_foot(vwin);
2174 } else {
2175 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2176 G_CALLBACK(text_popup_handler), vwin);
2177 cursor_to_top(vwin);
2178 }
2179
2180 gtk_widget_grab_focus(vwin->text);
2181
2182 return vwin;
2183 }
2184
view_buffer(PRN * prn,int hsize,int vsize,const char * title,int role,gpointer data)2185 windata_t *view_buffer (PRN *prn, int hsize, int vsize,
2186 const char *title, int role,
2187 gpointer data)
2188 {
2189 return view_buffer_with_parent(NULL, prn, hsize,
2190 vsize, title,
2191 role, data);
2192 }
2193
2194 /* hansl_output_viewer_new: here we're creating a window
2195 that will display script output, allowing for the
2196 possibility that it may take a while for the (full)
2197 output to appear, and the script "flush" mechanism
2198 may be operating to produce incremental display.
2199 */
2200
hansl_output_viewer_new(PRN * prn,int role,const char * title)2201 windata_t *hansl_output_viewer_new (PRN *prn, int role,
2202 const char *title)
2203 {
2204 windata_t *vwin;
2205 const char *buf;
2206
2207 if (title != NULL) {
2208 vwin = gretl_viewer_new_with_parent(NULL, role,
2209 title, NULL);
2210 } else {
2211 gchar *tmp = make_viewer_title(role, NULL, NULL);
2212
2213 vwin = gretl_viewer_new_with_parent(NULL, role,
2214 tmp, NULL);
2215 g_free(tmp);
2216 }
2217
2218 if (vwin == NULL) {
2219 return NULL;
2220 }
2221
2222 vwin_add_tmpbar(vwin);
2223 create_text(vwin, SCRIPT_WIDTH, 450, 0, FALSE);
2224 text_table_setup(vwin->vbox, vwin->text);
2225
2226 /* insert the text buffer from @prn */
2227 buf = gretl_print_get_buffer(prn);
2228 if (buf != NULL && *buf != '\0') {
2229 textview_set_text_colorized(vwin->text, buf);
2230 }
2231
2232 g_signal_connect(G_OBJECT(vwin->main), "key-press-event",
2233 G_CALLBACK(catch_viewer_key), vwin);
2234 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2235 G_CALLBACK(text_popup_handler), vwin);
2236
2237 gtk_widget_show(vwin->vbox);
2238 gtk_widget_show(vwin->main);
2239 gtk_widget_grab_focus(vwin->text);
2240
2241 return vwin;
2242 }
2243
2244 #define text_out_ok(r) (r == VIEW_DATA || r == VIEW_FILE)
2245
2246 windata_t *
view_file_with_title(const char * filename,int editable,int del_file,int hsize,int vsize,int role,const char * given_title)2247 view_file_with_title (const char *filename, int editable, int del_file,
2248 int hsize, int vsize, int role,
2249 const char *given_title)
2250 {
2251 windata_t *vwin;
2252 FILE *fp;
2253 int ins = 0;
2254
2255 /* first check that we can open the specified file */
2256 fp = gretl_fopen(filename, "r");
2257 if (fp == NULL) {
2258 errbox_printf(_("Can't open %s for reading"), filename);
2259 return NULL;
2260 } else {
2261 fclose(fp);
2262 }
2263
2264 #if 0
2265 /* experimental, not yet */
2266 if (swallow && role == EDIT_HANSL) {
2267 ins = mainwin_get_vwin_insertion();
2268 fprintf(stderr, "HERE ins=%d, title '%s'\n", ins, given_title);
2269 if (ins) {
2270 preset_viewer_flag(VWIN_SWALLOW);
2271 }
2272 }
2273 #endif
2274
2275 if (!ins && role == EDIT_HANSL && use_tabbed_editor()) {
2276 vwin = viewer_tab_new(role, filename, NULL);
2277 } else if (editing_alt_script(role) && use_tabbed_editor()) {
2278 vwin = viewer_tab_new(role, filename, NULL);
2279 } else if (given_title != NULL) {
2280 vwin = gretl_viewer_new(role, given_title, NULL);
2281 } else {
2282 gchar *title = make_viewer_title(role, filename, NULL);
2283
2284 vwin = gretl_viewer_new(role, (title != NULL)? title : filename,
2285 NULL);
2286 g_free(title);
2287 }
2288
2289 if (vwin == NULL) {
2290 return NULL;
2291 }
2292
2293 strcpy(vwin->fname, filename);
2294
2295 if (role != VIEW_DOC) {
2296 ViewbarFlags vflags = 0;
2297
2298 if (editable) {
2299 vflags = VIEWBAR_EDITABLE;
2300 }
2301 if (text_out_ok(role)) {
2302 vflags |= VIEWBAR_HAS_TEXT;
2303 }
2304 vwin_add_viewbar(vwin, vflags);
2305 }
2306
2307 if (textview_use_highlighting(role) || editable) {
2308 create_source(vwin, hsize, vsize, editable);
2309 } else {
2310 create_text(vwin, hsize, vsize, 0, editable);
2311 }
2312
2313 text_table_setup(vwin->vbox, vwin->text);
2314
2315 if (textview_use_highlighting(role) || editable) {
2316 sourceview_insert_file(vwin, filename);
2317 } else {
2318 textview_insert_file(vwin, filename);
2319 }
2320
2321 /* editing script or graph commands: grab the "changed" signal
2322 and set up alert for unsaved changes on exit */
2323 if (vwin_editing_script(role)) {
2324 attach_content_changed_signal(vwin);
2325 if (!window_is_tab(vwin)) {
2326 g_signal_connect(G_OBJECT(vwin->main), "delete-event",
2327 G_CALLBACK(query_save_text), vwin);
2328 }
2329 /* since 2021-05-18 */
2330 vwin->flags |= VWIN_USE_FOOTER;
2331 }
2332
2333 /* clean up when dialog is destroyed */
2334 if (del_file) {
2335 gchar *fname = g_strdup(filename);
2336
2337 g_signal_connect(G_OBJECT(vwin->main), "destroy",
2338 G_CALLBACK(delete_file), (gpointer) fname);
2339 }
2340
2341 if (window_is_tab(vwin)) {
2342 show_tabbed_viewer(vwin);
2343 } else {
2344 g_signal_connect(G_OBJECT(vwin->main), "key-press-event",
2345 G_CALLBACK(catch_viewer_key), vwin);
2346 gtk_widget_show_all(vwin->main);
2347 }
2348
2349 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2350 G_CALLBACK(text_popup_handler), vwin);
2351
2352 cursor_to_top(vwin);
2353 gtk_widget_grab_focus(vwin->text);
2354
2355 #if 0 /* not yet */
2356 if (vwin->flags & VWIN_SWALLOW) {
2357 mainwin_insert_vwin(vwin);
2358 }
2359 #endif
2360
2361 return vwin;
2362 }
2363
view_file(const char * filename,int editable,int del_file,int hsize,int vsize,int role)2364 windata_t *view_file (const char *filename, int editable, int del_file,
2365 int hsize, int vsize, int role)
2366 {
2367 return view_file_with_title(filename, editable, del_file,
2368 hsize, vsize, role, NULL);
2369 }
2370
view_script(const char * filename,int editable,int role)2371 windata_t *view_script (const char *filename, int editable,
2372 int role)
2373 {
2374 if (editable) {
2375 windata_t *vwin = get_editor_for_file(filename);
2376
2377 if (vwin != NULL) {
2378 gretl_viewer_present(vwin);
2379 return vwin;
2380 }
2381 }
2382
2383 return view_file_with_title(filename, editable, 0,
2384 SCRIPT_WIDTH, SCRIPT_HEIGHT,
2385 role, NULL);
2386 }
2387
console_window(int hsize,int vsize)2388 windata_t *console_window (int hsize, int vsize)
2389 {
2390 windata_t *vwin;
2391
2392 if (swallow) {
2393 vwin = gretl_viewer_new(CONSOLE, NULL, NULL);
2394 } else {
2395 gchar *title = NULL;
2396 #ifdef GRETL_PID_FILE
2397 int seqno = gretl_sequence_number();
2398
2399 if (seqno > 1) {
2400 title = g_strdup_printf("%s (%d)", _("gretl console"), seqno);
2401 }
2402 #endif
2403 if (title != NULL) {
2404 vwin = gretl_viewer_new(CONSOLE, title, NULL);
2405 g_free(title);
2406 } else {
2407 vwin = gretl_viewer_new(CONSOLE, _("gretl console"), NULL);
2408 }
2409 }
2410
2411 if (vwin == NULL) {
2412 return NULL;
2413 }
2414
2415 vwin->flags |= VWIN_USE_FOOTER;
2416 vwin_add_viewbar(vwin, VIEWBAR_EDITABLE);
2417 create_console(vwin, hsize, vsize);
2418 text_table_setup(vwin->vbox, vwin->text);
2419
2420 /* catch some special keystrokes */
2421 g_signal_connect(G_OBJECT(vwin->text), "key-press-event",
2422 G_CALLBACK(catch_viewer_key), vwin);
2423
2424 gtk_widget_show(vwin->vbox);
2425 if (vwin->main != vwin->vbox) {
2426 gtk_widget_show(vwin->main);
2427 }
2428
2429 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2430 G_CALLBACK(text_popup_handler), vwin);
2431
2432 return vwin;
2433 }
2434
help_panes_setup(windata_t * vwin,GtkWidget * text)2435 void help_panes_setup (windata_t *vwin, GtkWidget *text)
2436 {
2437 GtkWidget *hp = gtk_hpaned_new();
2438 GtkWidget *sw;
2439
2440 gtk_container_add(GTK_CONTAINER(vwin->vbox), hp);
2441
2442 add_help_navigator(vwin, hp);
2443
2444 sw = gtk_scrolled_window_new(NULL, NULL);
2445 gtk_paned_pack2(GTK_PANED(hp), sw, TRUE, TRUE);
2446 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
2447 GTK_POLICY_AUTOMATIC,
2448 GTK_POLICY_AUTOMATIC);
2449 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
2450 GTK_SHADOW_IN);
2451 gtk_container_add(GTK_CONTAINER(sw), text);
2452
2453 gtk_widget_show_all(hp);
2454 }
2455
view_help_file(const char * filename,int role)2456 windata_t *view_help_file (const char *filename, int role)
2457 {
2458 windata_t *vwin;
2459 gchar *fbuf = NULL;
2460 gchar *title = NULL;
2461 int hsize = 82, vsize = 450;
2462
2463 /* grab content of the appropriate help file into a buffer */
2464 gretl_file_get_contents(filename, &fbuf, NULL);
2465 if (fbuf == NULL) {
2466 return NULL;
2467 }
2468
2469 title = make_viewer_title(role, NULL, NULL);
2470 vwin = gretl_viewer_new(role, title, NULL);
2471 g_free(title);
2472
2473 if (vwin == NULL) return NULL;
2474
2475 strcpy(vwin->fname, filename);
2476 vwin->data = fbuf;
2477
2478 if (role != GUI_HELP && role != GUI_HELP_EN) {
2479 set_up_helpview_menu(vwin);
2480 hsize += 4;
2481 }
2482
2483 if (role == FUNC_HELP || role == FUNC_HELP_EN) {
2484 vsize = 500;
2485 }
2486
2487 create_text(vwin, hsize, vsize, 0, FALSE);
2488
2489 if (role == GUI_HELP || role == GUI_HELP_EN) {
2490 text_table_setup(vwin->vbox, vwin->text);
2491 } else {
2492 help_panes_setup(vwin, vwin->text);
2493 }
2494
2495 g_signal_connect(G_OBJECT(vwin->text), "key-press-event",
2496 G_CALLBACK(catch_viewer_key), vwin);
2497
2498 if (vwin->role == CMD_HELP || vwin->role == CMD_HELP_EN ||
2499 vwin->role == FUNC_HELP || vwin->role == FUNC_HELP_EN) {
2500 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2501 G_CALLBACK(help_popup_handler),
2502 vwin);
2503 } else {
2504 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2505 G_CALLBACK(text_popup_handler), vwin);
2506 }
2507
2508 gtk_widget_show(vwin->vbox);
2509 gtk_widget_show(vwin->main);
2510
2511 /* make the helpfile variant discoverable via vwin->text */
2512 g_object_set_data(G_OBJECT(vwin->text), "role",
2513 GINT_TO_POINTER(vwin->role));
2514
2515 gtk_widget_grab_focus(vwin->text);
2516
2517 return vwin;
2518 }
2519
enter_close_button(GtkWidget * button,GdkEventCrossing * event,gpointer p)2520 static gboolean enter_close_button (GtkWidget *button,
2521 GdkEventCrossing *event,
2522 gpointer p)
2523 {
2524 /* remove text cursor: looks broken over a button */
2525 gdk_window_set_cursor(gtk_widget_get_window(button), NULL);
2526 return FALSE;
2527 }
2528
leave_close_button(GtkWidget * button,GdkEventCrossing * event,gpointer p)2529 static gboolean leave_close_button (GtkWidget *button,
2530 GdkEventCrossing *event,
2531 gpointer p)
2532 {
2533 GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
2534
2535 if (cursor != NULL) {
2536 /* revert to text cursor */
2537 gdk_window_set_cursor(gtk_widget_get_window(button), cursor);
2538 gdk_cursor_unref(cursor);
2539 }
2540 return FALSE;
2541 }
2542
small_close_button(GtkWidget * targ)2543 static GtkWidget *small_close_button (GtkWidget *targ)
2544 {
2545 GtkWidget *img = gtk_image_new_from_stock(GRETL_STOCK_CLOSE,
2546 GTK_ICON_SIZE_MENU);
2547 GtkWidget *button = gtk_button_new();
2548
2549 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
2550 gtk_container_add(GTK_CONTAINER(button), img);
2551
2552 gtk_widget_add_events(button, GDK_ENTER_NOTIFY_MASK |
2553 GDK_LEAVE_NOTIFY_MASK);
2554 g_signal_connect(button, "enter-notify-event",
2555 G_CALLBACK(enter_close_button), NULL);
2556 g_signal_connect(button, "leave-notify-event",
2557 G_CALLBACK(leave_close_button), NULL);
2558 g_signal_connect_swapped(button, "clicked",
2559 G_CALLBACK(gtk_widget_destroy),
2560 targ);
2561 gtk_widget_show_all(button);
2562
2563 return button;
2564 }
2565
2566 /* Stick a little "close" button into a GtkTextBuffer */
2567
add_text_closer(windata_t * vwin)2568 static void add_text_closer (windata_t *vwin)
2569 {
2570 GtkTextBuffer *tbuf;
2571 GtkTextIter iter, iend;
2572 GtkTextTag *tag;
2573 GtkTextChildAnchor *anchor;
2574 GtkWidget *button;
2575
2576 tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
2577 gtk_text_buffer_get_start_iter(tbuf, &iter);
2578 tag = gtk_text_buffer_create_tag(tbuf, NULL, "justification",
2579 GTK_JUSTIFY_RIGHT, NULL);
2580 anchor = gtk_text_buffer_create_child_anchor(tbuf, &iter);
2581 button = small_close_button(vwin->main);
2582 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(vwin->text),
2583 button, anchor);
2584 gtk_text_buffer_get_iter_at_child_anchor(tbuf, &iend, anchor);
2585 gtk_text_iter_forward_char(&iend);
2586 gtk_text_buffer_insert(tbuf, &iend, "\n", -1);
2587 gtk_text_buffer_get_start_iter(tbuf, &iter);
2588 gtk_text_buffer_apply_tag(tbuf, tag, &iter, &iend);
2589 }
2590
2591 /* For use when we want to display a piece of formatted text -- such
2592 as help for a gretl function package or a help bibliography entry
2593 -- in a window of its own, without any menu apparatus on the
2594 window. In the case of VIEW_BIBITEM, this should be a minimal window
2595 with no decorations and a simple "closer" button embedded in the
2596 GtkTextView (bibliographical popup).
2597 */
2598
view_formatted_text_buffer(const gchar * title,const char * buf,int hsize,int vsize,int role)2599 windata_t *view_formatted_text_buffer (const gchar *title,
2600 const char *buf,
2601 int hsize, int vsize,
2602 int role)
2603 {
2604 windata_t *vwin;
2605
2606 vwin = gretl_viewer_new_with_parent(NULL, role, title, NULL);
2607 if (vwin == NULL) return NULL;
2608
2609 /* non-editable text */
2610 create_text(vwin, hsize, vsize, 0, FALSE);
2611
2612 if (role == VIEW_BIBITEM) {
2613 /* no scrolling apparatus */
2614 gtk_container_add(GTK_CONTAINER(vwin->vbox), vwin->text);
2615 gtk_widget_show(vwin->text);
2616 gtk_window_set_decorated(GTK_WINDOW(vwin->main), FALSE);
2617 } else {
2618 text_table_setup(vwin->vbox, vwin->text);
2619 }
2620
2621 gretl_viewer_set_formatted_buffer(vwin, buf);
2622
2623 if (role == VIEW_BIBITEM) {
2624 add_text_closer(vwin);
2625 }
2626
2627 gtk_widget_show(vwin->vbox);
2628
2629 if (role != VIEW_BIBITEM) {
2630 gtk_widget_show(vwin->main);
2631 gtk_widget_grab_focus(vwin->text);
2632 }
2633
2634 return vwin;
2635 }
2636
2637 /* Called on destroying an editing window: give the user a chance
2638 to save if the content is changed, or to cancel the close.
2639 */
2640
query_save_text(GtkWidget * w,GdkEvent * event,windata_t * vwin)2641 gint query_save_text (GtkWidget *w, GdkEvent *event, windata_t *vwin)
2642 {
2643 if (vwin_content_changed(vwin)) {
2644 int resp = yes_no_cancel_dialog("gretl",
2645 _("Save changes?"),
2646 vwin_toplevel(vwin));
2647
2648 if (resp == GRETL_CANCEL) {
2649 /* cancel -> don't save, but also don't close */
2650 return TRUE;
2651 } else if (resp == GRETL_YES) {
2652 vwin_save_callback(NULL, vwin);
2653 }
2654 }
2655
2656 return FALSE;
2657 }
2658
edit_buffer(char ** pbuf,int hsize,int vsize,char * title,int role)2659 windata_t *edit_buffer (char **pbuf, int hsize, int vsize,
2660 char *title, int role)
2661 {
2662 windata_t *vwin;
2663
2664 vwin = gretl_viewer_new(role, title, pbuf);
2665 if (vwin == NULL) {
2666 return NULL;
2667 }
2668
2669 /* add a tool bar */
2670 vwin_add_viewbar(vwin, VIEWBAR_EDITABLE);
2671
2672 create_source(vwin, hsize, vsize, TRUE);
2673 text_table_setup(vwin->vbox, vwin->text);
2674
2675 /* insert the buffer text */
2676 if (pbuf != NULL && *pbuf != NULL) {
2677 sourceview_insert_buffer(vwin, *pbuf);
2678 }
2679
2680 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2681 G_CALLBACK(text_popup_handler), vwin);
2682 g_signal_connect(G_OBJECT(vwin->main), "key-press-event",
2683 G_CALLBACK(catch_viewer_key), vwin);
2684
2685 attach_content_changed_signal(vwin);
2686
2687 /* alert for unsaved changes on exit */
2688 g_signal_connect(G_OBJECT(vwin->main), "delete-event",
2689 G_CALLBACK(query_save_text), vwin);
2690
2691 gtk_widget_show(vwin->vbox);
2692 gtk_widget_show(vwin->main);
2693
2694 cursor_to_top(vwin);
2695
2696 return vwin;
2697 }
2698
view_model(PRN * prn,MODEL * pmod,char * title)2699 windata_t *view_model (PRN *prn, MODEL *pmod, char *title)
2700 {
2701 int hsize = MODEL_WIDTH;
2702 int vsize = MODEL_HEIGHT;
2703 windata_t *vwin;
2704 const char *buf;
2705 gchar *tmp;
2706 int width, nlines, tabbed;
2707
2708 #if 0
2709 fprintf(stderr, "view_model: pmod at %p, model %d\n",
2710 (void *) pmod, pmod->ID);
2711 #endif
2712
2713 tabbed = use_tabbed_model_viewer();
2714
2715 if (tabbed) {
2716 tmp = g_strdup_printf(_("model %d"), pmod->ID);
2717 vwin = viewer_tab_new(VIEW_MODEL, tmp, pmod);
2718 g_free(tmp);
2719 } else if (title != NULL) {
2720 vwin = gretl_viewer_new(VIEW_MODEL, title, pmod);
2721 } else {
2722 tmp = g_strdup_printf(_("gretl: model %d"), pmod->ID);
2723 vwin = gretl_viewer_new(VIEW_MODEL, tmp, pmod);
2724 g_free(tmp);
2725 }
2726
2727 if (vwin == NULL) {
2728 return NULL;
2729 }
2730
2731 /* Take responsibility for one reference to this model */
2732 gretl_object_ref(pmod, GRETL_OBJ_EQN);
2733
2734 set_up_model_view_menu(vwin);
2735
2736 gretl_print_get_size(prn, &width, &nlines);
2737 if (!tabbed && width > 0 && width + 2 < hsize) {
2738 hsize = width + 2;
2739 }
2740
2741 create_text(vwin, hsize, vsize, nlines, FALSE);
2742 text_table_setup(vwin->vbox, vwin->text);
2743
2744 /* insert and then free the model results buffer */
2745 buf = gretl_print_get_trimmed_buffer(prn);
2746 textview_set_text(vwin->text, buf);
2747 gretl_print_destroy(prn);
2748
2749 /* record digits in force */
2750 widget_set_int(vwin->text, "digits", get_gretl_digits());
2751
2752 /* sync number of model tests */
2753 vwin->n_model_tests = pmod->ntests;
2754
2755 /* attach popup */
2756 g_signal_connect(G_OBJECT(vwin->text), "button-press-event",
2757 G_CALLBACK(text_popup_handler), vwin);
2758
2759 if (window_is_tab(vwin)) {
2760 show_tabbed_viewer(vwin);
2761 } else {
2762 g_signal_connect(G_OBJECT(vwin->main), "key-press-event",
2763 G_CALLBACK(catch_viewer_key), vwin);
2764 gtk_widget_show_all(vwin->main);
2765 }
2766
2767 cursor_to_top(vwin);
2768 gtk_widget_grab_focus(vwin->text);
2769
2770 return vwin;
2771 }
2772
mnl_probs_callback(GtkAction * action,gpointer p)2773 static void mnl_probs_callback (GtkAction *action, gpointer p)
2774 {
2775 windata_t *vwin = (windata_t *) p;
2776 MODEL *pmod = vwin->data;
2777 gretl_matrix *P = NULL;
2778 int err = 0;
2779
2780 if (pmod == NULL) return;
2781
2782 P = mn_logit_probabilities(pmod, dataset, &err);
2783
2784 if (err) {
2785 gui_errmsg(err);
2786 } else {
2787 PRN *prn = NULL;
2788
2789 if (bufopen(&prn)) {
2790 gretl_matrix_free(P);
2791 } else {
2792 gretl_matrix *yvals = gretl_model_get_data(pmod, "yvals");
2793 int obslen = max_obs_marker_length(dataset);
2794 int i, j, t = gretl_matrix_get_t1(P);
2795 int n = gretl_vector_get_length(yvals);
2796 double x;
2797
2798 pprintf(prn, "\nEstimated outcome probabilities for %s\n\n",
2799 gretl_model_get_depvar_name(pmod, dataset));
2800
2801 /* case values */
2802 bufspace(obslen, prn);
2803 for (j=0; j<n; j++) {
2804 pprintf(prn, "%9g", yvals->val[j]);
2805 }
2806 pputc(prn, '\n');
2807
2808 /* format the matrix content nicely, prepending
2809 observation strings */
2810
2811 for (i=0; i<P->rows; i++) {
2812 print_obs_marker(t, dataset, obslen, prn);
2813 for (j=0; j<P->cols; j++) {
2814 x = gretl_matrix_get(P, i, j);
2815 if (na(x)) {
2816 pprintf(prn, "%9s", " ");
2817 } else {
2818 pprintf(prn, "%9.4f", x);
2819 }
2820 }
2821 pputc(prn, '\n');
2822 t++;
2823 }
2824
2825 view_buffer(prn, 78, 400, _("Outcome probabilities"), PRINT, NULL);
2826 gretl_matrix_free(P);
2827 }
2828 }
2829 }
2830
add_multinomial_probs_item(windata_t * vwin)2831 static void add_multinomial_probs_item (windata_t *vwin)
2832 {
2833 const gchar *mpath = "/menubar/Analysis";
2834 GtkActionEntry entry;
2835
2836 action_entry_init(&entry);
2837 entry.name = "mnlprobs";
2838 entry.label = _("Outcome probabilities");
2839 entry.callback = G_CALLBACK(mnl_probs_callback);
2840 vwin_menu_add_item(vwin, mpath, &entry);
2841 }
2842
dw_pval_ok(const MODEL * pmod)2843 static int dw_pval_ok (const MODEL *pmod)
2844 {
2845 if (na(pmod->dw)) {
2846 return 0;
2847 } else if (pmod->ci == OLS) {
2848 return 1;
2849 } else if (pmod->ci == PANEL) {
2850 return panel_DW_pval_ok(pmod);
2851 } else {
2852 return 0;
2853 }
2854 }
2855
get_ci_and_opt(const gchar * s,int * ci,gretlopt * opt)2856 static void get_ci_and_opt (const gchar *s, int *ci, gretlopt *opt)
2857 {
2858 char c, word[9];
2859
2860 sscanf(s, "%8[^:]:%c", word, &c);
2861 *ci = gretl_command_number(word);
2862 *opt = opt_from_flag((unsigned char) c);
2863 }
2864
set_tests_menu_state(GtkUIManager * ui,const MODEL * pmod)2865 static void set_tests_menu_state (GtkUIManager *ui, const MODEL *pmod)
2866 {
2867 gretlopt opt;
2868 char path[128];
2869 const gchar *s;
2870 int i, n, ci;
2871
2872 if (pmod->ci == MPOLS) {
2873 /* can we relax this? */
2874 flip(ui, "/menubar/Tests", FALSE);
2875 return;
2876 }
2877
2878 n = G_N_ELEMENTS(model_test_items);
2879
2880 for (i=0; i<n; i++) {
2881 int skip = 0;
2882
2883 opt = OPT_NONE;
2884 s = model_test_items[i].name;
2885 if (strchr(s, ':')) {
2886 get_ci_and_opt(s, &ci, &opt);
2887 } else if (!strcmp(s, "dwpval")) {
2888 sprintf(path, "/menubar/Tests/%s", s);
2889 flip(ui, path, dw_pval_ok(pmod));
2890 continue;
2891 } else if (!strcmp(s, "Hsk")) {
2892 ci = MODTEST;
2893 if (pmod->ci == PANEL && (pmod->opt & OPT_U)) {
2894 /* random effects: not supported (FIXME?) */
2895 skip = 1;
2896 } else {
2897 opt = (dataset_is_panel(dataset))? OPT_P : OPT_W;
2898 }
2899 } else {
2900 ci = gretl_command_number(s);
2901 }
2902 sprintf(path, "/menubar/Tests/%s", s);
2903 if (skip) {
2904 flip(ui, path, FALSE);
2905 } else {
2906 flip(ui, path, model_test_ok(ci, opt, pmod, dataset));
2907 }
2908 }
2909
2910 if (pmod->ci == GARCH) {
2911 flip(ui, "/menubar/Tests/Hsk", FALSE);
2912 } else if (pmod->ci == PROBIT && (pmod->opt & OPT_E)) {
2913 /* random effects probit */
2914 flip(ui, "/menubar/Tests/modtest:n", FALSE);
2915 } else if (gretl_is_between_model(pmod)) {
2916 flip(ui, "/menubar/Tests/coeffsum", FALSE);
2917 flip(ui, "/menubar/Tests/Hsk", FALSE);
2918 }
2919 }
2920
set_analysis_menu_state(windata_t * vwin,const MODEL * pmod)2921 static void set_analysis_menu_state (windata_t *vwin, const MODEL *pmod)
2922 {
2923 GtkUIManager *ui = vwin->ui;
2924 gboolean s;
2925
2926 if (pmod->ci == MLE || pmod->ci == GMM || pmod->ci == BIPROBIT) {
2927 /* can we relax some of this later? */
2928 flip(ui, "/menubar/Analysis/DisplayAFR", FALSE);
2929 flip(ui, "/menubar/Analysis/Forecasts", FALSE);
2930 } else if (pmod->ci == LOGIT && gretl_model_get_int(pmod, "multinom")) {
2931 /* relax this? */
2932 flip(ui, "/menubar/Analysis/Forecasts", FALSE);
2933 add_multinomial_probs_item(vwin);
2934 } else if (pmod->ci == PROBIT && (pmod->opt & OPT_E)) {
2935 /* random effects probit */
2936 flip(ui, "/menubar/Analysis/Forecasts", FALSE);
2937 }
2938
2939 if (pmod->ncoeff == 1) {
2940 flip(ui, "/menubar/Analysis/ConfEllipse", FALSE);
2941 }
2942
2943 if (pmod->ci == DPANEL || (pmod->ci == PANEL && !(pmod->opt & OPT_P))) {
2944 flip(ui, "/menubar/Analysis/Forecasts", FALSE);
2945 }
2946
2947 if (pmod->ci != OLS || !pmod->ifc || na(pmod->ess) || na(pmod->tss)) {
2948 flip(ui, "/menubar/Analysis/ANOVA", FALSE);
2949 }
2950
2951 if (!bootstrap_ok(pmod->ci)) {
2952 flip(ui, "/menubar/Analysis/Bootstrap", FALSE);
2953 }
2954
2955 if (gretl_model_get_int(pmod, "null-model")) {
2956 flip(ui, "/menubar/Analysis/ConfIntervals", FALSE);
2957 flip(ui, "/menubar/Analysis/Covariance", FALSE);
2958 }
2959
2960 s = model_test_ok(VIF, OPT_NONE, pmod, dataset) ||
2961 pmod->vcv != NULL;
2962 flip(ui, "/menubar/Analysis/Collinearity", s);
2963
2964 if (!model_test_ok(LEVERAGE, OPT_NONE, pmod, dataset)) {
2965 flip(ui, "/menubar/Analysis/Leverage", FALSE);
2966 }
2967 }
2968
arma_x12_menu_mod(windata_t * vwin)2969 static void arma_x12_menu_mod (windata_t *vwin)
2970 {
2971 flip(vwin->ui, "/menubar/Analysis/Covariance", FALSE);
2972 add_x12_output_menu_item(vwin);
2973 }
2974
rq_coeff_intervals_mod(windata_t * vwin)2975 static void rq_coeff_intervals_mod (windata_t *vwin)
2976 {
2977 flip(vwin->ui, "/menubar/Analysis/ConfIntervals", FALSE);
2978 }
2979
midas_plot_callback(GtkAction * action,gpointer p)2980 static void midas_plot_callback (GtkAction *action, gpointer p)
2981 {
2982 windata_t *vwin = (windata_t *) p;
2983 MODEL *pmod = vwin->data;
2984 gretl_matrix *C = NULL;
2985 int err;
2986
2987 if (pmod == NULL) return;
2988
2989 C = gretl_model_get_data(pmod, "midas_coeffs");
2990
2991 if (C != NULL) {
2992 const char *literal =
2993 "{set title 'MIDAS coefficients';"
2994 " set xlabel 'high-frequency lag';"
2995 " set ylabel '';}";
2996
2997 err = matrix_plot(C, NULL, literal, OPT_P | OPT_S | OPT_G);
2998 gui_graph_handler(err);
2999 }
3000 }
3001
arma_spectrum_callback(GtkAction * action,gpointer p)3002 static void arma_spectrum_callback (GtkAction *action, gpointer p)
3003 {
3004 windata_t *vwin = (windata_t *) p;
3005 MODEL *pmod = (MODEL *) vwin->data;
3006 int err;
3007
3008 err = arma_spectrum_plot(pmod, dataset, OPT_NONE);
3009
3010 gui_graph_handler(err);
3011 }
3012
3013 #define intervals_model(m) (m->ci == LAD && \
3014 gretl_model_get_data(m, "coeff_intervals"))
3015
adjust_model_menu_state(windata_t * vwin,const MODEL * pmod)3016 static void adjust_model_menu_state (windata_t *vwin, const MODEL *pmod)
3017 {
3018 /* disallow saving an already-saved model */
3019 if (is_session_model((void *) pmod)) {
3020 set_model_save_state(vwin, FALSE);
3021 }
3022
3023 if (RQ_SPECIAL_MODEL(pmod)) {
3024 /* can we relax this later? */
3025 flip(vwin->ui, "/menubar/Tests", FALSE);
3026 flip(vwin->ui, "/menubar/Save", FALSE);
3027 flip(vwin->ui, "/menubar/Analysis", FALSE);
3028 return;
3029 }
3030
3031 set_tests_menu_state(vwin->ui, pmod);
3032 set_analysis_menu_state(vwin, pmod);
3033
3034 if (intervals_model(pmod)) {
3035 rq_coeff_intervals_mod(vwin);
3036 }
3037
3038 if (pmod->ci == ARMA && arma_by_x12a(pmod)) {
3039 arma_x12_menu_mod(vwin);
3040 }
3041
3042 if (pmod->ci == MLE || pmod->ci == GMM || pmod->ci == BIPROBIT) {
3043 /* can we relax this later? */
3044 flip(vwin->ui, "/menubar/Graphs", FALSE);
3045 } else if (gretl_is_between_model(pmod) &&
3046 pmod->dataset == NULL) {
3047 flip(vwin->ui, "/menubar/Graphs", FALSE);
3048 }
3049
3050 if (pmod->ci == GMM || pmod->ci == BIPROBIT) {
3051 /* FIXME? */
3052 flip(vwin->ui, "/menubar/Save", FALSE);
3053 }
3054 }
3055
3056 static GtkActionEntry model_data_base_items[] = {
3057 { "bundle", NULL, N_("_Model as bundle"), NULL, NULL,
3058 G_CALLBACK(model_stat_callback) },
3059 { "yhat", NULL, N_("_Fitted values"), NULL, NULL,
3060 G_CALLBACK(fit_resid_callback) },
3061 { "uhat", NULL, N_("_Residuals"), NULL, NULL,
3062 G_CALLBACK(fit_resid_callback) },
3063 { "uhat2", NULL, N_("_Squared residuals"), NULL, NULL,
3064 G_CALLBACK(fit_resid_callback) }
3065 };
3066
3067 static GtkActionEntry ess_items[] = {
3068 { "ess", NULL, N_("_Error sum of squares"), NULL, NULL,
3069 G_CALLBACK(model_stat_callback) },
3070 { "se", NULL, N_("_Standard error of the regression"), NULL, NULL,
3071 G_CALLBACK(model_stat_callback) }
3072 };
3073
3074 static GtkActionEntry r_squared_items[] = {
3075 { "rsq", NULL, N_("_R-squared"), NULL, NULL, G_CALLBACK(model_stat_callback) },
3076 { "trsq", NULL, N_("_T*R-squared"), NULL, NULL, G_CALLBACK(model_stat_callback) }
3077 };
3078
3079 static GtkActionEntry lnl_data_items[] = {
3080 { "lnL", NULL, N_("_Log likelihood"), NULL, NULL,
3081 G_CALLBACK(model_stat_callback) }
3082 };
3083
3084 static GtkActionEntry criteria_items[] = {
3085 { "AIC", NULL, N_("_Akaike Information Criterion"), NULL, NULL,
3086 G_CALLBACK(model_stat_callback) },
3087 { "BIC", NULL, N_("_Bayesian Information Criterion"), NULL, NULL,
3088 G_CALLBACK(model_stat_callback) },
3089 { "HQC", NULL, N_("_Hannan-Quinn Information Criterion"), NULL, NULL,
3090 G_CALLBACK(model_stat_callback) }
3091 };
3092
3093 static GtkActionEntry garch_data_items[] = {
3094 { "h", NULL, N_("_Predicted error variance"), NULL, NULL,
3095 G_CALLBACK(fit_resid_callback)
3096 }
3097 };
3098
3099 static GtkActionEntry fixed_effects_data_items[] = {
3100 { "ahat", NULL, N_("Per-unit _constants"), NULL, NULL,
3101 G_CALLBACK(fit_resid_callback)
3102 }
3103 };
3104
3105 static GtkActionEntry random_effects_data_items[] = {
3106 { "ahat", NULL, N_("Individual effects"), NULL, NULL,
3107 G_CALLBACK(fit_resid_callback)
3108 }
3109 };
3110
3111 static GtkActionEntry define_var_items[] = {
3112 /* Under Save; Sep wanted */
3113 { "NewVar", NULL, N_("Define _new variable..."), NULL, NULL,
3114 G_CALLBACK(model_genr_callback) }
3115 };
3116
criteria_available(const MODEL * pmod)3117 static int criteria_available (const MODEL *pmod)
3118 {
3119 int i;
3120
3121 for (i=0; i<C_MAX; i++) {
3122 if (na(pmod->criterion[i])) {
3123 return 0;
3124 }
3125 }
3126
3127 return 1;
3128 }
3129
add_model_dataset_items(windata_t * vwin)3130 static void add_model_dataset_items (windata_t *vwin)
3131 {
3132 const gchar *path = "/menubar/Save";
3133 MODEL *pmod = vwin->data;
3134
3135 vwin_menu_add_items(vwin, path, model_data_base_items,
3136 G_N_ELEMENTS(model_data_base_items));
3137
3138 if (gretl_model_get_data(pmod, "ahat") != NULL) {
3139 if (pmod->opt & OPT_U) {
3140 vwin_menu_add_items(vwin, path, random_effects_data_items,
3141 G_N_ELEMENTS(random_effects_data_items));
3142 } else {
3143 vwin_menu_add_items(vwin, path, fixed_effects_data_items,
3144 G_N_ELEMENTS(fixed_effects_data_items));
3145 }
3146 }
3147
3148 if (pmod->ci != GARCH && !(pmod->ci == LOGIT && (pmod->opt & OPT_M))) {
3149 vwin_menu_add_items(vwin, path, ess_items,
3150 G_N_ELEMENTS(ess_items));
3151 }
3152
3153 if (!ML_ESTIMATOR(pmod->ci) && pmod->ci != LAD && !na(pmod->rsq)) {
3154 vwin_menu_add_items(vwin, path, r_squared_items,
3155 G_N_ELEMENTS(r_squared_items));
3156 }
3157
3158 if (!na(pmod->lnL)) {
3159 vwin_menu_add_items(vwin, path, lnl_data_items,
3160 G_N_ELEMENTS(lnl_data_items));
3161 }
3162
3163 if (criteria_available(pmod)) {
3164 vwin_menu_add_items(vwin, path, criteria_items,
3165 G_N_ELEMENTS(criteria_items));
3166 }
3167
3168 if (pmod->ci == GARCH) {
3169 vwin_menu_add_items(vwin, path, garch_data_items,
3170 G_N_ELEMENTS(garch_data_items));
3171 }
3172
3173 vwin_menu_add_separator(vwin, path);
3174
3175 vwin_menu_add_items(vwin, path, define_var_items,
3176 G_N_ELEMENTS(define_var_items));
3177 }
3178
add_model_tex_items(windata_t * vwin)3179 static void add_model_tex_items (windata_t *vwin)
3180 {
3181 MODEL *pmod = (MODEL *) vwin->data;
3182 int eqn_ok = command_ok_for_model(EQNPRINT, 0, pmod);
3183 GtkActionGroup *actions;
3184 GError *err = NULL;
3185 int imod = 0;
3186
3187 gtk_ui_manager_add_ui_from_string(vwin->ui, model_tex_ui, -1, &err);
3188
3189 if (err != NULL) {
3190 g_message("building LaTeX menu failed: %s", err->message);
3191 g_error_free(err);
3192 return;
3193 }
3194
3195 actions = gtk_action_group_new("ModelTeX");
3196 gtk_action_group_set_translation_domain(actions, "gretl");
3197 gtk_action_group_add_actions(actions, model_tex_items,
3198 G_N_ELEMENTS(model_tex_items),
3199 vwin);
3200 gtk_action_group_add_radio_actions(actions, tex_eqn_items,
3201 G_N_ELEMENTS(tex_eqn_items),
3202 (get_tex_eqn_opt() == OPT_T),
3203 G_CALLBACK(set_tex_eqn_opt),
3204 vwin);
3205 gtk_ui_manager_insert_action_group(vwin->ui, actions, 0);
3206 g_object_unref(actions);
3207
3208 if (intervals_model(pmod)) {
3209 eqn_ok = 0;
3210 imod = 1;
3211 }
3212
3213 if (!eqn_ok || pmod->errcode) {
3214 flip(vwin->ui, "/menubar/LaTeX/TeXView/EqnView", FALSE);
3215 flip(vwin->ui, "/menubar/LaTeX/TeXCopy/EqnCopy", FALSE);
3216 flip(vwin->ui, "/menubar/LaTeX/TeXSave/EqnSave", FALSE);
3217 flip(vwin->ui, "/menubar/LaTeX/EqnOpts", FALSE);
3218 }
3219
3220 if (imod) {
3221 flip(vwin->ui, "/menubar/LaTeX/TabOpts", FALSE);
3222 }
3223 }
3224
3225 /* dummy placeholder, for when TeX is not supported */
3226
add_missing_tex_items(windata_t * vwin)3227 static void add_missing_tex_items (windata_t *vwin)
3228 {
3229 GtkActionGroup *actions;
3230 GError *err = NULL;
3231
3232 gtk_ui_manager_add_ui_from_string(vwin->ui, missing_tex_ui, -1, &err);
3233 if (err != NULL) {
3234 g_message("building menus failed: %s", err->message);
3235 g_error_free(err);
3236 return;
3237 }
3238
3239 actions = gtk_action_group_new("MissingTeX");
3240 gtk_action_group_add_actions(actions, missing_tex_items,
3241 G_N_ELEMENTS(missing_tex_items),
3242 vwin);
3243 gtk_ui_manager_insert_action_group(vwin->ui, actions, 0);
3244 g_object_unref(actions);
3245
3246 flip(vwin->ui, "/menubar/LaTeX", FALSE);
3247 }
3248
3249 #define VNAMELEN2 (2*VNAMELEN)
3250
add_vars_to_plot_menu(windata_t * vwin)3251 static void add_vars_to_plot_menu (windata_t *vwin)
3252 {
3253 GtkActionEntry entry;
3254 const gchar *mpath[] = {
3255 "/menubar/Graphs/ResidPlot",
3256 "/menubar/Graphs/FittedActualPlot"
3257 };
3258 MODEL *pmod = vwin->data;
3259 char tmp[VNAMELEN2], aname[VNAMELEN];
3260 gchar *alabel;
3261 int *xlist;
3262 int v1, v2;
3263 int i, j;
3264
3265 action_entry_init(&entry);
3266
3267 /* non-time series: residual boxplot */
3268 if (!dataset_is_time_series(dataset)) {
3269 entry.label = _("_Boxplot");
3270 entry.name = "r:box";
3271 entry.callback = G_CALLBACK(resid_plot);
3272 vwin_menu_add_item(vwin, mpath[0], &entry);
3273 }
3274
3275 xlist = gretl_model_get_x_list(pmod);
3276
3277 for (i=0; i<2; i++) {
3278 /* plot against time/obs number */
3279 if (dataset_is_time_series(dataset)) {
3280 entry.label = _("_Against time");
3281 } else {
3282 entry.label = _("By _observation number");
3283 }
3284 entry.name = (i == 0)? "r:byobs" : "f:byobs";
3285 entry.callback = (i == 0)? G_CALLBACK(resid_plot) :
3286 G_CALLBACK(fit_actual_plot);
3287 vwin_menu_add_item(vwin, mpath[i], &entry);
3288
3289 if (pmod->ci == NLS ||
3290 pmod->ci == MLE ||
3291 pmod->ci == GMM ||
3292 pmod->ci == PANEL) {
3293 continue;
3294 }
3295
3296 /* if doing resid plot, put dependent var in menu */
3297 if (i == 0) {
3298 v1 = gretl_model_get_depvar(pmod);
3299 if (v1 > 0) {
3300 sprintf(aname, "r:xvar %d", v1); /* FIXME */
3301 double_underscores(tmp, dataset->varname[v1]);
3302 alabel = g_strdup_printf(_("_Against %s"), tmp);
3303 entry.name = aname;
3304 entry.label = alabel;
3305 entry.callback = G_CALLBACK(resid_plot);
3306 vwin_menu_add_item(vwin, mpath[0], &entry);
3307 g_free(alabel);
3308 }
3309 }
3310
3311 if (xlist != NULL) {
3312 /* put the independent vars on the menu list */
3313 for (j=1; j<=xlist[0]; j++) {
3314 v1 = xlist[j];
3315 if (v1 == 0) {
3316 continue;
3317 }
3318 if (!strcmp(dataset->varname[v1], "time")) {
3319 continue;
3320 }
3321 sprintf(aname, "%c:xvar %d", (i == 0)? 'r' : 'f', v1);
3322 double_underscores(tmp, dataset->varname[v1]);
3323 alabel = g_strdup_printf(_("_Against %s"), tmp);
3324 entry.name = aname;
3325 entry.label = alabel;
3326 entry.callback = (i == 0)? G_CALLBACK(resid_plot) :
3327 G_CALLBACK(fit_actual_plot);
3328 vwin_menu_add_item(vwin, mpath[i], &entry);
3329 g_free(alabel);
3330 }
3331 }
3332
3333 if (i == 1) {
3334 /* fitted values: offer Theil-type scatterplot */
3335 entry.name = "f:theil";
3336 entry.label = _("Actual vs. Fitted");
3337 entry.callback = G_CALLBACK(fit_actual_plot);
3338 vwin_menu_add_item(vwin, mpath[i], &entry);
3339 }
3340 }
3341
3342 /* time series models: residual correlogram, spectrum */
3343 if (dataset_is_time_series(dataset)) {
3344 vwin_menu_add_separator(vwin, "/menubar/Graphs");
3345 entry.name = "Correlogram";
3346 entry.label = _("Residual _correlogram");
3347 entry.callback = G_CALLBACK(residual_correlogram_callback);
3348 vwin_menu_add_item(vwin, "/menubar/Graphs", &entry);
3349 entry.name = "Spectrum";
3350 entry.label = _("Residual _periodogram");
3351 entry.callback = G_CALLBACK(residual_periodogram_callback);
3352 vwin_menu_add_item(vwin, "/menubar/Graphs", &entry);
3353 if (pmod->ci == ARMA && gretl_model_get_data(pmod, "ainfo") != NULL) {
3354 entry.name = "ARMAspectrum";
3355 entry.label = _("_Spectrum vs sample periodogram");
3356 entry.callback = G_CALLBACK(arma_spectrum_callback);
3357 vwin_menu_add_item(vwin, "/menubar/Graphs", &entry);
3358 } else if (gretl_model_get_data(pmod, "midas_coeffs") != NULL) {
3359 entry.name = "MIDAScoeffs";
3360 entry.label = _("_MIDAS coefficients");
3361 entry.callback = G_CALLBACK(midas_plot_callback);
3362 vwin_menu_add_item(vwin, "/menubar/Graphs", &entry);
3363 }
3364 } else {
3365 vwin_menu_add_separator(vwin, "/menubar/Graphs");
3366 }
3367
3368 /* residual Q-Q plot */
3369 entry.name = "QQPlot";
3370 entry.label = _("Residual _Q-Q plot");
3371 entry.callback = G_CALLBACK(residual_qq_plot);
3372 vwin_menu_add_item(vwin, "/menubar/Graphs", &entry);
3373
3374 /* 3-D fitted versus actual plot? */
3375 if (xlist != NULL) {
3376 int parnames = pmod->dataset != NULL;
3377
3378 v1 = v2 = -1;
3379 if (pmod->ifc && xlist[0] == 3) {
3380 v1 = parnames ? 1 : xlist[2];
3381 v2 = parnames ? 2 : xlist[3];
3382 } else if (!pmod->ifc && xlist[0] == 2) {
3383 v1 = parnames ? 0 : xlist[1];
3384 v2 = parnames ? 1 : xlist[2];
3385 }
3386 if (v1 >= 0 && v2 >= 0) {
3387 char tmp2[VNAMELEN2];
3388
3389 if (parnames) {
3390 char pname[VNAMELEN];
3391
3392 gretl_model_get_param_name(pmod, pmod->dataset,
3393 v1, pname);
3394 double_underscores(tmp, pname);
3395 gretl_model_get_param_name(pmod, pmod->dataset,
3396 v2, pname);
3397 double_underscores(tmp2, pname);
3398 } else {
3399 double_underscores(tmp, dataset->varname[v1]);
3400 double_underscores(tmp2, dataset->varname[v2]);
3401 }
3402 vwin_menu_add_separator(vwin, mpath[1]);
3403 alabel = g_strdup_printf(_("_Against %s and %s"), tmp, tmp2);
3404 entry.name = "splot";
3405 entry.label = alabel;
3406 entry.callback = G_CALLBACK(fit_actual_splot);
3407 vwin_menu_add_item(vwin, mpath[1], &entry);
3408 g_free(alabel);
3409 }
3410 }
3411
3412 free(xlist);
3413 }
3414
plot_dummy_call(GtkRadioAction * action,GtkRadioAction * current,windata_t * vwin)3415 static void plot_dummy_call (GtkRadioAction *action,
3416 GtkRadioAction *current,
3417 windata_t *vwin)
3418 {
3419 vwin->active_var = gtk_radio_action_get_current_value(action);
3420 }
3421
radio_action_init(GtkRadioActionEntry * a)3422 static void radio_action_init (GtkRadioActionEntry *a)
3423 {
3424 a->stock_id = NULL;
3425 a->accelerator = NULL;
3426 a->tooltip = NULL;
3427 }
3428
add_dummies_to_plot_menu(windata_t * vwin)3429 static void add_dummies_to_plot_menu (windata_t *vwin)
3430 {
3431 GtkActionEntry item;
3432 GtkRadioActionEntry *items;
3433 MODEL *pmod = vwin->data;
3434 const gchar *gpath = "/menubar/Graphs/ResidPlot";
3435 const gchar *spath = "/menubar/Graphs/ResidPlot/Separation";
3436 char tmp[VNAMELEN2];
3437 int *dlist = NULL;
3438 int i, vi, ndums;
3439
3440 /* make a list of dummy independent variables */
3441 for (i=2; i<=pmod->list[0]; i++) {
3442 vi = pmod->list[i];
3443 if (vi == LISTSEP) {
3444 break;
3445 } else if (vi > 0 && vi < dataset->v &&
3446 gretl_isdummy(dataset->t1, dataset->t2, dataset->Z[vi])) {
3447 gretl_list_append_term(&dlist, vi);
3448 }
3449 }
3450
3451 if (dlist == NULL) {
3452 return;
3453 }
3454
3455 ndums = dlist[0];
3456 items = malloc((ndums + 1) * sizeof *items);
3457 if (items == NULL) {
3458 free(dlist);
3459 return;
3460 }
3461
3462 /* add separator */
3463 vwin_menu_add_separator(vwin, gpath);
3464
3465 /* add menu branch */
3466 action_entry_init(&item);
3467 item.name = "Separation";
3468 item.label = _("Separation");
3469 vwin_menu_add_menu(vwin, gpath, &item);
3470
3471 /* configure "none" radio option */
3472 radio_action_init(&items[0]);
3473 items[0].name = "none";
3474 items[0].label = _("none");
3475 items[0].value = 0;
3476
3477 /* put the dummy independent vars on the menu list */
3478 for (i=1; i<=dlist[0]; i++) {
3479 vi = dlist[i];
3480 radio_action_init(&items[i]);
3481 double_underscores(tmp, dataset->varname[vi]);
3482 items[i].name = g_strdup_printf("dum %d", vi);
3483 items[i].label = g_strdup_printf(_("By %s"), tmp);
3484 items[i].value = vi;
3485 }
3486
3487 vwin_menu_add_radios(vwin, spath, items, ndums + 1, 0,
3488 G_CALLBACK(plot_dummy_call));
3489
3490 for (i=1; i<=dlist[0]; i++) {
3491 g_free((gchar *) items[i].name);
3492 g_free((gchar *) items[i].label);
3493 }
3494
3495 free(items);
3496 free(dlist);
3497 }
3498
varnum_from_action(GtkAction * action,int * i)3499 static void varnum_from_action (GtkAction *action, int *i)
3500 {
3501 const gchar *s = gtk_action_get_name(action);
3502
3503 sscanf(s, "%*s %d", i);
3504 }
3505
tau_plot_call(GtkAction * action,gpointer p)3506 static void tau_plot_call (GtkAction *action, gpointer p)
3507 {
3508 windata_t *vwin = (windata_t *) p;
3509 MODEL *pmod = (MODEL *) vwin->data;
3510 int v, err;
3511
3512 varnum_from_action(action, &v);
3513 err = plot_tau_sequence(pmod, dataset, v);
3514 gui_graph_handler(err);
3515 }
3516
add_tau_plot_menu(windata_t * vwin)3517 static void add_tau_plot_menu (windata_t *vwin)
3518 {
3519 GtkActionEntry item;
3520 MODEL *pmod = vwin->data;
3521 char tmp[VNAMELEN2], aname[VNAMELEN];
3522 int i;
3523
3524 action_entry_init(&item);
3525 item.name = "TauMenu";
3526 item.label = _("tau sequence");
3527 vwin_menu_add_menu(vwin, "/menubar/Graphs", &item);
3528
3529 item.callback = G_CALLBACK(tau_plot_call);
3530
3531 /* put the independent vars on the menu list */
3532 for (i=2; i<=pmod->list[0]; i++) {
3533 sprintf(aname, "tauseq %d", i - 2);
3534 double_underscores(tmp, dataset->varname[pmod->list[i]]);
3535 item.name = aname;
3536 item.label = tmp;
3537 vwin_menu_add_item(vwin, "/menubar/Graphs/TauMenu", &item);
3538 }
3539
3540 /* and disable what we can't (yet) show */
3541 flip(vwin->ui, "/menubar/Graphs/ResidPlot", FALSE);
3542 flip(vwin->ui, "/menubar/Graphs/FittedActualPlot", FALSE);
3543 }
3544
x12_output_callback(GtkAction * action,gpointer p)3545 static void x12_output_callback (GtkAction *action, gpointer p)
3546 {
3547 windata_t *vwin = (windata_t *) p;
3548 MODEL *pmod = vwin->data;
3549 char *fname;
3550
3551 if (pmod == NULL) return;
3552
3553 fname = gretl_model_get_data(pmod, "x12a_output");
3554
3555 if (fname != NULL) {
3556 char *p = strrchr(fname, '.');
3557
3558 if (p != NULL && strlen(p) == 7) {
3559 gchar *tmp = g_strdup(fname);
3560
3561 sprintf(p, ".%d", pmod->ID);
3562 gretl_rename(tmp, fname);
3563 g_free(tmp);
3564 }
3565 view_file(fname, 0, 0, 78, 350, VIEW_FILE);
3566 }
3567 }
3568
get_model_ui(void)3569 static gchar *get_model_ui (void)
3570 {
3571 gchar *ui = NULL;
3572 gchar *fname;
3573 int err;
3574
3575 fname = g_strdup_printf("%sui%cgretlmodel.xml", gretl_home(), SLASH);
3576 err = gretl_file_get_contents(fname, &ui, NULL);
3577 g_free(fname);
3578
3579 return err ? NULL : ui;
3580 }
3581
set_up_model_view_menu(windata_t * vwin)3582 static void set_up_model_view_menu (windata_t *vwin)
3583 {
3584 static gchar *model_ui;
3585 MODEL *pmod = (MODEL *) vwin->data;
3586 GtkActionGroup *actions;
3587 GtkWidget *toplevel;
3588 GError *err = NULL;
3589
3590 if (model_ui == NULL) {
3591 model_ui = get_model_ui();
3592 if (model_ui == NULL) {
3593 errbox("building menus failed");
3594 return;
3595 }
3596 }
3597
3598 actions = gtk_action_group_new("ModelActions");
3599 gtk_action_group_set_translation_domain(actions, "gretl");
3600
3601 gtk_action_group_add_actions(actions, model_items,
3602 G_N_ELEMENTS(model_items),
3603 vwin);
3604 gtk_action_group_add_actions(actions, model_test_items,
3605 G_N_ELEMENTS(model_test_items),
3606 vwin);
3607
3608 vwin->ui = gtk_ui_manager_new();
3609 gtk_ui_manager_insert_action_group(vwin->ui, actions, 0);
3610 g_object_unref(actions);
3611
3612 gtk_ui_manager_add_ui_from_string(vwin->ui, model_ui, -1, &err);
3613 if (err != NULL) {
3614 g_message("building menus failed: %s", err->message);
3615 g_error_free(err);
3616 }
3617
3618 if (pmod->ci != MLE && pmod->ci != GMM && pmod->ci != BIPROBIT) {
3619 if (RQ_SPECIAL_MODEL(pmod)) {
3620 add_tau_plot_menu(vwin);
3621 } else {
3622 add_vars_to_plot_menu(vwin);
3623 }
3624 add_model_dataset_items(vwin);
3625 }
3626
3627 /* heteroskedasticity tests: the permissible options vary
3628 depending on the nature of the model
3629 */
3630
3631 if (dataset_is_panel(dataset)) {
3632 if (pmod->ci == OLS) {
3633 vwin_menu_add_items(vwin, "/menubar/Tests/Hsk",
3634 panel_hsk_items,
3635 G_N_ELEMENTS(panel_hsk_items));
3636 } else if (pmod->ci == PANEL && (pmod->opt & OPT_F)) {
3637 /* fixed effects */
3638 vwin_menu_add_items(vwin, "/menubar/Tests/Hsk",
3639 panel_hsk_items + 1, 1);
3640 } else if (0 && pmod->ci == PANEL && (pmod->opt & OPT_U)) {
3641 /* random effects: is this OK?? */
3642 vwin_menu_add_items(vwin, "/menubar/Tests/Hsk",
3643 panel_hsk_items + 1, 1);
3644 }
3645 } else if (pmod->ci == IVREG) {
3646 vwin_menu_add_items(vwin, "/menubar/Tests/Hsk",
3647 ivreg_hsk_items,
3648 G_N_ELEMENTS(ivreg_hsk_items));
3649 } else if (model_test_ok(MODTEST, OPT_W, pmod, dataset)) {
3650 vwin_menu_add_items(vwin, "/menubar/Tests/Hsk",
3651 base_hsk_items,
3652 G_N_ELEMENTS(base_hsk_items));
3653 if (pmod->ncoeff == 1 || (pmod->ifc && pmod->ncoeff == 2)) {
3654 flip(vwin->ui, "/menubar/Tests/Hsk/WhiteSquares", FALSE);
3655 }
3656 }
3657
3658 maybe_add_packages_to_model_menus(vwin);
3659
3660 if (latex_is_ok() && !pmod->errcode && !RQ_SPECIAL_MODEL(pmod)) {
3661 add_model_tex_items(vwin);
3662 } else {
3663 add_missing_tex_items(vwin);
3664 }
3665
3666 if (!text_equation_ok(pmod)) {
3667 flip(vwin->ui, "/menubar/File/TextEqn", FALSE);
3668 }
3669
3670 if (pmod->ci != ARMA && pmod->ci != GARCH &&
3671 pmod->ci != NLS && pmod->ci != MLE && pmod->ci != GMM &&
3672 pmod->ci != PANEL && pmod->ci != DPANEL &&
3673 pmod->ci != BIPROBIT) {
3674 add_dummies_to_plot_menu(vwin);
3675 }
3676
3677 toplevel = vwin_toplevel(vwin);
3678 if (toplevel != NULL) {
3679 /* FIXME tabbed case? */
3680 gtk_window_add_accel_group(GTK_WINDOW(toplevel),
3681 gtk_ui_manager_get_accel_group(vwin->ui));
3682 }
3683
3684 vwin->mbar = gtk_ui_manager_get_widget(vwin->ui, "/menubar");
3685
3686 /* disable some menu items if need be */
3687 adjust_model_menu_state(vwin, pmod);
3688
3689 g_signal_connect(G_OBJECT(vwin->mbar), "button-press-event",
3690 G_CALLBACK(check_model_menu), vwin);
3691
3692 vwin_pack_toolbar(vwin);
3693 }
3694
3695 enum {
3696 SYS_DATA_RESIDS,
3697 SYS_DATA_FITTED,
3698 SYS_DATA_SIGMA
3699 };
3700
sys_data_code(GtkAction * action)3701 static int sys_data_code (GtkAction *action)
3702 {
3703 const gchar *s = gtk_action_get_name(action);
3704
3705 if (!strcmp(s, "uhat")) {
3706 return SYS_DATA_RESIDS;
3707 } else if (!strcmp(s, "yhat")) {
3708 return SYS_DATA_FITTED;
3709 } else if (!strcmp(s, "sigma")) {
3710 return SYS_DATA_SIGMA;
3711 } else {
3712 return SYS_DATA_RESIDS;
3713 }
3714 }
3715
system_data_callback(GtkAction * action,gpointer p)3716 static void system_data_callback (GtkAction *action, gpointer p)
3717 {
3718 windata_t *vwin = (windata_t *) p;
3719 GRETL_VAR *var = NULL;
3720 equation_system *sys = NULL;
3721 const gretl_matrix *M = NULL;
3722 gchar *wtitle = NULL;
3723 PRN *prn;
3724 int code, k = 0;
3725 int err = 0;
3726
3727 if (vwin->role == SYSTEM) {
3728 sys = (equation_system *) vwin->data;
3729 } else {
3730 var = (GRETL_VAR *) vwin->data;
3731 }
3732
3733 if ((var == NULL && sys == NULL) || bufopen(&prn)) {
3734 return;
3735 }
3736
3737 code = sys_data_code(action);
3738
3739 if (code == SYS_DATA_SIGMA) {
3740 if (var != NULL) {
3741 wtitle = g_strdup(_("gretl: VAR covariance matrix"));
3742 err = gretl_VAR_print_sigma(var, prn);
3743 } else {
3744 wtitle = g_strdup(_("gretl: system covariance matrix"));
3745 err = system_print_sigma(sys, prn);
3746 }
3747 } else if (code == SYS_DATA_RESIDS || code == SYS_DATA_FITTED) {
3748 const char *titles[] = {
3749 N_("System residuals"),
3750 N_("System fitted values")
3751 };
3752 const char *title;
3753 const char **heads = NULL;
3754
3755 if (var != NULL) {
3756 /* fitted values matrix not currently available */
3757 M = (code == SYS_DATA_RESIDS)? gretl_VAR_get_residual_matrix(var) :
3758 NULL;
3759 } else {
3760 M = (code == SYS_DATA_RESIDS)? sys->E : sys->yhat;
3761 }
3762
3763 if (M == NULL) {
3764 err = E_DATA;
3765 } else {
3766 k = gretl_matrix_cols(M);
3767 heads = malloc(k * sizeof *heads);
3768 if (heads == NULL) {
3769 err = E_ALLOC;
3770 }
3771 }
3772
3773 if (!err) {
3774 int i, v;
3775
3776 for (i=0; i<k && !err; i++) {
3777 v = (var != NULL)? gretl_VAR_get_variable_number(var, i) :
3778 sys->lists[i][1];
3779 if (v < 0 || v >= dataset->v) {
3780 err = E_DATA;
3781 } else {
3782 heads[i] = dataset->varname[v];
3783 }
3784 }
3785 }
3786
3787 if (!err) {
3788 title = (code == SYS_DATA_RESIDS)? titles[0] : titles[1];
3789 wtitle = g_strdup_printf("gretl: %s", _(title));
3790 gretl_matrix_print_with_col_heads(M, _(title), heads,
3791 dataset, prn);
3792 }
3793
3794 free(heads);
3795 }
3796
3797 if (err) {
3798 gui_errmsg(err);
3799 gretl_print_destroy(prn);
3800 } else {
3801 /* FIXME: add matrix as saveable data */
3802 view_buffer(prn, 80, 400, wtitle, PRINT, NULL);
3803 }
3804
3805 g_free(wtitle);
3806 }
3807
add_x12_output_menu_item(windata_t * vwin)3808 static void add_x12_output_menu_item (windata_t *vwin)
3809 {
3810 const gchar *mpath = "/menubar/Analysis";
3811 GtkActionEntry entry;
3812
3813 vwin_menu_add_separator(vwin, mpath);
3814
3815 action_entry_init(&entry);
3816 entry.name = "x12aout";
3817 entry.label = _("View X-12-ARIMA output");
3818 entry.callback = G_CALLBACK(x12_output_callback);
3819 vwin_menu_add_item(vwin, mpath, &entry);
3820 }
3821
3822 #include "up_down.h" /* arrows for buttons below */
3823
up_down_button(int up)3824 static GtkWidget *up_down_button (int up)
3825 {
3826 GtkWidget *img, *w = gtk_button_new();
3827 GdkPixbuf *pbuf;
3828
3829 if (up) {
3830 pbuf = gdk_pixbuf_new_from_inline(-1, up_pixbuf, FALSE, NULL);
3831 } else {
3832 pbuf = gdk_pixbuf_new_from_inline(-1, down_pixbuf, FALSE, NULL);
3833 }
3834
3835 img = gtk_image_new_from_pixbuf(pbuf);
3836 gtk_container_add(GTK_CONTAINER(w), img);
3837 g_object_unref(pbuf);
3838
3839 return w;
3840 }
3841
set_order_vec(GtkWidget * view)3842 static void set_order_vec (GtkWidget *view)
3843 {
3844 GtkTreeModel *model;
3845 GtkTreeIter iter;
3846 gretl_matrix *m;
3847 int v, i = 0;
3848
3849 m = g_object_get_data(G_OBJECT(view), "ordvec");
3850 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
3851
3852 gtk_tree_model_get_iter_first(model, &iter);
3853 gtk_tree_model_get(model, &iter, 1, &v, -1);
3854 m->val[0] = v;
3855
3856 while (gtk_tree_model_iter_next(model, &iter)) {
3857 gtk_tree_model_get(model, &iter, 1, &v, -1);
3858 m->val[++i] = v;
3859 }
3860 }
3861
sensitize_up_down(GtkTreeSelection * selection,GtkWidget * view)3862 static void sensitize_up_down (GtkTreeSelection *selection,
3863 GtkWidget *view)
3864 {
3865 gretl_matrix *v;
3866 GtkTreeModel *model;
3867 GtkTreeIter iter;
3868 GtkTreePath *path;
3869 GtkWidget *up, *down;
3870 gboolean s;
3871
3872 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
3873 v = g_object_get_data(G_OBJECT(view), "ordvec");
3874 up = g_object_get_data(G_OBJECT(view), "up-button");
3875 down = g_object_get_data(G_OBJECT(view), "down-button");
3876
3877 gtk_tree_model_get_iter_first(model, &iter);
3878 s = gtk_tree_selection_iter_is_selected(selection, &iter);
3879 gtk_widget_set_sensitive(up, !s);
3880
3881 path = gtk_tree_path_new_from_indices(gretl_vector_get_length(v) - 1,
3882 -1);
3883 s = gtk_tree_selection_path_is_selected(selection, path);
3884 gtk_widget_set_sensitive(down, !s);
3885 gtk_tree_path_free(path);
3886 }
3887
shift_var_up(GtkButton * b,GtkWidget * view)3888 static void shift_var_up (GtkButton *b, GtkWidget *view)
3889 {
3890 GtkTreeSelection *selection;
3891 GtkTreeModel *model;
3892 GtkTreeIter seliter, previter;
3893 GtkTreePath *path;
3894
3895 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
3896 gtk_tree_selection_get_selected(selection, &model, &seliter);
3897 path = gtk_tree_model_get_path(model, &seliter);
3898 if (gtk_tree_path_prev(path)) {
3899 gtk_tree_model_get_iter(model, &previter, path);
3900 gtk_list_store_swap(GTK_LIST_STORE(model), &seliter, &previter);
3901 set_order_vec(view);
3902 sensitize_up_down(selection, view);
3903 }
3904 gtk_tree_path_free(path);
3905 }
3906
shift_var_down(GtkButton * b,GtkWidget * view)3907 static void shift_var_down (GtkButton *b, GtkWidget *view)
3908 {
3909 GtkTreeSelection *selection;
3910 GtkTreeModel *model;
3911 GtkTreeIter seliter, nextiter;
3912
3913 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
3914 gtk_tree_selection_get_selected(selection, &model, &seliter);
3915 nextiter = seliter;
3916 if (gtk_tree_model_iter_next(model, &nextiter)) {
3917 gtk_list_store_swap(GTK_LIST_STORE(model), &seliter, &nextiter);
3918 set_order_vec(view);
3919 sensitize_up_down(selection, view);
3920 }
3921 }
3922
dialog_add_order_selector(GtkWidget * dlg,GRETL_VAR * var,gretl_matrix * ordvec)3923 static void dialog_add_order_selector (GtkWidget *dlg, GRETL_VAR *var,
3924 gretl_matrix *ordvec)
3925 {
3926 GtkWidget *b1, *b2;
3927 GtkWidget *vbox, *hbox;
3928 GtkWidget *bbox, *scroller;
3929 GtkTreeViewColumn *column;
3930 GtkCellRenderer *renderer;
3931 GtkTreeSelection *select;
3932 GtkListStore *store;
3933 GtkWidget *view, *lbl;
3934 GtkTreeIter iter;
3935 const char *vname;
3936 int i, j, v;
3937
3938 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3939
3940 hbox = gtk_hbox_new(FALSE, 5);
3941 lbl = gtk_label_new(_("Cholesky ordering:"));
3942 gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
3943 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3944
3945 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
3946 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
3947 g_object_set_data(G_OBJECT(view), "ordvec", ordvec);
3948
3949 renderer = gtk_cell_renderer_text_new();
3950 column = gtk_tree_view_column_new_with_attributes(NULL,
3951 renderer,
3952 "text", 0,
3953 NULL);
3954 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
3955
3956 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
3957 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(view), FALSE);
3958
3959 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3960
3961 for (i=0; i<var->neqns; i++) {
3962 j = gretl_vector_get(ordvec, i);
3963 v = var->ylist[j+1];
3964 vname = dataset->varname[v];
3965 gtk_list_store_append(store, &iter);
3966 gtk_list_store_set(store, &iter, 0, vname,
3967 1, j, -1);
3968 }
3969
3970 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
3971 gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
3972 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3973 gtk_tree_selection_select_iter(select, &iter);
3974
3975 gtk_widget_set_size_request(view, 140 * gui_scale, -1);
3976
3977 scroller = gtk_scrolled_window_new(NULL, NULL);
3978 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scroller),
3979 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3980 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scroller),
3981 GTK_SHADOW_IN);
3982 gtk_container_add(GTK_CONTAINER(scroller), view);
3983
3984 #if GTK_MAJOR_VERSION >= 3
3985 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(scroller),
3986 140 * gui_scale);
3987 #endif
3988
3989 bbox = gtk_vbox_new(FALSE, 5);
3990 b1 = up_down_button(1);
3991 b2 = up_down_button(0);
3992 gtk_box_pack_start(GTK_BOX(bbox), b1, FALSE, FALSE, 5);
3993 gtk_box_pack_start(GTK_BOX(bbox), b2, FALSE, FALSE, 5);
3994 g_signal_connect(G_OBJECT(b1), "clicked",
3995 G_CALLBACK(shift_var_up), view);
3996 g_signal_connect(G_OBJECT(b2), "clicked",
3997 G_CALLBACK(shift_var_down), view);
3998
3999 /* FIXME this is ignored in GTK3 ? */
4000 gtk_widget_set_sensitive(b1, FALSE);
4001 g_object_set_data(G_OBJECT(view), "up-button", b1);
4002 g_object_set_data(G_OBJECT(view), "down-button", b2);
4003 g_signal_connect(G_OBJECT(select), "changed",
4004 G_CALLBACK(sensitize_up_down), view);
4005
4006 hbox = gtk_hbox_new(FALSE, 5);
4007 gtk_box_pack_start(GTK_BOX(hbox), scroller, FALSE, FALSE, 5);
4008 gtk_box_pack_start(GTK_BOX(hbox), bbox, FALSE, FALSE, 5);
4009 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
4010
4011 g_object_unref(store);
4012 }
4013
4014 static int
impulse_response_setup(GRETL_VAR * var,gretl_matrix * ordvec,int * horizon,int * bootstrap,double * alpha,int * piters,gretlopt * gopt,GtkWidget * parent)4015 impulse_response_setup (GRETL_VAR *var, gretl_matrix *ordvec, int *horizon,
4016 int *bootstrap, double *alpha, int *piters,
4017 gretlopt *gopt, GtkWidget *parent)
4018 {
4019 gchar *title;
4020 int h = default_VAR_horizon(dataset);
4021 const char *impulse_opts[] = {
4022 N_("include bootstrap confidence interval")
4023 };
4024 static int active[] = {0};
4025 GtkWidget *dlg;
4026 double conf = 1 - *alpha;
4027 int iters = *piters;
4028 int resp = -1;
4029
4030 title = g_strdup_printf("gretl: %s", _("impulse responses"));
4031 dlg = build_checks_dialog(title, NULL,
4032 impulse_opts, 1, active, 0, 0, /* check */
4033 0, NULL, /* no radios */
4034 &h, _("forecast horizon (periods):"),
4035 2, dataset->n / 2, IRF_BOOT,
4036 parent, &resp);
4037 g_free(title);
4038
4039 if (dlg == NULL) {
4040 return -1;
4041 }
4042
4043 dialog_add_confidence_selector(dlg, &conf, gopt);
4044
4045 if (iters == 0) {
4046 iters = libset_get_int(BOOT_ITERS);
4047 }
4048 dialog_add_iters_spinner(dlg, &iters);
4049
4050 if (ordvec != NULL) {
4051 dialog_add_order_selector(dlg, var, ordvec);
4052 }
4053 gtk_widget_show_all(dlg);
4054
4055 if (resp < 0) {
4056 /* canceled */
4057 *horizon = 0;
4058 } else {
4059 *horizon = h;
4060 *bootstrap = (active[0] > 0);
4061 if (*bootstrap) {
4062 *alpha = 1 - conf;
4063 *piters = iters;
4064 }
4065 }
4066
4067 return resp;
4068 }
4069
FEVD_setup(GRETL_VAR * var,gretl_matrix * ordvec,int * horizon,gretlopt * opt,GtkWidget * parent)4070 static int FEVD_setup (GRETL_VAR *var, gretl_matrix *ordvec,
4071 int *horizon, gretlopt *opt,
4072 GtkWidget *parent)
4073 {
4074 const char *opts[] = {
4075 N_("stacked bar graph"),
4076 N_("line graph"),
4077 };
4078 gchar *title;
4079 int h = default_VAR_horizon(dataset);
4080 GtkWidget *dlg;
4081 int lines = 0;
4082 int resp = -1;
4083
4084 title = g_strdup_printf("gretl: %s", _("Forecast variance decomposition"));
4085
4086 dlg = build_checks_dialog(title, NULL, opts,
4087 0, NULL, 0, 0, /* no checks */
4088 2, &lines, /* two radio buttons */
4089 &h, _("forecast horizon (periods):"),
4090 2, dataset->n / 2, 0,
4091 parent, &resp);
4092
4093 g_free(title);
4094
4095 if (dlg == NULL) {
4096 return -1;
4097 }
4098
4099 if (ordvec != NULL) {
4100 dialog_add_order_selector(dlg, var, ordvec);
4101 }
4102
4103 gtk_widget_show_all(dlg);
4104
4105 if (resp < 0) {
4106 /* cancelled */
4107 *horizon = 0;
4108 } else {
4109 *horizon = h;
4110 if (!lines) {
4111 *opt = OPT_H;
4112 }
4113 }
4114
4115 return resp;
4116 }
4117
impulse_params_from_action(GtkAction * action,int * targ,int * shock)4118 static void impulse_params_from_action (GtkAction *action,
4119 int *targ,
4120 int *shock)
4121 {
4122 const gchar *s = gtk_action_get_name(action);
4123
4124 sscanf(s, "Imp:%d:%d", targ, shock);
4125 }
4126
FEVD_param_from_action(GtkAction * action,int * targ)4127 static void FEVD_param_from_action (GtkAction *action,
4128 int *targ)
4129 {
4130 const gchar *s = gtk_action_get_name(action);
4131
4132 sscanf(s, "FEVD:%d", targ);
4133 }
4134
ordvec_default(gretl_matrix * v)4135 static int ordvec_default (gretl_matrix *v)
4136 {
4137 int i, n = gretl_vector_get_length(v);
4138
4139 for (i=0; i<n; i++) {
4140 if (v->val[i] != i) {
4141 return 0;
4142 }
4143 }
4144
4145 return 1;
4146 }
4147
cholesky_order_vector(GRETL_VAR * var)4148 static gretl_matrix *cholesky_order_vector (GRETL_VAR *var)
4149 {
4150 gretl_matrix *v = NULL;
4151
4152 if (var->ord != NULL) {
4153 v = gretl_matrix_copy(var->ord);
4154 } else if (var->neqns > 1) {
4155 int i;
4156
4157 v = gretl_vector_alloc(var->neqns);
4158 if (v != NULL) {
4159 for (i=0; i<var->neqns; i++) {
4160 v->val[i] = i;
4161 }
4162 }
4163 }
4164
4165 return v;
4166 }
4167
FEVD_plot_call(GtkAction * action,gpointer p)4168 static void FEVD_plot_call (GtkAction *action, gpointer p)
4169 {
4170 windata_t *vwin = (windata_t *) p;
4171 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4172 int targ, horizon;
4173 gretl_matrix *ordvec = NULL;
4174 gretlopt opt = OPT_NONE;
4175 int resp, err;
4176
4177 FEVD_param_from_action(action, &targ);
4178 ordvec = cholesky_order_vector(var);
4179
4180 resp = FEVD_setup(var, ordvec, &horizon, &opt, vwin->main);
4181
4182 if (resp < 0) {
4183 /* canceled */
4184 gretl_matrix_free(ordvec);
4185 return;
4186 }
4187
4188 if (ordvec != NULL) {
4189 if (ordvec_default(ordvec)) {
4190 gretl_matrix_free(ordvec);
4191 gretl_VAR_set_ordering(var, NULL);
4192 } else {
4193 gretl_VAR_set_ordering(var, ordvec);
4194 }
4195 }
4196
4197 err = gretl_VAR_plot_FEVD(var, targ, horizon, dataset, opt);
4198 gui_graph_handler(err);
4199 }
4200
impulse_plot_call(GtkAction * action,gpointer p)4201 static void impulse_plot_call (GtkAction *action, gpointer p)
4202 {
4203 windata_t *vwin = (windata_t *) p;
4204 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4205 int horizon, bootstrap;
4206 gint shock, targ;
4207 static double alpha = 0.10;
4208 static gretlopt gopt = OPT_NONE;
4209 static int iters = 0;
4210 gretl_matrix *ordvec = NULL;
4211 double this_alpha = 0;
4212 int save_iters;
4213 int resp, err;
4214
4215 impulse_params_from_action(action, &targ, &shock);
4216 ordvec = cholesky_order_vector(var);
4217 save_iters = libset_get_int(BOOT_ITERS);
4218
4219 resp = impulse_response_setup(var, ordvec, &horizon, &bootstrap,
4220 &alpha, &iters, &gopt, vwin->main);
4221
4222 if (resp < 0) {
4223 /* canceled */
4224 gretl_matrix_free(ordvec);
4225 return;
4226 }
4227
4228 if (bootstrap) {
4229 this_alpha = alpha;
4230 }
4231
4232 if (ordvec != NULL) {
4233 if (ordvec_default(ordvec)) {
4234 gretl_matrix_free(ordvec);
4235 gretl_VAR_set_ordering(var, NULL);
4236 } else {
4237 gretl_VAR_set_ordering(var, ordvec);
4238 }
4239 }
4240
4241 if (iters != save_iters) {
4242 libset_set_int(BOOT_ITERS, iters);
4243 }
4244 err = gretl_VAR_plot_impulse_response(var, targ, shock,
4245 horizon, this_alpha,
4246 dataset, gopt);
4247 if (iters != save_iters) {
4248 libset_set_int(BOOT_ITERS, save_iters);
4249 }
4250
4251 gui_graph_handler(err);
4252 }
4253
multiple_irf_plot_call(GtkAction * action,gpointer p)4254 static void multiple_irf_plot_call (GtkAction *action, gpointer p)
4255 {
4256 windata_t *vwin = (windata_t *) p;
4257 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4258 int horizon, bootstrap;
4259 static double alpha = 0.10;
4260 static gretlopt gopt = OPT_NONE;
4261 static int iters = 0;
4262 gretl_matrix *ordvec = NULL;
4263 double this_alpha = 0;
4264 int save_iters;
4265 int resp, err;
4266
4267 ordvec = cholesky_order_vector(var);
4268 save_iters = libset_get_int(BOOT_ITERS);
4269
4270 resp = impulse_response_setup(var, ordvec, &horizon, &bootstrap,
4271 &alpha, &iters, &gopt, vwin->main);
4272
4273 if (resp < 0) {
4274 /* canceled */
4275 gretl_matrix_free(ordvec);
4276 return;
4277 }
4278
4279 if (bootstrap) {
4280 this_alpha = alpha;
4281 }
4282
4283 if (ordvec != NULL) {
4284 if (ordvec_default(ordvec)) {
4285 gretl_matrix_free(ordvec);
4286 gretl_VAR_set_ordering(var, NULL);
4287 } else {
4288 gretl_VAR_set_ordering(var, ordvec);
4289 }
4290 }
4291
4292 if (iters != save_iters) {
4293 libset_set_int(BOOT_ITERS, iters);
4294 }
4295 err = gretl_VAR_plot_multiple_irf(var, horizon, this_alpha,
4296 dataset, gopt);
4297 if (iters != save_iters) {
4298 libset_set_int(BOOT_ITERS, save_iters);
4299 }
4300
4301 gui_graph_handler(err);
4302 }
4303
VAR_model_data_code(GtkAction * action)4304 static int VAR_model_data_code (GtkAction *action)
4305 {
4306 const gchar *s = gtk_action_get_name(action);
4307
4308 if (!strcmp(s, "VarIrf")) {
4309 return VAR_IRF;
4310 } else if (!strcmp(s, "VarDecomp")) {
4311 return VAR_DECOMP;
4312 } else {
4313 return VAR_IRF;
4314 }
4315 }
4316
VAR_model_data_callback(GtkAction * action,gpointer p)4317 static void VAR_model_data_callback (GtkAction *action, gpointer p)
4318 {
4319 windata_t *vwin = (windata_t *) p;
4320 GRETL_VAR *var = vwin->data;
4321 gretl_matrix *ordvec;
4322 GtkWidget *dlg;
4323 gchar *title;
4324 PRN *prn = NULL;
4325 int code, h = 0;
4326 int resp = -1;
4327 int err;
4328
4329 if (var == NULL) {
4330 return;
4331 }
4332
4333 code = VAR_model_data_code(action);
4334 h = default_VAR_horizon(dataset);
4335 ordvec = cholesky_order_vector(var);
4336
4337 title = g_strdup_printf("gretl: %s",
4338 (code == VAR_IRF)? _("impulse responses") :
4339 _("variance decompositions"));
4340
4341 dlg = build_checks_dialog(title, NULL,
4342 NULL, 0, NULL, 0, 0, /* no check-buttons */
4343 0, NULL, /* no radios */
4344 &h, _("forecast horizon (periods):"),
4345 2, dataset->n / 2,
4346 0, vwin->main, &resp);
4347
4348 if (dlg == NULL) {
4349 goto bailout;
4350 }
4351
4352 if (ordvec != NULL) {
4353 dialog_add_order_selector(dlg, var, ordvec);
4354 }
4355
4356 /* blocks till response is selected */
4357 gtk_widget_show_all(dlg);
4358
4359 if (resp < 0 || bufopen(&prn)) {
4360 /* cancel or fail */
4361 goto bailout;
4362 }
4363
4364 if (ordvec != NULL) {
4365 if (ordvec_default(ordvec)) {
4366 gretl_matrix_free(ordvec);
4367 ordvec = NULL;
4368 }
4369 gretl_VAR_set_ordering(var, ordvec);
4370 ordvec = NULL;
4371 }
4372
4373 if (code == VAR_IRF) {
4374 err = gretl_VAR_print_all_impulse_responses(var, dataset, h, prn);
4375 } else if (code == VAR_DECOMP) {
4376 err = gretl_VAR_print_all_fcast_decomps(var, dataset, h, prn);
4377 } else {
4378 err = 1;
4379 }
4380
4381 if (err) {
4382 gui_errmsg(err);
4383 gretl_print_destroy(prn);
4384 } else {
4385 windata_t *viewer;
4386
4387 viewer = view_buffer_with_parent(vwin, prn, 80, 400, title,
4388 code, NULL);
4389 /* for use when printing in other formats */
4390 viewer->active_var = h;
4391 }
4392
4393 bailout:
4394
4395 g_free(title);
4396 gretl_matrix_free(ordvec);
4397 }
4398
system_forecast_callback(GtkAction * action,gpointer p)4399 static void system_forecast_callback (GtkAction *action, gpointer p)
4400 {
4401 static gretlopt gopt = OPT_P;
4402 windata_t *vwin = (windata_t *) p;
4403 int ci = vwin->role;
4404 GRETL_VAR *var = NULL;
4405 equation_system *sys = NULL;
4406 FITRESID *fr;
4407 int t1, t2, t2est, yno, resp;
4408 int premax, pre_n, dyn_ok;
4409 int static_model = 0;
4410 gretlopt opt = OPT_NONE;
4411 double conf = 0.95;
4412 int i, err = 0;
4413
4414 varnum_from_action(action, &i);
4415
4416 if (ci == VAR || ci == VECM) {
4417 var = (GRETL_VAR *) vwin->data;
4418 t2est = gretl_VAR_get_t2(var);
4419 yno = var->ylist[i+1];
4420 } else if (ci == SYSTEM) {
4421 sys = (equation_system *) vwin->data;
4422 t2est = sys->t2;
4423 yno = sys->ylist[i+1];
4424 static_model = (sys->order == 0);
4425 } else {
4426 return;
4427 }
4428
4429 t2 = dataset->n - 1;
4430
4431 /* if no out-of-sample obs are available, alert the user */
4432 if (t2 == t2est) {
4433 err = out_of_sample_info(1, &t2);
4434 if (err) {
4435 return;
4436 }
4437 t2 = dataset->n - 1;
4438 }
4439
4440 /* max number of pre-forecast obs in "best case" */
4441 premax = dataset->n - 1;
4442
4443 /* if there are spare obs available, default to an
4444 out-of-sample forecast */
4445 if (t2 > t2est) {
4446 t1 = t2est + 1;
4447 pre_n = t2est / 2;
4448 if (pre_n > 100) {
4449 pre_n = 100;
4450 }
4451 dyn_ok = !static_model;
4452 } else {
4453 if (var != NULL) {
4454 t1 = effective_order(var);
4455 } else {
4456 t1 = sys->order;
4457 }
4458 pre_n = 0;
4459 dyn_ok = 0;
4460 }
4461
4462 resp = forecast_dialog(t1, t1, &t1,
4463 t1, t2, &t2, NULL,
4464 0, premax, &pre_n,
4465 dyn_ok, &gopt, &conf,
4466 NULL, vwin->main);
4467 if (resp < 0) {
4468 return;
4469 }
4470
4471 if (resp == 1) {
4472 opt = OPT_D;
4473 } else if (resp == 2) {
4474 opt = OPT_S;
4475 }
4476
4477 fr = get_system_forecast(vwin->data, ci, i, t1, t2, pre_n,
4478 dataset, opt, &err);
4479
4480 if (err) {
4481 gui_errmsg(err);
4482 } else {
4483 char obs1[OBSLEN];
4484 char obs2[OBSLEN];
4485 PRN *prn;
4486
4487 ntolabel(obs1, t1, dataset);
4488 ntolabel(obs2, t2, dataset);
4489 lib_command_sprintf("fcast %s %s %s%s", obs1, obs2, dataset->varname[yno],
4490 print_flags(opt, FCAST));
4491 record_command_verbatim();
4492
4493 if (bufopen(&prn)) {
4494 return;
4495 }
4496
4497 fr->alpha = 1 - conf;
4498 err = text_print_forecast(fr, dataset, gopt, prn);
4499 gui_graph_handler(err);
4500
4501 view_buffer(prn, (fr->sderr == NULL)? 50 : 78, 400,
4502 _("gretl: forecasts"), FCAST, fr);
4503 }
4504 }
4505
4506 enum {
4507 SYS_AUTOCORR_TEST,
4508 SYS_ARCH_TEST,
4509 SYS_NORMALITY_TEST,
4510 SYS_RESTRICT
4511 };
4512
sys_test_code(GtkAction * action)4513 static int sys_test_code (GtkAction *action)
4514 {
4515 const gchar *s = gtk_action_get_name(action);
4516
4517 if (!strcmp(s, "autocorr")) {
4518 return SYS_AUTOCORR_TEST;
4519 } else if (!strcmp(s, "ARCH")) {
4520 return SYS_ARCH_TEST;
4521 } else if (!strcmp(s, "normtest")) {
4522 return SYS_NORMALITY_TEST;
4523 } else if (!strcmp(s, "restrict")) {
4524 return SYS_RESTRICT;
4525 } else {
4526 return SYS_NORMALITY_TEST;
4527 }
4528 }
4529
system_test_call(GtkAction * action,gpointer p)4530 static void system_test_call (GtkAction *action, gpointer p)
4531 {
4532 windata_t *vwin = (windata_t *) p;
4533 GRETL_VAR *var = NULL;
4534 equation_system *sys = NULL;
4535 gchar *title = NULL;
4536 gchar *cstr = NULL;
4537 PRN *prn;
4538 int code, order = 0;
4539 int err = 0;
4540
4541 if (bufopen(&prn)) {
4542 return;
4543 }
4544
4545 code = sys_test_code(action);
4546
4547 if (vwin->role == SYSTEM) {
4548 sys = (equation_system *) vwin->data;
4549 } else {
4550 var = (GRETL_VAR *) vwin->data;
4551 }
4552
4553 if (code == SYS_AUTOCORR_TEST || code == SYS_ARCH_TEST) {
4554 int resp;
4555
4556 order = default_lag_order(dataset);
4557 resp = spin_dialog((code == SYS_AUTOCORR_TEST)?
4558 _("gretl: autocorrelation") :
4559 _("gretl: ARCH test"), NULL,
4560 &order, _("Lag order for test:"),
4561 1, dataset->n / 2, 0, vwin->main);
4562 if (canceled(resp)) {
4563 gretl_print_destroy(prn);
4564 return;
4565 }
4566 }
4567
4568 if (code == SYS_AUTOCORR_TEST) {
4569 title = g_strdup(_("gretl: autocorrelation"));
4570 cstr = g_strdup_printf("modtest %d --autocorr", order);
4571 if (var != NULL) {
4572 err = gretl_VAR_autocorrelation_test(var, order,
4573 dataset,
4574 OPT_NONE,
4575 prn);
4576 } else {
4577 err = system_autocorrelation_test(sys, order, OPT_NONE, prn);
4578 }
4579 } else if (code == SYS_ARCH_TEST) {
4580 title = g_strdup(_("gretl: ARCH test"));
4581 cstr = g_strdup_printf("modtest %d --arch", order);
4582 if (var != NULL) {
4583 err = gretl_VAR_arch_test(var, order, dataset, OPT_NONE, prn);
4584 } else {
4585 err = system_arch_test(sys, order, OPT_NONE, prn);
4586 }
4587 } else if (code == SYS_NORMALITY_TEST) {
4588 title = g_strdup_printf("gretl: %s", _("Test for normality of residual"));
4589 cstr = g_strdup("modtest --normality");
4590 if (var != NULL) {
4591 err = gretl_VAR_normality_test(var, OPT_NONE, prn);
4592 } else {
4593 err = system_normality_test(sys, OPT_NONE, prn);
4594 }
4595 } else {
4596 err = 1;
4597 }
4598
4599 if (err) {
4600 gui_errmsg(err);
4601 gretl_print_destroy(prn);
4602 } else {
4603 add_command_to_stack(cstr, 0);
4604 view_buffer(prn, 78, 400, title, PRINT, NULL);
4605 }
4606
4607 g_free(title);
4608 g_free(cstr);
4609 }
4610
VAR_roots_plot_call(GtkAction * action,gpointer p)4611 static void VAR_roots_plot_call (GtkAction *action, gpointer p)
4612 {
4613 windata_t *vwin = (windata_t *) p;
4614 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4615 int err;
4616
4617 err = gretl_VAR_roots_plot(var);
4618 gui_graph_handler(err);
4619 }
4620
combined_EC_plot_call(GtkAction * action,gpointer p)4621 static void combined_EC_plot_call (GtkAction *action, gpointer p)
4622 {
4623 windata_t *vwin = (windata_t *) p;
4624 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4625 int err;
4626
4627 err = gretl_VECM_combined_EC_plot(var, dataset);
4628 gui_graph_handler(err);
4629 }
4630
sys_ci_from_action(GtkAction * action,int * eqn)4631 static int sys_ci_from_action (GtkAction *action, int *eqn)
4632 {
4633 const gchar *s = gtk_action_get_name(action);
4634 char cmdword[9];
4635
4636 if (eqn != NULL) {
4637 sscanf(s, "residplot_%d", eqn);
4638 }
4639 sscanf(s, "%*s %8s", cmdword);
4640 return gretl_command_number(cmdword);
4641 }
4642
system_resid_plot_call(GtkAction * action,gpointer p)4643 static void system_resid_plot_call (GtkAction *action, gpointer p)
4644 {
4645 windata_t *vwin = (windata_t *) p;
4646 int ci, eqn = 0;
4647 int err;
4648
4649 ci = sys_ci_from_action(action, &eqn);
4650 err = gretl_system_residual_plot(vwin->data, ci, eqn, dataset);
4651 gui_graph_handler(err);
4652 }
4653
system_resid_mplot_call(GtkAction * action,gpointer p)4654 static void system_resid_mplot_call (GtkAction *action, gpointer p)
4655 {
4656 windata_t *vwin = (windata_t *) p;
4657 int ci = sys_ci_from_action(action, NULL);
4658 int err;
4659
4660 err = gretl_system_residual_mplot(vwin->data, ci, dataset);
4661 gui_graph_handler(err);
4662 }
4663
VECM_matrix_name(int idx)4664 static const char *VECM_matrix_name (int idx)
4665 {
4666 if (idx == M_JALPHA) {
4667 return "alpha";
4668 } else if (idx == M_JBETA) {
4669 return "beta";
4670 } else if (idx == M_JVBETA) {
4671 return "var(beta)";
4672 } else {
4673 /* not registered! */
4674 return NULL;
4675 }
4676 }
4677
get_VECM_matrix_idx(GtkAction * action)4678 static int get_VECM_matrix_idx (GtkAction *action)
4679 {
4680 const gchar *aname = gtk_action_get_name(action);
4681 int idx;
4682
4683 sscanf(aname, "matrix %d", &idx);
4684 return idx;
4685 }
4686
VECM_add_matrix(GtkAction * action,gpointer p)4687 static void VECM_add_matrix (GtkAction *action, gpointer p)
4688 {
4689 windata_t *vwin = (windata_t *) p;
4690 GRETL_VAR *var = (GRETL_VAR *) vwin->data;
4691 gretl_matrix *m = NULL;
4692 char vname[VNAMELEN];
4693 const char *mname;
4694 gchar *blurb = NULL;
4695 int vecid = gretl_VECM_id(var);
4696 int idx, resp, show = 1;
4697 int err = 0;
4698
4699 idx = get_VECM_matrix_idx(action);
4700 mname = VECM_matrix_name(idx);
4701 if (mname == NULL) {
4702 /* internal error! */
4703 gui_errmsg(E_DATA);
4704 return;
4705 }
4706
4707 if (!strcmp(mname, "var(beta)")) {
4708 sprintf(vname, "jvbeta_%d", vecid);
4709 } else {
4710 sprintf(vname, "j%s_%d", mname, vecid);
4711 }
4712 blurb = g_strdup_printf("%s (%s) from VECM %d\n"
4713 "Name (max. %d characters):",
4714 mname, gretl_type_get_name(GRETL_TYPE_MATRIX),
4715 vecid, VNAMELEN - 1);
4716 resp = object_name_entry_dialog(vname, GRETL_TYPE_MATRIX, blurb,
4717 &show, vwin->main);
4718 g_free(blurb);
4719 if (resp < 0) {
4720 /* canceled */
4721 return;
4722 }
4723
4724 m = gretl_VAR_get_matrix(var, idx, &err);
4725 if (!err) {
4726 err = user_var_add_or_replace(vname, GRETL_TYPE_MATRIX, m);
4727 }
4728 if (err) {
4729 gui_errmsg(err);
4730 } else if (show) {
4731 view_session();
4732 }
4733 }
4734
add_system_menu_items(windata_t * vwin,int ci)4735 static void add_system_menu_items (windata_t *vwin, int ci)
4736 {
4737 GtkActionEntry item;
4738 const gchar *top = "/menubar";
4739 const gchar *tests = "/menubar/Tests";
4740 const gchar *save = "/menubar/Save";
4741 const gchar *graphs = "/menubar/Graphs";
4742 const gchar *analysis = "/menubar/Analysis";
4743 GRETL_VAR *var = NULL;
4744 equation_system *sys = NULL;
4745 int neqns, nfc, vtarg, vshock;
4746 char tmp[VNAMELEN2], istr[VNAMELEN];
4747 char maj[128], min[64];
4748 const char *cmdword;
4749 int i, j;
4750
4751 if (ci == SYSTEM) {
4752 sys = (equation_system *) vwin->data;
4753 neqns = sys->neqns;
4754 nfc = sys->neqns + sys->nidents;
4755 } else {
4756 var = (GRETL_VAR *) vwin->data;
4757 nfc = neqns = gretl_VAR_get_n_equations(var);
4758 }
4759
4760 cmdword = gretl_command_word(ci);
4761 action_entry_init(&item);
4762
4763 /* FIXME: the following two tests should really be multivariate */
4764
4765 if (dataset_is_time_series(dataset)) {
4766 /* univariate autocorrelation tests */
4767 item.name = "autocorr";
4768 item.label = N_("_Autocorrelation");
4769 item.callback = G_CALLBACK(system_test_call);
4770 vwin_menu_add_item(vwin, tests, &item);
4771
4772 /* univariate ARCH tests */
4773 item.name = "ARCH";
4774 item.label = N_("A_RCH");
4775 vwin_menu_add_item(vwin, tests, &item);
4776 }
4777
4778 /* multivariate normality test */
4779 item.name = "normtest";
4780 item.label = N_("_Normality of residuals");
4781 item.callback = G_CALLBACK(system_test_call);
4782 vwin_menu_add_item(vwin, tests, &item);
4783
4784 if (ci == VECM || ci == SYSTEM) {
4785 /* linear restrictions */
4786 item.name = "restrict";
4787 item.label = N_("Linear restrictions");
4788 item.callback = G_CALLBACK(gretl_callback);
4789 vwin_menu_add_item(vwin, tests, &item);
4790 } else if (ci == VAR) {
4791 /* regular VAR: omit exogenous variables test */
4792 if (gretl_VAR_get_exo_list(var) != NULL) {
4793 item.name = "VarOmit";
4794 item.label = N_("Omit exogenous variables...");
4795 item.callback = G_CALLBACK(selector_callback);
4796 vwin_menu_add_item(vwin, tests, &item);
4797 }
4798 if (var->detflags & DET_TREND) {
4799 item.name = "VarOmitTrend";
4800 item.label = N_("Omit time trend");
4801 item.callback = G_CALLBACK(VAR_omit_auto);
4802 vwin_menu_add_item(vwin, tests, &item);
4803 }
4804 if (var->detflags & DET_SEAS) {
4805 item.name = "VarOmitSeas";
4806 item.label = N_("Omit seasonal dummies");
4807 item.callback = G_CALLBACK(VAR_omit_auto);
4808 vwin_menu_add_item(vwin, tests, &item);
4809 }
4810 }
4811
4812 /* Save residuals */
4813 for (i=0; i<neqns; i++) {
4814 sprintf(istr, "resid %d", i);
4815 sprintf(maj, "%s %d", _("Residuals from equation"), i + 1);
4816 item.name = istr;
4817 item.label = maj;
4818 item.callback = G_CALLBACK(add_system_resid);
4819 vwin_menu_add_item(vwin, save, &item);
4820 }
4821
4822 /* Display residual matrix */
4823 item.name = "uhat";
4824 item.label = N_("Display residuals, all equations");
4825 item.callback = G_CALLBACK(system_data_callback);
4826 vwin_menu_add_item(vwin, analysis, &item);
4827
4828 if (ci == SYSTEM) {
4829 /* Display fitted values matrix */
4830 item.name = "yhat";
4831 item.label = N_("Display fitted values, all equations");
4832 vwin_menu_add_item(vwin, analysis, &item);
4833 }
4834
4835 if (neqns > 1) {
4836 /* Display VCV matrix */
4837 item.name = "sigma";
4838 item.label = N_("Cross-equation covariance matrix");
4839 vwin_menu_add_item(vwin, analysis, &item);
4840 }
4841
4842 if (ci == VAR || ci == VECM) {
4843 /* impulse response printout */
4844 item.name = "VarIrf";
4845 item.label = N_("Impulse responses");
4846 item.callback = G_CALLBACK(VAR_model_data_callback);
4847 vwin_menu_add_item(vwin, analysis, &item);
4848
4849 /* variance decomp printout */
4850 item.name = "VarDecomp";
4851 item.label = N_("Forecast variance decomposition");
4852 vwin_menu_add_item(vwin, analysis, &item);
4853 }
4854
4855 /* Residual plots */
4856
4857 action_entry_init(&item);
4858 item.name = "ResidsMenu";
4859 item.label = _("Residuals");
4860 vwin_menu_add_menu(vwin, graphs, &item);
4861
4862 if (neqns > 1) {
4863 /* combined residual plot */
4864 sprintf(min, "comboresid %s", cmdword);
4865 item.name = min;
4866 item.label = N_("Combined plot");
4867 item.callback = G_CALLBACK(system_resid_plot_call);
4868 vwin_menu_add_item(vwin, "/menubar/Graphs/ResidsMenu", &item);
4869 }
4870
4871 if (neqns > 1 && neqns <= 6) {
4872 /* multiple residual plots in one frame */
4873 sprintf(min, "multiresid %s", cmdword);
4874 item.name = min;
4875 item.label = N_("Multiple plots");
4876 item.callback = G_CALLBACK(system_resid_mplot_call);
4877 vwin_menu_add_item(vwin, "/menubar/Graphs/ResidsMenu", &item);
4878 }
4879
4880 item.callback = G_CALLBACK(system_resid_plot_call);
4881
4882 for (i=0; i<neqns; i++) {
4883 sprintf(min, "residplot_%d %s", i+1, cmdword);
4884 sprintf(maj, N_("Equation %d"), i+1);
4885 item.name = min;
4886 item.label = maj;
4887 vwin_menu_add_item(vwin, "/menubar/Graphs/ResidsMenu", &item);
4888 }
4889
4890 /* end residual plots */
4891
4892 if (ci == VECM) {
4893 int r = gretl_VECM_rank(var);
4894
4895 if (r == 1) {
4896 item.name = "ecplot";
4897 item.label = N_("EC plot");
4898 item.callback = G_CALLBACK(combined_EC_plot_call);
4899 vwin_menu_add_item(vwin, graphs, &item);
4900 } else {
4901 item.name = "ecplot";
4902 item.label = N_("Combined EC plot");
4903 item.callback = G_CALLBACK(combined_EC_plot_call);
4904 vwin_menu_add_item(vwin, graphs, &item);
4905 }
4906 }
4907
4908 if (ci != SYSTEM) {
4909 /* VAR inverse roots */
4910 item.name = "VarRoots";
4911 item.label = N_("VAR inverse roots");
4912 item.callback = G_CALLBACK(VAR_roots_plot_call);
4913 vwin_menu_add_item(vwin, graphs, &item);
4914 }
4915
4916 if (ci != SYSTEM && neqns > 1 && neqns <= 4) {
4917 /* Multiple IRFs */
4918 item.name = "MultiIrf";
4919 item.label = N_("Impulse responses (combined)");
4920 item.callback = G_CALLBACK(multiple_irf_plot_call);
4921 vwin_menu_add_item(vwin, graphs, &item);
4922 }
4923
4924 for (i=0; i<nfc; i++) {
4925 char newpath[64];
4926 int dv;
4927
4928 /* forecast items */
4929 if (var != NULL) {
4930 dv = gretl_VAR_get_variable_number(var, i);
4931 } else {
4932 dv = sys->ylist[i+1];
4933 }
4934 double_underscores(tmp, dataset->varname[dv]);
4935 sprintf(istr, "fcast %d", i);
4936 item.name = istr;
4937 item.label = tmp;
4938 item.callback = G_CALLBACK(system_forecast_callback);
4939 vwin_menu_add_item(vwin, "/menubar/Analysis/Forecasts", &item);
4940
4941 if (var == NULL) {
4942 continue;
4943 }
4944
4945 /* impulse response plots: make menu for target */
4946 vtarg = gretl_VAR_get_variable_number(var, i);
4947 double_underscores(tmp, dataset->varname[vtarg]);
4948 sprintf(istr, "targ_%d", i);
4949 sprintf(maj, _("Response of %s"), tmp);
4950 item.name = istr;
4951 item.label = maj;
4952 item.callback = NULL;
4953 vwin_menu_add_menu(vwin, graphs, &item);
4954
4955 /* path under which to add shocks */
4956 sprintf(newpath, "/menubar/Graphs/targ_%d", i);
4957
4958 for (j=0; j<neqns; j++) {
4959 /* impulse responses: subitems for shocks */
4960 vshock = gretl_VAR_get_variable_number(var, j);
4961 double_underscores(tmp, dataset->varname[vshock]);
4962 sprintf(istr, "Imp:%d:%d", i, j);
4963 sprintf(min, _("to %s"), tmp);
4964 item.name = istr;
4965 item.label = min;
4966 item.callback = G_CALLBACK(impulse_plot_call);
4967 vwin_menu_add_item(vwin, newpath, &item);
4968 }
4969 }
4970
4971 if (var != NULL) {
4972 item.name = "FEVD";
4973 item.label = _("Forecast variance decomposition");
4974 item.callback = NULL;
4975 vwin_menu_add_menu(vwin, graphs, &item);
4976 for (j=0; j<neqns; j++) {
4977 /* FEVD graphs per equation */
4978 vtarg = gretl_VAR_get_variable_number(var, j);
4979 double_underscores(tmp, dataset->varname[vtarg]);
4980 sprintf(istr, "FEVD:%d", j);
4981 item.name = istr;
4982 item.label = tmp;
4983 item.callback = G_CALLBACK(FEVD_plot_call);
4984 vwin_menu_add_item(vwin, "/menubar/Graphs/FEVD", &item);
4985 }
4986 }
4987
4988 if (ci == VECM) {
4989 /* saving things specific to VECMs */
4990 int mtypes[] = {M_JALPHA, M_JBETA, M_JVBETA};
4991
4992 /* save error correction terms as series */
4993 for (i=0; i<jrank(var); i++) {
4994 sprintf(istr, "EC %d", i);
4995 sprintf(maj, "%s %d", _("EC term"), i+1);
4996 item.name = istr;
4997 item.label = maj;
4998 item.callback = G_CALLBACK(VECM_add_EC_data);
4999 vwin_menu_add_item(vwin, save, &item);
5000 }
5001 /* save relevant matrices */
5002 for (i=0; i<G_N_ELEMENTS(mtypes); i++) {
5003 sprintf(istr, "matrix %d", mtypes[i]);
5004 item.name = istr;
5005 item.label = VECM_matrix_name(mtypes[i]);
5006 item.callback = G_CALLBACK(VECM_add_matrix);
5007 vwin_menu_add_item(vwin, save, &item);
5008 }
5009 }
5010
5011 maybe_add_packages_to_model_menus(vwin);
5012
5013 if (latex_is_ok()) {
5014 int n = G_N_ELEMENTS(sys_tex_items);
5015
5016 vwin_menu_add_menu(vwin, top, &sys_tex_items[0]);
5017 vwin_menu_add_items(vwin, "/menubar/LaTeX",
5018 sys_tex_items + 1, n - 1);
5019 }
5020 }
5021
vector_suitable_for_series(const gretl_matrix * m)5022 static int vector_suitable_for_series (const gretl_matrix *m)
5023 {
5024 if (m->cols == 1 && gretl_matrix_is_dated(m)) {
5025 int t2 = gretl_matrix_get_t2(m);
5026
5027 /* the column vector can be "cast" to series
5028 without data loss */
5029 return t2 < dataset->n;
5030 } else {
5031 return 0;
5032 }
5033 }
5034
save_bundled_item_call(GtkAction * action,gpointer p)5035 static void save_bundled_item_call (GtkAction *action, gpointer p)
5036 {
5037 windata_t *vwin = (windata_t *) p;
5038 gretl_bundle *bundle = vwin->data;
5039 const gchar *key = gtk_action_get_name(action);
5040 const char *note;
5041 GretlType type;
5042 void *val;
5043 int size = 0;
5044 int err = 0;
5045
5046 val = gretl_bundle_get_data(bundle, key, &type, &size, &err);
5047 if (err) {
5048 gui_errmsg(err);
5049 return;
5050 }
5051
5052 note = gretl_bundle_get_note(bundle, key);
5053
5054 if (type == GRETL_TYPE_SERIES && size <= dataset->n) {
5055 const double *x = (double *) val;
5056
5057 save_bundled_series(x, 0, size - 1, key, note, vwin);
5058 } else if (type == GRETL_TYPE_MATRIX &&
5059 vector_suitable_for_series((gretl_matrix *) val)) {
5060 const gretl_matrix *m = val;
5061 int t1 = gretl_matrix_get_t1(m);
5062 int t2 = gretl_matrix_get_t2(m);
5063
5064 save_bundled_series(m->val, t1, t2, key, note, vwin);
5065 } else {
5066 char vname[VNAMELEN];
5067 gchar *blurb;
5068 int resp, show = 1;
5069
5070 *vname = '\0';
5071 strncat(vname, key, VNAMELEN - 1);
5072
5073 blurb = g_strdup_printf("%s (%s) from bundle\n"
5074 "Name (max. %d characters):",
5075 key, gretl_type_get_name(type),
5076 VNAMELEN - 1);
5077 resp = object_name_entry_dialog(vname, type, blurb,
5078 &show, vwin->main);
5079 g_free(blurb);
5080
5081 if (resp < 0) {
5082 /* canceled */
5083 return;
5084 }
5085
5086 if (gretl_is_scalar_type(type)) {
5087 double *xp = malloc(sizeof *xp);
5088
5089 if (type == GRETL_TYPE_INT || type == GRETL_TYPE_BOOL) {
5090 *xp = *(int *) val;
5091 } else if (type == GRETL_TYPE_UNSIGNED) {
5092 *xp = *(unsigned *) val;
5093 } else {
5094 *xp = *(double *) val;
5095 }
5096 err = user_var_add_or_replace(vname, GRETL_TYPE_DOUBLE, xp);
5097 } else if (type == GRETL_TYPE_MATRIX) {
5098 gretl_matrix *orig = (gretl_matrix *) val;
5099 gretl_matrix *m = gretl_matrix_copy(orig);
5100
5101 if (m == NULL) {
5102 err = E_ALLOC;
5103 } else {
5104 err = user_var_add_or_replace(vname, GRETL_TYPE_MATRIX, m);
5105 }
5106 } else if (type == GRETL_TYPE_SERIES) {
5107 double *x = (double *) val;
5108 gretl_matrix *m;
5109
5110 m = gretl_vector_from_array(x, size, GRETL_MOD_NONE);
5111 err = user_var_add_or_replace(vname, GRETL_TYPE_MATRIX, m);
5112 } else if (type == GRETL_TYPE_STRING) {
5113 char *s = gretl_strdup((char *) val);
5114
5115 err = user_var_add_or_replace(vname, GRETL_TYPE_STRING, s);
5116 } else if (type == GRETL_TYPE_BUNDLE) {
5117 gretl_bundle *orig = (gretl_bundle *) val;
5118 gretl_bundle *b = gretl_bundle_copy(orig, &err);
5119
5120 if (!err) {
5121 err = user_var_add_or_replace(vname, GRETL_TYPE_BUNDLE, b);
5122 }
5123 } else if (type == GRETL_TYPE_ARRAY) {
5124 gretl_array *orig = (gretl_array *) val;
5125 gretl_array *a = gretl_array_copy(orig, &err);
5126
5127 if (!err) {
5128 err = user_var_add_or_replace(vname, gretl_array_get_type(a), a);
5129 }
5130 }
5131
5132 if (show && !err) {
5133 if (gretl_is_scalar_type(type)) {
5134 edit_scalars();
5135 } else {
5136 view_session();
5137 }
5138 }
5139 }
5140
5141 if (err) {
5142 gui_errmsg(err);
5143 }
5144 }
5145
bundle_plot_call(GtkAction * action,gpointer p)5146 static void bundle_plot_call (GtkAction *action, gpointer p)
5147 {
5148 windata_t *vwin = (windata_t *) p;
5149 gretl_bundle *bundle = vwin->data;
5150 const gchar *aname = gtk_action_get_name(action);
5151
5152 exec_bundle_special_function(bundle, BUNDLE_PLOT,
5153 aname, vwin->main);
5154 }
5155
add_blist_item_to_menu(gpointer listitem,gpointer p)5156 static void add_blist_item_to_menu (gpointer listitem,
5157 gpointer p)
5158 {
5159 bundled_item *bi = listitem;
5160 gpointer data;
5161 const char *key;
5162 GtkAction *action;
5163 GtkWidget *item;
5164 GtkWidget *menu = p;
5165 gchar *keystr, *label = NULL;
5166 const char *typestr = "?";
5167 const char *note;
5168 GretlType type;
5169 int scalar = 0;
5170 int r = 0, c = 0;
5171 int size = 0;
5172
5173 key = bundled_item_get_key(bi);
5174 data = bundled_item_get_data(bi, &type, &size);
5175
5176 if (data == NULL || type == GRETL_TYPE_STRING) {
5177 return;
5178 }
5179
5180 if (type == GRETL_TYPE_MATRIX) {
5181 gretl_matrix *m = data;
5182
5183 if (gretl_is_null_matrix(m)) {
5184 return;
5185 } else if (vector_suitable_for_series(m)) {
5186 type = GRETL_TYPE_SERIES;
5187 } else {
5188 r = m->rows;
5189 c = m->cols;
5190 }
5191 } else if (type == GRETL_TYPE_SERIES && size > dataset->n) {
5192 type = GRETL_TYPE_MATRIX;
5193 r = size;
5194 c = 1;
5195 } else if (gretl_is_scalar_type(type)) {
5196 scalar = 1;
5197 }
5198
5199 typestr = gretl_type_get_name(type);
5200 note = bundled_item_get_note(bi);
5201 keystr = double_underscores_new((gchar *) key);
5202
5203 if (r > 0 && c > 0) {
5204 if (note != NULL) {
5205 label = g_strdup_printf("%s (%s: %s, %d x %d)", keystr,
5206 typestr, note, r, c);
5207 } else {
5208 label = g_strdup_printf("%s (%s, %d x %d)", keystr,
5209 typestr, r, c);
5210 }
5211 } else if (scalar) {
5212 if (type == GRETL_TYPE_DOUBLE) {
5213 label = g_strdup_printf("%s (scalar: %g)", keystr,
5214 *(double *) data);
5215 } else if (type == GRETL_TYPE_INT || type == GRETL_TYPE_BOOL) {
5216 label = g_strdup_printf("%s (scalar: %d)", keystr,
5217 *(int *) data);
5218 } else if (type == GRETL_TYPE_UNSIGNED) {
5219 label = g_strdup_printf("%s (scalar: %d)", keystr,
5220 *(unsigned int *) data);
5221 }
5222 } else if (note != NULL) {
5223 label = g_strdup_printf("%s (%s: %s)", keystr, typestr, note);
5224 } else {
5225 label = g_strdup_printf("%s (%s)", keystr, typestr);
5226 }
5227
5228 g_free(keystr);
5229
5230 action = gtk_action_new(key, label, NULL, NULL);
5231 g_signal_connect(G_OBJECT(action), "activate",
5232 G_CALLBACK(save_bundled_item_call),
5233 g_object_get_data(G_OBJECT(menu), "vwin"));
5234
5235 item = gtk_action_create_menu_item(action);
5236 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5237
5238 g_free(label);
5239 }
5240
add_kalman_items_to_menu(GtkWidget * menu,kalman * K)5241 static void add_kalman_items_to_menu (GtkWidget *menu,
5242 kalman *K)
5243 {
5244 GtkAction *action;
5245 GtkWidget *item;
5246 gchar *label;
5247 char **S;
5248 int i, ns = 0;
5249
5250 S = kalman_bundle_get_matrix_names(K, &ns);
5251
5252 for (i=0; i<ns; i++) {
5253 label = g_strdup_printf("%s (matrix)", S[i]);
5254 action = gtk_action_new(S[i], label, NULL, NULL);
5255 g_signal_connect(G_OBJECT(action), "activate",
5256 G_CALLBACK(save_bundled_item_call),
5257 g_object_get_data(G_OBJECT(menu), "vwin"));
5258 item = gtk_action_create_menu_item(action);
5259 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5260 g_free(label);
5261 }
5262
5263 strings_array_free(S, ns);
5264 ns = 0;
5265
5266 S = kalman_bundle_get_scalar_names(K, &ns);
5267
5268 for (i=0; i<ns; i++) {
5269 label = g_strdup_printf("%s (scalar)", S[i]);
5270 action = gtk_action_new(S[i], label, NULL, NULL);
5271 g_signal_connect(G_OBJECT(action), "activate",
5272 G_CALLBACK(save_bundled_item_call),
5273 g_object_get_data(G_OBJECT(menu), "vwin"));
5274 item = gtk_action_create_menu_item(action);
5275 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5276 g_free(label);
5277 }
5278
5279 strings_array_free(S, ns);
5280 }
5281
check_for_saveable(gpointer key,gpointer value,gpointer data)5282 static void check_for_saveable (gpointer key,
5283 gpointer value,
5284 gpointer data)
5285 {
5286 int *pn = (int *) data;
5287 GretlType type;
5288 void *val;
5289
5290 val = bundled_item_get_data((bundled_item *) value, &type, NULL);
5291 if (val == NULL) {
5292 /* "can't happen" */
5293 return;
5294 }
5295 if (type == GRETL_TYPE_STRING) {
5296 /* not useful in GUI? */
5297 return;
5298 }
5299 if (type == GRETL_TYPE_MATRIX) {
5300 gretl_matrix *m = val;
5301
5302 if (gretl_is_null_matrix(m)) {
5303 /* no use to man nor beast? */
5304 return;
5305 }
5306 }
5307
5308 *pn += 1;
5309 }
5310
any_saveable_content(gretl_bundle * b)5311 static int any_saveable_content (gretl_bundle *b)
5312 {
5313 int n = gretl_bundle_get_n_keys(b);
5314
5315 if (n > 0) {
5316 GHashTable *ht = (GHashTable *) gretl_bundle_get_content(b);
5317
5318 n = 0;
5319 g_hash_table_foreach(ht, check_for_saveable, &n);
5320 }
5321
5322 return n;
5323 }
5324
make_bundle_content_menu(windata_t * vwin)5325 GtkWidget *make_bundle_content_menu (windata_t *vwin)
5326 {
5327 gretl_bundle *bundle = vwin->data;
5328 GtkWidget *menu = NULL;
5329
5330 if (gretl_bundle_get_type(bundle) == BUNDLE_KALMAN) {
5331 kalman *K = gretl_bundle_get_private_data(bundle);
5332
5333 if (K != NULL) {
5334 menu = gtk_menu_new();
5335 g_object_set_data(G_OBJECT(menu), "vwin", vwin);
5336 add_kalman_items_to_menu(menu, K);
5337 }
5338 }
5339
5340 if (any_saveable_content(bundle)) {
5341 GList *blist = gretl_bundle_get_sorted_items(bundle);
5342
5343 if (menu == NULL) {
5344 menu = gtk_menu_new();
5345 g_object_set_data(G_OBJECT(menu), "vwin", vwin);
5346 }
5347 g_list_foreach(blist, add_blist_item_to_menu, menu);
5348 g_list_free(blist);
5349 }
5350
5351 return menu;
5352 }
5353
make_bundle_plot_menu(windata_t * vwin)5354 GtkWidget *make_bundle_plot_menu (windata_t *vwin)
5355 {
5356 gretl_bundle *bundle = vwin->data;
5357 gchar *plotfunc;
5358 GtkWidget *menu = NULL;
5359
5360 plotfunc = get_bundle_special_function(bundle, BUNDLE_PLOT);
5361
5362 if (plotfunc != NULL) {
5363 ufunc *fun = NULL;
5364 const char **S = NULL;
5365 int ng = 0;
5366
5367 if (strcmp(plotfunc, "builtin")) {
5368 fun = get_user_function_by_name(plotfunc);
5369 }
5370
5371 if (fun != NULL) {
5372 S = fn_param_value_labels(fun, 1, &ng);
5373 }
5374
5375 if (S != NULL) {
5376 /* the plotfunc has some options available */
5377 GtkAction *action;
5378 GtkWidget *item;
5379 gchar *aname;
5380 int i;
5381
5382 menu = gtk_menu_new();
5383
5384 for (i=0; i<ng; i++) {
5385 aname = g_strdup_printf("%s:%d", plotfunc, i);
5386 action = gtk_action_new(aname, S[i], NULL, NULL);
5387 g_signal_connect(G_OBJECT(action), "activate",
5388 G_CALLBACK(bundle_plot_call),
5389 vwin);
5390 item = gtk_action_create_menu_item(action);
5391 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5392 g_free(aname);
5393 }
5394 }
5395 g_free(plotfunc);
5396 }
5397
5398 return menu;
5399 }
5400
make_bundle_save_menu(windata_t * vwin)5401 GtkWidget *make_bundle_save_menu (windata_t *vwin)
5402 {
5403 gretl_bundle *bundle = vwin->data;
5404 GtkWidget *menu = gtk_menu_new();
5405 GtkAction *action;
5406 GtkWidget *item;
5407
5408 action = gtk_action_new("SaveAs", _("_Save text..."),
5409 NULL, NULL);
5410 g_signal_connect(G_OBJECT(action), "activate",
5411 G_CALLBACK(model_output_save), vwin);
5412 item = gtk_action_create_menu_item(action);
5413 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5414
5415 action = gtk_action_new("SaveAsIcon", _("Save bundle to session as _icon"),
5416 NULL, NULL);
5417 g_signal_connect(G_OBJECT(action), "activate",
5418 G_CALLBACK(bundle_add_as_icon), vwin);
5419 item = gtk_action_create_menu_item(action);
5420 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5421 vwin_record_action(vwin, action);
5422
5423 if (get_user_var_by_data(bundle)) {
5424 gtk_action_set_sensitive(action, FALSE);
5425 }
5426
5427 return menu;
5428 }
5429
set_sample_from_model(void * ptr,int role)5430 static int set_sample_from_model (void *ptr, int role)
5431 {
5432 MODEL *pmod = NULL;
5433 int range_set = 0;
5434 int err = 0;
5435
5436 if (role == VIEW_MODEL) {
5437 /* called from single-eqn model window */
5438 pmod = ptr;
5439 }
5440
5441 /* first restore the full dataset */
5442 err = restore_full_sample(dataset, NULL);
5443
5444 /* then, if the model was subsampled, restore the subsample */
5445 if (!err) {
5446 if (pmod != NULL && pmod->submask != NULL) {
5447 err = restrict_sample_from_mask(pmod->submask, dataset,
5448 OPT_NONE);
5449 range_set = 1;
5450 } else {
5451 /* VAR, VECM or something */
5452 int t1 = 0, t2 = 0;
5453
5454 model_get_t1_t2(ptr, role, &t1, &t2);
5455 if (t1 == 0 && t2 == 0) {
5456 err = E_DATA;
5457 } else if (t1 != dataset->t1 || t2 != dataset->t2) {
5458 dataset->t1 = t1;
5459 dataset->t2 = t2;
5460 range_set = 1;
5461 }
5462 }
5463 }
5464
5465 if (err) {
5466 gui_errmsg(err);
5467 } else {
5468 if (range_set) {
5469 char comment[64];
5470
5471 restore_sample_state(TRUE);
5472 if (pmod != NULL) {
5473 sprintf(comment, "# restored sample from model %d\n", pmod->ID);
5474 } else {
5475 strcpy(comment, "# restored sample from model\n");
5476 }
5477 add_command_to_stack(comment, 0);
5478 } else {
5479 restore_sample_state(FALSE);
5480 lib_command_strcpy("smpl --full");
5481 record_command_verbatim();
5482 }
5483
5484 mark_session_changed();
5485 set_sample_label(dataset);
5486 }
5487
5488 return err;
5489 }
5490
5491 /* maybe_set_sample_from_model: return TRUE if the problem situation
5492 (sample mismatch) is successfully handled, else FALSE.
5493 */
5494
maybe_set_sample_from_model(windata_t * vwin)5495 static gboolean maybe_set_sample_from_model (windata_t *vwin)
5496 {
5497 const char *msg = N_("The model sample differs from the dataset sample,\n"
5498 "so some menu options will be disabled.\n\n"
5499 "Do you want to restore the sample on which\n"
5500 "this model was estimated?");
5501 int resp, err = 0;
5502
5503 resp = yes_no_dialog(NULL, _(msg), vwin_toplevel(vwin));
5504
5505 if (resp == GRETL_NO) {
5506 return FALSE;
5507 }
5508
5509 err = set_sample_from_model(vwin->data, vwin->role);
5510
5511 return (err == 0);
5512 }
5513
check_model_menu(GtkWidget * w,GdkEventButton * eb,gpointer data)5514 static gint check_model_menu (GtkWidget *w, GdkEventButton *eb,
5515 gpointer data)
5516 {
5517 windata_t *vwin = (windata_t *) data;
5518 MODEL *pmod = vwin->data;
5519 GtkAction *action;
5520 int resampled = 0;
5521 int between = 0;
5522 gboolean s, ok = TRUE;
5523
5524 if (RQ_SPECIAL_MODEL(pmod)) {
5525 return FALSE;
5526 }
5527
5528 if (dataset == NULL || dataset->Z == NULL) {
5529 flip(vwin->ui, "/menubar/File/SaveAsIcon", FALSE);
5530 flip(vwin->ui, "/menubar/File/SaveAndClose", FALSE);
5531 flip(vwin->ui, "/menubar/Edit/Copy", FALSE);
5532 flip(vwin->ui, "/menubar/Tests", FALSE);
5533 flip(vwin->ui, "/menubar/Graphs", FALSE);
5534 flip(vwin->ui, "/menubar/Analysis", FALSE);
5535 return FALSE;
5536 }
5537
5538 if (pmod->ci == MLE || pmod->ci == GMM ||
5539 pmod->ci == MPOLS || pmod->ci == BIPROBIT) {
5540 return FALSE;
5541 }
5542
5543 if (model_sample_problem(pmod, dataset)) {
5544 resampled = (pmod->submask == RESAMPLED);
5545 between = gretl_is_between_model(pmod);
5546 ok = FALSE;
5547 }
5548
5549 /* check current menu state */
5550 action = gtk_ui_manager_get_action(vwin->ui, "/menubar/Save/uhat");
5551 s = gtk_action_is_sensitive(action);
5552
5553 if (s == ok) {
5554 /* no need to flip state */
5555 return FALSE;
5556 }
5557
5558 if (s && !ok) {
5559 if (resampled) {
5560 infobox(_("The model sample differs from the dataset sample,\n"
5561 "so some menu options will be disabled."));
5562 } else if (!between) {
5563 /* give option to restore model sample */
5564 ok = maybe_set_sample_from_model(vwin);
5565 if (ok) {
5566 return FALSE;
5567 }
5568 }
5569 }
5570
5571 flip(vwin->ui, "/menubar/Analysis/Forecasts", ok);
5572 flip(vwin->ui, "/menubar/Save/yhat", ok);
5573 flip(vwin->ui, "/menubar/Save/uhat", ok);
5574 flip(vwin->ui, "/menubar/Save/uhat2", ok);
5575 flip(vwin->ui, "/menubar/Save/NewVar", ok);
5576
5577 if (resampled) {
5578 flip(vwin->ui, "/menubar/Tests", FALSE);
5579 flip(vwin->ui, "/menubar/Analysis/DisplayAFR", FALSE);
5580 flip(vwin->ui, "/menubar/Analysis/Bootstrap", FALSE);
5581 flip(vwin->ui, "/menubar/Graphs", FALSE);
5582 }
5583
5584 if (between) {
5585 flip(vwin->ui, "/menubar/Edit/Revise", FALSE);
5586 }
5587
5588 return FALSE;
5589 }
5590
check_VAR_menu(GtkWidget * w,GdkEventButton * eb,gpointer data)5591 static gint check_VAR_menu (GtkWidget *w, GdkEventButton *eb,
5592 gpointer data)
5593 {
5594 windata_t *vwin = (windata_t *) data;
5595 GtkAction *action;
5596 gboolean s, ok = TRUE;
5597
5598 if (complex_subsampled()) {
5599 ok = FALSE;
5600 }
5601
5602 action = gtk_ui_manager_get_action(vwin->ui, "/menubar/Tests");
5603 s = gtk_action_is_sensitive(action);
5604
5605 if (s == ok) {
5606 /* no need to flip state */
5607 return FALSE;
5608 }
5609
5610 flip(vwin->ui, "/menubar/Edit/Revise", ok);
5611 flip(vwin->ui, "/menubar/Tests", ok);
5612 flip(vwin->ui, "/menubar/Save", ok);
5613 flip(vwin->ui, "/menubar/Graphs", ok);
5614 flip(vwin->ui, "/menubar/Analysis/Forecasts", ok);
5615 flip(vwin->ui, "/menubar/Analysis/VarIrf", ok);
5616 flip(vwin->ui, "/menubar/Analysis/VarDecomp", ok);
5617
5618 if (!ok) {
5619 warnbox(_("dataset is subsampled"));
5620 }
5621
5622 return FALSE;
5623 }
5624
exists_string(const char * name,GretlType t)5625 static gchar *exists_string (const char *name, GretlType t)
5626 {
5627 gchar *s = NULL;
5628
5629 if (t == GRETL_TYPE_SERIES) {
5630 s = g_strdup_printf(_("A series named %s already exists"), name);
5631 } else if (t == GRETL_TYPE_MATRIX) {
5632 s = g_strdup_printf(_("A matrix named %s already exists"), name);
5633 } else if (t == GRETL_TYPE_DOUBLE) {
5634 s = g_strdup_printf(_("A scalar named %s already exists"), name);
5635 } else if (t == GRETL_TYPE_LIST) {
5636 s = g_strdup_printf(_("A list named %s already exists"), name);
5637 } else if (t == GRETL_TYPE_STRING) {
5638 s = g_strdup_printf(_("A string named %s already exists"), name);
5639 } else if (t == GRETL_TYPE_BUNDLE) {
5640 s = g_strdup_printf(_("A bundle named %s already exists"), name);
5641 } else if (t == GRETL_TYPE_ARRAY) {
5642 s = g_strdup_printf(_("An array named %s already exists"), name);
5643 }
5644
5645 return s;
5646 }
5647
object_overwrite_ok(const char * name,GretlType t,GtkWidget * parent)5648 static int object_overwrite_ok (const char *name, GretlType t,
5649 GtkWidget *parent)
5650 {
5651 gchar *info = exists_string(name, t);
5652 gchar *msg = g_strdup_printf("%s\n%s", info, _("OK to overwrite it?"));
5653 int resp;
5654
5655 resp = yes_no_dialog("gretl", msg, parent);
5656 g_free(info);
5657 g_free(msg);
5658
5659 return (resp == GRETL_YES);
5660 }
5661
5662 /* note: returns non-zero if the varname is not acceptable */
5663
real_gui_validate_varname(const char * name,GretlType t,int allow_overwrite,GtkWidget * parent)5664 static int real_gui_validate_varname (const char *name,
5665 GretlType t,
5666 int allow_overwrite,
5667 GtkWidget *parent)
5668 {
5669 int i, n = strlen(name);
5670 char namebit[VNAMELEN];
5671 unsigned char c;
5672 int err = 0;
5673
5674 *namebit = '\0';
5675
5676 if (n > VNAMELEN - 1) {
5677 strncat(namebit, name, VNAMELEN - 1);
5678 errbox_printf(_("Variable name %s... is too long\n"
5679 "(the max is %d characters)"), namebit,
5680 VNAMELEN - 1);
5681 err = 1;
5682 } else if (!(isalpha(*name))) {
5683 errbox_printf(_("First char of name ('%c') is bad\n"
5684 "(first must be alphabetical)"), *name);
5685 err = 1;
5686 } else {
5687 for (i=1; i<n && !err; i++) {
5688 c = (unsigned char) name[i];
5689
5690 if ((!(isalpha(c)) && !(isdigit(c)) && c != '_') || c > 127) {
5691 errbox_printf(_("Name contains an illegal char (in place %d)\n"
5692 "Use only unaccented letters, digits and underscore"),
5693 i + 1);
5694 err = 1;
5695 }
5696 }
5697 }
5698
5699 if (!err && t != GRETL_TYPE_NONE) {
5700 /* check for variable type collisions */
5701 GretlType t0 = gretl_type_from_name(name, dataset);
5702
5703 if (t0 != GRETL_TYPE_NONE) {
5704 /* there's already a variable of this name */
5705 if (t == t0 && allow_overwrite) {
5706 /* the types agree: overwrite? */
5707 err = !object_overwrite_ok(name, t, parent);
5708 } else {
5709 /* the types disgree: won't work */
5710 gchar *msg = exists_string(name, t0);
5711
5712 errbox(msg);
5713 g_free(msg);
5714 err = 1;
5715 }
5716 }
5717 }
5718
5719 return err;
5720 }
5721
5722 /* The "gui_validate_varname" family: both functions below check the
5723 putative @name for legality as a gretl variable name and return
5724 non-zero if it's not legal. In addition, both return non-zero if
5725 the name is valid but belongs to an existing variable of a type
5726 other than @type.
5727
5728 They diverge in this respect:
5729
5730 gui_validate_varname_strict: unconditionally returns non-zero
5731 if there's an existing variable of the same name, even if it's
5732 of type @type.
5733
5734 gui_validate_varname: checks with the user whether overwriting is
5735 OK in the case where a variable of type @type already exists; if
5736 so, it's assumed that the distinction between redefining a variable
5737 and adding a new variable is handled by the caller.
5738 */
5739
gui_validate_varname_strict(const char * name,GretlType type,GtkWidget * parent)5740 int gui_validate_varname_strict (const char *name, GretlType type,
5741 GtkWidget *parent)
5742 {
5743 return real_gui_validate_varname(name, type, 0, parent);
5744 }
5745
gui_validate_varname(const char * name,GretlType type,GtkWidget * parent)5746 int gui_validate_varname (const char *name, GretlType type,
5747 GtkWidget *parent)
5748 {
5749 return real_gui_validate_varname(name, type, 1, parent);
5750 }
5751
popup_menu_handler(GtkWidget * widget,GdkEventButton * event,gpointer data)5752 gint popup_menu_handler (GtkWidget *widget, GdkEventButton *event,
5753 gpointer data)
5754 {
5755 if (right_click(event)) {
5756 gtk_menu_popup(GTK_MENU(data), NULL, NULL, NULL, NULL,
5757 event->button, event->time);
5758 return TRUE;
5759 }
5760
5761 return FALSE;
5762 }
5763
add_popup_item(const gchar * label,GtkWidget * menu,GCallback callback,gpointer data)5764 void add_popup_item (const gchar *label, GtkWidget *menu,
5765 GCallback callback,
5766 gpointer data)
5767 {
5768 GtkWidget *item;
5769
5770 item = gtk_menu_item_new_with_label(label);
5771 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
5772 g_signal_connect(G_OBJECT(item), "activate",
5773 G_CALLBACK(callback), data);
5774 gtk_widget_show(item);
5775 }
5776
gui_get_plugin_function(const char * funcname)5777 void *gui_get_plugin_function (const char *funcname)
5778 {
5779 void *func;
5780
5781 func = get_plugin_function(funcname);
5782 if (func == NULL) {
5783 errbox(gretl_errmsg_get());
5784 }
5785
5786 return func;
5787 }
5788
double_underscores(char * targ,const char * src)5789 char *double_underscores (char *targ, const char *src)
5790 {
5791 char *p = targ;
5792
5793 while (*src) {
5794 if (*src == '_') {
5795 *p++ = '_';
5796 *p++ = '_';
5797 } else {
5798 *p++ = *src;
5799 }
5800 src++;
5801 }
5802 *p = '\0';
5803
5804 return targ;
5805 }
5806
double_underscores_new(const char * src)5807 gchar *double_underscores_new (const char *src)
5808 {
5809 const char *s = src;
5810 gchar *ret;
5811 int n = 0;
5812
5813 while (*s && (s = strchr(s, '_')) != NULL) {
5814 n++;
5815 s++;
5816 }
5817
5818 ret = g_malloc(strlen(src) + n + 1);
5819
5820 return double_underscores(ret, src);
5821 }
5822
adjust_fontspec_string(char * targ,const char * src,int mod)5823 char *adjust_fontspec_string (char *targ, const char *src,
5824 int mod)
5825 {
5826 char *p, c0, c1;
5827
5828 strcpy(targ, src);
5829
5830 if (mod == ADD_COMMA) {
5831 c0 = ' ';
5832 c1 = ',';
5833 } else {
5834 c0 = ',';
5835 c1 = ' ';
5836 }
5837
5838 p = strrchr(targ, c0);
5839 if (p != NULL && isdigit(p[1])) {
5840 *p = c1;
5841 }
5842
5843 return targ;
5844 }
5845
got_printable_output(PRN * prn)5846 static int got_printable_output (PRN *prn)
5847 {
5848 int ret = 0;
5849
5850 if (prn == NULL) {
5851 warnbox(_("No output was produced"));
5852 } else {
5853 const char *buf = gretl_print_get_buffer(prn);
5854
5855 if (string_is_blank(buf)) {
5856 warnbox(_("No output was produced"));
5857 gretl_print_destroy(prn);
5858 } else {
5859 ret = 1;
5860 }
5861 }
5862
5863 return ret;
5864 }
5865
5866 #ifdef G_OS_WIN32
5867
5868 /* MS Windows variants of functions to exec some third-party
5869 programs */
5870
win32_run_R_sync(const char * buf,gretlopt opt)5871 static void win32_run_R_sync (const char *buf, gretlopt opt)
5872 {
5873 PRN *prn = NULL;
5874 int err;
5875
5876 if (bufopen(&prn)) {
5877 return;
5878 }
5879
5880 err = execute_R_buffer(buf, dataset, opt, prn);
5881
5882 if (err) {
5883 gui_errmsg(err);
5884 } else {
5885 view_buffer(prn, 78, 350, _("gretl: script output"),
5886 PRINT, NULL);
5887 }
5888 }
5889
5890 /* win32 version */
5891
run_foreign_script(gchar * buf,int lang,gretlopt opt)5892 void run_foreign_script (gchar *buf, int lang, gretlopt opt)
5893 {
5894 const char *fname = NULL;
5895 int err;
5896
5897 opt |= OPT_G;
5898
5899 /* note: as things stand, the @fname we obtain here
5900 (composed in gretl_foreign.c) will be in the locale
5901 encoding, ready to pass on the Windows command line
5902 as in "foreign.exe fname"; this composite string is
5903 given to gretl_win32_grab_output() or gretl_spawn()
5904 below.
5905 */
5906
5907 err = write_gretl_foreign_script(buf, lang, opt, dataset, &fname);
5908
5909 if (err) {
5910 gui_errmsg(err);
5911 } else {
5912 PRN *prn = NULL;
5913 gchar *cmd = NULL;
5914
5915 if (bufopen(&prn)) {
5916 return;
5917 }
5918
5919 if (lang == LANG_OX) {
5920 cmd = g_strdup_printf("\"%s\" \"%s\"", gretl_oxl_path(), fname);
5921 } else if (lang == LANG_PYTHON) {
5922 cmd = g_strdup_printf("\"%s\" \"%s\"", gretl_python_path(), fname);
5923 } else if (lang == LANG_JULIA) {
5924 cmd = g_strdup_printf("\"%s\" \"%s\"", gretl_julia_path(), fname);
5925 } else if (lang == LANG_STATA) {
5926 cmd = g_strdup_printf("\"%s\" /e do \"%s\"", gretl_stata_path(), fname);
5927 } else if (lang == LANG_OCTAVE) {
5928 cmd = g_strdup_printf("\"%s\" -q \"%s\"", gretl_octave_path(), fname);
5929 }
5930
5931 if (lang == LANG_STATA) {
5932 gchar *buf = NULL;
5933
5934 gretl_chdir(gretl_workdir());
5935 remove("gretltmp.log");
5936 err = gretl_spawn(cmd);
5937
5938 if (g_file_get_contents("gretltmp.log", &buf, NULL, NULL)) {
5939 pputs(prn, buf);
5940 g_free(buf);
5941 pputc(prn, '\n');
5942 }
5943 } else {
5944 err = gretl_win32_pipe_output(cmd, gretl_dotdir(), OPT_NONE, prn);
5945 }
5946
5947 if (got_printable_output(prn)) {
5948 /* note: this check destroys @prn on failure */
5949 view_buffer(prn, 78, 350, _("gretl: script output"), PRINT, NULL);
5950 } else if (err) {
5951 gui_errmsg(err);
5952 }
5953
5954 g_free(cmd);
5955 }
5956 }
5957
5958 #else /* some non-Windows functions follow */
5959
browser_open(const char * url)5960 int browser_open (const char *url)
5961 {
5962 # if defined(OS_OSX)
5963 return osx_open_url(url);
5964 # else
5965 return gretl_fork("Browser", url, NULL);
5966 # endif
5967 }
5968
5969 /* Start an R session in asynchronous (interactive) mode.
5970 Note that there's a separate win32 function for this
5971 in gretlwin32.c.
5972 */
5973
start_R_async(void)5974 static void start_R_async (void)
5975 {
5976 char *s0 = NULL, *s1 = NULL, *s2 = NULL;
5977 int n = -1;
5978
5979 s0 = mymalloc(64);
5980 s1 = mymalloc(32);
5981 s2 = mymalloc(32);
5982
5983 if (s0 != NULL && s1 != NULL && s2 != NULL) {
5984 *s0 = *s1 = *s2 = '\0';
5985 /* probably "xterm -e R" or similar */
5986 n = sscanf(Rcommand, "%63s %31s %31s", s0, s1, s2);
5987 }
5988
5989 if (n == 0) {
5990 errbox(_("No command was supplied to start R"));
5991 } else if (n > 0) {
5992 char *supp1 = "--no-init-file";
5993 char *supp2 = "--no-restore-data";
5994 gchar *argv[6];
5995 GError *error = NULL;
5996 gboolean ok;
5997 int i = 0;
5998
5999 argv[i++] = s0;
6000 if (n > 1) {
6001 argv[i++] = s1;
6002 }
6003 if (n > 2) {
6004 argv[i++] = s2;
6005 }
6006 argv[i++] = supp1;
6007 argv[i++] = supp2;
6008 argv[i++] = NULL;
6009
6010 ok = g_spawn_async(NULL,
6011 argv,
6012 NULL,
6013 G_SPAWN_SEARCH_PATH,
6014 NULL,
6015 NULL,
6016 NULL,
6017 &error);
6018
6019 if (error != NULL) {
6020 errbox(error->message);
6021 g_error_free(error);
6022 } else if (!ok) {
6023 gui_errmsg(E_EXTERNAL);
6024 g_error_free(error);
6025 }
6026 }
6027
6028 free(s0);
6029 free(s1);
6030 free(s2);
6031 }
6032
6033 /* run R, Ox, etc., in synchronous (batch) mode and display the
6034 results in a gretl window: non-Windows variant
6035 */
6036
run_prog_sync(char ** argv,int lang)6037 static void run_prog_sync (char **argv, int lang)
6038 {
6039 gchar *sout = NULL;
6040 gchar *errout = NULL;
6041 gint status = 0;
6042 GError *gerr = NULL;
6043 PRN *prn = NULL;
6044
6045 if (lang == LANG_STATA) {
6046 /* control location of Stata log file */
6047 gretl_chdir(gretl_workdir());
6048 remove("gretltmp.log");
6049 }
6050
6051 g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
6052 NULL, NULL, &sout, &errout,
6053 &status, &gerr);
6054
6055 if (gerr != NULL) {
6056 errbox(gerr->message);
6057 g_error_free(gerr);
6058 } else if (status != 0) {
6059 if (errout != NULL && *errout != '\0') {
6060 if (strlen(errout) < MAXLEN) {
6061 errbox(errout);
6062 } else {
6063 bufopen(&prn);
6064 pputs(prn, errout);
6065 }
6066 } else if (sout != NULL && *sout != '\0') {
6067 if (strlen(sout) < MAXLEN) {
6068 errbox(sout);
6069 } else {
6070 bufopen(&prn);
6071 pputs(prn, sout);
6072 }
6073 } else {
6074 errbox_printf("%s exited with status %d", argv[0], status);
6075 }
6076 } else if (lang == LANG_STATA) {
6077 /* read log file */
6078 gchar *buf = NULL;
6079
6080 if (g_file_get_contents("gretltmp.log", &buf, NULL, NULL)) {
6081 bufopen(&prn);
6082 pputs(prn, buf);
6083 g_free(buf);
6084 pputc(prn, '\n');
6085 }
6086 } else {
6087 /* read good old stdout */
6088 if (!string_is_blank(sout)) {
6089 bufopen(&prn);
6090 pputs(prn, sout);
6091 }
6092 }
6093
6094 if (got_printable_output(prn)) {
6095 view_buffer(prn, 78, 350, _("gretl: script output"), PRINT, NULL);
6096 }
6097
6098 g_free(sout);
6099 g_free(errout);
6100 }
6101
run_R_sync(void)6102 static void run_R_sync (void)
6103 {
6104 gchar *argv[] = {
6105 "R",
6106 "--no-save",
6107 "--no-init-file",
6108 "--no-restore-data",
6109 "--slave",
6110 NULL
6111 };
6112
6113 run_prog_sync(argv, LANG_R);
6114 }
6115
run_foreign_script(gchar * buf,int lang,gretlopt opt)6116 void run_foreign_script (gchar *buf, int lang, gretlopt opt)
6117 {
6118 const char *fname = NULL;
6119 int err;
6120
6121 opt |= OPT_G;
6122
6123 err = write_gretl_foreign_script(buf, lang, opt, dataset, &fname);
6124
6125 if (err) {
6126 gui_errmsg(err);
6127 } else {
6128 gchar *argv[6];
6129
6130 if (lang == LANG_OCTAVE && (opt & OPT_Y)) {
6131 gretl_chdir(gretl_workdir());
6132 }
6133
6134 if (lang == LANG_OX) {
6135 argv[0] = (gchar *) gretl_oxl_path();
6136 argv[1] = (gchar *) fname;
6137 argv[2] = NULL;
6138 } else if (lang == LANG_PYTHON) {
6139 argv[0] = (gchar *) gretl_python_path();
6140 argv[1] = (gchar *) fname;
6141 argv[2] = NULL;
6142 } else if (lang == LANG_JULIA) {
6143 argv[0] = (gchar *) gretl_julia_path();
6144 argv[1] = (gchar *) fname;
6145 argv[2] = NULL;
6146 } else if (lang == LANG_STATA) {
6147 argv[0] = (gchar *) gretl_stata_path();
6148 argv[1] = (gchar *) "-q";
6149 argv[2] = (gchar *) "-b";
6150 argv[3] = (gchar *) "do";
6151 argv[4] = (gchar *) fname;
6152 argv[5] = NULL;
6153 } else if (lang == LANG_OCTAVE) {
6154 argv[0] = (gchar *) gretl_octave_path();
6155 argv[1] = (gchar *) "-q";
6156 argv[2] = (gchar *) fname;
6157 argv[3] = NULL;
6158 }
6159
6160 run_prog_sync(argv, lang);
6161 }
6162 }
6163
6164 #endif /* !G_OS_WIN32 */
6165
6166 /* driver for starting R, either interactive or in batch mode */
6167
start_R(const char * buf,int send_data,int interactive)6168 void start_R (const char *buf, int send_data, int interactive)
6169 {
6170 gretlopt Ropt = OPT_G;
6171 int err = 0;
6172
6173 if (send_data && !data_status) {
6174 warnbox(_("Please open a data file first"));
6175 return;
6176 }
6177
6178 if (interactive) {
6179 Ropt |= OPT_I;
6180 }
6181
6182 if (send_data) {
6183 Ropt |= OPT_D;
6184 if (annual_data(dataset) || quarterly_or_monthly(dataset)) {
6185 const char *opts[] = {
6186 N_("multiple time series object"),
6187 N_("data frame")
6188 };
6189 int resp;
6190
6191 resp = radio_dialog(NULL, _("Send data as"), opts, 2, 0, 0, NULL);
6192 if (resp < 0) {
6193 return;
6194 } else if (resp == 1) {
6195 Ropt |= OPT_F;
6196 }
6197 }
6198 }
6199
6200 /* On Windows in non-interactive mode, don't write
6201 these files here; that will be handled later
6202 */
6203 #ifdef G_OS_WIN32
6204 if (interactive) {
6205 err = write_gretl_R_files(buf, dataset, Ropt);
6206 }
6207 #else
6208 err = write_gretl_R_files(buf, dataset, Ropt);
6209 #endif
6210
6211 if (err) {
6212 gui_errmsg(err);
6213 delete_gretl_R_files();
6214 } else if (interactive) {
6215 #ifdef G_OS_WIN32
6216 win32_start_R_async();
6217 #else
6218 start_R_async();
6219 #endif
6220 } else {
6221 /* non-interactive */
6222 #ifdef G_OS_WIN32
6223 win32_run_R_sync(buf, Ropt);
6224 #else
6225 run_R_sync();
6226 #endif
6227 }
6228 }
6229
verbose_gerror_report(GError * gerr,const char * src)6230 void verbose_gerror_report (GError *gerr, const char *src)
6231 {
6232 fprintf(stderr, "GError details from %s\n"
6233 " message: '%s'\n domain = %d, code = %d\n",
6234 src, gerr->message, gerr->domain, gerr->code);
6235 }
6236
6237 /* Note: simplified 2020-12-08 on the assumption that filenames
6238 within gretl will be in UTF-8 on all platforms.
6239 */
6240
gretl_file_get_contents(const gchar * fname,gchar ** contents,gsize * size)6241 int gretl_file_get_contents (const gchar *fname, gchar **contents,
6242 gsize *size)
6243 {
6244 GError *gerr = NULL;
6245 gboolean ok = 0;
6246
6247 ok = g_file_get_contents(fname, contents, size, &gerr);
6248
6249 if (gerr != NULL) {
6250 verbose_gerror_report(gerr, "g_file_get_contents");
6251 errbox(gerr->message);
6252 g_error_free(gerr);
6253 }
6254
6255 return ok ? 0 : E_FOPEN;
6256 }
6257
print_today(void)6258 const char *print_today (void)
6259 {
6260 static char timestr[16];
6261 struct tm *local;
6262 time_t t;
6263
6264 t = time(NULL);
6265 local = localtime(&t);
6266 strftime(timestr, 15, "%Y-%m-%d", local);
6267
6268 return timestr;
6269 }
6270