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 /* callbacks.c for gretl */
21 
22 #include "gretl.h"
23 #include "selector.h"
24 #include "session.h"
25 #include "database.h"
26 #include "datafiles.h"
27 #include "textbuf.h"
28 #include "textutil.h"
29 #include "dlgutils.h"
30 #include "fileselect.h"
31 #include "ssheet.h"
32 #include "treeutils.h"
33 #include "datawiz.h"
34 #include "winstack.h"
35 #include "matrix_extra.h"
36 
doubleclick_action(windata_t * vwin)37 static void doubleclick_action (windata_t *vwin)
38 {
39     switch (vwin->role) {
40     case MAINWIN:
41 	if (dataset != NULL && dataset->n > 0) {
42 	    display_var();
43 	}
44 	break;
45     case TEXTBOOK_DATA:
46 	browser_open_data(NULL, vwin);
47 	break;
48     case PS_FILES:
49 	browser_open_ps(NULL, vwin);
50 	break;
51     case FUNC_FILES:
52 	browser_call_func(NULL, vwin);
53 	break;
54     case NATIVE_DB:
55 	open_db_index(NULL, vwin);
56 	break;
57     case REMOTE_DB:
58 	open_remote_db_index(NULL, vwin);
59 	break;
60     case NATIVE_SERIES:
61     case RATS_SERIES:
62     case PCGIVE_SERIES:
63     case REMOTE_SERIES:
64 	display_db_series(vwin);
65 	break;
66     case DBNOMICS_TOP:
67 	open_dbnomics_provider(NULL, vwin);
68 	break;
69     case DBNOMICS_DB:
70 	open_dbnomics_dataset(NULL, vwin);
71 	break;
72     case DBNOMICS_SERIES:
73 	open_dbnomics_series(NULL, vwin);
74 	break;
75     default:
76 	break;
77     }
78 }
79 
listbox_select_row(GtkTreeSelection * selection,gpointer data)80 void listbox_select_row (GtkTreeSelection *selection, gpointer data)
81 {
82     windata_t *win = (windata_t *) data;
83     GtkTreeIter iter;
84     GtkTreeModel *model;
85     GtkTreePath *path;
86 
87     if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
88 	return;
89     }
90 
91     path = gtk_tree_model_get_path(model, &iter);
92     win->active_var = tree_path_get_row_number(path);
93     gtk_tree_path_free(path);
94 }
95 
listbox_double_click(GtkWidget * widget,GdkEventButton * event,windata_t * win)96 gint listbox_double_click (GtkWidget *widget, GdkEventButton *event,
97 			   windata_t *win)
98 {
99     if (event != NULL && event->type == GDK_2BUTTON_PRESS
100 	&& event->button == 1) {
101 	doubleclick_action(win);
102     }
103     return FALSE;
104 }
105 
listbox_drag(GtkWidget * listbox,GdkEventMotion * event,gpointer data)106 gboolean listbox_drag (GtkWidget *listbox, GdkEventMotion *event,
107 		       gpointer data)
108 {
109     gint x, y;
110     GdkModifierType state;
111     GtkTreeView *view = GTK_TREE_VIEW(listbox);
112     GtkTreePath *path;
113 
114     if (event->is_hint) {
115         gdk_window_get_pointer(event->window, &x, &y, &state);
116     } else {
117         x = event->x;
118         y = event->y;
119         state = event->state;
120     }
121 
122     if ((state & GDK_BUTTON1_MASK) &&
123 	gtk_tree_view_get_path_at_pos(view, x, y, &path,
124 				      NULL, NULL, NULL)) {
125 	GtkTreeSelection *select = NULL;
126 	GtkTreePath *anchor_path = NULL;
127 	gchar *anchor_id = NULL;
128 	gint row;
129 	int anchor;
130 	static gint lastrow;
131 
132 	anchor = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(listbox),
133 						   "active_row"));
134 	row = tree_path_get_row_number(path);
135 
136 	select = gtk_tree_view_get_selection(view);
137 	if (select == NULL) {
138 	    return FALSE;
139 	}
140 	anchor_id = g_strdup_printf("%d", anchor);
141 	anchor_path = gtk_tree_path_new_from_string(anchor_id);
142 	g_free(anchor_id);
143 
144 	if (row != lastrow) {
145 	    gtk_tree_selection_unselect_all(select);
146 	    gtk_tree_selection_select_range(select, anchor_path,
147 					    path);
148 	}
149 
150 	gtk_tree_path_free(path);
151 	gtk_tree_path_free(anchor_path);
152 
153 	lastrow = row;
154     }
155 
156     return FALSE;
157 }
158 
159 struct open_data_code {
160     int c;
161     const gchar *s;
162 };
163 
164 struct open_data_code open_data_codes[] = {
165     { OPEN_DATA,       "OpenData" },
166     { APPEND_DATA,     "AppendData" },
167     { OPEN_MARKERS,    "AddMarkers" },
168     { OPEN_RATS_DB,    "RATSDB" },
169     { OPEN_PCGIVE_DB,  "PcGiveDB" },
170     { 0, NULL }
171 };
172 
open_data_code(const gchar * s)173 static int open_data_code (const gchar *s)
174 {
175     int i;
176 
177     for (i=0; open_data_codes[i].s != NULL; i++) {
178 	if (!strcmp(s, open_data_codes[i].s)) {
179 	    return open_data_codes[i].c;
180 	}
181     }
182 
183     return 0;
184 }
185 
open_data(GtkAction * action)186 void open_data (GtkAction *action)
187 {
188     if (!dataset_locked()) {
189 	int code = open_data_code(gtk_action_get_name(action));
190 
191 	file_selector(code, FSEL_DATA_NONE, NULL);
192     }
193 }
194 
file_save(windata_t * vwin,int ci)195 void file_save (windata_t *vwin, int ci)
196 {
197     switch (ci) {
198     case SAVE_OUTPUT:
199     case SAVE_CONSOLE:
200     case SAVE_SCRIPT:
201     case SAVE_GP_CMDS:
202     case SAVE_R_CMDS:
203     case SAVE_OX_CMDS:
204     case SAVE_OCTAVE_CMDS:
205     case SAVE_PYTHON_CMDS:
206     case SAVE_STATA_CMDS:
207     case SAVE_JULIA_CODE:
208     case SAVE_DYNARE_CODE:
209     case SAVE_LPSOLVE_CODE:
210     case SAVE_DATA:
211     case SAVE_DATA_AS:
212     case SAVE_SPEC_FILE:
213     case SAVE_HELP_TEXT:
214 	file_selector(ci, FSEL_DATA_VWIN, vwin);
215 	break;
216     case EXPORT_CSV:
217     case EXPORT:
218 	data_export_selection_wrapper(ci);
219 	break;
220     case SAVE_TEX:
221     case SAVE_TEXT:
222 	file_selector(ci, FSEL_DATA_MISC, vwin->data);
223 	break;
224     default:
225 	dummy_call();
226     }
227 }
228 
fsave_code(const gchar * s)229 static int fsave_code (const gchar *s)
230 {
231     if (!strcmp(s, "SaveDataAs"))
232 	return SAVE_DATA_AS;
233     if (!strcmp(s, "ExportData"))
234 	return EXPORT;
235 
236     return SAVE_DATA;
237 }
238 
fsave_callback(GtkAction * action,gpointer p)239 void fsave_callback (GtkAction *action, gpointer p)
240 {
241     const gchar *s = gtk_action_get_name(action);
242     int ci = fsave_code(s);
243 
244     file_save(p, ci);
245 }
246 
dummy_call(void)247 void dummy_call (void)
248 {
249     errbox(_("Sorry, this item not yet implemented!"));
250 }
251 
model_action_code(GtkAction * action)252 static int model_action_code (GtkAction *action)
253 {
254     const gchar *s = gtk_action_get_name(action);
255     int ci = gretl_command_number(s);
256 
257     if (ci == 0) {
258 	/* look up "GUI special" */
259 	if (!strcmp(s, "PANEL_WLS"))
260 	    ci = PANEL_WLS;
261 	else if (!strcmp(s, "PANEL_B"))
262 	    ci = PANEL_B;
263 	else if (!strcmp(s, "VLAGSEL"))
264 	    ci = VLAGSEL;
265 	else if (!strcmp(s, "blogit"))
266 	    ci = LOGIT;
267 	else if (!strcmp(s, "ologit"))
268 	    ci = OLOGIT;
269 	else if (!strcmp(s, "mlogit"))
270 	    ci = MLOGIT;
271 	else if (!strcmp(s, "bprobit"))
272 	    ci = PROBIT;
273 	else if (!strcmp(s, "oprobit"))
274 	    ci = OPROBIT;
275 	else if (!strcmp(s, "reprobit"))
276 	    ci = REPROBIT;
277 	else if (!strcmp(s, "iv-liml"))
278 	    ci = IV_LIML;
279 	else if (!strcmp(s, "iv-gmm"))
280 	    ci = IV_GMM;
281 	else if (!strcmp(s, "countmod"))
282 	    ci = COUNTMOD;
283 	else if (!strcmp(s, "regls"))
284 	    ci = REGLS;
285 	else if (!strcmp(s, "FE_LOGISTIC"))
286 	    ci = FE_LOGISTIC;
287     }
288 
289     return ci;
290 }
291 
fit_resid_callback(GtkAction * action,gpointer data)292 void fit_resid_callback (GtkAction *action, gpointer data)
293 {
294     const gchar *s = gtk_action_get_name(action);
295     windata_t *vwin = (windata_t *) data;
296     int code = M_UHAT;
297 
298     if (!strcmp(s, "yhat")) {
299 	code = M_YHAT;
300     } else if (!strcmp(s, "uhat")) {
301 	code = M_UHAT;
302     } else if (!strcmp(s, "uhat2")) {
303 	code = M_UHAT2;
304     } else if (!strcmp(s, "h")) {
305 	code = M_H;
306     } else if (!strcmp(s, "ahat")) {
307 	code = M_AHAT;
308     }
309 
310     save_fit_resid(vwin, code);
311 }
312 
313 /* callback for adding a scalar from a model, also
314    pressed into service for saving a model as bundle
315 */
316 
model_stat_callback(GtkAction * action,gpointer data)317 void model_stat_callback (GtkAction *action, gpointer data)
318 {
319     const gchar *s = gtk_action_get_name(action);
320     windata_t *vwin = (windata_t *) data;
321     MODEL *pmod = vwin->data;
322     int code = M_ESS;
323 
324     if (!strcmp(s, "ess")) {
325 	code = M_ESS;
326     } else if (!strcmp(s, "se")) {
327 	code = M_SIGMA;
328     } else if (!strcmp(s, "rsq")) {
329 	code = M_RSQ;
330     } else if (!strcmp(s, "trsq")) {
331 	code = M_TRSQ;
332     } else if (!strcmp(s, "df")) {
333 	code = M_DF;
334     } else if (!strcmp(s, "lnL")) {
335 	code = M_LNL;
336     } else if (!strcmp(s, "AIC")) {
337 	code = M_AIC;
338     } else if (!strcmp(s, "BIC")) {
339 	code = M_BIC;
340     } else if (!strcmp(s, "HQC")) {
341 	code = M_HQC;
342     } else if (!strcmp(s, "bundle")) {
343 	code = B_MODEL;
344     }
345 
346     add_model_stat(pmod, code, vwin);
347 }
348 
have_midas_data(void)349 static int have_midas_data (void)
350 {
351     int i, m, got_midas = 0;
352 
353     for (i=1; i<dataset->v; i++) {
354 	m = series_is_midas_anchor(dataset, i);
355 	if (m > 0 && i + m <= dataset->v) {
356 	    int is_midas = 1;
357 	    int j, p, p0 = m;
358 
359 	    for (j=i+1; j<i+m; j++) {
360 		p = series_get_midas_period(dataset, j);
361 		if (p != p0 - 1) {
362 		    is_midas = 0;
363 		    break;
364 		} else {
365 		    p0 = p;
366 		}
367 	    }
368 	    if (is_midas) {
369 		got_midas = 1;
370 		break;
371 	    }
372 	}
373     }
374 
375     if (!got_midas) {
376 	const gchar *title = N_("gretl: warning");
377 	GtkWidget *dialog, *hbox, *help;
378 	const gchar *msg;
379 
380 	msg = N_("No MIDAS data were found in the current dataset");
381 	dialog = gtk_message_dialog_new(GTK_WINDOW(mdata->main),
382 					GTK_DIALOG_DESTROY_WITH_PARENT,
383 					GTK_MESSAGE_WARNING,
384 					GTK_BUTTONS_CLOSE,
385 					"%s", _(msg));
386 	g_signal_connect_swapped(dialog, "response",
387 				 G_CALLBACK(gtk_widget_destroy),
388 				 dialog);
389 	hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
390 	help = context_help_button(hbox, MIDAS_LIST);
391 	g_signal_connect_swapped(help, "clicked",
392 				 G_CALLBACK(gtk_widget_destroy),
393 				 dialog);
394 	gtk_widget_show(help);
395 	gtk_window_set_title(GTK_WINDOW(dialog), _(title));
396 	gtk_widget_show(dialog);
397     }
398 
399     return got_midas;
400 }
401 
model_callback(GtkAction * action,gpointer data)402 void model_callback (GtkAction *action, gpointer data)
403 {
404     int code = model_action_code(action);
405 
406     if (code == MIDASREG && !have_midas_data()) {
407 	return;
408     } else {
409 	modelspec_dialog(code);
410     }
411 }
412 
model_genr_callback(GtkAction * action,gpointer data)413 void model_genr_callback (GtkAction *action, gpointer data)
414 {
415     windata_t *vwin = (windata_t *) data;
416 
417     edit_dialog(MODEL_GENR, _("gretl: add var"),
418 		_("Enter formula for new variable:"),
419 		"", do_model_genr, vwin,
420 		VARCLICK_INSERT_NAME,
421 		vwin_toplevel(vwin));
422 }
423 
selector_callback_code(const gchar * s)424 static int selector_callback_code (const gchar *s)
425 {
426     int ci = gretl_command_number(s);
427 
428     if (ci > 0) return ci;
429 
430     if (!strcmp(s, "TSPlot"))
431 	return GR_PLOT;
432     if (!strcmp(s, "ScatterPlot"))
433 	return GR_XY;
434     if (!strcmp(s, "ImpulsePlot"))
435 	return GR_IMP;
436     if (!strcmp(s, "FactorPlot"))
437 	return GR_DUMMY;
438     if (!strcmp(s, "FrischPlot"))
439 	return GR_XYZ;
440     if (!strcmp(s, "ThreeDPlot"))
441 	return GR_3D;
442     if (!strcmp(s, "MultiXY"))
443 	return SCATTERS;
444     if (!strcmp(s, "MultiTS"))
445 	return TSPLOTS;
446     if (!strcmp(s, "GR_BOX"))
447 	return GR_BOX;
448     if (!strcmp(s, "GR_FBOX"))
449 	return GR_FBOX;
450     if (!strcmp(s, "GR_QQ"))
451 	return QQPLOT;
452     if (!strcmp(s, "VLAGSEL"))
453 	return VLAGSEL;
454     if (!strcmp(s, "ConfEllipse"))
455 	return ELLIPSE;
456     if (!strcmp(s, "VarOmit"))
457 	return VAROMIT;
458     if (!strcmp(s, "loess"))
459 	return LOESS;
460     if (!strcmp(s, "nadarwat"))
461 	return NADARWAT;
462 
463     return 0;
464 }
465 
selector_callback(GtkAction * action,gpointer data)466 void selector_callback (GtkAction *action, gpointer data)
467 {
468     const gchar *s = gtk_action_get_name(action);
469     windata_t *vwin = (windata_t *) data;
470     int ci;
471 
472     ci = selector_callback_code(s);
473 
474     if (ci == COINT || ci == COINT2) {
475 	selection_dialog(ci, _("gretl: cointegration test"), NULL, do_coint);
476     } else if (ci == VAR || ci == VECM) {
477 	selection_dialog(ci, (ci == VAR)? _("gretl: VAR") : _("gretl: VECM"),
478 			 NULL, do_vector_model);
479     } else if (ci == VLAGSEL) {
480 	selection_dialog(ci, _("gretl: VAR lag selection"), NULL, do_vector_model);
481     } else if (ci == GR_XY || ci == GR_IMP || ci == GR_DUMMY ||
482 	       ci == SCATTERS || ci == GR_3D || ci == GR_XYZ ||
483 	       ci == GR_FBOX) {
484 	int (*selfunc)() = NULL;
485 
486 	switch (ci) {
487 	case GR_XY:
488 	case GR_IMP:
489 	    selfunc = do_graph_from_selector;
490 	    break;
491 	case GR_3D:
492 	    selfunc = do_splot_from_selector;
493 	    break;
494 	case GR_DUMMY:
495 	    selfunc = do_dummy_graph;
496 	    break;
497 	case GR_XYZ:
498 	    selfunc = do_xyz_graph;
499 	    break;
500 	case SCATTERS:
501 	    selfunc = do_scatters;
502 	    break;
503 	case GR_FBOX:
504 	    selfunc = do_factorized_boxplot;
505 	    break;
506 	default:
507 	    return;
508 	}
509 	selection_dialog(ci, _("gretl: define graph"), NULL, selfunc);
510     } else if (ci == ADD || ci == OMIT) {
511 	simple_selection_for_viewer(ci, _("gretl: model tests"),
512 				    do_add_omit, vwin);
513     } else if (ci == VAROMIT) {
514 	simple_selection_for_viewer(ci, _("gretl: model tests"),
515 				    do_VAR_omit, vwin);
516     } else if (ci == COEFFSUM) {
517 	simple_selection_for_viewer(ci, _("gretl: model tests"),
518 				    do_coeff_sum, vwin);
519     } else if (ci == ELLIPSE) {
520 	simple_selection_for_viewer(ci, _("gretl: model tests"),
521 				    do_confidence_region, vwin);
522     } else if (ci == GR_PLOT) {
523 	simple_selection(ci, _("gretl: define graph"), do_graph_from_selector,
524 			 NULL);
525     } else if (ci == TSPLOTS) {
526 	simple_selection(ci, _("gretl: define graph"), do_scatters, NULL);
527     } else if (ci == GR_BOX) {
528 	simple_selection(ci, _("gretl: define graph"), do_regular_boxplot, NULL);
529     } else if (ci == QQPLOT) {
530 	simple_selection(ci, _("gretl: define graph"), do_qq_from_selector, NULL);
531     } else if (ci == LOESS || ci == NADARWAT) {
532 	const char *trstr = (ci == LOESS)? N_("Loess") : N_("Nadaraya-Watson");
533 	gchar *title;
534 
535 	title = g_strdup_printf("gretl: %s", _(trstr));
536 	selection_dialog(ci, title, NULL, do_nonparam_model);
537 	g_free(title);
538     } else {
539 	errbox("selector_callback: code was not recognized");
540     }
541 }
542 
gretl_callback_code(const gchar * s)543 static int gretl_callback_code (const gchar *s)
544 {
545     if (!strcmp(s, "SampleRestrict"))
546 	return SMPLBOOL;
547     if (!strcmp(s, "GENR"))
548 	return GENR;
549     if (!strcmp(s, "VSETMISS"))
550 	return VSETMISS;
551     if (!strcmp(s, "GSETMISS"))
552 	return GSETMISS;
553     if (!strcmp(s, "gmm"))
554 	return GMM;
555     if (!strcmp(s, "mle"))
556 	return MLE;
557     if (!strcmp(s, "nls"))
558 	return NLS;
559     if (!strcmp(s, "system"))
560 	return SYSTEM;
561     if (!strcmp(s, "restrict"))
562 	return RESTRICT;
563     if (!strcmp(s, "MINIBUF"))
564 	return MINIBUF;
565     return 0;
566 }
567 
568 /* callback for menu items, where we want to prepare an "edit dialog"
569    to handle the request */
570 
gretl_callback(GtkAction * action,gpointer data)571 void gretl_callback (GtkAction *action, gpointer data)
572 {
573     windata_t *vwin = (windata_t *) data;
574     GtkWidget *parent = NULL;
575     const char *title = NULL;
576     const char *query = NULL;
577     const char *defstr = NULL;
578     gchar *dynquery = NULL;
579     void (*okfunc)() = NULL;
580     Varclick click = VARCLICK_NONE;
581     int ci;
582 
583     ci = gretl_callback_code(gtk_action_get_name(action));
584 
585     switch (ci) {
586     case GENR:
587 	title = N_("gretl: add var");
588 	if (dataset->n > 5000) {
589 	    query = N_("Enter formula for new variable");
590 	} else {
591 	    query = N_("Enter formula for new variable\n"
592 		       "(or just a name, to enter data manually)");
593 	}
594 	okfunc = do_genr;
595 	click = VARCLICK_INSERT_NAME;
596 	break;
597     case VSETMISS:
598 	title = N_("gretl: missing code");
599 	dynquery = g_strdup_printf(_("Enter value to be read as \"missing\"\n"
600 				     "for the variable \"%s\""),
601 				   dataset->varname[mdata->active_var]);
602 	okfunc = do_variable_setmiss;
603 	break;
604     case GSETMISS:
605 	title = N_("gretl: missing code");
606 	query = N_("Enter value to be read as \"missing\":");
607 	okfunc = do_global_setmiss;
608 	break;
609     case GMM:
610 	title = N_("gretl: GMM");
611 	query = N_("GMM: Specify function and orthogonality conditions:");
612 	okfunc = do_gmm_model;
613 	click = VARCLICK_INSERT_TEXT;
614 	data = NULL;
615 	break;
616     case MLE:
617 	title = N_("gretl: maximum likelihood");
618 	query = N_("MLE: Specify function, and derivatives if possible:");
619 	okfunc = do_mle_model;
620 	click = VARCLICK_INSERT_TEXT;
621 	data = NULL;
622 	break;
623     case NLS:
624 	title = N_("gretl: nonlinear least squares");
625 	query = N_("NLS: Specify function, and derivatives if possible:");
626 	okfunc = do_nls_model;
627 	click = VARCLICK_INSERT_TEXT;
628 	data = NULL;
629 	break;
630     case SYSTEM:
631 	title = N_("gretl: simultaneous equations system");
632 	query = N_("Specify simultaneous equations:");
633 	data = NULL;
634 	okfunc = do_eqn_system;
635 	click = VARCLICK_INSERT_TEXT;
636 	break;
637     case RESTRICT:
638 	title = N_("gretl: linear restrictions");
639 	query = N_("Specify restrictions:");
640 	okfunc = do_restrict;
641 	parent = vwin_toplevel(vwin);
642 	break;
643     case MINIBUF:
644 	title = N_("gretl: command entry");
645 	query = N_("Type a command:");
646 	okfunc = do_minibuf;
647 	break;
648     default:
649 	fprintf(stderr, "gretl_callback: unrecognized action '%s'\n",
650 	       gtk_action_get_name(action));
651 	return;
652     }
653 
654     if (dynquery != NULL) {
655 	edit_dialog(ci, _(title), dynquery, defstr, okfunc, data,
656 		    click, parent);
657 	g_free(dynquery);
658     } else {
659 	edit_dialog(ci, _(title), _(query), defstr, okfunc, data,
660 		    click, parent);
661     }
662 }
663 
menu_boxplot_callback(int varnum)664 void menu_boxplot_callback (int varnum)
665 {
666     const char *opts[] = {
667 	N_("Simple boxplot"),
668 	N_("With confidence interval for median"),
669 	N_("Factorized")
670     };
671     int ret;
672 
673     ret = radio_dialog(_("gretl: define graph"), NULL,
674 		       opts, 3, 0, 0, NULL);
675 
676     if (ret == 0) {
677 	do_boxplot_var(varnum, OPT_NONE);
678     } else if (ret == 1) {
679 	do_boxplot_var(varnum, OPT_O);
680     } else if (ret == 2) {
681 	selector_set_varnum(varnum);
682 	selection_dialog(GR_FBOX, _("gretl: define graph"),
683 			 NULL, do_factorized_boxplot);
684     }
685 }
686 
boxplot_callback(void)687 void boxplot_callback (void)
688 {
689     menu_boxplot_callback(mdata_active_var());
690 }
691 
revise_nl_model(MODEL * pmod,GtkWidget * parent)692 void revise_nl_model (MODEL *pmod, GtkWidget *parent)
693 {
694     const char *title = NULL;
695     const char *query = NULL;
696     const char *defstr;
697     void (*okfunc)() = NULL;
698 
699     switch (pmod->ci) {
700     case GMM:
701 	title = N_("gretl: GMM");
702 	query = N_("GMM: Specify function and orthogonality conditions:");
703 	okfunc = do_gmm_model;
704 	break;
705     case MLE:
706 	title = N_("gretl: maximum likelihood");
707 	query = N_("MLE: Specify function, and derivatives if possible:");
708 	okfunc = do_mle_model;
709 	break;
710     case NLS:
711 	title = N_("gretl: nonlinear least squares");
712 	query = N_("NLS: Specify function, and derivatives if possible:");
713 	okfunc = do_nls_model;
714 	break;
715     }
716 
717     defstr = gretl_model_get_data(pmod, "nlinfo");
718 
719     edit_dialog(pmod->ci, _(title), _(query), defstr, okfunc, pmod,
720 		VARCLICK_INSERT_TEXT, parent);
721 }
722 
revise_system_model(void * ptr,GtkWidget * parent)723 void revise_system_model (void *ptr, GtkWidget *parent)
724 {
725     equation_system *sys = (equation_system *) ptr;
726 
727     edit_dialog(SYSTEM, _("gretl: simultaneous equations system"),
728 		_("Specify simultaneous equations:"), NULL,
729 		do_eqn_system, sys,
730 		VARCLICK_INSERT_TEXT,
731 		parent);
732 }
733 
genr_callback(void)734 void genr_callback (void)
735 {
736     const char *msg;
737 
738     if (dataset->n > 5000) {
739 	msg = N_("Enter formula for new variable");
740     } else {
741 	msg = N_("Enter formula for new variable\n"
742 		 "(or just a name, to enter data manually)");
743     }
744 
745     edit_dialog(GENR, _("gretl: add var"), _(msg),
746 		NULL, do_genr, NULL,
747 		VARCLICK_INSERT_NAME, NULL);
748 }
749 
minibuf_callback(void)750 void minibuf_callback (void)
751 {
752     edit_dialog(MINIBUF, _("gretl: command entry"),
753 		_("Type a command:"), NULL,
754 		do_minibuf, NULL,
755 		VARCLICK_NONE, NULL);
756 }
757 
newdata_callback(void)758 void newdata_callback (void)
759 {
760     if (!dataset_locked()) {
761 	new_data_structure_dialog();
762     }
763 }
764 
edit_gfn_callback(void)765 void edit_gfn_callback (void)
766 {
767     gchar *syspath = NULL;
768     gchar *dotpath = NULL;
769     gchar *startdir = NULL;
770     int edit_sys_ok = 0;
771     int edit_dot_ok = 0;
772     int n_opts = 1;
773 
774     syspath = g_strdup_printf("%sfunctions", gretl_home());
775     if (gretl_write_access(syspath) == 0) {
776 	edit_sys_ok = 1;
777 	n_opts++;
778     }
779 
780     dotpath = g_strdup_printf("%sfunctions", gretl_dotdir());
781     if (gretl_write_access(dotpath) == 0) {
782 	edit_dot_ok = 1;
783 	n_opts++;
784     }
785 
786     if (n_opts > 1) {
787 	const char *opts[n_opts];
788 	int resp;
789 
790 	if (edit_sys_ok && edit_dot_ok) {
791 	    opts[0] = N_("system gfn directory");
792 	    opts[1] = N_("personal gfn directory");
793 	    opts[2] = N_("current working directory");
794 	} else if (edit_sys_ok) {
795 	    opts[0] = N_("system gfn directory");
796 	    opts[1] = N_("current working directory");
797 	} else if (edit_dot_ok) {
798 	    opts[0] = N_("personal gfn directory");
799 	    opts[1] = N_("current working directory");
800 	}
801 
802 	resp = radio_dialog(_("Open .gfn file"), _("Start looking in:"),
803 			    opts, n_opts, 0, 0, NULL);
804 	if (resp < 0) {
805 	    /* canceled */
806 	    return;
807 	}
808 
809 	if (edit_sys_ok && edit_dot_ok) {
810 	    startdir = resp == 0 ? syspath : resp == 1 ? dotpath : NULL;
811 	} else if (edit_sys_ok) {
812 	    startdir = resp == 0 ? syspath : NULL;
813 	} else if (edit_dot_ok) {
814 	    startdir = resp == 0 ? dotpath : NULL;
815 	}
816     }
817 
818     if (startdir != NULL) {
819 	file_selector_with_startdir(OPEN_GFN, startdir, NULL);
820     } else {
821 	file_selector(OPEN_GFN, FSEL_DATA_NONE, NULL);
822     }
823 
824     g_free(syspath);
825     g_free(dotpath);
826 }
827 
xcorrgm_callback(void)828 void xcorrgm_callback (void)
829 {
830     if (mdata_selection_count() == 2) {
831 	do_xcorrgm(NULL);
832     } else {
833 	gchar *title = g_strdup_printf("gretl: %s", _("cross-correlogram"));
834 
835 	simple_selection(XCORRGM, title, do_xcorrgm, NULL);
836 	g_free(title);
837     }
838 }
839 
cond_number_callback(void)840 void cond_number_callback (void)
841 {
842     gretl_matrix *X = NULL;
843     gretl_matrix *XX = NULL;
844     gretl_matrix *chk = NULL;
845     int *list = main_window_selection_as_list();
846     int resp, err = 0;
847 
848     resp = yes_no_cancel_dialog(_("Collinearity check"),
849 				_("Include a constant?"),
850 				NULL);
851     if (resp < 0) {
852 	/* canceled */
853 	return;
854     }
855 
856     if (resp == GRETL_YES) {
857 	int *lplus = gretl_list_new(list[0] + 1);
858 	int i;
859 
860 	lplus[1] = 0;
861 	for (i=2; i<=lplus[0]; i++) {
862 	    lplus[i] = list[i-1];
863 	}
864 	free(list);
865 	list = lplus;
866     }
867 
868     X = gretl_matrix_data_subset(list, dataset,
869 				 dataset->t1,
870 				 dataset->t2,
871 				 M_MISSING_SKIP,
872 				 &err);
873     if (!err) {
874 	XX = gretl_matrix_XTX_new(X);
875 	if (XX == NULL) {
876 	    err = E_ALLOC;
877 	} else {
878 	    chk = gretl_matrix_copy(XX);
879 	    err = gretl_invert_symmetric_matrix(XX);
880 	    if (err == E_NOTPD && chk != NULL) {
881 		int r, sverr = 0;
882 
883 		r = gretl_matrix_rank(chk, &sverr);
884 		if (!sverr && r < XX->cols) {
885 		    infobox_printf(_("X'X is singular to machine precision:\n"
886 				     "it is of dimension %d but rank %d."),
887 				   XX->rows, r);
888 		    goto finish;
889 		}
890 	    }
891 	}
892     }
893 
894     if (err) {
895 	gui_errmsg(err);
896     } else {
897 	gretl_matrix *(*bkwfunc) (const gretl_matrix *, gretl_array *,
898 				  PRN *, int *);
899 	PRN *prn = NULL;
900 
901 	bkwfunc = gui_get_plugin_function("bkw_matrix");
902 	if (bkwfunc != NULL && bufopen(&prn) == 0) {
903 	    (*bkwfunc)(XX, NULL, prn, &err);
904 	    if (err) {
905 		gui_errmsg(err);
906 	    } else {
907 		view_buffer(prn, 78, 400, _("Collinearity check"), PRINT, NULL);
908 		/* record command? */
909 	    }
910 	}
911     }
912 
913  finish:
914 
915     gretl_matrix_free(X);
916     gretl_matrix_free(XX);
917     gretl_matrix_free(chk);
918     free(list);
919 }
920 
map_save_callback(void)921 void map_save_callback (void)
922 {
923     file_selector(WRITE_MAP, FSEL_DATA_NONE, NULL);
924 }
925 
nist_verbosity(GtkAction * action)926 static int nist_verbosity (GtkAction *action)
927 {
928     const gchar *s = gtk_action_get_name(action);
929 
930     if (!strcmp(s, "NistVVerbose"))
931 	return 2;
932     else if (!strcmp(s, "NistVerbose"))
933 	return 1;
934     else
935 	return 0;
936 }
937 
do_nistcheck(GtkAction * action)938 void do_nistcheck (GtkAction *action)
939 {
940     int (*run_nist_tests)(const char *, const char *, int);
941     gchar *datadir = NULL;
942     gchar *fname = NULL;
943 
944     run_nist_tests = gui_get_plugin_function("run_nist_tests");
945     if (run_nist_tests == NULL) {
946 	return;
947     }
948 
949     datadir = g_strdup_printf("%sdata%s", gretl_home(), SLASHSTR);
950     fname = g_strdup_printf("%snist.out", gretl_dotdir());
951 
952     (*run_nist_tests)(datadir, fname, nist_verbosity(action));
953 
954     view_file(fname, 0, 1, 78, 400, VIEW_CODEBOOK);
955 
956     g_free(datadir);
957     g_free(fname);
958 }
959 
mailer_help(void)960 static void mailer_help (void)
961 {
962     show_gui_help(MAILHELP);
963 }
964 
send_attachment(const char * filename)965 void send_attachment (const char *filename)
966 {
967     int (*email_file) (const char *, GtkWindow *, void *);
968     int err = 0;
969 
970     email_file = gui_get_plugin_function("email_file");
971 
972     if (email_file != NULL) {
973 	set_plugin_dialog_open(1);
974 	err = email_file(filename, GTK_WINDOW(mdata->main), mailer_help);
975 	set_plugin_dialog_open(0);
976 	if (err) {
977 	    gui_errmsg(err);
978 	}
979     }
980 }
981