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 /* toolbar.c: main-window toolbar, viewer window toolbars, etc. */
21 
22 #include "gretl.h"
23 #include "console.h"
24 #include "session.h"
25 #include "datafiles.h"
26 #include "selector.h"
27 #include "textbuf.h"
28 #include "textutil.h"
29 #include "series_view.h"
30 #include "model_table.h"
31 #include "cmdstack.h"
32 #include "dlgutils.h"
33 #include "fileselect.h"
34 #include "winstack.h"
35 #include "tabwin.h"
36 #include "fncall.h"
37 #include "fnsave.h"
38 #include "database.h"
39 #include "toolbar.h"
40 
41 #include "uservar.h"
42 #include "forecast.h"
43 #include "gretl_www.h"
44 
45 #ifdef G_OS_WIN32
46 # include "gretlwin32.h"
47 #endif
48 
49 #include <gio/gio.h>
50 
51 /* for viewer window toolbars */
52 #include "../pixmaps/mini.en.xpm"
53 
54 /* for pop-up search entry */
55 #include "../pixmaps/close_16.xpm"
56 
57 /* for window-finder menu */
58 #include "../pixmaps/mini.gretl.xpm"
59 #include "../pixmaps/mini.table.xpm"
60 #include "../pixmaps/mini.page.xpm"
61 
62 enum {
63     SAVE_ITEM = 1,
64     SAVE_AS_ITEM,
65     EDIT_ITEM,
66     PLOT_ITEM,
67     EXEC_ITEM,
68     COPY_ITEM,
69     PRINT_ITEM,
70     TEX_ITEM,
71     ADD_DATA_ITEM,
72     ADD_MATRIX_ITEM,
73     MAIL_ITEM,
74     HELP_ITEM,
75     CMD_HELP_ITEM,
76     GP_HELP_ITEM,
77     X12A_HELP_ITEM,
78     SORT_ITEM,
79     SORT_BY_ITEM,
80     FORMAT_ITEM,
81     INDEX_ITEM,
82     EDIT_HANSL_ITEM,
83     STICKIFY_ITEM,
84     ALPHA_ITEM,
85     REFRESH_ITEM,
86     OPEN_ITEM,
87     SPLIT_H_ITEM,
88     SPLIT_V_ITEM,
89     EDITOR_ITEM,
90     NOTES_ITEM,
91     NEW_ITEM,
92     BUNDLE_ITEM,
93     FIND_ITEM,
94     COPY_SCRIPT_ITEM,
95     BUILD_ITEM,
96     HMAP_ITEM,
97     DIGITS_ITEM,
98     DBN_ITEM,
99     FCAST_ITEM,
100     CLOSE_ITEM
101 } viewbar_flags;
102 
103 int toolbar_icon_size = GTK_ICON_SIZE_MENU;
104 
105 struct png_stock_maker {
106     char *fname;
107     const char *id;
108     gint8 in_menu;
109 };
110 
111 struct png_stock_maker png_stocks[] = {
112     { "calc.png",      GRETL_STOCK_CALC, 0 },
113     { "database.png",  GRETL_STOCK_DB, 0 },
114     { "fx.png",        GRETL_STOCK_FUNC, 0 },
115     { "betahat.png",   GRETL_STOCK_MODEL, 0 },
116     { "iconview.png",  GRETL_STOCK_ICONS, 0 },
117     { "console.png",   GRETL_STOCK_CONSOLE, 0 },
118     { "plot.png",      GRETL_STOCK_SCATTER, 0 },
119     { "winlist.png",   GRETL_STOCK_WINLIST },
120     { "bundle.png",    GRETL_STOCK_BUNDLE, 1 },
121     { "alpha.png",     GRETL_STOCK_ALPHA, 0 },
122     { "tex.png",       GRETL_STOCK_TEX, 0 },
123     { "bigger.png",    GRETL_STOCK_BIGGER, 0 },
124     { "smaller.png",   GRETL_STOCK_SMALLER, 0 },
125     { "menu.png",      GRETL_STOCK_MENU, 0 },
126     { "tools.png",     GRETL_STOCK_TOOLS, 0 },
127     { "dbnomics.png",  GRETL_STOCK_DBN, 1 },
128     { "fcast.png",     GRETL_STOCK_FCAST, 0 },
129     { "heatmap.png",   GRETL_STOCK_HMAP, 0 },
130     { "pushpin.png",   GRETL_STOCK_PIN, 0 },
131     { "mail.png",      GRETL_STOCK_MAIL, 1 },
132     { "pdf.png",       GRETL_STOCK_PDF, 1 },
133     { "split_h.png",   GRETL_STOCK_SPLIT_H, 0 },
134     { "join_h.png",    GRETL_STOCK_JOIN_H, 0 },
135     { "split_v.png",   GRETL_STOCK_SPLIT_V, 0 },
136     { "join_v.png",    GRETL_STOCK_JOIN_V, 0 },
137     { "boxplot.png",   GRETL_STOCK_BOX, 0 },
138     { "tsplot.png",    GRETL_STOCK_TS, 0 },
139     { "book.png",      GRETL_STOCK_BOOK, 0 },
140     { "query.png",     GRETL_STOCK_QUERY, 0 },
141 };
142 
143 struct xpm_stock_maker {
144     char **xpm;
145     const char *id;
146 };
147 
148 #if GTK_MAJOR_VERSION == 3
149 
try_auto_icon_sizing(int * bigger)150 static void try_auto_icon_sizing (int *bigger)
151 {
152     GdkDisplay *display = gdk_display_get_default();
153     GdkMonitor *monitor = gdk_display_get_primary_monitor(display);
154     GdkScreen *screen = gdk_screen_get_default();
155 
156     if (monitor != NULL) {
157 	int mmw = gdk_monitor_get_width_mm(monitor);
158 	int pxw = gdk_screen_get_width(screen);
159 	double mm16 = 16 * mmw / (double) pxw;
160 
161 	if (mm16 < 2.8) {
162 	    /* size of 16 pixels in millimeters */
163 	    fprintf(stderr, " auto-setting larger icons\n");
164 	    *bigger = 1;
165 	}
166     }
167 }
168 
169 #endif /* GTK3 */
170 
gretl_stock_icons_init(void)171 void gretl_stock_icons_init (void)
172 {
173     struct xpm_stock_maker xpm_stocks[] = {
174 	{ mini_en_xpm, GRETL_STOCK_EN },
175 	{ mini_gretl_xpm, GRETL_STOCK_GRETL},
176 	{ mini_table_xpm, GRETL_STOCK_TABLE},
177 	{ mini_page_xpm, GRETL_STOCK_PAGE},
178 	{ close_16_xpm, GRETL_STOCK_CLOSE}
179     };
180     static GtkIconFactory *gretl_factory;
181     int n1 = G_N_ELEMENTS(png_stocks);
182     int n2 = G_N_ELEMENTS(xpm_stocks);
183 
184     if (gretl_factory == NULL) {
185 	int bigger = (get_icon_sizing() == ICON_SIZE_MEDIUM);
186 	char icon_path[48], menu_path[48];
187 	gchar *p, *pm, *respath;
188 	GResource *icons;
189 	GtkIconSource *isrc;
190 	GtkIconSet *iset;
191 	GdkPixbuf *pbuf;
192 	int i;
193 
194 #if GTK_MAJOR_VERSION == 3
195 	if (get_icon_sizing() == ICON_SIZE_AUTO) {
196 	    try_auto_icon_sizing(&bigger);
197 	}
198 #endif
199 
200 	if (bigger) {
201 #if GTK_MAJOR_VERSION == 3
202 	    toolbar_icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
203 #else
204 	    toolbar_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
205 #endif
206 	}
207 
208 	gretl_factory = gtk_icon_factory_new();
209 
210 	respath = g_strdup_printf("%sgretl-icons.gresource", gretl_home());
211 	icons = g_resource_load(respath, NULL);
212 	if (icons == NULL) {
213 	    fprintf(stderr, "g_resource_load: failed to load icons\n");
214 	    g_free(respath);
215 	    goto do_pixmaps;
216 	}
217 
218 	g_resources_register(icons);
219 
220 	if (bigger) {
221 	    strcpy(icon_path, "/gretl/icons/24x24/");
222 	    strcpy(menu_path, "/gretl/icons/16x16/");
223 	    pm = strrchr(menu_path, '/') + 1;
224 	} else {
225 	    strcpy(icon_path, "/gretl/icons/16x16/");
226 	}
227 	p = strrchr(icon_path, '/') + 1;
228 
229 	for (i=0; i<n1; i++) {
230 	    strcat(icon_path, png_stocks[i].fname);
231 	    pbuf = gdk_pixbuf_new_from_resource(icon_path, NULL);
232 	    if (pbuf == NULL) {
233 		fprintf(stderr, "Failed to load %s\n", icon_path);
234 		*p = '\0';
235 		continue;
236 	    }
237 	    if (bigger && png_stocks[i].in_menu) {
238 		iset = gtk_icon_set_new();
239 		/* for toolbar use */
240 		isrc = gtk_icon_source_new();
241 		gtk_icon_source_set_pixbuf(isrc, pbuf);
242 		gtk_icon_source_set_size(isrc, toolbar_icon_size);
243 		gtk_icon_source_set_size_wildcarded(isrc, FALSE);
244 		gtk_icon_set_add_source(iset, isrc);
245 		g_object_unref(pbuf);
246 		/* for menu use */
247 		strcat(menu_path, png_stocks[i].fname);
248 		pbuf = gdk_pixbuf_new_from_resource(menu_path, NULL);
249 		isrc = gtk_icon_source_new();
250 		gtk_icon_source_set_pixbuf(isrc, pbuf);
251 		gtk_icon_source_set_size(isrc, GTK_ICON_SIZE_MENU);
252 		gtk_icon_source_set_size_wildcarded(isrc, FALSE);
253 		gtk_icon_set_add_source(iset, isrc);
254 		g_object_unref(pbuf);
255 		*pm = '\0';
256 	    } else {
257 		/* we just need a single icon */
258 		iset = gtk_icon_set_new_from_pixbuf(pbuf);
259 	    }
260 	    gtk_icon_factory_add(gretl_factory, png_stocks[i].id, iset);
261 	    gtk_icon_set_unref(iset);
262 	    *p = '\0';
263 	}
264 
265 	g_free(respath);
266 	g_resources_unregister(icons);
267 	g_resource_unref(icons);
268 
269     do_pixmaps:
270 
271 	for (i=0; i<n2; i++) {
272 	    pbuf = gdk_pixbuf_new_from_xpm_data((const char **) xpm_stocks[i].xpm);
273 	    iset = gtk_icon_set_new_from_pixbuf(pbuf);
274 	    g_object_unref(pbuf);
275 	    gtk_icon_factory_add(gretl_factory, xpm_stocks[i].id, iset);
276 	    gtk_icon_set_unref(iset);
277 	}
278 
279 	gtk_icon_factory_add_default(gretl_factory);
280     }
281 }
282 
283 /* callbacks for viewer window toolbar */
284 
copy_to_editor(GtkWidget * w,windata_t * vwin)285 static void copy_to_editor (GtkWidget *w, windata_t *vwin)
286 {
287     gchar *buf = textview_get_text(vwin->text);
288 
289     if (vwin->role == VIEW_LOG) {
290 	/* allow for the possibility that the buffer is empty */
291 	gchar *s = buf;
292 	int n = 0;
293 
294 	while (s != NULL && n < 3) {
295 	    s = strchr(s, '\n');
296 	    if (s != NULL) {
297 		s++;
298 		n++;
299 	    }
300 	}
301 
302 	if (s != NULL) {
303 	    gchar *modbuf;
304 
305 	    modbuf = g_strdup_printf("# logged commands\n%s", s);
306 	    do_new_script(EDIT_HANSL, modbuf);
307 	    g_free(modbuf);
308 	} else {
309 	    do_new_script(EDIT_HANSL, buf);
310 	}
311     } else {
312 	do_new_script(EDIT_HANSL, buf);
313     }
314 
315     g_free(buf);
316 }
317 
save_as_callback(GtkWidget * w,windata_t * vwin)318 static void save_as_callback (GtkWidget *w, windata_t *vwin)
319 {
320     GtkWidget *vmain = vwin_toplevel(vwin);
321     guint u = 0;
322 
323     if (g_object_get_data(G_OBJECT(vmain), "text_out")) {
324 	const char *opts[] = {
325 	    N_("Save to file"),
326 	    N_("Save to session as icon")
327 	};
328 	int resp;
329 
330 	resp = radio_dialog(_("gretl: save text"), _("Save text"),
331 			    opts, 2, 0, 0, vmain);
332 	if (resp < 0) {
333 	    return;
334 	} else if (resp == 1) {
335 	    save_output_as_text_icon(vwin);
336 	    return;
337 	} else {
338 	    u = SAVE_OUTPUT;
339 	}
340     } else if (vwin->role == EDIT_HANSL) {
341 	u = SAVE_SCRIPT;
342     } else if (vwin->role == EDIT_GP) {
343 	u = SAVE_GP_CMDS;
344     } else if (vwin->role == EDIT_R) {
345 	u = SAVE_R_CMDS;
346     } else if (vwin->role == EDIT_OX) {
347 	u = SAVE_OX_CMDS;
348     } else if (vwin->role == EDIT_OCTAVE) {
349 	u = SAVE_OCTAVE_CMDS;
350     } else if (vwin->role == EDIT_PYTHON) {
351         u = SAVE_PYTHON_CMDS;
352     } else if (vwin->role == EDIT_JULIA) {
353 	u = SAVE_JULIA_CODE;
354     } else if (vwin->role == EDIT_DYNARE) {
355 	u = SAVE_DYNARE_CODE;
356     } else if (vwin->role == EDIT_LPSOLVE) {
357 	u = SAVE_LPSOLVE_CODE;
358     } else if (vwin->role == EDIT_STATA) {
359 	u = SAVE_STATA_CMDS;
360     } else if (vwin->role == EDIT_SPEC) {
361 	u = SAVE_SPEC_FILE;
362     } else if (vwin->role == VIEW_FILE) {
363 	u = SAVE_TEXT;
364     } else if (vwin->role == EDIT_PKG_HELP ||
365 	       vwin->role == EDIT_PKG_GHLP) {
366 	u = SAVE_HELP_TEXT;
367     } else {
368 	dummy_call();
369 	return;
370     }
371 
372     file_save(vwin, u);
373 }
374 
375 /* Adjust the number of significant figures used in printing
376    coefficients and standard errors in a model viewer window,
377    or descriptive statistics in a "summary" window. Also record
378    the number of digits for use via Copy.
379 */
380 
display_digits_callback(GtkWidget * w,windata_t * vwin)381 static void display_digits_callback (GtkWidget *w, windata_t *vwin)
382 {
383     int wdigits = widget_get_int(vwin->text, "digits");
384     int save_digits = get_gretl_digits();
385     int digits, resp;
386 
387     digits = wdigits > 0 ? wdigits : save_digits;
388 
389     if (vwin->role == SUMMARY) {
390 	/* desciptive statistics window */
391 	Summary *s = vwin->data;
392 	int dmax = (s->opt & OPT_S)? 4 : 5;
393 
394 	digits = (digits > dmax)? dmax : digits;
395 	resp = spin_dialog(NULL, NULL, &digits,
396 			   _("Number of digits to show for statistics"),
397 			   3, dmax, 0, vwin_toplevel(vwin));
398     } else {
399 	/* model window */
400 	resp = spin_dialog(NULL, NULL, &digits,
401 			   _("Number of digits to show for coefficients"),
402 			   3, 6, 0, vwin_toplevel(vwin));
403     }
404 
405     if (resp != GRETL_CANCEL && digits != wdigits) {
406 	const char *buf;
407 	int save_digits;
408 	PRN *prn;
409 
410 	if (bufopen(&prn)) return;
411 	save_digits = get_gretl_digits();
412 	set_gretl_digits(digits);
413 	if (vwin->role == SUMMARY) {
414 	    print_summary(vwin->data, dataset, prn);
415 	} else {
416 	    printmodel(vwin->data, dataset, OPT_NONE, prn);
417 	}
418 	buf = gretl_print_get_trimmed_buffer(prn);
419 	textview_set_text(vwin->text, buf);
420 	gretl_print_destroy(prn);
421 	set_gretl_digits(save_digits);
422 	widget_set_int(vwin->text, "digits", digits);
423     }
424 }
425 
mail_script_callback(GtkWidget * w,windata_t * vwin)426 static void mail_script_callback (GtkWidget *w, windata_t *vwin)
427 {
428     if (viewer_char_count(vwin) == 0) {
429 	infobox(_("Nothing to send"));
430 	return;
431     }
432 
433     if (query_save_text(NULL, NULL, vwin)) {
434 	return;
435     }
436 
437     send_attachment(vwin->fname);
438 }
439 
440 /* callback for the "Open" icon in a script editing window,
441    which enables the user to switch to a different script,
442    or to open another tab if the editor is tab-enabled
443 */
444 
file_open_callback(GtkWidget * w,windata_t * vwin)445 static void file_open_callback (GtkWidget *w, windata_t *vwin)
446 {
447     file_selector(OPEN_SCRIPT, FSEL_DATA_VWIN, vwin);
448 }
449 
open_pkg_sample(GtkWidget * w,windata_t * vwin)450 static void open_pkg_sample (GtkWidget *w, windata_t *vwin)
451 {
452     if (viewer_char_count(vwin) > 0) {
453 	int resp;
454 
455 	resp = yes_no_dialog(NULL, _("Really replace content with\n"
456 				     "a selected file?"),
457 			     vwin->main);
458 	if (resp != GRETL_YES) {
459 	    return;
460 	}
461     }
462 
463     file_selector(OPEN_SCRIPT, FSEL_DATA_VWIN, vwin);
464 }
465 
toolbar_new_callback(GtkWidget * w,windata_t * vwin)466 static void toolbar_new_callback (GtkWidget *w, windata_t *vwin)
467 {
468     do_new_script(vwin->role, NULL);
469 }
470 
window_print_callback(GtkWidget * w,windata_t * vwin)471 static void window_print_callback (GtkWidget *w, windata_t *vwin)
472 {
473     if (textview_use_highlighting(vwin->role)) {
474 	int resp = yes_no_cancel_dialog(NULL,
475 					_("Print with syntax highlighting?"),
476 					vwin_toplevel(vwin));
477 
478 	if (resp == GRETL_YES) {
479 	    sourceview_print(vwin);
480 	} else if (resp == GRETL_NO) {
481 	    window_print(NULL, vwin);
482 	}
483     } else {
484 	window_print(NULL, vwin);
485     }
486 }
487 
window_help(GtkWidget * w,windata_t * vwin)488 static void window_help (GtkWidget *w, windata_t *vwin)
489 {
490     show_gui_help(vwin->role);
491 }
492 
multi_save_as_callback(GtkWidget * w,windata_t * vwin)493 static void multi_save_as_callback (GtkWidget *w, windata_t *vwin)
494 {
495     copy_format_dialog(vwin, W_SAVE);
496 }
497 
script_index(GtkWidget * w,windata_t * vwin)498 static void script_index (GtkWidget *w, windata_t *vwin)
499 {
500     display_files(PS_FILES, NULL);
501 }
502 
toolbar_refresh(GtkWidget * w,windata_t * vwin)503 static void toolbar_refresh (GtkWidget *w, windata_t *vwin)
504 {
505     if (vwin->role == VIEW_SERIES) {
506 	series_view_refresh(w, vwin);
507     }
508 }
509 
set_matrix_name(GtkWidget * widget,dialog_t * dlg)510 static void set_matrix_name (GtkWidget *widget, dialog_t *dlg)
511 {
512     char *vname = (char *) edit_dialog_get_data(dlg);
513     GtkWidget *parent =  edit_dialog_get_window(dlg);
514     const gchar *s = edit_dialog_get_text(dlg);
515 
516     if (s == NULL || gui_validate_varname(s, GRETL_TYPE_MATRIX, parent)) {
517 	edit_dialog_reset(dlg);
518     } else {
519 	strcpy(vname, s);
520 	edit_dialog_close(dlg);
521     }
522 }
523 
add_matrix_callback(GtkWidget * w,windata_t * vwin)524 static void add_matrix_callback (GtkWidget *w, windata_t *vwin)
525 {
526     if (vwin->role == XTAB) {
527 	char mname[VNAMELEN];
528 	gretl_matrix *m;
529 	int err, cancel = 0;
530 
531 	blocking_edit_dialog(0, _("gretl: save matrix"),
532 			     _("Enter a name"), NULL,
533 			     set_matrix_name, mname,
534 			     VARCLICK_NONE,
535 			     vwin_toplevel(vwin),
536 			     &cancel);
537 	if (!cancel) {
538 	    m = xtab_to_matrix(vwin->data);
539 	    if (m == NULL) {
540 		nomem();
541 	    } else {
542 		err = user_var_add_or_replace(mname,
543 					      GRETL_TYPE_MATRIX,
544 					      m);
545 		if (err) {
546 		    gretl_matrix_free(m);
547 		    gui_errmsg(err);
548 		} else {
549 		    infobox_printf(_("Saved matrix as %s"), mname);
550 		}
551 	    }
552 	}
553     }
554 }
555 
add_data_callback(GtkWidget * w,windata_t * vwin)556 static void add_data_callback (GtkWidget *w, windata_t *vwin)
557 {
558     int oldv = dataset->v;
559 
560     if (vwin->role == PCA) {
561 	add_pca_data(vwin);
562     } else if (vwin->role == LEVERAGE) {
563 	add_leverage_data(vwin);
564     } else if (vwin->role == MAHAL) {
565 	add_mahalanobis_data(vwin);
566     } else if (vwin->role == FCAST) {
567 	add_fcast_data(vwin, M_FCAST);
568     } else if (vwin->role == LOESS || vwin->role == NADARWAT) {
569 	add_nonparam_data(vwin);
570     } else if (vwin->role == VIEW_DBNOMICS) {
571 	add_dbnomics_data(vwin);
572     }
573 
574     if (dataset->v > oldv) {
575 	populate_varlist();
576 	mark_dataset_as_modified();
577     }
578 }
579 
real_coeffint_set_alpha(GtkWidget * w,GtkWidget * dialog)580 static void real_coeffint_set_alpha (GtkWidget *w, GtkWidget *dialog)
581 {
582     windata_t *vwin = g_object_get_data(G_OBJECT(dialog), "vwin");
583     double *x = g_object_get_data(G_OBJECT(dialog), "xptr");
584     CoeffIntervals *cf = vwin->data;
585     GtkTextBuffer *buf;
586     const char *newtext;
587     PRN *prn;
588 
589     if (bufopen(&prn)) {
590 	return;
591     }
592 
593     reset_coeff_intervals(cf, 1.0 - *x);
594     text_print_model_confints(cf, prn);
595     newtext = gretl_print_get_buffer(prn);
596     buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
597     gtk_text_buffer_set_text(buf, "", -1);
598     textview_set_text(vwin->text, newtext);
599     gretl_print_destroy(prn);
600 
601     gtk_widget_destroy(dialog);
602 }
603 
alpha_button_callback(GtkToggleButton * b,double * x)604 static void alpha_button_callback (GtkToggleButton *b, double *x)
605 {
606     if (gtk_toggle_button_get_active(b)) {
607 	int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(b), "i"));
608 
609 	if (i == 0) {
610 	    *x = 0.90;
611 	} else if (i == 1) {
612 	    *x = 0.95;
613 	} else if (i == 2) {
614 	    *x = 0.99;
615 	}
616     }
617 }
618 
reformat_callback(GtkWidget * w,windata_t * vwin)619 static void reformat_callback (GtkWidget *w, windata_t *vwin)
620 {
621     if (vwin->role == VIEW_MODELTABLE) {
622 	format_model_table(vwin);
623     } else {
624 	series_view_format_dialog(vwin);
625     }
626 }
627 
split_pane_callback(GtkWidget * w,windata_t * vwin)628 static void split_pane_callback (GtkWidget *w, windata_t *vwin)
629 {
630     GtkWidget *hb = g_object_get_data(G_OBJECT(w), "hpane");
631     GtkWidget *vb = g_object_get_data(G_OBJECT(w), "vpane");
632     int vertical = 0;
633 
634     if (hb != NULL) {
635 	vb = w;
636 	vertical = 1;
637     } else {
638 	hb = w;
639     }
640 
641     /* Note: by "vertical" here we mean that the split runs vertically,
642        dividing the pane into left- and right-hand sections; otherwise
643        the split runs horizontally. In a "gnuplot commands" window we
644        only offer a horizontal split, which means that @vb ("vertical
645        button") may be NULL.
646     */
647 
648     if (g_object_get_data(G_OBJECT(vwin->vbox), "sw") != NULL) {
649 	/* currently in single-view mode: so split */
650 	viewer_split_pane(vwin, vertical);
651 	if (vb != NULL) {
652 	    gtk_widget_set_sensitive(vb, vertical);
653 	}
654 	gtk_widget_set_sensitive(hb, !vertical);
655 	if (vertical) {
656 	    gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(vb),
657 					 GRETL_STOCK_JOIN_V);
658 	} else {
659 	    gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(hb),
660 					 GRETL_STOCK_JOIN_H);
661 	}
662     } else {
663 	GtkWidget *paned;
664 
665 	paned = g_object_get_data(G_OBJECT(vwin->vbox), "paned");
666 
667 	if (paned != NULL) {
668 	    /* currently in split-view mode: so rejoin */
669 	    vertical = GTK_IS_HPANED(paned);
670 	    viewer_close_pane(vwin);
671 	    gtk_widget_set_sensitive(hb, TRUE);
672 	    if (vb != NULL) {
673 		gtk_widget_set_sensitive(vb, TRUE);
674 	    }
675 	    if (vertical) {
676 		gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(vb),
677 					     GRETL_STOCK_SPLIT_V);
678 	    } else {
679 		gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(hb),
680 					     GRETL_STOCK_SPLIT_H);
681 	    }
682 	}
683     }
684 }
685 
toggle_alpha_spin(GtkToggleButton * b,GtkWidget * w)686 static void toggle_alpha_spin (GtkToggleButton *b, GtkWidget *w)
687 {
688     gtk_widget_set_sensitive(w, gtk_toggle_button_get_active(b));
689 }
690 
coeffint_set_alpha(GtkWidget * w,windata_t * vwin)691 static void coeffint_set_alpha (GtkWidget *w, windata_t *vwin)
692 {
693     CoeffIntervals *cf = vwin->data;
694     GtkWidget *dialog, *tmp, *hbox;
695     GtkWidget *vbox, *b, *hb2;
696     GSList *group = NULL;
697     GtkAdjustment *adj;
698     gchar txt[16];
699     double x = 1.0 - cf->alpha;
700     gboolean defset = FALSE;
701     int i;
702 
703     if (maybe_raise_dialog()) {
704 	return;
705     }
706 
707     dialog = gretl_dialog_new(_("gretl: coefficient confidence intervals"),
708 			      vwin_toplevel(vwin), GRETL_DLG_BLOCK);
709 
710     hbox = gtk_hbox_new(FALSE, 5);
711     hb2 = gtk_hbox_new(FALSE, 5);
712     tmp = gtk_label_new(_("Confidence level"));
713     gtk_box_pack_start(GTK_BOX(hb2), tmp, FALSE, FALSE, 0);
714 
715     tmp = gtk_label_new("1 - α :");
716     gtk_box_pack_start(GTK_BOX(hb2), tmp, FALSE, FALSE, 0);
717     gtk_box_pack_start(GTK_BOX(hbox), hb2, TRUE, TRUE, 10);
718     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
719     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
720 
721     hbox = gtk_hbox_new(FALSE, 5);
722     vbox = gtk_vbox_new(FALSE, 5);
723 
724     /* radio button for 90%, 95%, 99% confidence */
725 
726     for (i=0; i<3; i++) {
727 	double a = (i == 0)? 0.90 : (i == 1)? 0.95 : 0.99;
728 
729 	sprintf(txt, "%.2f", a);
730 	b = gtk_radio_button_new_with_label(group, txt);
731 	gtk_box_pack_start(GTK_BOX(vbox), b, FALSE, FALSE, 0);
732 	group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b));
733 	if (a == x) {
734 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), TRUE);
735 	    defset = TRUE;
736 	} else {
737 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), FALSE);
738 	}
739 	g_object_set_data(G_OBJECT(b), "i", GINT_TO_POINTER(i));
740 	g_signal_connect(G_OBJECT(b), "toggled",
741 			 G_CALLBACK(alpha_button_callback),
742 			 &x);
743     }
744 
745     /* radio button for "other" confidence level, plus spinner */
746 
747     hb2 = gtk_hbox_new(FALSE, 0);
748     b = gtk_radio_button_new_with_label(group, _("Other"));
749     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), !defset);
750     gtk_box_pack_start(GTK_BOX(hb2), b, FALSE, FALSE, 0);
751     adj = (GtkAdjustment *) gtk_adjustment_new(x, 0.60, 0.99, 0.01, 0, 0);
752     tmp = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.01, 2);
753     g_signal_connect(G_OBJECT(tmp), "value-changed",
754 		     G_CALLBACK(set_double_from_spinner), &x);
755     gtk_widget_set_sensitive(tmp, !defset);
756     g_signal_connect(G_OBJECT(b), "toggled",
757 		     G_CALLBACK(toggle_alpha_spin),
758 		     tmp);
759     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
760     gtk_box_pack_start(GTK_BOX(hb2), tmp, FALSE, FALSE, 5);
761     gtk_box_pack_start(GTK_BOX(vbox), hb2, FALSE, FALSE, 0);
762 
763     gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 10);
764 
765     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
766     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
767 
768     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
769 
770     /* Cancel button */
771     cancel_delete_button(hbox, dialog);
772 
773     g_object_set_data(G_OBJECT(dialog), "vwin", vwin);
774     g_object_set_data(G_OBJECT(dialog), "xptr", &x);
775 
776     /* "OK" button */
777     tmp = ok_button(hbox);
778     g_signal_connect(G_OBJECT(tmp), "clicked",
779 		     G_CALLBACK(real_coeffint_set_alpha), dialog);
780     gtk_widget_grab_default(tmp);
781 
782     gtk_widget_show_all(dialog);
783 }
784 
stickiness_callback(GtkWidget * w,windata_t * vwin)785 static void stickiness_callback (GtkWidget *w, windata_t *vwin)
786 {
787     output_policy_dialog(vwin, vwin, 1);
788 }
789 
do_corr_plot(windata_t * vwin)790 static void do_corr_plot (windata_t *vwin)
791 {
792     VMatrix *corr = vwin->data;
793     int err;
794 
795     err = plot_corrmat(corr, OPT_NONE);
796     gui_graph_handler(err);
797 }
798 
toolbar_plot_callback(GtkWidget * w,windata_t * vwin)799 static void toolbar_plot_callback (GtkWidget *w, windata_t *vwin)
800 {
801     if (vwin->role == VIEW_SERIES) {
802 	series_view_graph(w, vwin);
803     } else if (vwin->role == VIEW_BUNDLE) {
804 	exec_bundle_special_function(vwin->data, BUNDLE_PLOT,
805 				     NULL, vwin->main);
806     } else if (vwin->role == CORR) {
807 	do_corr_plot(vwin);
808     } else if (vwin->role == VIEW_DBNOMICS) {
809 	show_dbnomics_data(vwin, 1);
810     } else {
811 	do_nonparam_plot(vwin);
812     }
813 }
814 
toolbar_fcast_callback(GtkWidget * w,windata_t * vwin)815 static void toolbar_fcast_callback (GtkWidget *w, windata_t *vwin)
816 {
817     if (vwin->role == VIEW_BUNDLE) {
818 	exec_bundle_special_function(vwin->data, BUNDLE_FCAST,
819 				     NULL, vwin->main);
820     }
821 }
822 
dbnomics_show_series(GtkWidget * w,windata_t * vwin)823 static void dbnomics_show_series (GtkWidget *w, windata_t *vwin)
824 {
825     show_dbnomics_data(vwin, 0);
826 }
827 
editor_prefs_callback(GtkWidget * w,windata_t * vwin)828 static void editor_prefs_callback (GtkWidget *w, windata_t *vwin)
829 {
830     if (vwin->role == CONSOLE) {
831 	console_prefs_dialog(vwin->main);
832     } else {
833 	preferences_dialog(TAB_EDITOR, NULL, vwin_toplevel(vwin));
834     }
835 }
836 
build_pkg_callback(GtkWidget * w,windata_t * vwin)837 static void build_pkg_callback (GtkWidget *w, windata_t *vwin)
838 {
839     if (vwin_content_changed(vwin)) {
840 	int resp;
841 
842 	resp = yes_no_cancel_dialog("gretl", _("Save changes?"),
843 				    vwin->main);
844 	if (resp == GRETL_CANCEL) {
845 	    return;
846 	}
847 	if (resp == GRETL_YES) {
848 	    vwin_save_callback(NULL, vwin);
849 	}
850     }
851 
852     build_package_from_spec_file(vwin);
853 }
854 
bundle_plot_ok(windata_t * vwin)855 static int bundle_plot_ok (windata_t *vwin)
856 {
857     gretl_bundle *b = vwin->data;
858     gchar *pf = get_bundle_special_function(b, BUNDLE_PLOT);
859     int ret = 0;
860 
861     if (pf != NULL) {
862 	ret = 1;
863 	g_free(pf);
864     }
865 
866     return ret;
867 }
868 
bundle_fcast_ok(windata_t * vwin)869 static int bundle_fcast_ok (windata_t *vwin)
870 {
871     gretl_bundle *b = vwin->data;
872     gchar *ff = get_bundle_special_function(b, BUNDLE_FCAST);
873     int ret = 0;
874 
875     if (ff != NULL) {
876 	ret = 1;
877 	g_free(ff);
878     }
879 
880     return ret;
881 }
882 
suppress_hmap(VMatrix * corr)883 static int suppress_hmap (VMatrix *corr)
884 {
885     return corr->dim < 3;
886 }
887 
activate_script_help(GtkWidget * widget,windata_t * vwin)888 static void activate_script_help (GtkWidget *widget, windata_t *vwin)
889 {
890     text_set_cursor(vwin->text, GDK_QUESTION_ARROW);
891     set_window_help_active(vwin);
892 }
893 
edit_script_popup_item(GretlToolItem * item)894 static int edit_script_popup_item (GretlToolItem *item)
895 {
896     if (item->icon == NULL) return 0;
897 
898     return !strcmp(item->icon, GTK_STOCK_COPY) ||
899 	!strcmp(item->icon, GTK_STOCK_PASTE) ||
900 	!strcmp(item->icon, GTK_STOCK_FIND) ||
901 	!strcmp(item->icon, GTK_STOCK_UNDO) ||
902 	!strcmp(item->icon, GTK_STOCK_FIND_AND_REPLACE);
903 }
904 
set_plot_icon(GretlToolItem * item,int role)905 static void set_plot_icon (GretlToolItem *item, int role)
906 {
907     if (role == LOESS || role == NADARWAT || role == VIEW_BUNDLE) {
908 	item->icon = GRETL_STOCK_SCATTER;
909     } else if (role == VIEW_SERIES && dataset_is_cross_section(dataset)) {
910 	item->icon = GRETL_STOCK_BOX;
911     } /* else stay with the default, a time series plot icon */
912 }
913 
vwin_cut_callback(GtkWidget * w,windata_t * vwin)914 static void vwin_cut_callback (GtkWidget *w, windata_t *vwin)
915 {
916     gtk_text_buffer_cut_clipboard(gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text)),
917 				  gtk_clipboard_get(GDK_NONE),
918 				  TRUE);
919 }
920 
921 static GretlToolItem viewbar_items[] = {
922     { N_("New window"), GTK_STOCK_NEW, G_CALLBACK(toolbar_new_callback), NEW_ITEM },
923     { N_("Open..."), GTK_STOCK_OPEN, G_CALLBACK(file_open_callback), OPEN_ITEM },
924     { N_("Save"), GTK_STOCK_SAVE, G_CALLBACK(vwin_save_callback), SAVE_ITEM },
925     { N_("Save as..."), GTK_STOCK_SAVE_AS, G_CALLBACK(save_as_callback), SAVE_AS_ITEM },
926     { N_("Open in script editor"), GTK_STOCK_EDIT, G_CALLBACK(copy_to_editor), COPY_SCRIPT_ITEM },
927     { N_("Save bundle content..."), GRETL_STOCK_BUNDLE, NULL, BUNDLE_ITEM },
928     { N_("Print..."), GTK_STOCK_PRINT, G_CALLBACK(window_print_callback), PRINT_ITEM },
929     { N_("Show/hide"), GRETL_STOCK_PIN, G_CALLBACK(session_notes_callback), NOTES_ITEM },
930     { N_("Display values"), GTK_STOCK_MEDIA_PLAY, G_CALLBACK(dbnomics_show_series), DBN_ITEM },
931     { N_("Run"), GTK_STOCK_EXECUTE, G_CALLBACK(do_run_script), EXEC_ITEM },
932     { N_("Build package"), GRETL_STOCK_TOOLS, G_CALLBACK(build_pkg_callback), BUILD_ITEM },
933     { N_("Cut"), GTK_STOCK_CUT, G_CALLBACK(vwin_cut_callback), EDIT_ITEM },
934     { N_("Copy"), GTK_STOCK_COPY, G_CALLBACK(vwin_copy_callback), COPY_ITEM },
935     { N_("Paste"), GTK_STOCK_PASTE, G_CALLBACK(text_paste), EDIT_ITEM },
936     { N_("Find..."), GTK_STOCK_FIND, G_CALLBACK(text_find), FIND_ITEM },
937     { N_("Replace..."), GTK_STOCK_FIND_AND_REPLACE, G_CALLBACK(text_replace), EDIT_ITEM },
938     { N_("Undo"), GTK_STOCK_UNDO, G_CALLBACK(text_undo), EDIT_ITEM },
939     { N_("Redo"), GTK_STOCK_REDO, G_CALLBACK(text_redo), EDIT_ITEM },
940     { N_("Sort"), GTK_STOCK_SORT_ASCENDING, G_CALLBACK(series_view_toggle_sort), SORT_ITEM },
941     { N_("Sort by..."), GTK_STOCK_SORT_ASCENDING, G_CALLBACK(multi_series_view_sort_by), SORT_BY_ITEM },
942     { N_("Preferences..."), GTK_STOCK_PREFERENCES, G_CALLBACK(editor_prefs_callback), EDIT_HANSL_ITEM },
943     { N_("Auto-indent script"), GTK_STOCK_INDENT, G_CALLBACK(indent_hansl), EDIT_HANSL_ITEM },
944     { N_("Send To..."), GRETL_STOCK_MAIL, G_CALLBACK(mail_script_callback), MAIL_ITEM },
945     { N_("Scripts index"), GTK_STOCK_INDEX, G_CALLBACK(script_index), INDEX_ITEM },
946     { N_("Confidence level..."), GRETL_STOCK_ALPHA, G_CALLBACK(coeffint_set_alpha), ALPHA_ITEM },
947     { N_("LaTeX"), GRETL_STOCK_TEX, G_CALLBACK(window_tex_callback), TEX_ITEM },
948     { N_("Graph"), GRETL_STOCK_TS, G_CALLBACK(toolbar_plot_callback), PLOT_ITEM },
949     { N_("Forecast"), GRETL_STOCK_FCAST, G_CALLBACK(toolbar_fcast_callback), FCAST_ITEM },
950     { N_("Heatmap"), GRETL_STOCK_HMAP, G_CALLBACK(toolbar_plot_callback), HMAP_ITEM },
951     { N_("Reformat..."), GTK_STOCK_CONVERT, G_CALLBACK(reformat_callback), FORMAT_ITEM },
952     { N_("Edit values..."), GTK_STOCK_EDIT, G_CALLBACK(series_view_edit), EDITOR_ITEM },
953     { N_("Refresh"), GTK_STOCK_REFRESH, G_CALLBACK(toolbar_refresh), REFRESH_ITEM },
954     { N_("Add to dataset..."), GTK_STOCK_ADD, G_CALLBACK(add_data_callback), ADD_DATA_ITEM },
955     { N_("Add as matrix..."), GTK_STOCK_ADD, G_CALLBACK(add_matrix_callback), ADD_MATRIX_ITEM },
956     { N_("Stickiness..."), GRETL_STOCK_PIN, G_CALLBACK(stickiness_callback), STICKIFY_ITEM },
957     { N_("Toggle split pane"), GRETL_STOCK_SPLIT_H, G_CALLBACK(split_pane_callback), SPLIT_H_ITEM },
958     { N_("Toggle split pane"), GRETL_STOCK_SPLIT_V, G_CALLBACK(split_pane_callback), SPLIT_V_ITEM },
959     { N_("Help on command"), GRETL_STOCK_QUERY, G_CALLBACK(activate_script_help), CMD_HELP_ITEM },
960     { N_("Help"), GTK_STOCK_HELP, G_CALLBACK(window_help), HELP_ITEM },
961     { N_("Help"), GTK_STOCK_HELP, G_CALLBACK(display_gnuplot_help), GP_HELP_ITEM },
962     { N_("Help"), GTK_STOCK_HELP, G_CALLBACK(display_x12a_help), X12A_HELP_ITEM },
963     { N_("Digits..."), NULL, G_CALLBACK(NULL), DIGITS_ITEM }
964 };
965 
966 static int n_viewbar_items = G_N_ELEMENTS(viewbar_items);
967 
968 #define exec_ok(r) (vwin_editing_script(r) || \
969 		    r == VIEW_SCRIPT || \
970 		    r == VIEW_PKG_SAMPLE || \
971 	            r == EDIT_PKG_SAMPLE)
972 
973 #define open_ok(r) (vwin_editing_script(r))
974 
975 #define new_ok(r) (vwin_editing_script(r))
976 
977 #define edit_ok(r) (vwin_editing_script(r) || \
978 		    vwin_editing_buffer(r) || \
979                     r == EDIT_PKG_CODE || \
980 		    r == EDIT_PKG_SAMPLE || \
981 		    r == EDIT_PKG_HELP || \
982 		    r == EDIT_PKG_GHLP)
983 
984 #define save_as_ok(r) (r != EDIT_HEADER && \
985 	               r != EDIT_NOTES && \
986 	               r != EDIT_PKG_CODE && \
987 		       r != EDIT_PKG_SAMPLE && \
988 		       r != CONSOLE && \
989 		       r != VIEW_BUNDLE && \
990 		       r != VIEW_DBNOMICS)
991 
992 #define help_ok(r) (r == LEVERAGE || \
993 		    r == COINT2 || \
994 		    r == HURST || \
995 		    r == RMPLOT || \
996 		    r == MAHAL)
997 
998 #define cmd_help_ok(r) (r == EDIT_HANSL || \
999 	                r == EDIT_PKG_CODE || \
1000                         r == EDIT_PKG_SAMPLE || \
1001 			r == VIEW_PKG_SAMPLE || \
1002 			r == VIEW_PKG_CODE || \
1003 			r == VIEW_SCRIPT || \
1004 			r == VIEW_LOG || \
1005 			r == CONSOLE)
1006 
1007 /* for a non-editable script: can offer option to copy
1008    content into an editor window */
1009 #define copy_script_ok(r) (r == VIEW_PKG_SAMPLE || \
1010 			   r == VIEW_PKG_CODE || \
1011 			   r == VIEW_SCRIPT || \
1012 			   r == VIEW_LOG)
1013 
1014 #define sort_ok(r) (r == VIEW_SERIES)
1015 
1016 #define plot_ok(r) (r == VIEW_SERIES || \
1017 		    r == LOESS || \
1018 		    r == NADARWAT || \
1019 		    r == VIEW_DBNOMICS)
1020 
1021 #define add_data_ok(r) (r == PCA || r == LEVERAGE || \
1022                         r == MAHAL || r == FCAST || \
1023 			r == LOESS || r == NADARWAT || \
1024 			r == VIEW_DBNOMICS)
1025 
1026 #define split_h_ok(r) (r == SCRIPT_OUT || r == FNCALL_OUT || \
1027 		       r == VIEW_LOG || r == VIEW_PKG_CODE || \
1028 		       r == VIEW_BUNDLE || vwin_editing_script(r))
1029 
1030 #define split_v_ok(r) (r == SCRIPT_OUT || r == FNCALL_OUT)
1031 
1032 /* Screen out unwanted menu items depending on the context; also
1033    adjust the callbacks associated with some items based on
1034    context.
1035 */
1036 
tool_item_get_callback(GretlToolItem * item,windata_t * vwin,int latex_ok,int sortby_ok,int format_ok,int save_ok)1037 static GCallback tool_item_get_callback (GretlToolItem *item, windata_t *vwin,
1038 					 int latex_ok, int sortby_ok,
1039 					 int format_ok, int save_ok)
1040 {
1041     static int mail_ok = -1;
1042     GCallback func = item->func;
1043     int f = item->flag;
1044     int r = vwin->role;
1045 
1046     if (mail_ok < 0) {
1047 	mail_ok = curl_does_smtp();
1048     }
1049 
1050     if (r == EDIT_SPEC) {
1051 	/* This is a "special" that should maybe be regularized:
1052 	   a bit like editing a script, but different...
1053 	*/
1054 	if (f == NEW_ITEM || f == OPEN_ITEM || f == EXEC_ITEM) {
1055 	    return NULL;
1056 	}
1057     } else if (f == BUILD_ITEM) {
1058 	return NULL;
1059     }
1060 
1061     /* popup use only */
1062     if (f == DIGITS_ITEM) {
1063 	return NULL;
1064     }
1065 
1066     if (use_toolbar_search_box(r) && f == FIND_ITEM) {
1067 	/* using an "inline" search box: skip the
1068 	   "Find" button */
1069 	return NULL;
1070     }
1071 
1072     if (r == VIEW_DBNOMICS) {
1073 	if (f == PRINT_ITEM || f == FIND_ITEM) {
1074 	    return NULL;
1075 	}
1076     } else if (f == DBN_ITEM) {
1077 	return NULL;
1078     }
1079 
1080     if (copy_script_ok(r)) {
1081 	if (f == SAVE_AS_ITEM) {
1082 	    return NULL;
1083 	}
1084     } else if (f == COPY_SCRIPT_ITEM) {
1085 	return NULL;
1086     }
1087 
1088     if (r == EDIT_PKG_SAMPLE && f == OPEN_ITEM) {
1089 	return G_CALLBACK(open_pkg_sample);
1090     } else if (!edit_ok(r) && f == EDIT_ITEM) {
1091 	return NULL;
1092     } else if (!open_ok(r) && f == OPEN_ITEM) {
1093 	return NULL;
1094     } else if (!new_ok(r) && f == NEW_ITEM) {
1095 	return NULL;
1096     } else if (!exec_ok(r) && f == EXEC_ITEM) {
1097 	return NULL;
1098     } else if (!cmd_help_ok(r) && f == CMD_HELP_ITEM) {
1099 	return NULL;
1100     } else if ((!mail_ok || r != EDIT_HANSL) && f == MAIL_ITEM) {
1101 	return NULL;
1102     } else if (!help_ok(r) && f == HELP_ITEM) {
1103 	return NULL;
1104     } else if ((!latex_ok || !multiple_formats_ok(vwin)) && f == TEX_ITEM) {
1105 	return NULL;
1106     } else if (!add_data_ok(r) && f == ADD_DATA_ITEM) {
1107 	return NULL;
1108     } else if (r != XTAB && f == ADD_MATRIX_ITEM) {
1109 	return NULL;
1110     } else if (!sort_ok(r) && f == SORT_ITEM) {
1111 	return NULL;
1112     } else if (!sortby_ok && f == SORT_BY_ITEM) {
1113 	return NULL;
1114     } else if (!plot_ok(r) && f == PLOT_ITEM) {
1115 	if (r == VIEW_BUNDLE && bundle_plot_ok(vwin)) {
1116 	    ; /* alright then */
1117 	} else {
1118 	    return NULL;
1119 	}
1120     } else if (f == FCAST_ITEM) {
1121 	if (r == VIEW_BUNDLE && bundle_fcast_ok(vwin)) {
1122 	    ; /* alright then */
1123 	} else {
1124 	    return NULL;
1125 	}
1126     } else if (!split_h_ok(r) && f == SPLIT_H_ITEM) {
1127 	return NULL;
1128     } else if (!split_v_ok(r) && f == SPLIT_V_ITEM) {
1129 	return NULL;
1130     } else if (!format_ok && f == FORMAT_ITEM) {
1131 	return NULL;
1132     } else if (r != VIEW_SERIES && f == EDITOR_ITEM) {
1133 	return NULL;
1134     } else if (r == CONSOLE && func == G_CALLBACK(editor_prefs_callback)) {
1135 	; /* alright then */
1136     } else if (r != EDIT_HANSL && r != EDIT_PKG_CODE &&
1137 	       r != EDIT_PKG_SAMPLE && f == EDIT_HANSL_ITEM) {
1138 	return NULL;
1139     } else if (r != VIEW_SCRIPT && f == INDEX_ITEM) {
1140 	return NULL;
1141     } else if (r != SCRIPT_OUT && f == STICKIFY_ITEM) {
1142 	return NULL;
1143     } else if (r != COEFFINT && f == ALPHA_ITEM) {
1144 	return NULL;
1145     } else if (r != VIEW_SERIES && f == REFRESH_ITEM) {
1146 	return NULL;
1147     } else if (r != EDIT_GP && f == GP_HELP_ITEM) {
1148 	return NULL;
1149     } else if (r != EDIT_X12A && f == X12A_HELP_ITEM) {
1150 	return NULL;
1151     } else if (f == SAVE_ITEM && !save_ok) {
1152 	return NULL;
1153     } else if (r != EDIT_NOTES && f == NOTES_ITEM) {
1154 	return NULL;
1155     } else if (r != VIEW_BUNDLE && r != VIEW_DBNOMICS && f == BUNDLE_ITEM) {
1156 	return NULL;
1157     } else if (f == HMAP_ITEM) {
1158 	if (r != CORR) {
1159 	    return NULL;
1160 	} else if (suppress_hmap(vwin->data)) {
1161 	    return NULL;
1162 	}
1163     } else if (f == SAVE_AS_ITEM) {
1164 	if (!save_as_ok(r) || (vwin->flags & VWIN_NO_SAVE)) {
1165 	    return NULL;
1166 	} else if (multiple_formats_ok(vwin) ||
1167 		   (vwin->flags & VWIN_MULTI_SERIES)) {
1168 	    func = G_CALLBACK(multi_save_as_callback);
1169 	}
1170     }
1171 
1172     return func;
1173 }
1174 
fcast_save_call(GtkAction * action,gpointer p)1175 static void fcast_save_call (GtkAction *action, gpointer p)
1176 {
1177     const char *s = gtk_action_get_name(action);
1178     ModelDataIndex idx;
1179 
1180     idx = (strcmp(s, "SaveSderr") == 0)? M_FCSE : M_FCAST;
1181 
1182     add_fcast_data((windata_t *) p, idx);
1183 }
1184 
make_fcast_save_menu(windata_t * vwin)1185 static GtkWidget *make_fcast_save_menu (windata_t *vwin)
1186 {
1187     GtkWidget *menu = gtk_menu_new();
1188     GtkAction *action;
1189     GtkWidget *item;
1190     int i;
1191 
1192     for (i=0; i<2; i++) {
1193 	action = gtk_action_new(i == 0 ? "SaveFcast" : "SaveSderr",
1194 				i == 0 ? _("_Save forecast...") :
1195 				_("Save standard errors..."),
1196 				NULL, NULL);
1197 	g_signal_connect(G_OBJECT(action), "activate",
1198 			 G_CALLBACK(fcast_save_call), vwin);
1199 	item = gtk_action_create_menu_item(action);
1200 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1201     }
1202 
1203     return menu;
1204 }
1205 
tool_item_get_menu(GretlToolItem * item,windata_t * vwin)1206 static GtkWidget *tool_item_get_menu (GretlToolItem *item, windata_t *vwin)
1207 {
1208     GtkWidget *menu = NULL;
1209 
1210     if (vwin->role == VIEW_BUNDLE) {
1211 	if (item->flag == BUNDLE_ITEM) {
1212 	    menu = make_bundle_content_menu(vwin);
1213 	} else if (item->flag == PLOT_ITEM) {
1214 	    menu = make_bundle_plot_menu(vwin);
1215 	} else if (item->flag == SAVE_ITEM) {
1216 	    menu = make_bundle_save_menu(vwin);
1217 	    if (menu != NULL) {
1218 		item->tip = N_("Save...");
1219 	    }
1220 	}
1221     } else if (vwin->role == VIEW_DBNOMICS) {
1222 	if (item->flag == BUNDLE_ITEM) {
1223 	    menu = make_bundle_content_menu(vwin);
1224 	} else if (item->flag == SAVE_ITEM) {
1225 	    menu = make_bundle_save_menu(vwin);
1226 	    if (menu != NULL) {
1227 		item->tip = N_("Save...");
1228 	    }
1229 	}
1230     } else if (vwin->role == FCAST && item->flag == ADD_DATA_ITEM) {
1231 	FITRESID *fr = vwin->data;
1232 
1233 	if (fr->sderr != NULL) {
1234 	    menu = make_fcast_save_menu(vwin);
1235 	}
1236     }
1237 
1238     if (menu != NULL) {
1239 	/* don't leak: record pointer to menu so it can
1240 	   be destroyed when the window is closed */
1241 	vwin_record_toolbar_popup(vwin, menu);
1242     }
1243 
1244     return menu;
1245 }
1246 
gretl_toolbar_flat(GtkWidget * w)1247 static void gretl_toolbar_flat (GtkWidget *w)
1248 {
1249     static int style_done;
1250 
1251     gtk_widget_set_name(w, "gretl_toolbar");
1252 
1253     if (!style_done) {
1254 	gtk_rc_parse_string("style \"gretl-tb-style\"\n{\n"
1255 			    "  GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
1256 			    "}\n"
1257 			    "widget \"*.gretl_toolbar\" style \"gretl-tb-style\"");
1258 	style_done = 1;
1259     }
1260 }
1261 
gretl_toolbar_new(GtkWidget * sibling)1262 GtkWidget *gretl_toolbar_new (GtkWidget *sibling)
1263 {
1264     GtkWidget *tb = gtk_toolbar_new();
1265 
1266     gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb), toolbar_icon_size);
1267     gtk_toolbar_set_style(GTK_TOOLBAR(tb), GTK_TOOLBAR_ICONS);
1268     gtk_toolbar_set_show_arrow(GTK_TOOLBAR(tb), FALSE);
1269 
1270     if (sibling == NULL) {
1271 	/* if we're not alongside a menu bar ("sibling"),
1272 	   show the toolbar without a shadow
1273 	*/
1274 	gretl_toolbar_flat(tb);
1275     }
1276 
1277     return tb;
1278 }
1279 
gretl_tooltips_add(GtkWidget * w,const gchar * str)1280 void gretl_tooltips_add (GtkWidget *w, const gchar *str)
1281 {
1282     gtk_widget_set_tooltip_text(w, str);
1283 }
1284 
gretl_menu_button(const char * icon,const char * tip,GtkWidget ** pw)1285 static GtkToolItem *gretl_menu_button (const char *icon,
1286 				       const char *tip,
1287 				       GtkWidget **pw)
1288 {
1289     GtkWidget *img, *button = gtk_button_new();
1290     GtkToolItem *item = gtk_tool_item_new();
1291 
1292     gtk_widget_set_tooltip_text(GTK_WIDGET(item), _(tip));
1293     gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1294     img = gtk_image_new_from_stock(icon, toolbar_icon_size /* GTK_ICON_SIZE_MENU */);
1295     gtk_container_add(GTK_CONTAINER(button), img);
1296     gtk_container_add(GTK_CONTAINER(item), button);
1297     *pw = button;
1298 
1299     return item;
1300 }
1301 
gretl_tool_item_set_tip(GtkWidget * item,GretlToolItem * tool)1302 static void gretl_tool_item_set_tip (GtkWidget *item,
1303 				     GretlToolItem *tool)
1304 {
1305     const char *accel = NULL;
1306 
1307     if (tool->flag == EXEC_ITEM) {
1308 	accel = "Ctrl+R";
1309     } else if (tool->flag == COPY_ITEM) {
1310 	accel = "Ctrl+C";
1311     } else if (tool->flag == SAVE_ITEM) {
1312 	accel = "Ctrl+S";
1313     } else if (tool->flag == FIND_ITEM) {
1314 	accel = "Ctrl+F";
1315     } else if (!strcmp(tool->icon, GTK_STOCK_FIND_AND_REPLACE)) {
1316 	accel = "Ctrl+H";
1317     }
1318 
1319     if (accel != NULL) {
1320 	gchar *s = g_strdup_printf("%s (%s)", _(tool->tip), accel);
1321 
1322 	gtk_widget_set_tooltip_text(item, s);
1323 	g_free(s);
1324     } else {
1325 	gtk_widget_set_tooltip_text(item, _(tool->tip));
1326     }
1327 }
1328 
gretl_toolbar_insert(GtkWidget * tbar,GretlToolItem * tool,GCallback func,gpointer data,gint pos)1329 GtkWidget *gretl_toolbar_insert (GtkWidget *tbar,
1330 				 GretlToolItem *tool,
1331 				 GCallback func,
1332 				 gpointer data,
1333 				 gint pos)
1334 {
1335     GtkToolItem *item;
1336 
1337     item = gtk_tool_button_new_from_stock(tool->icon);
1338     gretl_tool_item_set_tip(GTK_WIDGET(item), tool);
1339     g_signal_connect(G_OBJECT(item), "clicked", func, data);
1340     gtk_widget_set_size_request(GTK_WIDGET(item), 30, -1);
1341     gtk_toolbar_insert(GTK_TOOLBAR(tbar), item, pos);
1342 
1343     return GTK_WIDGET(item);
1344 }
1345 
button_menu_pos(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer data)1346 static void button_menu_pos (GtkMenu *menu,
1347 			     gint *x,
1348 			     gint *y,
1349 			     gboolean *push_in,
1350 			     gpointer data)
1351 {
1352     GtkWidget *button = data;
1353     gint wx, wy, tx, ty;
1354 
1355     gdk_window_get_origin(gtk_widget_get_window(button), &wx, &wy);
1356     gtk_widget_translate_coordinates(button, gtk_widget_get_toplevel(button),
1357 				     0, 0, &tx, &ty);
1358     *x = wx + tx;
1359     *y = wy + ty + 26;
1360     *push_in = TRUE;
1361 }
1362 
tool_item_popup(GtkWidget * button,GdkEvent * event,GtkWidget * menu)1363 static void tool_item_popup (GtkWidget *button, GdkEvent *event,
1364 			     GtkWidget *menu)
1365 {
1366     gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
1367 		   button_menu_pos, button,
1368 		   event->button.button, event->button.time);
1369 }
1370 
1371 /* right-click action for exec button */
1372 
exec_press(GtkWidget * w,GdkEventButton * eb,windata_t * vwin)1373 static gint exec_press (GtkWidget *w, GdkEventButton *eb, windata_t *vwin)
1374 {
1375     if (eb->button == 3) {
1376 	run_script_silent(NULL, vwin);
1377 	return TRUE;
1378     } else {
1379 	return FALSE;
1380     }
1381 }
1382 
vwin_toolbar_insert(GretlToolItem * tool,GCallback func,GtkWidget * menu,windata_t * vwin,gint pos)1383 GtkWidget *vwin_toolbar_insert (GretlToolItem *tool,
1384 				GCallback func,
1385 				GtkWidget *menu,
1386 				windata_t *vwin,
1387 				gint pos)
1388 {
1389     GtkToolItem *item;
1390 
1391     if (menu != NULL) {
1392 	/* make and insert a button that pops down a menu */
1393 	GtkWidget *button;
1394 
1395 	item = gretl_menu_button(tool->icon, tool->tip, &button);
1396 	g_signal_connect(G_OBJECT(button), "button-press-event",
1397 			 G_CALLBACK(tool_item_popup), menu);
1398     } else {
1399 	/* make and insert a regular callback button */
1400 	item = gtk_tool_button_new_from_stock(tool->icon);
1401 	g_signal_connect(G_OBJECT(item), "clicked", func, vwin);
1402 	if (tool->flag == NEW_ITEM && window_is_tab(vwin)) {
1403 	    gtk_widget_set_tooltip_text(GTK_WIDGET(item), _("New tab"));
1404 	} else {
1405 	    gretl_tool_item_set_tip(GTK_WIDGET(item), tool);
1406 	    if (tool->flag == EXEC_ITEM) {
1407 		g_signal_connect(G_OBJECT(item), "button-press-event",
1408 				 G_CALLBACK(exec_press), vwin);
1409 	    }
1410 	}
1411     }
1412 
1413     gtk_toolbar_insert(GTK_TOOLBAR(vwin->mbar), item, pos);
1414 
1415     return GTK_WIDGET(item);
1416 }
1417 
viewbar_add_items(windata_t * vwin,ViewbarFlags flags)1418 static void viewbar_add_items (windata_t *vwin, ViewbarFlags flags)
1419 {
1420     int sortby_ok = has_sortable_data(vwin);
1421     int format_ok = can_format_data(vwin);
1422     int latex_ok = latex_is_ok();
1423     int save_ok = (flags & VIEWBAR_EDITABLE);
1424     GtkWidget *hpane = NULL, *vpane = NULL;
1425     GtkWidget *button;
1426     GtkWidget *menu;
1427     GretlToolItem *item;
1428     GCallback func;
1429     int i;
1430 
1431     for (i=0; i<n_viewbar_items; i++) {
1432 	func = NULL;
1433 	menu = NULL;
1434 	item = &viewbar_items[i];
1435 
1436 	/* Is there anything to hook up, in context? We
1437 	   try first for a menu to attach to the toolbar
1438 	   button; failing that we test for a "direct"
1439 	   callback function.
1440 	*/
1441 	menu = tool_item_get_menu(item, vwin);
1442 	if (menu == NULL && item->func != NULL) {
1443 	    func = tool_item_get_callback(item, vwin, latex_ok, sortby_ok,
1444 					  format_ok, save_ok);
1445 	}
1446 	if (func == NULL && menu == NULL) {
1447 	    /* nothing to hook up */
1448 	    continue;
1449 	}
1450 
1451 	if (item->flag == PLOT_ITEM) {
1452 	    set_plot_icon(item, vwin->role);
1453 	}
1454 
1455 	button = vwin_toolbar_insert(item, func, menu, vwin, -1);
1456 
1457 	if (func == (GCallback) split_pane_callback) {
1458 	    if (hpane == NULL) {
1459 		hpane = button;
1460 	    } else {
1461 		vpane = button;
1462 	    }
1463 	}
1464 
1465 	if (item->flag == SAVE_ITEM) {
1466 	    if (vwin->role != CONSOLE &&
1467 		vwin->role != VIEW_BUNDLE &&
1468 		vwin->role != VIEW_DBNOMICS) {
1469 		/* nothing to save just yet */
1470 		g_object_set_data(G_OBJECT(vwin->mbar), "save_button", button);
1471 		gtk_widget_set_sensitive(button, FALSE);
1472 	    }
1473 	} else if (item->flag == SAVE_AS_ITEM) {
1474 	    g_object_set_data(G_OBJECT(vwin->mbar), "save_as_button", button);
1475 	    if (strstr(vwin->fname, "script_tmp")) {
1476 		gtk_widget_set_sensitive(button, FALSE);
1477 	    }
1478 	}
1479     }
1480 
1481     if (hpane != NULL) {
1482 	g_object_set_data(G_OBJECT(hpane), "vpane", vpane);
1483     }
1484 
1485     if (vpane != NULL) {
1486 	g_object_set_data(G_OBJECT(vpane), "hpane", hpane);
1487     }
1488 }
1489 
vwin_add_viewbar(windata_t * vwin,ViewbarFlags flags)1490 void vwin_add_viewbar (windata_t *vwin, ViewbarFlags flags)
1491 {
1492     if ((flags & VIEWBAR_HAS_TEXT) || vwin->role == SCRIPT_OUT) {
1493 	g_object_set_data(G_OBJECT(vwin->main), "text_out",
1494 			  GINT_TO_POINTER(1));
1495     }
1496 
1497     vwin->mbar = gretl_toolbar_new(NULL);
1498     viewbar_add_items(vwin, flags);
1499     vwin_pack_toolbar(vwin);
1500 }
1501 
build_text_popup(windata_t * vwin)1502 GtkWidget *build_text_popup (windata_t *vwin)
1503 {
1504     GtkWidget *pmenu = gtk_menu_new();
1505     GretlToolItem *item;
1506     GCallback func;
1507     GtkWidget *w;
1508     int i;
1509 
1510     for (i=0; i<n_viewbar_items; i++) {
1511 	item = &viewbar_items[i];
1512 	func = G_CALLBACK(NULL);
1513 	if (item->flag == SPLIT_H_ITEM || item->flag == SPLIT_V_ITEM) {
1514 	    continue;
1515 	} else if (item->flag == DIGITS_ITEM &&
1516 		   (vwin->role == VIEW_MODEL || vwin->role == SUMMARY)) {
1517 	    func = G_CALLBACK(display_digits_callback);
1518 	} else if (vwin->role == EDIT_HANSL) {
1519 	    /* the script editor popup may have some special stuff
1520 	       added: don't clutter it up */
1521 	    if (edit_script_popup_item(item)) {
1522 		func = item->func;
1523 	    } else {
1524 		func = NULL;
1525 	    }
1526 	} else {
1527 	    func = tool_item_get_callback(item, vwin, 0, 0, 0, 0);
1528 	}
1529 	if (func != G_CALLBACK(NULL)) {
1530 	    if (func == G_CALLBACK(text_paste)) {
1531 		GtkClipboard *cb = gtk_clipboard_get(GDK_NONE);
1532 
1533 		if (!gtk_clipboard_wait_is_text_available(cb)) {
1534 		    continue;
1535 		}
1536 	    } else if (func == G_CALLBACK(text_undo) && !text_can_undo(vwin)) {
1537 		continue;
1538 	    }
1539 	    w = gtk_menu_item_new_with_label(_(item->tip));
1540 	    g_signal_connect(G_OBJECT(w), "activate", func, vwin);
1541 	    gtk_widget_show(w);
1542 	    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), w);
1543 	}
1544     }
1545 
1546     if (vwin->role != EDIT_HANSL) {
1547 	if (window_is_undockable(vwin)) {
1548 	    add_undock_popup_item(pmenu, vwin);
1549 	} else if (window_is_dockable(vwin)) {
1550 	    add_dock_popup_item(pmenu, vwin);
1551 	}
1552     }
1553 
1554     return pmenu;
1555 }
1556 
1557 /* callbacks for main-window toolbar icons */
1558 
tbar_calc(void)1559 static void tbar_calc (void)
1560 {
1561 #ifdef G_OS_WIN32
1562     win32_run_async(calculator, NULL);
1563 #else
1564     gretl_fork("calculator", NULL, NULL);
1565 #endif
1566 }
1567 
tbar_open_data(void)1568 static void tbar_open_data (void)
1569 {
1570     display_files(TEXTBOOK_DATA, NULL);
1571 }
1572 
tbar_command_ref(void)1573 static void tbar_command_ref (void)
1574 {
1575     display_text_help(NULL);
1576 }
1577 
tbar_xy_graph(void)1578 static void tbar_xy_graph (void)
1579 {
1580     if (data_status) {
1581 	if (dataset->v == 2) {
1582 	    do_graph_var(mdata->active_var);
1583 	} else if (mdata_selection_count() == 2) {
1584 	    plot_from_selection(GR_XY);
1585 	} else {
1586 	    selection_dialog(GR_XY, _("gretl: define graph"),
1587 			     NULL, do_graph_from_selector);
1588 	}
1589     } else {
1590 	warnbox(_("Please open a data file first"));
1591     }
1592 }
1593 
tbar_model(void)1594 static void tbar_model (void)
1595 {
1596     if (data_status) {
1597 	selection_dialog(OLS, _("gretl: specify model"), NULL, do_model);
1598     } else {
1599 	warnbox(_("Please open a data file first"));
1600     }
1601 }
1602 
tbar_new_script(void)1603 static void tbar_new_script (void)
1604 {
1605     do_new_script(EDIT_HANSL, NULL);
1606 }
1607 
tbar_show_funcs(GtkWidget * w,gpointer p)1608 static void tbar_show_funcs (GtkWidget *w, gpointer p)
1609 {
1610     display_files(FUNC_FILES, NULL);
1611 }
1612 
1613 /* end toolbar icon callbacks */
1614 
1615 static GretlToolItem mainbar_items[] = {
1616     { N_("launch calculator"),  GRETL_STOCK_CALC,    G_CALLBACK(tbar_calc), 0 },
1617     { N_("new script"),         GTK_STOCK_EDIT,      G_CALLBACK(tbar_new_script), 0 },
1618     { N_("open gretl console"), GRETL_STOCK_CONSOLE, G_CALLBACK(gretl_console), 1 },
1619     { N_("session icon view"),  GRETL_STOCK_ICONS,   G_CALLBACK(view_session), 0 },
1620     { N_("function packages"),  GRETL_STOCK_FUNC,    G_CALLBACK(tbar_show_funcs), 0 },
1621     { N_("command reference"),  GTK_STOCK_HELP,      G_CALLBACK(tbar_command_ref), 0 },
1622     { N_("find series"),        GTK_STOCK_FIND,      G_CALLBACK(listbox_find), 0 },
1623     { N_("X-Y graph"),          GRETL_STOCK_SCATTER, G_CALLBACK(tbar_xy_graph), 0 },
1624     { N_("OLS model"),          GRETL_STOCK_MODEL,   G_CALLBACK(tbar_model), 0 },
1625     { N_("databases"),          GRETL_STOCK_DB,      G_CALLBACK(show_native_dbs), 0 },
1626     { N_("open dataset"),       GTK_STOCK_OPEN,      G_CALLBACK(tbar_open_data), 0 },
1627 };
1628 
add_mainwin_toolbar(GtkWidget * vbox)1629 void add_mainwin_toolbar (GtkWidget *vbox)
1630 {
1631     GretlToolItem *item;
1632     GtkWidget *hbox;
1633     int i, n = G_N_ELEMENTS(mainbar_items);
1634 
1635     mdata->mbar = gretl_toolbar_new(NULL);
1636 
1637     for (i=0; i<n; i++) {
1638 	item = &mainbar_items[i];
1639 	if (swallow && item->flag) {
1640 	    continue;
1641 	}
1642 	gretl_toolbar_insert(mdata->mbar, item, item->func, mdata, -1);
1643     }
1644 
1645     hbox = gtk_hbox_new(FALSE, 0);
1646     gtk_box_pack_start(GTK_BOX(hbox), mdata->mbar, FALSE, FALSE, 0);
1647     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1648 }
1649 
1650 /* Add a temporary menubar for use in a script output
1651    window, while we're waiting for the output. If the
1652    output window is being reused this is a bit more
1653    complicated; we have to "hide" the regular menubar
1654    before inserting the temporary one.
1655  */
1656 
vwin_add_tmpbar(windata_t * vwin)1657 void vwin_add_tmpbar (windata_t *vwin)
1658 {
1659     GretlToolItem item = {
1660 	N_("Stop"),
1661 	GTK_STOCK_STOP,
1662 	G_CALLBACK(do_stop_script),
1663 	0
1664     };
1665     GtkWidget *hbox, *tmp;
1666 
1667     hbox = g_object_get_data(G_OBJECT(vwin->main), "top-hbox");
1668 
1669     if (hbox != NULL) {
1670 	/* We're replacing a "real" menubar temporarily: ref. the
1671 	   widgets in @hbox before removing them so we can put
1672 	   them back later.
1673 	*/
1674 	GtkWidget *winlist = g_object_get_data(G_OBJECT(hbox), "winlist");
1675 
1676 	g_object_ref(G_OBJECT(vwin->mbar));
1677 	gtk_container_remove(GTK_CONTAINER(hbox), vwin->mbar);
1678 	if (vwin->finder != NULL) {
1679 	    g_object_ref(G_OBJECT(vwin->finder));
1680 	    gtk_container_remove(GTK_CONTAINER(hbox), vwin->finder);
1681 	}
1682 	if (winlist != NULL) {
1683 	    g_object_ref(G_OBJECT(winlist));
1684 	    gtk_container_remove(GTK_CONTAINER(hbox), winlist);
1685 	}
1686     } else {
1687 	/* starting from scratch */
1688 	hbox = gtk_hbox_new(FALSE, 0);
1689 	g_object_set_data(G_OBJECT(vwin->main), "top-hbox", hbox);
1690 	gtk_box_pack_start(GTK_BOX(vwin->vbox), hbox, FALSE, FALSE, 0);
1691     }
1692 
1693     tmp = gretl_toolbar_new(NULL);
1694     gretl_toolbar_insert(tmp, &item, item.func, NULL, 0);
1695     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
1696 
1697     start_wait_for_output(vwin, hbox);
1698     gtk_widget_show_all(hbox);
1699 }
1700