1 /*
2  *  gretl -- Gnu Regression, Econometrics and Time-series Library
3  *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include "gretl.h"
21 #include "version.h"
22 #include "dlgutils.h"
23 #include "selector.h"
24 #include "gretl_func.h"
25 #include "monte_carlo.h"
26 #include "uservar.h"
27 #include "cmd_private.h"
28 #include "gretl_www.h"
29 #include "gretl_xml.h"
30 #include "gretl_typemap.h"
31 #include "matrix_extra.h"
32 #include "gretl_zip.h"
33 #include "addons_utils.h"
34 #include "database.h"
35 #include "guiprint.h"
36 #include "ssheet.h"
37 #include "datafiles.h"
38 #include "toolbar.h"
39 #include "obsbutton.h"
40 #include "cmdstack.h"
41 #include "winstack.h"
42 #include "treeutils.h"
43 #include "gfn_arglists.h"
44 #include "gpt_control.h"
45 #include "fnsave.h"
46 #include "fncall.h"
47 
48 #include <errno.h>
49 
50 #define FCDEBUG 0
51 #define PKG_DEBUG 0
52 #define MPKG_DEBUG 0
53 
54 enum {
55     SHOW_GUI_MAIN = 1 << 0,
56     MODEL_CALL    = 1 << 1,
57     DATA_ACCESS   = 1 << 2
58 };
59 
60 typedef struct call_info_ call_info;
61 
62 struct call_info_ {
63     GtkWidget *dlg;      /* main dialog */
64     GtkWidget *top_hbox; /* upper hbox in dialog */
65     windata_t *vwin;     /* gretl caller window */
66     GList *vsels;        /* series argument selectors */
67     GList *lsels;        /* list argument selectors */
68     GList *msels;        /* matrix arg selectors */
69     GList *ssels;        /* scalar arg selectors */
70     GList *bsels;        /* bundle arg selectors */
71     GList *asels;        /* array arg selectors */
72     fnpkg *pkg;          /* the active function package */
73     gchar *pkgname;      /* and its name */
74     gchar *pkgver;       /* plus its version */
75     int *publist;        /* list of public interfaces */
76     int iface;           /* selected interface */
77     int flags;           /* misc. info on package */
78     const ufunc *func;   /* the function we're calling */
79     DataReq dreq;        /* the function's data requirement */
80     int modelreq;        /* the function's model (command) requirement */
81     int minver;          /* minimum gretl version for pkg */
82     int n_params;        /* its number of parameters */
83     char rettype;        /* its return type */
84     gchar **args;        /* its arguments */
85     gchar *ret;          /* return assignment name */
86     gchar *label;        /* the function's label */
87 };
88 
89 #define scalar_arg(t) (t == GRETL_TYPE_DOUBLE || t == GRETL_TYPE_SCALAR_REF)
90 #define series_arg(t) (t == GRETL_TYPE_SERIES || t == GRETL_TYPE_SERIES_REF)
91 #define matrix_arg(t) (t == GRETL_TYPE_MATRIX || t == GRETL_TYPE_MATRIX_REF)
92 #define bundle_arg(t) (t == GRETL_TYPE_BUNDLE || t == GRETL_TYPE_BUNDLE_REF)
93 #define array_arg(t)  (t == GRETL_TYPE_ARRAY  || t == GRETL_TYPE_ARRAY_REF)
94 
95 #define AUTOLIST "LTmp___"
96 #define DUMLIST  "LRetTmp___"
97 #define SELNAME "selected series"
98 
99 static GtkWidget *open_fncall_dlg;
100 static gboolean close_on_OK = TRUE;
101 static gboolean allow_full_data = TRUE;
102 
103 static void fncall_exec_callback (GtkWidget *w, call_info *cinfo);
104 static void maybe_record_include (const char *pkgname, int model_id);
105 static void set_genr_model_from_vwin (windata_t *vwin);
106 static void maybe_open_sample_script (call_info *cinfo,
107 				      windata_t *vwin,
108 				      const char *path);
109 
glib_str_array_new(int n)110 static gchar **glib_str_array_new (int n)
111 {
112     gchar **S = g_malloc0(n * sizeof *S);
113 
114     return S;
115 }
116 
glib_str_array_free(gchar ** S,int n)117 static void glib_str_array_free (gchar **S, int n)
118 {
119     if (S != NULL) {
120 	int i;
121 
122 	for (i=0; i<n; i++) {
123 	    g_free(S[i]);
124 	}
125 	g_free(S);
126     }
127 }
128 
caller_is_model_window(windata_t * vwin)129 static int caller_is_model_window (windata_t *vwin)
130 {
131     if (vwin != NULL &&
132 	(vwin->role == VIEW_MODEL ||
133 	 vwin->role == VAR ||
134 	 vwin->role == VECM ||
135 	 vwin->role == SYSTEM) &&
136 	vwin->data != NULL) {
137 	return 1;
138     }
139 
140     return 0;
141 }
142 
cinfo_new(fnpkg * pkg,windata_t * vwin)143 static call_info *cinfo_new (fnpkg *pkg, windata_t *vwin)
144 {
145     call_info *cinfo = mymalloc(sizeof *cinfo);
146 
147     if (cinfo == NULL) {
148 	return NULL;
149     }
150 
151     cinfo->pkg = pkg;
152     cinfo->pkgname = NULL;
153     cinfo->pkgver = NULL;
154 
155     cinfo->vwin = vwin;
156     cinfo->dlg = NULL;
157     cinfo->top_hbox = NULL;
158 
159     cinfo->publist = NULL;
160     cinfo->iface = -1;
161     cinfo->flags = 0;
162 
163     if (caller_is_model_window(vwin)) {
164 	cinfo->flags |= MODEL_CALL;
165     }
166 
167     cinfo->vsels = NULL;
168     cinfo->lsels = NULL;
169     cinfo->msels = NULL;
170     cinfo->bsels = NULL;
171     cinfo->asels = NULL;
172     cinfo->ssels = NULL;
173 
174     cinfo->func = NULL;
175     cinfo->n_params = 0;
176 
177     cinfo->rettype = GRETL_TYPE_NONE;
178 
179     cinfo->args = NULL;
180     cinfo->ret = NULL;
181 
182     cinfo->dreq = FN_NEEDS_DATA;
183     cinfo->modelreq = 0;
184     cinfo->label = NULL;
185 
186     return cinfo;
187 }
188 
189 static int *mylist; /* custom list constructed by gfn */
190 
lmaker_run(ufunc * func,call_info * cinfo)191 static int lmaker_run (ufunc *func, call_info *cinfo)
192 {
193     fncall *fcall = NULL;
194     int *biglist = NULL;
195     int *list = NULL;
196     PRN *prn;
197     int err = 0;
198 
199     free(mylist);
200     mylist = NULL;
201 
202     fcall = fncall_new(func, 0);
203     if (fn_n_params(func) == 1) {
204 	/* pass full dataset list as argument */
205 	biglist = full_var_list(dataset, NULL);
206 	if (biglist != NULL) {
207 	    push_anon_function_arg(fcall, GRETL_TYPE_LIST, biglist);
208 	}
209     }
210 
211     prn = gretl_print_new(GRETL_PRINT_STDERR, &err);
212     if (cinfo->flags & MODEL_CALL) {
213 	set_genr_model_from_vwin(cinfo->vwin);
214     }
215     err = gretl_function_exec(fcall, GRETL_TYPE_LIST, dataset,
216 			      &list, NULL, prn);
217     if (cinfo->flags & MODEL_CALL) {
218 	unset_genr_model();
219     }
220     gretl_print_destroy(prn);
221 
222     if (err) {
223 	gui_errmsg(err);
224     }
225 
226     if (!err && list == NULL) {
227 	err = 1;
228     }
229 
230     if (!err) {
231 	mylist = list;
232 	list = NULL;
233     }
234 
235     free(list);
236     free(biglist);
237 
238     return err;
239 }
240 
cinfo_args_init(call_info * cinfo)241 static int cinfo_args_init (call_info *cinfo)
242 {
243     int err = 0;
244 
245     cinfo->args = NULL;
246     cinfo->ret = NULL;
247 
248     if (cinfo->n_params > 0) {
249 	cinfo->args = glib_str_array_new(cinfo->n_params);
250 	if (cinfo->args == NULL) {
251 	    err = E_ALLOC;
252 	}
253     }
254 
255     return err;
256 }
257 
cinfo_free(call_info * cinfo)258 static void cinfo_free (call_info *cinfo)
259 {
260     if (cinfo->n_params > 0) {
261 	glib_str_array_free(cinfo->args, cinfo->n_params);
262     }
263     if (cinfo->ret != NULL) {
264 	g_free(cinfo->ret);
265     }
266     if (cinfo->vsels != NULL) {
267 	g_list_free(cinfo->vsels);
268     }
269     if (cinfo->lsels != NULL) {
270 	g_list_free(cinfo->lsels);
271     }
272     if (cinfo->msels != NULL) {
273 	g_list_free(cinfo->msels);
274     }
275     if (cinfo->bsels != NULL) {
276 	g_list_free(cinfo->bsels);
277     }
278     if (cinfo->asels != NULL) {
279 	g_list_free(cinfo->asels);
280     }
281     if (cinfo->ssels != NULL) {
282 	g_list_free(cinfo->ssels);
283     }
284 
285     g_free(cinfo->pkgname);
286     g_free(cinfo->pkgver);
287 
288     g_free(cinfo->label);
289     free(cinfo->publist);
290     free(cinfo);
291 }
292 
check_args(call_info * cinfo)293 static int check_args (call_info *cinfo)
294 {
295     int i;
296 
297     if (cinfo->args != NULL) {
298 	for (i=0; i<cinfo->n_params; i++) {
299 	    if (cinfo->args[i] == NULL) {
300 		if (fn_param_optional(cinfo->func, i)) {
301 		    cinfo->args[i] = g_strdup("null");
302 		} else {
303 		    errbox_printf(_("Argument %d (%s) is missing"), i + 1,
304 				  fn_param_name(cinfo->func, i));
305 		    return 1;
306 		}
307 	    }
308 	}
309     }
310 
311     return 0;
312 }
313 
fncall_dialog_destruction(GtkWidget * w,call_info * cinfo)314 static void fncall_dialog_destruction (GtkWidget *w, call_info *cinfo)
315 {
316     /* turn off out-of-sample data access */
317     allow_full_data_access(0);
318     cinfo_free(cinfo);
319     open_fncall_dlg = NULL;
320 }
321 
fncall_close(GtkWidget * w,call_info * cinfo)322 static void fncall_close (GtkWidget *w, call_info *cinfo)
323 {
324     gtk_widget_destroy(cinfo->dlg);
325 }
326 
label_hbox(call_info * cinfo,GtkWidget * w)327 static GtkWidget *label_hbox (call_info *cinfo, GtkWidget *w)
328 {
329     GtkWidget *hbox, *lbl;
330     gchar *buf = NULL;
331 
332     hbox = gtk_hbox_new(FALSE, 5);
333     gtk_box_pack_start(GTK_BOX(w), hbox, FALSE, FALSE, 5);
334 
335     if (cinfo->label != NULL) {
336 	buf = g_markup_printf_escaped("<span weight=\"bold\">%s</span>",
337 				      _(cinfo->label));
338     } else {
339 	const char *funcname;
340 
341 	funcname = user_function_name_by_index(cinfo->iface);
342 	buf = g_markup_printf_escaped("<span weight=\"bold\">%s</span>",
343 				      funcname);
344     }
345 
346     lbl = gtk_label_new(NULL);
347     gtk_label_set_markup(GTK_LABEL(lbl), buf);
348     g_free(buf);
349 
350     gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
351     gtk_widget_show(lbl);
352 
353     return hbox;
354 }
355 
update_double_arg(GtkWidget * w,call_info * cinfo)356 static gboolean update_double_arg (GtkWidget *w, call_info *cinfo)
357 {
358     double val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
359     int i = widget_get_int(w, "argnum");
360 
361     g_free(cinfo->args[i]);
362     cinfo->args[i] = g_strdup_printf("%g", val);
363 
364     return FALSE;
365 }
366 
update_int_arg(GtkWidget * w,call_info * cinfo)367 static gboolean update_int_arg (GtkWidget *w, call_info *cinfo)
368 {
369     int val = (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
370     int i = widget_get_int(w, "argnum");
371 
372     g_free(cinfo->args[i]);
373     cinfo->args[i] = g_strdup_printf("%d", val);
374 
375     return FALSE;
376 }
377 
update_bool_arg(GtkWidget * w,call_info * cinfo)378 static gboolean update_bool_arg (GtkWidget *w, call_info *cinfo)
379 {
380     int i = widget_get_int(w, "argnum");
381 
382     g_free(cinfo->args[i]);
383     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
384 	cinfo->args[i] = g_strdup("1");
385     } else {
386 	cinfo->args[i] = g_strdup("0");
387     }
388 
389     return FALSE;
390 }
391 
combo_box_get_trimmed_text(GtkComboBox * combo)392 static gchar *combo_box_get_trimmed_text (GtkComboBox *combo)
393 {
394     gchar *s = combo_box_get_active_text(combo);
395     gchar *ret = NULL;
396 
397     if (s != NULL && *s != '\0') {
398 	while (isspace(*s)) s++;
399 	if (*s != '\0') {
400 	    int i, len = strlen(s);
401 
402 	    for (i=len-1; i>0; i--) {
403 		if (!isspace(s[i])) break;
404 		len--;
405 	    }
406 
407 	    if (len > 0) {
408 		ret = g_strndup(s, len);
409 	    }
410 	}
411     }
412 
413     g_free(s);
414 
415     return ret;
416 }
417 
update_arg(GtkComboBox * combo,call_info * cinfo)418 static gboolean update_arg (GtkComboBox *combo,
419 			    call_info *cinfo)
420 {
421     int i = widget_get_int(combo, "argnum");
422     char *s;
423 
424     g_free(cinfo->args[i]);
425     s = cinfo->args[i] = combo_box_get_trimmed_text(combo);
426 
427     if (s != NULL && fn_param_type(cinfo->func, i) == GRETL_TYPE_DOUBLE) {
428 	if (isdigit(*s) || *s == '-' || *s == '+' || *s == ',') {
429 	    gretl_charsub(s, ',', '.');
430 	}
431     }
432 
433     return FALSE;
434 }
435 
update_return(GtkComboBox * combo,call_info * cinfo)436 static gboolean update_return (GtkComboBox *combo,
437 			       call_info *cinfo)
438 {
439     g_free(cinfo->ret);
440     cinfo->ret = combo_box_get_trimmed_text(combo);
441 
442     return FALSE;
443 }
444 
445 /* simple heuristic for whether or not a series probably
446    represents a stochastic variable
447 */
448 
probably_stochastic(int v)449 static int probably_stochastic (int v)
450 {
451     int ret = 1;
452 
453     if (sample_size(dataset) >= 3) {
454 	/* rule out vars that seem to be integer-valued with
455 	   a constant increment */
456 	int t = dataset->t1;
457 	double d1 = dataset->Z[v][t+1] - dataset->Z[v][t];
458 	double d2 = dataset->Z[v][t+2] - dataset->Z[v][t+1];
459 
460 	if (d1 == floor(d1) && d2 == d1) {
461 	    ret = 0;
462 	}
463     }
464 
465     return ret;
466 }
467 
add_names_for_type(GList * list,GretlType type)468 static GList *add_names_for_type (GList *list, GretlType type)
469 {
470     GList *tlist = user_var_names_for_type(type);
471     GList *tail = tlist;
472 
473     while (tail != NULL) {
474 	list = g_list_append(list, tail->data);
475 	tail = tail->next;
476     }
477 
478     if (type == GRETL_TYPE_LIST && mdata_selection_count() > 1) {
479 	list = g_list_append(list, SELNAME);
480     }
481 
482     g_list_free(tlist);
483 
484     return list;
485 }
486 
add_series_names(GList * list)487 static GList *add_series_names (GList *list)
488 {
489     int i;
490 
491     for (i=1; i<dataset->v; i++) {
492 	if (!series_is_hidden(dataset, i)) {
493 	    list = g_list_append(list, (gpointer) dataset->varname[i]);
494 	}
495     }
496 
497     list = g_list_append(list, (gpointer) dataset->varname[0]);
498 
499     return list;
500 }
501 
get_selection_list(int type)502 static GList *get_selection_list (int type)
503 {
504     GList *list = NULL;
505 
506     if (series_arg(type)) {
507 	list = add_series_names(list);
508     } else if (scalar_arg(type)) {
509 	list = add_names_for_type(list, GRETL_TYPE_DOUBLE);
510     } else if (type == GRETL_TYPE_LIST) {
511 	list = add_names_for_type(list, GRETL_TYPE_LIST);
512     } else if (matrix_arg(type)) {
513 	list = add_names_for_type(list, GRETL_TYPE_MATRIX);
514     } else if (bundle_arg(type)) {
515 	list = add_names_for_type(list, GRETL_TYPE_BUNDLE);
516     } else if (array_arg(type)) {
517 	list = add_names_for_type(list, GRETL_TYPE_ARRAY);
518     }
519 
520     return list;
521 }
522 
make_help_viewer(const char * fnname,const char * pdfname,PRN * prn)523 static windata_t *make_help_viewer (const char *fnname,
524 				    const char *pdfname,
525 				    PRN *prn)
526 {
527     windata_t *vwin;
528     gchar *title;
529     char *buf;
530 
531     if (pdfname != NULL) {
532 	/* append a link to the PDF file */
533 	gchar *localpdf = g_strdup(pdfname);
534 	gchar *p = strrchr(localpdf, '.');
535 
536 	*p = '\0';
537 	strcat(p, ".pdf");
538 	pprintf(prn, "<@itl=\"Documentation\">: <@adb=\"%s\">\n", localpdf);
539 	g_free(localpdf);
540     }
541 
542     buf = gretl_print_steal_buffer(prn);
543     title = g_strdup_printf(_("help on %s"), fnname);
544     vwin = view_formatted_text_buffer(title, buf, 76, 350, VIEW_PKG_INFO);
545     g_free(title);
546     free(buf);
547 
548     return vwin;
549 }
550 
fncall_help(GtkWidget * w,call_info * cinfo)551 static void fncall_help (GtkWidget *w, call_info *cinfo)
552 {
553     char *pdfname = NULL;
554     int show_ghlp = 0;
555     int have_pdf = 0;
556 
557     if ((cinfo->flags & SHOW_GUI_MAIN) &&
558 	function_package_has_gui_help(cinfo->pkg)) {
559 	show_ghlp = 1;
560     }
561 
562     have_pdf = function_package_has_PDF_doc(cinfo->pkg, &pdfname);
563 
564     if (have_pdf && !show_ghlp) {
565 	/* simple: just show PDF doc */
566 	FILE *fp = gretl_fopen(pdfname, "r");
567 
568 	if (fp != NULL) {
569 	    fclose(fp);
570 	    gretl_show_pdf(pdfname, NULL);
571 	} else {
572 	    gui_errmsg(E_FOPEN);
573 	}
574     } else {
575 	/* show help text, either "plain" or GUI */
576 	const char *fnname;
577 	PRN *prn = NULL;
578 	gretlopt opt = OPT_M;
579 	int err;
580 
581 	if (bufopen(&prn)) {
582 	    return;
583 	}
584 
585 	if (show_ghlp) {
586 	    opt |= OPT_G;
587 	}
588 
589 	fnname = user_function_name_by_index(cinfo->iface);
590 	err = user_function_help(fnname, opt, prn);
591 
592 	if (err) {
593 	    gretl_print_destroy(prn);
594 	    errbox("Couldn't find any help");
595 	} else {
596 	    make_help_viewer(fnname, pdfname, prn);
597 	    gretl_print_destroy(prn);
598 	}
599     }
600 
601     free(pdfname);
602 }
603 
combo_list_index(const gchar * s,GList * list)604 static int combo_list_index (const gchar *s, GList *list)
605 {
606     GList *tmp = list;
607     int i;
608 
609     for (i=0; tmp != NULL; i++) {
610 	if (!strcmp(s, (gchar *) tmp->data)) {
611 	    return i;
612 	}
613 	tmp = tmp->next;
614     }
615 
616     return -1;
617 }
618 
619 /* Update the combo argument selector(s) for series, matrices
620    lists or scalars after defining a new variable of one of
621    these types.
622 */
623 
update_combo_selectors(call_info * cinfo,GtkWidget * refsel,int ptype)624 static void update_combo_selectors (call_info *cinfo,
625 				    GtkWidget *refsel,
626 				    int ptype)
627 {
628     GList *sellist, *newlist;
629     int llen;
630 
631     /* get the list of relevant selectors and the
632        list of relevant variables to put into the
633        selectors
634     */
635 
636     if (ptype == GRETL_TYPE_MATRIX) {
637 	sellist = g_list_first(cinfo->msels);
638     } else if (ptype == GRETL_TYPE_BUNDLE) {
639 	sellist = g_list_first(cinfo->bsels);
640     } else if (ptype == GRETL_TYPE_ARRAY) {
641 	sellist = g_list_first(cinfo->asels);
642     } else if (ptype == GRETL_TYPE_LIST) {
643 	sellist = g_list_first(cinfo->lsels);
644     } else if (ptype == GRETL_TYPE_DOUBLE) {
645 	sellist = g_list_first(cinfo->ssels);
646     } else {
647 	sellist = g_list_first(cinfo->vsels);
648     }
649 
650     newlist = get_selection_list(ptype);
651     llen = g_list_length(newlist);
652 
653     while (sellist != NULL) {
654 	/* iterate over the affected selectors */
655 	GtkComboBox *sel = GTK_COMBO_BOX(sellist->data);
656 	int target = GTK_WIDGET(sel) == refsel;
657 	int null_OK, selpos;
658 	gchar *saved = NULL;
659 
660 	/* target == 1 means that we're looking at the
661 	   selector whose button was clicked to add a
662 	   variable: for this selector the newly added
663 	   variable should be marked as selected;
664 	   otherwise we modify the list of choices but
665 	   preserve the previous selection.
666 	*/
667 
668 	if (!target) {
669 	    /* make a record of the old selected item */
670 	    saved = combo_box_get_active_text(sel);
671 	}
672 
673 	depopulate_combo_box(sel);
674 	set_combo_box_strings_from_list(GTK_WIDGET(sel), newlist);
675 	null_OK = widget_get_int(sel, "null_OK");
676 	if (null_OK) {
677 	    combo_box_append_text(sel, "null");
678 	}
679 
680 	if (target) {
681 	    /* select the newly added var, which will be at the
682 	       end, or thereabouts */
683 	    selpos = llen - 1;
684 	    if (series_arg(ptype)) {
685 		selpos--; /* the const is always in last place */
686 	    }
687 	    gtk_combo_box_set_active(sel, selpos);
688 	} else if (saved != NULL) {
689 	    /* reinstate the previous selection */
690 	    selpos = combo_list_index(saved, newlist);
691 	    if (selpos < 0) {
692 		if (*saved == '\0') {
693 		    combo_box_prepend_text(sel, "");
694 		    selpos = 0;
695 		} else if (!strcmp(saved, "null")) {
696 		    selpos = llen;
697 		}
698 	    }
699 	    gtk_combo_box_set_active(sel, selpos);
700 	    g_free(saved);
701 	} else {
702 	    /* reinstate empty selection */
703 	    gtk_combo_box_set_active(sel, -1);
704 	}
705 
706 	sellist = sellist->next;
707     }
708 
709     g_list_free(newlist);
710 }
711 
do_make_list(selector * sr)712 static int do_make_list (selector *sr)
713 {
714     const char *buf = selector_list(sr);
715     const char *lname = selector_entry_text(sr);
716     gpointer data = selector_get_data(sr);
717     call_info *cinfo = NULL;
718     GtkWidget *aux = NULL;
719     const char *msg = NULL;
720     PRN *prn = NULL;
721     int *list = NULL;
722     int empty = 0;
723     int nl, err = 0;
724 
725     if (lname == NULL || *lname == '\0') {
726 	errbox(_("No name was given for the list"));
727 	return 1;
728     }
729 
730     err = gui_validate_varname(lname, GRETL_TYPE_LIST,
731 			       selector_get_window(sr));
732     if (err) {
733 	return err;
734     }
735 
736     if (data != NULL) {
737 	/* called from elsewhere in fncall.c */
738 	GtkWidget *entry = GTK_WIDGET(data);
739 
740 	cinfo = g_object_get_data(G_OBJECT(entry), "cinfo");
741 	aux = g_object_get_data(G_OBJECT(entry), "sel");
742     }
743 
744     /* record initial status */
745     nl = n_user_lists();
746 
747     if (buf == NULL || *buf == '\0') {
748 	int resp;
749 
750 	resp = yes_no_dialog("gretl", _("Really create an empty list?"),
751 			     selector_get_window(sr));
752 	if (resp == GRETL_YES) {
753 	    list = gretl_null_list();
754 	    if (list == NULL) {
755 		err = E_ALLOC;
756 	    } else {
757 		empty = 1;
758 	    }
759 	} else {
760 	    /* canceled */
761 	    return 0;
762 	}
763     } else {
764 	list = command_list_from_string(buf, &err);
765     }
766 
767     if (err) {
768 	gui_errmsg(err);
769 	return err;
770     }
771 
772     if (cinfo != NULL) {
773 	/* don't bother with "Added list..." message */
774 	err = remember_list(list, lname, NULL);
775 	if (err) {
776 	    gui_errmsg(err);
777 	}
778     } else {
779 	if (bufopen(&prn)) {
780 	    free(list);
781 	    return 1;
782 	}
783 	err = remember_list(list, lname, prn);
784 	msg = gretl_print_get_buffer(prn);
785 	if (err) {
786 	    errbox(msg);
787 	}
788     }
789 
790     if (!err) {
791 	lib_command_sprintf("list %s =%s", lname, empty ? " null" : buf);
792 	record_command_verbatim();
793 	gtk_widget_hide(selector_get_window(sr));
794 	if (cinfo != NULL) {
795 	    if (n_user_lists() > nl) {
796 		update_combo_selectors(cinfo, aux, GRETL_TYPE_LIST);
797 	    }
798 	} else {
799 	    infobox(msg);
800 	}
801     }
802 
803     free(list);
804 
805     if (prn != NULL) {
806 	gretl_print_destroy(prn);
807     }
808 
809     return err;
810 }
811 
launch_list_maker(GtkWidget * button,GtkWidget * entry)812 static void launch_list_maker (GtkWidget *button, GtkWidget *entry)
813 {
814     call_info *cinfo;
815 
816     cinfo = g_object_get_data(G_OBJECT(button), "cinfo");
817     g_object_set_data(G_OBJECT(cinfo->dlg), "button", button);
818     simple_selection_with_data(DEFINE_LIST, _("Define list"),
819 			       do_make_list, cinfo->dlg,
820 			       entry);
821 }
822 
gui_define_list(void)823 void gui_define_list (void)
824 {
825     simple_selection_with_data(DEFINE_LIST, _("Define list"),
826 			       do_make_list, NULL, NULL);
827 }
828 
launch_matrix_maker(GtkWidget * button,call_info * cinfo)829 static void launch_matrix_maker (GtkWidget *button, call_info *cinfo)
830 {
831     int n = n_user_matrices();
832 
833     if (!strcmp(cinfo->pkgname, "SVAR")) {
834 	widget_set_int(cinfo->dlg, "matrix-no-series", 1);
835     }
836 
837     g_object_set_data(G_OBJECT(cinfo->dlg), "button", button);
838     fncall_add_matrix(cinfo->dlg);
839 
840     if (n_user_matrices() > n) {
841 	GtkWidget *sel = g_object_get_data(G_OBJECT(button), "combo");
842 
843 	update_combo_selectors(cinfo, sel, GRETL_TYPE_MATRIX);
844     }
845 
846     gtk_window_present(GTK_WINDOW(cinfo->dlg));
847 }
848 
849 /* callback after invoking "genr" via the "+" button
850    beside a combo argument selector */
851 
fncall_register_genr(int addv,gpointer p)852 void fncall_register_genr (int addv, gpointer p)
853 {
854     GtkWidget *combo = p;
855     GtkWidget *entry = gtk_bin_get_child(GTK_BIN(combo));
856     call_info *cinfo = g_object_get_data(G_OBJECT(entry), "cinfo");
857     int ptype = widget_get_int(combo, "ptype");
858 
859     if (addv > 0) {
860 	update_combo_selectors(cinfo, combo, ptype);
861     }
862 
863     gtk_window_present(GTK_WINDOW(cinfo->dlg));
864 }
865 
launch_series_maker(GtkWidget * button,call_info * cinfo)866 static void launch_series_maker (GtkWidget *button, call_info *cinfo)
867 {
868     GtkWidget *combo = g_object_get_data(G_OBJECT(button), "combo");
869 
870     edit_dialog(GENR, _("add series"),
871 		_("Enter name=formula for new series"), NULL,
872 		do_fncall_genr, combo,
873 		VARCLICK_INSERT_NAME, cinfo->dlg);
874 }
875 
launch_scalar_maker(GtkWidget * button,call_info * cinfo)876 static void launch_scalar_maker (GtkWidget *button, call_info *cinfo)
877 {
878     GtkWidget *combo = g_object_get_data(G_OBJECT(button), "combo");
879 
880     edit_dialog(GENR, _("add scalar"),
881 		_("Enter name=formula for new scalar"), NULL,
882 		do_fncall_genr, combo,
883 		VARCLICK_INSERT_NAME, cinfo->dlg);
884 }
885 
bool_arg_selector(call_info * cinfo,int i,const char * prior_val)886 static GtkWidget *bool_arg_selector (call_info *cinfo, int i,
887 				     const char *prior_val)
888 {
889     GtkWidget *button;
890     int active;
891 
892     if (prior_val != NULL) {
893 	active = *prior_val == '1';
894     } else {
895 	double deflt = fn_param_default(cinfo->func, i);
896 
897 	active = !na(deflt) && deflt != 0.0;
898     }
899 
900     button = gtk_check_button_new();
901     widget_set_int(button, "argnum", i);
902     g_object_set_data(G_OBJECT(button), "cinfo", cinfo);
903     g_signal_connect(G_OBJECT(button), "toggled",
904 		     G_CALLBACK(update_bool_arg), cinfo);
905     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active);
906     cinfo->args[i] = g_strdup((active)? "1" : "0");
907 
908     return button;
909 }
910 
update_xlist_arg(GtkComboBox * combo,call_info * cinfo)911 static void update_xlist_arg (GtkComboBox *combo,
912 			      call_info *cinfo)
913 {
914     MODEL *pmod = cinfo->vwin->data;
915     int i = widget_get_int(combo, "argnum");
916     int k = gtk_combo_box_get_active(combo);
917 
918     g_free(cinfo->args[i]);
919     cinfo->args[i] = g_strdup_printf("%d", k + 1 + pmod->ifc);
920 }
921 
xlist_int_selector(call_info * cinfo,int i)922 static GtkWidget *xlist_int_selector (call_info *cinfo, int i)
923 {
924     MODEL *pmod;
925     GtkWidget *combo;
926     int *xlist;
927 
928     if (cinfo->vwin == NULL || cinfo->vwin->data == NULL) {
929 	return NULL;
930     }
931 
932     pmod = cinfo->vwin->data;
933 
934     combo = gtk_combo_box_text_new();
935     widget_set_int(combo, "argnum", i);
936     g_signal_connect(G_OBJECT(combo), "changed",
937 		     G_CALLBACK(update_xlist_arg), cinfo);
938 
939     xlist = gretl_model_get_x_list(pmod);
940 
941     if (xlist != NULL) {
942 	const char *s;
943 	int i, vi;
944 
945 	for (i=1; i<=xlist[0]; i++) {
946 	    vi = xlist[i];
947 	    if (vi > 0) {
948 		s = dataset->varname[xlist[i]];
949 		combo_box_append_text(combo, s);
950 	    }
951 	}
952 	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
953 	free(xlist);
954     }
955 
956     return combo;
957 }
958 
update_mylist_arg(GtkComboBox * combo,call_info * cinfo)959 static void update_mylist_arg (GtkComboBox *combo,
960 			       call_info *cinfo)
961 {
962     int i = widget_get_int(combo, "argnum");
963     int k = gtk_combo_box_get_active(combo);
964 
965     g_free(cinfo->args[i]);
966     cinfo->args[i] = g_strdup_printf("%d", mylist[k+1]);
967 }
968 
mylist_int_selector(call_info * cinfo,int i)969 static GtkWidget *mylist_int_selector (call_info *cinfo, int i)
970 {
971     GtkWidget *combo = NULL;
972     const char *lmaker;
973     ufunc *func;
974     int err = 0;
975 
976     function_package_get_properties(cinfo->pkg,
977 				    "list-maker", &lmaker,
978 				    NULL);
979     if (lmaker == NULL) {
980 	err = 1;
981     } else {
982 	func = get_function_from_package(lmaker, cinfo->pkg);
983 	if (func == NULL) {
984 	    err = 1;
985 	} else {
986 	    err = lmaker_run(func, cinfo);
987 	}
988     }
989 
990     if (!err) {
991 	const char *s;
992 	int j;
993 
994 	combo = gtk_combo_box_text_new();
995 	widget_set_int(combo, "argnum", i);
996 	g_signal_connect(G_OBJECT(combo), "changed",
997 			 G_CALLBACK(update_mylist_arg), cinfo);
998 	for (j=1; j<=mylist[0]; j++) {
999 	    s = dataset->varname[mylist[j]];
1000 	    combo_box_append_text(combo, s);
1001 	}
1002 	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
1003     }
1004 
1005     return combo;
1006 }
1007 
update_enum_arg(GtkComboBox * combo,call_info * cinfo)1008 static void update_enum_arg (GtkComboBox *combo, call_info *cinfo)
1009 {
1010     int val = gtk_combo_box_get_active(combo);
1011     int i = widget_get_int(combo, "argnum");
1012 
1013     val += widget_get_int(combo, "minv");
1014     g_free(cinfo->args[i]);
1015     cinfo->args[i] = g_strdup_printf("%d", val);
1016 }
1017 
maybe_limit_enum(call_info * cinfo,int nvals)1018 static int maybe_limit_enum (call_info *cinfo, int nvals)
1019 {
1020     if (!strcmp(cinfo->pkgname, "lp-mfx") &&
1021 	atoi(cinfo->pkgver) > 0 &&
1022 	cinfo->vwin != NULL &&
1023 	cinfo->vwin->role == VIEW_MODEL) {
1024 	MODEL *pmod = cinfo->vwin->data;
1025 
1026 	if (gretl_model_get_int(pmod, "ordered") ||
1027 	    gretl_model_get_int(pmod, "multinom")) {
1028 	    /* exclude the final "per obs" option */
1029 	    return nvals - 1;
1030 	}
1031     }
1032 
1033     return nvals;
1034 }
1035 
enum_arg_selector(call_info * cinfo,int i,const char ** S,int nvals,int minv,int initv)1036 static GtkWidget *enum_arg_selector (call_info *cinfo, int i,
1037 				     const char **S, int nvals,
1038 				     int minv, int initv)
1039 {
1040     GtkWidget *combo;
1041     int j, jmax, jactive;
1042 
1043     jmax = maybe_limit_enum(cinfo, nvals);
1044     combo = gtk_combo_box_text_new();
1045     widget_set_int(combo, "argnum", i);
1046     widget_set_int(combo, "minv", minv);
1047     g_signal_connect(G_OBJECT(combo), "changed",
1048 		     G_CALLBACK(update_enum_arg), cinfo);
1049     for (j=0; j<jmax; j++) {
1050 	combo_box_append_text(combo, (const char *) S[j]);
1051     }
1052     jactive = MIN(initv - minv, jmax - 1);
1053     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), jactive);
1054 
1055     return combo;
1056 }
1057 
spin_arg_selector(call_info * cinfo,int i,int minv,int maxv,int initv,GretlType type)1058 static GtkWidget *spin_arg_selector (call_info *cinfo, int i,
1059 				     int minv, int maxv, int initv,
1060 				     GretlType type)
1061 {
1062     GtkAdjustment *adj;
1063     GtkWidget *spin;
1064 
1065     adj = (GtkAdjustment *) gtk_adjustment_new(initv, minv, maxv,
1066 					       1, 1, 0);
1067     if (type == GRETL_TYPE_OBS) {
1068 	spin = obs_button_new(adj, dataset, 0);
1069     } else {
1070 	spin = gtk_spin_button_new(adj, 1, 0);
1071     }
1072     widget_set_int(spin, "argnum", i);
1073     g_object_set_data(G_OBJECT(spin), "cinfo", cinfo);
1074     g_signal_connect(G_OBJECT(spin), "value-changed",
1075 		     G_CALLBACK(update_int_arg), cinfo);
1076 
1077     cinfo->args[i] = g_strdup_printf("%d", initv);
1078 
1079     return spin;
1080 }
1081 
int_arg_selector(call_info * cinfo,int i,GretlType type,const char * prior_val)1082 static GtkWidget *int_arg_selector (call_info *cinfo,
1083 				    int i, GretlType type,
1084 				    const char *prior_val)
1085 {
1086     double dminv = fn_param_minval(cinfo->func, i);
1087     double dmaxv = fn_param_maxval(cinfo->func, i);
1088     double deflt = fn_param_default(cinfo->func, i);
1089     int minv, maxv, initv = 0;
1090 
1091     if (type == GRETL_TYPE_OBS) {
1092 	/* the incoming vals will be 1-based */
1093 	minv = (na(dminv) || dminv < 1)? 0 : (int) dminv - 1;
1094 	maxv = (na(dmaxv) || dmaxv > dataset->n)?
1095 	    (dataset->n - 1) : (int) dmaxv - 1;
1096     } else {
1097 	minv = (na(dminv))? INT_MIN : (int) dminv;
1098 	maxv = (na(dmaxv))? INT_MAX : (int) dmaxv;
1099     }
1100 
1101     if (prior_val != NULL) {
1102 	initv = atoi(prior_val);
1103     } else if (!na(deflt)) {
1104 	initv = (int) deflt;
1105     } else if (!na(dminv)) {
1106 	initv = (int) dminv;
1107     }
1108 
1109     if (type == GRETL_TYPE_INT && !na(dminv) && !na(dmaxv)) {
1110 	const char **S;
1111 	int nvals;
1112 
1113 	S = fn_param_value_labels(cinfo->func, i, &nvals);
1114 	if (S != NULL) {
1115 	    return enum_arg_selector(cinfo, i, S, nvals, minv, initv);
1116 	}
1117     }
1118 
1119     return spin_arg_selector(cinfo, i, minv, maxv, initv, type);
1120 }
1121 
double_arg_selector(call_info * cinfo,int i,const char * prior_val)1122 static GtkWidget *double_arg_selector (call_info *cinfo, int i,
1123 				       const char *prior_val)
1124 {
1125     double minv  = fn_param_minval(cinfo->func, i);
1126     double maxv  = fn_param_maxval(cinfo->func, i);
1127     double deflt = fn_param_default(cinfo->func, i);
1128     double step  = fn_param_step(cinfo->func, i);
1129     GtkAdjustment *adj;
1130     GtkWidget *spin;
1131     gchar *p, *tmp;
1132     int ndec = 0;
1133 
1134     tmp = g_strdup_printf("%g", maxv - step);
1135     p = strchr(tmp, '.');
1136     if (p == NULL) {
1137 	p = strchr(tmp, ',');
1138     }
1139     if (p != NULL) {
1140 	ndec = strlen(p + 1);
1141     }
1142     g_free(tmp);
1143 
1144     if (prior_val != NULL) {
1145 	/* locale? */
1146 	deflt = atof(prior_val);
1147     }
1148 
1149     if (deflt > maxv) {
1150 	/* note that default may be NADBL */
1151 	deflt = minv;
1152     }
1153 
1154     adj = (GtkAdjustment *) gtk_adjustment_new(deflt, minv, maxv,
1155 					       step, step, 0);
1156     spin = gtk_spin_button_new(adj, 1, ndec);
1157     widget_set_int(spin, "argnum", i);
1158     g_object_set_data(G_OBJECT(spin), "cinfo", cinfo);
1159     g_signal_connect(G_OBJECT(spin), "value-changed",
1160 		     G_CALLBACK(update_double_arg), cinfo);
1161     cinfo->args[i] = g_strdup_printf("%g", deflt);
1162 
1163     return spin;
1164 }
1165 
1166 /* see if the variable named @name of type @ptype
1167    has already been set as the default argument in
1168    an "upstream" combo argument selector
1169 */
1170 
already_set_as_default(call_info * cinfo,const char * name,int ptype)1171 static int already_set_as_default (call_info *cinfo,
1172 				   const char *name,
1173 				   int ptype)
1174 {
1175     GList *slist;
1176     int ret = 0;
1177 
1178     if (series_arg(ptype)) {
1179 	slist = g_list_first(cinfo->vsels);
1180     } else if (matrix_arg(ptype)) {
1181 	slist = g_list_first(cinfo->msels);
1182     } else if (bundle_arg(ptype)) {
1183 	slist = g_list_first(cinfo->bsels);
1184     } else if (array_arg(ptype)) {
1185 	slist = g_list_first(cinfo->asels);
1186     } else if (scalar_arg(ptype)) {
1187 	slist = g_list_first(cinfo->ssels);
1188     } else if (ptype == GRETL_TYPE_LIST) {
1189 	slist = g_list_first(cinfo->lsels);
1190     } else {
1191 	return 0;
1192     }
1193 
1194     while (slist != NULL && !ret) {
1195 	GtkComboBox *sel = GTK_COMBO_BOX(slist->data);
1196 	gchar *s = combo_box_get_active_text(sel);
1197 
1198 	if (!strcmp(s, name)) {
1199 	    ret = 1;
1200 	} else {
1201 	    slist = g_list_next(slist);
1202 	}
1203 	g_free(s);
1204     }
1205 
1206     return ret;
1207 }
1208 
has_single_arg_of_type(call_info * cinfo,GretlType type)1209 static int has_single_arg_of_type (call_info *cinfo,
1210 				   GretlType type)
1211 {
1212     int i, n = 0;
1213 
1214     for (i=0; i<cinfo->n_params; i++) {
1215 	if (fn_param_type(cinfo->func, i) == type) {
1216 	    n++;
1217 	}
1218     }
1219 
1220     return n == 1;
1221 }
1222 
1223 /* Try to be somewhat clever in selecting the default values to show
1224    in function-argument drop-down "combo" selectors.
1225 
1226    Heuristics: (a) when a series is wanted, it's more likely to be a
1227    stochastic series rather than (e.g.) a time trend or panel group
1228    variable, so we try to avoid the latter as defaults; and (b) it's
1229    unlikely that the user wants to select the same named variable in
1230    more than one argument slot, so we try to avoid setting duplicate
1231    defaults.
1232 
1233    Special case: the function has exactly one series argument, and
1234    a single series is selected in the main gretl window: in that
1235    case we pre-select that series.
1236 */
1237 
arg_combo_set_default(call_info * cinfo,GtkComboBox * combo,GList * list,int ptype)1238 static void arg_combo_set_default (call_info *cinfo,
1239 				   GtkComboBox *combo,
1240 				   GList *list,
1241 				   int ptype)
1242 {
1243     GList *tmp = g_list_first(list);
1244     const char *targname = NULL;
1245     int i, v, k = 0;
1246 
1247     if (ptype == GRETL_TYPE_SERIES) {
1248 	if (has_single_arg_of_type(cinfo, ptype)) {
1249 	    v = mdata_active_var();
1250 	    if (v > 0 && probably_stochastic(v)) {
1251 		targname = dataset->varname[v];
1252 	    }
1253 	}
1254     } else if (ptype == GRETL_TYPE_LIST) {
1255 	if (has_single_arg_of_type(cinfo, ptype) &&
1256 	    mdata_selection_count() > 1) {
1257 	    targname = SELNAME;
1258 	    tmp = g_list_prepend(tmp, SELNAME);
1259 	}
1260     }
1261 
1262     for (i=0; tmp != NULL; i++) {
1263 	gchar *name = tmp->data;
1264 	int ok = 0;
1265 
1266 	if (targname != NULL) {
1267 	    ok = strcmp(name, targname) == 0;
1268 	} else if (series_arg(ptype)) {
1269 	    v = current_series_index(dataset, name);
1270 	    if (v > 0 && probably_stochastic(v)) {
1271 		ok = !already_set_as_default(cinfo, name, ptype);
1272 	    }
1273 	} else {
1274 	    ok = !already_set_as_default(cinfo, name, ptype);
1275 	}
1276 
1277 	if (ok) {
1278 	    k = i;
1279 	    break;
1280 	} else {
1281 	    tmp = g_list_next(tmp);
1282 	}
1283     }
1284 
1285     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), k);
1286 }
1287 
1288 /* create an argument selector widget in the form of a
1289    GtkComboBox, with an entry field plus a drop-down
1290    list (which may initially be empty)
1291 */
1292 
combo_arg_selector(call_info * cinfo,int ptype,int i,const char * prior_val)1293 static GtkWidget *combo_arg_selector (call_info *cinfo, int ptype, int i,
1294 				      const char *prior_val)
1295 {
1296     GList *list = NULL;
1297     GtkWidget *combo;
1298     GtkWidget *entry;
1299     int k = 0, null_OK = 0;
1300 
1301     combo = combo_box_text_new_with_entry();
1302     entry = gtk_bin_get_child(GTK_BIN(combo));
1303     g_object_set_data(G_OBJECT(entry), "cinfo", cinfo);
1304     widget_set_int(combo, "argnum", i);
1305     g_signal_connect(G_OBJECT(combo), "changed",
1306 		     G_CALLBACK(update_arg), cinfo);
1307     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
1308 
1309     if (fn_param_optional(cinfo->func, i)) {
1310 	null_OK = 1;
1311 	widget_set_int(combo, "null_OK", 1);
1312     }
1313 
1314     list = get_selection_list(ptype);
1315     if (list != NULL) {
1316 	set_combo_box_strings_from_list(combo, list);
1317 	arg_combo_set_default(cinfo, GTK_COMBO_BOX(combo),
1318 			      list, ptype);
1319 	k = g_list_length(list);
1320 	g_list_free(list);
1321     }
1322 
1323     if (null_OK) {
1324 	combo_box_append_text(combo, "null");
1325 	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), k);
1326     }
1327 
1328     if (prior_val != NULL) {
1329 	gtk_entry_set_text(GTK_ENTRY(entry), prior_val);
1330     } else if (ptype == GRETL_TYPE_INT) {
1331 	double x = fn_param_default(cinfo->func, i);
1332 
1333 	if (!na(x)) {
1334 	    gchar *tmp = g_strdup_printf("%g", x);
1335 
1336 	    gtk_entry_set_text(GTK_ENTRY(entry), tmp);
1337 	    g_free(tmp);
1338 	}
1339     } else if (ptype == GRETL_TYPE_DOUBLE &&
1340 	       fn_param_has_default(cinfo->func, i)) {
1341 	double x = fn_param_default(cinfo->func, i);
1342 
1343 	if (na(x)) {
1344 	    gtk_entry_set_text(GTK_ENTRY(entry), "NA");
1345 	} else {
1346 	    gchar *tmp = g_strdup_printf("%g", x);
1347 
1348 	    gtk_entry_set_text(GTK_ENTRY(entry), tmp);
1349 	    g_free(tmp);
1350 	}
1351     }
1352 
1353     return combo;
1354 }
1355 
add_table_header(GtkWidget * tbl,gchar * txt,int cols,int r0,int ypad)1356 static void add_table_header (GtkWidget *tbl, gchar *txt,
1357 			      int cols, int r0, int ypad)
1358 {
1359     GtkWidget *label = gtk_label_new(txt);
1360     GtkWidget *align = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
1361 
1362     gtk_container_add(GTK_CONTAINER(align), label);
1363     gtk_table_attach(GTK_TABLE(tbl), align, 0, cols, r0, r0 + 1,
1364 		     GTK_FILL, GTK_FILL, 5, ypad);
1365 }
1366 
add_table_cell(GtkWidget * tbl,GtkWidget * w,int c0,int c1,int r0)1367 static void add_table_cell (GtkWidget *tbl, GtkWidget *w,
1368 			    int c0, int c1, int r0)
1369 {
1370     gtk_table_attach(GTK_TABLE(tbl), w, c0, c1, r0, r0 + 1,
1371 		     GTK_FILL, GTK_FILL, 5, 3);
1372 }
1373 
add_object_button(int ptype,GtkWidget * combo,const char * parname)1374 static GtkWidget *add_object_button (int ptype, GtkWidget *combo,
1375 				     const char *parname)
1376 {
1377     GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_ADD,
1378 					      GTK_ICON_SIZE_MENU);
1379     GtkWidget *button = gtk_button_new();
1380 
1381     gtk_container_add(GTK_CONTAINER(button), img);
1382     g_object_set_data(G_OBJECT(button), "combo", combo);
1383     if (parname != NULL) {
1384 	/* FIXME is the cast OK here? */
1385 	g_object_set_data(G_OBJECT(button), "parname", (char *) parname);
1386     }
1387 
1388     if (series_arg(ptype)) {
1389 	gretl_tooltips_add(button, _("New variable"));
1390     } else if (matrix_arg(ptype)) {
1391 	gretl_tooltips_add(button, _("Define matrix"));
1392     } else if (ptype == GRETL_TYPE_LIST) {
1393 	gretl_tooltips_add(button, _("Define list"));
1394     }
1395 
1396     return button;
1397 }
1398 
spinnable_scalar_arg(call_info * cinfo,int i)1399 static int spinnable_scalar_arg (call_info *cinfo, int i)
1400 {
1401     const ufunc *func = cinfo->func;
1402     double mi = fn_param_minval(func, i);
1403     double ma = fn_param_maxval(func, i);
1404     double s = fn_param_step(func, i);
1405 
1406     return !na(mi) && !na(ma) && !na(s);
1407 }
1408 
set_close_on_OK(GtkWidget * b,gpointer p)1409 static void set_close_on_OK (GtkWidget *b, gpointer p)
1410 {
1411     close_on_OK = button_is_active(b);
1412 }
1413 
set_allow_full_data(GtkWidget * b,gpointer p)1414 static void set_allow_full_data (GtkWidget *b, gpointer p)
1415 {
1416     allow_full_data = button_is_active(b);
1417     allow_full_data_access(allow_full_data);
1418 }
1419 
cinfo_show_return(call_info * c)1420 static int cinfo_show_return (call_info *c)
1421 {
1422     if (c->rettype == GRETL_TYPE_NONE ||
1423 	c->rettype == GRETL_TYPE_VOID) {
1424 	return 0;
1425     } else if (c->rettype == GRETL_TYPE_BUNDLE &&
1426 	       (c->flags & SHOW_GUI_MAIN)) {
1427 	return 0;
1428     } else {
1429 	return 1;
1430     }
1431 }
1432 
cinfo_pkg_title(call_info * cinfo)1433 static gchar *cinfo_pkg_title (call_info *cinfo)
1434 {
1435     return g_strdup_printf("gretl: %s %s", cinfo->pkgname,
1436 			   cinfo->pkgver);
1437 }
1438 
function_call_dialog(call_info * cinfo)1439 static int function_call_dialog (call_info *cinfo)
1440 {
1441     GtkWidget *button, *label;
1442     GtkWidget *sel, *tbl = NULL;
1443     GtkWidget *vbox, *hbox, *bbox;
1444     arglist *alist = NULL;
1445     gchar *txt;
1446     int trows = 0, tcols = 0;
1447     int show_ret;
1448     int i, row;
1449     int err;
1450 
1451     if (open_fncall_dlg != NULL) {
1452 	gtk_window_present(GTK_WINDOW(open_fncall_dlg));
1453 	return 0;
1454     }
1455 
1456     err = cinfo_args_init(cinfo);
1457     if (err) {
1458 	gui_errmsg(err);
1459 	return err;
1460     }
1461 
1462     cinfo->dlg = gretl_gtk_window();
1463     txt = cinfo_pkg_title(cinfo);
1464     gtk_window_set_title(GTK_WINDOW(cinfo->dlg), txt);
1465     g_free(txt);
1466     gretl_emulated_dialog_add_structure(cinfo->dlg, &vbox, &bbox);
1467     open_fncall_dlg = cinfo->dlg;
1468     g_signal_connect(G_OBJECT(cinfo->dlg), "destroy",
1469 		     G_CALLBACK(fncall_dialog_destruction), cinfo);
1470 
1471     /* above table: label or name of function being called */
1472     cinfo->top_hbox = hbox = label_hbox(cinfo, vbox);
1473 
1474     show_ret = cinfo_show_return(cinfo);
1475 
1476     if (cinfo->n_params > 0) {
1477 	tcols = 3; /* label, selector, add-button */
1478 	trows = cinfo->n_params + 1;
1479 	if (show_ret) {
1480 	    trows += 4;
1481 	}
1482 	alist = arglist_lookup(cinfo->pkgname, cinfo->func);
1483     } else if (show_ret) {
1484 	tcols = 2;
1485 	trows = 3;
1486     }
1487 
1488     if (trows > 0 && tcols > 0) {
1489 	tbl = gtk_table_new(trows, tcols, FALSE);
1490     }
1491 
1492     row = 0; /* initialize writing row */
1493 
1494     for (i=0; i<cinfo->n_params; i++) {
1495 	const char *desc = fn_param_descrip(cinfo->func, i);
1496 	const char *parname = fn_param_name(cinfo->func, i);
1497 	const char *prior_val = NULL;
1498 	int ptype = fn_param_type(cinfo->func, i);
1499 	int spinnable = 0;
1500 	gchar *argtxt;
1501 
1502 	if (i == 0 && cinfo->n_params > 1) {
1503 	    add_table_header(tbl, _("Select arguments:"), tcols, row, 5);
1504 	}
1505 
1506 	if (alist != NULL) {
1507 	    prior_val = arglist_lookup_val(alist, i);
1508 	}
1509 
1510 	row++;
1511 
1512 	if (ptype == GRETL_TYPE_DOUBLE) {
1513 	    spinnable = spinnable_scalar_arg(cinfo, i);
1514 	}
1515 
1516 	/* label for name (and maybe type) of argument, using
1517 	   descriptive string if available */
1518 	if (ptype == GRETL_TYPE_INT ||
1519 	    ptype == GRETL_TYPE_BOOL ||
1520 	    ptype == GRETL_TYPE_OBS ||
1521 	    spinnable) {
1522 	    argtxt = g_strdup_printf("%s",
1523 				     (desc != NULL)? _(desc) :
1524 				     parname);
1525 	} else {
1526 	    const char *astr = gretl_type_get_name(ptype);
1527 
1528 	    if (desc != NULL && strstr(desc, astr)) {
1529 		argtxt = g_strdup_printf("%s", _(desc));
1530 	    } else {
1531 		argtxt = g_strdup_printf("%s (%s)",
1532 					 (desc != NULL)? _(desc) :
1533 					 parname, astr);
1534 	    }
1535 	}
1536 
1537 	label = gtk_label_new(argtxt);
1538 	g_free(argtxt);
1539 	gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1540 	add_table_cell(tbl, label, 0, 1, row);
1541 
1542 	/* make the appropriate type of selector widget */
1543 
1544 	if (fn_param_uses_xlist(cinfo->func, i)) {
1545 	    sel = xlist_int_selector(cinfo, i);
1546 	} else if (fn_param_uses_mylist(cinfo->func, i)) {
1547 	    sel = mylist_int_selector(cinfo, i);
1548 	} else if (ptype == GRETL_TYPE_BOOL) {
1549 	    sel = bool_arg_selector(cinfo, i, prior_val);
1550 	} else if (ptype == GRETL_TYPE_INT ||
1551 		   ptype == GRETL_TYPE_OBS) {
1552 	    sel = int_arg_selector(cinfo, i, ptype, prior_val);
1553 	} else if (spinnable) {
1554 	    sel = double_arg_selector(cinfo, i, prior_val);
1555 	} else {
1556 	    sel = combo_arg_selector(cinfo, ptype, i, prior_val);
1557 	}
1558 
1559 	if (sel == NULL) {
1560 	    /* panic! */
1561 	    err = 1;
1562 	    break;
1563 	}
1564 
1565 	add_table_cell(tbl, sel, 1, 2, row);
1566 
1567 	/* hook up signals and "+" add buttons for the
1568 	   selectors for most types of arguments (though
1569 	   not for bool and spinner-type args)
1570 	*/
1571 
1572 	if (series_arg(ptype)) {
1573 	    cinfo->vsels = g_list_append(cinfo->vsels, sel);
1574 	    widget_set_int(sel, "ptype", GRETL_TYPE_SERIES);
1575 	    button = add_object_button(ptype, sel, parname);
1576 	    add_table_cell(tbl, button, 2, 3, row);
1577 	    g_signal_connect(G_OBJECT(button), "clicked",
1578 			     G_CALLBACK(launch_series_maker),
1579 			     cinfo);
1580 	} else if (scalar_arg(ptype) && !spinnable) {
1581 	    cinfo->ssels = g_list_append(cinfo->ssels, sel);
1582 	    widget_set_int(sel, "ptype", GRETL_TYPE_DOUBLE);
1583 	    button = add_object_button(ptype, sel, parname);
1584 	    add_table_cell(tbl, button, 2, 3, row);
1585 	    g_signal_connect(G_OBJECT(button), "clicked",
1586 			     G_CALLBACK(launch_scalar_maker),
1587 			     cinfo);
1588 	} else if (matrix_arg(ptype)) {
1589 	    cinfo->msels = g_list_append(cinfo->msels, sel);
1590 	    button = add_object_button(ptype, sel, parname);
1591 	    add_table_cell(tbl, button, 2, 3, row);
1592 	    g_signal_connect(G_OBJECT(button), "clicked",
1593 			     G_CALLBACK(launch_matrix_maker),
1594 			     cinfo);
1595 	} else if (bundle_arg(ptype)) {
1596 	    cinfo->bsels = g_list_append(cinfo->bsels, sel);
1597 	} else if (array_arg(ptype)) {
1598 	    cinfo->asels = g_list_append(cinfo->asels, sel);
1599 	} else if (ptype == GRETL_TYPE_LIST) {
1600 	    GtkWidget *entry = gtk_bin_get_child(GTK_BIN(sel));
1601 
1602 	    cinfo->lsels = g_list_append(cinfo->lsels, sel);
1603 	    button = add_object_button(ptype, sel, parname);
1604 	    add_table_cell(tbl, button, 2, 3, row);
1605 	    widget_set_int(entry, "argnum", i);
1606 	    g_object_set_data(G_OBJECT(button), "cinfo", cinfo);
1607 	    g_object_set_data(G_OBJECT(entry), "sel", sel);
1608 	    g_signal_connect(G_OBJECT(button), "clicked",
1609 			     G_CALLBACK(launch_list_maker),
1610 			     entry);
1611 	}
1612     }
1613 
1614     if (err) {
1615 	/* failed to build all selectors */
1616 	gtk_widget_destroy(tbl);
1617 	gtk_widget_destroy(cinfo->dlg);
1618 	errbox("Setup of function failed");
1619 	return err;
1620     }
1621 
1622     if (show_ret) {
1623 	/* selector/entry for return value */
1624 	GtkWidget *child;
1625 	GList *list = NULL;
1626 
1627 	if (cinfo->n_params > 0) {
1628 	    /* separator row */
1629 	    add_table_header(tbl, "", tcols, ++row, 0);
1630 	}
1631 
1632 	add_table_header(tbl, _("Assign return value (optional):"),
1633 			 tcols, ++row, 5);
1634 
1635 	label = gtk_label_new(_("selection (or new variable)"));
1636 	add_table_cell(tbl, label, 1, 2, ++row);
1637 
1638 	label = gtk_label_new(gretl_type_get_name(cinfo->rettype));
1639 	gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1640 	add_table_cell(tbl, label, 0, 1, ++row);
1641 
1642 	sel = combo_box_text_new_with_entry();
1643 	g_signal_connect(G_OBJECT(sel), "changed",
1644 			 G_CALLBACK(update_return), cinfo);
1645 	list = get_selection_list(cinfo->rettype);
1646 	if (list != NULL) {
1647 	    set_combo_box_strings_from_list(sel, list);
1648 	    g_list_free(list);
1649 	}
1650 
1651 	/* prepend blank option and select it */
1652 	combo_box_prepend_text(sel, "");
1653 	gtk_combo_box_set_active(GTK_COMBO_BOX(sel), 0);
1654 	child = gtk_bin_get_child(GTK_BIN(sel));
1655 	gtk_entry_set_activates_default(GTK_ENTRY(child), TRUE);
1656 	add_table_cell(tbl, sel, 1, 2, row); /* same row as above */
1657     }
1658 
1659     if (tbl != NULL) {
1660 	/* the table is complete: pack it now */
1661 	gtk_box_pack_start(GTK_BOX(vbox), tbl, FALSE, FALSE, 0);
1662     }
1663 
1664     if ((cinfo->flags & DATA_ACCESS) && sample_size(dataset) < dataset->n) {
1665 	/* "allow data access" option button */
1666 	hbox = gtk_hbox_new(FALSE, 5);
1667 	button = gtk_check_button_new_with_label(_("allow access to out-of-sample data"));
1668 	g_signal_connect(G_OBJECT(button), "toggled",
1669 			 G_CALLBACK(set_allow_full_data), NULL);
1670 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
1671 				     allow_full_data);
1672 	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
1673 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1674     }
1675 
1676     /* "close on exec" option button */
1677     hbox = gtk_hbox_new(FALSE, 5);
1678     button = gtk_check_button_new_with_label(_("close this dialog on \"OK\""));
1679     g_signal_connect(G_OBJECT(button), "toggled",
1680 		     G_CALLBACK(set_close_on_OK), NULL);
1681     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
1682 				 close_on_OK);
1683     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
1684     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1685 
1686     /* Close button */
1687     button = close_button(bbox);
1688     g_signal_connect(G_OBJECT (button), "clicked",
1689 		     G_CALLBACK(fncall_close), cinfo);
1690 
1691     /* "OK" button */
1692     button = ok_button(bbox);
1693     g_signal_connect(G_OBJECT(button), "clicked",
1694 		     G_CALLBACK(fncall_exec_callback), cinfo);
1695     gtk_widget_grab_default(button);
1696 
1697     /* Help button */
1698     button = context_help_button(bbox, -1);
1699     g_signal_connect(G_OBJECT(button), "clicked",
1700 		     G_CALLBACK(fncall_help), cinfo);
1701 
1702     if (cinfo->vwin != NULL) {
1703 	gtk_window_set_transient_for(GTK_WINDOW(cinfo->dlg),
1704 				     GTK_WINDOW(cinfo->vwin->main));
1705     }
1706 
1707     gtk_widget_show_all(cinfo->dlg);
1708 
1709     return 0;
1710 }
1711 
1712 /* called when defining a matrix for use as an argument:
1713    @dlg will be the function call dialog
1714 */
1715 
get_fncall_param_info(GtkWidget * dlg,int * series_ok,char ** pname)1716 void get_fncall_param_info (GtkWidget *dlg, int *series_ok,
1717 			    char **pname)
1718 {
1719     if (dlg == NULL) {
1720 	return;
1721     }
1722 
1723     if (series_ok != NULL) {
1724 	*series_ok = !widget_get_int(dlg, "matrix-no-series");
1725     }
1726 
1727     if (pname != NULL) {
1728 	GtkWidget *button =
1729 	    g_object_get_data(G_OBJECT(dlg), "button");
1730 
1731 	if (button != NULL) {
1732 	    char *name = g_object_get_data(G_OBJECT(button),
1733 					   "parname");
1734 
1735 	    if (name != NULL &&
1736 		current_series_index(dataset, name) < 0 &&
1737 		gretl_get_object_by_name(name) == NULL) {
1738 		/* OK, not the name of current object, so
1739 		   offer it as default */
1740 		*pname = g_strdup(name);
1741 	    }
1742 	}
1743     }
1744 }
1745 
function_data_check(call_info * cinfo,windata_t * vwin,const char * path)1746 static int function_data_check (call_info *cinfo,
1747 				windata_t *vwin,
1748 				const char *path)
1749 {
1750     int err = 0;
1751 
1752     if (dataset != NULL && dataset->v > 0) {
1753 	; /* OK, we have data */
1754     } else if (cinfo->dreq != FN_NODATA_OK) {
1755 	/* The package requires a dataset but no dataset
1756 	   is loaded: this error should have been caught
1757 	   earlier?
1758 	*/
1759 	err = 1;
1760     } else {
1761 	/* check the particular function being called:
1762 	   this is potentially relevant if we're coming
1763 	   from the gfn browser, trying to execute the
1764 	   default function of a package. It's possible
1765 	   that the package as such does not require a
1766 	   dataset but its default function does --
1767 	   though that is arguably somewhat anomalous.
1768 	*/
1769 	int i;
1770 
1771 	for (i=0; i<cinfo->n_params; i++) {
1772 	    int type = fn_param_type(cinfo->func, i);
1773 
1774 	    if (type == GRETL_TYPE_SERIES ||
1775 		type == GRETL_TYPE_LIST ||
1776 		type == GRETL_TYPE_SERIES_REF) {
1777 		err = 1;
1778 		break;
1779 	    }
1780 	}
1781     }
1782 
1783     if (err) {
1784 	/* 2018-02-12: was warnbox(_("Please open a data file first")); */
1785 	maybe_open_sample_script(cinfo, vwin, path);
1786     }
1787 
1788     return err;
1789 }
1790 
1791 /* detect the case where we need a "pointer" variable but
1792    have been given a scalar or matrix constant
1793 */
1794 
should_addressify_var(call_info * cinfo,int i)1795 static int should_addressify_var (call_info *cinfo, int i)
1796 {
1797     char *numchars = "0123456789+-.,";
1798     int t = fn_param_type(cinfo->func, i);
1799     gchar *s = cinfo->args[i];
1800 
1801     return (t == GRETL_TYPE_SCALAR_REF && strchr(numchars, *s)) ||
1802 	(t == GRETL_TYPE_MATRIX_REF && *s == '{');
1803 }
1804 
maybe_add_amp(call_info * cinfo,int i,PRN * prn,int * add)1805 static int maybe_add_amp (call_info *cinfo, int i, PRN *prn, int *add)
1806 {
1807     int t = fn_param_type(cinfo->func, i);
1808     gchar *name = cinfo->args[i];
1809     int err = 0;
1810 
1811     *add = 0;
1812 
1813     if (!gretl_ref_type(t)) {
1814 	return 0;
1815     }
1816 
1817     if (*name == '&' || !strcmp(name, "null")) {
1818 	return 0;
1819     }
1820 
1821     /* Handle cases where an "indirect return" variable
1822        does not yet exist: we need to declare it.
1823     */
1824 
1825     if (t == GRETL_TYPE_MATRIX_REF) {
1826 	if (get_matrix_by_name(name) == NULL) {
1827 	    gretl_matrix *m = gretl_null_matrix_new();
1828 
1829 	    if (m == NULL) {
1830 		err = E_ALLOC;
1831 	    } else {
1832 		err = user_var_add_or_replace(name,
1833 					      GRETL_TYPE_MATRIX,
1834 					      m);
1835 	    }
1836 	    if (!err) {
1837 		pprintf(prn, "? matrix %s\n", name);
1838 	    }
1839 	}
1840     } else if (t == GRETL_TYPE_SERIES_REF) {
1841 	if (current_series_index(dataset, name) < 0) {
1842 	    err = generate(name, dataset, GRETL_TYPE_SERIES,
1843 			   OPT_Q, NULL);
1844 	    if (!err) {
1845 		pprintf(prn, "? series %s\n", name);
1846 	    }
1847 	}
1848     }
1849 
1850     if (!err) {
1851 	*add = 1;
1852     }
1853 
1854     return err;
1855 }
1856 
needs_quoting(call_info * cinfo,int i)1857 static int needs_quoting (call_info *cinfo, int i)
1858 {
1859     int t = fn_param_type(cinfo->func, i);
1860     gchar *s = cinfo->args[i];
1861 
1862     return (t == GRETL_TYPE_STRING &&
1863 	    strcmp(s, "null") &&
1864 	    get_string_by_name(s) == NULL &&
1865 	    *s != '"');
1866 }
1867 
pre_process_args(call_info * cinfo,int * autolist,PRN * prn)1868 static int pre_process_args (call_info *cinfo, int *autolist,
1869 			     PRN *prn)
1870 {
1871     char auxline[MAXLINE];
1872     char auxname[VNAMELEN+2];
1873     int i, add = 0, err = 0;
1874 
1875     for (i=0; i<cinfo->n_params && !err; i++) {
1876 	if (should_addressify_var(cinfo, i)) {
1877 	    sprintf(auxname, "FNARG%d", i + 1);
1878 	    sprintf(auxline, "%s=%s", auxname, cinfo->args[i]);
1879 	    err = generate(auxline, dataset, GRETL_TYPE_ANY,
1880 			   OPT_NONE, NULL);
1881 	    if (!err) {
1882 		g_free(cinfo->args[i]);
1883 		cinfo->args[i] = g_strdup(auxname);
1884 		pprintf(prn, "? %s\n", auxline);
1885 	    }
1886 	}
1887 
1888 	err = maybe_add_amp(cinfo, i, prn, &add);
1889 
1890 	if (add) {
1891 	    strcpy(auxname, "&");
1892 	    strncat(auxname, cinfo->args[i], VNAMELEN);
1893 	    g_free(cinfo->args[i]);
1894 	    cinfo->args[i] = g_strdup(auxname);
1895 	} else if (needs_quoting(cinfo, i)) {
1896 	    sprintf(auxname, "\"%s\"", cinfo->args[i]);
1897 	    g_free(cinfo->args[i]);
1898 	    cinfo->args[i] = g_strdup(auxname);
1899 	}
1900 
1901 	if (fn_param_type(cinfo->func, i) == GRETL_TYPE_OBS) {
1902 	    /* convert integer value from 0- to 1-based */
1903 	    int val = atoi(cinfo->args[i]) + 1;
1904 
1905 	    g_free(cinfo->args[i]);
1906 	    cinfo->args[i] = g_strdup_printf("%d", val);
1907 	} else if (fn_param_type(cinfo->func, i) == GRETL_TYPE_LIST) {
1908 	    /* do we have an automatic list arg? */
1909 	    if (!strcmp(cinfo->args[i], SELNAME)) {
1910 		user_var_add(AUTOLIST, GRETL_TYPE_LIST,
1911 			     main_window_selection_as_list());
1912 		g_free(cinfo->args[i]);
1913 		cinfo->args[i] = g_strdup(AUTOLIST);
1914 		*autolist = i;
1915 	    }
1916 	}
1917     }
1918 
1919     return err;
1920 }
1921 
set_genr_model_from_vwin(windata_t * vwin)1922 static void set_genr_model_from_vwin (windata_t *vwin)
1923 {
1924     GretlObjType type = GRETL_OBJ_EQN;
1925 
1926     if (vwin->role == VAR || vwin->role == VECM) {
1927 	type = GRETL_OBJ_VAR;
1928     } else if (vwin->role == SYSTEM) {
1929 	type = GRETL_OBJ_SYS;
1930     }
1931 
1932     set_genr_model(vwin->data, type);
1933 }
1934 
1935 /* Compose the command line that calls a packaged function with the
1936    appropriate arguments, if any, and possible assignment of the
1937    return value, if any.
1938 */
1939 
compose_fncall_line(char * line,call_info * cinfo,const char * funname,char ** tmpname,int * grab_bundle,int * dummy_list)1940 static void compose_fncall_line (char *line,
1941 				 call_info *cinfo,
1942 				 const char *funname,
1943 				 char **tmpname,
1944 				 int *grab_bundle,
1945 				 int *dummy_list)
1946 {
1947     arglist *alist;
1948 
1949     alist = arglist_lookup(cinfo->pkgname, cinfo->func);
1950 
1951     if (alist == NULL) {
1952 	alist = arglist_new(cinfo->pkgname, cinfo->func,
1953 			    cinfo->n_params);
1954     }
1955 
1956     *line = '\0';
1957 
1958     if (cinfo->rettype == GRETL_TYPE_LIST && cinfo->ret == NULL) {
1959 	strcpy(line, "list " DUMLIST " = ");
1960 	*dummy_list = 1;
1961     } else if (cinfo->ret != NULL) {
1962 	strcat(line, cinfo->ret);
1963 	strcat(line, " = ");
1964     } else if (cinfo->rettype == GRETL_TYPE_BUNDLE) {
1965 	/* the function offers a bundle return but this has not been
1966 	   assigned by the user; make a special arrangement to grab
1967 	   the bundle for GUI purposes
1968 	*/
1969 	*tmpname = temp_name_for_bundle();
1970 	strcat(line, *tmpname);
1971 	strcat(line, " = ");
1972 	*grab_bundle = 1;
1973     }
1974 
1975     strcat(line, funname);
1976     strcat(line, "(");
1977 
1978     if (cinfo->args != NULL) {
1979 	int i;
1980 
1981 	for (i=0; i<cinfo->n_params; i++) {
1982 	    strcat(line, cinfo->args[i]);
1983 	    if (alist != NULL) {
1984 		arglist_record_arg(alist, i, cinfo->args[i]);
1985 	    }
1986 	    if (i < cinfo->n_params - 1) {
1987 		strcat(line, ", ");
1988 	    }
1989 	}
1990     }
1991 
1992     strcat(line, ")");
1993 }
1994 
real_GUI_function_call(call_info * cinfo,PRN * prn)1995 static int real_GUI_function_call (call_info *cinfo, PRN *prn)
1996 {
1997     windata_t *outwin = NULL;
1998     ExecState state;
1999     char fnline[MAXLINE];
2000     char *tmpname = NULL;
2001     const char *funname;
2002     const char *title;
2003     gretl_bundle *bundle = NULL;
2004     int grab_bundle = 0;
2005     int dummy_list = 0;
2006     int show = 1;
2007     int err = 0;
2008 
2009     funname = user_function_name_by_index(cinfo->iface);
2010     title = cinfo->label != NULL ? cinfo->label : funname;
2011 
2012     compose_fncall_line(fnline, cinfo, funname,
2013 			&tmpname, &grab_bundle,
2014 			&dummy_list);
2015 
2016     /* FIXME: the following conditionality may be wrong? */
2017 
2018     if (!grab_bundle && strncmp(funname, "GUI", 3)) {
2019 	pprintf(prn, "? %s\n", fnline);
2020     }
2021 
2022 #if FCDEBUG
2023     fprintf(stderr, "fnline: %s\n", fnline);
2024 #endif
2025 
2026     /* note: gretl_exec_state_init zeros the first byte of its
2027        'line' member
2028     */
2029     gretl_exec_state_init(&state, SCRIPT_EXEC, NULL, get_lib_cmd(),
2030 			  model, prn);
2031     state.line = fnline;
2032 
2033     if (cinfo->flags & MODEL_CALL) {
2034 	set_genr_model_from_vwin(cinfo->vwin);
2035     }
2036 
2037     show = !user_func_is_noprint(cinfo->func);
2038 
2039 #if FCDEBUG
2040     fprintf(stderr, "show = %d, grab_bundle = %d\n", show, grab_bundle);
2041 #endif
2042 
2043     if (show) {
2044 	/* allow the "flush" mechanism to operate */
2045 	if (close_on_OK && cinfo->dlg != NULL) {
2046 	    gtk_widget_hide(cinfo->dlg);
2047 	}
2048 	err = exec_line_with_output_handler(&state, dataset,
2049 					    title, &outwin);
2050     } else {
2051 	/* execute "invisibly" */
2052 	GtkWidget *ctop = NULL;
2053 	GdkWindow *cwin = NULL;
2054 	int modal = 0;
2055 
2056 	if (cinfo->dlg != NULL) {
2057 	    /* set modality */
2058 	    ctop = gtk_widget_get_toplevel(cinfo->dlg);
2059 	    if (GTK_IS_WINDOW(ctop)) {
2060 		gtk_window_set_modal(GTK_WINDOW(ctop), TRUE);
2061 		modal = 1;
2062 		cwin = gtk_widget_get_window(ctop);
2063 	    }
2064 	}
2065 
2066 	set_wait_cursor(&cwin);
2067 	err = gui_exec_line(&state, dataset, NULL);
2068 	unset_wait_cursor(cwin);
2069 
2070 	if (cinfo->dlg != NULL) {
2071 	    /* unset modality */
2072 	    if (modal) {
2073 		gtk_window_set_modal(GTK_WINDOW(ctop), FALSE);
2074 	    }
2075 	    if (close_on_OK) {
2076 		gtk_widget_hide(cinfo->dlg);
2077 	    }
2078 	}
2079     }
2080 
2081     if (dummy_list) {
2082 	/* handle use of dummy list to get series saved */
2083 	int *L = get_list_by_name(DUMLIST);
2084 
2085 	if (L != NULL && L[0] > 0) {
2086 	    set_dataset_is_changed(dataset, 1);
2087 	}
2088 	user_var_delete_by_name(DUMLIST, NULL);
2089     }
2090 
2091     if (!err && strstr(fnline, AUTOLIST) == NULL) {
2092 	int ID = 0;
2093 
2094 	if (cinfo->flags & MODEL_CALL) {
2095 	    ID = get_genr_model_ID();
2096 	}
2097 
2098 	maybe_record_include(cinfo->pkgname, ID);
2099 
2100 	if (ID > 0) {
2101 	    lib_command_sprintf("# %s", fnline);
2102 	    record_model_command_verbatim(ID);
2103 	} else {
2104 	    lib_command_strcpy(fnline);
2105 	    record_command_verbatim();
2106 	    if (dummy_list) {
2107 		lib_command_strcpy("list " DUMLIST " delete");
2108 		record_command_verbatim();
2109 	    }
2110 	}
2111     }
2112 
2113     if (cinfo->flags & MODEL_CALL) {
2114 	unset_genr_model();
2115     }
2116 
2117     if (!err && cinfo->rettype == GRETL_TYPE_BUNDLE) {
2118 	if (grab_bundle) {
2119 	    bundle = get_bundle_by_name(tmpname);
2120 	    if (bundle != NULL && !gretl_bundle_has_content(bundle)) {
2121 		/* we got a useless empty bundle */
2122 		gretl_bundle_pull_from_stack(tmpname, &err);
2123 		gretl_bundle_destroy(bundle);
2124 		bundle = NULL;
2125 	    }
2126 	} else if (cinfo->ret != NULL) {
2127 	    bundle = get_bundle_by_name(cinfo->ret);
2128 	}
2129     }
2130 
2131     if (!err && bundle != NULL && !show) {
2132 	gretl_print_reset_buffer(prn);
2133 	if (try_exec_bundle_print_function(bundle, prn)) {
2134 	    /* flag the fact that we do have something to show */
2135 	    show = 1;
2136 	}
2137     }
2138 
2139     if (grab_bundle && bundle != NULL) {
2140 	/* If the user specified an assignment of a returned bundle,
2141 	   we should leave it in the user_vars stack; but if we added
2142 	   the assignment automatically, we should pull it out of the
2143 	   stack, leaving the saving (or not) up to the user.
2144 	*/
2145 	gretl_bundle_pull_from_stack(tmpname, &err);
2146     }
2147 
2148     if (!err && !show) {
2149 	gretl_print_destroy(prn);
2150     } else if (outwin == NULL) {
2151 	/* output window not already in place */
2152 	view_buffer(prn, 80, 400, title,
2153 		    (bundle == NULL)? PRINT : VIEW_BUNDLE,
2154 		    bundle);
2155     } else {
2156 	/* an output window has already been opened
2157 	   via "flush" */
2158 	if (bundle != NULL) {
2159 	    finalize_script_output_window(VIEW_BUNDLE, bundle);
2160 	} else {
2161 	    finalize_script_output_window(0, NULL);
2162 	}
2163     }
2164 
2165     free(tmpname);
2166 
2167     if (err && !show) {
2168 	gui_errmsg(err);
2169     }
2170 
2171     if (check_dataset_is_changed(dataset)) {
2172 	mark_dataset_as_modified();
2173 	populate_varlist();
2174     }
2175 
2176     return err;
2177 }
2178 
2179 /* For interface selection via the GUI, when no gui-main
2180    is set: we'll suppose that if there's an interface with
2181    the same name as the package itself, it should probably
2182    be the first option on the list
2183 */
2184 
maybe_reshuffle_iface_order(call_info * cinfo)2185 static void maybe_reshuffle_iface_order (call_info *cinfo)
2186 {
2187     int *list = cinfo->publist;
2188     const char *s;
2189     int i, pref = 1;
2190 
2191     for (i=1; i<=list[0]; i++) {
2192 	s = user_function_name_by_index(list[i]);
2193 	if (!strcmp(s, cinfo->pkgname)) {
2194 	    pref = i;
2195 	    break;
2196 	}
2197     }
2198 
2199     if (pref > 1) {
2200 	int tmp = list[1];
2201 
2202 	list[1] = list[pref];
2203 	list[pref] = tmp;
2204     }
2205 }
2206 
2207 /* In case a function package offers more than one public
2208    interface, give the user a selector: for four or fewer
2209    options we use radio buttons, otherwise we use a pull-down
2210    list.
2211 */
2212 
pkg_select_interface(call_info * cinfo,int npub)2213 static void pkg_select_interface (call_info *cinfo, int npub)
2214 {
2215     const char *funname;
2216     char **opts = NULL;
2217     GList *ilist = NULL;
2218     int radios = (npub < 5);
2219     int i, nopts = 0;
2220     int err = 0;
2221 
2222     maybe_reshuffle_iface_order(cinfo);
2223 
2224     for (i=1; i<=npub && !err; i++) {
2225 	funname = user_function_name_by_index(cinfo->publist[i]);
2226 	if (funname == NULL) {
2227 	    err = E_DATA;
2228 	} else if (radios) {
2229 	    err = strings_array_add(&opts, &nopts, funname);
2230 	} else {
2231 	    ilist = g_list_append(ilist, (gpointer) funname);
2232 	}
2233     }
2234 
2235     if (err) {
2236 	cinfo->iface = -1;
2237 	gui_errmsg(err);
2238     } else {
2239 	GtkWidget *parent = vwin_toplevel(cinfo->vwin);
2240 	int resp;
2241 
2242 	if (radios) {
2243 	    gchar *title = g_strdup_printf("gretl: %s\n", cinfo->pkgname);
2244 
2245 	    resp = radio_dialog(title, _("Select function"),
2246 				(const char **) opts,
2247 				nopts, 0, 0, parent);
2248 	    if (resp >= 0) {
2249 		cinfo->iface = cinfo->publist[resp+1];
2250 	    } else {
2251 		cinfo->iface = -1;
2252 	    }
2253 	    strings_array_free(opts, nopts);
2254 	    g_free(title);
2255 	} else {
2256 	    resp = combo_selector_dialog(ilist, _("Select function"),
2257 					 0, parent);
2258 	    if (resp >= 0) {
2259 		cinfo->iface = cinfo->publist[resp+1];
2260 	    } else {
2261 		cinfo->iface = -1;
2262 	    }
2263 	    g_list_free(ilist);
2264 	}
2265     }
2266 }
2267 
2268 /* Callback from "OK" button in function call GUI: if there's a
2269    problem with the argument selection just return so the dialog stays
2270    in place and the user can correct matters; otherwise really execute
2271    the function.
2272 */
2273 
fncall_exec_callback(GtkWidget * w,call_info * cinfo)2274 static void fncall_exec_callback (GtkWidget *w, call_info *cinfo)
2275 {
2276     if (check_args(cinfo)) {
2277 	return;
2278     } else {
2279 	PRN *prn = NULL;
2280 	int autopos = -1;
2281 	int err;
2282 
2283 	err = bufopen(&prn);
2284 
2285 	if (!err && cinfo->args != NULL) {
2286 	    err = pre_process_args(cinfo, &autopos, prn);
2287 	    if (err) {
2288 		gui_errmsg(err);
2289 	    }
2290 	}
2291 
2292 	if (!err) {
2293 	    err = real_GUI_function_call(cinfo, prn);
2294 	} else {
2295 	    gretl_print_destroy(prn);
2296 	}
2297 
2298 	if (autopos >= 0) {
2299 	    user_var_delete_by_name(AUTOLIST, NULL);
2300 	    g_free(cinfo->args[autopos]);
2301 	    cinfo->args[autopos] = g_strdup(SELNAME);
2302 	}
2303 
2304 	if (cinfo->dlg != NULL && close_on_OK) {
2305 	    gtk_widget_destroy(cinfo->dlg);
2306 	} else if (cinfo->dlg == NULL) {
2307 	    cinfo_free(cinfo);
2308 	}
2309     }
2310 }
2311 
2312 /* Here we're testing whether @pkg has a "gui-main" function
2313    that should be displayed as the default interface.
2314 */
2315 
maybe_set_gui_interface(call_info * cinfo,int from_browser)2316 static void maybe_set_gui_interface (call_info *cinfo,
2317 				     int from_browser)
2318 {
2319     int gmid = -1, fid = -1;
2320 
2321     function_package_get_properties(cinfo->pkg,
2322 				    "gui-main-id", &gmid,
2323 				    NULL);
2324 
2325     if (gmid >= 0 && !from_browser) {
2326 	fid = gmid;
2327     } else if (cinfo->publist[0] == 1) {
2328 	/* single suitable interface: implicit gui-main */
2329 	fid = cinfo->publist[1];
2330     } else if (gmid >= 0) {
2331 	/* called from browser: check for masking */
2332 	const ufunc *u = get_user_function_by_index(gmid);
2333 
2334 	if (!user_func_is_menu_only(u)) {
2335 	    fid = gmid;
2336 	}
2337     }
2338 
2339     if (fid >= 0) {
2340 	/* we found a usable gui-main */
2341 	gchar *name = NULL, *label = NULL;
2342 
2343 	cinfo->iface = fid;
2344 	cinfo->flags |= SHOW_GUI_MAIN;
2345 	function_package_get_properties(cinfo->pkg,
2346 					"name", &name,
2347 					"label", &label,
2348 					NULL);
2349 	if (label != NULL) {
2350 	    cinfo->label = label;
2351 	    g_free(name);
2352 	} else {
2353 	    cinfo->label = name;
2354 	}
2355     }
2356 }
2357 
need_model_check(call_info * cinfo)2358 static int need_model_check (call_info *cinfo)
2359 {
2360     int i, err = 0;
2361 
2362     for (i=0; i<cinfo->n_params; i++) {
2363 	if (fn_param_uses_xlist(cinfo->func, i)) {
2364 	    if (cinfo->vwin == NULL || cinfo->vwin->role != VIEW_MODEL) {
2365 		err = E_DATA;
2366 		errbox(_("This function needs a model in place"));
2367 		break;
2368 	    }
2369 	}
2370     }
2371 
2372     return err;
2373 }
2374 
start_cinfo_for_package(const char * pkgname,const char * fname,windata_t * vwin,int * err)2375 static call_info *start_cinfo_for_package (const char *pkgname,
2376 					   const char *fname,
2377 					   windata_t *vwin,
2378 					   int *err)
2379 {
2380     call_info *cinfo;
2381     int data_access = 0;
2382     int gid = -1;
2383     fnpkg *pkg;
2384 
2385     pkg = get_function_package_by_name(pkgname);
2386 
2387     if (pkg == NULL) {
2388 	/* not already loaded */
2389 	pkg = get_function_package_by_filename(fname, err);
2390 	if (*err) {
2391 	    gui_errmsg(*err);
2392 	    return NULL;
2393 	}
2394     }
2395 
2396     cinfo = cinfo_new(pkg, vwin);
2397     if (cinfo == NULL) {
2398 	*err = E_ALLOC;
2399 	return NULL;
2400     }
2401 
2402     /* get the interface list and other basic info for package */
2403 
2404     *err = function_package_get_properties(pkg,
2405 					   "name", &cinfo->pkgname,
2406 					   "version", &cinfo->pkgver,
2407 					   "gui-publist", &cinfo->publist,
2408 					   "gui-main-id", &gid,
2409 					   "data-requirement", &cinfo->dreq,
2410 					   "model-requirement", &cinfo->modelreq,
2411 					   "min-version", &cinfo->minver,
2412 					   "wants-data-access", &data_access,
2413 					   NULL);
2414 
2415     if (*err) {
2416 	gui_errmsg(*err);
2417     } else if (cinfo->publist == NULL) {
2418 	if (gid >= 0) {
2419 	    cinfo->publist = gretl_list_new(1);
2420 	    cinfo->publist[1] = gid;
2421 	}
2422     }
2423 
2424     if (!*err && cinfo->publist == NULL) {
2425 	/* no available interfaces */
2426 	errbox(_("Function package is broken"));
2427 	*err = E_DATA;
2428     }
2429 
2430     if (!*err && data_access) {
2431 	cinfo->flags |= DATA_ACCESS;
2432     }
2433 
2434     if (*err) {
2435 	cinfo_free(cinfo);
2436 	cinfo = NULL;
2437     }
2438 
2439     return cinfo;
2440 }
2441 
2442 /* Call to execute a function from the package pre-attached to
2443    @cinfo. We may or may not end up offering a list of
2444    interfaces. This is called both from menu items (see below in this
2445    file) and (indirectly) from the "browser" window that lists
2446    installed function packages -- see open_function_package() below.
2447 */
2448 
call_function_package(call_info * cinfo,windata_t * vwin,const char * path,int from_browser)2449 static int call_function_package (call_info *cinfo,
2450 				  windata_t *vwin,
2451 				  const char *path,
2452 				  int from_browser)
2453 {
2454     int err = 0;
2455 
2456     if (!from_browser) {
2457 	/* Do we have suitable data in place? (This is already
2458 	   checked if @from_browser is non-zero).
2459 	*/
2460 	err = check_function_needs(dataset, cinfo->dreq, cinfo->minver);
2461 	if (err) {
2462 	    gui_errmsg(err);
2463 	}
2464     }
2465 
2466     if (!err) {
2467 	maybe_set_gui_interface(cinfo, from_browser);
2468     }
2469 
2470     if (!err && cinfo->iface < 0) {
2471 	pkg_select_interface(cinfo, cinfo->publist[0]);
2472 	if (cinfo->iface < 0) {
2473 	    /* failed, or cancelled */
2474 	    cinfo_free(cinfo);
2475 	    return 0; /* note: handled */
2476 	}
2477     }
2478 
2479     if (!err) {
2480 	cinfo->func = get_user_function_by_index(cinfo->iface);
2481 	if (cinfo->func == NULL) {
2482 	    fprintf(stderr, "get_user_function_by_index: failed\n");
2483 	    errbox(_("Couldn't get function package information"));
2484 	}
2485     }
2486 
2487     if (!err) {
2488 	cinfo->n_params = fn_n_params(cinfo->func);
2489 	err = function_data_check(cinfo, vwin, path);
2490     }
2491 
2492     if (!err) {
2493 	cinfo->rettype = user_func_get_return_type(cinfo->func);
2494 	if (err) {
2495 	    fprintf(stderr, "user_func_get_return_type: failed\n");
2496 	    errbox(_("Couldn't get function package information"));
2497 	}
2498     }
2499 
2500     if (!err) {
2501 	/* Should this check come earlier? */
2502 	err = need_model_check(cinfo);
2503     }
2504 
2505     if (!err) {
2506 	if (fn_n_params(cinfo->func) == 0) {
2507 	    /* no arguments to be gathered */
2508 	    fncall_exec_callback(NULL, cinfo);
2509 	} else {
2510 	    /* put up a dialog to collect arguments */
2511 	    err = function_call_dialog(cinfo);
2512 	}
2513     } else {
2514 	cinfo_free(cinfo);
2515     }
2516 
2517     return err;
2518 }
2519 
maybe_open_sample_script(call_info * cinfo,windata_t * vwin,const char * path)2520 static void maybe_open_sample_script (call_info *cinfo,
2521 				      windata_t *vwin,
2522 				      const char *path)
2523 {
2524     const char *ts_msg = N_("This package needs time series data.");
2525     const char *qm_msg = N_("This package needs quarterly or monthly data.");
2526     const char *pn_msg = N_("This package needs panel data.");
2527     const char *ds_msg = N_("This package needs a dataset in place.");
2528     const char *query = N_("Would you like to open its sample script?");
2529     gchar *msg, *title = cinfo_pkg_title(cinfo);
2530     const char *req;
2531     int resp;
2532 
2533     if (cinfo->dreq == FN_NEEDS_TS) {
2534 	req = ts_msg;
2535     } else if (cinfo->dreq == FN_NEEDS_QM) {
2536 	req = qm_msg;
2537     } else if (cinfo->dreq == FN_NEEDS_PANEL) {
2538 	req = pn_msg;
2539     } else {
2540 	req = ds_msg;
2541     }
2542 
2543     msg = g_strdup_printf("%s\n%s", _(req), _(query));
2544     resp = yes_no_dialog(title, msg, vwin_toplevel(vwin));
2545 
2546     if (resp == GRETL_YES) {
2547 	display_function_package_data(cinfo->pkgname, path,
2548 				      VIEW_PKG_SAMPLE);
2549     }
2550 
2551     g_free(msg);
2552 }
2553 
2554 /* Called from the function-package browser: unless the
2555    package can't be loaded we should return 0 to signal
2556    that loading happened.
2557 */
2558 
open_function_package(const char * pkgname,const char * fname,windata_t * vwin)2559 int open_function_package (const char *pkgname,
2560 			   const char *fname,
2561 			   windata_t *vwin)
2562 {
2563     call_info *cinfo;
2564     int can_call = 1;
2565     int free_cinfo = 1;
2566     int err = 0;
2567 
2568     /* note: this ensures the package gets loaded */
2569     cinfo = start_cinfo_for_package(pkgname, fname, vwin, &err);
2570 
2571     if (err) {
2572 	return err;
2573     }
2574 
2575     /* do we have suitable data in place? */
2576     err = check_function_needs(dataset, cinfo->dreq, cinfo->minver);
2577 
2578     if (err == E_DATA) {
2579 	/* we might still run the sample script */
2580 	can_call = 0;
2581 	err = 0;
2582 	gretl_error_clear();
2583     } else if (err) {
2584 	/* fatal error */
2585 	gui_errmsg(err);
2586 	return err;
2587     }
2588 
2589     if (can_call) {
2590 	/* actually call the package: must preserve @cinfo! */
2591 	free_cinfo = 0;
2592 	call_function_package(cinfo, vwin, fname, 1);
2593     } else {
2594 	/* notify and give choice of running sample */
2595 	maybe_open_sample_script(cinfo, vwin, fname);
2596     }
2597 
2598     if (free_cinfo) {
2599 	cinfo_free(cinfo);
2600     }
2601 
2602     return 0;
2603 }
2604 
function_call_cleanup(void)2605 void function_call_cleanup (void)
2606 {
2607     if (open_fncall_dlg != NULL) {
2608 	gtk_widget_destroy(open_fncall_dlg);
2609     }
2610 
2611     arglist_cleanup();
2612 }
2613 
compose_pkg_title(ufunc * func,const char * id)2614 static gchar *compose_pkg_title (ufunc *func,
2615 					const char *id)
2616 {
2617     fnpkg *pkg = gretl_function_get_package(func);
2618     const char *pname = function_package_get_name(pkg);
2619     gchar *title;
2620 
2621     if (!strcmp(id, BUNDLE_FCAST)) {
2622 	title = g_strdup_printf("gretl: %s %s", pname, _("forecast"));
2623     } else {
2624 	title = g_strdup_printf("gretl: %s bundle", pname);
2625     }
2626 
2627     return title;
2628 }
2629 
2630 /* Execute a special-purpose function made available by the
2631    package that produced bundle @b, possibly inflected by an
2632    integer option. If an option is present it's packed into
2633    @aname, following a colon.
2634 */
2635 
exec_bundle_special_function(gretl_bundle * b,const char * id,const char * aname,GtkWidget * parent)2636 int exec_bundle_special_function (gretl_bundle *b,
2637 				  const char *id,
2638 				  const char *aname,
2639 				  GtkWidget *parent)
2640 {
2641     ufunc *func = NULL;
2642     fncall *fc = NULL;
2643     char funname[32];
2644     PRN *prn = NULL;
2645     int plotting = 0;
2646     int forecast = 0;
2647     int t1 = 0, t2 = 0;
2648     int iopt = -1;
2649     int err = 0;
2650 
2651     plotting = strcmp(id, BUNDLE_PLOT) == 0;
2652     forecast = strcmp(id, BUNDLE_FCAST) == 0;
2653 
2654     if (aname != NULL) {
2655 	if (strchr(aname, ':') != NULL) {
2656 	    /* extract option */
2657 	    sscanf(aname, "%31[^:]:%d", funname, &iopt);
2658 	} else {
2659 	    /* name but no option present */
2660 	    strcpy(funname, aname);
2661 	}
2662     } else {
2663 	gchar *sf = get_bundle_special_function(b, id);
2664 
2665 	if (sf == NULL) {
2666 	    return E_DATA;
2667 	} else {
2668 	    strcpy(funname, sf);
2669 	    g_free(sf);
2670 	}
2671     }
2672 
2673     func = get_user_function_by_name(funname);
2674 
2675     if (func == NULL) {
2676 	errbox_printf(_("Couldn't find function %s"), funname);
2677 	return E_DATA;
2678     }
2679 
2680     if (forecast) {
2681 	/* check for feasibility */
2682 	int resp = simple_forecast_dialog(&t1, &t2, parent);
2683 
2684 	if (canceled(resp)) {
2685 	    return 0;
2686 	}
2687 	allow_full_data_access(1);
2688     }
2689 
2690     if (!err) {
2691 	user_var *uv = get_user_var_by_data(b);
2692 	const char *bname = NULL;
2693 
2694 	if (uv != NULL) {
2695 	    bname = user_var_get_name(uv);
2696 	}
2697 	fc = fncall_new(func, 0);
2698 	if (bname != NULL) {
2699 	    err = push_function_arg(fc, bname, uv, GRETL_TYPE_BUNDLE_REF, b);
2700 	} else {
2701 	    err = push_anon_function_arg(fc, GRETL_TYPE_BUNDLE_REF, b);
2702 	}
2703 	if (!err && forecast) {
2704 	    t1++; t2++; /* convert to 1-based */
2705 	    push_anon_function_arg(fc, GRETL_TYPE_INT, &t1);
2706 	    push_anon_function_arg(fc, GRETL_TYPE_INT, &t2);
2707 	} else if (!err && iopt >= 0) {
2708 	    /* add the option flag, if any, to args */
2709 	    double minv = fn_param_minval(func, 1);
2710 
2711 	    if (!na(minv)) {
2712 		iopt += (int) minv;
2713 		err = push_anon_function_arg(fc, GRETL_TYPE_INT, &iopt);
2714 	    }
2715 	}
2716     }
2717 
2718     if (!err) {
2719 	if (plotting) {
2720 	    prn = gretl_print_new(GRETL_PRINT_STDERR, &err);
2721 	} else {
2722 	    err = bufopen(&prn);
2723 	}
2724     }
2725 
2726     if (!err && plotting) {
2727 	/* A plotting function may need a non-NULL PRN for
2728 	   use with printing redirection (outfile). But we
2729 	   don't expect any printed output.
2730 	*/
2731 	err = gretl_function_exec(fc, GRETL_TYPE_NONE, dataset,
2732 				  NULL, NULL, prn);
2733     } else if (!err) {
2734 	/* For other bundle-specials we expect printed output */
2735 	GretlType rtype = user_func_get_return_type(func);
2736 	gretl_bundle *retb = NULL;
2737 
2738 	if (rtype == GRETL_TYPE_BUNDLE) {
2739 	    /* if a bundle is offered, let's grab it */
2740 	    err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, dataset,
2741 				      &retb, NULL, prn);
2742 	} else {
2743 	    /* otherwise ignore any return value */
2744 	    err = gretl_function_exec(fc, GRETL_TYPE_NONE, dataset,
2745 				      NULL, NULL, prn);
2746 	}
2747 	if (err) {
2748 	    gui_errmsg(err);
2749 	} else {
2750 	    int role = retb != NULL ? VIEW_BUNDLE : PRINT;
2751 	    gchar *title = compose_pkg_title(func, id);
2752 
2753 	    view_buffer(prn, 78, 450, title, role, retb);
2754 	    g_free(title);
2755 	    prn = NULL; /* ownership taken by viewer */
2756 	}
2757     } else {
2758 	fncall_destroy(fc);
2759     }
2760 
2761     gretl_print_destroy(prn);
2762 
2763     if (err) {
2764 	gui_errmsg(err);
2765     }
2766 
2767     return err;
2768 }
2769 
2770 /* See if a bundle has the name of a "creator" function package
2771    recorded on it. If so, see whether that package is already loaded,
2772    or can be loaded.  And if that works, see if the package has a
2773    default function for @task (e.g. BUNDLE_PRINT).
2774 */
2775 
get_bundle_special_function(gretl_bundle * b,const char * id)2776 gchar *get_bundle_special_function (gretl_bundle *b,
2777 				    const char *id)
2778 {
2779     const char *pkgname = gretl_bundle_get_creator(b);
2780     gchar *ret = NULL;
2781 
2782     if (pkgname != NULL && *pkgname != '\0') {
2783 	fnpkg *pkg = get_function_package_by_name(pkgname);
2784 
2785 	if (pkg == NULL) {
2786 	    char *fname =
2787 		gretl_function_package_get_path(pkgname, PKG_ALL);
2788 	    int err = 0;
2789 
2790 	    if (fname != NULL) {
2791 		pkg = get_function_package_by_filename(fname, &err);
2792 		free(fname);
2793 	    }
2794 	}
2795 	if (pkg != NULL) {
2796 	    function_package_get_properties(pkg, id, &ret, NULL);
2797 	}
2798     }
2799 
2800     return ret;
2801 }
2802 
2803 /* See if we can find a "native" printing function for a
2804    gretl bundle. If we can find this, try executing it.
2805 
2806    Notice that this function returns 1 on success, 0 on
2807    failure.
2808 */
2809 
try_exec_bundle_print_function(gretl_bundle * b,PRN * prn)2810 int try_exec_bundle_print_function (gretl_bundle *b, PRN *prn)
2811 {
2812     gchar *funname;
2813     int ret = 0;
2814 
2815     funname = get_bundle_special_function(b, BUNDLE_PRINT);
2816 
2817     if (funname != NULL) {
2818 	const char *name = user_var_get_name_by_data(b);
2819 	gchar *genline;
2820 	int err;
2821 
2822 	genline = g_strdup_printf("%s(&%s)", funname, name);
2823 	err = generate_void(genline, dataset, prn);
2824 	g_free(genline);
2825 	if (err) {
2826 	    gui_errmsg(err);
2827 	} else {
2828 	    ret = 1;
2829 	}
2830     }
2831 
2832     return ret;
2833 }
2834 
2835 /* get a listing of available "official" addons along with (a) the
2836    name of the versioned subdirectory containing the most recent
2837    usable version (given the gretl version) and (b) the date of that
2838    package version, taken from its spec file. E.g.
2839 
2840    gig 1.9.5 2011-04-22
2841    ivpanel 1.9.4 2011-02-10
2842 */
2843 
query_addons(void)2844 int query_addons (void)
2845 {
2846     gchar *query;
2847     char *buf = NULL;
2848     int err = 0;
2849 
2850     query = g_strdup_printf("/addons-data/pkginfo.php?gretl_version=%s",
2851 			    GRETL_VERSION);
2852     err = query_sourceforge(query, &buf);
2853     g_free(query);
2854 
2855     if (!err && buf == NULL) {
2856 	/* shouldn't happen */
2857 	err = E_DATA;
2858     }
2859 
2860     if (!err) {
2861 	infobox(buf);
2862     }
2863 
2864     free(buf);
2865 
2866     return err;
2867 }
2868 
download_addon(const char * pkgname,char ** local_path)2869 int download_addon (const char *pkgname, char **local_path)
2870 {
2871     char *uri;
2872     int err = 0;
2873 
2874     uri = get_uri_for_addon(pkgname, &err);
2875 
2876     if (!err) {
2877 	const char *path = gretl_function_package_path();
2878 	gchar *fullname = g_strdup_printf("%s%s.zip", path, pkgname);
2879 
2880 #if 1
2881 	fprintf(stderr, "download_addon: uri   = '%s'\n", uri);
2882 	fprintf(stderr, "download_addon: fname = '%s'\n", fullname);
2883 #endif
2884 
2885 	err = retrieve_public_file(uri, fullname);
2886 	fprintf(stderr, "retrieve_public_file: err = %d\n", err);
2887 	if (!err) {
2888 	    err = gretl_unzip_into(fullname, path);
2889 	    fprintf(stderr, "gretl_unzip_into: err = %d\n", err);
2890 	    gretl_remove(fullname);
2891 	}
2892 	if (err) {
2893 	    gui_errmsg(err);
2894 	} else {
2895 	    update_addons_index(NULL);
2896 	    if (local_path != NULL) {
2897 		/* fill local path to gfn file */
2898 		gchar *tmp;
2899 
2900 		tmp = g_build_filename(path, pkgname, pkgname, NULL);
2901 		*local_path = calloc(strlen(tmp) + 5, 1);
2902 		sprintf(*local_path, "%s.gfn", tmp);
2903 		g_free(tmp);
2904 		fprintf(stderr, "local_path: '%s'\n", *local_path);
2905 	    }
2906 	}
2907 	g_free(fullname);
2908     }
2909 
2910     free(uri);
2911 
2912     return err;
2913 }
2914 
2915 /* information about a function package that offers a
2916    menu attachment point */
2917 
2918 typedef enum {
2919     GPI_MODELWIN = 1 << 0,
2920     GPI_SUBDIR   = 1 << 1,
2921     GPI_SYSFILE  = 1 << 2,
2922     GPI_INCLUDED = 1 << 3,
2923     GPI_DATAREQ  = 1 << 4
2924 } GpiFlags;
2925 
2926 enum {
2927     SYS_PACKAGES,
2928     USER_PACKAGES
2929 };
2930 
2931 #define gpi_included(g) (g->flags & GPI_INCLUDED)
2932 #define gpi_modelwin(g) (g->flags & GPI_MODELWIN)
2933 #define gpi_sysfile(g) (g->flags & GPI_SYSFILE)
2934 #define gpi_subdir(g) (g->flags & GPI_SUBDIR)
2935 #define gpi_ptype(g) ((g->flags & GPI_SUBDIR)? PKG_SUBDIR : PKG_TOPLEV)
2936 
2937 struct gui_package_info_ {
2938     char *pkgname;  /* @name element from packages.xml */
2939     char *label;    /* @label element from packages.xml */
2940     char *menupath; /* @path element from packages.xml */
2941     char *filepath; /* actual filesystem path */
2942     DataReq dreq;   /* data requirement */
2943     int modelreq;   /* model (command number) requirement */
2944     GpiFlags flags; /* state flags */
2945     guint merge_id; /* created at runtime when added to GUI */
2946     GtkActionGroup *ag; /* run-time UI thing */
2947 };
2948 
2949 typedef struct gui_package_info_ gui_package_info;
2950 
2951 static void add_package_to_menu (gui_package_info *gpi,
2952 				 windata_t *vwin);
2953 
2954 static gui_package_info *gpkgs;
2955 static int n_gpkgs;
2956 static int gpkgs_changed;
2957 
2958 /* Return the total number of slots for function packages
2959    "registered" for use via menus. Note that this number
2960    may include some slots that are actually empty, if the
2961    user has removed a dynamic menu item during the
2962    current gretl session.
2963 */
2964 
n_registered_packages(void)2965 int n_registered_packages (void)
2966 {
2967     return n_gpkgs;
2968 }
2969 
n_user_handled_packages(void)2970 int n_user_handled_packages (void)
2971 {
2972     int i, n = 0;
2973 
2974     for (i=0; i<n_gpkgs; i++) {
2975 	if (gpkgs[i].pkgname == NULL) {
2976 	    /* a vacant slot */
2977 	    continue;
2978 	} else if (gpkgs[i].flags & GPI_SYSFILE) {
2979 	    /* a file under control of the "system"
2980 	       packages.xml file */
2981 	    continue;
2982 	} else {
2983 	    n++;
2984 	}
2985     }
2986 
2987     return n;
2988 }
2989 
2990 /* On adding a new entry to the gui package info
2991    array, zero it appropriately */
2992 
gpi_entry_init(gui_package_info * gpi)2993 static void gpi_entry_init (gui_package_info *gpi)
2994 {
2995     gpi->pkgname = NULL;
2996     gpi->label = NULL;
2997     gpi->menupath = NULL;
2998     gpi->filepath = NULL;
2999     gpi->dreq = FN_NEEDS_DATA;
3000     gpi->modelreq = 0;
3001     gpi->flags = 0;
3002     gpi->merge_id = 0;
3003     gpi->ag = NULL;
3004 }
3005 
packages_xml_path(int which)3006 static gchar *packages_xml_path (int which)
3007 {
3008     if (which == SYS_PACKAGES) {
3009 	return g_strdup_printf("%sfunctions%cpackages.xml",
3010 			       gretl_home(), SLASH);
3011     } else {
3012 	return g_strdup_printf("%sfunctions%cpackages.xml",
3013 			       gretl_dotdir(), SLASH);
3014     }
3015 }
3016 
modelreq_string(int ci)3017 static const char *modelreq_string (int ci)
3018 {
3019     if (ci == 0) {
3020 	return "any";
3021     } else {
3022 	return gretl_command_word(ci);
3023     }
3024 }
3025 
write_packages_xml(void)3026 static void write_packages_xml (void)
3027 {
3028     gchar *fname = packages_xml_path(USER_PACKAGES);
3029     int i, n_write = n_user_handled_packages();
3030 
3031     if (n_write == 0) {
3032 	gretl_remove(fname);
3033     } else {
3034 	FILE *fp = gretl_fopen(fname, "w");
3035 
3036 	if (fp == NULL) {
3037 	    fprintf(stderr, "Couldn't write to %s\n", fname);
3038 	    return;
3039 	}
3040 
3041 	fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
3042 	fputs("<gretl-package-info>\n", fp);
3043 
3044 	for (i=0; i<n_gpkgs; i++) {
3045 	    if (gpkgs[i].pkgname != NULL &&
3046 		!(gpkgs[i].flags & GPI_SYSFILE)) {
3047 		fprintf(fp, "<package name=\"%s\"", gpkgs[i].pkgname);
3048 		fprintf(fp, " label=\"%s\"", gpkgs[i].label);
3049 		if (gpkgs[i].flags & GPI_MODELWIN) {
3050 		    fputs(" model-window=\"true\"", fp);
3051 		    fprintf(fp, " model-requirement=\"%s\"",
3052 			    modelreq_string(gpkgs[i].modelreq));
3053 		}
3054 		fprintf(fp, " path=\"%s\"", gpkgs[i].menupath);
3055 		if (!(gpkgs[i].flags & GPI_SUBDIR)) {
3056 		    fputs(" toplev=\"true\"", fp);
3057 		}
3058 		if (gpkgs[i].flags & GPI_DATAREQ) {
3059 		    fprintf(fp, " data-requirement=\"%d\"", gpkgs[i].dreq);
3060 		}
3061 		fputs("/>\n", fp);
3062 	    }
3063 	}
3064 
3065 	fputs("</gretl-package-info>\n", fp);
3066 	fclose(fp);
3067     }
3068 
3069     g_free(fname);
3070 }
3071 
3072 /* At exit, clean up the entire array of gui package
3073    info, after first saving the info to file if anything
3074    relevant has changed.
3075 */
3076 
destroy_gui_package_info(void)3077 void destroy_gui_package_info (void)
3078 {
3079     if (gpkgs_changed) {
3080 	/* save info to packages.xml first */
3081 	write_packages_xml();
3082     }
3083 
3084     if (gpkgs != NULL && n_gpkgs > 0) {
3085 	int i;
3086 
3087 	for (i=0; i<n_gpkgs; i++) {
3088 	    free(gpkgs[i].pkgname);
3089 	    free(gpkgs[i].label);
3090 	    free(gpkgs[i].menupath);
3091 	    free(gpkgs[i].filepath);
3092 	}
3093 	free(gpkgs);
3094     }
3095 
3096     gpkgs = NULL;
3097     n_gpkgs = 0;
3098     gpkgs_changed = 0;
3099 }
3100 
gpkg_name_match(char * s1,const char * s2)3101 static int gpkg_name_match (char *s1, const char *s2)
3102 {
3103     return s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0;
3104 }
3105 
get_gpi_entry(const gchar * pkgname)3106 static gui_package_info *get_gpi_entry (const gchar *pkgname)
3107 {
3108     int i;
3109 
3110     for (i=0; i<n_gpkgs; i++) {
3111 	if (gpkg_name_match(gpkgs[i].pkgname, pkgname)) {
3112 	    return &gpkgs[i];
3113 	}
3114     }
3115 
3116     return NULL;
3117 }
3118 
get_registered_pkg_info(int i,char ** name,char ** path,char ** label,int * modelwin)3119 void get_registered_pkg_info (int i, char **name, char **path,
3120 			      char **label, int *modelwin)
3121 {
3122     if (i < 0 || i >= n_gpkgs ||
3123 	gpkgs[i].pkgname == NULL ||
3124 	(gpkgs[i].flags & GPI_SYSFILE)) {
3125 	*name = *path = *label = NULL;
3126     } else {
3127 	*name = gpkgs[i].pkgname;
3128 	*path = gpkgs[i].menupath;
3129 	*label = gpkgs[i].label;
3130 	*modelwin = (gpkgs[i].flags & GPI_MODELWIN)? 1 : 0;
3131     }
3132 }
3133 
maybe_record_include(const char * pkgname,int model_id)3134 static void maybe_record_include (const char *pkgname,
3135 				  int model_id)
3136 {
3137     gui_package_info *gpi;
3138     int i;
3139 
3140     for (i=0; i<n_gpkgs; i++) {
3141 	gpi = &gpkgs[i];
3142 	if (gpkg_name_match(gpi->pkgname, pkgname)) {
3143 	    if (!gpi_included(gpi)) {
3144 		lib_command_sprintf("include %s.gfn", pkgname);
3145 		if (model_id > 0) {
3146 		    record_model_command_verbatim(model_id);
3147 		} else {
3148 		    record_command_verbatim();
3149 		}
3150 		gpi->flags |= GPI_INCLUDED;
3151 	    }
3152 	    break;
3153 	}
3154     }
3155 }
3156 
package_is_available_for_menu(const gchar * pkgname,const char * fname)3157 int package_is_available_for_menu (const gchar *pkgname,
3158 				   const char *fname)
3159 {
3160     int present = 0;
3161     int i, ret = 0;
3162 
3163     for (i=0; i<n_gpkgs && !present; i++) {
3164 	if (gpkg_name_match(gpkgs[i].pkgname, pkgname)) {
3165 	    present = 1;
3166 	}
3167     }
3168 
3169     if (!present) {
3170 	/* not already present in menus: can it be added? */
3171 	ret = package_has_menu_attachment(fname, NULL, NULL, NULL);
3172     }
3173 
3174     return ret;
3175 }
3176 
3177 /* Callback for a menu item representing a function package whose
3178    name is attached to @action. We first see if we can find the full
3179    path to the corresponding gfn file; if so we initiate a GUI call to
3180    the package.
3181 */
3182 
gfn_menu_callback(GtkAction * action,windata_t * vwin)3183 static void gfn_menu_callback (GtkAction *action, windata_t *vwin)
3184 {
3185     const gchar *pkgname = gtk_action_get_name(action);
3186     gui_package_info *gpi;
3187 
3188     gpi = get_gpi_entry(pkgname);
3189     if (gpi == NULL) {
3190 	/* "can't happen" */
3191 	return;
3192     }
3193 
3194     if (gpi->filepath == NULL) {
3195 	gpi->filepath =
3196 	    gretl_function_package_get_path(pkgname, gpi_ptype(gpi));
3197     }
3198 
3199     if (gpi->filepath == NULL && is_gretl_addon(pkgname)) {
3200 	gchar *msg = g_strdup_printf(_("The %s package was not found, or is not "
3201 				       "up to date.\nWould you like to try "
3202 				       "downloading it now?"), pkgname);
3203 	int resp = yes_no_dialog(NULL, msg, vwin_toplevel(vwin));
3204 
3205 	g_free(msg);
3206 	if (resp == GRETL_YES) {
3207 	    int err = download_addon(pkgname, &gpi->filepath);
3208 
3209 	    if (err) {
3210 		return;
3211 	    }
3212 	} else {
3213 	    /* canceled, effectively */
3214 	    return;
3215 	}
3216     }
3217 
3218     if (gpi->filepath != NULL) {
3219 	call_info *cinfo;
3220 	int err = 0;
3221 
3222 	cinfo = start_cinfo_for_package(pkgname, gpi->filepath, vwin, &err);
3223 	if (cinfo != NULL) {
3224 	    call_function_package(cinfo, vwin, gpi->filepath, 0);
3225 	}
3226     } else {
3227 	errbox_printf("Sorry, could not find %s", pkgname);
3228 	gui_function_pkg_unregister(pkgname);
3229     }
3230 }
3231 
package_is_unseen(const char * name,int n)3232 static int package_is_unseen (const char *name, int n)
3233 {
3234     int i;
3235 
3236     for (i=0; i<n; i++) {
3237 	if (gpkg_name_match(gpkgs[i].pkgname, name)) {
3238 	    return 0;
3239 	}
3240     }
3241 
3242     return 1;
3243 }
3244 
gpi_set_flags(gui_package_info * gpi,int which,int subdir,int modelwin,int need_dreq)3245 static void gpi_set_flags (gui_package_info *gpi,
3246 			   int which,
3247 			   int subdir,
3248 			   int modelwin,
3249 			   int need_dreq)
3250 {
3251     gpi->flags = 0;
3252 
3253     if (which == SYS_PACKAGES) {
3254 	gpi->flags |= GPI_SYSFILE;
3255     }
3256     if (subdir) {
3257 	gpi->flags |= GPI_SUBDIR;
3258     }
3259     if (modelwin) {
3260 	gpi->flags |= GPI_MODELWIN;
3261     }
3262     if (need_dreq) {
3263 	gpi->flags |= GPI_DATAREQ;
3264     }
3265 }
3266 
3267 /* Use libxml2 to peek inside package and determine its data
3268    or model requirement, without having to load the package
3269    into memory.
3270 */
3271 
gfn_peek_requirement(const char * fname,int model)3272 static int gfn_peek_requirement (const char *fname, int model)
3273 {
3274     int ret = 0;
3275     xmlDocPtr doc = NULL;
3276     xmlNodePtr node = NULL;
3277     xmlNodePtr cur;
3278     int err;
3279 
3280     err = gretl_xml_open_doc_root(fname, "gretl-functions", &doc, &node);
3281 
3282     if (!err) {
3283 	cur = node->xmlChildrenNode;
3284 	while (cur != NULL) {
3285 	    if (!xmlStrcmp(cur->name, (XUC) "gretl-function-package")) {
3286 		if (model) {
3287 		    char *s = NULL;
3288 
3289 		    gretl_xml_get_prop_as_string(cur, "model-requirement", &s);
3290 		    if (s != NULL) {
3291 			ret = gretl_command_number(s);
3292 			free(s);
3293 		    }
3294 		    break;
3295 		}
3296 		if (gretl_xml_get_prop_as_bool(cur, NEEDS_TS)) {
3297 		    ret = FN_NEEDS_TS;
3298 		} else if (gretl_xml_get_prop_as_bool(cur, NEEDS_QM)) {
3299 		    ret = FN_NEEDS_QM;
3300 		} else if (gretl_xml_get_prop_as_bool(cur, NEEDS_PANEL)) {
3301 		    ret = FN_NEEDS_PANEL;
3302 		} else if (gretl_xml_get_prop_as_bool(cur, NO_DATA_OK)) {
3303 		    ret = FN_NODATA_OK;
3304 		}
3305 		break;
3306 	    }
3307 	    cur = cur->next;
3308 	}
3309     }
3310 
3311     if (doc != NULL) {
3312 	xmlFreeDoc(doc);
3313     }
3314 
3315     return ret;
3316 }
3317 
discover_gfn_requirement(const char * pkgname,int toplev,int model)3318 static int discover_gfn_requirement (const char *pkgname,
3319 				     int toplev, int model)
3320 {
3321     char *path;
3322     PkgType ptype;
3323     int ret = 0;
3324 
3325     ptype = toplev ? PKG_TOPLEV : PKG_SUBDIR;
3326     path = gretl_function_package_get_path(pkgname, ptype);
3327     if (path != NULL) {
3328 	ret = gfn_peek_requirement(path, model);
3329 	free(path);
3330     }
3331 
3332     return ret;
3333 }
3334 
3335 /* Figure out whether we need to pay attention to the data requirement
3336    of a function package in order to set its sensitivity ("grayed out"
3337    or not). We don't need to do this if it has a model-window
3338    attachment (the package will be added to a model-window menu only
3339    if its model-type specification is matched). Neither do we need
3340    this if the package attaches under the main-window Model menu: in
3341    that case its sensitivity will be governed by the code that sets
3342    the overall sensitivity of the Model menu and its sub-menus
3343    (time-series, panel).
3344 */
3345 
need_gfn_data_req(const char * path)3346 static int need_gfn_data_req (const char *path)
3347 {
3348     return strncmp(path, "/menubar/Model", 14) != 0;
3349 }
3350 
read_packages_file(const char * fname,int * pn,int which)3351 static int read_packages_file (const char *fname, int *pn, int which)
3352 {
3353     xmlDocPtr doc = NULL;
3354     xmlNodePtr cur = NULL;
3355     int err, n = *pn;
3356 
3357     err = gretl_xml_open_doc_root(fname, "gretl-package-info", &doc, &cur);
3358     if (err) {
3359 	return (which == SYS_PACKAGES)? err : 0;
3360     }
3361 
3362     cur = cur->xmlChildrenNode;
3363 
3364     while (cur != NULL && !err) {
3365         if (!xmlStrcmp(cur->name, (XUC) "package")) {
3366 	    int mw = gretl_xml_get_prop_as_bool(cur, "model-window");
3367 	    int top = gretl_xml_get_prop_as_bool(cur, "toplev");
3368 	    char *name, *desc, *path;
3369 	    int dreq, modelreq = 0, need_dr = 0;
3370 	    int freeit = 1;
3371 
3372 	    name = (char *) xmlGetProp(cur, (XUC) "name");
3373 	    desc = (char *) xmlGetProp(cur, (XUC) "label");
3374 	    path = (char *) xmlGetProp(cur, (XUC) "path");
3375 	    if (name == NULL || desc == NULL || path == NULL) {
3376 		err = E_DATA;
3377 		break;
3378 	    }
3379 
3380 	    if (!strcmp(name, "SVAR") &&
3381 		!strcmp(path, "/menubar/Model/TSModels")) {
3382 		/* update menu path (legacy SVAR) */
3383 		free(path);
3384 		path = gretl_strdup("/menubar/Model/TSMulti");
3385 	    } else if (strstr(path, "TSModels/TSMulti") ||
3386 		       strstr(path, "TSModels/CointMenu")) {
3387 		free(path);
3388 		path = gretl_strdup("/menubar/Model/TSMulti");
3389 	    }
3390 
3391 	    if (mw) {
3392 		/* package with a model-window attachment */
3393 		if (!gretl_xml_get_prop_as_int(cur, "model-requirement", &modelreq)) {
3394 		    modelreq = discover_gfn_requirement(name, top, 1);
3395 		    gpkgs_changed = 1;
3396 		}
3397 	    } else {
3398 		/* a main-window package */
3399 		need_dr = need_gfn_data_req(path);
3400 	    }
3401 
3402 	    if (need_dr && !gretl_xml_get_prop_as_int(cur, "data-requirement", &dreq)) {
3403 		dreq = discover_gfn_requirement(name, top, 0);
3404 		gpkgs_changed = 1;
3405 	    }
3406 
3407 	    if (package_is_unseen(name, n)) {
3408 		gpkgs = myrealloc(gpkgs, (n+1) * sizeof *gpkgs);
3409 		if (gpkgs == NULL) {
3410 		    err = E_ALLOC;
3411 		} else {
3412 		    freeit = 0;
3413 		    gpkgs[n].pkgname = name;
3414 		    gpkgs[n].label = desc;
3415 		    gpkgs[n].menupath = path;
3416 		    gpkgs[n].filepath = NULL;
3417 		    gpi_set_flags(&gpkgs[n], which, !top, mw, need_dr);
3418 		    gpkgs[n].dreq = (DataReq) dreq;
3419 		    if (mw) {
3420 			gpkgs[n].modelreq = modelreq;
3421 		    }
3422 		    gpkgs[n].merge_id = 0;
3423 		    gpkgs[n].ag = NULL;
3424 		    n++;
3425 		}
3426 	    }
3427 	    if (freeit) {
3428 		free(name);
3429 		free(desc);
3430 		free(path);
3431 	    }
3432 	}
3433 	if (!err) {
3434 	    cur = cur->next;
3435 	}
3436     }
3437 
3438     if (doc != NULL) {
3439 	xmlFreeDoc(doc);
3440     }
3441 
3442     *pn = n;
3443 
3444     return err;
3445 }
3446 
destroy_gpi_ui(gui_package_info * gpi)3447 static void destroy_gpi_ui (gui_package_info *gpi)
3448 {
3449     fprintf(stderr, "removing UI for %s\n", gpi->pkgname);
3450     gtk_ui_manager_remove_ui(mdata->ui, gpi->merge_id);
3451     gtk_ui_manager_remove_action_group(mdata->ui, gpi->ag);
3452     g_object_unref(gpi->ag);
3453 
3454     gpi->merge_id = 0;
3455     gpi->ag = NULL;
3456 }
3457 
3458 /* On the call to remove a dynamic menu item, tear down
3459    its UI and blank out @gpi so that it may be safely
3460    reused by another package.
3461 */
3462 
clear_gpi_entry(gui_package_info * gpi)3463 static void clear_gpi_entry (gui_package_info *gpi)
3464 {
3465     if (gpi->merge_id > 0) {
3466 	destroy_gpi_ui(gpi);
3467     }
3468 
3469     free(gpi->pkgname);
3470     free(gpi->label);
3471     free(gpi->menupath);
3472     free(gpi->filepath);
3473 
3474     gpi->pkgname = NULL;
3475     gpi->label = NULL;
3476     gpi->menupath = NULL;
3477     gpi->filepath = NULL;
3478 
3479     gpi->dreq = FN_NEEDS_DATA;
3480     gpi->modelreq = 0;
3481     gpi->flags = 0;
3482 
3483     gpkgs_changed = 1;
3484 }
3485 
fill_gpi_entry(gui_package_info * gpi,const char * pkgname,const char * fname,const char * label,const char * relpath,int modelwin,int uses_subdir,DataReq dreq,int modelreq,int replace)3486 static int fill_gpi_entry (gui_package_info *gpi,
3487 			   const char *pkgname,
3488 			   const char *fname,
3489 			   const char *label,
3490 			   const char *relpath,
3491 			   int modelwin,
3492 			   int uses_subdir,
3493 			   DataReq dreq,
3494 			   int modelreq,
3495 			   int replace)
3496 {
3497     int need_dr = 0;
3498     int err = 0;
3499 
3500     if (replace) {
3501 	free(gpi->pkgname);
3502 	free(gpi->label);
3503 	free(gpi->menupath);
3504 	free(gpi->filepath);
3505     }
3506 
3507     gpi->pkgname = gretl_strdup(pkgname);
3508     gpi->label = gretl_strdup(label);
3509     gpi->menupath = malloc(9 + strlen(relpath));
3510     if (gpi->menupath != NULL) {
3511 	sprintf(gpi->menupath, "/menubar%s", relpath);
3512     }
3513     gpi->filepath = gretl_strdup(fname);
3514     if (modelwin) {
3515 	gpi->modelreq = modelreq;
3516     } else {
3517 	need_dr = need_gfn_data_req(gpi->menupath);
3518     }
3519     gpi_set_flags(gpi, USER_PACKAGES, uses_subdir, modelwin, need_dr);
3520     gpi->dreq = dreq;
3521 
3522     if (gpi->pkgname == NULL || gpi->label == NULL ||
3523 	gpi->menupath == NULL || gpi->filepath == NULL) {
3524 	err = E_ALLOC;
3525     }
3526 
3527     return err;
3528 }
3529 
get_new_package_info(int * err)3530 static gui_package_info *get_new_package_info (int *err)
3531 {
3532     int i, pos = -1;
3533 
3534     for (i=0; i<n_gpkgs; i++) {
3535 	if (gpkgs[i].pkgname == NULL) {
3536 	    /* found an unused slot */
3537 	    pos = i;
3538 	    break;
3539 	}
3540     }
3541 
3542     if (pos < 0) {
3543 	/* we need to extend the array */
3544 	gui_package_info *gpkgs_new;
3545 	int n = n_gpkgs + 1;
3546 
3547 	gpkgs_new = realloc(gpkgs, n * sizeof *gpkgs);
3548 	if (gpkgs_new == NULL) {
3549 	    *err = E_ALLOC;
3550 	    return NULL;
3551 	} else {
3552 	    gpkgs = gpkgs_new;
3553 	    n_gpkgs = n;
3554 	    pos = n - 1;
3555 	    gpi_entry_init(&gpkgs[pos]);
3556 	}
3557     }
3558 
3559     return &gpkgs[pos];
3560 }
3561 
menu_paths_differ(const char * rp,const char * mp)3562 static int menu_paths_differ (const char *rp, const char *mp)
3563 {
3564     if ((rp == NULL && mp != NULL) ||
3565 	(rp != NULL && mp == NULL)) {
3566 	return 1;
3567     } else if (rp == NULL && mp == NULL) {
3568 	return 0;
3569     } else {
3570 	if (!strncmp(mp, "/menubar", 8)) {
3571 	    mp += 8;
3572 	}
3573 
3574 	return strcmp(rp, mp);
3575     }
3576 }
3577 
gpi_strings_differ(const char * s1,const char * s2)3578 static int gpi_strings_differ (const char *s1, const char *s2)
3579 {
3580     if ((s1 == NULL && s2 != NULL) ||
3581 	(s1 != NULL && s2 == NULL)) {
3582 	return 1;
3583     } else if (s1 == NULL && s2 == NULL) {
3584 	return 0;
3585     } else {
3586 	return strcmp(s1, s2);
3587     }
3588 }
3589 
3590 /* This is called when creating a new entry in the
3591    gui package registry, and also when updating
3592    the entry for a previously registered package.
3593 */
3594 
update_gui_package_info(const char * pkgname,const char * fname,const char * label,const char * relpath,int modelwin,int uses_subdir,DataReq dreq,int modelreq)3595 static int update_gui_package_info (const char *pkgname,
3596 				    const char *fname,
3597 				    const char *label,
3598 				    const char *relpath,
3599 				    int modelwin,
3600 				    int uses_subdir,
3601 				    DataReq dreq,
3602 				    int modelreq)
3603 {
3604     gui_package_info *gpi;
3605     int menu_update = 0;
3606     int update = 0;
3607     int replace = 1;
3608     int err = 0;
3609 
3610     gpi = get_gpi_entry(pkgname);
3611 
3612     if (gpi != NULL) {
3613 	/* found a pre-existing entry for @pkgname:
3614 	   let's see if there are really any changes
3615 	*/
3616 	if (gpi_strings_differ(label, gpi->label)) {
3617 	    menu_update = update = 1;
3618 	} else if (menu_paths_differ(relpath, gpi->menupath)) {
3619 	    menu_update = update = 1;
3620 	} else if (gpi_strings_differ(fname, gpi->filepath)) {
3621 	    update = 1;
3622 	} else if (modelwin && !gpi_modelwin(gpi)) {
3623 	    menu_update = update = 1;
3624 	} else if (uses_subdir && !gpi_subdir(gpi)) {
3625 	    update = 1;
3626 	} else if (dreq != gpi->dreq) {
3627 	    update = 1;
3628 	} else if (modelreq != gpi->modelreq) {
3629 	    update = 1;
3630 	}
3631     } else {
3632 	gpi = get_new_package_info(&err);
3633 	menu_update = update = 1;
3634 	replace = 0;
3635     }
3636 
3637     fprintf(stderr, "update_gui_package_info: update=%d, menu_update=%d, "
3638 	    "err=%d\n", update, menu_update, err);
3639 
3640     if (!err && menu_update && gpi->merge_id > 0) {
3641 	/* trash stale UI info */
3642 	destroy_gpi_ui(gpi);
3643     }
3644 
3645     if (!err && update) {
3646 	err = fill_gpi_entry(gpi,
3647 			     pkgname,
3648 			     fname,
3649 			     label,
3650 			     relpath,
3651 			     modelwin,
3652 			     uses_subdir,
3653 			     dreq,
3654 			     modelreq,
3655 			     replace);
3656     }
3657 
3658     if (update && !err) {
3659 	gpkgs_changed = 1;
3660 	if (menu_update) {
3661 	    if (!modelwin) {
3662 		/* add to main-window menu */
3663 		add_package_to_menu(gpi, mdata);
3664 	    }
3665 	}
3666 	/* sync GUI */
3667 	maybe_update_pkg_registry_window(pkgname, MENU_ADD_FN_PKG);
3668     }
3669 
3670     return err;
3671 }
3672 
3673 /* read "packages.xml" to find out what's what among packages
3674    that offer to place themselves in the gretl menu system
3675 */
3676 
gui_package_info_init(void)3677 static int gui_package_info_init (void)
3678 {
3679     gchar *fname;
3680     int err, n = 0;
3681 
3682     /* start with the "system" packages.xml, which should
3683        always be present */
3684     fname = packages_xml_path(SYS_PACKAGES);
3685     err = read_packages_file(fname, &n, SYS_PACKAGES);
3686 #if PKG_DEBUG
3687     fprintf(stderr, "read_packages_file: n=%d, err=%d from '%s'\n",
3688 	    n, err, fname);
3689 #endif
3690     g_free(fname);
3691 
3692     if (!err) {
3693 	/* then read the per-user packages.xml, if present */
3694 	fname = packages_xml_path(USER_PACKAGES);
3695 #if PKG_DEBUG
3696 	fprintf(stderr, "now trying '%s'\n", fname);
3697 #endif
3698 	if (gretl_file_exists(fname)) {
3699 	    err = read_packages_file(fname, &n, USER_PACKAGES);
3700 #if PKG_DEBUG
3701 	    fprintf(stderr, "read_packages_file: n=%d, err=%d from '%s'\n",
3702 		    n, err, fname);
3703 #endif
3704 	}
3705 	g_free(fname);
3706     }
3707 
3708     if (err) {
3709 	destroy_gui_package_info();
3710     } else {
3711 	n_gpkgs = n;
3712     }
3713 
3714     return err;
3715 }
3716 
3717 /* For function packages offering a menu attachment point: given the
3718    internal package name (e.g. "gig") and a menu path where we'd like
3719    it to appear (e.g. "/menubar/Model/TSModels" -- see the ui
3720    definition file gui/gretlmain.xml), construct the appropriate menu
3721    item and connect it to gfn_menu_callback(), for which see above.
3722 
3723    This is called for both main-window and model-window menu
3724    attachments.
3725 */
3726 
add_package_to_menu(gui_package_info * gpi,windata_t * vwin)3727 static void add_package_to_menu (gui_package_info *gpi,
3728 				 windata_t *vwin)
3729 {
3730     static GtkActionEntry item = {
3731 	NULL, NULL, NULL, NULL, NULL, G_CALLBACK(gfn_menu_callback)
3732     };
3733     gchar *fixed_label = NULL;
3734     guint merge_id;
3735 
3736 #if PKG_DEBUG
3737     fprintf(stderr, "add_package_to_menu:\n pkgname='%s', menupath='%s', label='%s'\n",
3738 	    gpi->pkgname, gpi->menupath, gpi->label);
3739 #endif
3740 
3741     item.name = gpi->pkgname;
3742     item.label = gpi->label != NULL ? gpi->label : gpi->pkgname;
3743 
3744     if (strchr(item.label, '_')) {
3745 	fixed_label = double_underscores_new(item.label);
3746 	item.label = fixed_label;
3747     }
3748 
3749     merge_id = gtk_ui_manager_new_merge_id(vwin->ui);
3750     gtk_ui_manager_add_ui(vwin->ui, merge_id, gpi->menupath,
3751 			  _(item.label), item.name,
3752 			  GTK_UI_MANAGER_MENUITEM,
3753 			  FALSE);
3754     if (vwin == mdata) {
3755 	gpi->merge_id = merge_id;
3756     }
3757 
3758     gpi->ag = gtk_action_group_new(item.name);
3759     gtk_action_group_set_translation_domain(gpi->ag, "gretl");
3760     gtk_action_group_add_actions(gpi->ag, &item, 1, vwin);
3761     if (gpi->flags & GPI_DATAREQ) {
3762 	g_object_set_data(G_OBJECT(gpi->ag), "datareq", GINT_TO_POINTER(1));
3763     }
3764     gtk_ui_manager_insert_action_group(vwin->ui, gpi->ag, 0);
3765     // g_object_unref(gpi->ag);
3766 
3767     g_free(fixed_label);
3768 #if PKG_DEBUG
3769     fprintf(stderr, " merge_id = %d\n", merge_id);
3770 #endif
3771 }
3772 
3773 /* run a package's gui-precheck function to determine if
3774    it's OK to add its GUI interface to a gretl
3775    model-window menu
3776 */
3777 
precheck_error(ufunc * func,windata_t * vwin)3778 static int precheck_error (ufunc *func, windata_t *vwin)
3779 {
3780     PRN *prn;
3781     double check_err = 0;
3782     void *ptr = NULL;
3783     int err = 0;
3784 
3785     prn = gretl_print_new(GRETL_PRINT_STDERR, &err);
3786     set_genr_model_from_vwin(vwin);
3787     err = gretl_function_exec(fncall_new(func, 0), GRETL_TYPE_DOUBLE,
3788 			      dataset, &ptr, NULL, prn);
3789     check_err = *(double *) ptr;
3790     unset_genr_model();
3791     gretl_print_destroy(prn);
3792 
3793     if (err == 0 && check_err != 0) {
3794 	err = 1;
3795     }
3796 
3797     return err;
3798 }
3799 
maybe_add_model_pkg(gui_package_info * gpi,windata_t * vwin)3800 static int maybe_add_model_pkg (gui_package_info *gpi,
3801 				windata_t *vwin)
3802 {
3803     int ci, dreq, modelreq, minver = 0;
3804     gchar *precheck = NULL;
3805     fnpkg *pkg;
3806     int err = 0;
3807 
3808     if (vwin->role == VIEW_MODEL) {
3809 	MODEL *pmod = vwin->data;
3810 
3811 	ci = pmod->ci;
3812     } else {
3813 	/* system: VAR, VECM or SYSTEM */
3814 	ci = vwin->role;
3815     }
3816 
3817 #if MPKG_DEBUG
3818     fprintf(stderr, "maybe_add_model_pkg: %s, ci=%s\n",
3819 	    gpi->pkgname, gretl_command_word(ci));
3820 #endif
3821 
3822     if (gpi->modelreq > 0 && ci != gpi->modelreq) {
3823 	return 0;
3824     }
3825 
3826     if (gpi->filepath == NULL) {
3827 	gpi->filepath =
3828 	    gretl_function_package_get_path(gpi->pkgname, gpi_ptype(gpi));
3829     }
3830 
3831     if (gpi->filepath == NULL) {
3832 	fprintf(stderr, "%s: couldn't find it\n", gpi->pkgname);
3833 	return E_FOPEN;
3834     }
3835 
3836     pkg = get_function_package_by_filename(gpi->filepath, &err);
3837 
3838     if (!err) {
3839 	err = function_package_get_properties(pkg,
3840 					      "data-requirement", &dreq,
3841 					      "model-requirement", &modelreq,
3842 					      "min-version", &minver,
3843 					      "gui-precheck", &precheck,
3844 					      NULL);
3845     }
3846 
3847     if (!err) {
3848 	/* "skip" means skip this package, since it won't work
3849 	   with the current model */
3850 	int skip = 0;
3851 
3852 	if (modelreq > 0) {
3853 	    skip = ci != modelreq;
3854 	}
3855 	if (!skip) {
3856 	    skip = check_function_needs(dataset, dreq, minver);
3857 	}
3858 	if (!skip && precheck != NULL) {
3859 	    ufunc *func = get_function_from_package(precheck, pkg);
3860 
3861 	    if (func == NULL || precheck_error(func, vwin)) {
3862 		skip = 1;
3863 	    }
3864 	}
3865 	if (!skip) {
3866 	    add_package_to_menu(gpi, vwin);
3867 	}
3868     }
3869 
3870     g_free(precheck);
3871 
3872     return err;
3873 }
3874 
3875 /* Called from gretl.c on initializing the GUI: put suitable
3876    function packages (other than those that are designed to
3877    appear in model-window menus) into the appropriate main-
3878    window menus.
3879 */
3880 
maybe_add_packages_to_menus(windata_t * vwin)3881 void maybe_add_packages_to_menus (windata_t *vwin)
3882 {
3883     gui_package_info *gpi;
3884     int i;
3885 
3886 #if PKG_DEBUG
3887     fprintf(stderr, "starting maybe_add_packages_to_menus\n");
3888 #endif
3889 
3890     if (gpkgs == NULL) {
3891 	gui_package_info_init();
3892     }
3893 
3894 #if PKG_DEBUG
3895     fprintf(stderr, "  n_gpkgs = %d\n", n_gpkgs);
3896 #endif
3897 
3898     for (i=0; i<n_gpkgs; i++) {
3899 	gpi = &gpkgs[i];
3900 	if (gpi->pkgname != NULL && !gpi_modelwin(gpi)) {
3901 	    add_package_to_menu(gpi, vwin);
3902 	}
3903     }
3904 
3905 #if PKG_DEBUG
3906     fprintf(stderr, "finished maybe_add_packages_to_menus\n");
3907 #endif
3908 }
3909 
3910 /* Called from gui_utils.c when setting up the UI for a
3911    model window.
3912 */
3913 
maybe_add_packages_to_model_menus(windata_t * vwin)3914 void maybe_add_packages_to_model_menus (windata_t *vwin)
3915 {
3916     gui_package_info *gpi;
3917     int i, err;
3918 
3919 #if MPKG_DEBUG
3920     fprintf(stderr, "starting maybe_add_packages_to_model_menus\n");
3921 #endif
3922 
3923     if (gpkgs == NULL) {
3924 	gui_package_info_init();
3925     }
3926 
3927 #if MPKG_DEBUG
3928     fprintf(stderr, "  n_gpkgs = %d\n", n_gpkgs);
3929 #endif
3930 
3931     for (i=0; i<n_gpkgs; i++) {
3932 	gpi = &gpkgs[i];
3933 	if (gpi->pkgname != NULL && gpi_modelwin(gpi)) {
3934 	    err = maybe_add_model_pkg(gpi, vwin);
3935 	    if (err) {
3936 		if (err == E_FOPEN && gpi_sysfile(gpi)) {
3937 		    ;
3938 		} else {
3939 		    /* delete entry from registry */
3940 		    gui_function_pkg_unregister(gpi->pkgname);
3941 		}
3942 	    }
3943 	}
3944     }
3945 }
3946 
3947 /* Below: apparatus for activation when the user installs a function
3948    package (other than an official addon) from the gretl server.
3949 
3950    We check to see if (a) the package offers a menu attachment, and if
3951    so (b) that the package is not already "registered" in the user's
3952    packages.xml file. If both of these conditions are met we put up a
3953    dialog asking if the user wants to add the package to the menu
3954    system. If the answer is Yes we write an appropriate entry into
3955    packages.xml, or write this file from scratch if it doesn't yet
3956    exist.
3957 */
3958 
3959 /* Find out where the package is supposed to attach: the
3960    @mpath string (which gets into the gfn file from its
3961    associated spec file or the GUI) should look something like
3962 
3963    MODELWIN/Analysis or
3964    MAINWIN/Model
3965 
3966    The first portion just tells us in which window it should
3967    appear.
3968 */
3969 
pkg_get_attachment(const gchar * mpath,int * modelwin)3970 static gchar *pkg_get_attachment (const gchar *mpath,
3971 				  int *modelwin)
3972 {
3973     const gchar *src = mpath;
3974     gchar *relpath = NULL;
3975 
3976 #if PKG_DEBUG
3977     fprintf(stderr, "pkg_get_attachment: mpath = '%s'\n", mpath);
3978 #endif
3979 
3980     if (!strncmp(mpath, "MAINWIN/", 8)) {
3981 	src = mpath + 7;
3982     } else if (!strncmp(mpath, "menubar/", 8)) {
3983 	/* backward compatibility for old packages */
3984 	src = mpath + 7;
3985     } else if (!strncmp(mpath, "MODELWIN/", 9)) {
3986 	src = mpath + 8;
3987 	*modelwin = 1;
3988     }
3989 
3990     if (!strcmp(src, "/Model/TSModels/TSMulti")) {
3991 	relpath = g_strdup("/Model/TSMulti");
3992     } else {
3993 	relpath = g_strdup(src);
3994     }
3995 
3996     return relpath;
3997 }
3998 
pkg_attach_query(const gchar * name,const gchar * label,const gchar * relpath,int modelwin,GtkWidget * parent)3999 static int pkg_attach_query (const gchar *name,
4000 			     const gchar *label,
4001 			     const gchar *relpath,
4002 			     int modelwin,
4003 			     GtkWidget *parent)
4004 {
4005     int resp = -1;
4006 
4007     if (relpath != NULL && *relpath != '\0') {
4008 	const gchar *window_names[] = {
4009 	    N_("main window"),
4010 	    N_("model window")
4011 	};
4012 	gchar *msg, *ustr = NULL;
4013 
4014 	ustr = user_friendly_menu_path(relpath, modelwin);
4015 	if (ustr == NULL) {
4016 	    errbox_printf("Invalid menu path '%s'", relpath);
4017 	} else {
4018 	    msg = g_strdup_printf(_("The package %s can be attached to the "
4019 				    "gretl menus\n"
4020 				    "as \"%s/%s\" in the %s.\n"
4021 				    "Do you want to do this?"),
4022 				  name, ustr ? ustr : relpath, _(label),
4023 				  modelwin ? _(window_names[1]) :
4024 				  _(window_names[0]));
4025 	    resp = yes_no_dialog(NULL, msg, parent);
4026 	    g_free(msg);
4027 	    g_free(ustr);
4028 	}
4029     }
4030 
4031     return resp;
4032 }
4033 
4034 /* Called from fnsave.c, when edits to a function package
4035    are being saved.
4036 */
4037 
gui_function_pkg_revise_status(const gchar * pkgname,const gchar * fname,const gchar * label,const gchar * mpath,gboolean uses_subdir,DataReq dreq,int modelreq)4038 int gui_function_pkg_revise_status (const gchar *pkgname,
4039 				    const gchar *fname,
4040 				    const gchar *label,
4041 				    const gchar *mpath,
4042 				    gboolean uses_subdir,
4043 				    DataReq dreq,
4044 				    int modelreq)
4045 {
4046     gui_package_info *gpi;
4047     int has_attachment = 0;
4048     int do_update = 0;
4049     int err = 0;
4050 
4051     /* In this context we may, in principle, be adding,
4052        removing, or revising the gui-menu status of
4053        a package.
4054     */
4055 
4056     if (label != NULL && mpath != NULL) {
4057 	has_attachment = 1;
4058     }
4059 
4060     gpi = get_gpi_entry(pkgname);
4061 
4062     if (gpi == NULL) {
4063 	/* not in registry yet */
4064 	if (has_attachment) {
4065 	    do_update = 1;
4066 	}
4067     } else {
4068 	/* already in registry */
4069 	if (has_attachment) {
4070 	    do_update = 1;
4071 	} else {
4072 	    gui_function_pkg_unregister(pkgname);
4073 	}
4074     }
4075 
4076     if (do_update) {
4077 	gchar *relpath;
4078 	int modelwin = 0;
4079 
4080 	relpath = pkg_get_attachment(mpath, &modelwin);
4081 	err = update_gui_package_info(pkgname,
4082 				      fname,
4083 				      label,
4084 				      relpath,
4085 				      modelwin,
4086 				      uses_subdir,
4087 				      dreq,
4088 				      modelreq);
4089 	if (err) {
4090 	    gui_errmsg(err);
4091 	}
4092 	g_free(relpath);
4093     }
4094 
4095     return err;
4096 }
4097 
pkg_get_data_requirement(GtkActionGroup * ag)4098 DataReq pkg_get_data_requirement (GtkActionGroup *ag)
4099 {
4100     int i;
4101 
4102     for (i=0; i<n_gpkgs; i++) {
4103 	if (gpkgs[i].ag == ag) {
4104 	    return gpkgs[i].dreq;
4105 	}
4106     }
4107 
4108     return 0;
4109 }
4110 
4111 /* Remove a package from the in-memory representation of
4112    menu-attached packages.
4113 */
4114 
gui_function_pkg_unregister(const gchar * pkgname)4115 void gui_function_pkg_unregister (const gchar *pkgname)
4116 {
4117     gui_package_info *gpi;
4118 
4119     gpi = get_gpi_entry(pkgname);
4120     if (gpi != NULL) {
4121 	clear_gpi_entry(gpi);
4122     }
4123 
4124     /* sync the package registry window, if it happens to
4125        be open currently */
4126     maybe_update_pkg_registry_window(pkgname, DELETE_FN_PKG);
4127 }
4128 
in_own_subdir(const char * pkgname,const char * path)4129 static int in_own_subdir (const char *pkgname, const char *path)
4130 {
4131     gchar *test;
4132     int ret = 0;
4133 
4134     /* e.g. "mypkg/mypkg" */
4135     test = g_strdup_printf("%s%c%s", pkgname, SLASH, pkgname);
4136 
4137     if (strstr(path, test) != NULL) {
4138 	ret = 1;
4139     } else {
4140 	gretl_errmsg_sprintf("The function file %s.gfn is not installed correctly:\n"
4141 			     "it should be in a subdirectory named '%s'.",
4142 			     pkgname, pkgname);
4143     }
4144 
4145     g_free(test);
4146 
4147     return ret;
4148 }
4149 
4150 /* Actually do the business of registering a function package
4151    to appear in a menu */
4152 
gui_function_pkg_register(const char * fname,const char * pkgname,const char * label,const char * relpath,int modelwin)4153 static int gui_function_pkg_register (const char *fname,
4154 				      const char *pkgname,
4155 				      const char *label,
4156 				      const char *relpath,
4157 				      int modelwin)
4158 {
4159     GtkWidget *editor;
4160     fnpkg *pkg = NULL;
4161     int err = 0;
4162 
4163     if (package_being_edited(pkgname, &editor)) {
4164 	pkg = package_editor_get_pkg(editor);
4165     }
4166 
4167     if (pkg == NULL) {
4168 	pkg = get_function_package_by_filename(fname, &err);
4169     }
4170 
4171     if (pkg == NULL) {
4172 	errbox_printf(_("Couldn't read '%s'"), fname);
4173 	return E_FOPEN;
4174     }
4175 
4176 #if PKG_DEBUG
4177     fprintf(stderr, "gui_function_pkg_register: %s: err = %d\n", fname, err);
4178 #endif
4179 
4180     if (!err) {
4181 	int uses_subdir = 0;
4182 	DataReq dreq = 0;
4183 	int modelreq = 0;
4184 
4185 	err = function_package_get_properties(pkg,
4186 					      "lives-in-subdir",
4187 					      &uses_subdir,
4188 					      "data-requirement",
4189 					      &dreq,
4190 					      "model-requirement",
4191 					      &modelreq,
4192 					      NULL);
4193 
4194 	if (!err && !uses_subdir) {
4195 	    /* fallback detection: packages that have PDF doc
4196 	       must be in their own subdir */
4197 	    uses_subdir = function_package_has_PDF_doc(pkg, NULL);
4198 	}
4199 
4200 	if (!err && uses_subdir && !in_own_subdir(pkgname, fname)) {
4201 	    /* detect mis-installed package: should be in
4202 	       own subdirectory but is not */
4203 	    err = E_DATA;
4204 	}
4205 
4206 	if (!err) {
4207 	    err = update_gui_package_info(pkgname,
4208 					  fname,
4209 					  label,
4210 					  relpath,
4211 					  modelwin,
4212 					  uses_subdir,
4213 					  dreq,
4214 					  modelreq);
4215 	}
4216     }
4217 
4218     if (err) {
4219 	gui_errmsg(err);
4220     }
4221 
4222     return err;
4223 }
4224 
4225 /* The following is called in two contexts:
4226 
4227    (1) From the handler for installing a function package from the
4228    gretl server.
4229 
4230    (2) From the popup menu-item or button "Add to menu" in the window
4231    displaying installed function packages.
4232 
4233    We return non-zero if we show a dialog here: that's for the
4234    benefit of the installation handler, to tell it not to put
4235    up a second, redundant confirmation dialog.
4236 */
4237 
gui_function_pkg_query_register(const char * fname,GtkWidget * parent)4238 int gui_function_pkg_query_register (const char *fname,
4239 				     GtkWidget *parent)
4240 {
4241     char *pkgname = NULL;
4242     char *menupath = NULL;
4243     char *label = NULL;
4244     int notified = 0;
4245 
4246     if (package_has_menu_attachment(fname, &pkgname, &menupath,
4247 				    &label)) {
4248 	gchar *relpath;
4249 	int resp, modelwin = 0;
4250 
4251 	relpath = pkg_get_attachment(menupath, &modelwin);
4252 	resp = pkg_attach_query(pkgname, label, relpath,
4253 				modelwin, parent);
4254 	if (resp == GRETL_YES) {
4255 	    gui_function_pkg_register(fname, pkgname,
4256 				      label, relpath,
4257 				      modelwin);
4258 	}
4259 	notified = 1;
4260 	g_free(relpath);
4261     }
4262 
4263     free(pkgname);
4264     free(menupath);
4265     free(label);
4266 
4267     return notified;
4268 }
4269 
installed_addon_status_string(const char * path,const char * svstr,int minver)4270 char *installed_addon_status_string (const char *path,
4271 				     const char *svstr,
4272 				     int minver)
4273 {
4274     char *ivstr = NULL;
4275     char *ret = NULL;
4276 
4277     /* @ivstr = installed package version string
4278        @svstr = package version string from server
4279        @minver = gretl version required for pkg on server
4280     */
4281 
4282     ivstr = get_addon_version(path, NULL);
4283 
4284     if (ivstr != NULL) {
4285 	double svnum = dot_atof(svstr);
4286 	double ivnum = dot_atof(ivstr);
4287 	int current = 0;
4288 	int update_ok = 0;
4289 	char reqstr[8] = {0};
4290 
4291 	current = ivnum >= svnum;
4292 
4293 	if (!current) {
4294 	    /* Not current, but can the addon be updated?  It may
4295 	       be that the running instance of gretl is too old.
4296 	    */
4297 	    update_ok = package_version_ok(minver, reqstr);
4298 	}
4299 
4300 	if (current) {
4301 	    ret = gretl_strdup(_("Up to date"));
4302 	} else if (update_ok) {
4303 	    ret = gretl_strdup(_("Not up to date"));
4304 	} else if (*reqstr != '\0') {
4305 	    ret = gretl_strdup_printf(_("Requires gretl %s"), reqstr);
4306 	}
4307 	free(ivstr);
4308     }
4309 
4310     if (ret == NULL) {
4311 	ret = gretl_strdup(_("Error reading package"));
4312     }
4313 
4314     return ret;
4315 }
4316 
4317 /* We invoke this function on the two GUI "entry-points" to
4318    dbnomics, namely retrieving a specified series and getting
4319    the current list of providers. We thereby ensure that if
4320    the dbnomics function package is not found on the local
4321    machine we try to download and install it.
4322 
4323    We also invoke it for regls, which requires a distinct
4324    saved path.
4325 */
4326 
get_addon_function_call(const char * addon,const char * funcname)4327 static fncall *get_addon_function_call (const char *addon,
4328 					const char *funcname)
4329 {
4330     static char *dbnpath;
4331     static char *rlspath;
4332     char **ppkgpath = NULL;
4333     fncall *fc = NULL;
4334     int err = 0;
4335 
4336     if (!strcmp(addon, "dbnomics")) {
4337 	ppkgpath = &dbnpath;
4338     } else if (!strcmp(addon, "regls")) {
4339 	ppkgpath = &rlspath;
4340     } else {
4341 	err = E_DATA;
4342     }
4343 
4344     if (!err && *ppkgpath == NULL) {
4345 	*ppkgpath = gretl_addon_get_path(addon);
4346 	if (*ppkgpath == NULL) {
4347 	    /* not found locally */
4348 	    err = download_addon(addon, ppkgpath);
4349 	}
4350     }
4351 
4352     if (!err && *ppkgpath != NULL) {
4353 	fc = get_pkg_function_call(funcname, addon, *ppkgpath);
4354     }
4355 
4356     return fc;
4357 }
4358 
dbnomics_report_error(const char * datacode,gretl_bundle * b,PRN ** pprn)4359 static void dbnomics_report_error (const char *datacode,
4360 				   gretl_bundle *b,
4361 				   PRN **pprn)
4362 {
4363     const char *buf = gretl_print_get_buffer(*pprn);
4364 
4365     if (!string_is_blank(buf)) {
4366 	/* show what we got via PRN */
4367 	gchar *title = g_strdup_printf("gretl: %s", datacode);
4368 
4369 	view_buffer(*pprn, 78, 200, title, IMPORT, NULL);
4370 	*pprn = NULL; /* ownership taken by viewer */
4371 	g_free(title);
4372     } else {
4373 	const char *errmsg = gretl_bundle_get_string(b, "errmsg", NULL);
4374 
4375 	if (!string_is_blank(errmsg)) {
4376 	    errbox(errmsg);
4377 	} else {
4378 	    /* fallback */
4379 	    gchar *msg = g_strdup_printf(_("%s: no data found"), datacode);
4380 
4381 	    errbox(msg);
4382 	    g_free(msg);
4383 	}
4384     }
4385 }
4386 
4387 /* below: callbacks from regular gretl GUI menu items/buttons
4388    that invoke calls to the dbnomics package in the background
4389 */
4390 
dbnomics_get_series_call(const char * datacode)4391 int dbnomics_get_series_call (const char *datacode)
4392 {
4393     gretl_bundle *b = NULL;
4394     fncall *fc = NULL;
4395     PRN *prn = NULL;
4396     int err = 0;
4397 
4398     err = bufopen(&prn);
4399 
4400     if (!err) {
4401 	fc = get_addon_function_call("dbnomics", "dbnomics_get_series");
4402 	if (fc == NULL) {
4403 	    gretl_print_destroy(prn);
4404 	    err = E_DATA;
4405 	}
4406     }
4407 
4408     if (err) {
4409 	return err;
4410     }
4411 
4412     err = push_anon_function_arg(fc, GRETL_TYPE_STRING, (void *) datacode);
4413     if (!err) {
4414 	err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, dataset,
4415 				  &b, NULL, prn);
4416 	if (err) {
4417 	    gui_errmsg(err);
4418 	}
4419     }
4420 
4421     if (b != NULL) {
4422 	int dberr = gretl_bundle_get_int(b, "error", &err);
4423 
4424 	if (dberr) {
4425 	    /* we need to handle the case where dbnomics failed
4426 	       but did not provide any error message
4427 	    */
4428 	    dbnomics_report_error(datacode, b, &prn);
4429 	    gretl_bundle_destroy(b);
4430 	} else {
4431 	    const char *p = strrchr(datacode, '/');
4432 	    gchar *title;
4433 
4434 	    title = g_strdup_printf("gretl: %s", p + 1);
4435 	    fc = get_pkg_function_call("dbnomics_bundle_print", "dbnomics", NULL);
4436 	    if (fc != NULL) {
4437 		err = push_anon_function_arg(fc, GRETL_TYPE_BUNDLE, (void *) b);
4438 		if (!err) {
4439 		    err = gretl_function_exec(fc, GRETL_TYPE_NONE, dataset,
4440 					      NULL, NULL, prn);
4441 		    if (err) {
4442 			gui_errmsg(err);
4443 		    } else {
4444 			view_buffer(prn, 78, 350, title, VIEW_DBNOMICS, b);
4445 			prn = NULL; /* ownership taken by viewer */
4446 		    }
4447 		}
4448 	    }
4449 	    g_free(title);
4450 	}
4451     }
4452 
4453     gretl_print_destroy(prn);
4454 
4455     return err;
4456 }
4457 
dbnomics_get_dimensions_call(const char * provider,const char * dsname)4458 int dbnomics_get_dimensions_call (const char *provider,
4459 				  const char *dsname)
4460 {
4461     fncall *fc = NULL;
4462     double one = 1;
4463     PRN *prn = NULL;
4464     int err;
4465 
4466     err = bufopen(&prn);
4467 
4468     if (!err) {
4469 	fc = get_addon_function_call("dbnomics", "dbnomics_get_dataset_dimensions");
4470 	if (fc == NULL) {
4471 	    gretl_print_destroy(prn);
4472 	    err = E_DATA;
4473 	}
4474     }
4475 
4476     if (err) {
4477 	return err;
4478     }
4479 
4480     pprintf(prn, "Information on dbnomics dataset %s/%s (may be quite voluminous)\n\n",
4481 	    provider, dsname);
4482     pputs(prn, "This may indicate (as applicable):\n"
4483 	  " * topics covered by the dataset\n"
4484 	  " * countries included\n"
4485 	  " * units of measurement\n"
4486 	  " * other information\n\n");
4487 
4488     err = push_anon_function_arg(fc, GRETL_TYPE_STRING, (void *) provider);
4489     if (!err) {
4490 	err = push_anon_function_arg(fc, GRETL_TYPE_STRING, (void *) dsname);
4491     }
4492     if (!err) {
4493 	/* verbosity */
4494 	err = push_anon_function_arg(fc, GRETL_TYPE_DOUBLE, (void *) &one);
4495     }
4496     if (!err) {
4497 	GdkWindow *cwin = NULL;
4498 
4499 	set_wait_cursor(&cwin);
4500 	err = gretl_function_exec(fc, GRETL_TYPE_NONE, dataset,
4501 				  NULL, NULL, prn);
4502 	unset_wait_cursor(cwin);
4503     }
4504 
4505     if (err) {
4506 	gui_errmsg(err);
4507 	gretl_print_destroy(prn);
4508     } else {
4509 	gchar *title;
4510 
4511 	title = g_strdup_printf("gretl: %s/%s", provider, dsname);
4512 	view_buffer(prn, 80, 500, title, PRINT, NULL);
4513 	g_free(title);
4514     }
4515 
4516     return err;
4517 }
4518 
dbnomics_get_providers_call(int * err)4519 void *dbnomics_get_providers_call (int *err)
4520 {
4521     gretl_array *A = NULL;
4522     fncall *fc = NULL;
4523     GdkWindow *cwin = NULL;
4524 
4525     fc = get_addon_function_call("dbnomics", "dbnomics_providers");
4526     if (fc == NULL) {
4527 	*err = E_DATA;
4528 	return NULL;
4529     }
4530 
4531     set_wait_cursor(&cwin);
4532     *err = gretl_function_exec(fc, GRETL_TYPE_BUNDLES, dataset,
4533 			       &A, NULL, NULL);
4534     unset_wait_cursor(cwin);
4535     if (*err) {
4536 	gui_errmsg(*err);
4537     }
4538 
4539     return A;
4540 }
4541 
dbnomics_search_call(const char * key,const char * prov,const char * dset,int limit,int offset,int * err)4542 void *dbnomics_search_call (const char *key,
4543 			    const char *prov,
4544 			    const char *dset,
4545 			    int limit, int offset,
4546 			    int *err)
4547 {
4548     gretl_array *A = NULL;
4549     fncall *fc = NULL;
4550     int use_dset = 0;
4551 
4552     if (prov != NULL && dset != NULL) {
4553 	use_dset = 1;
4554 	fc = get_pkg_function_call("dset_search", "dbnomics", NULL);
4555     } else {
4556 	fc = get_pkg_function_call("general_search", "dbnomics", NULL);
4557     }
4558     if (fc == NULL) {
4559 	*err = E_DATA;
4560 	return NULL;
4561     }
4562 
4563     if (use_dset) {
4564 	*err = push_function_args(fc, GRETL_TYPE_STRING, (void *) key,
4565 				  GRETL_TYPE_STRING, (void *) prov,
4566 				  GRETL_TYPE_STRING, (void *) dset,
4567 				  GRETL_TYPE_INT, (void *) &limit,
4568 				  GRETL_TYPE_INT, (void *) &offset, -1);
4569     } else {
4570 	*err = push_function_args(fc, GRETL_TYPE_STRING, (void *) key,
4571 				  GRETL_TYPE_INT, (void *) &limit,
4572 				  GRETL_TYPE_INT, (void *) &offset, -1);
4573     }
4574 
4575     if (!*err) {
4576 	GdkWindow *cwin = NULL;
4577 
4578 	set_wait_cursor(&cwin);
4579 	*err = gretl_function_exec(fc, GRETL_TYPE_BUNDLES, dataset,
4580 				   &A, NULL, NULL);
4581 	unset_wait_cursor(cwin);
4582     }
4583 
4584     if (*err) {
4585 	gui_errmsg(*err);
4586     }
4587 
4588     return A;
4589 }
4590 
dbnomics_dataset_list(const char * provider,int * err)4591 void *dbnomics_dataset_list (const char *provider, int *err)
4592 {
4593     gretl_bundle *b = NULL;
4594     fncall *fc = NULL;
4595 
4596     fc = get_pkg_function_call("dbnomics_dsets_for_provider",
4597 			       "dbnomics", NULL);
4598     if (fc == NULL) {
4599 	*err = E_DATA;
4600 	return NULL;
4601     }
4602 
4603     *err = push_anon_function_arg(fc, GRETL_TYPE_STRING, (void *) provider);
4604     if (!*err) {
4605 	GdkWindow *cwin = NULL;
4606 
4607 	set_wait_cursor(&cwin);
4608 	*err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, dataset,
4609 				   &b, NULL, NULL);
4610 	unset_wait_cursor(cwin);
4611     }
4612     if (*err) {
4613 	gui_errmsg(*err);
4614     }
4615 
4616     return b;
4617 }
4618 
dbnomics_probe_series(const char * prov,const char * dset,int limit,int offset,int * err)4619 void *dbnomics_probe_series (const char *prov,
4620 			     const char *dset,
4621 			     int limit, int offset,
4622 			     int *err)
4623 {
4624     gretl_array *A = NULL;
4625     fncall *fc = NULL;
4626 
4627     fc = get_pkg_function_call("dbnomics_get_dataset_content",
4628 			       "dbnomics", NULL);
4629     if (fc == NULL) {
4630 	*err = E_DATA;
4631 	return NULL;
4632     }
4633 
4634     *err = push_function_args(fc, GRETL_TYPE_STRING, (void *) prov,
4635 			      GRETL_TYPE_STRING, (void *) dset,
4636 			      GRETL_TYPE_INT, (void *) &limit,
4637 			      GRETL_TYPE_INT, (void *) &offset, -1);
4638     if (!*err) {
4639 	GdkWindow *cwin = NULL;
4640 
4641 	set_wait_cursor(&cwin);
4642 	*err = gretl_function_exec(fc, GRETL_TYPE_BUNDLES, dataset,
4643 				   &A, NULL, NULL);
4644 	unset_wait_cursor(cwin);
4645     }
4646 
4647     if (*err) {
4648 	gui_errmsg(*err);
4649     }
4650 
4651     return A;
4652 }
4653 
real_do_regls(const char * buf)4654 int real_do_regls (const char *buf)
4655 {
4656     gretl_bundle *parms = selector_get_regls_bundle();
4657     gretl_bundle *rb = NULL;
4658     fncall *fc = NULL;
4659     int orig_v;
4660     int *X = NULL;
4661     PRN *prn = NULL;
4662     int err = 0;
4663 
4664     if (parms == NULL) {
4665 	errbox("regls: no parameters bundle");
4666 	return E_DATA;
4667     }
4668 
4669     fc = get_addon_function_call("regls", "regls");
4670     if (fc == NULL) {
4671 	errbox("regls: couldn't find regls()");
4672 	return E_DATA;
4673     }
4674 
4675     bufopen(&prn);
4676     orig_v = dataset->v;
4677 
4678     X = generate_list(buf, dataset, &err);
4679     if (!err) {
4680 	int yno = X[1];
4681 
4682 	gretl_list_delete_at_pos(X, 1);
4683 	err = push_function_arg(fc, dataset->varname[yno], NULL,
4684 				GRETL_TYPE_USERIES, &yno);
4685 	if (!err) {
4686 	    err = push_function_args(fc, GRETL_TYPE_LIST, (void *) X,
4687 				     GRETL_TYPE_BUNDLE, (void *) parms, -1);
4688 	}
4689     }
4690 
4691     if (!err) {
4692 	GdkWindow *cwin = NULL;
4693 
4694 	set_wait_cursor(&cwin);
4695 	err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, dataset,
4696 				  &rb, NULL, prn);
4697 	unset_wait_cursor(cwin);
4698 	if (!err) {
4699 	    view_buffer(prn, 78, 350, "gretl: regls", VIEW_BUNDLE, rb);
4700 	    prn = NULL; /* ownership taken by viewer */
4701 	}
4702 	if (dataset->v > orig_v) {
4703 	    /* in case any lags got added */
4704 	    populate_varlist();
4705 	}
4706     }
4707 
4708     if (err) {
4709 	gui_errmsg(err);
4710     }
4711 
4712     free(X);
4713     gretl_print_destroy(prn);
4714 
4715     return err;
4716 }
4717 
4718 /* geomap related functions */
4719 
plausible_payload_list(int v,int * selpos)4720 static GList *plausible_payload_list (int v, int *selpos)
4721 {
4722     GList *list = NULL;
4723     int i, j = 1;
4724 
4725     for (i=dataset->v-1; i>0; i--) {
4726 	if (!is_string_valued(dataset, i) &&
4727 	    !gretl_isconst(dataset->t1, dataset->t2, dataset->Z[i])) {
4728 	    list = g_list_append(list, (gpointer) dataset->varname[i]);
4729 	    if (i == v) {
4730 		*selpos = j;
4731 	    }
4732 	    j++;
4733 	}
4734     }
4735 
4736     if (list != NULL) {
4737 	list = g_list_prepend(list, (gpointer) "none");
4738     }
4739 
4740     return list;
4741 }
4742 
4743 /* Called in response to "Display map" */
4744 
map_plot_callback(int v)4745 void map_plot_callback (int v)
4746 {
4747     const char *mapfile = dataset_get_mapfile(dataset);
4748 
4749     if (mapfile == NULL) {
4750 	errbox(_("No mapfile is present"));
4751     } else {
4752 	gretl_bundle *opts = NULL;
4753 	GList *payload_list = NULL;
4754 	double *payload = NULL;
4755 	int payload_id = 0;
4756 	int resp, selpos = 0;
4757 	int err = 0;
4758 
4759 	opts = gretl_bundle_new();
4760 	gretl_bundle_set_int(opts, "gui_auto", 1);
4761 	payload_list = plausible_payload_list(v, &selpos);
4762 
4763 	/* get options from the user */
4764 	resp = map_options_dialog(payload_list, selpos,
4765 				  opts, &payload_id);
4766 	if (resp == GRETL_CANCEL) {
4767 	    return;
4768 	}
4769 	if (payload_list != NULL) {
4770 	    g_list_free(payload_list);
4771 	}
4772 	if (payload_id == 0) {
4773 	    /* just showing outlines */
4774 	    gretl_bundle_set_int(opts, "tics", 1);
4775 	} else {
4776 	    payload = dataset->Z[payload_id];
4777 	}
4778 	err = geoplot_driver(mapfile, NULL, payload, dataset, opts);
4779 	if (err) {
4780 	    gui_errmsg(err);
4781 	} else {
4782             gchar *mapname = g_path_get_basename(mapfile);
4783 
4784             gretl_bundle_set_string(opts, "mapname", mapname);
4785             gnuplot_show_map(opts);
4786             g_free(mapname);
4787 	}
4788 	gretl_bundle_destroy(opts);
4789     }
4790 }
4791