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 /* dialogs.c for gretl */
21 
22 #include "gretl.h"
23 #include "cmdstack.h"
24 #include "session.h"
25 #include "obsbutton.h"
26 #include "textutil.h"
27 #include "menustate.h"
28 #include "dlgutils.h"
29 #include "treeutils.h"
30 #include "ssheet.h"
31 #include "database.h"
32 #include "selector.h"
33 #include "fileselect.h"
34 #include "winstack.h"
35 #include "gretl_panel.h"
36 #include "gretl_midas.h"
37 #include "texprint.h"
38 #include "forecast.h"
39 #include "console.h"
40 #include "libset.h"
41 #include "uservar.h"
42 #include "gretl_bfgs.h"
43 #include "libglue.h"
44 
45 #include <errno.h>
46 
47 static GtkWidget *option_spinbox (int *spinvar, const char *spintxt,
48                                   int spinmin, int spinmax,
49                                   int hcode, gpointer p);
50 static GtkWidget *option_checkbox (int *checkvar, const char *checktxt);
51 static void set_radio_opt (GtkWidget *w, int *opt);
52 static GtkWidget *dialog_blurb_box (const char *text);
53 
menu_exit_check(void)54 void menu_exit_check (void)
55 {
56     if (!exit_check()) {
57         gtk_main_quit();
58     }
59 }
60 
61 /* This callback is invoked if the user is quitting a session and (a)
62    the session is not associated with a file on disk (in which case
63    the data-save is automatic if the session is saved) and (b) the
64    dataset has been modified.
65 */
66 
save_data_callback(void)67 static void save_data_callback (void)
68 {
69     data_export_selection_wrapper(SAVE_DATA);
70     if (data_status & MODIFIED_DATA) {
71         data_status ^= MODIFIED_DATA;
72     }
73     /* FIXME: need to do more here? */
74 }
75 
gretl_dialog_keep_above(GtkWidget * w)76 static void gretl_dialog_keep_above (GtkWidget *w)
77 {
78     /* note: this could be ifdef'd out if not wanted */
79     gtk_window_set_keep_above(GTK_WINDOW(w), TRUE);
80 }
81 
gretl_dialog_add_message(GtkWidget * dlg,const char * msg)82 void gretl_dialog_add_message (GtkWidget *dlg, const char *msg)
83 {
84     GtkWidget *hbox, *vbox;
85     GtkWidget *label;
86 
87     hbox = gtk_hbox_new(FALSE, 0);
88     label = gtk_label_new(msg);
89     gtk_widget_show(label);
90     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 12);
91     gtk_widget_show(hbox);
92 
93     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
94     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 12);
95 }
96 
97 static gint
real_yes_no_dialog(const char * title,const char * msg,int cancel,GtkWidget * parent,int default_id)98 real_yes_no_dialog (const char *title, const char *msg,
99                     int cancel, GtkWidget *parent,
100                     int default_id)
101 {
102     GtkDialogFlags flags = GTK_DIALOG_MODAL;
103     GtkWidget *dlg;
104     int ret = GTK_RESPONSE_HELP;
105 
106     if (title == NULL) {
107         title = "gretl";
108     }
109 
110     if (parent != NULL) {
111         flags |= GTK_DIALOG_DESTROY_WITH_PARENT;
112     } else if (mdata != NULL && mdata->main != NULL) {
113         parent = mdata->main;
114         flags |= GTK_DIALOG_DESTROY_WITH_PARENT;
115     }
116 
117     dlg = gtk_dialog_new_with_buttons(title,
118                                       GTK_WINDOW(parent),
119                                       flags,
120                                       GTK_STOCK_YES,
121                                       GTK_RESPONSE_ACCEPT,
122                                       GTK_STOCK_NO,
123                                       GTK_RESPONSE_NO,
124                                       NULL);
125 
126     if (cancel) {
127         gtk_dialog_add_button(GTK_DIALOG(dlg),
128                               GTK_STOCK_CANCEL,
129                               GTK_RESPONSE_REJECT);
130     }
131 
132     if (default_id != 0) {
133         gtk_dialog_set_default_response(GTK_DIALOG(dlg), default_id);
134     }
135 
136     gretl_dialog_add_message(dlg, msg);
137 
138 #if GTK_MAJOR_VERSION < 3
139     gtk_dialog_set_has_separator(GTK_DIALOG(dlg), FALSE);
140 #endif
141     gtk_window_set_keep_above(GTK_WINDOW(dlg), TRUE);
142     ret = gtk_dialog_run(GTK_DIALOG(dlg));
143 
144     gtk_widget_destroy(dlg);
145 
146     switch (ret) {
147     case GTK_RESPONSE_ACCEPT:
148         return GRETL_YES;
149     case GTK_RESPONSE_NO:
150         return GRETL_NO;
151     default:
152         return GRETL_CANCEL;
153     }
154 }
155 
yes_no_dialog(const char * title,const char * msg,GtkWidget * parent)156 gint yes_no_dialog (const char *title,
157                     const char *msg,
158                     GtkWidget *parent)
159 {
160     return real_yes_no_dialog(title, msg, 0, parent, 0);
161 }
162 
yes_no_cancel_dialog(const char * title,const char * msg,GtkWidget * parent)163 gint yes_no_cancel_dialog (const char *title,
164                            const char *msg,
165                            GtkWidget *parent)
166 {
167     return real_yes_no_dialog(title, msg, 1, parent, 0);
168 }
169 
no_yes_dialog(const char * title,const char * msg)170 gint no_yes_dialog (const char *title, const char *msg)
171 {
172     return real_yes_no_dialog(title, msg, 0, NULL,
173                               GTK_RESPONSE_NO);
174 }
175 
toggle_session_prompt(GtkToggleButton * b)176 static void toggle_session_prompt (GtkToggleButton *b)
177 {
178     set_session_prompt(button_is_active(b));
179 }
180 
set_ret_no(GtkButton * b,int * ret)181 static void set_ret_no (GtkButton *b, int *ret)
182 {
183     *ret = GRETL_NO;
184 }
185 
set_ret_yes(GtkButton * b,int * ret)186 static void set_ret_yes (GtkButton *b, int *ret)
187 {
188     *ret = GRETL_YES;
189 }
190 
save_session_prompt(int gui_session)191 static int save_session_prompt (int gui_session)
192 {
193     const char *gui_msg =
194         N_("Do you want to save this gretl session?");
195     const char *cmds_msg =
196         N_("Save a record of the commands you executed?");
197     const char *check_msg =
198         N_("Always prompt if there are unsaved changes");
199     GtkWidget *dialog;
200     GtkWidget *vbox, *hbox, *tmp, *b;
201     gchar *title;
202     int ret = GRETL_CANCEL;
203 
204     title = g_strdup_printf("gretl: %s", gui_session ?
205                             _("save session") : _("save commands"));
206     dialog = gretl_dialog_new(title, NULL, GRETL_DLG_BLOCK);
207     g_free(title);
208 
209     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
210 
211     /* label */
212     tmp = dialog_blurb_box(gui_session ? _(gui_msg) : _(cmds_msg));
213     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
214 
215     /* check button */
216     b = gtk_check_button_new_with_label(_(check_msg));
217     gtk_box_pack_start(GTK_BOX(vbox), b, TRUE, TRUE, 0);
218     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), session_prompt_on());
219     g_signal_connect(G_OBJECT(b), "clicked",
220                      G_CALLBACK(toggle_session_prompt), NULL);
221 
222     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
223 
224     /* "Yes" button */
225     b = gtk_button_new_from_stock(GTK_STOCK_YES);
226     gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 0);
227     g_signal_connect(G_OBJECT(b), "clicked",
228                      G_CALLBACK(set_ret_yes), &ret);
229     g_signal_connect(G_OBJECT(b), "clicked",
230                      G_CALLBACK(delete_widget),
231                      dialog);
232 
233     gtk_widget_set_can_default(b, TRUE);
234     gtk_widget_grab_default(b);
235     gtk_widget_grab_focus(b);
236 
237     /* "No" button */
238     b = gtk_button_new_from_stock(GTK_STOCK_NO);
239     gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 0);
240     g_signal_connect(G_OBJECT(b), "clicked",
241                      G_CALLBACK(set_ret_no), &ret);
242     g_signal_connect(G_OBJECT(b), "clicked",
243                      G_CALLBACK(delete_widget),
244                      dialog);
245 
246     /* Cancel button */
247     cancel_delete_button(hbox, dialog);
248 
249     /* "Help" button */
250     context_help_button(hbox, gui_session ? SAVE_SESSION :
251                         SAVE_CMD_LOG);
252 
253     gtk_widget_show_all(dialog);
254 
255     return ret;
256 }
257 
258 /* exit_check: returning FALSE allows the exit to proceed;
259    to block the exit we return TRUE.
260 */
261 
exit_check(void)262 gboolean exit_check (void)
263 {
264     int resp, datamod, status = 0;
265     int err = 0;
266 
267     if (maybe_raise_dialog() || console_is_busy()) {
268         /* we're not ready: block the exit now */
269         return TRUE;
270     }
271 
272     if (window_list_exit_check()) {
273         /* got cancel exit message from an editor window */
274         return TRUE;
275     }
276 
277     datamod = (data_status & MODIFIED_DATA);
278 
279     if (session_file_is_open() && (session_is_modified() || datamod)) {
280         const char *save_msg = N_("Do you want to save the changes you made\n"
281                                   "to this session?");
282 
283         resp = yes_no_cancel_dialog("gretl", _(save_msg), NULL);
284         if (resp == GRETL_YES) {
285             err = save_session(NULL);
286             if (err) {
287                 /* give the user a shot at remedial action */
288                 return TRUE;
289             }
290         } else if (resp == GRETL_CANCEL) {
291             /* canceled exit: block */
292             return TRUE;
293         }
294     } else if (session_prompt_on()) {
295         if (session_is_modified()) {
296             /* give the user the chance to save the session */
297             resp = save_session_prompt(1);
298             if (resp == GRETL_YES) {
299                 file_selector(SAVE_SESSION, FSEL_DATA_STATUS, &status);
300                 if (status != 0 && status != GRETL_CANCEL) {
301                     /* error saving session */
302                     return TRUE;
303                 }
304                 /* now provisionally allow exit to proceed */
305             } else if (resp == GRETL_CANCEL) {
306                 /* canceled exit: block */
307                 return TRUE;
308             }
309         } else if (!session_file_is_open() && get_commands_recorded()) {
310             /* give the user the chance to save commands */
311             resp = save_session_prompt(0);
312             if (resp == GRETL_YES) {
313                 file_selector(SAVE_CMD_LOG, FSEL_DATA_STATUS, &status);
314                 if (status != 0 && status != GRETL_CANCEL) {
315                     /* error saving commands */
316                     return TRUE;
317                 }
318                 /* now provisionally allow exit to proceed */
319             } else if (resp == GRETL_CANCEL) {
320                 /* canceled exit: block */
321                 return TRUE;
322             }
323         }
324     }
325 
326     if (!session_file_is_open() && (data_status & MODIFIED_DATA)) {
327         /* give the user a chance to save modified dataset */
328         resp =
329             yes_no_cancel_dialog("gretl",
330                                  _("Do you want to save changes you have\n"
331                                    "made to the current data set?"), NULL);
332         if (resp == GRETL_YES) {
333             save_data_callback();
334         } else if (resp == GRETL_CANCEL) {
335             /* the user canceled exit: block further processing */
336             return TRUE;
337         }
338     }
339 
340     write_rc(OPT_NONE);
341 
342     return FALSE;
343 }
344 
gui_double_from_string(const char * str,int * err)345 double gui_double_from_string (const char *str, int *err)
346 {
347     double x = 0;
348     char *p, s[32];
349 
350     gretl_error_clear();
351 
352     *s = '\0';
353     strncat(s, str, 31);
354     p = s + strspn(s, " ");
355     gretl_lower(p);
356 
357     if (!strcmp(p, "na") || !strcmp(p, "nan") || !strcmp(p, ".")) {
358         x = NADBL;
359     } else {
360         int sub = 0;
361 
362         if (get_local_decpoint() != '.') {
363             gretl_push_c_numeric_locale();
364             gretl_charsub(p, ',', '.');
365             sub = 1;
366         }
367 
368         *err = check_atof(p);
369 
370         if (*err) {
371             gui_errmsg(*err);
372         } else {
373             x = atof(p);
374         }
375 
376         if (sub) {
377             gretl_pop_c_numeric_locale();
378         }
379     }
380 
381     return x;
382 }
383 
hboxit(GtkWidget * w,GtkWidget * vbox)384 static GtkWidget *hboxit (GtkWidget *w, GtkWidget *vbox)
385 {
386     GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
387 
388     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
389     if (vbox != NULL) {
390         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
391     }
392 
393     return hbox;
394 }
395 
csv_na_callback(GtkComboBox * box,gpointer p)396 static void csv_na_callback (GtkComboBox *box, gpointer p)
397 {
398     gchar *s = combo_box_get_active_text(box);
399 
400     set_csv_na_write_string(s);
401     g_free(s);
402 }
403 
csv_na_combo(void)404 static GtkWidget *csv_na_combo (void)
405 {
406     GtkWidget *hbox, *label, *combo;
407     const char *na_strs[] = {
408         "NA", ".NaN", "-999", "-9999.0", "?", "."
409     };
410     const char *setna = get_csv_na_write_string();
411     int i, n = G_N_ELEMENTS(na_strs);
412     int matched = 0;
413 
414     hbox = gtk_hbox_new(FALSE, 5);
415     label = gtk_label_new(_("Print missing values as:"));
416     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
417 
418     combo = gtk_combo_box_text_new();
419     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
420     for (i=0; i<n; i++) {
421         combo_box_append_text(combo, na_strs[i]);
422         if (!strcmp(setna, na_strs[i])) {
423             matched = 1;
424         }
425     }
426 
427     if (!matched) {
428         combo_box_append_text(combo, setna);
429         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
430     } else {
431         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
432     }
433 
434     g_signal_connect(G_OBJECT(combo), "changed",
435                      G_CALLBACK(csv_na_callback), NULL);
436 
437     return hbox;
438 }
439 
440 /* CSV files: setting the delimiter, etc. */
441 
442 typedef struct {
443     GtkWidget *semic_button;
444     GtkWidget *comma_sep;
445     gint delim;     /* delimiter (comma, etc.) */
446     gint decpoint;  /* decimal character */
447     gboolean xobs;  /* exclude obs column on export? */
448 } csv_stuff;
449 
set_dec(GtkWidget * w,csv_stuff * csv)450 static void set_dec (GtkWidget *w, csv_stuff *csv)
451 {
452     gint i;
453 
454     if (button_is_active(w)) {
455         i = widget_get_int(w, "action");
456         csv->decpoint = i;
457         if (csv->decpoint == ',') {
458             csv->delim = ';';
459             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(csv->semic_button),
460                                          TRUE);
461         } else if (csv->delim == ';') {
462             csv->delim = ',';
463             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(csv->comma_sep),
464                                          TRUE);
465         }
466     }
467 }
468 
set_delim(GtkWidget * w,csv_stuff * csv)469 static void set_delim (GtkWidget *w, csv_stuff *csv)
470 {
471     gint i;
472 
473     if (button_is_active(w)) {
474         i = widget_get_int(w, "action");
475         if (i != 'a') {
476             csv->delim = i;
477         }
478     }
479 }
480 
toggle_csv_xobs(GtkToggleButton * b,csv_stuff * csv)481 static void toggle_csv_xobs (GtkToggleButton *b, csv_stuff *csv)
482 {
483     csv->xobs = !gtk_toggle_button_get_active(b);
484 }
485 
really_set_csv_stuff(GtkWidget * w,csv_stuff * csv)486 static void really_set_csv_stuff (GtkWidget *w, csv_stuff *csv)
487 {
488     set_data_export_delimiter(csv->delim);
489     set_data_export_decimal_comma(csv->decpoint == ',');
490     set_csv_exclude_obs(csv->xobs);
491 }
492 
destroy_delim_dialog(GtkWidget * w,gint * p)493 static void destroy_delim_dialog (GtkWidget *w, gint *p)
494 {
495     free(p);
496 }
497 
csv_options_dialog(int ci,GretlObjType otype,GtkWidget * parent)498 int csv_options_dialog (int ci, GretlObjType otype, GtkWidget *parent)
499 {
500     GtkWidget *dialog, *vbox, *hbox;
501     GtkWidget *tmp, *button;
502     GSList *group = NULL;
503     csv_stuff *csvp = NULL;
504     int ret = GRETL_CANCEL;
505 
506     if (maybe_raise_dialog()) {
507         return ret;
508     }
509 
510     csvp = mymalloc(sizeof *csvp);
511     if (csvp == NULL) {
512         return ret;
513     }
514 
515     csvp->delim = ',';
516     csvp->decpoint = '.';
517     csvp->xobs = get_csv_exclude_obs();
518 
519     dialog = gretl_dialog_new(_("gretl: data delimiter"), parent,
520                               GRETL_DLG_BLOCK);
521 
522     g_signal_connect(G_OBJECT(dialog), "destroy",
523                      G_CALLBACK(destroy_delim_dialog), csvp);
524 
525     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
526 
527     tmp = gtk_label_new(_("separator for data columns:"));
528     pack_in_hbox(tmp, vbox, 5);
529 
530     if (ci == OPEN_DATA || ci == APPEND_DATA) {
531         /* on input only, add option to auto-detect separator */
532         button = gtk_radio_button_new_with_label(group, _("auto-detect"));
533         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
534         pack_in_hbox(button, vbox, 0);
535         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
536         g_signal_connect(G_OBJECT(button), "clicked",
537                          G_CALLBACK(set_delim), csvp);
538         g_object_set_data(G_OBJECT(button), "action",
539                           GINT_TO_POINTER('a'));
540     }
541 
542     /* comma separator */
543     button = gtk_radio_button_new_with_label(group, _("comma (,)"));
544     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
545     csvp->comma_sep = button;
546     pack_in_hbox(button, vbox, 0);
547     if (ci != OPEN_DATA && ci != APPEND_DATA)
548         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
549     g_signal_connect(G_OBJECT(button), "clicked",
550                      G_CALLBACK(set_delim), csvp);
551     g_object_set_data(G_OBJECT(button), "action",
552                       GINT_TO_POINTER(','));
553 
554     /* space separator */
555     button = gtk_radio_button_new_with_label(group, _("space"));
556     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
557     pack_in_hbox(button, vbox, 0);
558     if (csvp->delim == ' ')
559         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
560     g_signal_connect(G_OBJECT(button), "clicked",
561                      G_CALLBACK(set_delim), csvp);
562     g_object_set_data(G_OBJECT(button), "action",
563                       GINT_TO_POINTER(' '));
564 
565     /* tab separator */
566     button = gtk_radio_button_new_with_label(group, _("tab"));
567     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
568     pack_in_hbox(button, vbox, 0);
569     g_signal_connect(G_OBJECT(button), "clicked",
570                      G_CALLBACK(set_delim), csvp);
571     g_object_set_data(G_OBJECT(button), "action",
572                       GINT_TO_POINTER('\t'));
573 
574     /* semicolon separator */
575     button = gtk_radio_button_new_with_label(group, _("semicolon"));
576     csvp->semic_button = button;
577     pack_in_hbox(button, vbox, 0);
578     g_signal_connect(G_OBJECT(button), "clicked",
579                      G_CALLBACK(set_delim), csvp);
580     g_object_set_data(G_OBJECT(button), "action",
581                       GINT_TO_POINTER(';'));
582 
583     if (',' == get_local_decpoint()) {
584         GSList *dgroup;
585 
586         vbox_add_hsep(vbox);
587         tmp = gtk_label_new(_("decimal point character:"));
588         pack_in_hbox(tmp, vbox, 5);
589 
590         /* period decpoint */
591         button = gtk_radio_button_new_with_label(NULL, _("period (.)"));
592         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
593         pack_in_hbox(button, vbox, 0);
594         g_signal_connect(G_OBJECT(button), "clicked",
595                          G_CALLBACK(set_dec), csvp);
596         g_object_set_data(G_OBJECT(button), "action",
597                           GINT_TO_POINTER('.'));
598 
599         /* comma decpoint */
600         dgroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
601         button = gtk_radio_button_new_with_label(dgroup, _("comma (,)"));
602         pack_in_hbox(button, vbox, 0);
603         g_signal_connect(G_OBJECT(button), "clicked",
604                          G_CALLBACK(set_dec), csvp);
605         g_object_set_data(G_OBJECT(button), "action",
606                           GINT_TO_POINTER(','));
607     }
608 
609     if (otype == GRETL_OBJ_DSET && (ci == EXPORT_CSV || ci == COPY_CSV)) {
610         /* On export/copy of series data only: allow choice to exclude
611            the observations column, and/or on representation of NAs,
612            if applicable.
613          */
614         int hsep_done = 0;
615 
616         if (dataset_is_time_series(dataset) || dataset->S != NULL) {
617             vbox_add_hsep(vbox);
618             hsep_done = 1;
619             tmp = gtk_check_button_new_with_label(_("include observations column"));
620             g_signal_connect(G_OBJECT(tmp), "toggled",
621                              G_CALLBACK(toggle_csv_xobs), csvp);
622             pack_in_hbox(tmp, vbox, 0);
623             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), !csvp->xobs);
624         }
625 
626         if (any_missing_user_values(dataset)) {
627             if (!hsep_done) {
628                 vbox_add_hsep(vbox);
629             }
630             tmp = csv_na_combo();
631             pack_in_hbox(tmp, vbox, 0);
632         }
633     }
634 
635     /* buttons */
636     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
637     tmp = ok_validate_button(hbox, &ret, NULL);
638     g_signal_connect(G_OBJECT(tmp), "clicked",
639                      G_CALLBACK(really_set_csv_stuff), csvp);
640     g_signal_connect(G_OBJECT(tmp), "clicked",
641                      G_CALLBACK(delete_widget), dialog);
642     gtk_widget_grab_default(tmp);
643 
644     gretl_dialog_keep_above(dialog);
645     gtk_widget_show_all(dialog);
646 
647     return ret;
648 }
649 
650 /* selection of format in which to copy material to clipboard,
651    or save to file */
652 
653 struct format_info {
654     GtkWidget *dialog;
655     windata_t *vwin;
656     int format;
657     int multi;
658     int action;
659 };
660 
destroy_format_dialog(GtkWidget * w,struct format_info * finfo)661 static void destroy_format_dialog (GtkWidget *w, struct format_info *finfo)
662 {
663     free(finfo);
664 }
665 
copy_with_format_callback(GtkWidget * w,struct format_info * finfo)666 static void copy_with_format_callback (GtkWidget *w, struct format_info *finfo)
667 {
668     windata_t *vwin = finfo->vwin;
669     int format = finfo->format;
670     int action = finfo->action;
671     int force_decpoint = 0;
672 
673     gtk_widget_destroy(finfo->dialog);
674 
675     if (action == W_COPY &&
676         vwin->role == VIEW_MODEL &&
677         format == GRETL_FORMAT_CSV &&
678         get_local_decpoint() == ',') {
679         const char *opts[] = {
680             N_("period (.)"),
681             N_("comma (,)")
682         };
683         int resp;
684 
685         resp = radio_dialog(NULL, _("decimal point character:"),
686                             opts, 2, 0, 0, vwin_toplevel(vwin));
687         if (resp < 0) {
688             return;
689         } else if (resp == 0) {
690             force_decpoint = 1;
691         }
692     }
693 
694     if (force_decpoint) {
695         gretl_push_c_numeric_locale();
696     }
697 
698     if (action == W_COPY) {
699         window_copy(vwin, format);
700     } else {
701         window_save(vwin, format);
702     }
703 
704     if (force_decpoint) {
705         gretl_pop_c_numeric_locale();
706     }
707 }
708 
preferred_format(int f,int multi)709 static int preferred_format (int f, int multi)
710 {
711 # ifdef G_OS_WIN32
712     static int multi_pref = GRETL_FORMAT_RTF;
713     static int simple_pref = GRETL_FORMAT_TXT;
714 # else
715     static int multi_pref = GRETL_FORMAT_TEX;
716     static int simple_pref = GRETL_FORMAT_TXT;
717 #endif
718     int ret;
719 
720     if (multi) {
721         if (f) multi_pref = f;
722         ret = multi_pref;
723     } else {
724         if (f) simple_pref = f;
725         ret = simple_pref;
726     }
727 
728     return ret;
729 }
730 
set_copy_format(GtkWidget * w,struct format_info * finfo)731 static void set_copy_format (GtkWidget *w, struct format_info *finfo)
732 {
733     gpointer p = g_object_get_data(G_OBJECT(w), "format");
734 
735     if (p != NULL) {
736         int f = GPOINTER_TO_INT(p);
737 
738         finfo->format = f;
739         if (f != GRETL_FORMAT_CSV) {
740             preferred_format(finfo->format, finfo->multi);
741         }
742     }
743 }
744 
745 static GtkWidget *
copy_item_button(GSList * group,GtkWidget * vbox,struct format_info * finfo,int format,const char * label,int pref)746 copy_item_button (GSList *group, GtkWidget *vbox, struct format_info *finfo,
747                   int format, const char *label, int pref)
748 {
749     GtkWidget *button;
750 
751     button = gtk_radio_button_new_with_label(group, label);
752     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
753     g_signal_connect(G_OBJECT(button), "clicked",
754                      G_CALLBACK(set_copy_format), finfo);
755     g_object_set_data(G_OBJECT(button), "format",
756                       GINT_TO_POINTER(format));
757     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
758                                  (pref == format));
759 
760     return button;
761 }
762 
763 #define can_do_tsv(v) ((v->role == PRINT && v->data != NULL) || \
764                        v->role == VIEW_SERIES)
765 
766 #define can_do_csv(v) ((v->role == PRINT && v->data != NULL) || \
767                         v->role == VIEW_SERIES || \
768                         v->role == VIEW_MODEL)
769 
770 /* This dialog allows for selection of a format option when saving
771    material to file or copying to the clipboard. The range of
772    formats offered depends on the content/role of @vwin.
773 */
774 
copy_format_dialog(windata_t * vwin,int action)775 void copy_format_dialog (windata_t *vwin, int action)
776 {
777     GtkWidget *dialog, *tmp, *hbox;
778     GtkWidget *button;
779     GtkWidget *vbox;
780     GSList *group = NULL;
781     struct format_info *finfo;
782     const char *rtf_label;
783     int rtf_format;
784     int pref;
785 
786     if (maybe_raise_dialog()) {
787         return;
788     }
789 
790     finfo = mymalloc(sizeof *finfo);
791     if (finfo == NULL) return;
792 
793     dialog = gretl_dialog_new(_("gretl: select format"),
794                               vwin_toplevel(vwin),
795                               GRETL_DLG_BLOCK);
796     finfo->vwin = vwin;
797     finfo->dialog = dialog;
798 
799     finfo->multi = multiple_formats_ok(vwin);
800     finfo->format = pref = preferred_format(0, finfo->multi);
801     finfo->action = action;
802 
803     g_signal_connect(G_OBJECT(dialog), "destroy",
804                      G_CALLBACK(destroy_format_dialog), finfo);
805 
806     /* set RTF params */
807 #ifdef G_OS_WIN32
808     rtf_label = "RTF (MS Word)";
809 #else
810     rtf_label = "RTF";
811 #endif
812     if (finfo->multi || can_do_tsv(finfo->vwin)) {
813         rtf_format = GRETL_FORMAT_RTF;
814     } else {
815         rtf_format = GRETL_FORMAT_RTF_TXT;
816     }
817 
818     vbox = gtk_vbox_new(FALSE, 2);
819 
820     hbox = gtk_hbox_new(FALSE, 5);
821     tmp = gtk_label_new((action == W_COPY)? _("Copy as:") : _("Save as"));
822     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
823     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
824 
825 #ifdef G_OS_WIN32
826     /* Windows: put RTF option first */
827     button = copy_item_button(group, vbox, finfo, rtf_format,
828                               rtf_label, pref);
829     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
830 #endif
831 
832     if (can_do_tsv(vwin)) {
833         /* tab-separated option */
834         button = copy_item_button(group, vbox, finfo, GRETL_FORMAT_TAB,
835                                   _("Tab separated"), pref);
836         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
837     }
838 
839     if (can_do_csv(vwin)) {
840         /* comma-separated option */
841         button = copy_item_button(group, vbox, finfo, GRETL_FORMAT_CSV,
842                                   _("Comma separated"), pref);
843         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
844     }
845 
846     /* plain text option */
847     button = copy_item_button(group, vbox, finfo, GRETL_FORMAT_TXT,
848                               _("plain text"), pref);
849     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
850 
851     /* LaTeX option? */
852     if (finfo->multi) {
853         button = copy_item_button(group, vbox, finfo, GRETL_FORMAT_TEX,
854                                   "LaTeX", pref);
855         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
856     }
857 
858 #ifndef G_OS_WIN32
859     /* not Windows: put RTF option last */
860     button = copy_item_button(group, vbox, finfo, rtf_format,
861                               rtf_label, pref);
862     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
863 #endif
864 
865     hbox = gtk_hbox_new(FALSE, 5);
866     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
867 
868     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
869     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
870 
871     /* buttons */
872     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
873     cancel_delete_button(hbox, dialog);
874     tmp = ok_button(hbox);
875     g_signal_connect(G_OBJECT(tmp), "clicked",
876                      G_CALLBACK(copy_with_format_callback), finfo);
877     gtk_widget_grab_default(tmp);
878 
879     gretl_dialog_keep_above(dialog);
880     gtk_widget_show_all(dialog);
881 }
882 
883 enum {
884     SET_CI = 1,
885     SET_PVAL,
886     SET_PAIRS,
887     SET_WILD,
888     SET_UHAT,
889     SET_NORMAL,
890     SET_STUDENT
891 };
892 
set_bs_opt(GtkWidget * w,gretlopt * opt)893 static void set_bs_opt (GtkWidget *w, gretlopt *opt)
894 {
895     int i = widget_get_int(w, "action");
896 
897     switch (i) {
898     case SET_CI:
899         *opt &= ~OPT_T;
900         *opt &= ~OPT_P;
901         break;
902     case SET_PVAL:
903         *opt &= ~OPT_T;
904         *opt |= OPT_P;
905         break;
906     case SET_UHAT:
907         *opt &= ~OPT_X;
908         *opt &= ~OPT_W;
909         *opt &= ~OPT_N;
910         break;
911     case SET_PAIRS:
912         *opt &= ~OPT_N;
913         *opt &= ~OPT_W;
914         *opt |= OPT_X;
915         break;
916     case SET_WILD:
917         *opt &= ~OPT_N;
918         *opt &= ~OPT_X;
919         *opt |= OPT_W;
920         break;
921     case SET_NORMAL:
922         *opt &= ~OPT_X;
923         *opt &= ~OPT_W;
924         *opt |= OPT_N;
925         break;
926     case SET_STUDENT:
927         *opt &= ~OPT_P;
928         *opt |= OPT_T;
929         break;
930     }
931 }
932 
bs_select_coeff(GtkComboBox * b,int * p)933 static void bs_select_coeff (GtkComboBox *b, int *p)
934 {
935     *p = gtk_combo_box_get_active(b);
936 }
937 
938 struct replic_set {
939     GtkWidget *dlg;
940     GtkWidget *w;
941     int *B;
942 };
943 
set_bs_replics(GtkButton * b,struct replic_set * rs)944 static void set_bs_replics (GtkButton *b, struct replic_set *rs)
945 {
946     char *s = combo_box_get_active_text(GTK_COMBO_BOX(rs->w));
947     char *test = NULL;
948     unsigned long u;
949 
950     errno = 0;
951     u = strtoul(s, &test, 10);
952     if (*test != '\0' || errno || (int) u <= 0) {
953         warnbox(_("Invalid entry"));
954     } else {
955         *rs->B = (int) u;
956         gtk_widget_destroy(rs->dlg);
957     }
958 
959     g_free(s);
960 }
961 
make_replics_list(GtkWidget * w)962 static void make_replics_list (GtkWidget *w)
963 {
964     combo_box_append_text(w, "100");
965     combo_box_append_text(w, "1000");
966     combo_box_append_text(w, "10000");
967     combo_box_append_text(w, "100000");
968 
969     gtk_combo_box_set_active(GTK_COMBO_BOX(w), 1);
970 }
971 
bs_coeff_popdown(MODEL * pmod,int * pp)972 static GtkWidget *bs_coeff_popdown (MODEL *pmod, int *pp)
973 {
974     GtkWidget *w;
975     int *xlist = NULL;
976     int i, vi;
977 
978     xlist = gretl_model_get_x_list(pmod);
979     if (xlist == NULL) {
980         return NULL;
981     }
982 
983     w = gtk_combo_box_text_new();
984 
985     for (i=1; i<=xlist[0]; i++) {
986         vi = xlist[i];
987         combo_box_append_text(w, dataset->varname[vi]);
988     }
989 
990     if (pmod->ifc && pmod->ncoeff > 1) {
991         *pp = 1;
992         gtk_combo_box_set_active(GTK_COMBO_BOX(w), 1);
993     } else {
994         *pp = 0;
995         gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0);
996     }
997 
998     free(xlist);
999 
1000     return w;
1001 }
1002 
bootstrap_dialog(windata_t * vwin,int * pp,int * pB,gretlopt * popt)1003 int bootstrap_dialog (windata_t *vwin, int *pp, int *pB,
1004                       gretlopt *popt)
1005 {
1006     MODEL *pmod = vwin->data;
1007     GtkWidget *dialog, *hbox, *vbox;
1008     GtkWidget *popdown = NULL;
1009     GtkWidget *button;
1010     GtkWidget *tmp;
1011     GSList *group = NULL;
1012     gchar *tmpstr;
1013     struct replic_set rs;
1014     int htest = (pp == NULL);
1015     int ret = GRETL_CANCEL;
1016 
1017     if (maybe_raise_dialog()) {
1018         return ret;
1019     }
1020 
1021     if (pp != NULL) {
1022         popdown = bs_coeff_popdown(pmod, pp);
1023         if (popdown == NULL) {
1024             gui_errmsg(E_DATA);
1025             return ret;
1026         }
1027     }
1028 
1029     dialog = gretl_dialog_new(_("gretl: bootstrap analysis"),
1030                               vwin_toplevel(vwin),
1031                               GRETL_DLG_BLOCK);
1032     rs.dlg = dialog;
1033 
1034     vbox = gtk_vbox_new(FALSE, 5);
1035     hbox = gtk_hbox_new(FALSE, 5);
1036     tmpstr = g_strdup_printf("%s:", _("Coefficient"));
1037     tmp = gtk_label_new(tmpstr);
1038     g_free(tmpstr);
1039     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1040 
1041     if (htest) {
1042         /* not selecting coeff, or conf int vs p-value */
1043         goto htest_only;
1044     }
1045 
1046     /* coefficient / variable selection */
1047 
1048     g_signal_connect(G_OBJECT(popdown), "changed",
1049                      G_CALLBACK(bs_select_coeff), pp);
1050     gtk_box_pack_start(GTK_BOX(hbox), popdown, TRUE, TRUE, 5);
1051     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1052 
1053     vbox_add_hsep(vbox);
1054 
1055     /* confidence interval vs p-value */
1056 
1057     button = gtk_radio_button_new_with_label(NULL, _("Confidence interval"));
1058     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1059     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
1060     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_CI));
1061     g_signal_connect(G_OBJECT(button), "clicked",
1062                      G_CALLBACK(set_bs_opt), popt);
1063 
1064     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1065     button = gtk_radio_button_new_with_label(group, _("Studentized confidence interval"));
1066     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1067     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), FALSE);
1068     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_STUDENT));
1069     g_signal_connect(G_OBJECT(button), "clicked",
1070                      G_CALLBACK(set_bs_opt), popt);
1071 
1072     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1073     button = gtk_radio_button_new_with_label(group, _("P-value"));
1074     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1075     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), FALSE);
1076     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_PVAL));
1077     g_signal_connect(G_OBJECT(button), "clicked",
1078                      G_CALLBACK(set_bs_opt), popt);
1079 
1080     vbox_add_hsep(vbox);
1081 
1082  htest_only:
1083 
1084     /* bootstrap method options */
1085 
1086     button = gtk_radio_button_new_with_label(NULL, _("Resample residuals"));
1087     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1088     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
1089     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_UHAT));
1090     g_signal_connect(G_OBJECT(button), "clicked",
1091                      G_CALLBACK(set_bs_opt), popt);
1092 
1093     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1094     button = gtk_radio_button_new_with_label(group, _("Resample data \"pairs\""));
1095     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1096     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), FALSE);
1097     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_PAIRS));
1098     g_signal_connect(G_OBJECT(button), "clicked",
1099                      G_CALLBACK(set_bs_opt), popt);
1100 
1101     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1102     button = gtk_radio_button_new_with_label(group, _("Wild bootstrap"));
1103     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1104     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), FALSE);
1105     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_WILD));
1106     g_signal_connect(G_OBJECT(button), "clicked",
1107                      G_CALLBACK(set_bs_opt), popt);
1108 
1109     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1110     button = gtk_radio_button_new_with_label(group, _("Simulate normal errors"));
1111     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1112     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), FALSE);
1113     g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(SET_NORMAL));
1114     g_signal_connect(G_OBJECT(button), "clicked",
1115                      G_CALLBACK(set_bs_opt), popt);
1116 
1117     vbox_add_hsep(vbox);
1118 
1119     /* Number of replications */
1120 
1121     hbox = gtk_hbox_new(FALSE, 5);
1122     tmp = gtk_label_new(_("Number of replications:"));
1123     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
1124 
1125     rs.B = pB;
1126     rs.w = combo_box_text_new_with_entry();
1127     make_replics_list(rs.w);
1128     tmp = gtk_bin_get_child(GTK_BIN(rs.w));
1129     gtk_entry_set_width_chars(GTK_ENTRY(tmp), 7);
1130     gtk_box_pack_start(GTK_BOX(hbox), rs.w, FALSE, FALSE, 5);
1131 
1132     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1133 
1134     if (!htest) {
1135         /* graph check box */
1136         button = gretl_option_check_button(_("Show graph of sampling "
1137                                              "distribution"),
1138                                            popt, OPT_G);
1139         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 5);
1140     }
1141 
1142     /* switch for saving output to file */
1143     button = gretl_option_check_button(_("Save bootstrap data to file"),
1144                                        popt, OPT_A);
1145     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 5);
1146 
1147     /* pack all of the above */
1148     hbox = gtk_hbox_new(FALSE, 5);
1149     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
1150     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1151     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1152 
1153     /* buttons */
1154     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
1155     cancel_delete_button(hbox, dialog);
1156     button = ok_button(hbox);
1157     g_signal_connect(G_OBJECT(button), "clicked",
1158                      G_CALLBACK(set_ret_yes), &ret);
1159     g_signal_connect(G_OBJECT(button), "clicked",
1160                      G_CALLBACK(set_bs_replics), &rs);
1161     gtk_widget_grab_default(button);
1162     if (!htest) {
1163         context_help_button(hbox, BOOTSTRAP);
1164     } else {
1165         gretl_dialog_keep_above(dialog);
1166     }
1167 
1168     gtk_widget_show_all(dialog);
1169 
1170     return ret;
1171 }
1172 
db_descrip_callback(GtkWidget * w,GtkWidget * dlg)1173 static void db_descrip_callback (GtkWidget *w, GtkWidget *dlg)
1174 {
1175     GtkWidget *entry;
1176     gchar *fname;
1177 
1178     entry = g_object_get_data(G_OBJECT(dlg), "entry");
1179     fname = g_object_get_data(G_OBJECT(dlg), "fname");
1180 
1181     if (entry != NULL && fname != NULL) {
1182         const gchar *newdesc = gtk_entry_get_text(GTK_ENTRY(entry));
1183 
1184         write_db_description(fname, newdesc);
1185     }
1186 
1187     gtk_widget_destroy(dlg);
1188 }
1189 
free_db_fname(GtkWidget * w,char * fname)1190 static void free_db_fname (GtkWidget *w, char *fname)
1191 {
1192     g_free(fname);
1193 }
1194 
database_description_dialog(const char * binname)1195 void database_description_dialog (const char *binname)
1196 {
1197     GtkWidget *dlg, *entry;
1198     GtkWidget *tmp, *vbox, *hbox;
1199     gchar *fname, *descrip;
1200 
1201     if (maybe_raise_dialog()) {
1202         return;
1203     }
1204 
1205     descrip = get_db_description(binname);
1206     if (descrip == NULL) {
1207         return;
1208     }
1209 
1210     fname = g_strdup(binname);
1211 
1212     dlg = gretl_dialog_new(_("gretl: database description"), NULL,
1213                            GRETL_DLG_BLOCK | GRETL_DLG_RESIZE);
1214 
1215     hbox = gtk_hbox_new(FALSE, 5);
1216     tmp = gtk_label_new(_("description:"));
1217     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0);
1218 
1219     g_signal_connect(G_OBJECT(dlg), "destroy",
1220                      G_CALLBACK(free_db_fname), fname);
1221 
1222     entry = gtk_entry_new();
1223     gtk_entry_set_max_length(GTK_ENTRY(entry), 64);
1224     gtk_entry_set_width_chars(GTK_ENTRY(entry), 32);
1225 
1226     gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1227     gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
1228     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
1229 
1230     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
1231     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1232 
1233     /* set data on dialog */
1234     g_object_set_data(G_OBJECT(dlg), "entry", entry);
1235     g_object_set_data(G_OBJECT(dlg), "fname", fname);
1236 
1237     /* buttons */
1238     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
1239     tmp = ok_button(hbox);
1240     g_signal_connect(G_OBJECT(tmp), "clicked",
1241                      G_CALLBACK(db_descrip_callback), dlg);
1242     gtk_widget_grab_default(tmp);
1243 
1244     gretl_set_window_modal(dlg);
1245     gtk_widget_show_all(dlg);
1246 }
1247 
set_rand_seed(GtkWidget * w,GtkAdjustment * adj)1248 static void set_rand_seed (GtkWidget *w, GtkAdjustment *adj)
1249 {
1250     guint32 s = (guint32) gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
1251 
1252     gretl_rand_set_seed(s);
1253     lib_command_sprintf("set seed %u", s);
1254     record_command_verbatim();
1255 }
1256 
rand_seed_dialog(void)1257 void rand_seed_dialog (void)
1258 {
1259     GtkWidget *dlg;
1260     GtkWidget *tmp, *hbox, *vbox;
1261     GtkAdjustment *adj;
1262     guint32 dseed;
1263 
1264     if (maybe_raise_dialog()) {
1265         return;
1266     }
1267 
1268     dlg = gretl_dialog_new(_("gretl: seed for random numbers"), NULL,
1269                            GRETL_DLG_BLOCK | GRETL_DLG_RESIZE);
1270 
1271     hbox = gtk_hbox_new(FALSE, 5);
1272     tmp = gtk_label_new(_("Seed for generator:"));
1273     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
1274 
1275     dseed = gretl_rand_get_seed();
1276     adj = (GtkAdjustment *) gtk_adjustment_new((gdouble) dseed, 1,
1277                                                (gdouble) UINT_MAX,
1278                                                1, 10000, 0);
1279     tmp = gtk_spin_button_new(adj, 1, 0);
1280     gtk_entry_set_width_chars(GTK_ENTRY(tmp), 10);
1281     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
1282     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1283 
1284     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
1285     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1286 
1287     /* buttons */
1288     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
1289     cancel_delete_button(hbox, dlg);
1290     tmp = ok_button(hbox);
1291     g_signal_connect(G_OBJECT(tmp), "clicked",
1292                      G_CALLBACK(set_rand_seed), adj);
1293     g_signal_connect(G_OBJECT(tmp), "clicked",
1294                      G_CALLBACK(delete_widget), dlg);
1295     gtk_widget_grab_default(tmp);
1296     context_help_button(hbox, SEED_RANDOM);
1297 
1298     gtk_widget_show_all(dlg);
1299 }
1300 
set_listname(GtkComboBox * combo,char * listname)1301 static void set_listname (GtkComboBox *combo,
1302                           char *listname)
1303 {
1304     gchar *active = combo_box_get_active_text(combo);
1305 
1306     strcpy(listname, active);
1307     g_free(active);
1308 }
1309 
select_list_dialog(char * listname)1310 int select_list_dialog (char *listname)
1311 {
1312     GtkWidget *dlg;
1313     GtkWidget *combo;
1314     GtkWidget *hbox, *vbox, *tmp;
1315     GList *llist;
1316     int ret = GRETL_CANCEL;
1317 
1318     if (maybe_raise_dialog()) {
1319         return ret;
1320     }
1321 
1322     dlg = gretl_dialog_new(NULL, NULL, GRETL_DLG_BLOCK);
1323 
1324     llist = user_var_names_for_type(GRETL_TYPE_LIST);
1325     llist = g_list_first(llist);
1326     strcpy(listname, (char *) llist->data);
1327 
1328     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
1329 
1330     /* label */
1331     hbox = gtk_hbox_new(FALSE, 5);
1332     tmp = gtk_label_new(_("Choose named list"));
1333     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1334     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1335 
1336     /* selector */
1337     hbox = gtk_hbox_new(FALSE, 5);
1338     combo = gtk_combo_box_text_new();
1339     set_combo_box_strings_from_list(combo, llist);
1340     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
1341     g_signal_connect(G_OBJECT(combo), "changed",
1342                      G_CALLBACK(set_listname), listname);
1343     gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, FALSE, 5);
1344     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1345     g_list_free(llist);
1346 
1347     /* buttons */
1348     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
1349     cancel_delete_button(hbox, dlg);
1350     tmp = ok_validate_button(hbox, &ret, NULL);
1351     g_signal_connect(G_OBJECT(tmp), "clicked",
1352                      G_CALLBACK(delete_widget), dlg);
1353     gtk_widget_grab_default(tmp);
1354 
1355     gtk_widget_show_all(dlg);
1356 
1357     return ret;
1358 }
1359 
combo_set_retval(GtkComboBox * combo,int * ret)1360 static void combo_set_retval (GtkComboBox *combo, int *ret)
1361 {
1362     *ret = gtk_combo_box_get_active(combo);
1363 }
1364 
combo_selector_dialog(GList * list,const char * msg,int deflt,GtkWidget * parent)1365 int combo_selector_dialog (GList *list, const char *msg,
1366                            int deflt, GtkWidget *parent)
1367 {
1368     GtkWidget *dlg;
1369     GtkWidget *combo;
1370     GtkWidget *hbox, *vbox, *tmp;
1371     int selval = deflt;
1372     int ret = GRETL_CANCEL;
1373 
1374     dlg = gretl_dialog_new(NULL, parent, GRETL_DLG_BLOCK);
1375     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
1376 
1377     /* label */
1378     hbox = gtk_hbox_new(FALSE, 5);
1379     tmp = gtk_label_new(msg);
1380     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1381     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1382 
1383     /* selector */
1384     hbox = gtk_hbox_new(FALSE, 5);
1385     combo = gtk_combo_box_text_new();
1386     set_combo_box_strings_from_list(combo, list);
1387     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), deflt);
1388     g_signal_connect(G_OBJECT(combo), "changed",
1389                      G_CALLBACK(combo_set_retval), &selval);
1390     gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, FALSE, 5);
1391     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1392 
1393     /* buttons */
1394     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
1395     cancel_delete_button(hbox, dlg);
1396     tmp = ok_validate_button(hbox, &ret, &selval);
1397     g_signal_connect(G_OBJECT(tmp), "clicked",
1398                      G_CALLBACK(delete_widget), dlg);
1399     gtk_widget_grab_default(tmp);
1400 
1401     gtk_widget_show_all(dlg);
1402 
1403     return ret;
1404 }
1405 
bfgs_mode_callback(GtkToggleButton * button,int * s)1406 static void bfgs_mode_callback (GtkToggleButton *button, int *s)
1407 {
1408     if (gtk_toggle_button_get_active(button)) {
1409         *s = LBFGS_MAX;
1410     } else {
1411         *s = BFGS_MAX;
1412     }
1413 }
1414 
1415 struct ic_info {
1416     double v1;
1417     int v2;
1418     double *ptol;
1419     int *ret;
1420 };
1421 
iter_control_callback(GtkButton * b,struct ic_info * ic)1422 static void iter_control_callback (GtkButton *b, struct ic_info *ic)
1423 {
1424     char numstr[32];
1425 
1426     sprintf(numstr, "%fe-%d", ic->v1, ic->v2);
1427     *ic->ptol = atof(numstr);
1428     *ic->ret = 0;
1429 }
1430 
iter_control_dialog(int * optim,int * pmaxit,double * ptol,int * plmem,GtkWidget * parent)1431 int iter_control_dialog (int *optim, int *pmaxit, double *ptol,
1432                          int *plmem, GtkWidget *parent)
1433 {
1434     struct ic_info ic;
1435     static GtkWidget *dlg;
1436     GtkWidget *tmp, *hbox, *vbox;
1437     const char *title;
1438     char *s, numstr[32];
1439     int ret = GRETL_CANCEL;
1440 
1441     if (dlg != NULL) {
1442         gtk_window_present(GTK_WINDOW(dlg));
1443         return ret;
1444     }
1445 
1446     dlg = gretl_dialog_new(_("gretl: iteration controls"), parent,
1447                            GRETL_DLG_BLOCK);
1448 
1449     g_signal_connect(G_OBJECT(dlg), "destroy",
1450                      G_CALLBACK(gtk_widget_destroyed), &dlg);
1451 
1452     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
1453 
1454     sprintf(numstr, "%g", *ptol);
1455     s = strchr(numstr, '-');
1456     *s = '\0';
1457 
1458     ic.v1 = atof(numstr);
1459     ic.v2 = atoi(s+1);
1460     ic.ptol = ptol;
1461     ic.ret = &ret;
1462 
1463     title = (*optim == BHHH_MAX)? N_("BHHH maximizer") :
1464         N_("BFGS maximizer");
1465 
1466     hbox = gtk_hbox_new(FALSE, 5);
1467     tmp = gtk_label_new(_(title));
1468     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1469     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1470 
1471     hbox = gtk_hbox_new(FALSE, 5);
1472     tmp = gtk_label_new(_("Maximum iterations:"));
1473     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
1474     tmp = gtk_spin_button_new_with_range(100, 100000, 100);
1475     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), *pmaxit);
1476     g_signal_connect(G_OBJECT(tmp), "value-changed",
1477                      G_CALLBACK(set_int_from_spinner), pmaxit);
1478     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
1479     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
1480     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1481 
1482     hbox = gtk_hbox_new(FALSE, 5);
1483     tmp = gtk_label_new(_("Convergence tolerance:"));
1484     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
1485     tmp = gtk_spin_button_new_with_range(1.00, 9.99, 0.01);
1486     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), ic.v1);
1487     g_signal_connect(G_OBJECT(tmp), "value-changed",
1488                      G_CALLBACK(set_double_from_spinner), &ic.v1);
1489     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
1490     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
1491 
1492     tmp = gtk_label_new("E-");
1493     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0);
1494     tmp = gtk_spin_button_new_with_range(2, 14, 1);
1495     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), ic.v2);
1496     g_signal_connect(G_OBJECT(tmp), "value-changed",
1497                      G_CALLBACK(set_int_from_spinner), &ic.v2);
1498     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
1499     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
1500     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1501 
1502     if (*optim != BHHH_MAX) {
1503         GtkWidget *lb;
1504 
1505         hbox = gtk_hbox_new(FALSE, 5);
1506         lb = gtk_check_button_new_with_label(_("Use L-BFGS-B, memory size:"));
1507         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lb),
1508                                      (*optim == LBFGS_MAX));
1509         g_signal_connect(G_OBJECT(lb), "toggled",
1510                          G_CALLBACK(bfgs_mode_callback), optim);
1511         gtk_box_pack_start(GTK_BOX(hbox), lb, FALSE, FALSE, 5);
1512         tmp = gtk_spin_button_new_with_range(3, 20, 1);
1513         gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), *plmem);
1514         g_signal_connect(G_OBJECT(tmp), "value-changed",
1515                          G_CALLBACK(set_int_from_spinner), plmem);
1516         gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
1517         gtk_widget_set_sensitive(tmp, (*optim == LBFGS_MAX));
1518         sensitize_conditional_on(tmp, lb);
1519         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0);
1520         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
1521     }
1522 
1523     /* buttons */
1524     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
1525     cancel_delete_button(hbox, dlg);
1526     tmp = ok_button(hbox);
1527     g_signal_connect(G_OBJECT(tmp), "clicked",
1528                      G_CALLBACK(iter_control_callback), &ic);
1529     g_signal_connect(G_OBJECT(tmp), "clicked",
1530                      G_CALLBACK(delete_widget), dlg);
1531     gtk_widget_grab_default(tmp);
1532     if (*optim == BFGS_MAX) {
1533         context_help_button(hbox, BFGS_CONFIG);
1534     }
1535 
1536     gtk_widget_show_all(dlg);
1537 
1538     return ret;
1539 }
1540 
1541 /* apparatus for setting sample range */
1542 
1543 struct range_setting {
1544     gretlopt opt;
1545     DATASET dinfo;        /* auxiliary data info structure */
1546     GtkWidget *dlg;       /* dialog box */
1547     GtkWidget *obslabel;  /* label for showing number of selected obs */
1548     GtkAdjustment *adj1;  /* adjustment for start spinner */
1549     GtkAdjustment *adj2;  /* adjustment for end spinner */
1550     GtkWidget *spin1;     /* start-of-range spinner */
1551     GtkWidget *spin2;     /* end-of-range spinner */
1552     GtkWidget *combo;     /* multi-purpose selector */
1553     GtkWidget *entry;
1554     gboolean markers;
1555     gpointer p;
1556     MODEL *pmod;
1557     int *t1;
1558     int *t2;
1559 };
1560 
free_rsetting(GtkWidget * w,struct range_setting * rset)1561 static void free_rsetting (GtkWidget *w, struct range_setting *rset)
1562 {
1563     set_active_edit_name(NULL);
1564     free(rset);
1565 }
1566 
unit_get_first_obs(int u)1567 static int unit_get_first_obs (int u)
1568 {
1569     return u * dataset->pd;
1570 }
1571 
unit_get_last_obs(int u)1572 static int unit_get_last_obs (int u)
1573 {
1574     return (u+1) * dataset->pd - 1;
1575 }
1576 
1577 static gboolean
set_sample_from_dialog(GtkWidget * w,struct range_setting * rset)1578 set_sample_from_dialog (GtkWidget *w, struct range_setting *rset)
1579 {
1580     const char *extra;
1581     int err;
1582 
1583     if ((rset->opt & OPT_P) && (rset->opt & OPT_T)) {
1584         extra = " --replace --permanent";
1585     } else if (rset->opt & OPT_P) {
1586         extra = " --replace";
1587     } else if (rset->opt & OPT_T) {
1588         extra = " --permanent";
1589     } else {
1590         extra = "";
1591     }
1592 
1593     if (rset->opt & OPT_R) {
1594         /* boolean restriction */
1595         gchar *s = get_genr_string(rset->entry, NULL);
1596 
1597         if (s == NULL) {
1598             return TRUE;
1599         }
1600 
1601         err = bool_subsample(s, rset->opt, rset->dlg);
1602         if (!err) {
1603             lib_command_sprintf("smpl %s --restrict%s", s, extra);
1604             record_command_verbatim();
1605             gtk_widget_destroy(rset->dlg);
1606         }
1607         g_free(s);
1608     } else if (rset->opt & OPT_O) {
1609         /* sampling using a dummy var */
1610         gchar *dumv;
1611 
1612         dumv = combo_box_get_active_text(GTK_COMBO_BOX(rset->combo));
1613         err = bool_subsample(dumv, rset->opt, rset->dlg);
1614         if (!err) {
1615             lib_command_sprintf("smpl %s --dummy%s", dumv, extra);
1616             record_command_verbatim();
1617             gtk_widget_destroy(rset->dlg);
1618         }
1619         g_free(dumv);
1620     } else if (rset->opt & OPT_N) {
1621         /* random subsample */
1622         int subn = obs_button_get_value(rset->spin1);
1623         gchar *nstr = g_strdup_printf("%d", subn);
1624 
1625         err = bool_subsample(nstr, rset->opt, rset->dlg);
1626         if (!err) {
1627             lib_command_sprintf("smpl %d --random%s", subn, extra);
1628             record_command_verbatim();
1629             gtk_widget_destroy(rset->dlg);
1630         }
1631         g_free(nstr);
1632     } else {
1633         GtkSpinButton *button;
1634         char s1[OBSLEN], s2[OBSLEN];
1635         int t1, t2;
1636 
1637         button = GTK_SPIN_BUTTON(rset->spin1);
1638         strcpy(s1, gtk_entry_get_text(GTK_ENTRY(button)));
1639         t1 = gtk_spin_button_get_value_as_int(button);
1640 
1641         button = GTK_SPIN_BUTTON(rset->spin2);
1642         strcpy(s2, gtk_entry_get_text(GTK_ENTRY(button)));
1643         t2 = gtk_spin_button_get_value_as_int(button);
1644 
1645         if (rset->opt & OPT_C) {
1646             /* creating a new dataset */
1647             gchar **obsstr = (gchar **) rset->p;
1648 
1649             if (obsstr != NULL) {
1650                 *obsstr = g_strdup_printf("%s %s", s1, s2);
1651             }
1652             gtk_widget_destroy(rset->dlg);
1653             return TRUE;
1654         } else if (rset->opt & OPT_P) {
1655             /* selecting panel group range */
1656             t1 = unit_get_first_obs(t1);
1657             t2 = unit_get_last_obs(t2);
1658             ntolabel(s1, t1, dataset);
1659             ntolabel(s2, t2, dataset);
1660         }
1661 
1662         if (t1 != dataset->t1 || t2 != dataset->t2) {
1663             err = set_sample(s1, s2, dataset, 0);
1664             if (err) {
1665                 gui_errmsg(err);
1666             } else {
1667                 lib_command_sprintf("smpl %s %s", s1, s2);
1668                 record_command_verbatim();
1669                 gtk_widget_destroy(rset->dlg);
1670                 set_sample_label(dataset);
1671                 mark_session_changed();
1672             }
1673         } else {
1674             /* no change */
1675             gtk_widget_destroy(rset->dlg);
1676         }
1677     }
1678 
1679     return TRUE;
1680 }
1681 
1682 static void
set_obs_from_dialog(GtkButton * b,struct range_setting * rset)1683 set_obs_from_dialog (GtkButton *b, struct range_setting *rset)
1684 {
1685     GtkSpinButton *button;
1686 
1687     if (rset->spin1 != NULL && rset->t1 != NULL) {
1688         button = GTK_SPIN_BUTTON(rset->spin1);
1689         *rset->t1 = gtk_spin_button_get_value_as_int(button);
1690     }
1691 
1692     if (rset->spin2 != NULL && rset->t2 != NULL) {
1693         button = GTK_SPIN_BUTTON(rset->spin2);
1694         *rset->t2 = gtk_spin_button_get_value_as_int(button);
1695     }
1696 
1697     gtk_widget_destroy(rset->dlg);
1698 }
1699 
get_dummy_list(int * thisdum)1700 static GList *get_dummy_list (int *thisdum)
1701 {
1702     GList *dumlist = NULL;
1703     int v = mdata_active_var();
1704     int i, j = 0;
1705 
1706     for (i=1; i<dataset->v; i++) {
1707         if (gretl_isdummy(dataset->t1, dataset->t2, dataset->Z[i])) {
1708             dumlist = g_list_append(dumlist, dataset->varname[i]);
1709             if (i == v) {
1710                 *thisdum = j;
1711             }
1712             j++;
1713         }
1714     }
1715 
1716     return dumlist;
1717 }
1718 
update_obs_label(GtkComboBox * box,gpointer data)1719 gboolean update_obs_label (GtkComboBox *box, gpointer data)
1720 {
1721     struct range_setting *rset = (struct range_setting *) data;
1722     int t1 = 0, t2 = 0, n = 0;
1723 
1724     if (box != NULL) {
1725         gchar *vname = combo_box_get_active_text(box);
1726 
1727         if (vname != NULL) {
1728             int v = series_index(dataset, vname);
1729 
1730             if (v < dataset->v) {
1731                 n = gretl_isdummy(0, dataset->n - 1, dataset->Z[v]);
1732             }
1733             g_free(vname);
1734         }
1735     } else {
1736         t1 = obs_button_get_value(rset->spin1);
1737         t2 = obs_button_get_value(rset->spin2);
1738         n = t2 - t1 + 1;
1739     }
1740 
1741     if (n > 0) {
1742         gchar *obstr = NULL;
1743 
1744         if (rset->opt == OPT_G) {
1745             obstr = g_strdup_printf(_("groups (N = %d)"), n);
1746         } else if (rset->opt == OPT_P) {
1747             obstr = g_strdup_printf(_("Included groups: %d"), n);
1748         } else {
1749             obstr = g_strdup_printf(_("Observations: %d"), n);
1750         }
1751 
1752         if (rset->markers) {
1753             const char *s1 = dataset->S[t1];
1754             const char *s2 = dataset->S[t2];
1755             gchar *tmp = g_strconcat(obstr, "\n(", s1,
1756                                      " .. ", s2, ")", NULL);
1757 
1758             g_free(obstr);
1759             obstr = tmp;
1760         }
1761 
1762         gtk_label_set_text(GTK_LABEL(rset->obslabel), obstr);
1763         g_free(obstr);
1764     }
1765 
1766     return FALSE;
1767 }
1768 
default_randsize(void)1769 static int default_randsize (void)
1770 {
1771     int n = sample_size(dataset);
1772 
1773     if (n > 1000) {
1774         return n / 10;
1775     } else {
1776         return n / 2;
1777     }
1778 }
1779 
rset_new(guint code,gpointer p,MODEL * pmod,int * t1,int * t2,const gchar * title,GtkWidget * parent)1780 static struct range_setting *rset_new (guint code, gpointer p,
1781                                        MODEL *pmod,
1782                                        int *t1, int *t2,
1783                                        const gchar *title,
1784                                        GtkWidget *parent)
1785 {
1786     struct range_setting *rset;
1787 
1788     rset = mymalloc(sizeof *rset);
1789     if (rset == NULL) return NULL;
1790 
1791     rset->opt = OPT_NONE;
1792     rset->markers = 0;
1793 
1794     if (code == SMPLDUM) {
1795         rset->opt = OPT_O;
1796     } else if (code == SMPLBOOL) {
1797         rset->opt = OPT_R;
1798     } else if (code == SMPLRAND) {
1799         rset->opt = OPT_N;
1800     } else if (code == CREATE_DATASET) {
1801         rset->opt = OPT_C;
1802     }
1803 
1804     rset->dlg = gretl_dialog_new(title, parent, GRETL_DLG_BLOCK);
1805     rset->combo = rset->entry = NULL;
1806     rset->adj1 = rset->adj2 = NULL;
1807     rset->spin1 = rset->spin2 = NULL;
1808     rset->obslabel = NULL;
1809 
1810     datainfo_init(&rset->dinfo);
1811     rset->p = p;
1812     rset->pmod = pmod;
1813 
1814     rset->t1 = t1;
1815     rset->t2 = t2;
1816 
1817     return rset;
1818 }
1819 
1820 /* Special sample range selector for panel datasets: express the
1821    choice as a matter of which units/groups to include. The
1822    @temp argument is non-zero if we're just setting the panel sample
1823    temporarily for the purpose of doing a panel plot.
1824 */
1825 
panel_sample_spinbox(struct range_setting * rset,int temp)1826 static GtkWidget *panel_sample_spinbox (struct range_setting *rset,
1827                                         int temp)
1828 {
1829     GtkWidget *lbl;
1830     GtkWidget *vbox;
1831     GtkWidget *hbox;
1832 
1833     rset->dinfo.n = dataset->n / dataset->pd;
1834 
1835     if (temp) {
1836         rset->dinfo.t1 = *rset->t1;
1837         rset->dinfo.t2 = *rset->t2;
1838     } else {
1839         rset->dinfo.t1 = dataset->t1 / dataset->pd;
1840         rset->dinfo.t2 = dataset->t2 / dataset->pd;
1841     }
1842 
1843     dataset_obs_info_default(&rset->dinfo);
1844 
1845     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
1846 
1847     if (temp) {
1848         hbox = gtk_hbox_new(FALSE, 5);
1849     } else {
1850         lbl = gtk_label_new(_("Panel groups"));
1851         gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 5);
1852         hbox = gtk_hbox_new(TRUE, 5);
1853     }
1854 
1855     /* spinner for u1 */
1856     lbl = gtk_label_new(_("Start:"));
1857     rset->adj1 = (GtkAdjustment *) gtk_adjustment_new(rset->dinfo.t1, 0,
1858                                                       rset->dinfo.n - 1,
1859                                                       1, 1, 0);
1860     rset->spin1 = obs_button_new(rset->adj1, &rset->dinfo, OBS_BUTTON_T1);
1861 
1862     if (temp) {
1863         gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" "), FALSE, FALSE, 0);
1864         gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
1865         gtk_box_pack_start(GTK_BOX(hbox), rset->spin1, FALSE, FALSE, 0);
1866     } else {
1867         vbox = gtk_vbox_new(FALSE, 5);
1868         gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 0);
1869         gtk_entry_set_activates_default(GTK_ENTRY(rset->spin1), TRUE);
1870         gtk_box_pack_start(GTK_BOX(vbox), rset->spin1, FALSE, FALSE, 0);
1871         gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
1872     }
1873 
1874     /* spinner for u2 */
1875     lbl = gtk_label_new(_("End:"));
1876     rset->adj2 = (GtkAdjustment *) gtk_adjustment_new(rset->dinfo.t2, 0,
1877                                                       rset->dinfo.n - 1,
1878                                                       1, 1, 0);
1879     rset->spin2 = obs_button_new(rset->adj2, &rset->dinfo, OBS_BUTTON_T2);
1880 
1881     if (temp) {
1882         gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
1883         gtk_box_pack_start(GTK_BOX(hbox), rset->spin2, FALSE, FALSE, 0);
1884     } else {
1885         vbox = gtk_vbox_new(FALSE, 5);
1886         gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 0);
1887         gtk_entry_set_activates_default(GTK_ENTRY(rset->spin2), TRUE);
1888         gtk_box_pack_start(GTK_BOX(vbox), rset->spin2, FALSE, FALSE, 0);
1889         gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
1890     }
1891 
1892     /* inter-connect the two spinners */
1893     obs_button_set_partner(rset->spin1, rset->spin2);
1894     obs_button_set_partner(rset->spin2, rset->spin1);
1895 
1896     return hbox;
1897 }
1898 
1899 #if 0 /* not ready yet */
1900 
1901 typedef struct panel_setting_ {
1902     int u1, u2;
1903     int t1, t2;
1904     int Nmax, Tmax;
1905     GtkWidget *spin[4];
1906     GtkWidget *dlg;
1907     GtkWidget *obslabel;
1908 } panel_setting;
1909 
1910 static panel_setting *pset_new (void)
1911 {
1912     panel_setting *pset;
1913 
1914     pset = mymalloc(sizeof *pset);
1915     if (pset == NULL) return NULL;
1916 
1917     pset->dlg = gretl_dialog_new(_("gretl: set sample"), NULL,
1918                                  GRETL_DLG_BLOCK);
1919     pset->obslabel = NULL;
1920 
1921     return pset;
1922 }
1923 
1924 static void free_pset (GtkWidget *w, panel_setting *pset)
1925 {
1926     free(pset);
1927 }
1928 
1929 static void gui_set_panel_sample (GtkWidget *w, panel_setting *pset)
1930 {
1931     int orig_u1 = 1 + dataset->t1 / dataset->pd;
1932     int orig_u2 = (dataset->t2 + 1) / dataset->pd;
1933     int T = pset->t2 - pset->t1 + 1;
1934 
1935     fprintf(stderr, "set panel sample\n");
1936     fprintf(stderr, "orig_u1 = %d, orig_u2 = %d\n", orig_u1, orig_u2);
1937     fprintf(stderr, "u1 = %d, u2 = %d, t1 = %d, t2 = %d\n",
1938             pset->u1, pset->u2, pset->t1, pset->t2);
1939 
1940     if (T < dataset->pd) {
1941         fprintf(stderr, "Need to shrink (restrict) by time\n");
1942     }
1943 
1944     if (pset->u1 != orig_u1 || pset->u2 != orig_u2) {
1945         fprintf(stderr, "Need to smpl by unit\n");
1946     }
1947 }
1948 
1949 static void panel_sample_callback (GtkSpinButton *b,
1950                                    panel_setting *pset)
1951 {
1952     int N, T, k = gtk_spin_button_get_value_as_int(b);
1953     GtkWidget *w = GTK_WIDGET(b);
1954     gchar *msg;
1955 
1956     if (w == pset->spin[0]) {
1957         if (k > pset->u2) {
1958             if (pset->u2 < pset->Nmax) {
1959                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pset->spin[1]),
1960                                           pset->u2 + 1);
1961             } else {
1962                 gtk_spin_button_set_value(b, --k);
1963             }
1964         }
1965         pset->u1 = k;
1966     } else if (w == pset->spin[1]) {
1967         if (k < pset->u1) {
1968             if (pset->u1 > 1) {
1969                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pset->spin[0]),
1970                                           pset->u1 - 1);
1971             } else {
1972                 gtk_spin_button_set_value(b, ++k);
1973             }
1974         }
1975         pset->u2 = k;
1976     } else if (w == pset->spin[2]) {
1977         if (k > pset->t2) {
1978             if (pset->t2 < pset->Tmax) {
1979                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pset->spin[3]),
1980                                           pset->t2 + 1);
1981             } else {
1982                 gtk_spin_button_set_value(b, --k);
1983             }
1984         }
1985         pset->t1 = k;
1986     } else if (w == pset->spin[3]) {
1987         if (k < pset->t1) {
1988             if (pset->t1 > 1) {
1989                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pset->spin[2]),
1990                                           pset->t1 - 1);
1991             } else {
1992                 gtk_spin_button_set_value(b, ++k);
1993             }
1994         }
1995         pset->t2 = k;
1996     }
1997 
1998     N = pset->u2 - pset->u1 + 1;
1999     T = pset->t2 - pset->t1 + 1;
2000 
2001     msg = g_strdup_printf("N=%d, T=%d, NT=%d", N, T, N*T);
2002     gtk_label_set_text(GTK_LABEL(pset->obslabel), msg);
2003     g_free(msg);
2004 }
2005 
2006 static void panel_new_spinbox (panel_setting *pset)
2007 {
2008     GtkWidget *lbl, *vbox;
2009     GtkWidget *tbl, *spin;
2010     GtkWidget *hbox;
2011     gchar *msg;
2012     int i, k, N, T;
2013 
2014     pset->u1 = 1 + dataset->t1 / dataset->pd;
2015     pset->u2 = (dataset->t2 + 1) / dataset->pd;
2016     pset->t1 = 1;
2017     pset->t2 = dataset->pd;
2018     pset->Nmax = dataset->n / dataset->pd;
2019     pset->Tmax = dataset->pd;
2020 
2021     vbox = gtk_dialog_get_content_area(GTK_DIALOG(pset->dlg));
2022     hbox = gtk_hbox_new(FALSE, 5);
2023 
2024     tbl = gtk_table_new(2, 4, FALSE);
2025     gtk_table_set_row_spacings(GTK_TABLE(tbl), 5);
2026     gtk_table_set_col_spacings(GTK_TABLE(tbl), 5);
2027     gtk_box_pack_start(GTK_BOX(hbox), tbl, FALSE, FALSE, 5);
2028     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2029 
2030     k = 0;
2031 
2032     /* group/unit spinners */
2033     for (i=0; i<2; i++) {
2034         int spinmax = (i==0)? pset->Nmax : pset->Tmax;
2035         int s1 = (i==0)? pset->u1 : pset->t1;
2036         int s2 = (i==0)? pset->u2 : pset->t2;
2037 
2038         lbl = gtk_label_new((i==0)? _("Groups") : _("Periods"));
2039         gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 0, 1, i, i+1);
2040         spin = gtk_spin_button_new_with_range(1, spinmax, 1);
2041         gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), s1);
2042         pset->spin[k++] = spin;
2043         gtk_table_attach_defaults(GTK_TABLE(tbl), spin,
2044                                   1, 2, i, i+1);
2045         lbl = gtk_label_new(_("to"));
2046         gtk_table_attach_defaults(GTK_TABLE(tbl), lbl,
2047                                   2, 3, i, i+1);
2048         spin = gtk_spin_button_new_with_range(1, spinmax, 1);
2049         gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), s2);
2050         pset->spin[k++] = spin;
2051         gtk_table_attach_defaults(GTK_TABLE(tbl), spin,
2052                                   3, 4, i, i+1);
2053     }
2054 
2055     for (i=0; i<4; i++) {
2056         gtk_entry_set_activates_default(GTK_ENTRY(pset->spin[i]), TRUE);
2057         g_signal_connect(G_OBJECT(pset->spin[i]), "value-changed",
2058                          G_CALLBACK(panel_sample_callback), pset);
2059     }
2060 
2061     N = pset->u2 - pset->u1 + 1;
2062     T = pset->t2 - pset->t1 + 1;
2063 
2064     hbox = gtk_hbox_new(FALSE, 5);
2065     msg = g_strdup_printf("N=%d, T=%d, NT=%d", N, T, N*T);
2066     pset->obslabel = lbl = gtk_label_new(msg);
2067     gtk_box_pack_start(GTK_BOX(hbox), lbl, TRUE, TRUE, 0);
2068     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2069     g_free(msg);
2070 }
2071 
2072 static void panel_sample_dialog (void)
2073 {
2074     panel_setting *pset;
2075     GtkWidget *w, *hbox;
2076 
2077     pset = pset_new();
2078     if (pset == NULL) {
2079         return;
2080     }
2081 
2082     panel_new_spinbox(pset);
2083 
2084     /* buttons */
2085     hbox = gtk_dialog_get_action_area(GTK_DIALOG(pset->dlg));
2086     cancel_delete_button(hbox, pset->dlg);
2087     w = ok_button(hbox);
2088     g_signal_connect(G_OBJECT(w), "clicked",
2089                      G_CALLBACK(gui_set_panel_sample), pset);
2090     gtk_widget_grab_default(w);
2091     g_signal_connect(G_OBJECT(pset->dlg), "destroy",
2092                      G_CALLBACK(free_pset), pset);
2093 
2094     gretl_dialog_keep_above(pset->dlg);
2095     gtk_widget_show_all(pset->dlg);
2096 }
2097 
2098 #endif /* not ready */
2099 
2100 typedef enum {
2101     SPIN_LABEL_NONE,
2102     SPIN_LABEL_ABOVE,
2103     SPIN_LABEL_INLINE
2104 } SpinLabelAlign;
2105 
2106 static GtkWidget *
obs_spinbox(struct range_setting * rset,const char * label,const char * t1str,const char * t2str,int t1min,int t1max,int t1,int t2min,int t2max,int t2,SpinLabelAlign align)2107 obs_spinbox (struct range_setting *rset, const char *label,
2108              const char *t1str, const char *t2str,
2109              int t1min, int t1max, int t1,
2110              int t2min, int t2max, int t2,
2111              SpinLabelAlign align)
2112 {
2113     GtkWidget *lbl;
2114     GtkWidget *vbox;
2115     GtkWidget *hbox;
2116     int smin; /* "step increment" */
2117     int smaj; /* "page increment" */
2118 
2119     if (dataset_is_panel(dataset)) {
2120         int tmp;
2121 
2122         smin = smaj = dataset->pd;
2123         /* below: minimal selection should be the complete time series
2124            for a single panel unit */
2125         if (t1max == t2max) {
2126             tmp = t1max - dataset->pd;
2127             t1max = (tmp < 0)? 0 : tmp;
2128         }
2129         if (t2min == t1min) {
2130             tmp = t2min + dataset->pd;
2131             t2min = (tmp > dataset->n - 1)? dataset->n - 1 : tmp;
2132         }
2133     } else {
2134         smin = 1;
2135         smaj = dataset->pd;
2136     }
2137 
2138     if (label != NULL && align == SPIN_LABEL_ABOVE) {
2139         lbl = gtk_label_new(label);
2140         vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2141         gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 5);
2142     }
2143 
2144     if (label != NULL && align == SPIN_LABEL_INLINE) {
2145         hbox = gtk_hbox_new(FALSE, 5);
2146         lbl = gtk_label_new(label);
2147         gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
2148     } else {
2149         hbox = gtk_hbox_new(TRUE, 5);
2150     }
2151 
2152     /* spinner for t1 */
2153     vbox = gtk_vbox_new(FALSE, 5);
2154     if (t1str != NULL) {
2155         lbl = gtk_label_new(t1str);
2156         gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 0);
2157     }
2158     rset->adj1 = (GtkAdjustment *) gtk_adjustment_new(t1, t1min, t1max,
2159                                                       smin, smaj, 0);
2160     rset->spin1 = obs_button_new(rset->adj1, dataset, OBS_BUTTON_T1);
2161     gtk_entry_set_activates_default(GTK_ENTRY(rset->spin1), TRUE);
2162     gtk_box_pack_start(GTK_BOX(vbox), rset->spin1, FALSE, FALSE, 0);
2163     gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
2164 
2165     /* spinner for t2, if wanted */
2166     if (!(t2min == 0 && t2max == 0)) {
2167         vbox = gtk_vbox_new(FALSE, 5);
2168         if (t2str != NULL) {
2169             lbl = gtk_label_new(t2str);
2170             gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 0);
2171         }
2172         rset->adj2 = (GtkAdjustment *) gtk_adjustment_new(t2, t2min, t2max,
2173                                                           smin, smaj, 0);
2174         rset->spin2 = obs_button_new(rset->adj2, dataset, OBS_BUTTON_T2);
2175         gtk_entry_set_activates_default(GTK_ENTRY(rset->spin2), TRUE);
2176         gtk_box_pack_start(GTK_BOX(vbox), rset->spin2, FALSE, FALSE, 0);
2177         gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
2178 
2179         /* inter-connect the two spinners */
2180         obs_button_set_partner(rset->spin1, rset->spin2);
2181         obs_button_set_partner(rset->spin2, rset->spin1);
2182     }
2183 
2184     return hbox;
2185 }
2186 
sample_range_code(GtkAction * action)2187 static int sample_range_code (GtkAction *action)
2188 {
2189     const gchar *s = gtk_action_get_name(action);
2190 
2191     return (!strcmp(s, "SMPLRAND"))? SMPLRAND : SMPL;
2192 }
2193 
build_dummies_combo(GList * dumlist,int thisdum)2194 static GtkWidget *build_dummies_combo (GList *dumlist,
2195                                        int thisdum)
2196 {
2197     GtkWidget *combo = gtk_combo_box_text_new();
2198     GList *dlist = dumlist;
2199 
2200     while (dlist != NULL) {
2201         combo_box_append_text(combo, dlist->data);
2202         dlist = dlist->next;
2203     }
2204 
2205     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), thisdum);
2206 
2207     return combo;
2208 }
2209 
add_dummies_combo(GList * dumlist,int thisdum,const gchar * label,GtkWidget * vbox)2210 static GtkWidget *add_dummies_combo (GList *dumlist,
2211                                      int thisdum,
2212                                      const gchar *label,
2213                                      GtkWidget *vbox)
2214 {
2215     GtkWidget *w, *hbox, *combo;
2216 
2217     if (label != NULL) {
2218         w = gtk_label_new(label);
2219         hbox = gtk_hbox_new(TRUE, 5);
2220         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2221         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2222     }
2223 
2224     combo = build_dummies_combo(dumlist, thisdum);
2225 
2226     hbox = gtk_hbox_new(TRUE, 5);
2227     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
2228     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2229 
2230     return combo;
2231 }
2232 
toggle_smpl_permanence(GtkToggleButton * b,struct range_setting * rset)2233 static void toggle_smpl_permanence (GtkToggleButton *b,
2234                                     struct range_setting *rset)
2235 {
2236     if (gtk_toggle_button_get_active(b)) {
2237         rset->opt |= OPT_T;
2238     } else {
2239         rset->opt &= ~OPT_T;
2240     }
2241 }
2242 
add_smpl_permanent_check(GtkWidget * vbox,struct range_setting * rset)2243 static void add_smpl_permanent_check (GtkWidget *vbox,
2244                                       struct range_setting *rset)
2245 {
2246     GtkWidget *hbox, *check;
2247 
2248     hbox = gtk_hbox_new(FALSE, 5);
2249     check = gtk_check_button_new_with_label(_("Make this restriction permanent"));
2250     gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, FALSE, 5);
2251     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
2252     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2253 
2254     g_signal_connect(G_OBJECT(check), "toggled",
2255                      G_CALLBACK(toggle_smpl_permanence), rset);
2256 }
2257 
sample_range_dialog(GtkAction * action,gpointer p)2258 void sample_range_dialog (GtkAction *action, gpointer p)
2259 {
2260     struct range_setting *rset = NULL;
2261     GtkWidget *w, *vbox, *hbox;
2262     int u = sample_range_code(action);
2263     int T = sample_size(dataset);
2264 
2265 #if 0 /* not ready */
2266     if (dataset_is_panel(dataset) && u == SMPL) {
2267         panel_sample_dialog();
2268         return;
2269     }
2270 #endif
2271 
2272     if (u == SMPLRAND && T < 2) {
2273         warnbox(_("The current data range is too small for this option"));
2274         return;
2275     }
2276 
2277     rset = rset_new(u, p, NULL, NULL, NULL, _("gretl: set sample"), NULL);
2278     if (rset == NULL) return;
2279 
2280     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2281 
2282     if (u == SMPLRAND) {
2283         gchar *labtxt;
2284         GtkAdjustment *adj;
2285 
2286         hbox = gtk_hbox_new(FALSE, 5);
2287 
2288         labtxt = g_strdup_printf(_("Number of observations to select (max %d)"),
2289                                  T - 1);
2290 
2291         /* spinner for number of obs */
2292         w = gtk_label_new(labtxt);
2293         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2294         adj = (GtkAdjustment *) gtk_adjustment_new(default_randsize(),
2295                                                    1, T - 1,
2296                                                    1, 1, 0);
2297         rset->spin1 = gtk_spin_button_new(adj, 1, 0);
2298         gtk_entry_set_activates_default(GTK_ENTRY(rset->spin1), TRUE);
2299         gtk_box_pack_start(GTK_BOX(hbox), rset->spin1, FALSE, FALSE, 5);
2300 
2301         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2302     } else if (u == SMPL && dataset_is_panel(dataset)) {
2303         hbox = panel_sample_spinbox(rset, 0);
2304         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2305         rset->opt = OPT_P;
2306     } else {
2307         /* either plain SMPL or CREATE_DATASET */
2308         hbox = obs_spinbox(rset, _("Set sample range"),
2309                            _("Start:"), _("End:"),
2310                            0, dataset->n - 1, dataset->t1,
2311                            0, dataset->n - 1, dataset->t2,
2312                            SPIN_LABEL_ABOVE);
2313         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2314     }
2315 
2316     if (u == SMPLRAND) {
2317         if (!complex_subsampled()) {
2318             add_smpl_permanent_check(vbox, rset);
2319         }
2320     } else {
2321         /* label that will show the number of observations */
2322         rset->obslabel = gtk_label_new("");
2323         gtk_box_pack_start(GTK_BOX(vbox), rset->obslabel, FALSE, FALSE, 5);
2324     }
2325 
2326     if (u == SMPL || u == CREATE_DATASET) {
2327         g_object_set_data(G_OBJECT(rset->spin1), "rset", rset);
2328         g_object_set_data(G_OBJECT(rset->spin2), "rset", rset);
2329     }
2330 
2331     /* buttons */
2332     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
2333     cancel_delete_button(hbox, rset->dlg);
2334     w = ok_button(hbox);
2335     g_signal_connect(G_OBJECT(w), "clicked",
2336                      G_CALLBACK(set_sample_from_dialog), rset);
2337     gtk_widget_grab_default(w);
2338 
2339     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
2340                      G_CALLBACK(free_rsetting), rset);
2341 
2342     gretl_dialog_keep_above(rset->dlg);
2343     gtk_widget_show_all(rset->dlg);
2344 }
2345 
2346 static gboolean
range_dummy_callback(GtkWidget * w,struct range_setting * rset)2347 range_dummy_callback (GtkWidget *w, struct range_setting *rset)
2348 {
2349     GtkWidget *name_entry;
2350     char s1[OBSLEN], s2[OBSLEN];
2351     const gchar *vname;
2352     gchar *buf;
2353     int t1, t2;
2354     int err;
2355 
2356     name_entry = g_object_get_data(G_OBJECT(rset->dlg), "name-entry");
2357     vname = gtk_entry_get_text(GTK_ENTRY(name_entry));
2358     if (vname == NULL || *vname == '\0') {
2359         gtk_widget_grab_focus(name_entry);
2360         return FALSE;
2361     }
2362 
2363     /* FIXME USERIES vs SERIES? */
2364     err = gui_validate_varname(vname, GRETL_TYPE_USERIES, rset->dlg);
2365     if (err) {
2366         return FALSE;
2367     }
2368 
2369     strcpy(s1, obs_button_get_string(rset->spin1));
2370     strcpy(s2, obs_button_get_string(rset->spin2));
2371 
2372     t1 = obs_button_get_value(rset->spin1);
2373     t2 = obs_button_get_value(rset->spin2);
2374 
2375     if (t2 == t1) {
2376         /* a singleton dummy */
2377         if (strchr(s1, '-')) {
2378             buf = g_strdup_printf("series %s = obs==\"%s\"", vname, s1);
2379         } else if (annual_data(dataset)) {
2380             buf = g_strdup_printf("series %s = obs==obsnum(%s)", vname, s1);
2381         } else if (rset->markers) {
2382             buf = g_strdup_printf("series %s = obs==\"%s\"", vname,
2383                                   dataset->S[t1]);
2384         } else {
2385             buf = g_strdup_printf("series %s = obs==%s", vname, s1);
2386         }
2387     } else {
2388         /* a range of 2 or more observations */
2389         if (strchr(s1, '-') || strchr(s2, '-')) {
2390             buf = g_strdup_printf("series %s = obs>=\"%s\" && obs<=\"%s\"",
2391                                   vname, s1, s2);
2392         } else if (annual_data(dataset)) {
2393             buf = g_strdup_printf("series %s = obs>=obsnum(%s) && obs<=obsnum(%s)",
2394                                   vname, s1, s2);
2395         } else {
2396             buf = g_strdup_printf("series %s = obs>=%s && obs<=%s",
2397                                   vname, s1, s2);
2398         }
2399     }
2400 
2401     do_range_dummy_genr(buf);
2402     g_free(buf);
2403 
2404     gtk_widget_destroy(rset->dlg);
2405 
2406     return TRUE;
2407 }
2408 
range_dummy_dialog(GtkAction * action,gpointer p)2409 void range_dummy_dialog (GtkAction *action, gpointer p)
2410 {
2411     struct range_setting *rset = NULL;
2412     GtkWidget *w, *vbox, *hbox;
2413     GtkWidget *label, *entry;
2414 
2415     rset = rset_new(0, p, NULL, NULL, NULL, _("gretl: define dummy"), NULL);
2416     if (rset == NULL) return;
2417 
2418     if (dataset_is_cross_section(dataset) &&
2419         dataset_has_markers(dataset)) {
2420         rset->markers = 1;
2421     }
2422 
2423     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2424 
2425     hbox = obs_spinbox(rset, _("Set dummy range"),
2426                        _("Start:"), _("End:"),
2427                        dataset->t1, dataset->t2, dataset->t1,
2428                        dataset->t1, dataset->t2, dataset->t2,
2429                        SPIN_LABEL_ABOVE);
2430     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2431 
2432     /* label that will show the number of observations */
2433     rset->obslabel = gtk_label_new("");
2434     gtk_box_pack_start(GTK_BOX(vbox), rset->obslabel, FALSE, FALSE, 5);
2435     if (rset->markers) {
2436         gtk_label_set_justify(GTK_LABEL(rset->obslabel),
2437                               GTK_JUSTIFY_CENTER);
2438     }
2439 
2440     g_object_set_data(G_OBJECT(rset->spin1), "rset", rset);
2441     g_object_set_data(G_OBJECT(rset->spin2), "rset", rset);
2442 
2443     /* entry for naming the dummy */
2444     label = gtk_label_new(_("Name of variable:"));
2445     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
2446     entry = gtk_entry_new();
2447     gtk_entry_set_max_length(GTK_ENTRY(entry), VNAMELEN-1);
2448     gtk_entry_set_width_chars(GTK_ENTRY(entry), 20);
2449     gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 5);
2450     g_object_set_data(G_OBJECT(rset->dlg), "name-entry", entry);
2451     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
2452 
2453     /* buttons */
2454     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
2455     cancel_delete_button(hbox, rset->dlg);
2456     w = ok_button(hbox);
2457     g_signal_connect(G_OBJECT(w), "clicked",
2458                      G_CALLBACK(range_dummy_callback), rset);
2459     gtk_widget_grab_default(w);
2460 
2461     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
2462                      G_CALLBACK(free_rsetting), rset);
2463 
2464     gretl_dialog_keep_above(rset->dlg);
2465     gtk_widget_show_all(rset->dlg);
2466 }
2467 
panel_units_finalize(GtkButton * b,struct range_setting * rset)2468 static void panel_units_finalize (GtkButton *b, struct range_setting *rset)
2469 {
2470     *rset->t1 = spinner_get_int(rset->spin1);
2471     *rset->t2 = spinner_get_int(rset->spin2);
2472 
2473     gtk_widget_destroy(rset->dlg);
2474 }
2475 
2476 #define PNMAX 130
2477 
sensitize_panel_options(GtkSpinButton * spin,GSList * group)2478 static void sensitize_panel_options (GtkSpinButton *spin,
2479                                      GSList *group)
2480 {
2481     struct range_setting *rset =
2482         g_object_get_data(G_OBJECT(spin), "rset");
2483     int ng = g_slist_length(group);
2484     GtkWidget *w, *w0 = NULL;
2485     int i, j, t1, t2, N;
2486     int fixit = 0;
2487 
2488     t1 = spinner_get_int(rset->spin1);
2489     t2 = spinner_get_int(rset->spin2);
2490     N = t2 - t1 + 1;
2491 
2492     for (i=0; i<ng; i++) {
2493         w = g_slist_nth_data(group, i);
2494         j = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "action"));
2495         if (j == 0) {
2496             w0 = w;
2497         } else if (j == 1 || j == 2) {
2498             gtk_widget_set_sensitive(w, N <= PNMAX);
2499         } else if (j == 3) {
2500             gtk_widget_set_sensitive(w, N <= 16);
2501         } else if (j == 4) {
2502             gtk_widget_set_sensitive(w, N <= 6);
2503         } else if (j == 5) {
2504             gtk_widget_set_sensitive(w, N <= 150);
2505         }
2506         if (button_is_active(w) && !gtk_widget_is_sensitive(w)) {
2507             fixit = 1;
2508         }
2509     }
2510 
2511     if (fixit && w0 != NULL) {
2512         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w0), TRUE);
2513     }
2514 }
2515 
panel_graph_dialog(int * t1,int * t2)2516 int panel_graph_dialog (int *t1, int *t2)
2517 {
2518     const char *opts[] = {
2519         N_("single graph: group means"),
2520         N_("single graph: groups overlaid (N <= %d)"),
2521         N_("single graph: groups in sequence (N <= %d)"),
2522         N_("multiple plots in grid (N <= 16)"),
2523         N_("multiple plots arranged vertically (N <= 6)"),
2524         N_("boxplots by group (N <= 150)"),
2525         N_("single boxplot")
2526     };
2527     struct range_setting *rset = NULL;
2528     GSList *group = NULL;
2529     GtkWidget *w, *vbox, *hbox;
2530     GtkWidget *button;
2531     gchar *title;
2532     int nunits = panel_sample_size(dataset);
2533     int i, deflt, nopts = 7;
2534     int radio_val = 0;
2535     int ret = GRETL_CANCEL;
2536 
2537     title = g_strdup_printf("gretl: %s", _("panel plot"));
2538 
2539     rset = rset_new(SMPL, NULL, NULL, t1, t2, title, NULL);
2540     g_free(title);
2541 
2542     if (rset == NULL) {
2543         return ret;
2544     }
2545 
2546     rset->opt = OPT_G; /* sampling for graphing only */
2547 
2548     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2549     w = gtk_label_new(_("panel plot"));
2550     gtk_box_pack_start(GTK_BOX(vbox), w, FALSE, FALSE, 5);
2551 
2552     deflt = (nunits <= PNMAX)? 1 : 0;
2553 
2554     for (i=0; i<nopts; i++) {
2555         if (i == 1 || i == 2) {
2556             gchar *label = g_strdup_printf(_(opts[i]), PNMAX);
2557 
2558             button = gtk_radio_button_new_with_label(group, label);
2559             g_free(label);
2560         } else {
2561             button = gtk_radio_button_new_with_label(group, _(opts[i]));
2562         }
2563         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
2564         if (i == deflt) {
2565             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
2566             radio_val = i;
2567         }
2568         g_signal_connect(G_OBJECT(button), "clicked",
2569                          G_CALLBACK(set_radio_opt), &radio_val);
2570         g_object_set_data(G_OBJECT(button), "action",
2571                           GINT_TO_POINTER(i));
2572         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
2573         if ((i == 1 || i == 2) && nunits > PNMAX) {
2574             gtk_widget_set_sensitive(button, FALSE);
2575         }
2576         if (i == 3 && nunits > 16) {
2577             gtk_widget_set_sensitive(button, FALSE);
2578         }
2579         if (i == 4 && nunits > 6) {
2580             gtk_widget_set_sensitive(button, FALSE);
2581         }
2582         if (i == 5 && (nunits > 150 || dataset->pd < 4)) {
2583             gtk_widget_set_sensitive(button, FALSE);
2584         }
2585         if (i == 4) {
2586             vbox_add_hsep(vbox);
2587         }
2588     }
2589 
2590     vbox_add_hsep(vbox);
2591     hbox = panel_sample_spinbox(rset, 1);
2592     rset->obslabel = gtk_label_new("");
2593     w = gtk_hbox_new(FALSE, 5);
2594     gtk_box_pack_start(GTK_BOX(w), rset->obslabel, FALSE, FALSE, 5);
2595     gtk_box_pack_start(GTK_BOX(vbox), w, FALSE, FALSE, 5);
2596     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2597     vbox_add_hsep(vbox);
2598 
2599     g_object_set_data(G_OBJECT(rset->spin1), "rset", rset);
2600     g_object_set_data(G_OBJECT(rset->spin2), "rset", rset);
2601 
2602     g_signal_connect(G_OBJECT(rset->spin1), "value-changed",
2603                      G_CALLBACK(sensitize_panel_options),
2604                      group);
2605     g_signal_connect(G_OBJECT(rset->spin2), "value-changed",
2606                      G_CALLBACK(sensitize_panel_options),
2607                      group);
2608 
2609     /* buttons */
2610     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
2611     cancel_delete_button(hbox, rset->dlg);
2612     w = ok_validate_button(hbox, &ret, &radio_val);
2613     g_signal_connect(G_OBJECT(w), "clicked",
2614                      G_CALLBACK(panel_units_finalize), rset);
2615     gtk_widget_grab_default(w);
2616 
2617     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
2618                      G_CALLBACK(free_rsetting), rset);
2619     gretl_dialog_keep_above(rset->dlg);
2620     gtk_widget_show_all(rset->dlg);
2621 
2622     return ret;
2623 }
2624 
toggle_rset_use_dummy(GtkToggleButton * b,struct range_setting * rset)2625 static void toggle_rset_use_dummy (GtkToggleButton *b,
2626                                    struct range_setting *rset)
2627 {
2628     gboolean usedum = gtk_toggle_button_get_active(b);
2629 
2630     if (usedum) {
2631         rset->opt |= OPT_O;
2632         rset->opt &= ~OPT_R;
2633         set_active_edit_name(NULL);
2634     } else {
2635         rset->opt |= OPT_R;
2636         rset->opt &= ~OPT_O;
2637         set_active_edit_name(rset->entry);
2638     }
2639 
2640     gtk_widget_set_sensitive(rset->entry, !usedum);
2641     gtk_widget_set_sensitive(rset->combo, usedum);
2642 }
2643 
toggle_replace_restrictions(GtkToggleButton * b,struct range_setting * rset)2644 static void toggle_replace_restrictions (GtkToggleButton *b,
2645                                          struct range_setting *rset)
2646 {
2647     if (gtk_toggle_button_get_active(b)) {
2648         rset->opt |= OPT_P;
2649     } else {
2650         rset->opt &= ~OPT_P;
2651     }
2652 }
2653 
sample_restrict_dialog(GtkAction * action,gpointer p)2654 void sample_restrict_dialog (GtkAction *action, gpointer p)
2655 {
2656     const char *btxt =
2657         N_("Enter boolean condition for selecting cases:");
2658     struct range_setting *rset = NULL;
2659     GList *dumlist = NULL;
2660     GSList *group = NULL;
2661     int thisdum = 0;
2662     GtkWidget *w, *vbox, *hbox;
2663 
2664     rset = rset_new(SMPLBOOL, p, NULL, NULL, NULL,
2665                     _("gretl: restrict sample"), NULL);
2666 
2667     if (rset == NULL) return;
2668 
2669     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2670 
2671     dumlist = get_dummy_list(&thisdum);
2672 
2673     if (dumlist != NULL) {
2674         /* radios for restriction/dummy */
2675         w = gtk_radio_button_new_with_label(NULL, _(btxt));
2676         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(w));
2677     } else {
2678         w = gtk_label_new(_(btxt));
2679     }
2680 
2681     hbox = gtk_hbox_new(FALSE, 5);
2682     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2683     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2684 
2685     /* text entry for restriction */
2686     if (dumlist != NULL) {
2687         hbox = gtk_hbox_new(FALSE, 5);
2688     }
2689     rset->entry = gtk_entry_new();
2690     gtk_entry_set_activates_default(GTK_ENTRY(rset->entry), TRUE);
2691     set_active_edit_name(rset->entry);
2692     g_signal_connect(G_OBJECT(GTK_EDITABLE(rset->entry)), "changed",
2693                      G_CALLBACK(raise_and_focus_dialog), rset->dlg);
2694     if (dumlist != NULL) {
2695         gtk_box_pack_start(GTK_BOX(hbox), rset->entry, TRUE, TRUE, 5);
2696         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2697     } else {
2698         gtk_box_pack_start(GTK_BOX(vbox), rset->entry, FALSE, FALSE, 0);
2699     }
2700 
2701     if (dumlist != NULL) {
2702         hbox = gtk_hbox_new(FALSE, 5);
2703         w = gtk_radio_button_new_with_label(group, _("Use dummy variable:"));
2704         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2705         rset->combo = build_dummies_combo(dumlist, thisdum);
2706         gtk_box_pack_start(GTK_BOX(hbox), rset->combo, FALSE, FALSE, 5);
2707         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2708         g_signal_connect(G_OBJECT(w), "toggled",
2709                          G_CALLBACK(toggle_rset_use_dummy), rset);
2710         gtk_widget_set_sensitive(rset->combo, FALSE);
2711         g_list_free(dumlist);
2712     }
2713 
2714     if (dataset_is_subsampled(dataset)) {
2715         if (dumlist != NULL) {
2716             vbox_add_hsep(vbox);
2717         }
2718 
2719         /* add to current sample restriction */
2720         hbox = gtk_hbox_new(FALSE, 5);
2721         w = gtk_radio_button_new_with_label(NULL, _("add to current restriction"));
2722         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2723         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE);
2724         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2725 
2726         /* replace current sample restriction */
2727         hbox = gtk_hbox_new(FALSE, 5);
2728         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(w));
2729         w = gtk_radio_button_new_with_label(group, _("replace current restriction"));
2730         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
2731         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE);
2732         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2733 
2734         g_signal_connect(G_OBJECT(w), "toggled",
2735                          G_CALLBACK(toggle_replace_restrictions), rset);
2736     }
2737 
2738     if (!complex_subsampled()) {
2739         /* add checkbox for permanence of restriction */
2740         add_smpl_permanent_check(vbox, rset);
2741     }
2742 
2743     /* buttons */
2744     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
2745     cancel_delete_button(hbox, rset->dlg);
2746     w = ok_button(hbox);
2747     g_signal_connect(G_OBJECT(w), "clicked",
2748                      G_CALLBACK(set_sample_from_dialog), rset);
2749     gtk_widget_grab_default(w);
2750     context_help_button(hbox, SMPLBOOL);
2751 
2752     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
2753                      G_CALLBACK(free_rsetting), rset);
2754     if (rset->entry != NULL) {
2755         gtk_widget_grab_focus(rset->entry);
2756     }
2757 
2758     gtk_widget_show_all(rset->dlg);
2759 }
2760 
chow_dumv_callback(GtkComboBox * box,int * dumv)2761 static void chow_dumv_callback (GtkComboBox *box, int *dumv)
2762 {
2763     gchar *vname = combo_box_get_active_text(box);
2764 
2765     *dumv = series_index(dataset, vname);
2766     g_free(vname);
2767 }
2768 
set_chow_subset(GtkToggleButton * b,gretlopt * popt)2769 static void set_chow_subset (GtkToggleButton *b, gretlopt *popt)
2770 {
2771     if (gtk_toggle_button_get_active(b)) {
2772         *popt |= OPT_L;
2773     } else {
2774         *popt &= ~OPT_L;
2775     }
2776 }
2777 
configure_chow_dlg(GtkToggleButton * b,struct range_setting * rset)2778 static void configure_chow_dlg (GtkToggleButton *b, struct range_setting *rset)
2779 {
2780     gboolean s = gtk_toggle_button_get_active(b);
2781 
2782     gtk_widget_set_sensitive(rset->spin1, !s);
2783 
2784     if (s) {
2785         gtk_widget_set_sensitive(rset->combo, TRUE);
2786         chow_dumv_callback(GTK_COMBO_BOX(rset->combo), rset->t2);
2787     } else {
2788         *rset->t2 = 0;
2789     }
2790 }
2791 
chow_dialog(int tmin,int tmax,int * t,int * dumv,gretlopt * popt,GtkWidget * parent)2792 int chow_dialog (int tmin, int tmax, int *t, int *dumv,
2793                  gretlopt *popt, GtkWidget *parent)
2794 {
2795     const gchar *olabel = N_("Observation at which to split the sample:");
2796     const gchar *dlabel = N_("Name of dummy variable to use:");
2797     GtkWidget *tmp, *vbox, *hbox;
2798     GtkWidget *b1 = NULL, *b2 = NULL;
2799     struct range_setting *rset;
2800     GList *dumlist;
2801     int thisdum = 0;
2802     int ret = GRETL_CANCEL;
2803 
2804     dumlist = get_dummy_list(&thisdum);
2805 
2806     rset = rset_new(0, NULL, NULL, t, NULL, _("gretl: Chow test"),
2807                     parent);
2808 
2809     if (rset == NULL) {
2810         return ret;
2811     }
2812 
2813     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
2814 
2815     if (dumlist != NULL) {
2816         GSList *grp;
2817 
2818         hbox = gtk_hbox_new(FALSE, 5);
2819         b1 = gtk_radio_button_new_with_label(NULL, _(olabel));
2820         gtk_box_pack_start(GTK_BOX(hbox), b1, FALSE, FALSE, 5);
2821         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
2822         grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1));
2823         b2 = gtk_radio_button_new_with_label(grp, _(dlabel));
2824     }
2825 
2826     tmp = obs_spinbox(rset, (b1 != NULL)? NULL : _(olabel),
2827                       NULL, NULL,
2828                       tmin, tmax, *t,
2829                       0, 0, 0,
2830                       (b1 != NULL)? SPIN_LABEL_NONE : SPIN_LABEL_ABOVE);
2831 
2832     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
2833 
2834     if (dumlist != NULL) {
2835         hbox = gtk_hbox_new(FALSE, 5);
2836         gtk_box_pack_start(GTK_BOX(hbox), b2, FALSE, FALSE, 5);
2837         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
2838         rset->combo = add_dummies_combo(dumlist, thisdum, NULL, vbox);
2839         gtk_widget_set_sensitive(rset->combo, FALSE);
2840         rset->t2 = dumv;
2841         g_signal_connect(b2, "toggled", G_CALLBACK(configure_chow_dlg), rset);
2842         g_signal_connect(G_OBJECT(rset->combo), "changed",
2843                          G_CALLBACK(chow_dumv_callback), dumv);
2844     }
2845 
2846     if (popt != NULL) {
2847         GtkWidget *cb;
2848 
2849         hbox = gtk_hbox_new(FALSE, 5);
2850         cb = gtk_check_button_new_with_label(_("Test a subset of regressors"));
2851         gtk_box_pack_start(GTK_BOX(hbox), cb, FALSE, FALSE, 5);
2852         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
2853         g_signal_connect(cb, "toggled", G_CALLBACK(set_chow_subset), popt);
2854     }
2855 
2856     /* buttons */
2857     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
2858     cancel_delete_button(hbox, rset->dlg);
2859     tmp = ok_button(hbox);
2860     g_signal_connect(G_OBJECT(tmp), "clicked",
2861                      G_CALLBACK(set_ret_yes), &ret);
2862     g_signal_connect(G_OBJECT(tmp), "clicked",
2863                      G_CALLBACK(set_obs_from_dialog), rset);
2864     gtk_widget_grab_default(tmp);
2865 
2866     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
2867                      G_CALLBACK(free_rsetting), rset);
2868 
2869     gretl_set_window_modal(rset->dlg);
2870     gtk_widget_show_all(rset->dlg);
2871 
2872     return ret;
2873 }
2874 
sync_pre_forecast(GtkWidget * w,struct range_setting * rset)2875 static void sync_pre_forecast (GtkWidget *w, struct range_setting *rset)
2876 {
2877     if (rset->p != NULL) {
2878         int t1 = obs_button_get_value(rset->spin1);
2879         GtkAdjustment *adj = GTK_ADJUSTMENT(rset->p);
2880 
2881         if (gtk_adjustment_get_upper(adj) != t1) {
2882             gtk_adjustment_set_upper(adj, t1);
2883             if (gtk_adjustment_get_value(adj) > t1) {
2884                 gtk_adjustment_set_value(adj, t1);
2885                 gtk_adjustment_value_changed(adj);
2886             }
2887             gtk_adjustment_changed(adj);
2888         }
2889     }
2890 }
2891 
adjust_fcast_t1(GtkWidget * w,struct range_setting * rset)2892 static void adjust_fcast_t1 (GtkWidget *w, struct range_setting *rset)
2893 {
2894     int t1 = obs_button_get_value(rset->spin1);
2895     int i = widget_get_int(w, "action");
2896 
2897     if (rset->pmod == NULL) {
2898         return;
2899     }
2900 
2901     if (i == 3) {
2902         int t1min = rset->pmod->t1 + rset->pmod->ncoeff;
2903 
2904         if (t1 < t1min) {
2905             gtk_spin_button_set_value(GTK_SPIN_BUTTON(rset->spin1),
2906                                       (gdouble) t1min);
2907             g_object_set(rset->adj1, "lower", (gdouble) t1min, NULL);
2908         }
2909     } else if (i == 2) {
2910         double txmin;
2911 
2912         g_object_get(rset->adj1, "lower", &txmin, NULL);
2913         if (txmin > *rset->t1) {
2914             g_object_set(rset->adj1, "lower", (gdouble) *rset->t1, NULL);
2915         }
2916     }
2917 }
2918 
toggle_activate_fitvals(GtkAdjustment * adj,GtkWidget * w)2919 static void toggle_activate_fitvals (GtkAdjustment *adj, GtkWidget *w)
2920 {
2921     gtk_widget_set_sensitive(w, gtk_adjustment_get_value(adj) > 0);
2922 }
2923 
toggle_graph_opt(GtkToggleButton * b,gretlopt * gopt)2924 static void toggle_graph_opt (GtkToggleButton *b, gretlopt *gopt)
2925 {
2926     if (button_is_active(b)) {
2927         *gopt |= OPT_E; /* error bars */
2928     } else {
2929         *gopt &= ~OPT_E;
2930     }
2931 }
2932 
dialog_add_confidence_selector(GtkWidget * dlg,double * conf,gretlopt * gopt)2933 void dialog_add_confidence_selector (GtkWidget *dlg, double *conf,
2934                                      gretlopt *gopt)
2935 {
2936     GtkWidget *spin, *lbl, *cb;
2937     GtkWidget *vbox, *hbox;
2938     GtkWidget *hbox1 = NULL, *hbox2 = NULL;
2939     GtkAdjustment *adj;
2940 
2941     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
2942 
2943     lbl = gtk_label_new("1 - α =");
2944     adj = (GtkAdjustment *) gtk_adjustment_new(*conf, 0.60, 0.99,
2945                                                0.01, 0.1, 0);
2946     spin = gtk_spin_button_new(adj, 1, 2);
2947     g_signal_connect(GTK_SPIN_BUTTON(spin), "value-changed",
2948                      G_CALLBACK(set_double_from_spinner), conf);
2949 
2950     hbox = gtk_hbox_new(FALSE, 5);
2951     gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
2952     gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 5);
2953     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2954 
2955     if (gopt != NULL) {
2956         GSList *group;
2957         GtkWidget *r1, *r2;
2958 
2959         r1 = gtk_radio_button_new_with_label(NULL, _("shaded area"));
2960         hbox1 = gtk_hbox_new(FALSE, 5);
2961         gtk_box_pack_start(GTK_BOX(hbox1), r1, FALSE, FALSE, 5);
2962         gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0);
2963 
2964         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(r1));
2965         r2 = gtk_radio_button_new_with_label(group, _("error bars"));
2966         hbox2 = gtk_hbox_new(FALSE, 5);
2967         gtk_box_pack_start(GTK_BOX(hbox2), r2, FALSE, FALSE, 5);
2968         gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 5);
2969         g_signal_connect(G_OBJECT(r2), "toggled",
2970                          G_CALLBACK(toggle_graph_opt), gopt);
2971 
2972         if (*gopt & OPT_E) {
2973             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(r2), TRUE);
2974         } else {
2975             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(r1), TRUE);
2976         }
2977     }
2978 
2979     cb = g_object_get_data(G_OBJECT(dlg), "checkbox");
2980     if (cb != NULL) {
2981         gboolean ok = button_is_active(cb);
2982 
2983         gtk_widget_set_sensitive(hbox, ok);
2984         sensitize_conditional_on(hbox, cb);
2985         if (hbox1 != NULL && hbox2 != NULL) {
2986             gtk_widget_set_sensitive(hbox1, ok);
2987             sensitize_conditional_on(hbox1, cb);
2988             gtk_widget_set_sensitive(hbox2, ok);
2989             sensitize_conditional_on(hbox2, cb);
2990         }
2991     }
2992 }
2993 
2994 /* at present this is specific to the IRF dialog box */
2995 
dialog_add_iters_spinner(GtkWidget * dlg,int * iters)2996 void dialog_add_iters_spinner (GtkWidget *dlg, int *iters)
2997 {
2998     GtkWidget *spin, *lbl, *cb;
2999     GtkWidget *vbox, *hbox;
3000     GtkAdjustment *adj;
3001 
3002     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3003 
3004     lbl = gtk_label_new("bootstrap iterations");
3005     adj = (GtkAdjustment *) gtk_adjustment_new(*iters, 499, 999999,
3006                                                500, 500, 0);
3007     spin = gtk_spin_button_new(adj, 1, 0);
3008     g_signal_connect(GTK_SPIN_BUTTON(spin), "value-changed",
3009                      G_CALLBACK(set_int_from_spinner), iters);
3010 
3011     hbox = gtk_hbox_new(FALSE, 5);
3012     gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
3013     gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 5);
3014     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3015 
3016     cb = g_object_get_data(G_OBJECT(dlg), "checkbox");
3017     if (cb != NULL) {
3018         gboolean ok = button_is_active(cb);
3019 
3020         gtk_widget_set_sensitive(hbox, ok);
3021         sensitize_conditional_on(hbox, cb);
3022     }
3023 }
3024 
fcast_toggle_scope(GtkComboBox * cb,gretlopt * optp)3025 static void fcast_toggle_scope (GtkComboBox *cb, gretlopt *optp)
3026 {
3027     gint i = gtk_combo_box_get_active(cb);
3028 
3029     if (i == 1) {
3030         *optp |= OPT_M;
3031     } else {
3032         *optp &= ~OPT_M;
3033     }
3034 }
3035 
confidence_scope_selector(GtkWidget * dlg,gretlopt * optp)3036 static void confidence_scope_selector (GtkWidget *dlg, gretlopt *optp)
3037 {
3038     GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3039     GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
3040     GtkWidget *lbl, *combo;
3041 
3042     lbl = gtk_label_new(_("Show interval for"));
3043     gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5);
3044     combo = gtk_combo_box_text_new();
3045     combo_box_append_text(combo, _("actual Y"));
3046     combo_box_append_text(combo, _("mean Y"));
3047     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
3048     g_signal_connect(G_OBJECT(combo), "changed",
3049                      G_CALLBACK(fcast_toggle_scope), optp);
3050     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
3051     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3052 }
3053 
toggle_opt_I(GtkToggleButton * b,gretlopt * optp)3054 static void toggle_opt_I (GtkToggleButton *b, gretlopt *optp)
3055 {
3056     if (gtk_toggle_button_get_active(b)) {
3057         *optp |= OPT_I;
3058     } else {
3059         *optp &= ~OPT_I;
3060     }
3061 }
3062 
forecast_integrate_option(const MODEL * pmod,GtkWidget * vbox,gretlopt * optp)3063 static GtkWidget *forecast_integrate_option (const MODEL *pmod,
3064                                              GtkWidget *vbox,
3065                                              gretlopt *optp)
3066 {
3067     GtkWidget *button = NULL;
3068 
3069     if (pmod != NULL) {
3070         GtkWidget *w, *tbl, *hbox;
3071         GSList *group;
3072         const char *s;
3073         int dv, dvp;
3074 
3075         dv = gretl_model_get_depvar(pmod);
3076         is_standard_diff(dv, dataset, &dvp);
3077 
3078         hbox = gtk_hbox_new(FALSE, 5);
3079         tbl = gtk_table_new(2, 2, FALSE);
3080         gtk_table_set_col_spacings(GTK_TABLE(tbl), 5);
3081 
3082         w = gtk_label_new(_("Produce forecast for"));
3083         gtk_table_attach_defaults(GTK_TABLE(tbl), w, 0, 1, 0, 1);
3084 
3085         s = dataset->varname[dv];
3086         w = gtk_radio_button_new_with_label(NULL, s);
3087         gtk_table_attach_defaults(GTK_TABLE(tbl), w, 1, 2, 0, 1);
3088 
3089         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(w));
3090         s = dataset->varname[dvp];
3091         w = gtk_radio_button_new_with_label(group, s);
3092         g_signal_connect(G_OBJECT(w), "toggled",
3093                          G_CALLBACK(toggle_opt_I), optp);
3094         gtk_table_attach_defaults(GTK_TABLE(tbl), w, 1, 2, 1, 2);
3095         button = w;
3096 
3097         gtk_box_pack_start(GTK_BOX(hbox), tbl, FALSE, FALSE, 5);
3098         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3099         vbox_add_hsep(vbox);
3100     }
3101 
3102     /* FIXME else */
3103 
3104     return button;
3105 }
3106 
flip_sensitivity(GtkToggleButton * b,GtkWidget * w)3107 static void flip_sensitivity (GtkToggleButton *b, GtkWidget *w)
3108 {
3109     gtk_widget_set_sensitive(w, gtk_toggle_button_get_active(b));
3110 }
3111 
snap_to_static(GtkToggleButton * b,GtkWidget * w)3112 static void snap_to_static (GtkToggleButton *b, GtkWidget *w)
3113 {
3114     gboolean s = gtk_toggle_button_get_active(b);
3115 
3116     if (!s) {
3117         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE);
3118     }
3119 }
3120 
3121 /* FIXME: Ideally this conditionality should be centralized in
3122    lib/src/forecast.c, and worked out in proper detail. Note
3123    that we don't need to worry here about estimators for which
3124    forecasts are not supported at all; we're just trying to
3125    screen out cases where forecast standard errors are not
3126    available.
3127 */
3128 
fcast_errs_ok(MODEL * pmod)3129 static int fcast_errs_ok (MODEL *pmod)
3130 {
3131     if (pmod->ci == LOGIT || pmod->ci == PROBIT) {
3132 	return 0;
3133     } else if (pmod->ci == NLS) {
3134         return gretl_model_get_int(pmod, "dynamic") == 0;
3135     } else if (pmod->ci == MIDASREG) {
3136         return gretl_model_get_int(pmod, "umidas") != 0;
3137     } else {
3138         return 1;
3139     }
3140 }
3141 
3142 /* Note: the @pmod argument will be NULL if this dialog is
3143    called in relation to a system of equations.
3144 */
3145 
forecast_dialog(int t1min,int t1max,int * t1,int t2min,int t2max,int * t2,int * k,int pmin,int pmax,int * p,int flags,gretlopt * optp,double * conf,MODEL * pmod,GtkWidget * parent)3146 int forecast_dialog (int t1min, int t1max, int *t1,
3147                      int t2min, int t2max, int *t2,
3148                      int *k, int pmin, int pmax, int *p,
3149                      int flags, gretlopt *optp,
3150                      double *conf, MODEL *pmod,
3151                      GtkWidget *parent)
3152 {
3153     const char *pre_txt = N_("Number of pre-forecast observations "
3154                              "to graph");
3155     const char *opts[] = {
3156         N_("automatic forecast (dynamic out of sample)"),
3157         N_("dynamic forecast"),
3158         N_("static forecast"),
3159         N_("recursive k-step ahead forecasts: k = "),
3160     };
3161     int nopts = 3;
3162     int deflt = 0;
3163     GtkWidget *tmp;
3164     GtkWidget *vbox, *hbox, *bbox;
3165     GtkWidget *sbutton = NULL;
3166     GtkWidget *ibutton = NULL;
3167     GtkWidget *button = NULL;
3168     struct range_setting *rset;
3169     int i, radio_val = 0;
3170     int ret = GRETL_CANCEL;
3171 
3172     rset = rset_new(0, NULL, pmod, t1, t2, _("gretl: forecast"),
3173                     parent);
3174     if (rset == NULL) {
3175         return ret;
3176     }
3177 
3178     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
3179 
3180     /* forecast range selection */
3181     tmp = obs_spinbox(rset, _("Forecast range:"),
3182                       _("Start"), _("End"),
3183                       t1min, t1max, *t1,
3184                       t2min, t2max, *t2,
3185                       SPIN_LABEL_INLINE);
3186     g_signal_connect(G_OBJECT(rset->adj1), "value-changed",
3187                      G_CALLBACK(sync_pre_forecast), rset);
3188     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
3189 
3190     if (!dataset_is_time_series(dataset)) {
3191 	/* only static forecast is available */
3192 	deflt = 2;
3193 	goto skip_ts_options;
3194     }
3195 
3196     tmp = gtk_hseparator_new();
3197     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
3198 
3199     if (flags & FC_INTEGRATE_OK) {
3200         ibutton = forecast_integrate_option(pmod, vbox, optp);
3201     } else if (pmod != NULL && pmod->ci == OLS) {
3202         /* allow the "recursive" option */
3203         nopts++;
3204     }
3205     if (!(flags & (FC_AUTO_OK | FC_DYNAMIC_OK))) {
3206         /* default to static forecast */
3207         deflt = 2;
3208     }
3209 
3210     /* forecast-type options */
3211     for (i=0; i<nopts; i++) {
3212         gboolean opt_ok = TRUE;
3213         GSList *group = NULL;
3214 
3215         if (button != NULL) {
3216             group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
3217         }
3218         hbox = gtk_hbox_new(FALSE, 5);
3219         button = gtk_radio_button_new_with_label(group, _(opts[i]));
3220         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
3221         if (i == 2) {
3222             /* keep a handle to the "static forecast" button */
3223             sbutton = button;
3224         }
3225 
3226         if (i == 3 && k != NULL) {
3227             /* steps ahead for recursive forecast */
3228             GtkWidget *spin = gtk_spin_button_new_with_range(1, 50, 1);
3229 
3230             g_signal_connect(G_OBJECT(spin), "value-changed",
3231                              G_CALLBACK(set_int_from_spinner), k);
3232             gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
3233             gtk_widget_set_sensitive(spin, deflt == 3);
3234             sensitize_conditional_on(spin, button);
3235         }
3236 
3237         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3238 
3239         if (i == deflt) {
3240             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
3241             radio_val = i;
3242         }
3243         if (i < 2 && !(flags & FC_DYNAMIC_OK)) {
3244             /* disallow dynamic options */
3245             opt_ok = FALSE;
3246         }
3247         if (i == 0 && (flags & FC_AUTO_OK)) {
3248             opt_ok = TRUE;
3249         }
3250         if (i >= 2) {
3251             g_signal_connect(G_OBJECT(button), "clicked",
3252                              G_CALLBACK(adjust_fcast_t1),
3253                              rset);
3254         }
3255         g_signal_connect(G_OBJECT(button), "clicked",
3256                          G_CALLBACK(set_radio_opt), &radio_val);
3257         g_object_set_data(G_OBJECT(button), "action",
3258                           GINT_TO_POINTER(i));
3259         if (!opt_ok) {
3260             gtk_widget_set_sensitive(button, FALSE);
3261             if (ibutton != NULL) {
3262                 /* integrate option makes dynamic option available */
3263                 g_signal_connect(G_OBJECT(ibutton), "toggled",
3264                                  G_CALLBACK(flip_sensitivity),
3265                                  button);
3266             }
3267         }
3268     }
3269 
3270     if (ibutton != NULL && sbutton != NULL && !(flags & FC_DYNAMIC_OK)) {
3271         g_signal_connect(G_OBJECT(ibutton), "toggled",
3272                          G_CALLBACK(snap_to_static),
3273                          sbutton);
3274     }
3275 
3276  skip_ts_options:
3277 
3278      /* pre-forecast obs spinner */
3279     tmp = gtk_hseparator_new();
3280     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
3281     hbox = gtk_hbox_new(FALSE, 5);
3282     tmp = option_spinbox(p, _(pre_txt), pmin, pmax, 0, &rset->p);
3283     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
3284     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
3285     /* get the max pre-forecast obs right */
3286     gtk_adjustment_value_changed(GTK_ADJUSTMENT(rset->adj1));
3287 
3288     /* show fitted values, pre-forecast? */
3289     hbox = gtk_hbox_new(FALSE, 5);
3290     tmp = gretl_option_check_button(_("Show fitted values for pre-forecast range"),
3291                                     optp, OPT_H);
3292     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
3293     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
3294     gtk_widget_set_sensitive(tmp, *p > 0);
3295     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (*optp & OPT_H));
3296     g_signal_connect(GTK_ADJUSTMENT(rset->p), "value-changed",
3297                      G_CALLBACK(toggle_activate_fitvals), tmp);
3298 
3299     if (pmod == NULL || fcast_errs_ok(pmod)) {
3300 	/* Applicable only if forecast standard errors can be
3301 	   produced: offer selection of plotting style and
3302 	   alpha value for confidence intervals
3303 	*/
3304         static const char *strs[] = {
3305             N_("error bars"),
3306             N_("low and high lines"),
3307             N_("shaded area"),
3308             NULL
3309         };
3310         static gretlopt opts[] = {
3311             OPT_NONE,
3312             OPT_L,
3313             OPT_F
3314         };
3315         static combo_opts ci_opts;
3316         GtkWidget *combo;
3317         int deflt, fixit = 0;
3318 
3319         if (*t2 - *t1 < 1) {
3320             /* one observation: can only do error bar */
3321             deflt = 0;
3322             fixit = 1;
3323             *optp &= ~OPT_L;
3324             *optp &= ~OPT_F;
3325         } else {
3326             deflt = (*optp & OPT_L)? 1 : (*optp & OPT_F)? 2 : 0;
3327         }
3328 
3329         ci_opts.strs = strs;
3330         ci_opts.vals = opts;
3331         ci_opts.optp = optp;
3332 
3333         tmp = gtk_hseparator_new();
3334         gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
3335 
3336         hbox = gtk_hbox_new(FALSE, 0);
3337         tmp = gtk_label_new(_("Plot confidence interval using"));
3338         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
3339         combo = gretl_opts_combo(&ci_opts, deflt);
3340         gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
3341         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
3342 
3343         if (conf != NULL) {
3344             dialog_add_confidence_selector(rset->dlg, conf, NULL);
3345             if (!fixit && (flags & FC_MEAN_OK)) {
3346                 confidence_scope_selector(rset->dlg, optp);
3347                 if (gretl_is_simple_OLS(pmod)) {
3348                     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
3349                     /* why were we doing the following? */
3350                     /* fixit = 1; */
3351                 }
3352             }
3353         }
3354 
3355         if (fixit) {
3356             gtk_widget_set_sensitive(combo, FALSE);
3357         }
3358     }
3359 
3360     /* buttons */
3361     bbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
3362     cancel_delete_button(bbox, rset->dlg);
3363     tmp = ok_validate_button(bbox, &ret, &radio_val);
3364     g_signal_connect(G_OBJECT(tmp), "clicked",
3365                      G_CALLBACK(set_obs_from_dialog), rset);
3366     gtk_widget_grab_default(tmp);
3367     context_help_button(bbox, FCAST);
3368 
3369     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
3370                      G_CALLBACK(free_rsetting), rset);
3371     gtk_widget_show_all(rset->dlg);
3372 
3373     return ret;
3374 }
3375 
simple_forecast_dialog(int * t1,int * t2,GtkWidget * parent)3376 int simple_forecast_dialog (int *t1, int *t2, GtkWidget *parent)
3377 {
3378     GtkWidget *vbox, *hbox;
3379     GtkWidget *tmp, *button;
3380     struct range_setting *rset;
3381     int ret = GRETL_CANCEL;
3382 
3383     if (dataset->t2 == dataset->n - 1) {
3384 	const char *msg = N_("No out-of-sample observations are "
3385 			     "available.\nShow \"forecast\" information "
3386 			     "for the estimation sample?");
3387 	*t1 = dataset->t1;
3388 	*t2 = dataset->t2;
3389 	ret = yes_no_dialog(_("gretl: forecast"), _(msg), parent);
3390 	return (ret == GRETL_NO)? GRETL_CANCEL : ret;
3391     }
3392 
3393     rset = rset_new(0, NULL, NULL, t1, t2, _("gretl: forecast"),
3394                     parent);
3395     if (rset == NULL) {
3396         return ret;
3397     }
3398 
3399     *t1 = dataset->t2 + 1;
3400     *t2 = dataset->n - 1;
3401 
3402     vbox = gtk_dialog_get_content_area(GTK_DIALOG(rset->dlg));
3403 
3404     /* forecast range selection */
3405     tmp = obs_spinbox(rset, _("Forecast range:"),
3406                       _("Start"), _("End"),
3407                       *t1, dataset->n - 2, *t1,
3408                       dataset->t2 + 2, *t2, *t2,
3409                       SPIN_LABEL_INLINE);
3410     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
3411 
3412     /* buttons */
3413     hbox = gtk_dialog_get_action_area(GTK_DIALOG(rset->dlg));
3414     cancel_delete_button(hbox, rset->dlg);
3415     button = ok_validate_button(hbox, &ret, NULL);
3416     g_signal_connect(G_OBJECT(button), "clicked",
3417                      G_CALLBACK(set_obs_from_dialog), rset);
3418     gtk_widget_grab_default(button);
3419 
3420     g_signal_connect(G_OBJECT(rset->dlg), "destroy",
3421                      G_CALLBACK(free_rsetting), rset);
3422     gtk_widget_show_all(rset->dlg);
3423 
3424     return ret;
3425 }
3426 
set_add_obs(GtkButton * b,int * n_add)3427 static void set_add_obs (GtkButton *b, int *n_add)
3428 {
3429     GtkWidget *spin = g_object_get_data(G_OBJECT(b), "spinner");
3430 
3431     *n_add = spinner_get_int(spin);
3432 }
3433 
add_obs_dialog(const char * blurb,int addmin,gretlopt opt,GtkWidget * parent)3434 int add_obs_dialog (const char *blurb, int addmin,
3435                     gretlopt opt, GtkWidget *parent)
3436 {
3437     int step, panel = dataset_is_panel(dataset);
3438     GtkWidget *dlg, *vbox, *hbox;
3439     GtkWidget *spin, *tmp;
3440     int n_add = -1;
3441 
3442     if (panel && !(opt & OPT_T)) {
3443         addmin = dataset->pd;
3444         step = dataset->pd;
3445     } else {
3446         step = 1;
3447     }
3448 
3449     dlg = gretl_dialog_new(_("Add observations"), parent,
3450                            GRETL_DLG_MODAL | GRETL_DLG_BLOCK);
3451 
3452     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3453 
3454     if (blurb != NULL) {
3455         hbox = gtk_hbox_new(FALSE, 5);
3456         tmp = gtk_label_new(blurb);
3457         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
3458         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3459     }
3460 
3461     hbox = gtk_hbox_new(FALSE, 5);
3462     tmp = gtk_label_new(_("Number of observations to add:"));
3463     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
3464 
3465     spin = gtk_spin_button_new_with_range(addmin, 10000, step);
3466     gtk_entry_set_activates_default(GTK_ENTRY(spin), TRUE);
3467     gtk_box_pack_start(GTK_BOX(hbox), spin, TRUE, TRUE, 5);
3468 
3469     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3470 
3471     /* buttons */
3472     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
3473     cancel_delete_button(hbox, dlg);
3474     tmp = ok_button(hbox);
3475     g_object_set_data(G_OBJECT(tmp), "spinner", spin);
3476     g_signal_connect(G_OBJECT(tmp), "clicked",
3477                      G_CALLBACK(set_add_obs), &n_add);
3478     g_signal_connect(G_OBJECT(tmp), "clicked",
3479                      G_CALLBACK(delete_widget), dlg);
3480     gtk_widget_grab_default(tmp);
3481 
3482     gtk_widget_show_all(dlg);
3483 
3484     return n_add;
3485 }
3486 
set_var_from_combo(GtkWidget * w,GtkWidget * dlg)3487 static void set_var_from_combo (GtkWidget *w, GtkWidget *dlg)
3488 {
3489     GtkWidget *combo = g_object_get_data(G_OBJECT(dlg), "combo");
3490     int *selvar = g_object_get_data(G_OBJECT(dlg), "selvar");
3491     gchar *vname;
3492 
3493     vname = combo_box_get_active_text(GTK_COMBO_BOX(combo));
3494     *selvar = series_index(dataset, vname);
3495     g_free(vname);
3496 }
3497 
dialog_option_callback(GtkWidget * w,dialog_opts * opts)3498 static void dialog_option_callback (GtkWidget *w, dialog_opts *opts)
3499 {
3500     int i = widget_get_int(w, "i");
3501 
3502     if (button_is_active(w)) {
3503         *opts->optp |= opts->vals[i];
3504     } else {
3505         *opts->optp &= ~(opts->vals[i]);
3506     }
3507 }
3508 
dialog_add_opts(dialog_opts * opts,GtkWidget * vbox)3509 static void dialog_add_opts (dialog_opts *opts, GtkWidget *vbox)
3510 {
3511     if (opts->type == OPT_TYPE_RADIO) {
3512         GSList *group = NULL;
3513         GtkWidget *b, *v2, *hbox;
3514         int i;
3515 
3516         v2 = gtk_vbox_new(FALSE, 0);
3517 
3518         for (i=0; i<opts->n; i++) {
3519             b = gtk_radio_button_new_with_label(group, _(opts->strs[i]));
3520             gtk_box_pack_start(GTK_BOX(v2), b, TRUE, TRUE, 0);
3521             g_object_set_data(G_OBJECT(b), "i", GINT_TO_POINTER(i));
3522             g_signal_connect(G_OBJECT(b), "clicked",
3523                              G_CALLBACK(dialog_option_callback), opts);
3524             gtk_widget_show(b);
3525             group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b));
3526         }
3527 
3528         hbox = gtk_hbox_new(FALSE, 5);
3529         gtk_box_pack_start(GTK_BOX(hbox), v2, TRUE, TRUE, 10);
3530         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3531         gtk_widget_show(hbox);
3532         gtk_widget_show(v2);
3533     } else if (opts->type == OPT_TYPE_CHECK) {
3534 	GtkWidget *b, *hbox;
3535 
3536 	b = gtk_check_button_new_with_label(_(opts->strs[0]));
3537 	hbox = gtk_hbox_new(FALSE, 5);
3538 	gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, FALSE, 0);
3539 	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3540 	g_signal_connect(G_OBJECT(b), "clicked",
3541 			 G_CALLBACK(dialog_option_callback), opts);
3542 	gtk_widget_show_all(hbox);
3543     } else {
3544         /* handle combo eventually? */
3545         dummy_call();
3546     }
3547 }
3548 
select_var_from_list_with_opt(const int * list,const char * query,dialog_opts * opts,int hcode,GtkWidget * parent)3549 int select_var_from_list_with_opt (const int *list,
3550                                    const char *query,
3551                                    dialog_opts *opts,
3552                                    int hcode,
3553                                    GtkWidget *parent)
3554 {
3555     GtkWidget *tmp, *vbox, *hbox;
3556     GtkWidget *dlg, *combo;
3557     gchar *title;
3558     int i, selvar = -1;
3559 
3560     title = g_strdup_printf("gretl: %s", _("select variable"));
3561 
3562     dlg = gretl_dialog_new(title, parent, GRETL_DLG_BLOCK);
3563     g_free(title);
3564 
3565     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3566 
3567     tmp = gtk_label_new(query);
3568     hbox = gtk_hbox_new(TRUE, 5);
3569     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
3570     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3571 
3572     combo = gtk_combo_box_text_new();
3573     for (i=1; i<=list[0]; i++) {
3574         combo_box_append_text(combo, dataset->varname[list[i]]);
3575     }
3576 
3577     /* select last entry in list */
3578     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), list[0] - 1);
3579 
3580     hbox = gtk_hbox_new(TRUE, 5);
3581     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
3582     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
3583 
3584     g_object_set_data(G_OBJECT(dlg), "combo", combo);
3585     g_object_set_data(G_OBJECT(dlg), "selvar", &selvar);
3586 
3587     if (opts != NULL) {
3588         dialog_add_opts(opts, vbox);
3589     }
3590 
3591     /* buttons */
3592     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
3593     cancel_delete_button(hbox, dlg);
3594     tmp = ok_button(hbox);
3595     g_signal_connect(G_OBJECT(tmp), "clicked",
3596                      G_CALLBACK(set_var_from_combo), dlg);
3597     g_signal_connect(G_OBJECT(tmp), "clicked",
3598                      G_CALLBACK(delete_widget), dlg);
3599     gtk_widget_grab_default(tmp);
3600     if (hcode) {
3601         context_help_button(hbox, hcode);
3602     }
3603 
3604     gtk_widget_show_all(dlg);
3605 
3606     return selvar;
3607 }
3608 
select_var_from_list(const int * list,const char * query,GtkWidget * parent)3609 int select_var_from_list (const int *list, const char *query,
3610                           GtkWidget *parent)
3611 {
3612     return select_var_from_list_with_opt(list, query, NULL, 0,
3613                                          parent);
3614 }
3615 
3616 /* material relating to the data compaction dialog */
3617 
3618 struct compaction_info {
3619     int *target_pd;
3620     int *repday;
3621     GtkWidget *monday_button;
3622     GtkWidget *sunday_button;
3623     GtkWidget *wkday_opt;
3624 };
3625 
abort_compact(GtkWidget * w,gpointer data)3626 static void abort_compact (GtkWidget *w, gpointer data)
3627 {
3628     gint *method = (gint *) data;
3629 
3630     *method = COMPACT_NONE;
3631 }
3632 
set_compact_type(GtkWidget * w,gpointer data)3633 static void set_compact_type (GtkWidget *w, gpointer data)
3634 {
3635     gint *method = (gint *) data;
3636 
3637     if (button_is_active(w)) {
3638         *method = widget_get_int(w, "action");
3639     }
3640 }
3641 
set_target_pd(GtkWidget * w,gpointer data)3642 static void set_target_pd (GtkWidget *w, gpointer data)
3643 {
3644     struct compaction_info *cinfo = data;
3645     gboolean wtarg;
3646 
3647     if (button_is_active(w)) {
3648         *cinfo->target_pd = widget_get_int(w, "action");
3649     }
3650 
3651     wtarg = *cinfo->target_pd == 52;
3652 
3653     if (cinfo->monday_button != NULL) {
3654         gtk_widget_set_sensitive(cinfo->monday_button, wtarg);
3655     }
3656     if (cinfo->sunday_button != NULL) {
3657         gtk_widget_set_sensitive(cinfo->sunday_button, wtarg);
3658     }
3659     if (cinfo->wkday_opt != NULL) {
3660         GtkWidget *combo = g_object_get_data(G_OBJECT(cinfo->wkday_opt),
3661                                              "combo");
3662 
3663         gtk_widget_set_sensitive(cinfo->wkday_opt, wtarg);
3664         if (combo != NULL) {
3665             gtk_widget_set_sensitive(cinfo->wkday_opt, wtarg);
3666         }
3667     }
3668 }
3669 
set_mon_start(GtkWidget * w,gpointer data)3670 static void set_mon_start (GtkWidget *w, gpointer data)
3671 {
3672     gint *ms = (gint *) data;
3673 
3674     if (button_is_active(w)) {
3675         *ms = widget_get_int(w, "action");
3676     }
3677 }
3678 
pd_buttons(GtkWidget * dlg,int spd,struct compaction_info * cinfo)3679 static void pd_buttons (GtkWidget *dlg, int spd, struct compaction_info *cinfo)
3680 {
3681     GtkWidget *button;
3682     GtkWidget *vbox;
3683     GSList *group = NULL;
3684     gint f[4] = {0};
3685     const char *fstr[4] = { NULL };
3686 
3687     if (spd == 12) {
3688         /* monthly: to quarterly or annual */
3689         f[0] = 4;
3690         f[1] = 1;
3691         fstr[0] = N_("Quarterly");
3692         fstr[1] = N_("Annual");
3693     } else if (spd == 5 || spd == 7) {
3694         /* daily: to weekly or monthly */
3695         f[0] = 52;
3696         f[1] = 12;
3697         fstr[0] = N_("Weekly");
3698         fstr[1] = N_("Monthly");
3699     } else if (spd == 24) {
3700         /* hourly: to daily */
3701         f[0] = 7;
3702         f[1] = 5;
3703         f[2] = 6;
3704         fstr[0] = N_("Daily (7 days)");
3705         fstr[1] = N_("Daily (5 days)");
3706         fstr[2] = N_("Daily (6 days)");
3707     } else {
3708         return;
3709     }
3710     int i;
3711 
3712     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3713 
3714     for (i=0; f[i]>0; i++) {
3715         button = gtk_radio_button_new_with_label(group, _(fstr[i]));
3716         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
3717         if (i == 0) {
3718             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
3719         }
3720         g_signal_connect(G_OBJECT(button), "clicked",
3721                          G_CALLBACK(set_target_pd), cinfo);
3722         g_object_set_data(G_OBJECT(button), "action",
3723                           GINT_TO_POINTER(f[i]));
3724         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
3725     }
3726 }
3727 
monday_buttons(GtkWidget * dlg,int * mon_start,struct compaction_info * cinfo)3728 static void monday_buttons (GtkWidget *dlg, int *mon_start,
3729                             struct compaction_info *cinfo)
3730 {
3731     GtkWidget *button;
3732     GtkWidget *vbox;
3733     GSList *group;
3734 
3735     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3736 
3737     button = gtk_radio_button_new_with_label(NULL, _("Week starts on Monday"));
3738     cinfo->monday_button = button;
3739     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
3740     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
3741 
3742     g_signal_connect(G_OBJECT(button), "clicked",
3743                      G_CALLBACK(set_mon_start), mon_start);
3744     g_object_set_data(G_OBJECT(button), "action",
3745                       GINT_TO_POINTER(1));
3746 
3747     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON (button));
3748     button = gtk_radio_button_new_with_label(group, _("Week starts on Sunday"));
3749     cinfo->sunday_button = button;
3750     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
3751 
3752     g_signal_connect(G_OBJECT(button), "clicked",
3753                      G_CALLBACK(set_mon_start), mon_start);
3754     g_object_set_data(G_OBJECT(button), "action",
3755                       GINT_TO_POINTER(0));
3756 }
3757 
3758 static const char *weekdays[] = {
3759     N_("Sunday"),
3760     N_("Monday"),
3761     N_("Tuesday"),
3762     N_("Wednesday"),
3763     N_("Thursday"),
3764     N_("Friday"),
3765     N_("Saturday")
3766 };
3767 
select_repday(GtkComboBox * menu,int * repday)3768 gboolean select_repday (GtkComboBox *menu, int *repday)
3769 {
3770     int i = gtk_combo_box_get_active(menu);
3771 
3772     *repday = (dataset->pd == 7)? i : i + 1;
3773 
3774     return FALSE;
3775 }
3776 
3777 enum {
3778     NO_METHODS_SET,
3779     SOME_METHODS_SET,
3780     ALL_METHODS_SET,
3781     SINGLE_SERIES,
3782     ALL_METHODS_SET_SAME
3783 };
3784 
method_selected(int code,CompactMethod method)3785 static int method_selected (int code, CompactMethod method)
3786 {
3787     if (code == COMPACT_AVG && method == COMPACT_NONE) {
3788         return 1;
3789     } else {
3790         return code == method;
3791     }
3792 }
3793 
spread_compaction_ok(int lf,int hf)3794 static int spread_compaction_ok (int lf, int hf)
3795 {
3796     if (lf == 1 && (hf == 4 || hf == 12)) {
3797         return 1;
3798     } else if (lf == 4 && hf == 12) {
3799         return 1;
3800     } else {
3801         return 0;
3802     }
3803 }
3804 
compact_method_buttons(GtkWidget * dlg,CompactMethod * method,int current_pd,int methods_set,struct compaction_info * cinfo)3805 static void compact_method_buttons (GtkWidget *dlg, CompactMethod *method,
3806                                     int current_pd, int methods_set,
3807                                     struct compaction_info *cinfo)
3808 {
3809     const char *cstrs[] = {
3810         N_("Compact by averaging"),
3811         N_("Compact by summing"),
3812         N_("Use end-of-period values"),
3813         N_("Use start-of-period values"),
3814         N_("Spread to multiple series (MIDAS)")
3815     };
3816     int ccodes[] = {
3817         COMPACT_AVG,
3818         COMPACT_SUM,
3819         COMPACT_EOP,
3820         COMPACT_SOP,
3821         COMPACT_SPREAD
3822     };
3823     GtkWidget *button;
3824     GtkWidget *vbox;
3825     GSList *group = NULL;
3826     int spread_ok;
3827     int i;
3828 
3829     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
3830 
3831     if (methods_set == SOME_METHODS_SET) {
3832         GtkWidget *label;
3833 
3834         label = gtk_label_new(_("Default method:"));
3835         gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
3836     }
3837 
3838     spread_ok = spread_compaction_ok(*cinfo->target_pd, current_pd);
3839 
3840     for (i=0; i<5; i++) { /* was 4 */
3841         int code = ccodes[i];
3842 
3843         button = gtk_radio_button_new_with_label(group, _(cstrs[i]));
3844         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
3845         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button),
3846                                      method_selected(code, *method));
3847         g_signal_connect(G_OBJECT(button), "clicked",
3848                          G_CALLBACK(set_compact_type), method);
3849         g_object_set_data(G_OBJECT(button), "action",
3850                           GINT_TO_POINTER(code));
3851         if (i > 0 && current_pd == 52) {
3852             gtk_widget_set_sensitive(button, FALSE);
3853         }
3854         if (code == COMPACT_SPREAD && !spread_ok) {
3855             gtk_widget_set_sensitive(button, FALSE);
3856         }
3857         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
3858     }
3859 
3860     if (dated_daily_data(dataset) && cinfo->repday != NULL) {
3861         GtkWidget *hbox, *daymenu;
3862 
3863         hbox = gtk_hbox_new(FALSE, 5);
3864         group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
3865         button = gtk_radio_button_new_with_label(group, _("Use representative day"));
3866         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3867         g_signal_connect(G_OBJECT(button), "clicked",
3868                          G_CALLBACK(set_compact_type), method);
3869         g_object_set_data(G_OBJECT(button), "action",
3870                           GINT_TO_POINTER(COMPACT_WDAY));
3871         cinfo->wkday_opt = button;
3872 
3873         daymenu = gtk_combo_box_text_new();
3874         for (i=0; i<7; i++) {
3875             if ((i == 0 && dataset->pd != 7) ||
3876                 (i == 6 && dataset->pd == 5)) {
3877                 continue;
3878             }
3879             combo_box_append_text(daymenu, _(weekdays[i]));
3880         }
3881         gtk_combo_box_set_active(GTK_COMBO_BOX(daymenu), 0);
3882         gtk_box_pack_start(GTK_BOX(hbox), daymenu, FALSE, FALSE, 5);
3883         g_signal_connect(G_OBJECT(daymenu), "changed",
3884                          G_CALLBACK(select_repday), cinfo->repday);
3885         if (*method != COMPACT_WDAY) {
3886             gtk_widget_set_sensitive(daymenu, FALSE);
3887         }
3888 
3889         sensitize_conditional_on(daymenu, button);
3890         g_object_set_data(G_OBJECT(button), "daymenu", daymenu);
3891 
3892         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3893     }
3894 }
3895 
compact_methods_set(CompactMethod * method)3896 static int compact_methods_set (CompactMethod *method)
3897 {
3898     int i, nset = 0;
3899     int m = 0, mbak = -1;
3900     int all_same = 1;
3901     int ret = NO_METHODS_SET;
3902 
3903     if (dataset->v == 2) {
3904         m = series_get_compact_method(dataset, 1);
3905         if (m != COMPACT_NONE) {
3906             *method = m;
3907         }
3908         return SINGLE_SERIES;
3909     }
3910 
3911     for (i=1; i<dataset->v; i++) {
3912         m = series_get_compact_method(dataset, i);
3913         if (m != COMPACT_NONE) {
3914             nset++;
3915         }
3916         if (all_same && mbak >= 0 && m != mbak) {
3917             all_same = 0;
3918         }
3919         mbak = m;
3920     }
3921 
3922     if (nset == dataset->v - 1) {
3923         if (all_same) {
3924             *method = m;
3925             ret = ALL_METHODS_SET_SAME;
3926         } else {
3927             ret = ALL_METHODS_SET;
3928         }
3929     } else if (nset > 0) {
3930         ret = SOME_METHODS_SET;
3931     }
3932 
3933     return ret;
3934 }
3935 
data_compact_dialog(int spd,int * target_pd,int * mon_start,CompactMethod * method,int * repday,GtkWidget * parent)3936 void data_compact_dialog (int spd, int *target_pd, int *mon_start,
3937                           CompactMethod *method, int *repday,
3938                           GtkWidget *parent)
3939 {
3940     GtkWidget *dlg, *tmp, *vbox, *hbox;
3941     int show_pd_buttons = 0;
3942     int show_monday_buttons = 0;
3943     int show_method_buttons = 0;
3944     int methods_set = NO_METHODS_SET;
3945     struct compaction_info cinfo;
3946     gchar *labelstr = NULL;
3947 
3948     dlg = gretl_dialog_new(_("gretl: compact data"), parent,
3949                            GRETL_DLG_BLOCK);
3950 
3951     cinfo.target_pd = target_pd;
3952     cinfo.repday = repday;
3953     cinfo.monday_button = NULL;
3954     cinfo.sunday_button = NULL;
3955     cinfo.wkday_opt = NULL;
3956 
3957     if (mon_start != NULL) {
3958         *mon_start = 1;
3959     }
3960 
3961     if (*target_pd != 0) {
3962         /* importing series from database */
3963         labelstr = g_strdup_printf(_("You are adding a %s series to %s dataset"),
3964                                    (spd == 4)? _("quarterly") : _("monthly"),
3965                                    (*target_pd == 4)? _("a quarterly"): _("an annual"));
3966     } else {
3967         /* compacting the whole dataset */
3968         if (spd == 4) {
3969             *target_pd = 1;
3970             labelstr = g_strdup(_("Compact quarterly data to annual"));
3971         } else if (spd == 12) {
3972             /* the source data are monthly */
3973             labelstr = g_strdup(_("Compact monthly data to:"));
3974             *target_pd = 4;
3975             show_pd_buttons = 1;
3976         } else if (spd >= 5 && spd <= 7) {
3977             /* the source data are daily */
3978             if (dated_daily_data(dataset)) {
3979                 labelstr = g_strdup(_("Compact daily data to:"));
3980                 show_pd_buttons = 1;
3981             } else {
3982                 labelstr = g_strdup(_("Compact daily data to weekly"));
3983             }
3984             *target_pd = 52;
3985             if (mon_start != NULL) {
3986                 show_monday_buttons = 1;
3987             }
3988         } else if (dated_weekly_data(dataset)) {
3989             labelstr = g_strdup(_("Compact weekly data to monthly"));
3990             *target_pd = 12;
3991         } else if (spd == 24) {
3992             labelstr = g_strdup(_("Compact hourly data to:"));
3993             *target_pd = 7;
3994             show_pd_buttons = 1;
3995         }
3996         methods_set = compact_methods_set(method);
3997     }
3998 
3999     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
4000 
4001     tmp = gtk_label_new(labelstr);
4002     g_free(labelstr);
4003     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
4004 
4005     show_method_buttons = (methods_set != ALL_METHODS_SET);
4006 
4007     /* Monthly data: give choice of going to quarterly or annual;
4008        Dated daily: give choice of going to weekly or monthly;
4009        Hourly data: give choice of days per week.
4010     */
4011     if (show_pd_buttons) {
4012         pd_buttons(dlg, spd, &cinfo);
4013         if (show_monday_buttons || show_method_buttons) {
4014             vbox_add_hsep(vbox);
4015         }
4016     }
4017 
4018     /* 7-day daily data: give choice of when the week starts */
4019     if (show_monday_buttons) {
4020         monday_buttons(dlg, mon_start, &cinfo);
4021         if (show_method_buttons) {
4022             vbox_add_hsep(vbox);
4023         }
4024     }
4025 
4026     /* per-variable compaction methods not all set already:
4027        give choice of default compaction method
4028     */
4029     if (show_method_buttons) {
4030         compact_method_buttons(dlg, method, spd, methods_set, &cinfo);
4031     }
4032 
4033     /* buttons */
4034     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
4035     tmp = cancel_button(hbox);
4036     g_signal_connect(G_OBJECT(tmp), "clicked",
4037                      G_CALLBACK(abort_compact), method);
4038     g_signal_connect (G_OBJECT(tmp), "clicked",
4039                       G_CALLBACK(delete_widget),
4040                       G_OBJECT(dlg));
4041     tmp = ok_button(hbox);
4042     g_signal_connect(G_OBJECT(tmp), "clicked",
4043                      G_CALLBACK(delete_widget),
4044                      G_OBJECT(dlg));
4045     gtk_widget_grab_default(tmp);
4046     context_help_button(hbox, COMPACT);
4047 
4048     gtk_widget_show_all(dlg);
4049 }
4050 
abort_expand(GtkWidget * w,gpointer data)4051 static void abort_expand (GtkWidget *w, gpointer data)
4052 {
4053     int *newpd = (int *) data;
4054 
4055     *newpd = -1;
4056 }
4057 
set_expansion(GtkComboBox * cb,gpointer data)4058 static void set_expansion (GtkComboBox *cb, gpointer data)
4059 {
4060     int sel = gtk_combo_box_get_active(cb);
4061     int *newpd = (int *) data;
4062 
4063     *newpd = sel == 0 ? 4 : 12;
4064 }
4065 
4066 /* called from do_expand_data_set() in database.c */
4067 
data_expand_dialog(int * newpd,GtkWidget * parent)4068 void data_expand_dialog (int *newpd, GtkWidget *parent)
4069 {
4070     GtkWidget *d, *tmp, *vbox, *hbox;
4071 
4072     if (dataset->pd != 1 && dataset->pd != 4) {
4073         /* "can't happen" */
4074         return;
4075     }
4076 
4077     d = gretl_dialog_new(_("gretl: expand data"), parent, GRETL_DLG_BLOCK);
4078     vbox = gtk_dialog_get_content_area(GTK_DIALOG(d));
4079 
4080     /* top message, possibly with frequency selector */
4081     hbox = gtk_hbox_new(FALSE, 5);
4082     if (dataset->pd == 1) {
4083         GtkWidget *com;
4084 
4085         tmp = gtk_label_new(_("Expand annual data to"));
4086         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
4087         com = gtk_combo_box_text_new();
4088         gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
4089         combo_box_append_text(com, _("quarterly"));
4090         combo_box_append_text(com, _("monthly"));
4091         gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
4092         g_signal_connect(G_OBJECT(com), "changed",
4093                          G_CALLBACK(set_expansion), newpd);
4094     } else if (dataset->pd == 4) {
4095         tmp = gtk_label_new(_("Expand quarterly data to monthly"));
4096         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
4097     }
4098     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
4099 
4100     /* message to check the Help */
4101     hbox = gtk_hbox_new(FALSE, 5);
4102     tmp = gtk_label_new(_("Please read the Help before proceeding."));
4103     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
4104     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
4105 
4106     /* buttons */
4107     hbox = gtk_dialog_get_action_area(GTK_DIALOG(d));
4108     tmp = cancel_button(hbox);
4109     g_signal_connect(G_OBJECT(tmp), "clicked",
4110                      G_CALLBACK(abort_expand), newpd);
4111     g_signal_connect(G_OBJECT(tmp), "clicked",
4112                      G_CALLBACK(delete_widget),
4113                      G_OBJECT(d));
4114     tmp = ok_button(hbox);
4115     g_signal_connect(G_OBJECT(tmp), "clicked",
4116                      G_CALLBACK(delete_widget),
4117                      G_OBJECT(d));
4118     gtk_widget_grab_default(tmp);
4119     context_help_button(hbox, EXPAND); /* FIXME! */
4120 
4121     gtk_widget_show_all(d);
4122 }
4123 
set_radio_opt(GtkWidget * w,int * opt)4124 static void set_radio_opt (GtkWidget *w, int *opt)
4125 {
4126     *opt = widget_get_int(w, "action");
4127 }
4128 
4129 /* Returns GRETL_CANCEL on cancel, otherwise the 0-based index of the radio
4130    option selected */
4131 
real_radio_dialog(const char * title,const char * label,const char ** opts,int nopts,int deflt,int hcode,int * extravar,const char * extratxt,int spinmin,int spinmax,GtkWidget * parent)4132 int real_radio_dialog (const char *title, const char *label,
4133                        const char **opts, int nopts, int deflt, int hcode,
4134                        int *extravar, const char *extratxt,
4135                        int spinmin, int spinmax, GtkWidget *parent)
4136 {
4137     GtkWidget *dialog;
4138     GtkWidget *vbox, *hbox, *tmp;
4139     GtkWidget *button = NULL;
4140     GSList *group = NULL;
4141     int radio_val = deflt;
4142     int i, ret = GRETL_CANCEL;
4143 
4144     if (maybe_raise_dialog()) {
4145         return ret;
4146     }
4147 
4148     dialog = gretl_dialog_new(title, parent, GRETL_DLG_BLOCK);
4149     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
4150 
4151     if (label != NULL) {
4152         hbox = gtk_hbox_new(FALSE, 5);
4153         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
4154         gtk_widget_show(hbox);
4155         tmp = gtk_label_new(label);
4156         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
4157     }
4158 
4159     for (i=0; i<nopts; i++) {
4160         button = gtk_radio_button_new_with_label(group, _(opts[i]));
4161         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
4162         g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(i));
4163         g_signal_connect(G_OBJECT(button), "clicked",
4164                          G_CALLBACK(set_radio_opt), &radio_val);
4165         if (i == deflt) {
4166             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
4167         }
4168         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
4169     }
4170 
4171     if (extravar != NULL) {
4172         if (spinmin == 0 && spinmax == 0) {
4173             /* must be checkbox */
4174             vbox_add_hsep(vbox);
4175             tmp = option_checkbox(extravar, extratxt);
4176         } else {
4177             /* create spinner */
4178             tmp = option_spinbox(extravar, extratxt, spinmin, spinmax, 0, NULL);
4179         }
4180         gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
4181     }
4182 
4183     /* buttons */
4184     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
4185     cancel_delete_button(hbox, dialog);
4186     tmp = ok_validate_button(hbox, &ret, &radio_val);
4187     g_signal_connect(G_OBJECT(tmp), "clicked",
4188                      G_CALLBACK(delete_widget), dialog);
4189     gtk_widget_grab_default(tmp);
4190     if (hcode) {
4191         context_help_button(hbox, hcode);
4192     } else {
4193         gretl_dialog_keep_above(dialog);
4194     }
4195 
4196     gtk_widget_show_all(dialog);
4197 
4198     return ret;
4199 }
4200 
radio_dialog(const char * title,const char * label,const char ** opts,int nopts,int deflt,int hcode,GtkWidget * parent)4201 int radio_dialog (const char *title, const char *label, const char **opts,
4202                   int nopts, int deflt, int hcode, GtkWidget *parent)
4203 {
4204     return real_radio_dialog(title, label, opts, nopts, deflt, hcode,
4205                              NULL, NULL, 0, 0, parent);
4206 }
4207 
radio_dialog_with_spinner(const char * title,const char ** opts,int nopts,int deflt,int hcode,int * spinvar,const char * spintxt,int spinmin,int spinmax,GtkWidget * parent)4208 int radio_dialog_with_spinner (const char *title, const char **opts,
4209                                int nopts, int deflt, int hcode,
4210                                int *spinvar, const char *spintxt,
4211                                int spinmin, int spinmax,
4212                                GtkWidget *parent)
4213 {
4214     return real_radio_dialog(title, NULL, opts, nopts, deflt, hcode,
4215                              spinvar, spintxt, spinmin, spinmax,
4216                              parent);
4217 }
4218 
radio_dialog_with_check(const char * title,const char * label,const char ** opts,int nopts,int deflt,int hcode,int * checkvar,const char * checktxt,GtkWidget * parent)4219 int radio_dialog_with_check (const char *title, const char *label,
4220                              const char **opts, int nopts, int deflt,
4221                              int hcode, int *checkvar, const char *checktxt,
4222                              GtkWidget *parent)
4223 {
4224     return real_radio_dialog(title, label, opts, nopts, deflt, hcode,
4225                              checkvar, checktxt, 0, 0, parent);
4226 }
4227 
4228 /* selections in relation to kernel density estimation */
4229 
bw_set(GtkWidget * w,gpointer p)4230 static void bw_set (GtkWidget *w, gpointer p)
4231 {
4232     double *bw = (double *) p;
4233 
4234     *bw = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
4235 }
4236 
density_dialog(int vnum,double * bw)4237 int density_dialog (int vnum, double *bw)
4238 {
4239     GtkWidget *dialog;
4240     GtkWidget *button;
4241     GtkWidget *vbox;
4242     GtkWidget *hbox;
4243     GtkWidget *tmp;
4244     GSList *group;
4245     int radio_val = 0;
4246     int ret = GRETL_CANCEL;
4247 
4248     dialog = gretl_dialog_new(_("density estimation options"), NULL,
4249                               GRETL_DLG_BLOCK);
4250 
4251     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
4252 
4253     /* kernel option buttons */
4254 
4255     button = gtk_radio_button_new_with_label(NULL, _("Gaussian kernel"));
4256     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
4257     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
4258 
4259     g_signal_connect(G_OBJECT(button), "clicked",
4260                      G_CALLBACK(set_radio_opt), &radio_val);
4261     g_object_set_data(G_OBJECT(button), "action",
4262                       GINT_TO_POINTER(0));
4263 
4264     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
4265     button = gtk_radio_button_new_with_label(group, _("Epanechnikov kernel"));
4266     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
4267     g_signal_connect(G_OBJECT(button), "clicked",
4268                      G_CALLBACK(set_radio_opt), &radio_val);
4269     g_object_set_data(G_OBJECT(button), "action",
4270                       GINT_TO_POINTER(1));
4271 
4272     /* separator */
4273     vbox_add_hsep(vbox);
4274 
4275     /* bandwidth adjustment */
4276 
4277     hbox = gtk_hbox_new(FALSE, 5);
4278     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
4279 
4280     tmp = gtk_label_new(_("bandwidth adjustment factor:"));
4281     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
4282 
4283     tmp = gtk_spin_button_new_with_range(0.25, 4.0, .05);
4284     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), 1.0);
4285     gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
4286     g_signal_connect(G_OBJECT(tmp), "value-changed",
4287                      G_CALLBACK(bw_set),
4288                      bw);
4289     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
4290 
4291     /* buttons */
4292     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
4293     cancel_delete_button(hbox, dialog);
4294     tmp = ok_validate_button(hbox, &ret, &radio_val);
4295     g_signal_connect(G_OBJECT(tmp), "clicked",
4296                      G_CALLBACK(delete_widget),
4297                      dialog);
4298     gtk_widget_grab_default(tmp);
4299     context_help_button(hbox, KERNEL_DENSITY);
4300 
4301     gtk_widget_show_all(dialog);
4302 
4303     return ret;
4304 }
4305 
paste_data_dialog(int * append)4306 int paste_data_dialog (int *append)
4307 {
4308     GtkWidget *dialog;
4309     GtkWidget *vbox;
4310     GtkWidget *hbox;
4311     GtkWidget *tmp;
4312     int ret = GRETL_CANCEL;
4313 
4314     dialog = gretl_dialog_new(_("paste data from clipboard"), NULL,
4315                               GRETL_DLG_BLOCK);
4316 
4317     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
4318     hbox = gtk_hbox_new(FALSE, 5);
4319     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
4320 
4321     tmp = gtk_label_new(_("Try pasting data from clipboard?"));
4322     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
4323 
4324     if (dataset != NULL && dataset->v > 0) {
4325         /* clear/append buttons, if applicable */
4326         GtkWidget *button;
4327         GSList *group;
4328 
4329         hbox = gtk_hbox_new(FALSE, 5);
4330         button = gtk_radio_button_new_with_label(NULL, _("Clear current dataset first"));
4331         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10);
4332         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4333         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
4334         g_signal_connect(G_OBJECT(button), "clicked",
4335                          G_CALLBACK(set_radio_opt), append);
4336         g_object_set_data(G_OBJECT(button), "action",
4337                           GINT_TO_POINTER(0));
4338 
4339         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
4340         hbox = gtk_hbox_new(FALSE, 5);
4341         button = gtk_radio_button_new_with_label(group, _("Try appending to current dataset"));
4342         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10);
4343         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4344         g_signal_connect(G_OBJECT(button), "clicked",
4345                          G_CALLBACK(set_radio_opt), append);
4346         g_object_set_data(G_OBJECT(button), "action",
4347                           GINT_TO_POINTER(1));
4348     }
4349 
4350     /* buttons */
4351     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
4352     cancel_delete_button(hbox, dialog);
4353     tmp = ok_validate_button(hbox, &ret, NULL);
4354     g_signal_connect(G_OBJECT(tmp), "clicked",
4355                      G_CALLBACK(delete_widget),
4356                      dialog);
4357     gtk_widget_grab_default(tmp);
4358 
4359     gtk_widget_show_all(dialog);
4360 
4361     return ret;
4362 }
4363 
option_spin_set(GtkWidget * w,int * ivar)4364 static void option_spin_set (GtkWidget *w, int *ivar)
4365 {
4366     *ivar = spinner_get_int(w);
4367 }
4368 
dialog_blurb_box(const char * text)4369 static GtkWidget *dialog_blurb_box (const char *text)
4370 {
4371     GtkWidget *hbox;
4372     GtkWidget *label;
4373 
4374     hbox = gtk_hbox_new(FALSE, 5);
4375     label = gtk_label_new(text);
4376     gtk_widget_show(label);
4377     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
4378 
4379     return hbox;
4380 }
4381 
option_spinbox(int * spinvar,const char * spintxt,int spinmin,int spinmax,int ci,gpointer p)4382 static GtkWidget *option_spinbox (int *spinvar, const char *spintxt,
4383                                   int spinmin, int spinmax,
4384                                   int ci, gpointer p)
4385 {
4386     GtkWidget *hbox;
4387     GtkWidget *label;
4388     GtkWidget *button;
4389     GtkAdjustment *adj;
4390     int step = (ci == FREQ)? 2 : 1;
4391 
4392     hbox = gtk_hbox_new(FALSE, 5);
4393 
4394     if (spintxt != NULL) {
4395         label = gtk_label_new(spintxt);
4396         gtk_widget_show(label);
4397         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
4398     }
4399 
4400     adj = (GtkAdjustment *) gtk_adjustment_new(*spinvar, spinmin, spinmax,
4401                                                step, step, 0);
4402     button = gtk_spin_button_new(adj, 1, 0);
4403     gtk_entry_set_activates_default(GTK_ENTRY(button), TRUE);
4404     gtk_widget_show(button);
4405     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
4406 
4407     g_signal_connect(G_OBJECT(button), "value-changed",
4408                      G_CALLBACK(option_spin_set), spinvar);
4409 
4410     if (p != NULL) {
4411         GtkAdjustment **pobj = (GtkAdjustment **) p;
4412 
4413         *pobj = adj;
4414     }
4415 
4416     g_object_set_data(G_OBJECT(hbox), "spin-button", button);
4417 
4418     return hbox;
4419 }
4420 
option_check_set(GtkWidget * w,int * checkvar)4421 static void option_check_set (GtkWidget *w, int *checkvar)
4422 {
4423     *checkvar = button_is_active(w);
4424 }
4425 
option_checkbox(int * checkvar,const char * checktxt)4426 static GtkWidget *option_checkbox (int *checkvar, const char *checktxt)
4427 {
4428     GtkWidget *hbox;
4429     GtkWidget *button;
4430 
4431     hbox = gtk_hbox_new(FALSE, 5);
4432     button = gtk_check_button_new_with_label(checktxt);
4433     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
4434     gtk_widget_show(button);
4435 
4436     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *checkvar);
4437     g_signal_connect(G_OBJECT(button), "toggled",
4438                      G_CALLBACK(option_check_set), checkvar);
4439 
4440     return hbox;
4441 }
4442 
4443 static GtkWidget *check_extra;
4444 static int check_extra_pos;
4445 
4446 /* Mechanism to set an extra selector widget, linked
4447    to the check button at position @i in a checks
4448    dialog. The extra widget is placed following
4449    button @i and its sensitivity is conditional
4450    on button @i being checked.
4451 */
4452 
set_checks_dialog_extra(int i,GtkWidget * extra)4453 void set_checks_dialog_extra (int i, GtkWidget *extra)
4454 {
4455     check_extra_pos = i;
4456     check_extra = extra;
4457 }
4458 
set_checks_opt(GtkWidget * w,int * active)4459 static void set_checks_opt (GtkWidget *w, int *active)
4460 {
4461     int i = widget_get_int(w, "optnum");
4462 
4463     active[i] = button_is_active(w);
4464 }
4465 
checks_dialog_add_checks(GtkWidget * dialog,GtkWidget * vbox,const char ** opts,int nchecks,int * active,int check_min,int check_max)4466 static void checks_dialog_add_checks (GtkWidget *dialog, GtkWidget *vbox,
4467                                       const char **opts, int nchecks,
4468                                       int *active, int check_min,
4469                                       int check_max)
4470 {
4471     GtkWidget *prev_button = NULL;
4472     GtkWidget *hbox, *button;
4473     int nc0 = 0, nc1 = 0;
4474     int i;
4475 
4476     if (check_min >= 0 && check_max > check_min && check_max <= nchecks) {
4477         nc0 = check_min;
4478         nc1 = check_max;
4479     }
4480 
4481     if (nc1 > 0) {
4482         g_object_set_data(G_OBJECT(dialog), "active", active);
4483         widget_set_int(dialog, "check-min", check_min);
4484         widget_set_int(dialog, "check-max", check_max);
4485     }
4486 
4487     for (i=0; i<nchecks; i++) {
4488         if (nc1 > 0 && i == nc0) {
4489             /* mark start of the "must check one" area */
4490             vbox_add_hsep(vbox);
4491         }
4492 
4493         button = gtk_check_button_new_with_label(_(opts[i]));
4494         hbox = gtk_hbox_new(FALSE, 0);
4495         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
4496         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4497 
4498         if (active[i] < 0) {
4499             gtk_widget_set_sensitive(button, FALSE);
4500         } else {
4501             if (active[i] > 0) {
4502                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
4503             }
4504             g_signal_connect(G_OBJECT(button), "clicked",
4505                              G_CALLBACK(set_checks_opt), active);
4506             g_object_set_data(G_OBJECT(button), "optnum",
4507                               GINT_TO_POINTER(i));
4508         }
4509 
4510         if (check_extra != NULL && i == check_extra_pos) {
4511             /* insert the "extra" widget under @button */
4512             gtk_box_pack_start(GTK_BOX(vbox), check_extra, TRUE, TRUE, 0);
4513             gtk_widget_set_sensitive(check_extra, active[i]);
4514             sensitize_conditional_on(check_extra, button);
4515             /* and erase the "extra" specification */
4516             check_extra = NULL;
4517             check_extra_pos = -1;
4518         } else if (prev_button != NULL && strstr(opts[i], "Perron-Qu")) {
4519             gtk_widget_set_sensitive(button, active[0]);
4520             sensitize_conditional_on(button, prev_button);
4521         }
4522 
4523         prev_button = button;
4524 
4525         if (i+1 == nc1) {
4526             /* mark end of the "must check one" area */
4527             vbox_add_hsep(vbox);
4528         }
4529     }
4530 
4531     if (nchecks == 1) {
4532         /* add handle for switching sensitivity */
4533         g_object_set_data(G_OBJECT(dialog), "checkbox", button);
4534     }
4535 }
4536 
checks_dialog_add_radios(GtkWidget * vbox,const char ** opts,int nradios,int * rvar)4537 static void checks_dialog_add_radios (GtkWidget *vbox, const char **opts,
4538                                       int nradios, int *rvar)
4539 {
4540     GtkWidget *hbox, *button = NULL;
4541     GSList *group = NULL;
4542     int i;
4543 
4544     for (i=0; i<nradios; i++) {
4545         button = gtk_radio_button_new_with_label(group, _(opts[i]));
4546         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
4547         hbox = gtk_hbox_new(FALSE, 0);
4548         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
4549         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4550         g_object_set_data(G_OBJECT(button), "action",
4551                           GINT_TO_POINTER(i));
4552         g_signal_connect(G_OBJECT(button), "clicked",
4553                          G_CALLBACK(set_radio_opt), rvar);
4554         if (rvar != NULL && *rvar == i) {
4555             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
4556         }
4557     }
4558 }
4559 
checks_dialog_ok(GtkButton * button,GtkWidget * dialog)4560 static void checks_dialog_ok (GtkButton *button, GtkWidget *dialog)
4561 {
4562     int nc0 = widget_get_int(dialog, "check-min");
4563     int nc1 = widget_get_int(dialog, "check-max");
4564     int done = 1;
4565 
4566     if (nc1 > 0) {
4567         /* in case at least one option needs to be selected,
4568            check that this is so */
4569         int *active = g_object_get_data(G_OBJECT(dialog), "active");
4570         int i;
4571 
4572         done = 0;
4573         for (i=nc0; i<nc1; i++) {
4574             if (active[i]) {
4575                 done = 1;
4576                 break;
4577             }
4578         }
4579     }
4580 
4581     if (done) {
4582         int *retptr = g_object_get_data(G_OBJECT(button), "retptr");
4583 
4584         if (retptr != NULL) {
4585             /* signal the all clear */
4586             *retptr = 0;
4587         }
4588         gtk_widget_destroy(dialog);
4589     } else {
4590         /* Right now this is used only for ADF test, in which case
4591            "no model" is a more specific message than "no action"
4592            or "no option". But if we use this for other dialogs this
4593            message may not be appropriate.
4594         */
4595         warnbox(_("No model is specified"));
4596     }
4597 }
4598 
4599 /*
4600   Notes:
4601 
4602   @nchecks is the number of check buttons.
4603 
4604   @check_min and @check_max: if @check_max is > 0, it indicates
4605   that at least one check button with index greater than or
4606   equal to @check_min and less than @check_max must be selected,
4607   or else the the dialog would give a null result.
4608 
4609   This is used to flag a warning to the user if OK is pressed with
4610   "nothing selected".
4611 */
4612 
4613 GtkWidget *
build_checks_dialog(const char * title,const char * blurb,const char ** opts,int nchecks,int * active,int check_min,int check_max,int nradios,int * rvar,int * spinvar,const char * spintxt,int spinmin,int spinmax,int hcode,GtkWidget * parent,int * ret)4614 build_checks_dialog (const char *title, const char *blurb,
4615                      const char **opts,
4616                      int nchecks, int *active,
4617                      int check_min, int check_max,
4618                      int nradios, int *rvar,
4619                      int *spinvar, const char *spintxt,
4620                      int spinmin, int spinmax,
4621                      int hcode, GtkWidget *parent,
4622                      int *ret)
4623 {
4624     GtkWidget *dialog, *tmp;
4625     GtkWidget *vbox, *hbox, *okb;
4626     int radios_first = 0;
4627 
4628     if (maybe_raise_dialog()) {
4629         return NULL;
4630     }
4631 
4632     dialog = gretl_dialog_new(title, parent, GRETL_DLG_BLOCK);
4633     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
4634 
4635     if (nradios < 0) {
4636         /* negative value for nradios says put the radios first */
4637         radios_first = 1;
4638         nradios = -nradios;
4639     }
4640 
4641     /* create upper label if wanted */
4642     if (blurb != NULL) {
4643         tmp = dialog_blurb_box(blurb);
4644         gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
4645     }
4646 
4647     /* create spinner if wanted */
4648     if (spinvar != NULL) {
4649         tmp = option_spinbox(spinvar, spintxt, spinmin, spinmax, hcode, NULL);
4650         gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
4651     }
4652 
4653     /* create leading radio buttons, if any */
4654     if (radios_first) {
4655         checks_dialog_add_radios(vbox, opts, nradios, rvar);
4656         opts += nradios;
4657     }
4658 
4659     /* create check buttons, if any */
4660     if (nchecks > 0) {
4661         if (radios_first) {
4662             gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), TRUE, TRUE, 5);
4663         }
4664         checks_dialog_add_checks(dialog, vbox, opts, nchecks, active,
4665                                  check_min, check_max);
4666         opts += nchecks;
4667     }
4668 
4669     /* create trailing radio buttons, if any */
4670     if (nradios > 0 && !radios_first) {
4671         if (nchecks > 0) {
4672             gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), TRUE, TRUE, 5);
4673         }
4674         checks_dialog_add_radios(vbox, opts, nradios, rvar);
4675     }
4676 
4677     /* buttons */
4678     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
4679     cancel_delete_button(hbox, dialog);
4680     okb = ok_button(hbox);
4681     if (ret != NULL) {
4682         g_object_set_data(G_OBJECT(okb), "retptr", ret);
4683     }
4684     g_signal_connect(G_OBJECT(okb), "clicked",
4685                      G_CALLBACK(checks_dialog_ok),
4686                      dialog);
4687     gtk_widget_grab_default(okb);
4688     if (hcode && hcode != FREQ) {
4689         context_help_button(hbox, hcode);
4690     }
4691 
4692     if (!hcode) {
4693         gretl_dialog_keep_above(dialog);
4694     }
4695 
4696     return dialog;
4697 }
4698 
4699 /* general purpose dialog offering check-button options and/or
4700    a spinner with numerical values */
4701 
checks_dialog(const char * title,const char * blurb,const char ** opts,int nchecks,int * active,int check_min,int check_max,int nradios,int * rvar,int * spinvar,const char * spintxt,int spinmin,int spinmax,int hcode,GtkWidget * parent)4702 int checks_dialog (const char *title, const char *blurb,
4703                    const char **opts,
4704                    int nchecks, int *active,
4705                    int check_min, int check_max,
4706                    int nradios, int *rvar,
4707                    int *spinvar, const char *spintxt,
4708                    int spinmin, int spinmax,
4709                    int hcode, GtkWidget *parent)
4710 {
4711     GtkWidget *dlg;
4712     int ret = GRETL_CANCEL;
4713 
4714     dlg = build_checks_dialog(title, blurb, opts,
4715                               nchecks, active,
4716                               check_min, check_max,
4717                               nradios, rvar,
4718                               spinvar, spintxt,
4719                               spinmin, spinmax,
4720                               hcode, parent, &ret);
4721 
4722     if (dlg != NULL) {
4723         gtk_widget_show_all(dlg);
4724     }
4725 
4726     return ret;
4727 }
4728 
checks_only_dialog(const char * title,const char * blurb,const char ** opts,int nopts,int * active,int hcode,GtkWidget * parent)4729 int checks_only_dialog (const char *title, const char *blurb,
4730                         const char **opts, int nopts, int *active,
4731                         int hcode, GtkWidget *parent)
4732 {
4733     GtkWidget *dlg;
4734     int ret = -1;
4735 
4736     dlg = build_checks_dialog(title, blurb,
4737                               opts, nopts, active, 0, 0,
4738                               0, NULL,    /* no radios */
4739                               NULL, NULL, /* no spinners */
4740                               0, 0, hcode, parent, &ret);
4741 
4742     if (dlg != NULL) {
4743         gtk_widget_show_all(dlg);
4744     }
4745 
4746     return ret;
4747 }
4748 
spin_dialog(const char * title,const char * blurb,int * spinvar,const char * spintxt,int spinmin,int spinmax,int hcode,GtkWidget * parent)4749 int spin_dialog (const char *title, const char *blurb,
4750                  int *spinvar, const char *spintxt,
4751                  int spinmin, int spinmax, int hcode,
4752                  GtkWidget *parent)
4753 {
4754     return checks_dialog(title, blurb,
4755                          NULL, 0, NULL, 0, 0, /* no checks */
4756                          0, NULL,             /* no radios */
4757                          spinvar, spintxt, spinmin, spinmax,
4758                          hcode, parent);
4759 }
4760 
pergm_set_bartlett(GtkToggleButton * button,gretlopt * opt)4761 static void pergm_set_bartlett (GtkToggleButton *button, gretlopt *opt)
4762 {
4763     if (gtk_toggle_button_get_active(button)) {
4764         *opt |= OPT_O;
4765     } else {
4766         *opt &= ~OPT_O;
4767     }
4768 }
4769 
pergm_set_log_scale(GtkToggleButton * button,gretlopt * opt)4770 static void pergm_set_log_scale (GtkToggleButton *button, gretlopt *opt)
4771 {
4772     if (gtk_toggle_button_get_active(button)) {
4773         *opt |= OPT_L;
4774     } else {
4775         *opt &= ~OPT_L;
4776     }
4777 }
4778 
pergm_set_axis(GtkComboBox * combo,gretlopt * opt)4779 static void pergm_set_axis (GtkComboBox *combo, gretlopt *opt)
4780 {
4781     int val = gtk_combo_box_get_active(combo);
4782 
4783     if (val == 0) {
4784         *opt &= ~OPT_R;
4785         *opt &= ~OPT_D;
4786     } else if (val == 1) {
4787         *opt &= ~OPT_D;
4788         *opt |= OPT_R;
4789     } else {
4790         *opt &= ~OPT_R;
4791         *opt |= OPT_D;
4792     }
4793 }
4794 
pergm_set_bandwidth(GtkSpinButton * spin,int * bw)4795 static void pergm_set_bandwidth (GtkSpinButton *spin, int *bw)
4796 {
4797     *bw = gtk_spin_button_get_value_as_int(spin);
4798 }
4799 
pergm_dialog(gretlopt * opt,int * spinval,int spinmin,int spinmax,GtkWidget * parent)4800 int pergm_dialog (gretlopt *opt, int *spinval, int spinmin, int spinmax,
4801                   GtkWidget *parent)
4802 {
4803     GtkWidget *dialog, *vbox, *hbox;
4804     GtkWidget *button, *spin, *w;
4805     GSList *group;
4806     int ret = GRETL_CANCEL;
4807 
4808     if (maybe_raise_dialog()) {
4809         return ret;
4810     }
4811 
4812     dialog = gretl_dialog_new(_("gretl: periodogram"), parent,
4813                               GRETL_DLG_BLOCK);
4814     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
4815 
4816     /* sample vs Bartlett radios, with Bartlett spinner */
4817 
4818     button = gtk_radio_button_new_with_label(NULL, _("Sample periodogram"));
4819     hboxit(button, vbox);
4820 
4821     hbox = gtk_hbox_new(FALSE, 5);
4822     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
4823     button = gtk_radio_button_new_with_label(group, _("Bartlett window, bandwidth:"));
4824     g_signal_connect(G_OBJECT(button), "toggled",
4825                      G_CALLBACK(pergm_set_bartlett), opt);
4826     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
4827 
4828     spin = gtk_spin_button_new_with_range(spinmin, spinmax, 1);
4829     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), *spinval);
4830     g_signal_connect(G_OBJECT(spin), "value-changed",
4831                      G_CALLBACK(pergm_set_bandwidth), spinval);
4832     gtk_widget_set_sensitive(spin, FALSE);
4833     sensitize_conditional_on(spin, button);
4834     gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 5);
4835     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4836 
4837     /* Log scale checkbox */
4838     button = gtk_check_button_new_with_label(_("log scale"));
4839     g_signal_connect(G_OBJECT(button), "toggled",
4840                      G_CALLBACK(pergm_set_log_scale), opt);
4841     hboxit(button, vbox);
4842 
4843     /* frequency axis selector */
4844     hbox = gtk_hbox_new(FALSE, 5);
4845     w = gtk_label_new(_("frequency axis scale:"));
4846     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
4847     w = gtk_combo_box_text_new();
4848     combo_box_append_text(w, _("data-based"));
4849     combo_box_append_text(w, _("radians"));
4850     combo_box_append_text(w, _("degrees"));
4851     gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0);
4852     g_signal_connect(G_OBJECT(w), "changed",
4853                      G_CALLBACK(pergm_set_axis), opt);
4854     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
4855     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
4856 
4857     /* buttons */
4858     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
4859     cancel_delete_button(hbox, dialog);
4860     button = ok_validate_button(hbox, &ret, NULL);
4861     g_signal_connect(G_OBJECT(button), "clicked",
4862                      G_CALLBACK(delete_widget),
4863                      dialog);
4864     gtk_widget_grab_default(button);
4865     context_help_button(hbox, PERGM);
4866 
4867     gtk_widget_show_all(dialog);
4868 
4869     return ret;
4870 }
4871 
set_response_yes(GtkButton * b,int * ret)4872 static void set_response_yes (GtkButton *b, int *ret)
4873 {
4874     *ret = GRETL_YES;
4875 }
4876 
yes_no_help_dialog(const char * msg,int hcode,int deflt)4877 int yes_no_help_dialog (const char *msg, int hcode, int deflt)
4878 {
4879     GtkWidget *dlg;
4880     GtkWidget *vbox, *hbox, *tmp;
4881     GtkWidget *button = NULL;
4882     int ret = GRETL_NO;
4883 
4884     dlg = gretl_dialog_new("gretl", NULL, GRETL_DLG_BLOCK);
4885 #if GTK_MAJOR_VERSION < 3
4886     gtk_dialog_set_has_separator(GTK_DIALOG(dlg), FALSE);
4887 #endif
4888 
4889     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
4890 
4891     tmp = dialog_blurb_box(msg);
4892     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
4893 
4894     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
4895 
4896     /* Yes button */
4897     button = gtk_button_new_from_stock(GTK_STOCK_YES);
4898     g_signal_connect(G_OBJECT(button), "clicked",
4899                      G_CALLBACK(set_response_yes), &ret);
4900     g_signal_connect(G_OBJECT(button), "clicked",
4901                      G_CALLBACK(delete_widget), dlg);
4902     gtk_widget_set_can_default(button, TRUE);
4903     gtk_container_add(GTK_CONTAINER(hbox), button);
4904     gtk_widget_set_can_default(button, TRUE);
4905     if (deflt == GRETL_YES) {
4906 	gtk_widget_grab_default(button);
4907     } else {
4908 	gtk_widget_set_can_default(button, FALSE);
4909     }
4910 
4911     /* No button */
4912     button = gtk_button_new_from_stock(GTK_STOCK_NO);
4913     gtk_container_add(GTK_CONTAINER(hbox), button);
4914     g_signal_connect(G_OBJECT(button), "clicked",
4915                      G_CALLBACK(delete_widget), dlg);
4916     if (deflt == GRETL_NO) {
4917 	gtk_widget_set_can_default(button, TRUE);
4918 	gtk_widget_grab_default(button);
4919     }
4920 
4921     /* Help button */
4922     context_help_button(hbox, hcode);
4923 
4924     gtk_widget_show_all(dlg);
4925 
4926     return ret;
4927 }
4928 
4929 /* mechanism for adjusting properties of frequency plot */
4930 
4931 struct freqdist_info {
4932     int *nbins;
4933     double *fmin;
4934     double *fwid;
4935     double xmin;
4936     double xmax;
4937     GtkWidget *spin[3];
4938 };
4939 
freq_info_set(GtkWidget * w,struct freqdist_info * f)4940 static gboolean freq_info_set (GtkWidget *w, struct freqdist_info *f)
4941 {
4942     int snum = widget_get_int(w, "snum");
4943     double val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
4944 
4945     if (snum == 0) {
4946         /* numbins */
4947         *f->nbins = (int) val;
4948     } else if (snum == 1) {
4949         /* minval */
4950         *f->fmin = val;
4951     } else {
4952         /* bin width */
4953         *f->fwid = val;
4954     }
4955 
4956     /* update complementary fields */
4957 
4958     if (snum == 0 && gtk_widget_is_sensitive(f->spin[0])) {
4959         *f->fwid = (f->xmax - f->xmin) / (*f->nbins - 1);
4960         gtk_spin_button_set_value(GTK_SPIN_BUTTON(f->spin[2]), *f->fwid);
4961         *f->fmin = f->xmin - 0.5 * (*f->fwid);
4962         if (f->xmin >= 0.0 && *f->fmin < 0) {
4963             *f->fmin = 0.0;
4964         }
4965         gtk_spin_button_set_value(GTK_SPIN_BUTTON(f->spin[1]), *f->fmin);
4966     } else if (snum == 2 && gtk_widget_is_sensitive(f->spin[2])) {
4967         *f->nbins = ceil((f->xmax - *f->fmin) / *f->fwid);
4968         gtk_spin_button_set_value(GTK_SPIN_BUTTON(f->spin[0]), *f->nbins);
4969     }
4970 
4971     return FALSE;
4972 }
4973 
freq_set_dist(GtkWidget * w,int * dist)4974 static void freq_set_dist (GtkWidget *w, int *dist)
4975 {
4976     int fopt = widget_get_int(w, "fopt");
4977 
4978     if (button_is_active(w)) {
4979         if (fopt == 0) *dist = D_NONE;
4980         else if (fopt == 1) *dist = D_NORMAL;
4981         else if (fopt == 2) *dist = D_GAMMA;
4982     }
4983 }
4984 
freq_info_control(GtkWidget * w,struct freqdist_info * f)4985 static void freq_info_control (GtkWidget *w, struct freqdist_info *f)
4986 {
4987     int snum = widget_get_int(w, "snum");
4988 
4989     if (button_is_active(w)) {
4990         gtk_widget_set_sensitive(f->spin[0], snum == 0);
4991         gtk_widget_set_sensitive(f->spin[1], snum == 1);
4992         gtk_widget_set_sensitive(f->spin[2], snum == 1);
4993     }
4994 }
4995 
revise_finfo(GtkWidget * w,struct freqdist_info * f)4996 static void revise_finfo (GtkWidget *w, struct freqdist_info *f)
4997 {
4998     if (!gtk_widget_is_sensitive(f->spin[0])) {
4999         *f->nbins = 0;
5000     } else {
5001         *f->fmin = NADBL;
5002         *f->fwid = NADBL;
5003     }
5004 }
5005 
freq_set_plot(GtkToggleButton * b,int * plot)5006 static void freq_set_plot (GtkToggleButton *b, int *plot)
5007 {
5008     *plot = gtk_toggle_button_get_active(b);
5009 }
5010 
freq_dialog(const char * title,const char * blurb,int * nbins,int nbmax,double * f0,double * fwid,double xmin,double xmax,int * dist,int * plot)5011 int freq_dialog (const char *title, const char *blurb,
5012                  int *nbins, int nbmax, double *f0, double *fwid,
5013                  double xmin, double xmax, int *dist, int *plot)
5014 {
5015     struct freqdist_info finfo;
5016     GtkWidget *dialog, *rb;
5017     GtkWidget *vbox, *hbox;
5018     GtkWidget *tmp, *okb;
5019     GSList *group = NULL;
5020     int show_bin_opts;
5021     int show_dist_opts;
5022     int i, ret = GRETL_CANCEL;
5023 
5024     if (maybe_raise_dialog()) {
5025         return ret;
5026     }
5027 
5028     dialog = gretl_dialog_new(title, NULL, GRETL_DLG_BLOCK);
5029 
5030     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
5031 
5032     finfo.nbins = nbins;
5033     finfo.fmin = f0;
5034     finfo.fwid = fwid;
5035     finfo.xmax = xmax;
5036     finfo.xmin = xmin;
5037 
5038     show_bin_opts = nbins != NULL;
5039     show_dist_opts = nbmax > 15;
5040 
5041     /* upper label */
5042     tmp = dialog_blurb_box(blurb);
5043     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
5044 
5045     if (show_bin_opts) {
5046         const char *strs[] = {
5047             N_("Number of bins:"),
5048             N_("Minimum value, left bin:"),
5049             N_("Bin width:")
5050         };
5051         GtkWidget *tbl;
5052         GtkAdjustment *adj;
5053         double f0min, f0max, f0step;
5054         double wmin, wmax, wstep;
5055 
5056         tbl = gtk_table_new(3, 2, FALSE);
5057         gtk_table_set_col_spacings(GTK_TABLE(tbl), 5);
5058         gtk_table_set_row_spacings(GTK_TABLE(tbl), 5);
5059 
5060         *f0 = xmin - 0.5 * (*fwid);
5061         if (xmin >= 0.0 && *f0 < 0) {
5062             *f0 = 0.0;
5063         }
5064 
5065         f0min = xmin - 0.2 * (xmax - xmin);
5066         f0max = xmin - 0.01 * (*fwid);
5067         f0step = .001;
5068 
5069         wmin = (xmax - xmin) / nbmax;
5070         wmax = (xmax - xmin) / 3.0;
5071         wstep = 0.001;
5072 
5073         for (i=0; i<3; i++) {
5074             int dig = (i == 0)? 0 : 3;
5075 
5076             if (i < 2) {
5077                 rb = gtk_radio_button_new_with_label(group, _(strs[i]));
5078                 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rb));
5079                 gtk_table_attach_defaults(GTK_TABLE(tbl), rb, 0, 1, i, i+1);
5080                 g_object_set_data(G_OBJECT(rb), "snum", GINT_TO_POINTER(i));
5081                 g_signal_connect(G_OBJECT(rb), "clicked",
5082                                  G_CALLBACK(freq_info_control), &finfo);
5083             } else {
5084                 tmp = gtk_label_new(_(strs[i]));
5085                 gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, i, i+1);
5086             }
5087 
5088             if (i == 0) {
5089                 adj = (GtkAdjustment *) gtk_adjustment_new(*nbins, 3, nbmax,
5090                                                            2, 2, 0);
5091             } else if (i == 1) {
5092                 adj = (GtkAdjustment *) gtk_adjustment_new(*f0, f0min, f0max,
5093                                                            f0step, 10.0 * f0step, 0);
5094             } else {
5095                 adj = (GtkAdjustment *) gtk_adjustment_new(*fwid, wmin, wmax,
5096                                                            wstep, 10.0 * wstep, 0);
5097             }
5098 
5099             finfo.spin[i] = gtk_spin_button_new(adj, 1, dig);
5100             gtk_entry_set_activates_default(GTK_ENTRY(finfo.spin[i]), TRUE);
5101             gtk_table_attach_defaults(GTK_TABLE(tbl), finfo.spin[i], 1, 2, i, i+1);
5102             g_object_set_data(G_OBJECT(finfo.spin[i]), "snum",
5103                               GINT_TO_POINTER(i));
5104             g_signal_connect(G_OBJECT(finfo.spin[i]), "value-changed",
5105                              G_CALLBACK(freq_info_set), &finfo);
5106             if (i > 0) {
5107                 gtk_widget_set_sensitive(finfo.spin[i], FALSE);
5108             }
5109         }
5110 
5111         gtk_container_add(GTK_CONTAINER(vbox), tbl);
5112 
5113         if (show_dist_opts) {
5114             vbox_add_hsep(vbox);
5115             group = NULL;
5116         }
5117     }
5118 
5119     if (show_dist_opts) {
5120         /* if var has negative values, don't show Gamma dist option */
5121         const char *dist_opts[] = {
5122             N_("Show data only"),
5123             N_("Test against normal distribution"),
5124             N_("Test against gamma distribution")
5125         };
5126         int imax = (xmin < 0)? 2 : 3;
5127 
5128         for (i=0; i<imax; i++) {
5129             hbox = gtk_hbox_new(FALSE, 5);
5130             rb = gtk_radio_button_new_with_label(group, _(dist_opts[i]));
5131             group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rb));
5132             g_object_set_data(G_OBJECT(rb), "fopt", GINT_TO_POINTER(i));
5133             g_signal_connect(G_OBJECT(rb), "clicked",
5134                              G_CALLBACK(freq_set_dist), dist);
5135             gtk_container_add(GTK_CONTAINER(hbox), rb);
5136             gtk_container_add(GTK_CONTAINER(vbox), hbox);
5137         }
5138     }
5139 
5140     /* show plot option */
5141     vbox_add_hsep(vbox);
5142     hbox = gtk_hbox_new(FALSE, 5);
5143     tmp = gtk_check_button_new_with_label(_("show plot"));
5144     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), *plot);
5145     g_signal_connect(G_OBJECT(tmp), "toggled",
5146                      G_CALLBACK(freq_set_plot), plot);
5147     gtk_container_add(GTK_CONTAINER(hbox), tmp);
5148     gtk_container_add(GTK_CONTAINER(vbox), hbox);
5149 
5150     /* buttons */
5151     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
5152     cancel_delete_button(hbox, dialog);
5153     okb = ok_validate_button(hbox, &ret, NULL);
5154     if (nbins != NULL) {
5155         g_signal_connect(G_OBJECT(okb), "clicked",
5156 			 G_CALLBACK(revise_finfo), &finfo);
5157     }
5158     g_signal_connect(G_OBJECT(okb), "clicked",
5159 		     G_CALLBACK(delete_widget), dialog);
5160     gtk_widget_grab_default(okb);
5161     if (nbins != NULL) {
5162         context_help_button(hbox, FREQ);
5163     } else {
5164         gretl_dialog_keep_above(dialog);
5165     }
5166 
5167     gtk_widget_show_all(dialog);
5168 
5169     return ret;
5170 }
5171 
5172 struct mtab_info {
5173     GtkWidget *ch0; /* column head default */
5174     GtkWidget *se0; /* stderr (vs t-stat) selector */
5175     GtkWidget *pv0; /* p-values checkbox */
5176     GtkWidget *as0; /* asterisks checkbox */
5177     GtkWidget *fig; /* figures spinner */
5178     GtkWidget *dec; /* decimal places option */
5179 };
5180 
mtab_reset_callback(GtkWidget * w,struct mtab_info * mti)5181 static void mtab_reset_callback (GtkWidget *w,
5182                                  struct mtab_info *mti)
5183 {
5184     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mti->ch0), TRUE);
5185     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mti->se0), TRUE);
5186     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mti->pv0), FALSE);
5187     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mti->as0), TRUE);
5188 
5189     gtk_spin_button_set_value(GTK_SPIN_BUTTON(mti->fig), 4);
5190     gtk_combo_box_set_active(GTK_COMBO_BOX(mti->dec), 0);
5191 }
5192 
model_table_set_format(GtkComboBox * combo,char * fmt)5193 static void model_table_set_format (GtkComboBox *combo, char *fmt)
5194 {
5195     if (gtk_combo_box_get_active(combo) == 0) {
5196         *fmt = 'g';
5197     } else {
5198         *fmt = 'f';
5199     }
5200 }
5201 
model_table_spin_config(GtkComboBox * combo,GtkSpinButton * spin)5202 static void model_table_spin_config (GtkComboBox *combo, GtkSpinButton *spin)
5203 {
5204     if (gtk_combo_box_get_active(combo) == 0) {
5205         gtk_spin_button_set_range(spin, 2, 6);
5206     } else {
5207         gtk_spin_button_set_range(spin, 0, 6);
5208     }
5209 }
5210 
model_table_set_figs(GtkSpinButton * spin,int * figs)5211 static void model_table_set_figs (GtkSpinButton *spin, int *figs)
5212 {
5213     *figs = gtk_spin_button_get_value(spin);
5214 }
5215 
5216 /* Sets option indices for column headings type and standard errors
5217    versus t-stats, also the number of significant figures to show.
5218    Returns GRETL_CANCEL on cancel, otherwise 0.
5219 */
5220 
model_table_dialog(int * colhead_opt,int * se_opt,int * pv_opt,int * ast_opt,int * figs,char * fmt,GtkWidget * parent)5221 int model_table_dialog (int *colhead_opt, int *se_opt, int *pv_opt,
5222                         int *ast_opt, int *figs, char *fmt,
5223                         GtkWidget *parent)
5224 {
5225     struct mtab_info mti = {0};
5226     const char *col_opts[] = {
5227         "(1), (2), (3), ...",
5228         "I, II, III, ...",
5229         "A, B, C, ...",
5230         N_("Use model names")
5231     };
5232     const char *se_opts[] = {
5233         N_("Show standard errors in parentheses"),
5234         N_("Show t-statistics in parentheses")
5235     };
5236     GtkWidget *dialog;
5237     GtkWidget *vbox, *hbox, *tmp;
5238     GtkWidget *spin, *button = NULL;
5239     GSList *group = NULL;
5240     int i, ret = GRETL_CANCEL;
5241 
5242     if (maybe_raise_dialog()) {
5243         return ret;
5244     }
5245 
5246     dialog = gretl_dialog_new("gretl", parent, GRETL_DLG_BLOCK);
5247 
5248     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
5249 
5250     hbox = gtk_hbox_new(FALSE, 5);
5251     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
5252     tmp = gtk_label_new(_("model table options"));
5253     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
5254 
5255     vbox_add_hsep(vbox);
5256 
5257     hbox = gtk_hbox_new(FALSE, 5);
5258     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
5259     tmp = gtk_label_new(_("column headings"));
5260     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5261 
5262     /* column heading options */
5263     for (i=0; i<4; i++) {
5264         if (i == 3) {
5265             button = gtk_radio_button_new_with_label(group, _(col_opts[i]));
5266         } else {
5267             button = gtk_radio_button_new_with_label(group, col_opts[i]);
5268         }
5269         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
5270         if (i == 0) {
5271             mti.ch0 = button;
5272         }
5273         if (i == *colhead_opt) {
5274             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
5275         }
5276         g_signal_connect(G_OBJECT(button), "clicked",
5277                          G_CALLBACK(set_radio_opt), colhead_opt);
5278         g_object_set_data(G_OBJECT(button), "action",
5279                           GINT_TO_POINTER(i));
5280         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
5281     }
5282 
5283     vbox_add_hsep(vbox);
5284 
5285     /* standard error / t-ratios option */
5286     group = NULL;
5287     for (i=0; i<2; i++) {
5288         button = gtk_radio_button_new_with_label(group, _(se_opts[i]));
5289         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
5290         if (i == *se_opt) {
5291             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
5292         }
5293         if (i == 0) {
5294             mti.se0 = button;
5295         }
5296         g_signal_connect(G_OBJECT(button), "clicked",
5297                          G_CALLBACK(set_radio_opt), se_opt);
5298         g_object_set_data(G_OBJECT(button), "action",
5299                           GINT_TO_POINTER(i));
5300         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
5301     }
5302 
5303     vbox_add_hsep(vbox);
5304 
5305     /* show p-values box */
5306     mti.pv0 = button =
5307         gtk_check_button_new_with_label(_("Show p-values"));
5308     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *pv_opt);
5309     g_signal_connect(G_OBJECT(button), "clicked",
5310                      G_CALLBACK(option_check_set), pv_opt);
5311     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
5312 
5313     /* show asterisks box */
5314     mti.as0 =button =
5315         gtk_check_button_new_with_label(_("Show significance asterisks"));
5316     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *ast_opt);
5317     g_signal_connect(G_OBJECT(button), "clicked",
5318                      G_CALLBACK(option_check_set), ast_opt);
5319     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
5320     vbox_add_hsep(vbox);
5321 
5322     /* spinner for number of digits */
5323     hbox = gtk_hbox_new(FALSE, 5);
5324     tmp = gtk_label_new(_("Show"));
5325     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5326     spin = gtk_spin_button_new_with_range((*fmt == 'g')? 2 : 0, 6, 1);
5327     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), *figs);
5328     g_signal_connect(G_OBJECT(GTK_SPIN_BUTTON(spin)), "value-changed",
5329                      G_CALLBACK(model_table_set_figs), figs);
5330     gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
5331     mti.fig = spin;
5332 
5333     /* selector for significant figs vs decimal places */
5334     mti.dec = tmp = gtk_combo_box_text_new();
5335     combo_box_append_text(tmp, _("significant figures"));
5336     combo_box_append_text(tmp, _("decimal places"));
5337     if (*fmt == 'g') {
5338         gtk_combo_box_set_active(GTK_COMBO_BOX(tmp), 0);
5339     } else {
5340         gtk_combo_box_set_active(GTK_COMBO_BOX(tmp), 1);
5341     }
5342     g_signal_connect(G_OBJECT(GTK_COMBO_BOX(tmp)), "changed",
5343                      G_CALLBACK(model_table_set_format), fmt);
5344     g_signal_connect(G_OBJECT(GTK_COMBO_BOX(tmp)), "changed",
5345                      G_CALLBACK(model_table_spin_config), spin);
5346     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5347     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
5348 
5349     /* buttons */
5350     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
5351     button = gtk_button_new_with_label(_("Reset"));
5352     gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
5353     g_signal_connect(G_OBJECT(button), "clicked",
5354                      G_CALLBACK(mtab_reset_callback), &mti);
5355     cancel_delete_button(hbox, dialog);
5356     tmp = ok_validate_button(hbox, &ret, NULL);
5357     g_signal_connect(G_OBJECT(tmp), "clicked",
5358                      G_CALLBACK(delete_widget), dialog);
5359     gtk_widget_grab_default(tmp);
5360 
5361     gretl_dialog_keep_above(dialog);
5362     gtk_widget_show_all(dialog);
5363 
5364     return ret;
5365 }
5366 
msgbox(const char * msg,int msgtype,GtkWidget * parent)5367 void msgbox (const char *msg, int msgtype, GtkWidget *parent)
5368 {
5369     const gchar *titles[] = {
5370         N_("gretl: error"),
5371         N_("gretl: warning"),
5372         N_("gretl: information")
5373     };
5374     const gchar *title;
5375     gchar *trmsg = NULL;
5376     GtkWidget *dialog;
5377     GtkWindow *pwin;
5378 
5379     if (msg == NULL) {
5380         return;
5381     }
5382 
5383     if (!g_utf8_validate(msg, -1, NULL)) {
5384         /* it's possible we have an OS string from strerror() that is
5385            not UTF-8 encoded */
5386         gsize bytes;
5387 
5388         trmsg = g_locale_to_utf8(msg, -1, NULL, &bytes, NULL);
5389     }
5390 
5391     if (parent == NULL) {
5392 	parent = get_focus_window();
5393 	if (parent == NULL && mdata != NULL) {
5394 	    parent = mdata->main;
5395 	}
5396 #if 0
5397 	fprintf(stderr, "Revised msgbox parent = %p\n", (void *) parent);
5398 #endif
5399     }
5400     pwin = parent != NULL ? GTK_WINDOW(parent) : NULL;
5401 
5402     dialog = gtk_message_dialog_new(pwin,
5403                                     0,    /* or GTK_DIALOG_DESTROY_WITH_PARENT? */
5404                                     msgtype,
5405                                     GTK_BUTTONS_CLOSE,
5406                                     "%s",
5407                                     (trmsg != NULL)? trmsg : msg);
5408 
5409     title = (msgtype == GTK_MESSAGE_ERROR)? titles[0] :
5410         (msgtype == GTK_MESSAGE_WARNING)? titles[1] : titles[2];
5411 
5412     gtk_window_set_title(GTK_WINDOW(dialog), _(title));
5413     gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
5414 
5415     gtk_dialog_run(GTK_DIALOG(dialog));
5416 
5417     gtk_widget_destroy(dialog);
5418 
5419     if (trmsg != NULL) {
5420         g_free(trmsg);
5421     }
5422 }
5423 
errbox(const char * err)5424 void errbox (const char *err)
5425 {
5426     char msg[MAXLEN];
5427 
5428     *msg = '\0';
5429 
5430     if (strlen(err) >= MAXLEN) {
5431         strncat(msg, err, MAXLEN - 4);
5432         strcat(msg, "...");
5433     } else {
5434         strcpy(msg, err);
5435     }
5436 
5437     msgbox(msg, GTK_MESSAGE_ERROR, NULL);
5438 }
5439 
errbox_printf(const char * template,...)5440 void errbox_printf (const char *template, ...)
5441 {
5442     char msg[MAXLEN];
5443     va_list args;
5444 
5445     if (template == NULL) {
5446         msgbox("Error", 1, NULL);
5447         return;
5448     }
5449 
5450     va_start(args, template);
5451     vsnprintf(msg, MAXLEN, template, args);
5452     va_end(args);
5453 
5454     msgbox(msg, GTK_MESSAGE_ERROR, NULL);
5455 }
5456 
infobox(const char * info)5457 void infobox (const char *info)
5458 {
5459     char msg[MAXLEN];
5460 
5461     *msg = '\0';
5462 
5463     if (strlen(info) >= MAXLEN) {
5464         strncat(msg, info, MAXLEN - 4);
5465         strcat(msg, "...");
5466     } else {
5467         strcpy(msg, info);
5468     }
5469 
5470     msgbox(msg, GTK_MESSAGE_INFO, NULL);
5471 }
5472 
infobox_printf(const char * template,...)5473 void infobox_printf (const char *template, ...)
5474 {
5475     char msg[MAXLEN];
5476     va_list args;
5477 
5478     va_start(args, template);
5479     vsnprintf(msg, MAXLEN, template, args);
5480     va_end(args);
5481 
5482     msgbox(msg, GTK_MESSAGE_INFO, NULL);
5483 }
5484 
warnbox(const char * warn)5485 void warnbox (const char *warn)
5486 {
5487     char msg[MAXLEN];
5488 
5489     *msg = '\0';
5490 
5491     if (strlen(warn) >= MAXLEN) {
5492         strncat(msg, warn, MAXLEN - 4);
5493         strcat(msg, "...");
5494     } else {
5495         strcpy(msg, warn);
5496     }
5497 
5498     msgbox(msg, GTK_MESSAGE_WARNING, NULL);
5499 }
5500 
warnbox_printf(const char * template,...)5501 void warnbox_printf (const char *template, ...)
5502 {
5503     char msg[MAXLEN];
5504     va_list args;
5505 
5506     va_start(args, template);
5507     vsnprintf(msg, MAXLEN, template, args);
5508     va_end(args);
5509 
5510     msgbox(msg, GTK_MESSAGE_WARNING, NULL);
5511 }
5512 
maybe_warn(void)5513 void maybe_warn (void)
5514 {
5515     if (check_gretl_warning()) {
5516         msgbox(gretl_warnmsg_get(), GTK_MESSAGE_WARNING, NULL);
5517     }
5518 }
5519 
file_read_errbox(const char * fname)5520 void file_read_errbox (const char *fname)
5521 {
5522     const char *msg = gretl_errmsg_get();
5523 
5524     if (*msg != '\0') {
5525         errbox(msg);
5526     } else {
5527         errbox_printf(_("Couldn't open %s"), fname);
5528     }
5529 }
5530 
file_write_errbox(const char * fname)5531 void file_write_errbox (const char *fname)
5532 {
5533     const char *msg = gretl_errmsg_get();
5534 
5535     if (*msg != '\0') {
5536         errbox(msg);
5537     } else {
5538         errbox_printf(_("Couldn't write to %s"), fname);
5539     }
5540 }
5541 
5542 static void
name_entry_finalize(GtkWidget * w,GtkWidget * dlg)5543 name_entry_finalize (GtkWidget *w, GtkWidget *dlg)
5544 {
5545     GtkWidget *entry = g_object_get_data(G_OBJECT(dlg), "entry");
5546     char *name = g_object_get_data(G_OBJECT(dlg), "name");
5547     GretlType type = widget_get_int(dlg, "type");
5548     const gchar *txt = gtk_entry_get_text(GTK_ENTRY(entry));
5549 
5550     if (gui_validate_varname(txt, type, dlg) == 0) {
5551         strcpy(name, txt);
5552         gtk_widget_destroy(dlg);
5553     }
5554 }
5555 
activate_show(GtkToggleButton * b,int * show)5556 static void activate_show (GtkToggleButton *b, int *show)
5557 {
5558     *show = button_is_active(b);
5559 }
5560 
5561 /* don't do this for types lacking a GUI representation */
5562 #define do_show_check(t) (t != GRETL_TYPE_STRING && t != GRETL_TYPE_ARRAY)
5563 
object_name_entry_dialog(char * name,GretlType type,const char * labeltxt,int * show,GtkWidget * parent)5564 int object_name_entry_dialog (char *name, GretlType type,
5565                               const char *labeltxt, int *show,
5566                               GtkWidget *parent)
5567 {
5568     GtkWidget *dlg, *tmp, *vbox, *hbox;
5569     GtkWidget *entry;
5570     int ret = GRETL_CANCEL;
5571 
5572     dlg = gretl_dialog_new(_("gretl: name variable"), parent,
5573                            GRETL_DLG_BLOCK);
5574 
5575     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
5576 
5577     if (labeltxt != NULL) {
5578         hbox = gtk_hbox_new(FALSE, 5);
5579         tmp = gtk_label_new(_(labeltxt));
5580         gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_CENTER);
5581         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, FALSE, 0);
5582         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
5583     }
5584 
5585     hbox = gtk_hbox_new(FALSE, 5);
5586     entry = gtk_entry_new();
5587     gtk_entry_set_width_chars(GTK_ENTRY(entry), VNAMELEN - 1);
5588     gtk_entry_set_max_length(GTK_ENTRY(entry), VNAMELEN - 1);
5589     gtk_entry_set_text(GTK_ENTRY(entry), name);
5590     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
5591     gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
5592     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
5593     gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 5);
5594     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
5595 
5596     if (show != NULL && do_show_check(type)) {
5597         const char *label = (type == GRETL_TYPE_DOUBLE)?
5598             N_("show scalars window") :
5599             N_("show icons window");
5600 
5601         hbox = gtk_hbox_new(FALSE, 5);
5602         tmp = gtk_check_button_new_with_label(_(label));
5603         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5604         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
5605         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), *show);
5606         g_signal_connect(G_OBJECT(tmp), "toggled",
5607                          G_CALLBACK(activate_show), show);
5608     }
5609 
5610     /* links */
5611     g_object_set_data(G_OBJECT(dlg), "entry", entry);
5612     g_object_set_data(G_OBJECT(dlg), "name", name);
5613     g_object_set_data(G_OBJECT(dlg), "type", GINT_TO_POINTER(type));
5614 
5615     /* buttons */
5616     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
5617     tmp = cancel_delete_button(hbox, dlg);
5618     tmp = ok_validate_button(hbox, &ret, NULL);
5619     g_signal_connect(G_OBJECT(tmp), "clicked",
5620                      G_CALLBACK(name_entry_finalize), dlg);
5621     gtk_widget_grab_default(tmp);
5622 
5623     gretl_dialog_keep_above(dlg);
5624     gtk_widget_show_all(dlg);
5625 
5626     return ret;
5627 }
5628 
5629 /* apparatus for setting custom format for TeX tabular model output */
5630 
5631 struct rbin {
5632     GtkWidget *b[2];
5633 };
5634 
5635 struct tex_formatter {
5636     GtkWidget *custom;
5637     GtkWidget *show[3];
5638     GtkAdjustment *adj[4];
5639     GtkWidget *spin[4];
5640     struct rbin radio[4];
5641 };
5642 
activate_row(GtkWidget * w,struct tex_formatter * tf)5643 static void activate_row (GtkWidget *w, struct tex_formatter *tf)
5644 {
5645     int i = widget_get_int(w, "row");
5646     int s = button_is_active(w);
5647 
5648     if (tf->spin[i] != NULL) {
5649         gtk_widget_set_sensitive(tf->spin[i], s);
5650         gtk_widget_set_sensitive(tf->radio[i].b[0], s);
5651         gtk_widget_set_sensitive(tf->radio[i].b[1], s);
5652     }
5653 }
5654 
toggle_tex_custom(GtkWidget * w,struct tex_formatter * tf)5655 static void toggle_tex_custom (GtkWidget *w, struct tex_formatter *tf)
5656 {
5657     int s = button_is_active(w);
5658     int i;
5659 
5660     if (tf->spin[0] != NULL) {
5661         for (i=0; i<4; i++) {
5662             if (i < 3) {
5663                 gtk_widget_set_sensitive(tf->show[i], s);
5664             }
5665             gtk_widget_set_sensitive(tf->spin[i], s);
5666             gtk_widget_set_sensitive(tf->radio[i].b[0], s);
5667             gtk_widget_set_sensitive(tf->radio[i].b[1], s);
5668         }
5669     }
5670 }
5671 
record_tex_format(GtkWidget * w,struct tex_formatter * tf)5672 static gboolean record_tex_format (GtkWidget *w, struct tex_formatter *tf)
5673 {
5674     if (button_is_active(tf->custom)) {
5675         char c, bit[8], fmt[32];
5676         int i, p;
5677 
5678         *fmt = '\0';
5679 
5680         for (i=0; i<4; i++) {
5681             if (i == 0 || button_is_active(tf->show[i-1])) {
5682                 p = (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(tf->spin[i]));
5683                 if (button_is_active(tf->radio[i].b[1])) {
5684                     c = 'g';
5685                 } else {
5686                     c = 'f';
5687                 }
5688                 sprintf(bit, "%%.%d%c", p, c);
5689                 strcat(fmt, bit);
5690             }
5691             if (i < 3) {
5692                 strcat(fmt, "|");
5693             }
5694         }
5695         set_tex_param_format(fmt);
5696     } else {
5697         /* chose standard (default) format */
5698         set_tex_param_format(NULL);
5699     }
5700 
5701     return FALSE;
5702 }
5703 
get_tex_prec(const char * s)5704 static int get_tex_prec (const char *s)
5705 {
5706     int p = 4;
5707 
5708     if (s != NULL) {
5709         s = strchr(s, '.');
5710         if (s != NULL) {
5711             p = atoi(s + 1);
5712         }
5713     }
5714 
5715     return p;
5716 }
5717 
get_tex_conv(const char * s)5718 static char get_tex_conv (const char *s)
5719 {
5720     char c = 'f';
5721     int n = strlen(s);
5722 
5723     if (n > 1) {
5724         c = s[n - 1];
5725     }
5726 
5727     return c;
5728 }
5729 
5730 /* callback from model-window menu */
5731 
tex_format_dialog(GtkAction * action,gpointer data)5732 void tex_format_dialog (GtkAction *action, gpointer data)
5733 {
5734     windata_t *vwin = (windata_t *) data;
5735     const char *labels[] = {
5736         N_("Coefficient"),
5737         N_("Standard error"),
5738         N_("t-ratio"),
5739         N_("p-value")
5740     };
5741     struct tex_formatter tf;
5742     GtkWidget *dlg, *tbl;
5743     GtkWidget *tmp, *hbox;
5744     GtkWidget *vbox, *dvbox;
5745     GSList *group;
5746     int i, nset = 0;
5747 
5748     for (i=0; i<4; i++) {
5749         const char *fmt = tex_column_format(i);
5750 
5751         tf.spin[i] = NULL;
5752         if (*fmt) nset++;
5753     }
5754 
5755     dlg = gretl_dialog_new(_("gretl: TeX tabular format"),
5756                            vwin_toplevel(vwin),
5757                            GRETL_DLG_BLOCK);
5758 
5759     dvbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
5760 
5761     hbox = gtk_hbox_new(FALSE, 5);
5762     vbox = gtk_vbox_new(FALSE, 0);
5763     tmp = gtk_radio_button_new_with_label(NULL, _("Standard format"));
5764     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 5);
5765     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tmp));
5766     tmp = tf.custom = gtk_radio_button_new_with_label(group, _("Custom format"));
5767     g_signal_connect(G_OBJECT(tmp), "clicked",
5768                      G_CALLBACK(toggle_tex_custom), &tf);
5769 
5770     gtk_box_pack_start(GTK_BOX(vbox), tmp, TRUE, TRUE, 0);
5771     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
5772     gtk_box_pack_start(GTK_BOX(dvbox), hbox, TRUE, TRUE, 0);
5773     gtk_widget_show_all(hbox);
5774 
5775     vbox_add_hsep(dvbox);
5776 
5777     tbl = gtk_table_new(11, 2, FALSE);
5778     gtk_table_set_row_spacings(GTK_TABLE(tbl), 5);
5779     gtk_table_set_col_spacings(GTK_TABLE(tbl), 5);
5780 
5781     for (i=0; i<4; i++) {
5782         const char *curr = tex_column_format(i);
5783         int p = get_tex_prec(curr);
5784         char c = get_tex_conv(curr);
5785         int shown = (i == 0 || curr[0] != 0 || nset == 0);
5786         int j = i * 3;
5787 
5788         hbox = gtk_hbox_new(FALSE, 5);
5789         tmp = gtk_label_new(_(labels[i]));
5790         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5791         gtk_table_attach_defaults(GTK_TABLE(tbl), hbox, 0, 2, j, j+1);
5792 
5793         /* "show" check button */
5794         if (i > 0) {
5795             tmp = tf.show[i-1] = gtk_check_button_new();
5796             gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, j+1, j+2);
5797             g_object_set_data(G_OBJECT(tmp), "row", GINT_TO_POINTER(i));
5798             g_signal_connect(G_OBJECT(tmp), "clicked",
5799                              G_CALLBACK(activate_row), &tf);
5800             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), shown);
5801         }
5802 
5803         /* spinner for precision */
5804         hbox = gtk_hbox_new(FALSE, 5);
5805         tmp = gtk_label_new(_("Show"));
5806         tf.adj[i] = (GtkAdjustment *) gtk_adjustment_new(p, 0, 15, 1, 1, 0);
5807         tf.spin[i] = gtk_spin_button_new(tf.adj[i], 1, 0);
5808         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
5809         gtk_box_pack_start(GTK_BOX(hbox), tf.spin[i], FALSE, FALSE, 5);
5810 
5811         /* decimal places versus significant figures */
5812         vbox = gtk_vbox_new(FALSE, 0);
5813         tf.radio[i].b[0] = gtk_radio_button_new_with_label(NULL, _("decimal places"));
5814         gtk_box_pack_start(GTK_BOX(vbox), tf.radio[i].b[0], TRUE, TRUE, 5);
5815         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tf.radio[i].b[0]));
5816         tf.radio[i].b[1] = gtk_radio_button_new_with_label(group, _("significant figures"));
5817         gtk_box_pack_start(GTK_BOX(vbox), tf.radio[i].b[1], TRUE, TRUE, 0);
5818         gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
5819 
5820         if (c == 'g') {
5821             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tf.radio[i].b[1]), TRUE);
5822         }
5823 
5824         gtk_table_attach_defaults(GTK_TABLE(tbl), hbox, 1, 2, j+1, j+2);
5825 
5826         gtk_widget_set_sensitive(tf.spin[i], shown);
5827         gtk_widget_set_sensitive(tf.radio[i].b[0], shown);
5828         gtk_widget_set_sensitive(tf.radio[i].b[1], shown);
5829 
5830         if (i < 3) {
5831             tmp = gtk_hseparator_new();
5832             gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, j+2, j+3);
5833         }
5834     }
5835 
5836     gtk_box_pack_start(GTK_BOX(dvbox), tbl, TRUE, TRUE, 0);
5837     gtk_widget_show_all(tbl);
5838 
5839     if (tex_using_custom_tabular()) {
5840         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tf.custom), TRUE);
5841     } else {
5842         toggle_tex_custom(tf.custom, &tf);
5843     }
5844 
5845     /* buttons */
5846     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
5847     cancel_delete_button(hbox, dlg);
5848     tmp = ok_button(hbox);
5849     g_signal_connect(G_OBJECT(tmp), "clicked",
5850                      G_CALLBACK(record_tex_format), &tf);
5851     g_signal_connect(G_OBJECT(tmp), "clicked",
5852                      G_CALLBACK(delete_widget), dlg);
5853     gtk_widget_grab_default(tmp);
5854 
5855     gtk_widget_show_all(hbox);
5856 
5857     gretl_dialog_keep_above(dlg);
5858     gtk_widget_show(dlg);
5859 }
5860 
5861 struct hc_opts {
5862     GtkWidget *dialog;
5863     GtkWidget *cbutton;
5864     GtkWidget *entry;
5865     char *targ;
5866     int retval;
5867 };
5868 
hc_ok_callback(GtkWidget * w,struct hc_opts * h)5869 static void hc_ok_callback (GtkWidget *w, struct hc_opts *h)
5870 {
5871     if (button_is_active(h->cbutton)) {
5872         const gchar *s = gtk_entry_get_text(GTK_ENTRY(h->entry));
5873         int v = current_series_index(dataset, s);
5874 
5875         if (v < 1) {
5876             h->retval = GRETL_CANCEL;
5877             if (*s == '\0') {
5878                 warnbox(_("Please specify a cluster variable"));
5879             } else {
5880                 errbox_printf(_("'%s' is not a known series"), s);
5881             }
5882             return;
5883         }
5884         *h->targ = '\0';
5885         strncat(h->targ, s, VNAMELEN - 1);
5886         h->retval = 1;
5887     } else {
5888         h->retval = 0;
5889     }
5890 
5891     gtk_widget_destroy(h->dialog);
5892 }
5893 
hc_config_dialog(char * vname,gretlopt opt,gboolean robust_conf,GtkWidget * parent)5894 int hc_config_dialog (char *vname, gretlopt opt, gboolean robust_conf,
5895                       GtkWidget *parent)
5896 {
5897     struct hc_opts opts;
5898     GtkWidget *dialog;
5899     GtkWidget *vbox, *hbox;
5900     GtkWidget *b1, *b2, *entry;
5901     GSList *group = NULL;
5902 
5903     if (maybe_raise_dialog()) {
5904         return GRETL_CANCEL;
5905     }
5906 
5907     opts.retval = GRETL_CANCEL;
5908     opts.targ = vname;
5909 
5910     opts.dialog = dialog = gretl_dialog_new(NULL, parent, GRETL_DLG_BLOCK);
5911     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
5912 
5913     hbox = gtk_hbox_new(FALSE, 5);
5914     if (robust_conf) {
5915         /* regular HCCME option */
5916         b1 = gtk_radio_button_new_with_label(NULL,
5917                                              _("Select from Regular HCCME options"));
5918     } else {
5919         b1 = gtk_radio_button_new_with_label(NULL, "QML");
5920     }
5921     gtk_box_pack_start(GTK_BOX(hbox), b1, FALSE, FALSE, 5);
5922     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
5923 
5924 
5925     /* cluster-robust option */
5926     hbox = gtk_hbox_new(FALSE, 5);
5927     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1));
5928     opts.cbutton = b2 = gtk_radio_button_new_with_label(group, _("Cluster by"));
5929     gtk_box_pack_start(GTK_BOX(hbox), b2, FALSE, FALSE, 5);
5930     opts.entry = entry = gtk_entry_new();
5931     gtk_entry_set_max_length(GTK_ENTRY(entry), VNAMELEN);
5932     gtk_entry_set_width_chars(GTK_ENTRY(entry), VNAMELEN + 2);
5933     gtk_entry_set_text(GTK_ENTRY(entry), vname);
5934     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
5935     sensitize_conditional_on(entry, b2);
5936     gtk_container_add(GTK_CONTAINER(hbox), entry);
5937     gtk_container_add(GTK_CONTAINER(vbox), hbox);
5938 
5939     if ((opt & OPT_C) && *vname != '\0') {
5940         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2), TRUE);
5941     } else {
5942         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1), TRUE);
5943         gtk_widget_set_sensitive(entry, FALSE);
5944     }
5945 
5946     /* buttons */
5947     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
5948     cancel_delete_button(hbox, dialog);
5949     b1 = ok_button(hbox);
5950     g_signal_connect(G_OBJECT(b1), "clicked",
5951                      G_CALLBACK(hc_ok_callback), &opts);
5952     gtk_widget_grab_default(b1);
5953     context_help_button(hbox, CLUSTER);
5954 
5955     gtk_widget_show_all(dialog);
5956 
5957     return opts.retval;
5958 }
5959 
5960 #ifndef G_OS_WIN32
5961 
dont_delete(void)5962 static gint dont_delete (void)
5963 {
5964     return TRUE;
5965 }
5966 
5967 #endif
5968 
real_output_policy_dlg(const char ** opts,int deflt,int toolbar,GtkWidget * parent)5969 static int real_output_policy_dlg (const char **opts,
5970                                    int deflt,
5971                                    int toolbar,
5972                                    GtkWidget *parent)
5973 {
5974     GtkWidget *dialog;
5975     GtkWidget *vbox, *hbox, *tmp;
5976     GtkWidget *button = NULL;
5977     GSList *group = NULL;
5978     int radio_val = deflt;
5979     int hcode = 0;
5980     int i, ret = GRETL_CANCEL;
5981 
5982     if (maybe_raise_dialog()) {
5983         return ret;
5984     }
5985 
5986     dialog = gretl_dialog_new(NULL, parent, GRETL_DLG_BLOCK);
5987 #ifdef G_OS_WIN32
5988     gtk_window_set_deletable(GTK_WINDOW(dialog), FALSE);
5989 #else
5990     /* the function above may well not work */
5991     g_signal_connect(G_OBJECT(dialog), "delete-event",
5992                      G_CALLBACK(dont_delete), NULL);
5993 #endif
5994 
5995     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
5996 
5997     hbox = gtk_hbox_new(FALSE, 5);
5998     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
5999     if (toolbar) {
6000         tmp = gtk_label_new(_("New script output:"));
6001     } else {
6002         tmp = gtk_label_new(_("New script output should:"));
6003     }
6004     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6005 
6006     for (i=0; i<3; i++) {
6007         button = gtk_radio_button_new_with_label(group, _(opts[i]));
6008         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
6009         g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(i));
6010         g_signal_connect(G_OBJECT(button), "clicked",
6011                          G_CALLBACK(set_radio_opt), &radio_val);
6012         if (i == deflt) {
6013             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
6014         }
6015         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
6016     }
6017 
6018     if (!toolbar) {
6019         hbox = gtk_hbox_new(FALSE, 5);
6020         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6021         tmp = gtk_image_new_from_stock(GRETL_STOCK_PIN,
6022                                        GTK_ICON_SIZE_MENU);
6023         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6024         tmp = gtk_label_new("Note that you can change this policy via the\n"
6025                             "\"Stickiness\" button in the script output window.");
6026         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6027     }
6028 
6029     /* buttons */
6030     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6031     tmp = ok_validate_button(hbox, &ret, &radio_val);
6032     g_signal_connect(G_OBJECT(tmp), "clicked",
6033                      G_CALLBACK(delete_widget), dialog);
6034     gtk_widget_grab_default(tmp);
6035     if (hcode) {
6036         context_help_button(hbox, hcode);
6037     } else {
6038         gretl_dialog_keep_above(dialog);
6039     }
6040 
6041     gtk_widget_show_all(dialog);
6042 
6043     return ret;
6044 }
6045 
output_policy_dialog(windata_t * source,windata_t * target,int toolbar)6046 int output_policy_dialog (windata_t *source,
6047                           windata_t *target,
6048                           int toolbar)
6049 {
6050     int orig = get_script_output_policy();
6051     int resp, deflt, policy;
6052 
6053     /* convert to zero-based? */
6054     deflt = (orig == OUTPUT_POLICY_UNSET)? orig : orig - 1;
6055 
6056     if (!toolbar) {
6057         /* not called via output window toolbar */
6058         const char *opts[] = {
6059             N_("Replace previous output"),
6060             N_("Add to previous output"),
6061             N_("Go to a new window")
6062         };
6063 
6064         resp = real_output_policy_dlg(opts, deflt, toolbar,
6065                                       vwin_toplevel(source));
6066     } else {
6067         const char *opts[] = {
6068             N_("Replaces output in this window"),
6069             N_("Adds to output in this window"),
6070             N_("Always goes to a new window")
6071         };
6072 
6073         resp = real_output_policy_dlg(opts, deflt, toolbar,
6074                                       vwin_toplevel(source));
6075     }
6076 
6077     /* convert policy back to 1-based */
6078     policy = (resp == GRETL_CANCEL)? (deflt + 1) : resp + 1;
6079 
6080     set_script_output_policy(policy, target);
6081 
6082     return policy;
6083 }
6084 
auto_pc_name(const char * vname,int idxvals)6085 static gchar *auto_pc_name (const char *vname, int idxvals)
6086 {
6087     char pcname[VNAMELEN];
6088 
6089     pcname[0] = '\0';
6090 
6091     if (idxvals) {
6092         strcat(pcname, "i_");
6093         strncat(pcname, vname, VNAMELEN - 4);
6094     } else {
6095         strcat(pcname, "pc_");
6096         strncat(pcname, vname, VNAMELEN - 5);
6097     }
6098 
6099     return g_strdup(pcname);
6100 }
6101 
6102 struct pc_change_info {
6103     GtkWidget *dialog;
6104     GtkWidget *entry;
6105     GtkWidget *logcheck;
6106     const int *varlist;
6107     int *ctrl;
6108 };
6109 
6110 struct index_vals_info {
6111     GtkWidget *dialog;
6112     GtkWidget *entry;
6113     GtkWidget *spin;
6114     const int *varlist;
6115 };
6116 
pc_change_get_vname(GtkWidget * dialog,GtkWidget * entry)6117 static gchar *pc_change_get_vname (GtkWidget *dialog,
6118                                    GtkWidget *entry)
6119 {
6120     gchar *newname = entry_box_get_trimmed_text(entry);
6121 
6122     if (newname == NULL || *newname == '\0') {
6123         gtk_widget_grab_focus(entry);
6124         g_free(newname);
6125         return NULL;
6126     } else {
6127         int err = gui_validate_varname(newname,
6128                                        GRETL_TYPE_SERIES,
6129                                        dialog);
6130         if (err) {
6131             gtk_widget_grab_focus(entry);
6132             g_free(newname);
6133             return NULL;
6134         }
6135     }
6136 
6137     return newname;
6138 }
6139 
do_pc_change(GtkWidget * w,struct pc_change_info * pci)6140 static void do_pc_change (GtkWidget *w, struct pc_change_info *pci)
6141 {
6142     gchar *lhname = NULL;
6143     int autoname = 0;
6144     int err = 0;
6145 
6146     if (pci->entry != NULL) {
6147         lhname = pc_change_get_vname(pci->dialog, pci->entry);
6148         if (lhname == NULL) {
6149             return;
6150         }
6151     } else {
6152         autoname = 1;
6153     }
6154 
6155     if (!err) {
6156         int use_logs = 0;
6157         int i, ctrl = 0;
6158 
6159         if (pci->ctrl != NULL) {
6160             ctrl = *pci->ctrl;
6161         }
6162 
6163         if (pci->logcheck != NULL &&
6164             gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pci->logcheck))) {
6165             use_logs = 1;
6166         }
6167 
6168         for (i=1; i<=pci->varlist[0] && !err; i++) {
6169             const char *vname = dataset->varname[pci->varlist[i]];
6170 	    gchar *genline = NULL;
6171 
6172             if (autoname) {
6173                 lhname = auto_pc_name(vname, 0);
6174             }
6175             if (ctrl == 0) {
6176                 /* period to period rate */
6177                 if (use_logs) {
6178                     genline = g_strdup_printf("series %s=100*log(%s/%s(-1))",
6179                                               lhname, vname, vname);
6180                 } else {
6181                     genline = g_strdup_printf("series %s=100*(%s/%s(-1)-1)",
6182                                               lhname, vname, vname);
6183                 }
6184             } else if (ctrl == 1) {
6185                 /* annualized */
6186                 if (use_logs) {
6187                     int mult = dataset->pd * 100;
6188                     genline = g_strdup_printf("series %s=%d*log(%s/%s(-1))",
6189                                               lhname, mult, vname, vname);
6190                 } else {
6191                     genline = g_strdup_printf("series %s=100*((%s/%s(-1))^%d-1)",
6192                                               lhname, vname, vname, dataset->pd);
6193                 }
6194             } else {
6195                 /* year on year */
6196                 if (use_logs) {
6197                     genline = g_strdup_printf("series %s=100*log(%s/%s(-%d))",
6198                                               lhname, vname, vname, dataset->pd);
6199                 } else {
6200                     genline = g_strdup_printf("series %s=100*(%s/%s(-%d)-1)",
6201                                               lhname, vname, vname, dataset->pd);
6202                 }
6203             }
6204 
6205             err = gui_run_genr(genline, dataset, OPT_NONE, NULL);
6206 
6207             if (err) {
6208                 gui_errmsg(err);
6209             } else {
6210                 add_command_to_stack(genline, 0);
6211                 refresh_data();
6212             }
6213 
6214             g_free(genline);
6215 	    if (autoname) {
6216 		g_free(lhname);
6217 		lhname = NULL;
6218 	    }
6219         }
6220     }
6221 
6222     if (!autoname) {
6223 	g_free(lhname);
6224     }
6225 
6226     if (!err) {
6227         gtk_widget_destroy(pci->dialog);
6228     }
6229 }
6230 
index_values_callback(GtkWidget * w,struct index_vals_info * ixi)6231 static void index_values_callback (GtkWidget *w,
6232                                    struct index_vals_info *ixi)
6233 {
6234     gchar *lhname = NULL;
6235     int autoname = 0;
6236     int err = 0;
6237 
6238     if (ixi->entry != NULL) {
6239         lhname = pc_change_get_vname(ixi->dialog, ixi->entry);
6240         if (lhname == NULL) {
6241             return;
6242         }
6243     } else {
6244         autoname = 1;
6245     }
6246 
6247     if (!err) {
6248         char obsstr[OBSLEN];
6249         int i, t1;
6250 
6251         t1 = spinner_get_int(ixi->spin);
6252         ntolabel(obsstr, t1, dataset);
6253 
6254         for (i=1; i<=ixi->varlist[0] && !err; i++) {
6255             const char *vname = dataset->varname[ixi->varlist[i]];
6256 	    gchar *genline = NULL;
6257 
6258             if (autoname) {
6259                 lhname = auto_pc_name(vname, 1);
6260             }
6261             genline = g_strdup_printf("series %s=100*%s/%s[%s]",
6262                                       lhname, vname, vname, obsstr);
6263             err = gui_run_genr(genline, dataset, OPT_NONE, NULL);
6264             if (err) {
6265                 gui_errmsg(err);
6266             } else {
6267                 add_command_to_stack(genline, 0);
6268                 refresh_data();
6269             }
6270             g_free(genline);
6271 	    if (autoname) {
6272 		g_free(lhname);
6273 		lhname = NULL;
6274 	    }
6275         }
6276     }
6277 
6278     if (!autoname) {
6279 	g_free(lhname);
6280     }
6281 
6282     if (!err) {
6283         gtk_widget_destroy(ixi->dialog);
6284     }
6285 }
6286 
percent_change_dialog(const int * list)6287 static void percent_change_dialog (const int *list)
6288 {
6289     struct pc_change_info pci;
6290     GtkWidget *dialog;
6291     GtkWidget *vbox, *hbox, *tmp;
6292     GtkWidget *button = NULL;
6293     gchar *msg;
6294     int radioval = 1;
6295 
6296     if (maybe_raise_dialog()) {
6297         return;
6298     }
6299 
6300     dialog = gretl_dialog_new(NULL, NULL, GRETL_DLG_BLOCK);
6301     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
6302 
6303     pci.dialog = dialog;
6304     pci.varlist = list;
6305     pci.ctrl = NULL;
6306 
6307     hbox = gtk_hbox_new(FALSE, 5);
6308     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6309     if (list[0] == 1) {
6310         msg = g_strdup_printf(_("percent change in %s"),
6311                               dataset->varname[list[1]]);
6312     } else {
6313         msg = g_strdup_printf(_("percent changes"));
6314     }
6315     tmp = gtk_label_new(msg);
6316     g_free(msg);
6317     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6318 
6319     if (pci.varlist[0] == 1) {
6320         hbox = gtk_hbox_new(FALSE, 5);
6321         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6322         msg = g_strdup_printf(_("Enter name for new variable\n"
6323                                 "(max. %d characters)"),
6324                               VNAMELEN - 1);
6325         tmp = gtk_label_new(msg);
6326         g_free(msg);
6327         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6328 
6329         hbox = gtk_hbox_new(FALSE, 5);
6330         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6331         pci.entry = tmp = gtk_entry_new();
6332         gtk_entry_set_max_length(GTK_ENTRY(tmp), 32);
6333         gtk_entry_set_width_chars(GTK_ENTRY(tmp), 32);
6334         gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
6335         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6336     } else {
6337         pci.entry = NULL;
6338     }
6339 
6340     if (quarterly_or_monthly(dataset)) {
6341         const char *q_opts[] = {
6342             N_("Quarterly"),
6343             N_("Quarterly, annualized"),
6344             N_("Year on year")
6345         };
6346         const char *m_opts[] = {
6347             N_("Monthly"),
6348             N_("Monthly, annualized"),
6349             N_("Year on year")
6350         };
6351         const char **opts;
6352         GSList *group = NULL;
6353         int i;
6354 
6355         opts = dataset->pd == 4 ? q_opts : m_opts;
6356 
6357         for (i=0; i<3; i++) {
6358             button = gtk_radio_button_new_with_label(group, _(opts[i]));
6359             gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
6360             g_object_set_data(G_OBJECT(button), "action", GINT_TO_POINTER(i));
6361             g_signal_connect(G_OBJECT(button), "clicked",
6362                              G_CALLBACK(set_radio_opt), &radioval);
6363             if (i == 1) {
6364                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (button), TRUE);
6365             }
6366             group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
6367         }
6368         pci.ctrl = &radioval;
6369     }
6370 
6371     /* add option of calculating via logs */
6372     hbox = gtk_hbox_new(FALSE, 5);
6373     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6374     pci.logcheck = gtk_check_button_new_with_label(_("Calculate using logs"));
6375     gtk_box_pack_start(GTK_BOX(hbox), pci.logcheck, TRUE, TRUE, 5);
6376 
6377     /* buttons */
6378     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6379     cancel_delete_button(hbox, dialog);
6380     tmp = ok_button(hbox);
6381     g_signal_connect(G_OBJECT(tmp), "clicked",
6382                      G_CALLBACK(do_pc_change), &pci);
6383     gtk_widget_grab_default(tmp);
6384 
6385     gretl_dialog_keep_above(dialog);
6386     gtk_widget_show_all(dialog);
6387 }
6388 
index_values_dialog(const int * list)6389 static void index_values_dialog (const int *list)
6390 {
6391     struct index_vals_info ixi;
6392     GtkAdjustment *adj;
6393     GtkWidget *dialog;
6394     GtkWidget *vbox, *hbox, *tmp;
6395     gchar *msg;
6396 
6397     if (maybe_raise_dialog()) {
6398         return;
6399     }
6400 
6401     dialog = gretl_dialog_new(NULL, NULL, GRETL_DLG_BLOCK);
6402     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
6403 
6404     ixi.dialog = dialog;
6405     ixi.varlist = list;
6406     ixi.spin = NULL;
6407 
6408     hbox = gtk_hbox_new(FALSE, 5);
6409     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6410     if (list[0] == 1) {
6411         msg = g_strdup_printf(_("100-based index of %s"),
6412                               dataset->varname[list[1]]);
6413     } else {
6414         msg = g_strdup_printf(_("100-based indices"));
6415     }
6416     tmp = gtk_label_new(msg);
6417     g_free(msg);
6418     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6419 
6420     if (ixi.varlist[0] == 1) {
6421         hbox = gtk_hbox_new(FALSE, 5);
6422         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6423         msg = g_strdup_printf(_("Enter name for new variable\n"
6424                                 "(max. %d characters)"),
6425                               VNAMELEN - 1);
6426         tmp = gtk_label_new(msg);
6427         g_free(msg);
6428         gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6429 
6430         hbox = gtk_hbox_new(FALSE, 5);
6431         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6432         ixi.entry = tmp = gtk_entry_new();
6433         gtk_entry_set_max_length(GTK_ENTRY(tmp), 32);
6434         gtk_entry_set_width_chars(GTK_ENTRY(tmp), 32);
6435         gtk_entry_set_activates_default(GTK_ENTRY(tmp), TRUE);
6436         gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6437     } else {
6438         ixi.entry = NULL;
6439     }
6440 
6441     /* selection of base period for index via spin button */
6442     hbox = gtk_hbox_new(FALSE, 5);
6443     adj = (GtkAdjustment *) gtk_adjustment_new(dataset->t1, 0,
6444                                                dataset->n - 1,
6445                                                1, 1, 0);
6446     ixi.spin = obs_button_new(adj, dataset, OBS_BUTTON_T1);
6447     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(_("Base period:")),
6448                        FALSE, FALSE, 5);
6449     gtk_box_pack_start(GTK_BOX(hbox), ixi.spin, FALSE, FALSE, 0);
6450     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6451 
6452     /* buttons */
6453     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6454     cancel_delete_button(hbox, dialog);
6455     tmp = ok_button(hbox);
6456     g_signal_connect(G_OBJECT(tmp), "clicked",
6457                      G_CALLBACK(index_values_callback), &ixi);
6458     gtk_widget_grab_default(tmp);
6459 
6460     gretl_dialog_keep_above(dialog);
6461     gtk_widget_show_all(dialog);
6462 }
6463 
single_percent_change_dialog(int v,int idxvals)6464 void single_percent_change_dialog (int v, int idxvals)
6465 {
6466     int list[2] = {1, v};
6467 
6468     if (idxvals) {
6469         index_values_dialog(list);
6470     } else {
6471         percent_change_dialog(list);
6472     }
6473 }
6474 
multi_percent_change_dialog(int idxvals)6475 void multi_percent_change_dialog (int idxvals)
6476 {
6477     int *list = main_window_selection_as_list();
6478 
6479     if (list != NULL) {
6480         if (idxvals) {
6481             index_values_dialog(list);
6482         } else {
6483             percent_change_dialog(list);
6484         }
6485         free(list);
6486     }
6487 }
6488 
6489 struct midas_sync {
6490     int *ptype;
6491     int *minlag;
6492     int *maxlag;
6493     GtkWidget *kspin;
6494     GtkWidget *l0spin;
6495     GtkWidget *l1spin;
6496 };
6497 
set_midas_ptype(GtkComboBox * w,struct midas_sync * msync)6498 static void set_midas_ptype (GtkComboBox *w, struct midas_sync *msync)
6499 {
6500     int pt = gtk_combo_box_get_active(w);
6501     int fixval = 0;
6502 
6503     if (pt == MIDAS_BETA1) {
6504 	fixval = 1;
6505     } else if (pt == MIDAS_BETA0) {
6506         fixval = 2;
6507     } else if (pt == MIDAS_BETAN) {
6508         fixval = 3;
6509     } else if (pt == MIDAS_U) {
6510         int l0 = spinner_get_int(msync->l0spin);
6511         int l1 = spinner_get_int(msync->l1spin);
6512         int k = l1 - l0 + 1;
6513 
6514         fixval = k;
6515     }
6516 
6517     if (fixval) {
6518         gtk_spin_button_set_value(GTK_SPIN_BUTTON(msync->kspin), fixval);
6519     }
6520     gtk_widget_set_sensitive(msync->kspin, fixval == 0);
6521 
6522     *msync->ptype = pt;
6523 }
6524 
set_midas_lag(GtkSpinButton * w,struct midas_sync * msync)6525 static void set_midas_lag (GtkSpinButton *w, struct midas_sync *msync)
6526 {
6527     int l0, l1, val = gtk_spin_button_get_value_as_int(w);
6528 
6529     if (GTK_WIDGET(w) == msync->l0spin) {
6530         l0 = val;
6531         if (spinner_get_int(msync->l1spin) < l0) {
6532             gtk_spin_button_set_value(GTK_SPIN_BUTTON(msync->l1spin), l0);
6533         }
6534         *msync->minlag = l0;
6535     } else {
6536         l1 = val;
6537         if (spinner_get_int(msync->l0spin) > l1) {
6538             gtk_spin_button_set_value(GTK_SPIN_BUTTON(msync->l0spin), l1);
6539         }
6540         *msync->maxlag = l1;
6541     }
6542 }
6543 
midas_term_dialog(const char * name,int m,int * minlag,int * maxlag,int * ptype,int * ncoef,gboolean no_beta1,GtkWidget * parent)6544 int midas_term_dialog (const char *name, int m,
6545                        int *minlag, int *maxlag,
6546                        int *ptype, int *ncoef,
6547                        gboolean no_beta1,
6548                        GtkWidget *parent)
6549 {
6550     const char *opts[] = {
6551         N_("Unrestricted (U-MIDAS)"),
6552         N_("Normalized exponential Almon"),
6553         N_("Normalized beta (zero last lag)"),
6554         N_("Normalized beta (non-zero last lag)"),
6555         N_("Almon polynomial"),
6556         N_("Normalized beta, one parameter")
6557     };
6558     struct midas_sync msync;
6559     GtkWidget *dialog, *combo;
6560     GtkWidget *vbox, *hbox, *tmp;
6561     gchar *msg;
6562     int i, np, hcode = MIDAS_PARM;
6563     int ret = GRETL_CANCEL;
6564 
6565     if (maybe_raise_dialog()) {
6566         return ret;
6567     }
6568 
6569     dialog = gretl_dialog_new("gretl: MIDAS term", parent, GRETL_DLG_BLOCK);
6570     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
6571 
6572     msync.ptype = ptype;
6573     msync.minlag = minlag;
6574     msync.maxlag = maxlag;
6575 
6576     /* label */
6577     hbox = gtk_hbox_new(FALSE, 5);
6578     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6579     msg = g_strdup_printf(_("High-frequency regressor %s"), name);
6580     tmp = gtk_label_new(msg);
6581     g_free(msg);
6582     gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
6583 
6584     np = G_N_ELEMENTS(opts);
6585     if (no_beta1) {
6586         np--;
6587     }
6588 
6589     /* param type selection */
6590     hbox = gtk_hbox_new(FALSE, 5);
6591     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6592     tmp = gtk_label_new(_("Parameterization"));
6593     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6594     combo = gtk_combo_box_text_new();
6595     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
6596     for (i=0; i<np; i++) {
6597         combo_box_append_text(combo, opts[i]);
6598     }
6599     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), *ptype);
6600 
6601     /* number of coefficients */
6602     hbox = gtk_hbox_new(FALSE, 5);
6603     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6604     tmp = gtk_label_new(_("Number of parameters"));
6605     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6606     msync.kspin = tmp = gtk_spin_button_new_with_range(1, 10, 1);
6607     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), *ncoef);
6608     g_signal_connect(G_OBJECT(tmp), "value-changed",
6609                      G_CALLBACK(set_int_from_spinner), ncoef);
6610     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6611 
6612     /* minimum and maximum lags */
6613     hbox = gtk_hbox_new(FALSE, 5);
6614     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
6615     tmp = gtk_label_new(_("Lags"));
6616     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6617     msync.l0spin = tmp = gtk_spin_button_new_with_range(-100, 100, 1);
6618     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), *minlag);
6619     g_signal_connect(G_OBJECT(tmp), "value-changed",
6620                      G_CALLBACK(set_midas_lag), &msync);
6621     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6622     tmp = gtk_label_new(_("to"));
6623     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6624     msync.l1spin = tmp = gtk_spin_button_new_with_range(-100, 100, 1);
6625     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), *maxlag);
6626     g_signal_connect(G_OBJECT(tmp), "value-changed",
6627                      G_CALLBACK(set_midas_lag), &msync);
6628     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6629 
6630     /* set param-type callback */
6631     g_signal_connect(G_OBJECT(combo), "changed",
6632                      G_CALLBACK(set_midas_ptype), &msync);
6633     /* and trigger it to ensure kspin is right */
6634     set_midas_ptype(GTK_COMBO_BOX(combo), &msync);
6635 
6636     /* buttons */
6637     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6638     cancel_delete_button(hbox, dialog);
6639     tmp = ok_validate_button(hbox, &ret, NULL);
6640     g_signal_connect(G_OBJECT(tmp), "clicked",
6641                      G_CALLBACK(delete_widget), dialog);
6642     gtk_widget_grab_default(tmp);
6643     if (hcode) {
6644         context_help_button(hbox, hcode);
6645     } else {
6646         gretl_dialog_keep_above(dialog);
6647     }
6648 
6649     gtk_widget_show_all(dialog);
6650 
6651     return ret;
6652 }
6653 
6654 struct dbnomics_info {
6655     int *retval;
6656     char **pcode;
6657     GtkWidget *entry;
6658     GtkWidget *dlg;
6659 };
6660 
dbn_callback(GtkWidget * w,struct dbnomics_info * di)6661 static void dbn_callback (GtkWidget *w, struct dbnomics_info *di)
6662 {
6663     const char *s = gtk_entry_get_text(GTK_ENTRY(di->entry));
6664 
6665     if (s != NULL && *s != '\0') {
6666         *di->retval = 0;
6667         *di->pcode = gretl_strdup(s);
6668         gtk_widget_destroy(di->dlg);
6669     } else {
6670         gtk_widget_grab_focus(di->entry);
6671     }
6672 }
6673 
dbnomics_dialog(char ** dbcode,GtkWidget * parent)6674 int dbnomics_dialog (char **dbcode, GtkWidget *parent)
6675 {
6676     struct dbnomics_info di = {0};
6677     GtkWidget *dialog, *entry;
6678     GtkWidget *vbox, *hbox, *tmp;
6679     int hcode = DBNHELP;
6680     int ret = GRETL_CANCEL;
6681 
6682     if (maybe_raise_dialog()) {
6683         return ret;
6684     }
6685 
6686     dialog = gretl_dialog_new("gretl: dbnomics access", parent, GRETL_DLG_BLOCK);
6687     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
6688 
6689     di.retval = &ret;
6690     di.pcode = dbcode;
6691     di.dlg = dialog;
6692 
6693     hbox = gtk_hbox_new(FALSE, 5);
6694     tmp = gtk_label_new(_("series code:"));
6695     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6696 
6697     di.entry = entry = gtk_entry_new();
6698     gtk_entry_set_max_length(GTK_ENTRY(entry), 128);
6699     gtk_entry_set_width_chars(GTK_ENTRY(entry), 48);
6700 
6701     gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
6702     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
6703     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6704 
6705     /* buttons */
6706     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6707     cancel_delete_button(hbox, dialog);
6708     tmp = ok_button(hbox);
6709     g_signal_connect(G_OBJECT(tmp), "clicked",
6710                      G_CALLBACK(dbn_callback), &di);
6711     gtk_widget_grab_default(tmp);
6712     if (hcode) {
6713         context_help_button(hbox, hcode);
6714     } else {
6715         gretl_dialog_keep_above(dialog);
6716     }
6717 
6718     gtk_widget_show_all(dialog);
6719 
6720     return ret;
6721 }
6722 
6723 /* geoplot GUI helper functions */
6724 
6725 static const char *palettes[] = {
6726     "default", "blues", "oranges", "green-to-red"
6727 };
6728 
6729 struct geoplot_info {
6730     int *retval;
6731     gretl_bundle *bundle;
6732     int *payload_id;
6733     int *palette_id;
6734     gchar **pplname;
6735     GtkWidget *payload_combo;
6736     GtkWidget *palette_combo;
6737     GtkWidget *border_check;
6738     GtkWidget *logscale_check;
6739     GtkWidget *linewidth_spin;
6740     GtkWidget *height_spin;
6741     GtkWidget *dlg;
6742 };
6743 
geoplot_callback(GtkWidget * w,struct geoplot_info * gi)6744 static void geoplot_callback (GtkWidget *w, struct geoplot_info *gi)
6745 {
6746     int border, logscale, height;
6747     double lwidth;
6748 
6749     if (gtk_widget_is_sensitive(gi->payload_combo)) {
6750         gchar *payload = NULL;
6751 	int palnum = 0;
6752 
6753         payload = combo_box_get_active_text(gi->payload_combo);
6754 	palnum = gtk_combo_box_get_active(GTK_COMBO_BOX(gi->palette_combo));
6755 
6756         if (payload != NULL && strcmp(payload, "none")) {
6757             *gi->payload_id = current_series_index(dataset, payload);
6758             if (palnum > 0) {
6759                 gretl_bundle_set_string(gi->bundle, "palette",
6760 					palettes[palnum]);
6761             }
6762         }
6763 	/* record the user's choices */
6764 	g_free(*gi->pplname);
6765 	*gi->pplname = payload;
6766 	*gi->palette_id = palnum;
6767     }
6768 
6769     border = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gi->border_check));
6770     logscale = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gi->logscale_check));
6771     height = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gi->height_spin));
6772 
6773     gretl_bundle_set_int(gi->bundle, "border", border);
6774     gretl_bundle_set_int(gi->bundle, "logscale", logscale);
6775     gretl_bundle_set_int(gi->bundle, "height", height);
6776 
6777     lwidth = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gi->linewidth_spin));
6778     lwidth = nearbyint(10*lwidth) / 10;
6779     if (lwidth != 1.0) {
6780 	gretl_bundle_set_scalar(gi->bundle, "linewidth", lwidth);
6781     }
6782 
6783     *gi->retval = 0;
6784     gtk_widget_destroy(gi->dlg);
6785 }
6786 
sensitize_map_controls(GtkComboBox * combo,struct geoplot_info * gi)6787 static void sensitize_map_controls (GtkComboBox *combo,
6788                                     struct geoplot_info *gi)
6789 {
6790     gchar *s = combo_box_get_active_text(combo);
6791     int active = strcmp(s, "none");
6792 
6793     gtk_widget_set_sensitive(gi->palette_combo, active);
6794     gtk_widget_set_sensitive(gi->logscale_check, active);
6795     gtk_spin_button_set_range(GTK_SPIN_BUTTON(gi->linewidth_spin),
6796 			      active ? 0.0 : 0.1, 2.0);
6797 }
6798 
6799 /* If we have a previously selected @payload, and it's a
6800    member of the current @plist, select it again by default.
6801 */
6802 
maybe_reinstate_selection(GList * plist,const gchar * payload,int * selpos)6803 static void maybe_reinstate_selection (GList *plist,
6804 				       const gchar *payload,
6805 				       int *selpos)
6806 {
6807     GList *tmp = g_list_first(plist);
6808     int i = 0;
6809 
6810     while (tmp != NULL) {
6811 	if (!strcmp((gchar *) tmp->data, payload)) {
6812 	    *selpos = 1;
6813 	    break;
6814 	}
6815 	tmp = tmp->next;
6816 	i++;
6817     }
6818 }
6819 
map_options_dialog(GList * plist,int selpos,gretl_bundle * b,int * payload_id)6820 int map_options_dialog (GList *plist, int selpos, gretl_bundle *b,
6821                         int *payload_id)
6822 {
6823     static gchar *payload = NULL;
6824     static int palette_id = 0;
6825     struct geoplot_info gi = {0};
6826     GtkWidget *dialog, *com1, *com2;
6827     GtkWidget *vbox, *hbox, *tmp;
6828     GtkWidget *bc, *ls, *hs, *lw;
6829     double lw_min = 0.0;
6830     int i, ret = GRETL_CANCEL;
6831 
6832     if (maybe_raise_dialog()) {
6833         return ret;
6834     }
6835 
6836     dialog = gretl_dialog_new(_("gretl: display map"), NULL, GRETL_DLG_BLOCK);
6837     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
6838 
6839     gi.retval = &ret;
6840     gi.bundle = b;
6841     gi.payload_id = payload_id;
6842     gi.palette_id = &palette_id;
6843     gi.pplname = &payload;
6844     gi.dlg = dialog;
6845 
6846     /* want a payload? */
6847     hbox = gtk_hbox_new(FALSE, 5);
6848     tmp = gtk_label_new(_("series to plot:"));
6849     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6850     gi.payload_combo = com1 = gtk_combo_box_text_new();
6851     gtk_box_pack_start(GTK_BOX(hbox), com1, FALSE, FALSE, 5);
6852     if (plist != NULL) {
6853 	if (payload != NULL) {
6854 	    maybe_reinstate_selection(plist, payload, &selpos);
6855 	}
6856         set_combo_box_strings_from_list(com1, plist);
6857         gtk_combo_box_set_active(GTK_COMBO_BOX(com1), selpos);
6858     } else {
6859         combo_box_append_text(com1, _("none"));
6860         gtk_combo_box_set_active(GTK_COMBO_BOX(com1), 0);
6861     }
6862     gtk_widget_set_sensitive(hbox, plist != NULL);
6863     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6864 
6865     /* palette? */
6866     hbox = gtk_hbox_new(FALSE, 5);
6867     tmp = gtk_label_new(_("palette:"));
6868     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6869     gi.palette_combo = com2 = gtk_combo_box_text_new();
6870     gtk_box_pack_start(GTK_BOX(hbox), com2, FALSE, FALSE, 5);
6871     for (i=0; i<G_N_ELEMENTS(palettes); i++) {
6872 	combo_box_append_text(com2, palettes[i]);
6873     }
6874     gtk_combo_box_set_active(GTK_COMBO_BOX(com2), palette_id);
6875     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6876     gtk_widget_set_sensitive(com2, selpos ? 1 : 0);
6877     gtk_widget_set_sensitive(hbox, plist != NULL);
6878 
6879     /* logscale? */
6880     hbox = gtk_hbox_new(FALSE, 5);
6881     ls = gtk_check_button_new_with_label(_("Log scale"));
6882     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ls), FALSE);
6883     gi.logscale_check = ls;
6884     gtk_box_pack_start(GTK_BOX(hbox), ls, FALSE, FALSE, 5);
6885     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6886     gtk_widget_set_sensitive(ls, selpos ? 1 : 0);
6887 
6888     /* border? */
6889     hbox = gtk_hbox_new(FALSE, 5);
6890     bc = gtk_check_button_new_with_label(_("draw border around map"));
6891     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bc), TRUE);
6892     gi.border_check = bc;
6893     gtk_box_pack_start(GTK_BOX(hbox), bc, FALSE, FALSE, 5);
6894     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6895 
6896     /* feature outlines? */
6897     hbox = gtk_hbox_new(FALSE, 5);
6898     tmp = gtk_label_new(_("Feature border width:"));
6899     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6900     if (gtk_combo_box_get_active(GTK_COMBO_BOX(com1)) == 0) {
6901 	/* no payload selected */
6902 	lw_min = 0.1;
6903     }
6904     lw = gtk_spin_button_new_with_range(lw_min, 2.0, 0.1);
6905     gtk_spin_button_set_value(GTK_SPIN_BUTTON(lw), 1.0);
6906     gi.linewidth_spin = lw;
6907     gtk_box_pack_start(GTK_BOX(hbox), lw, FALSE, FALSE, 5);
6908     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6909 
6910     /* height in pixels? */
6911     hbox = gtk_hbox_new(FALSE, 5);
6912     tmp = gtk_label_new(_("height in pixels:"));
6913     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
6914     hs = gtk_spin_button_new_with_range(300, 1000, 50);
6915     gtk_spin_button_set_value(GTK_SPIN_BUTTON(hs), 600);
6916     gi.height_spin = hs;
6917     gtk_box_pack_start(GTK_BOX(hbox), hs, FALSE, FALSE, 5);
6918     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
6919 
6920     /* inter-connect controls */
6921     g_signal_connect(G_OBJECT(gi.payload_combo), "changed",
6922                      G_CALLBACK(sensitize_map_controls), &gi);
6923 
6924     /* buttons */
6925     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
6926     cancel_delete_button(hbox, dialog);
6927     tmp = ok_button(hbox);
6928     g_signal_connect(G_OBJECT(tmp), "clicked",
6929                      G_CALLBACK(geoplot_callback), &gi);
6930     gtk_widget_grab_default(tmp);
6931     context_help_button(hbox, MAPHELP);
6932 
6933     gtk_widget_show_all(dialog);
6934 
6935     return ret;
6936 }
6937 
6938 struct tdisagg_info {
6939     int v;                 /* target series ID */
6940     int s;                 /* expansion factor */
6941     GtkWidget *name_entry; /* entry box for output name */
6942     GtkWidget *agg_combo;  /* aggregation type */
6943     GtkWidget *cl_combo;   /* chow-lin methods */
6944     GtkWidget *det_combo;  /* chow-lin deterministics */
6945     GtkWidget *cov_combo;  /* chow-lin covariates */
6946     GtkWidget *dn_combo;   /* denton methods */
6947     GtkWidget *dp_combo;   /* denton preliminary series */
6948     GtkWidget *plot_check; /* sanity-check plot? */
6949     GtkWidget *reg_check;  /* regression results? */
6950     GtkWidget *dlg;
6951 };
6952 
do_tdisagg(GtkWidget * w,struct tdisagg_info * tdi)6953 static void do_tdisagg (GtkWidget *w, struct tdisagg_info *tdi)
6954 {
6955     PRN *prn = NULL;
6956     GString *GSB = NULL;
6957     GString *GSC = NULL;
6958     gchar *agg, *xname = NULL;
6959     const gchar *yname, *str;
6960     int discard_x = 0;
6961     int idx, err;
6962 
6963     GSB = g_string_new(NULL);
6964     GSC = g_string_new(NULL);
6965 
6966     if (tdi->name_entry != NULL) {
6967         yname = gtk_entry_get_text(GTK_ENTRY(tdi->name_entry));
6968     } else {
6969         yname = dataset->varname[tdi->v];
6970     }
6971 
6972     agg = combo_box_get_active_text(tdi->agg_combo);
6973     g_string_printf(GSB, "_(aggtype=\"%s\"", agg);
6974     g_free(agg);
6975 
6976     if (gtk_widget_is_sensitive(tdi->cl_combo)) {
6977         idx = gtk_combo_box_get_active(GTK_COMBO_BOX(tdi->cl_combo));
6978         str = idx == 1 ? "fernandez" : "chow-lin";
6979         g_string_append_printf(GSB, ", method=\"%s\"", str);
6980         idx = gtk_combo_box_get_active(GTK_COMBO_BOX(tdi->det_combo));
6981         g_string_append_printf(GSB, ", det=%d", idx);
6982         if (gtk_widget_is_sensitive(tdi->cov_combo)) {
6983             xname = combo_box_get_active_text(tdi->cov_combo);
6984 	    discard_x = strcmp(xname, _("none")) == 0;
6985         }
6986     } else {
6987         idx = gtk_combo_box_get_active(GTK_COMBO_BOX(tdi->dn_combo));
6988         str = idx == 1 ? "denton-afd" : "denton-pfd";
6989         g_string_append_printf(GSB, ", method=\"%s\"", str);
6990         xname = combo_box_get_active_text(tdi->dp_combo);
6991 	discard_x = strcmp(xname, _("constant")) == 0;
6992     }
6993 
6994     if (xname != NULL) {
6995 	if (discard_x || current_series_index(dataset, xname) < 0) {
6996 	    g_free(xname);
6997 	    xname = NULL;
6998 	}
6999     }
7000 
7001     if (button_is_active(tdi->plot_check)) {
7002         g_string_append(GSB, ", plot=1");
7003     }
7004     if (gtk_widget_is_sensitive(tdi->reg_check) &&
7005         button_is_active(tdi->reg_check)) {
7006         g_string_append(GSB, ", verbose=2");
7007         bufopen(&prn);
7008     }
7009     g_string_append(GSB, ")");
7010 
7011     g_string_printf(GSC, "series %s = tdisagg(%s, %s, %d, %s)",
7012                     yname, dataset->varname[tdi->v],
7013                     xname != NULL ? xname : "null", tdi->s, GSB->str);
7014 
7015     err = generate(GSC->str, dataset, GRETL_TYPE_ANY, OPT_NONE, prn);
7016     if (err) {
7017         gui_errmsg(err);
7018         gretl_print_destroy(prn);
7019     } else {
7020         lib_command_strcpy(GSC->str);
7021         record_command_verbatim();
7022         mark_dataset_as_modified();
7023         populate_varlist();
7024         if (prn != NULL) {
7025             view_buffer(prn, 78, 400, "tdisagg", PRINT, NULL);
7026         }
7027     }
7028 
7029     g_string_free(GSC, TRUE);
7030     g_string_free(GSB, TRUE);
7031 
7032     gtk_widget_destroy(tdi->dlg);
7033 }
7034 
sensitize_chowlin(struct tdisagg_info * tdi,gboolean s)7035 static void sensitize_chowlin (struct tdisagg_info *tdi,
7036                                gboolean s)
7037 {
7038     gtk_widget_set_sensitive(tdi->cl_combo, s);
7039     gtk_widget_set_sensitive(tdi->det_combo, s);
7040     if (tdi->cov_combo != NULL) {
7041         gtk_widget_set_sensitive(tdi->cov_combo, s);
7042     }
7043 }
7044 
sensitize_denton(struct tdisagg_info * tdi,gboolean s)7045 static void sensitize_denton (struct tdisagg_info *tdi,
7046                               gboolean s)
7047 {
7048     gtk_widget_set_sensitive(tdi->dn_combo, s);
7049     gtk_widget_set_sensitive(tdi->dp_combo, s);
7050 }
7051 
tdisagg_switch_method(GtkToggleButton * tb,struct tdisagg_info * tdi)7052 static void tdisagg_switch_method (GtkToggleButton *tb,
7053                                    struct tdisagg_info *tdi)
7054 {
7055     gboolean s = gtk_toggle_button_get_active(tb);
7056 
7057     sensitize_chowlin(tdi, s);
7058     sensitize_denton(tdi, !s);
7059     gtk_widget_set_sensitive(tdi->reg_check, s);
7060 }
7061 
plausible_covariate_list(int v)7062 static GList *plausible_covariate_list (int v)
7063 {
7064     GList *list = NULL;
7065     int i;
7066 
7067     for (i=dataset->v-1; i>0; i--) {
7068         if (i == v) {
7069             continue;
7070         }
7071         if (gretl_isstoch(dataset->t1, dataset->t2, dataset->Z[i])) {
7072             list = g_list_append(list, (gpointer) dataset->varname[i]);
7073         }
7074     }
7075 
7076     return list;
7077 }
7078 
td_pattern(const double * x,int t1,int t2,int pd)7079 static int td_pattern (const double *x, int t1, int t2, int pd)
7080 {
7081     int t, i, err = 0;
7082 
7083     for (t=t1; t<=t2 && !err; t+=pd) {
7084 	/* the first obs per period must be valid */
7085 	if (na(x[t])) {
7086 	    err = E_MISSDATA;
7087 	}
7088 	/* subsequent values must be NA or the same
7089 	   as the first */
7090 	for (i=1; i<pd; i++) {
7091 	    if (!na(x[t+i]) && x[t+i] != x[t+i-1]) {
7092 		err = E_DATA;
7093 	    }
7094 	}
7095     }
7096 
7097     return err;
7098 }
7099 
7100 /* Try to figure the expansion factor for temporal
7101    disaggregation candidate series @v. Return 0 if
7102    this doesn't work.
7103 */
7104 
tdisagg_expansion(int v)7105 static int tdisagg_expansion (int v)
7106 {
7107     int opd = series_get_orig_pd(dataset, v);
7108     int s = 0;
7109 
7110     if (opd > 0) {
7111 	/* series is pre-approved */
7112 	s = dataset->pd / opd;
7113     } else {
7114 	const double *x = dataset->Z[v];
7115 	int t1 = dataset->t1;
7116 	int t2 = dataset->t2;
7117 	int pd = dataset->pd;
7118 	int sub, err;
7119 
7120 	series_adjust_sample(x, &t1, &t2);
7121 	date_maj_min(t1, dataset, NULL, &sub);
7122 	if (sub > 1) {
7123 	    /* advance to first sub-period */
7124 	    t1 += pd - sub + 1;
7125 	}
7126 	err = td_pattern(x, t1, t2, pd);
7127 	if (err && pd == 12) {
7128 	    /* monthly dataset: try for quarterly series */
7129 	    pd = 3;
7130 	    err = td_pattern(x, t1, t2, pd);
7131 	}
7132 	if (!err) {
7133 	    s = pd;
7134 	} else if (err == E_DATA) {
7135 	    errbox_printf(_("The series %s seems to be of the same frequency "
7136 			    "as the current dataset"), dataset->varname[v]);
7137 	} else {
7138 	    gui_errmsg(err);
7139 	}
7140     }
7141 
7142     return s;
7143 }
7144 
tdisagg_dialog(int v)7145 void tdisagg_dialog (int v)
7146 {
7147     const char *aggs[] = {
7148         "sum", "avg", "first", "last"
7149     };
7150     struct tdisagg_info tdi = {0};
7151     GtkWidget *dialog, *com, *hbox;
7152     GtkWidget *vbox, *tmp;
7153     GtkWidget *rb1, *rb2;
7154     GtkWidget *entry;
7155     GList *xlist = NULL;
7156     GSList *group = NULL;
7157     int i, s;
7158 
7159     if (maybe_raise_dialog()) {
7160         return;
7161     }
7162 
7163     s = tdisagg_expansion(v);
7164     if (s == 0) {
7165 	return;
7166     }
7167 
7168     dialog = gretl_dialog_new("gretl: temporal disaggregation",
7169                               NULL, GRETL_DLG_BLOCK);
7170     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
7171 
7172     tdi.dlg = dialog;
7173     tdi.v = v;
7174     tdi.s = s;
7175 
7176     xlist = plausible_covariate_list(v);
7177 
7178     /* output name */
7179     hbox = gtk_hbox_new(FALSE, 5);
7180     tmp = gtk_label_new(_("Output name:"));
7181     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7182     tdi.name_entry = entry = gtk_entry_new();
7183     gtk_entry_set_max_length(GTK_ENTRY(entry), 31);
7184     gtk_entry_set_width_chars(GTK_ENTRY(entry), 16);
7185     gtk_entry_set_text(GTK_ENTRY(entry), dataset->varname[v]);
7186     gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
7187     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7188     tmp = gtk_hseparator_new();
7189     gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 5);
7190 
7191     /* aggregation type */
7192     hbox = gtk_hbox_new(FALSE, 5);
7193     tmp = gtk_label_new(_("Aggregation type:"));
7194     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7195     tdi.agg_combo = com = gtk_combo_box_text_new();
7196     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7197     for (i=0; i<4; i++) {
7198         combo_box_append_text(com, aggs[i]);
7199     }
7200     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
7201     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7202     tmp = gtk_hseparator_new();
7203     gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 5);
7204 
7205     /* Regression vs Denton radio buttons */
7206     rb1 = gtk_radio_button_new_with_label(group, _("Regression based"));
7207     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rb1));
7208     rb2 = gtk_radio_button_new_with_label(group, "Denton");
7209 
7210     /* Regression */
7211     hbox = gtk_hbox_new(FALSE, 5);
7212     gtk_box_pack_start(GTK_BOX(hbox), rb1, FALSE, FALSE, 5);
7213     tdi.cl_combo = com = gtk_combo_box_text_new();
7214     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7215     combo_box_append_text(com, "Chow-Lin");
7216     combo_box_append_text(com, "Fernández");
7217     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
7218     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7219 
7220     hbox = gtk_hbox_new(FALSE, 5);
7221     tmp = gtk_label_new(_("Deterministic terms:"));
7222     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7223     tdi.det_combo = com = gtk_combo_box_text_new();
7224     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7225     combo_box_append_text(com, _("none"));
7226     combo_box_append_text(com, _("constant"));
7227     combo_box_append_text(com, _("constant plus trend"));
7228     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 1);
7229     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7230 
7231     xlist = g_list_prepend(xlist, (gpointer) _("none"));
7232     hbox = gtk_hbox_new(FALSE, 5);
7233     tmp = gtk_label_new(_("Covariate:"));
7234     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7235     tdi.cov_combo = com = gtk_combo_box_text_new();
7236     set_combo_box_strings_from_list(com, xlist);
7237     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7238     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
7239     gtk_widget_set_sensitive(com, g_list_length(xlist) > 1);
7240     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7241 
7242     tmp = gtk_hseparator_new();
7243     gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 5);
7244 
7245     /* denton radio */
7246     hbox = gtk_hbox_new(FALSE, 5);
7247     gtk_box_pack_start(GTK_BOX(hbox), rb2, FALSE, FALSE, 5);
7248     tdi.dn_combo = com = gtk_combo_box_text_new();
7249     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7250     combo_box_append_text(com, _("proportional"));
7251     combo_box_append_text(com, _("additive"));
7252     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
7253     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7254 
7255     xlist = g_list_prepend(xlist, (gpointer) "constant");
7256     hbox = gtk_hbox_new(FALSE, 5);
7257     tmp = gtk_label_new(_("Preliminary series:"));
7258     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7259     tdi.dp_combo = com = gtk_combo_box_text_new();
7260     set_combo_box_strings_from_list(com, xlist);
7261     gtk_box_pack_start(GTK_BOX(hbox), com, FALSE, FALSE, 5);
7262     gtk_combo_box_set_active(GTK_COMBO_BOX(com), 0);
7263     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7264 
7265     tmp = gtk_hseparator_new();
7266     gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 5);
7267 
7268     /* sensitivity */
7269     sensitize_denton(&tdi, FALSE);
7270     g_signal_connect(G_OBJECT(rb1), "toggled",
7271                      G_CALLBACK(tdisagg_switch_method), &tdi);
7272 
7273     /* show plot? */
7274     hbox = gtk_hbox_new(FALSE, 5);
7275     tdi.plot_check = tmp = gtk_check_button_new_with_label(_("show plot"));
7276     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), FALSE);
7277     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7278     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
7279 
7280     /* show regression results? (Not for Denton) */
7281     hbox = gtk_hbox_new(FALSE, 5);
7282     tdi.reg_check = tmp =
7283         gtk_check_button_new_with_label(_("show regression results"));
7284     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), FALSE);
7285     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7286     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
7287 
7288     /* buttons */
7289     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
7290     cancel_delete_button(hbox, dialog);
7291     tmp = ok_button(hbox);
7292     g_signal_connect(G_OBJECT(tmp), "clicked",
7293                      G_CALLBACK(do_tdisagg), &tdi);
7294     gtk_widget_grab_default(tmp);
7295     context_help_button(hbox, TDISAGG);
7296 
7297     gtk_widget_show_all(dialog);
7298 }
7299 
7300 /* apparatus for BDS nonlinearity test from menu */
7301 
7302 struct bds_info {
7303     int vnum;         /* ID of series to test */
7304     GtkWidget *dlg;   /* the dialog widget */
7305     GtkWidget *src;   /* source or parent of dialog */
7306     GtkWidget *mspin; /* spin button for order/max dimension */
7307     GtkWidget *sdb;   /* radio button for interpretation of eps */
7308     GtkWidget *cspin; /* spin button for eps a la Kanzler */
7309     GtkWidget *sspin; /* spin button for eps = multiple of s.d. */
7310     GtkWidget *boot;  /* radio button for bootstrapped P-values */
7311 };
7312 
record_bdstest(int m,int v,gretlopt opt,double dval,int boot,GtkWidget * modelwin)7313 static void record_bdstest (int m, int v, gretlopt opt, double dval,
7314 			    int boot, GtkWidget *modelwin)
7315 {
7316     const char *dstr[2] = {"corr1", "sdcrit"};
7317     GString *gs = g_string_new("bds ");
7318     int i = (opt == OPT_C)? 0 : 1;
7319 
7320     if (modelwin != NULL) {
7321 	lib_command_strcpy("# series residual = $uhat");
7322 	record_command_verbatim();
7323     }
7324 
7325     g_string_append_printf(gs, "%d %s ", m, dataset->varname[v]);
7326     gretl_push_c_numeric_locale();
7327     g_string_append_printf(gs, "--%s=%g ", dstr[i], dval);
7328     gretl_pop_c_numeric_locale();
7329     g_string_append_printf(gs, "--boot=%d", boot);
7330 
7331     lib_command_strcpy(gs->str);
7332     record_command_verbatim();
7333     g_string_free(gs, TRUE);
7334 }
7335 
do_bdstest(GtkWidget * w,struct bds_info * bi)7336 static void do_bdstest (GtkWidget *w, struct bds_info *bi)
7337 {
7338     gretlopt dopt, opt = OPT_B;
7339     int m = spinner_get_int(bi->mspin);
7340     int sdcrit = button_is_active(bi->sdb);
7341     int boot = button_is_active(bi->boot);
7342     double dval;
7343     PRN *prn = NULL;
7344 
7345     if (sdcrit) {
7346 	dval = gtk_spin_button_get_value(GTK_SPIN_BUTTON(bi->sspin));
7347 	dopt = OPT_S;
7348     } else {
7349 	dval = gtk_spin_button_get_value(GTK_SPIN_BUTTON(bi->cspin));
7350 	dopt = OPT_C;
7351     }
7352 
7353     opt |= dopt;
7354     set_optval_double(BDS, dopt, dval);
7355     set_optval_int(BDS, OPT_B, boot);
7356 
7357     bufopen(&prn);
7358 
7359     if (prn != NULL) {
7360 	int list[2] = {1, bi->vnum};
7361 	int err = 0;
7362 
7363 	err = bds_test_driver(m, list, dataset, opt, prn);
7364 	if (err) {
7365 	    gui_errmsg(err);
7366 	    gretl_print_destroy(prn);
7367 	} else {
7368             view_buffer(prn, 78, 400, "bds", PRINT, NULL);
7369 	    record_bdstest(m, bi->vnum, dopt, dval, boot, bi->src);
7370 	}
7371     }
7372 
7373     gtk_widget_destroy(bi->dlg);
7374 }
7375 
switch_bds_mode(GtkToggleButton * b,struct bds_info * bi)7376 static void switch_bds_mode (GtkToggleButton *b, struct bds_info *bi)
7377 {
7378     int sdcrit = gtk_toggle_button_get_active(b);
7379 
7380     gtk_widget_set_sensitive(bi->sspin, sdcrit);
7381     gtk_widget_set_sensitive(bi->cspin, !sdcrit);
7382 }
7383 
bdstest_dialog(int v,GtkWidget * parent)7384 void bdstest_dialog (int v, GtkWidget *parent)
7385 {
7386     struct bds_info bi = {0};
7387     GtkWidget *dialog, *hbox;
7388     GtkWidget *vbox, *label;
7389     GtkWidget *rb1, *tmp;
7390     GtkWidget *tbl;
7391     GSList *group = NULL;
7392 
7393     if (maybe_raise_dialog()) {
7394         return;
7395     }
7396 
7397     dialog = gretl_dialog_new("gretl: BDS test", parent, GRETL_DLG_BLOCK);
7398     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
7399 
7400     bi.vnum = v;
7401     bi.dlg = dialog;
7402     bi.src = parent;
7403 
7404     /* maximum dimension control */
7405     hbox = gtk_hbox_new(FALSE, 5);
7406     label = gtk_label_new(_("Maximum dimension:"));
7407     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
7408     bi.mspin = gtk_spin_button_new_with_range(2, 10, 1);
7409     gtk_box_pack_start(GTK_BOX(hbox), bi.mspin, FALSE, FALSE, 5);
7410     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
7411 
7412     vbox_add_hsep(vbox);
7413 
7414     /* distance controls */
7415     hbox = gtk_hbox_new(FALSE, 5);
7416     label = gtk_label_new(_("Criterion for closeness:"));
7417     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
7418     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7419     tbl = gtk_table_new(2, 2, FALSE);
7420     /* via correlation */
7421     rb1 = gtk_radio_button_new_with_label(NULL, _("First-order correlation"));
7422     gtk_table_attach_defaults(GTK_TABLE(tbl), rb1, 0, 1, 0, 1);
7423     bi.cspin = tmp = gtk_spin_button_new_with_range(0.1, 0.9, .01);
7424     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), 0.7);
7425     gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 1, 2, 0, 1);
7426     /* via s.d. */
7427     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rb1));
7428     bi.sdb = gtk_radio_button_new_with_label(group, _("Multiple of std. dev."));
7429     gtk_table_attach_defaults(GTK_TABLE(tbl), bi.sdb, 0, 1, 1, 2);
7430     bi.sspin = tmp = gtk_spin_button_new_with_range(0.1, 4.0, .01);
7431     gtk_spin_button_set_value(GTK_SPIN_BUTTON(tmp), 1.5);
7432     gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 1, 2, 1, 2);
7433     gtk_box_pack_start(GTK_BOX(vbox), tbl, FALSE, FALSE, 0);
7434     gtk_widget_set_sensitive(bi.sspin, FALSE);
7435     g_signal_connect(G_OBJECT(bi.sdb), "toggled",
7436 		     G_CALLBACK(switch_bds_mode), &bi);
7437 
7438     vbox_add_hsep(vbox);
7439 
7440     /* p-value type control */
7441     hbox = gtk_hbox_new(FALSE, 5);
7442     rb1 = gtk_radio_button_new_with_label(NULL, _("Asymptotic p-values"));
7443     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rb1));
7444     gtk_box_pack_start(GTK_BOX(hbox), rb1, FALSE, FALSE, 5);
7445     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
7446     hbox = gtk_hbox_new(FALSE, 5);
7447     bi.boot = tmp = gtk_radio_button_new_with_label(group, _("Bootstrap p-values"));
7448     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
7449     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7450     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), dataset->n < 600);
7451 
7452     /* buttons */
7453     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
7454     cancel_delete_button(hbox, dialog);
7455     tmp = ok_button(hbox);
7456     g_signal_connect(G_OBJECT(tmp), "clicked",
7457                      G_CALLBACK(do_bdstest), &bi);
7458     gtk_widget_grab_default(tmp);
7459     context_help_button(hbox, BDS);
7460 
7461     gtk_widget_show_all(dialog);
7462 }
7463 
7464 struct regls_options {
7465     gretl_bundle *parms;
7466     GtkWidget *dlg;
7467     GtkWidget *c[3];
7468     GtkWidget *b[4];
7469 };
7470 
set_regls_options(GtkWidget * w,struct regls_options * ro)7471 static void set_regls_options (GtkWidget *w, struct regls_options *ro)
7472 {
7473     int use_1se, set_seed;
7474     int lccd, rccd, timer;
7475     double seed;
7476 
7477     lccd = gtk_combo_box_get_active(GTK_COMBO_BOX(ro->c[0]));
7478     rccd = gtk_combo_box_get_active(GTK_COMBO_BOX(ro->c[1]));
7479     use_1se = gtk_combo_box_get_active(GTK_COMBO_BOX(ro->c[2]));
7480     set_seed = button_is_active(ro->b[0]);
7481     timer = button_is_active(ro->b[3]);
7482 
7483     gretl_bundle_set_int(ro->parms, "lccd", lccd);
7484     gretl_bundle_set_int(ro->parms, "rccd", rccd);
7485     gretl_bundle_set_int(ro->parms, "use_1se", use_1se);
7486     gretl_bundle_set_int(ro->parms, "set_seed", set_seed);
7487     gretl_bundle_set_int(ro->parms, "timer", timer);
7488 
7489 #ifdef HAVE_MPI
7490     int no_mpi = !button_is_active(ro->b[2]);
7491     gretl_bundle_set_int(ro->parms, "no_mpi", no_mpi);
7492 #endif
7493 
7494     if (set_seed) {
7495 	seed = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ro->b[1]));
7496 	gretl_bundle_set_scalar(ro->parms, "seed", seed);
7497     }
7498 
7499     gtk_widget_destroy(ro->dlg);
7500 }
7501 
regls_advanced_dialog(gretl_bundle * b,GtkWidget * parent)7502 void regls_advanced_dialog (gretl_bundle *b, GtkWidget *parent)
7503 {
7504     struct regls_options ro = {0};
7505     const char *anames[] = {
7506 	N_("LASSO algorithm:"),
7507 	N_("RIDGE algorithm:")
7508     };
7509     const char *lopts[] = {"ADMM", "CCD"};
7510     const char *ropts[] = {"SVD", "CCD"};
7511     const char **opts;
7512     GtkWidget *dialog, *vbox, *hbox, *w;
7513     double seed;
7514     int use_1se, set_seed;
7515     int lccd, rccd, timer;
7516 #ifdef HAVE_MPI
7517     int no_mpi = 0;
7518 #endif
7519     int i;
7520 
7521     dialog = gretl_dialog_new("gretl: regls options", parent, GRETL_DLG_BLOCK);
7522     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
7523 
7524     ro.dlg = dialog;
7525     ro.parms = b;
7526 
7527     lccd = gretl_bundle_get_int(b, "lccd", NULL);
7528     rccd = gretl_bundle_get_int(b, "rccd", NULL);
7529     use_1se = gretl_bundle_get_int(b, "use_1se", NULL);
7530     timer = gretl_bundle_get_int(b, "timer", NULL);
7531     set_seed = gretl_bundle_get_int(b, "set_seed", NULL);
7532     seed = gretl_bundle_get_scalar(b, "seed", NULL);
7533 #ifdef HAVE_MPI
7534     no_mpi = gretl_bundle_get_int(b, "no_mpi", NULL);
7535 #endif
7536 
7537     /* algorithms for LASSO, Ridge */
7538     for (i=0; i<2; i++) {
7539 	hbox = gtk_hbox_new(FALSE, 5);
7540 	w = gtk_label_new(_(anames[i]));
7541 	gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
7542 	ro.c[i] = gtk_combo_box_text_new();
7543 	opts = (i == 1)? ropts : lopts;
7544 	combo_box_append_text(ro.c[i], opts[0]);
7545 	combo_box_append_text(ro.c[i], opts[1]);
7546 	gtk_combo_box_set_active(GTK_COMBO_BOX(ro.c[i]), (i == 1)? rccd : lccd);
7547 	gtk_box_pack_start(GTK_BOX(hbox), ro.c[i], FALSE, FALSE, 5);
7548 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7549     }
7550 
7551     /* optimization criterion */
7552     hbox = gtk_hbox_new(FALSE, 5);
7553     w = gtk_label_new(_("cross validation criterion"));
7554     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
7555     ro.c[i] = gtk_combo_box_text_new();
7556     combo_box_append_text(ro.c[i], _("minimized MSE"));
7557     combo_box_append_text(ro.c[i], _("one-standard-error rule"));
7558     gtk_combo_box_set_active(GTK_COMBO_BOX(ro.c[i]), use_1se);
7559     gtk_box_pack_start(GTK_BOX(hbox), ro.c[i], FALSE, FALSE, 5);
7560     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7561 
7562     /* seed */
7563     hbox = gtk_hbox_new(FALSE, 5);
7564     ro.b[0] = gtk_check_button_new_with_label(_("set seed for random folds"));
7565     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ro.b[0]), set_seed);
7566     gtk_box_pack_start(GTK_BOX(hbox), ro.b[0], FALSE, FALSE, 5);
7567     ro.b[1] = gtk_spin_button_new_with_range(1, (gdouble) UINT_MAX, 1);
7568     gtk_entry_set_width_chars(GTK_ENTRY(ro.b[1]), 10);
7569     gtk_spin_button_set_value(GTK_SPIN_BUTTON(ro.b[1]), seed);
7570     gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ro.b[1]), 1, 100000);
7571     gtk_widget_set_sensitive(ro.b[1], set_seed);
7572     sensitize_conditional_on(ro.b[1], ro.b[0]);
7573     gtk_box_pack_start(GTK_BOX(hbox), ro.b[1], FALSE, FALSE, 5);
7574     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7575 
7576 #ifdef HAVE_MPI
7577     /* MPI switch */
7578     hbox = gtk_hbox_new(FALSE, 5);
7579     ro.b[2] = gtk_check_button_new_with_label(_("use MPI if available"));
7580     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ro.b[2]), !no_mpi);
7581     gtk_box_pack_start(GTK_BOX(hbox), ro.b[2], FALSE, FALSE, 5);
7582     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7583 #endif
7584 
7585     /* timer */
7586     hbox = gtk_hbox_new(FALSE, 5);
7587     ro.b[3] = gtk_check_button_new_with_label(_("show execution time"));
7588     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ro.b[3]), timer);
7589     gtk_box_pack_start(GTK_BOX(hbox), ro.b[3], FALSE, FALSE, 5);
7590     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
7591 
7592     /* buttons */
7593     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
7594     cancel_delete_button(hbox, dialog);
7595     w = ok_button(hbox);
7596     g_signal_connect(G_OBJECT(w), "clicked",
7597                      G_CALLBACK(set_regls_options), &ro);
7598     gtk_widget_grab_default(w);
7599     context_help_button(hbox, REGLS_ADV);
7600 
7601     gtk_widget_show_all(dialog);
7602 }
7603