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 /* dlgutils.c for gretl: utilities for composing dialog boxes */
21 
22 #include "gretl.h"
23 #include "textbuf.h"
24 #include "menustate.h"
25 #include "tabwin.h"
26 #include "dlgutils.h"
27 
28 #include "libset.h"
29 #include "system.h"
30 #include "gretl_bfgs.h"
31 
dialog_opts_new(int n,int type,gretlopt * optp,const gretlopt * vals,const char ** strs)32 dialog_opts *dialog_opts_new (int n, int type,
33 			      gretlopt *optp,
34 			      const gretlopt *vals,
35 			      const char **strs)
36 {
37     dialog_opts *opts;
38 
39     opts = malloc(sizeof *opts);
40     if (opts == NULL) {
41 	nomem();
42 	return NULL;
43     }
44 
45     opts->n = n;
46     opts->type = type;
47     opts->optp = optp;
48     opts->vals = vals;
49     opts->strs = strs;
50 
51     return opts;
52 }
53 
dialog_opts_free(dialog_opts * opts)54 void dialog_opts_free (dialog_opts *opts)
55 {
56     free(opts);
57 }
58 
vbox_add_hsep(GtkWidget * vbox)59 void vbox_add_hsep (GtkWidget *vbox)
60 {
61     GtkWidget *h = gtk_hseparator_new();
62 
63     gtk_box_pack_start(GTK_BOX(vbox), h, FALSE, FALSE, 0);
64     gtk_widget_show(h);
65 }
66 
pack_in_hbox(GtkWidget * w,GtkWidget * vbox,int vspace)67 void pack_in_hbox (GtkWidget *w, GtkWidget *vbox, int vspace)
68 {
69     GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
70 
71     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
72     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, vspace);
73 }
74 
75 /* Various buttons, usable in several sorts of dialogs */
76 
cancel_delete_button(GtkWidget * hbox,GtkWidget * targ)77 GtkWidget *cancel_delete_button (GtkWidget *hbox, GtkWidget *targ)
78 {
79     GtkWidget *button;
80 
81     button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
82     gtk_widget_set_can_default(button, TRUE);
83     gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
84     g_signal_connect(G_OBJECT(button), "clicked",
85 		     G_CALLBACK(delete_widget),
86 		     targ);
87 
88     return button;
89 }
90 
ok_button(GtkWidget * hbox)91 GtkWidget *ok_button (GtkWidget *hbox)
92 {
93     GtkWidget *w;
94 
95     w = gtk_button_new_from_stock(GTK_STOCK_OK);
96     gtk_widget_set_can_default(w, TRUE);
97     gtk_container_add(GTK_CONTAINER(hbox), w);
98 
99     return w;
100 }
101 
set_valid_response(GtkButton * b,int * valptr)102 static void set_valid_response (GtkButton *b, int *valptr)
103 {
104     int *retptr = g_object_get_data(G_OBJECT(b), "retptr");
105 
106     if (valptr == NULL) {
107 	*retptr = 0;
108     } else {
109 	*retptr = *valptr;
110     }
111 }
112 
113 /* on "OK": if @valptr is non-NULL, copy the valid value from
114    @valptr to @retptr; otherwise signal all-clear by copying
115    0 to @retptr
116 */
117 
ok_validate_button(GtkWidget * hbox,int * retptr,int * valptr)118 GtkWidget *ok_validate_button (GtkWidget *hbox, int *retptr,
119 			       int *valptr)
120 {
121     GtkWidget *button = ok_button(hbox);
122 
123     g_object_set_data(G_OBJECT(button), "retptr", retptr);
124     g_signal_connect(G_OBJECT(button), "clicked",
125 		     G_CALLBACK(set_valid_response), valptr);
126 
127     return button;
128 }
129 
apply_button(GtkWidget * hbox)130 GtkWidget *apply_button (GtkWidget *hbox)
131 {
132     GtkWidget *w;
133 
134     w = gtk_button_new_from_stock(GTK_STOCK_APPLY);
135     gtk_widget_set_can_default(w, TRUE);
136     gtk_container_add(GTK_CONTAINER(hbox), w);
137 
138     return w;
139 }
140 
cancel_button(GtkWidget * hbox)141 GtkWidget *cancel_button (GtkWidget *hbox)
142 {
143     GtkWidget *w;
144 
145     w = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
146     gtk_widget_set_can_default(w, TRUE);
147     gtk_container_add(GTK_CONTAINER(hbox), w);
148 
149     return w;
150 }
151 
close_button(GtkWidget * hbox)152 GtkWidget *close_button (GtkWidget *hbox)
153 {
154     GtkWidget *w;
155 
156     w = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
157     gtk_widget_set_can_default(w, TRUE);
158     gtk_container_add(GTK_CONTAINER(hbox), w);
159 
160     return w;
161 }
162 
next_button(GtkWidget * hbox)163 GtkWidget *next_button (GtkWidget *hbox)
164 {
165     GtkWidget *w;
166 
167     w = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD);
168     gtk_widget_set_can_default(w, TRUE);
169     gtk_container_add(GTK_CONTAINER(hbox), w);
170 
171     return w;
172 }
173 
back_button(GtkWidget * hbox)174 GtkWidget *back_button (GtkWidget *hbox)
175 {
176     GtkWidget *w;
177 
178     w = gtk_button_new_from_stock(GTK_STOCK_GO_BACK);
179     gtk_widget_set_can_default(w, TRUE);
180     gtk_container_add(GTK_CONTAINER(hbox), w);
181 
182     return w;
183 }
184 
set_dialog_border_widths(GtkWidget * ca,GtkWidget * aa)185 static void set_dialog_border_widths (GtkWidget *ca, GtkWidget *aa)
186 {
187     int w1 = 10, w2 = 5;
188 
189     gtk_container_set_border_width(GTK_CONTAINER(ca), w1);
190     gtk_box_set_spacing(GTK_BOX(ca), w2);
191     gtk_container_set_border_width(GTK_CONTAINER(aa), w2);
192 }
193 
gretl_dialog_set_resizeable(GtkWidget * w,gboolean s)194 static void gretl_dialog_set_resizeable (GtkWidget *w, gboolean s)
195 {
196     gtk_window_set_resizable(GTK_WINDOW(w), s);
197 }
198 
199 static GtkWidget *current_dialog;
200 static GtkWidget *open_edit_dialog;
201 static int plugin_dialog_open;
202 
maybe_raise_dialog(void)203 int maybe_raise_dialog (void)
204 {
205     int ret = 0;
206 
207     if (plugin_dialog_open) {
208 	ret = 1;
209     } else if (current_dialog != NULL) {
210 	gtk_window_present(GTK_WINDOW(current_dialog));
211 	ret = 1;
212     } else if (open_edit_dialog != NULL) {
213 	gtk_window_present(GTK_WINDOW(open_edit_dialog));
214 	ret = 1;
215     }
216 
217     return ret;
218 }
219 
set_plugin_dialog_open(gboolean s)220 void set_plugin_dialog_open (gboolean s)
221 {
222     plugin_dialog_open = s;
223 }
224 
dialog_unblock(GtkWidget * w,gpointer p)225 static gint dialog_unblock (GtkWidget *w, gpointer p)
226 {
227     gtk_main_quit();
228     current_dialog = NULL;
229     return FALSE;
230 }
231 
gretl_dialog_set_destruction(GtkWidget * w,gpointer p)232 gint gretl_dialog_set_destruction (GtkWidget *w, gpointer p)
233 {
234     gtk_window_set_transient_for(GTK_WINDOW(w), GTK_WINDOW(p));
235     gtk_window_set_destroy_with_parent(GTK_WINDOW(w), TRUE);
236 
237     if (g_object_get_data(G_OBJECT(p), "tabwin") != NULL) {
238 	tabwin_register_dialog(w, p);
239     }
240 
241     return FALSE;
242 }
243 
gretl_dialog_new(const char * title,GtkWidget * parent,unsigned char flags)244 GtkWidget *gretl_dialog_new (const char *title, GtkWidget *parent,
245 			     unsigned char flags)
246 {
247     GtkWidget *d = gretl_gtk_dialog();
248     GtkWidget *ca, *aa;
249 
250     if (flags & GRETL_DLG_UNDECORATED) {
251 	gtk_window_set_decorated(GTK_WINDOW(d), FALSE);
252     } else if (title != NULL) {
253 	gtk_window_set_title(GTK_WINDOW(d), title);
254     } else {
255 	gtk_window_set_title(GTK_WINDOW(d), "gretl");
256     }
257 
258     ca = gtk_dialog_get_content_area(GTK_DIALOG(d));
259     aa = gtk_dialog_get_action_area(GTK_DIALOG(d));
260     gtk_button_box_set_layout(GTK_BUTTON_BOX(aa), GTK_BUTTONBOX_END);
261     set_dialog_border_widths(ca, aa);
262     gtk_window_set_position(GTK_WINDOW(d), GTK_WIN_POS_MOUSE);
263 
264     if (flags & GRETL_DLG_BLOCK) {
265 	current_dialog = d;
266     }
267 
268     if (flags & GRETL_DLG_MODAL) {
269 	gretl_set_window_modal(d);
270     } else if (flags & GRETL_DLG_QUASI_MODAL) {
271 	gretl_set_window_quasi_modal(d);
272     }
273 
274     if (!(flags & GRETL_DLG_RESIZE)) {
275 	gretl_dialog_set_resizeable(d, FALSE);
276     }
277 
278     if (flags & GRETL_DLG_BLOCK) {
279 	g_signal_connect(G_OBJECT(d), "destroy",
280 			 G_CALLBACK(dialog_unblock), NULL);
281     }
282 
283     if (parent == NULL && mdata != NULL) {
284 	parent = mdata->main;
285     }
286 
287     if (parent != NULL) {
288 	g_signal_connect(G_OBJECT(d), "realize", /* was "show" */
289 			 G_CALLBACK(gretl_dialog_set_destruction),
290 			 parent);
291     }
292 
293     if (flags & GRETL_DLG_BLOCK) {
294 	g_signal_connect(G_OBJECT(d), "show",
295 			 G_CALLBACK(gtk_main), NULL);
296     }
297 
298     return d;
299 }
300 
sensitize_widget(GtkWidget * b,GtkWidget * w)301 static void sensitize_widget (GtkWidget *b, GtkWidget *w)
302 {
303     gboolean s = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b));
304 
305     gtk_widget_set_sensitive(w, s);
306 }
307 
308 /* make the sensitivity of widget @w positively dependent on the state
309    of button @b */
310 
sensitize_conditional_on(GtkWidget * w,GtkWidget * b)311 void sensitize_conditional_on (GtkWidget *w, GtkWidget *b)
312 {
313     g_signal_connect(G_OBJECT(b), "toggled",
314 		     G_CALLBACK(sensitize_widget), w);
315 }
316 
desensitize_widget(GtkWidget * b,GtkWidget * w)317 static void desensitize_widget (GtkWidget *b, GtkWidget *w)
318 {
319     gboolean s = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b));
320 
321     gtk_widget_set_sensitive(w, !s);
322 }
323 
324 /* make the sensitivity of widget @w negatively dependent on the state
325    of button @b */
326 
desensitize_conditional_on(GtkWidget * w,GtkWidget * b)327 void desensitize_conditional_on (GtkWidget *w, GtkWidget *b)
328 {
329     g_signal_connect(G_OBJECT(b), "toggled",
330 		     G_CALLBACK(desensitize_widget), w);
331 }
332 
set_double_from_spinner(GtkSpinButton * b,double * x)333 void set_double_from_spinner (GtkSpinButton *b, double *x)
334 {
335     *x = gtk_spin_button_get_value(b);
336 }
337 
set_int_from_spinner(GtkSpinButton * b,int * k)338 void set_int_from_spinner (GtkSpinButton *b, int *k)
339 {
340     *k = gtk_spin_button_get_value_as_int(b);
341 }
342 
toggle_gretl_option(GtkToggleButton * b,gretlopt * popt)343 static void toggle_gretl_option (GtkToggleButton *b, gretlopt *popt)
344 {
345     gretlopt val =
346 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(b), "optval"));
347 
348     if (gtk_toggle_button_get_active(b)) {
349 	*popt |= val;
350     } else {
351 	*popt &= ~val;
352     }
353 }
354 
355 /* Create a check button which sets @val in @popt when
356    activated, and unsets the flag when deactivated */
357 
gretl_option_check_button(const char * label,gretlopt * popt,gretlopt val)358 GtkWidget *gretl_option_check_button (const char *label,
359 				      gretlopt *popt,
360 				      gretlopt val)
361 {
362     GtkWidget *button;
363 
364     button = gtk_check_button_new_with_label(label);
365     g_object_set_data(G_OBJECT(button), "optval",
366 		      GINT_TO_POINTER(val));
367     g_signal_connect(G_OBJECT(button), "toggled",
368 		     G_CALLBACK(toggle_gretl_option), popt);
369 
370     return button;
371 }
372 
toggle_gretl_option_switched(GtkToggleButton * b,gretlopt * popt)373 static void toggle_gretl_option_switched (GtkToggleButton *b, gretlopt *popt)
374 {
375     gretlopt val =
376 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(b), "optval"));
377 
378     if (gtk_toggle_button_get_active(b)) {
379 	*popt &= ~val;
380     } else {
381 	*popt |= val;
382     }
383 }
384 
385 /* Create a check button which unsets @val in @popt when
386    activated, and sets the flag when deactivated */
387 
gretl_option_check_button_switched(const char * label,gretlopt * popt,gretlopt val)388 GtkWidget *gretl_option_check_button_switched (const char *label,
389 					       gretlopt *popt,
390 					       gretlopt val)
391 {
392     GtkWidget *button;
393 
394     button = gtk_check_button_new_with_label(label);
395     g_object_set_data(G_OBJECT(button), "optval",
396 		      GINT_TO_POINTER(val));
397     g_signal_connect(G_OBJECT(button), "toggled",
398 		     G_CALLBACK(toggle_gretl_option_switched), popt);
399 
400     return button;
401 }
402 
403 /* "edit dialog" apparatus */
404 
405 static GtkWidget *active_edit_id;
406 static GtkWidget *active_edit_name;
407 static GtkWidget *active_edit_text;
408 
get_active_edit_id(void)409 GtkWidget *get_active_edit_id (void)
410 {
411     return active_edit_id;
412 }
413 
get_active_edit_name(void)414 GtkWidget *get_active_edit_name (void)
415 {
416     return active_edit_name;
417 }
418 
get_active_edit_text(void)419 GtkWidget *get_active_edit_text (void)
420 {
421     return active_edit_text;
422 }
423 
set_active_edit_name(GtkWidget * w)424 void set_active_edit_name (GtkWidget *w)
425 {
426     active_edit_name = w;
427 }
428 
429 struct dialog_t_ {
430     int ci;
431     void (*okfunc)();
432     void *data;
433     int blocking;
434     int *cancel;
435     gretlopt opt;
436     GtkWidget *dialog;
437     GtkWidget *vbox;
438     GtkWidget *bbox;
439     GtkWidget *edit;
440     GtkWidget *popup;
441 };
442 
destroy_edit_dialog(GtkWidget * w,gpointer data)443 static void destroy_edit_dialog (GtkWidget *w, gpointer data)
444 {
445     dialog_t *d = (dialog_t *) data;
446 
447     if (d->blocking) {
448 	gtk_main_quit();
449     }
450 
451     g_free(d);
452 
453     open_edit_dialog = NULL;
454 
455     if (active_edit_id) active_edit_id = NULL;
456     if (active_edit_name) active_edit_name = NULL;
457     if (active_edit_text) active_edit_text = NULL;
458 }
459 
esc_kills_window(GtkWidget * w,GdkEventKey * key,gpointer p)460 gboolean esc_kills_window (GtkWidget *w, GdkEventKey *key,
461 			   gpointer p)
462 {
463     if (key->keyval == GDK_Escape) {
464         gtk_widget_destroy(w);
465 	return TRUE;
466     } else {
467 	return FALSE;
468     }
469 }
470 
edit_dialog_new(int ci,const char * title,void (* okfunc)(),void * data,int helpcode,GtkWidget * parent,int * canceled)471 static dialog_t *edit_dialog_new (int ci, const char *title,
472 				  void (*okfunc)(), void *data,
473 				  int helpcode, GtkWidget *parent,
474 				  int *canceled)
475 {
476     dialog_t *d = mymalloc(sizeof *d);
477 
478     if (d == NULL) {
479 	return NULL;
480     }
481 
482     d->ci = ci;
483     d->okfunc = okfunc;
484     d->data = data;
485     d->opt = OPT_NONE;
486     d->popup = NULL;
487     d->blocking = 0;
488     d->cancel = canceled;
489 
490     d->dialog = gretl_gtk_dialog();
491     d->vbox = gtk_dialog_get_content_area(GTK_DIALOG(d->dialog));
492     d->bbox = gtk_dialog_get_action_area(GTK_DIALOG(d->dialog));
493 
494     if (canceled != NULL) {
495 	*canceled = 1; /* will be undone by "OK" */
496 	d->blocking = 1;
497     }
498 
499     if (!strncmp(title, "gretl", 5)) {
500 	gtk_window_set_title(GTK_WINDOW(d->dialog), title);
501     } else {
502 	gchar *tmp = g_strdup_printf("gretl: %s", title);
503 
504 	gtk_window_set_title(GTK_WINDOW(d->dialog), tmp);
505 	g_free(tmp);
506     }
507 
508     gtk_box_set_homogeneous(GTK_BOX(d->bbox), TRUE);
509     gtk_window_set_position(GTK_WINDOW(d->dialog), GTK_WIN_POS_MOUSE);
510 
511     if (parent == NULL) {
512 	parent = mdata->main;
513     }
514 
515     g_signal_connect(G_OBJECT(d->dialog), "destroy",
516 		     G_CALLBACK(destroy_edit_dialog), d);
517     g_signal_connect(G_OBJECT(d->dialog), "key-press-event",
518 		     G_CALLBACK(esc_kills_window), NULL);
519     g_signal_connect(G_OBJECT(d->dialog), "show",
520 		     G_CALLBACK(gretl_dialog_set_destruction), parent);
521     if (d->blocking) {
522 	g_signal_connect(G_OBJECT(d->dialog), "show",
523 			 G_CALLBACK(gtk_main), NULL);
524     }
525 
526     return d;
527 }
528 
edit_dialog_close(dialog_t * dlg)529 void edit_dialog_close (dialog_t *dlg)
530 {
531     gtk_widget_destroy(dlg->dialog);
532 }
533 
534 /* saved material from "complex" edit dialog */
535 
536 static int edit_save_code;
537 static char *edit_save_buf;
538 
edit_save_buf_clear(void)539 static void edit_save_buf_clear (void)
540 {
541     g_free(edit_save_buf);
542     edit_save_buf = NULL;
543     edit_save_code = 0;
544 }
545 
set_edit_save_buf(const char * buf,int code)546 static void set_edit_save_buf (const char *buf, int code)
547 {
548     edit_save_buf_clear();
549 
550     if (buf != NULL) {
551 	edit_save_buf = g_strdup(buf);
552 	edit_save_code = code;
553     }
554 }
555 
dlg_text_set_previous(dialog_t * d)556 static int dlg_text_set_previous (dialog_t *d)
557 {
558     if (d->ci == edit_save_code &&
559 	edit_save_buf != NULL) {
560 	textview_set_text(d->edit, edit_save_buf);
561 	return 1;
562     } else {
563 	return 0;
564     }
565 }
566 
dlg_text_set_skeleton(dialog_t * d)567 static int dlg_text_set_skeleton (dialog_t *d)
568 {
569     const char *gmm_skel =
570 	"# initializations go here\n\n\n"
571 	"gmm\n"
572 	"  orthog\n"
573 	"  weights\n"
574 	"  params\n"
575 	"end gmm\n";
576     const char *sys_skel =
577 	"system\n\n"
578 	"end system\n";
579 
580     if (edit_save_buf == NULL) {
581 	if (d->ci == GMM) {
582 	    textview_set_text(d->edit, gmm_skel);
583 	    textview_set_cursor_at_line(d->edit, 1);
584 	    return 1;
585 	} else if (d->ci == SYSTEM) {
586 	    textview_set_text(d->edit, sys_skel);
587 	    textview_set_cursor_at_line(d->edit, 1);
588 	    return 1;
589 	}
590     }
591 
592     return 0;
593 }
594 
595 /* end edit saver apparatus */
596 
edit_dialog_special_get_text(dialog_t * dlg)597 gchar *edit_dialog_special_get_text (dialog_t *dlg)
598 {
599     gchar *buf;
600 
601     if (dlg == NULL) {
602 	edit_save_buf_clear();
603 	return NULL;
604     }
605 
606     buf = textview_get_text(dlg->edit);
607 
608     if (buf != NULL && *buf == '\0') {
609 	/* nothing was entered */
610 	g_free(buf);
611 	buf = NULL;
612     }
613 
614     if (buf == NULL) {
615 	gtk_widget_destroy(dlg->dialog);
616     }
617 
618     set_edit_save_buf(buf, dlg->ci);
619 
620     return buf;
621 }
622 
edit_dialog_get_text(dialog_t * dlg)623 const gchar *edit_dialog_get_text (dialog_t *dlg)
624 {
625     const gchar *buf;
626 
627     buf = gtk_entry_get_text(GTK_ENTRY(dlg->edit));
628 
629     if (buf == NULL || *buf == '\0') {
630 	if (dlg->ci != CORRGM) {
631 	    gtk_widget_destroy(dlg->dialog);
632 	}
633 	return NULL;
634     }
635 
636     return buf;
637 }
638 
edit_dialog_get_action(const dialog_t * dlg)639 int edit_dialog_get_action (const dialog_t *dlg)
640 {
641     return dlg->ci;
642 }
643 
edit_dialog_get_opt(const dialog_t * dlg)644 gretlopt edit_dialog_get_opt (const dialog_t *dlg)
645 {
646     return dlg->opt;
647 }
648 
edit_dialog_get_data(dialog_t * dlg)649 gpointer edit_dialog_get_data (dialog_t *dlg)
650 {
651     return dlg->data;
652 }
653 
edit_dialog_get_window(dialog_t * dlg)654 GtkWidget *edit_dialog_get_window (dialog_t *dlg)
655 {
656     return dlg->dialog;
657 }
658 
dialog_table_setup(dialog_t * dlg,int hsize)659 static void dialog_table_setup (dialog_t *dlg, int hsize)
660 {
661     GtkWidget *sw;
662 
663     sw = gtk_scrolled_window_new(NULL, NULL);
664     gtk_widget_set_size_request(sw, hsize, 200);
665     gtk_box_pack_start(GTK_BOX(dlg->vbox), sw, TRUE, TRUE, FALSE);
666     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw),
667 				   GTK_POLICY_AUTOMATIC,
668 				   GTK_POLICY_AUTOMATIC);
669     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (sw),
670 					GTK_SHADOW_IN);
671     gtk_container_add(GTK_CONTAINER(sw), dlg->edit);
672     gtk_widget_show(dlg->edit);
673     gtk_widget_show(sw);
674 }
675 
dlg_text_edit_new(int * hsize,gboolean s)676 static GtkWidget *dlg_text_edit_new (int *hsize, gboolean s)
677 {
678     GtkTextBuffer *tbuf;
679     GtkWidget *tview;
680 
681     tbuf = gtk_text_buffer_new(NULL);
682     tview = gtk_text_view_new_with_buffer(tbuf);
683 
684     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tview), GTK_WRAP_WORD);
685     gtk_text_view_set_left_margin(GTK_TEXT_VIEW(tview), 4);
686     gtk_text_view_set_right_margin(GTK_TEXT_VIEW(tview), 4);
687 
688     gtk_widget_modify_font(GTK_WIDGET(tview), fixed_font);
689     *hsize *= get_char_width(tview);
690     *hsize += 48;
691     gtk_text_view_set_editable(GTK_TEXT_VIEW(tview), s);
692     gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(tview), s);
693 
694     return tview;
695 }
696 
dlg_text_set_from_sys(equation_system * sys,dialog_t * d)697 static void dlg_text_set_from_sys (equation_system *sys,
698 				   dialog_t *d)
699 {
700     const char *buf;
701     PRN *prn;
702 
703     if (bufopen(&prn)) {
704 	return;
705     }
706 
707     print_equation_system_info(sys, dataset, OPT_NONE, prn);
708     buf = gretl_print_get_buffer(prn);
709     textview_set_text(d->edit, buf);
710     gretl_print_destroy(prn);
711 }
712 
713 enum {
714     ADD_EQN,
715     ADD_DERIV,
716     ADD_IDENT,
717     ADD_ENDO_LIST,
718     ADD_INSTR_LIST
719 };
720 
edit_has_list(GtkWidget * w,int i)721 static int edit_has_list (GtkWidget *w, int i)
722 {
723     gchar *buf;
724     int ret = 0;
725 
726     buf = textview_get_text(w);
727 
728     if (buf != NULL) {
729 	if (i == ADD_ENDO_LIST) {
730 	    if (strstr(buf, "endog ")) ret = 1;
731 	} else if (i == ADD_INSTR_LIST) {
732 	    if (strstr(buf, "instr ")) ret = 1;
733 	}
734 	g_free(buf);
735     }
736 
737     return ret;
738 }
739 
edit_popup_click(GtkWidget * w,dialog_t * d)740 static gint edit_popup_click (GtkWidget *w, dialog_t *d)
741 {
742     gint action =
743 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "action"));
744     const char *ins = NULL;
745 
746     if (action == ADD_EQN) {
747 	ins = "equation ";
748     } else if (action == ADD_DERIV) {
749 	ins = "deriv ";
750     } else if (action == ADD_IDENT) {
751 	ins = "identity ";
752     } else if (action == ADD_ENDO_LIST) {
753 	ins = "endog ";
754     } else if (action == ADD_INSTR_LIST) {
755 	ins = "instr ";
756     }
757 
758     if (ins != NULL) {
759 	GtkTextBuffer *tbuf;
760 	GtkTextMark *mark;
761 	GtkTextIter iter;
762 	gint offset, at_end;
763 
764 	tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(d->edit));
765 	mark = gtk_text_buffer_get_insert(tbuf);
766 	gtk_text_buffer_get_iter_at_mark(tbuf, &iter, mark);
767 	offset = gtk_text_iter_get_line_offset(&iter);
768 	at_end = gtk_text_iter_ends_line(&iter);
769 	if (offset == 0) {
770 	    /* at start of line */
771 	    if (!at_end) {
772 		gtk_text_iter_forward_to_line_end(&iter);
773 		gtk_text_buffer_insert(tbuf, &iter, "\n", -1);
774 	    }
775 	} else {
776 	    if (!at_end) {
777 		gtk_text_iter_forward_to_line_end(&iter);
778 	    }
779 	    gtk_text_buffer_insert(tbuf, &iter, "\n", -1);
780 	}
781 	gtk_text_buffer_insert(tbuf, &iter, ins, -1);
782     }
783 
784     gtk_widget_destroy(d->popup);
785 
786     return FALSE;
787 }
788 
build_edit_popup(dialog_t * d)789 static GtkWidget *build_edit_popup (dialog_t *d)
790 {
791     const char *items[] = {
792 	N_("Add equation"),
793 	N_("Add derivative"),
794 	N_("Add identity"),
795 	N_("Add list of endogenous variables"),
796 	N_("Add list of instruments")
797     };
798     GtkWidget *menu;
799     GtkWidget *item;
800     int i, n_items = sizeof items / sizeof items[0];
801 
802     if (d->ci == GMM || d->ci == RESTRICT) {
803 	return NULL;
804     }
805 
806     menu = gtk_menu_new();
807 
808     for (i=0; i<n_items; i++) {
809 	if (d->ci == NLS && (i != ADD_DERIV)) {
810 	    continue;
811 	} else if (d->ci == MLE && (i != ADD_DERIV)) {
812 	    continue;
813 	} else if (d->ci == SYSTEM) {
814 	    if (i == ADD_DERIV) continue;
815 	    if ((i == ADD_ENDO_LIST || i == ADD_INSTR_LIST) &&
816 		edit_has_list(d->edit, i)) {
817 		continue;
818 	    }
819 	}
820 	item = gtk_menu_item_new_with_label(_(items[i]));
821 	g_object_set_data(G_OBJECT(item), "action", GINT_TO_POINTER(i));
822 	g_signal_connect(G_OBJECT(item), "activate",
823 			 G_CALLBACK(edit_popup_click), d);
824 	gtk_widget_show(item);
825 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
826     }
827 
828     return menu;
829 }
830 
831 static gboolean
edit_dialog_popup_handler(GtkWidget * w,GdkEventButton * event,dialog_t * d)832 edit_dialog_popup_handler (GtkWidget *w, GdkEventButton *event,
833 			   dialog_t *d)
834 {
835     if (right_click(event)) {
836 	if (d->popup != NULL) {
837 	    gtk_widget_destroy(d->popup);
838 	    d->popup = NULL;
839 	}
840 
841 	d->popup = build_edit_popup(d);
842 
843 	if (d->popup != NULL) {
844 	    gtk_menu_popup(GTK_MENU(d->popup), NULL, NULL, NULL, NULL,
845 			   event->button, event->time);
846 	    g_signal_connect(G_OBJECT(d->popup), "destroy",
847 			     G_CALLBACK(gtk_widget_destroyed),
848 			     &d->popup);
849 	}
850 	return TRUE;
851     }
852 
853     return FALSE;
854 }
855 
set_sys_method(GtkComboBox * box,dialog_t * d)856 static void set_sys_method (GtkComboBox *box, dialog_t *d)
857 {
858     gchar *str = combo_box_get_active_text(box);
859     char *s, mstr[8] = {0};
860 
861     s = strrchr(str, '(');
862 
863     if (s != NULL) {
864 	GtkWidget *bt, *bv;
865 
866 	sscanf(s + 1, "%7[^)]", mstr);
867 	d->opt = system_method_from_string(mstr);
868 
869 	bt = g_object_get_data(G_OBJECT(box), "bt");
870 	bv = g_object_get_data(G_OBJECT(box), "bv");
871 
872 	if (d->opt == 0 || d->opt == 1 || d->opt == 6) {
873 	    /* SUR, 3SLS, WLS */
874 	    gtk_widget_set_sensitive(bt, TRUE);
875 	    gtk_widget_set_sensitive(bv, TRUE);
876 	} else if (d->opt == 2) {
877 	    /* FIML */
878 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bt), TRUE);
879 	    gtk_widget_set_sensitive(bt, FALSE);
880 	    gtk_widget_set_sensitive(bv, TRUE);
881 	} else {
882 	    /* LIML, OLS, TSLS */
883 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bt), FALSE);
884 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bt), FALSE);
885 	    gtk_widget_set_sensitive(bt, FALSE);
886 	    gtk_widget_set_sensitive(bv, FALSE);
887 	}
888     }
889 
890     g_free(str);
891 }
892 
dialog_option_switch(GtkWidget * vbox,dialog_t * dlg,gretlopt opt,MODEL * pmod)893 static GtkWidget *dialog_option_switch (GtkWidget *vbox, dialog_t *dlg,
894 					gretlopt opt, MODEL *pmod)
895 {
896     GtkWidget *b = NULL;
897 
898     if (opt == OPT_T) {
899 	b = gretl_option_check_button(_("Iterated estimation"),
900 				      &dlg->opt, opt); /* OPT_T vs OPT_I?? */
901 	if (pmod != NULL && (pmod->opt & OPT_I)) {
902 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), TRUE);
903 	}
904     } else if (opt == OPT_V) {
905 	b = gretl_option_check_button(_("Show details of iterations"),
906 				      &dlg->opt, opt);
907     } else if (opt == OPT_R) {
908 	b = gretl_option_check_button(_("Robust standard errors"),
909 				      &dlg->opt, opt);
910 	if (pmod != NULL && (pmod->opt & OPT_R)) {
911 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), TRUE);
912 	}
913     } else if (opt == OPT_B) {
914 	b = gretl_option_check_button(_("Use bootstrap"),
915 				      &dlg->opt, opt);
916     } else if (opt == OPT_F) {
917 	b = gretl_option_check_button(_("Show full restricted estimates"),
918 				      &dlg->opt, opt);
919     }
920 
921     if (b != NULL) {
922 	GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
923 
924 	gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 5);
925 	gtk_widget_show(b);
926 
927 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
928 	gtk_widget_show(hbox);
929     }
930 
931     return b;
932 }
933 
combo_opt_changed(GtkComboBox * box,combo_opts * opts)934 static void combo_opt_changed (GtkComboBox *box, combo_opts *opts)
935 {
936     gchar *s = combo_box_get_active_text(box);
937     int i;
938 
939     for (i=0; opts->strs[i] != NULL; i++) {
940 	if (!strcmp(s, _(opts->strs[i]))) {
941 	    *opts->optp |= opts->vals[i];
942 	} else {
943 	    *opts->optp &= ~opts->vals[i];
944 	}
945     }
946 
947     g_free(s);
948 }
949 
gretl_opts_combo_full(combo_opts * opts,int deflt,const int * masked,GCallback callback,gpointer calldata)950 GtkWidget *gretl_opts_combo_full (combo_opts *opts, int deflt,
951 				  const int *masked,
952 				  GCallback callback,
953 				  gpointer calldata)
954 {
955     GtkWidget *combo;
956     int i;
957 
958     *opts->optp |= opts->vals[deflt];
959 
960     combo = gtk_combo_box_text_new();
961     for (i=0; opts->strs[i] != NULL; i++) {
962 	if (!in_gretl_list(masked, i)) {
963 	    combo_box_append_text(combo, _(opts->strs[i]));
964 	}
965     }
966     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), deflt);
967     g_signal_connect(G_OBJECT(combo), "changed",
968 		     G_CALLBACK(combo_opt_changed), opts);
969     if (callback != NULL) {
970 	g_signal_connect(G_OBJECT(combo), "changed",
971 			 callback, calldata);
972     }
973 
974     return combo;
975 }
976 
gretl_opts_combo(combo_opts * opts,int deflt)977 GtkWidget *gretl_opts_combo (combo_opts *opts, int deflt)
978 {
979     return gretl_opts_combo_full(opts, deflt, NULL, NULL, NULL);
980 }
981 
gretl_opts_combo_masked(combo_opts * opts,int deflt,const int * masked)982 GtkWidget *gretl_opts_combo_masked (combo_opts *opts, int deflt,
983 				    const int *masked)
984 {
985     return gretl_opts_combo_full(opts, deflt, masked,
986 				 NULL, NULL);
987 }
988 
depopulate_combo_box(GtkComboBox * box)989 void depopulate_combo_box (GtkComboBox *box)
990 {
991     GtkTreeModel *model = gtk_combo_box_get_model(box);
992     GtkTreeIter iter;
993 
994     while (gtk_tree_model_get_iter_first(model, &iter)) {
995 	combo_box_remove(box, 0);
996     }
997 }
998 
mle_gmm_iters_dialog(GtkWidget * w,dialog_t * d)999 static void mle_gmm_iters_dialog (GtkWidget *w, dialog_t *d)
1000 {
1001     int maxit, lmem = 0, optim = BFGS_MAX;
1002     double tol;
1003     int resp;
1004 
1005     BFGS_defaults(&maxit, &tol, d->ci);
1006     lmem = libset_get_int(LBFGS_MEM);
1007 
1008     if (maxit <= 0) {
1009 	maxit = 1000;
1010     }
1011 
1012     if ((d->opt & OPT_L) || libset_get_bool(USE_LBFGS)) {
1013 	optim = LBFGS_MAX;
1014     }
1015 
1016     resp = iter_control_dialog(&optim, &maxit, &tol, &lmem,
1017 			       d->dialog);
1018 
1019     if (!canceled(resp)) {
1020 	int err;
1021 
1022 	err = libset_set_int(BFGS_MAXITER, maxit);
1023 	err += libset_set_double(BFGS_TOLER, tol);
1024 
1025 	if (optim == LBFGS_MAX) {
1026 	    d->opt |= OPT_L;
1027 	    libset_set_int(LBFGS_MEM, lmem);
1028 	} else {
1029 	    d->opt &= ~OPT_L;
1030 	}
1031 
1032 	if (err) {
1033 	    errbox("Error setting values");
1034 	}
1035     }
1036 }
1037 
add_bfgs_controls(dialog_t * d,GtkWidget * vbox,GtkWidget * hbox)1038 static void add_bfgs_controls (dialog_t *d,
1039 			       GtkWidget *vbox,
1040 			       GtkWidget *hbox)
1041 {
1042     GtkWidget *button;
1043 
1044     button = gtk_button_new_from_stock(GTK_STOCK_PREFERENCES);
1045     g_signal_connect(G_OBJECT(button), "clicked",
1046 		     G_CALLBACK(mle_gmm_iters_dialog), d);
1047     if (hbox == NULL) {
1048 	/* in the MLE case we want this on a new line */
1049 	hbox = gtk_hbox_new(FALSE, 5);
1050     }
1051     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1052     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1053     gtk_widget_show_all(hbox);
1054 }
1055 
build_gmm_combo(GtkWidget * vbox,dialog_t * d,MODEL * pmod)1056 static void build_gmm_combo (GtkWidget *vbox, dialog_t *d, MODEL *pmod)
1057 {
1058     GtkWidget *combo, *hbox;
1059     static const char *strs[] = {
1060 	N_("One-step estimation"),
1061 	N_("Two-step estimation"),
1062 	N_("Iterated estimation"),
1063 	NULL
1064     };
1065     static gretlopt opts[] = {
1066 	OPT_NONE,
1067 	OPT_T,
1068 	OPT_I
1069     };
1070     static combo_opts gmm_opts;
1071     int deflt = 0;
1072 
1073     gmm_opts.strs = strs;
1074     gmm_opts.vals = opts;
1075     gmm_opts.optp = &d->opt;
1076 
1077     if (pmod != NULL) {
1078 	if (pmod->opt & OPT_T) {
1079 	    deflt = 1;
1080 	} else if (pmod->opt & OPT_I) {
1081 	    deflt = 2;
1082 	}
1083 	if (pmod->opt & OPT_L) {
1084 	    d->opt |= OPT_L;
1085 	}
1086     }
1087 
1088     combo = gretl_opts_combo(&gmm_opts, deflt);
1089     hbox = gtk_hbox_new(FALSE, 5);
1090     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
1091     add_bfgs_controls(d, vbox, hbox);
1092 }
1093 
build_mle_combo(GtkWidget * vbox,dialog_t * d,MODEL * pmod)1094 static void build_mle_combo (GtkWidget *vbox, dialog_t *d, MODEL *pmod)
1095 {
1096     GtkWidget *combo, *hbox, *label;
1097     static const char *strs[] = {
1098 	N_("Outer product of gradient"),
1099 	N_("Hessian"),
1100 	N_("Robust (QML)"),
1101 	N_("Robust (HAC)"),
1102 	NULL
1103     };
1104     static gretlopt opts[] = {
1105 	OPT_NONE,
1106 	OPT_H,
1107 	OPT_R,
1108 	OPT_N
1109     };
1110     static combo_opts mle_opts;
1111     int tsmask[2] = {1, 3};
1112     int deflt = 0;
1113 
1114     mle_opts.strs = strs;
1115     mle_opts.vals = opts;
1116     mle_opts.optp = &d->opt;
1117 
1118     if (pmod != NULL) {
1119 	if (pmod->opt & OPT_H) {
1120 	    deflt = 1;
1121 	} else if (pmod->opt & OPT_R) {
1122 	    deflt = 2;
1123 	}
1124 	if (pmod->opt & OPT_L) {
1125 	    d->opt |= OPT_L;
1126 	}
1127     }
1128 
1129     if (dataset_is_time_series(dataset)) {
1130 	combo = gretl_opts_combo(&mle_opts, deflt);
1131     } else {
1132 	/* disallow the HAC option */
1133 	combo = gretl_opts_combo_masked(&mle_opts, deflt, tsmask);
1134     }
1135     hbox = gtk_hbox_new(FALSE, 5);
1136     label = gtk_label_new(_("Standard errors"));
1137     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1138     gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 5);
1139     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1140     gtk_widget_show_all(hbox);
1141     add_bfgs_controls(d, vbox, NULL);
1142 }
1143 
system_estimator_list(GtkWidget * vbox,dialog_t * d,GtkWidget * bt,GtkWidget * bv)1144 static void system_estimator_list (GtkWidget *vbox, dialog_t *d,
1145 				   GtkWidget *bt, GtkWidget *bv)
1146 {
1147     equation_system *sys = NULL;
1148     GtkWidget *w, *hbox;
1149     gchar *str;
1150     int active = 0;
1151     int i, j;
1152 
1153     if (d->data != NULL) {
1154 	sys = (equation_system *) d->data;
1155     }
1156 
1157     hbox = gtk_hbox_new(FALSE, 5);
1158     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1159     gtk_widget_show(hbox);
1160 
1161     w = gtk_label_new(_("Estimator"));
1162     gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 5);
1163     gtk_widget_show(w);
1164 
1165     w = gtk_combo_box_text_new();
1166 
1167     j = 0;
1168     for (i=SYS_METHOD_SUR; i<SYS_METHOD_MAX; i++) {
1169 	if (system_supports_method(sys, i)) {
1170 	    str = g_strdup_printf("%s (%s)", _(system_method_full_string(i)),
1171 				  system_method_short_string(i));
1172 	    combo_box_append_text(w, str);
1173 	    g_free(str);
1174 	    if (sys != NULL && sys->method == i) {
1175 		active = j;
1176 	    }
1177 	    j++;
1178 	}
1179     }
1180 
1181     g_object_set_data(G_OBJECT(w), "bt", bt);
1182     g_object_set_data(G_OBJECT(w), "bv", bv);
1183     g_signal_connect(G_OBJECT(w), "changed",
1184 		     G_CALLBACK(set_sys_method), d);
1185 
1186     gtk_combo_box_set_active(GTK_COMBO_BOX(w), active);
1187 
1188     gtk_box_pack_start(GTK_BOX(hbox), w, TRUE, TRUE, 5);
1189     gtk_widget_show(w);
1190 }
1191 
dlg_display_sys(dialog_t * d)1192 static void dlg_display_sys (dialog_t *d)
1193 {
1194     equation_system *sys = d->data;
1195     GtkWidget *w;
1196     int hsize = 62;
1197 
1198     if (d->ci == ESTIMATE) {
1199 	/* estimating an existing system, not editing */
1200 	w = gtk_label_new(sys->name);
1201 	gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_CENTER);
1202 	gtk_box_pack_start(GTK_BOX(d->vbox), w, TRUE, TRUE, 10);
1203 	gtk_widget_show(w);
1204     }
1205 
1206     d->edit = dlg_text_edit_new(&hsize, d->ci == SYSTEM);
1207     dialog_table_setup(d, hsize);
1208     dlg_text_set_from_sys(sys, d);
1209     gretl_dialog_set_resizeable(d->dialog, TRUE);
1210 }
1211 
raise_and_focus_dialog(GtkEditable * entry,GtkWidget * parent)1212 void raise_and_focus_dialog (GtkEditable *entry,
1213 			     GtkWidget *parent)
1214 {
1215     g_return_if_fail(entry != NULL && parent != NULL);
1216 
1217     gtk_window_present(GTK_WINDOW(parent));
1218 
1219     if (!gtk_widget_has_focus(GTK_WIDGET(entry))) {
1220 	gtk_widget_grab_focus(GTK_WIDGET(entry));
1221     }
1222 }
1223 
edit_dialog_help_code(int ci,void * p)1224 static int edit_dialog_help_code (int ci, void *p)
1225 {
1226     int hc = ci;
1227 
1228     if (ci == ESTIMATE || ci == CREATE_DATASET ||
1229 	ci == PRINT || ci == MINIBUF) {
1230 	hc = 0;
1231     } else if (ci == RESTRICT) {
1232 	windata_t *vwin = (windata_t *) p;
1233 
1234 	if (vwin->role == VIEW_MODEL) {
1235 	    hc = MODEL_RESTR;
1236 	} else if (vwin->role == SYSTEM) {
1237 	    hc = SYS_RESTR;
1238 	} else if (vwin->role == VECM) {
1239 	    hc = VECM_RESTR;
1240 	}
1241     }
1242 
1243     return hc;
1244 }
1245 
clear_dlg_previous(GtkWidget * w,dialog_t * d)1246 static void clear_dlg_previous (GtkWidget *w, dialog_t *d)
1247 {
1248     edit_save_buf_clear();
1249     textview_set_text(d->edit, NULL);
1250 }
1251 
edit_dialog_ok(GtkWidget * w,dialog_t * d)1252 static void edit_dialog_ok (GtkWidget *w, dialog_t *d)
1253 {
1254     if (d->okfunc != NULL) {
1255 	d->okfunc(w, d);
1256     } else {
1257 	gtk_widget_destroy(d->dialog);
1258     }
1259 }
1260 
ols_model_window(windata_t * vwin)1261 static int ols_model_window (windata_t *vwin)
1262 {
1263     if (vwin->role == VIEW_MODEL) {
1264 	MODEL *pmod = (MODEL *) vwin->data;
1265 
1266 	if (pmod->ci == OLS) {
1267 	    return 1;
1268 	}
1269     }
1270 
1271     return 0;
1272 }
1273 
vecm_model_window(windata_t * vwin)1274 static int vecm_model_window (windata_t *vwin)
1275 {
1276     return vwin->role == VECM;
1277 }
1278 
edit_dialog_add_note(int ci,const char * s,GtkWidget * vbox)1279 static void edit_dialog_add_note (int ci, const char *s,
1280 				  GtkWidget *vbox)
1281 {
1282     GtkWidget *w;
1283     gchar *lbl;
1284 
1285     if (ci == GMM) {
1286 	lbl = g_strdup_printf("%s\n%s", s,
1287 			      _("(Please refer to Help for guidance)"));
1288     } else {
1289 	lbl = g_strdup_printf("%s\n%s\n%s", s,
1290 			      _("(Please refer to Help for guidance)"),
1291 			      _("right-click for some shortcuts"));
1292     }
1293     w = gtk_label_new(lbl);
1294     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_CENTER);
1295     gtk_box_pack_start(GTK_BOX(vbox), w, FALSE, FALSE, 10);
1296     gtk_widget_show(w);
1297     g_free(lbl);
1298 }
1299 
1300 void
blocking_edit_dialog(int ci,const char * title,const char * info,const char * deflt,void (* okfunc)(),void * okptr,Varclick click,GtkWidget * parent,int * canceled)1301 blocking_edit_dialog (int ci, const char *title,
1302 		      const char *info, const char *deflt,
1303 		      void (*okfunc)(), void *okptr,
1304 		      Varclick click, GtkWidget *parent,
1305 		      int *canceled)
1306 {
1307     dialog_t *d;
1308     GtkWidget *w;
1309     MODEL *pmod = NULL;
1310     int helpcode;
1311     int clear = 0;
1312 
1313     if (open_edit_dialog != NULL && ci != MINIBUF) {
1314 	gtk_window_present(GTK_WINDOW(open_edit_dialog));
1315 	return;
1316     }
1317 
1318     helpcode = edit_dialog_help_code(ci, okptr);
1319     d = edit_dialog_new(ci, title, okfunc, okptr, helpcode,
1320 			parent, canceled);
1321     if (d == NULL) return;
1322 
1323     open_edit_dialog = d->dialog;
1324     set_dialog_border_widths(d->vbox, d->bbox);
1325     gretl_dialog_set_resizeable(d->dialog, FALSE);
1326 
1327     gtk_button_box_set_layout(GTK_BUTTON_BOX(d->bbox),
1328 			      GTK_BUTTONBOX_END);
1329 
1330     if (ci == ESTIMATE) {
1331 	/* estimating saved equation system */
1332 	dlg_display_sys(d);
1333     } else if (ci == SYSTEM && d->data != NULL) {
1334 	/* respecifying equation system */
1335 	edit_dialog_add_note(ci, info, d->vbox);
1336 	dlg_display_sys(d);
1337 	clear = 1;
1338     } else if (ci == NLS || ci == MLE || ci == GMM ||
1339 	       ci == SYSTEM || ci == RESTRICT) {
1340 	int hsize = 62;
1341 
1342 	edit_dialog_add_note(ci, info, d->vbox);
1343 	d->edit = dlg_text_edit_new(&hsize, TRUE);
1344 	dialog_table_setup(d, hsize);
1345 	gretl_dialog_set_resizeable(d->dialog, TRUE);
1346 
1347 	if (ci != RESTRICT && deflt != NULL) {
1348 	    /* re-specifying a nonlinear model */
1349 	    textview_set_text(d->edit, deflt);
1350 	    if (ci == NLS || ci == MLE || ci == GMM) {
1351 		pmod = okptr;
1352 	    }
1353 	} else if (dlg_text_set_previous(d) ||
1354 		   dlg_text_set_skeleton(d)) {
1355 	    /* insert previous text, if any, and if the command
1356 	       is the same as previously -- or insert skeleton
1357 	       of command
1358 	    */
1359 	    clear = 1;
1360 	}
1361 	g_signal_connect(G_OBJECT(d->edit), "button-press-event",
1362 			 G_CALLBACK(edit_dialog_popup_handler), d);
1363     } else {
1364 	if (info != NULL) {
1365 	    w = gtk_label_new(info);
1366 	    gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1367 	    gtk_box_pack_start(GTK_BOX(d->vbox), w, TRUE, TRUE, 5);
1368 	    gtk_widget_show(w);
1369 	}
1370 
1371 	d->edit = gtk_entry_new();
1372 	gtk_box_pack_start(GTK_BOX(d->vbox), d->edit, TRUE, TRUE, 5);
1373 
1374 	/* make the Enter key do the business */
1375 	if (okfunc != NULL) {
1376 	    gtk_entry_set_activates_default(GTK_ENTRY(d->edit), TRUE);
1377 	}
1378 
1379 	if (deflt != NULL && *deflt != '\0') {
1380 	    gtk_entry_set_text(GTK_ENTRY(d->edit), deflt);
1381 	    gtk_editable_select_region(GTK_EDITABLE(d->edit), 0, strlen(deflt));
1382 	}
1383 
1384 	g_signal_connect(G_OBJECT(GTK_EDITABLE(d->edit)), "changed",
1385 			 G_CALLBACK(raise_and_focus_dialog), d->dialog);
1386     }
1387 
1388     if (ci == SYSTEM || ci == ESTIMATE) {
1389 	GtkWidget *bt, *bv;
1390 
1391 	bt = dialog_option_switch(d->vbox, d, OPT_T, NULL);
1392 	bv = dialog_option_switch(d->vbox, d, OPT_V, NULL);
1393 	system_estimator_list(d->vbox, d, bt, bv);
1394     } else if (ci == NLS) {
1395 	dialog_option_switch(d->vbox, d, OPT_V, pmod);
1396 	dialog_option_switch(d->vbox, d, OPT_R, pmod);
1397     } else if (ci == MLE) {
1398 	dialog_option_switch(d->vbox, d, OPT_V, pmod);
1399 	build_mle_combo(d->vbox, d, pmod);
1400     } else if (ci == GMM) {
1401 	dialog_option_switch(d->vbox, d, OPT_V, pmod);
1402 	build_gmm_combo(d->vbox, d, pmod);
1403     } else if (ci == RESTRICT && ols_model_window(okptr)) {
1404 	dialog_option_switch(d->vbox, d, OPT_B, NULL);
1405     } else if (ci == RESTRICT && vecm_model_window(okptr)) {
1406 	dialog_option_switch(d->vbox, d, OPT_F, NULL);
1407     } else if (ci == GR_BOX) {
1408 	dialog_option_switch(d->vbox, d, OPT_O, NULL);
1409     }
1410 
1411     if (click == VARCLICK_INSERT_ID) {
1412 	active_edit_id = d->edit;
1413     } else if (click == VARCLICK_INSERT_NAME) {
1414 	active_edit_name = d->edit;
1415     } else if (click == VARCLICK_INSERT_TEXT) {
1416 	active_edit_text = d->edit;
1417     }
1418 
1419     if (click != VARCLICK_NONE || helpcode > 0) {
1420 	gtk_window_set_keep_above(GTK_WINDOW(d->dialog), FALSE);
1421     } else {
1422 	gtk_window_set_keep_above(GTK_WINDOW(d->dialog), TRUE);
1423     }
1424 
1425     gtk_widget_grab_focus(d->edit);
1426 
1427     /* "Clear" button? */
1428     if (clear) {
1429 	w = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1430 	gtk_container_add(GTK_CONTAINER(d->bbox), w);
1431 	g_signal_connect(G_OBJECT(w), "clicked",
1432 			 G_CALLBACK(clear_dlg_previous), d);
1433     }
1434 
1435     /* "Cancel" button */
1436     cancel_delete_button(d->bbox, d->dialog);
1437 
1438     /* "OK" button */
1439     if (canceled != NULL) {
1440 	w = ok_validate_button(d->bbox, canceled, NULL);
1441     } else {
1442 	w = ok_button(d->bbox);
1443     }
1444     g_signal_connect(G_OBJECT(w), "clicked",
1445 		     G_CALLBACK(edit_dialog_ok), d);
1446     gtk_widget_grab_default(w);
1447 
1448     /* "Help" button, if wanted */
1449     if (helpcode > 0) {
1450 	context_help_button(d->bbox, helpcode);
1451     }
1452 
1453     if (ci == GENR) {
1454 	gtk_widget_set_size_request(GTK_WIDGET(d->dialog), 400, -1);
1455     }
1456 
1457     gtk_widget_show_all(d->dialog);
1458 }
1459 
edit_dialog(int ci,const char * title,const char * info,const char * deflt,void (* okfunc)(),void * okptr,Varclick click,GtkWidget * parent)1460 void edit_dialog (int ci, const char *title,
1461 		  const char *info, const char *deflt,
1462 		  void (*okfunc)(), void *okptr,
1463 		  Varclick click, GtkWidget *parent)
1464 {
1465     blocking_edit_dialog(ci, title, info, deflt, okfunc, okptr,
1466 			 click, parent, NULL);
1467 }
1468 
edit_dialog_reset(dialog_t * dlg)1469 void edit_dialog_reset (dialog_t *dlg)
1470 {
1471     if (dlg->cancel != NULL) {
1472 	*dlg->cancel = 1;
1473     }
1474 }
1475 
entry_box_get_trimmed_text(GtkWidget * w)1476 gchar *entry_box_get_trimmed_text (GtkWidget *w)
1477 {
1478     const gchar *s = gtk_entry_get_text(GTK_ENTRY(w));
1479     gchar *ret = NULL;
1480 
1481     if (s != NULL) {
1482 	while (isspace(*s)) s++;
1483 	if (*s != '\0') {
1484 	    ret = g_strstrip(g_strdup(s));
1485 	}
1486     }
1487 
1488     return ret;
1489 }
1490 
set_combo_box_strings_from_list(GtkWidget * box,GList * list)1491 void set_combo_box_strings_from_list (GtkWidget *box, GList *list)
1492 {
1493     GList *mylist = list;
1494 
1495     while (mylist != NULL) {
1496 	combo_box_append_text(box, mylist->data);
1497 	mylist = mylist->next;
1498     }
1499 }
1500 
set_combo_box_default_text(GtkComboBox * box,const char * s)1501 void set_combo_box_default_text (GtkComboBox *box, const char *s)
1502 {
1503     GtkWidget *entry = gtk_bin_get_child(GTK_BIN(box));
1504 
1505     gtk_entry_set_text(GTK_ENTRY(entry), s);
1506 }
1507 
combo_box_text_new_with_entry(void)1508 GtkWidget *combo_box_text_new_with_entry (void)
1509 {
1510 #if GTK_MAJOR_VERSION >= 3
1511     return gtk_combo_box_text_new_with_entry();
1512 #else
1513     return gtk_combo_box_entry_new_text();
1514 #endif
1515 }
1516 
combo_box_get_active_text(gpointer p)1517 gchar *combo_box_get_active_text (gpointer p)
1518 {
1519     gchar *ret = NULL;
1520 
1521 #if GTK_MAJOR_VERSION >= 3
1522     ret = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(p));
1523 #else /* gtk < 2.24 */
1524     ret = gtk_combo_box_get_active_text(GTK_COMBO_BOX(p));
1525 #endif
1526 
1527     return ret;
1528 }
1529 
combo_box_append_text(gpointer p,const gchar * s)1530 void combo_box_append_text (gpointer p, const gchar *s)
1531 {
1532 #if GTK_MAJOR_VERSION >= 3
1533     gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p), s);
1534 #else
1535     gtk_combo_box_append_text(GTK_COMBO_BOX(p), s);
1536 #endif
1537 }
1538 
combo_box_prepend_text(gpointer p,const gchar * s)1539 void combo_box_prepend_text (gpointer p, const gchar *s)
1540 {
1541 #if GTK_MAJOR_VERSION >= 3
1542     gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(p), s);
1543 #else
1544     gtk_combo_box_prepend_text(GTK_COMBO_BOX(p), s);
1545 #endif
1546 }
1547 
combo_box_remove(gpointer p,int pos)1548 void combo_box_remove (gpointer p, int pos)
1549 {
1550 #if GTK_MAJOR_VERSION >= 3
1551     gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(p), pos);
1552 #else
1553     gtk_combo_box_remove_text(GTK_COMBO_BOX(p), pos);
1554 #endif
1555 }
1556 
widget_get_pointer_info(GtkWidget * w,gint * x,gint * y,GdkModifierType * mask)1557 gboolean widget_get_pointer_info (GtkWidget *w, gint *x, gint *y,
1558 				  GdkModifierType *mask)
1559 {
1560     GdkWindow *window = gtk_widget_get_window(w);
1561 
1562     if (window == NULL) {
1563 	return FALSE;
1564     } else {
1565 	gdk_window_get_pointer(window, x, y, mask);
1566 	return TRUE;
1567     }
1568 }
1569 
1570 /* set-up for a top-level window, @dlg, which emulates a GtkDialog
1571    structure: *pvbox is like the vbox member of a GtkDialog, and
1572    *pbbox like the action_area member.
1573 */
1574 
gretl_emulated_dialog_add_structure(GtkWidget * dlg,GtkWidget ** pvbox,GtkWidget ** pbbox)1575 void gretl_emulated_dialog_add_structure (GtkWidget *dlg,
1576 					  GtkWidget **pvbox,
1577 					  GtkWidget **pbbox)
1578 {
1579     GtkWidget *base;
1580 
1581     g_signal_connect(G_OBJECT(dlg), "key-press-event",
1582 		     G_CALLBACK(esc_kills_window), NULL);
1583 
1584     base = gtk_vbox_new(FALSE, 5);
1585     gtk_container_add(GTK_CONTAINER(dlg), base);
1586 
1587     *pvbox = gtk_vbox_new(FALSE, 0);
1588 
1589     /* make (upper) vbox expansible */
1590     gtk_box_pack_start(GTK_BOX(base), *pvbox, TRUE, TRUE, 0);
1591     gtk_container_set_border_width(GTK_CONTAINER(*pvbox), 5);
1592     gtk_box_set_spacing(GTK_BOX(*pvbox), 5);
1593 
1594 #if 0
1595     vbox_add_hsep(base);
1596 #endif
1597 
1598     *pbbox = gtk_hbutton_box_new();
1599     gtk_button_box_set_layout(GTK_BUTTON_BOX(*pbbox),
1600 			      GTK_BUTTONBOX_END);
1601     gtk_box_set_spacing(GTK_BOX(*pbbox), 10);
1602     gtk_box_pack_start(GTK_BOX(base), *pbbox,
1603 		       FALSE, FALSE, 0);
1604     gtk_container_set_border_width(GTK_CONTAINER(*pbbox), 5);
1605 }
1606