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 /* series_view.c for gretl */
21 
22 #include "gretl.h"
23 #include "textutil.h"
24 #include "dlgutils.h"
25 #include "menustate.h"
26 #include "textbuf.h"
27 #include "ssheet.h"
28 #include "series_view.h"
29 
30 #include "libset.h"
31 
32 #ifdef G_OS_WIN32
33 # include "gretlwin32.h"
34 #else
35 # include "clipboard.h"
36 #endif
37 
38 enum {
39     VIEW_STANDARD,
40     VIEW_CUSTOM
41 };
42 
43 typedef struct data_point_t data_point;
44 
45 struct data_point_t {
46     int obsnum;
47     double val;
48 };
49 
50 struct series_view_t {
51     int varnum;
52     int *list;
53     int sortvar;
54     int npoints;
55     char view;
56     int digits;
57     char format;
58     char sorted;
59     data_point *points;
60 };
61 
62 static void series_view_unsort (series_view *sview);
63 
free_series_view(gpointer p)64 void free_series_view (gpointer p)
65 {
66     series_view *sview = (series_view *) p;
67 
68     if (sview == NULL) return;
69 
70     if (sview->points != NULL) {
71 	free(sview->points);
72     }
73 
74     if (sview->list != NULL) {
75 	free(sview->list);
76     }
77 
78     free(sview);
79 }
80 
series_view_fill_points(series_view * sview)81 static void series_view_fill_points (series_view *sview)
82 {
83     int v, t, s = 0;
84 
85     v = (sview->varnum > 0)? sview->varnum : sview->sortvar;
86 
87     for (t=dataset->t1; t<=dataset->t2; t++) {
88 	sview->points[s].obsnum = t;
89 	sview->points[s].val = dataset->Z[v][t];
90 	s++;
91     }
92 }
93 
series_view_allocate(series_view * sview)94 static int series_view_allocate (series_view *sview)
95 {
96     int err = 0;
97 
98     if (sview == NULL) {
99 	return E_DATA;
100     }
101 
102     if (sview->points != NULL) {
103 	/* already allocated */
104 	return 0;
105     } else {
106 	int T = sample_size(dataset);
107 
108 	sview->points = mymalloc(T * sizeof *sview->points);
109 	if (sview->points == NULL) {
110 	    err = E_ALLOC;
111 	} else {
112 	    sview->npoints = T;
113 	}
114     }
115 
116     if (sview->varnum > 0) {
117 	/* single series view */
118 	series_view_fill_points(sview);
119     }
120 
121     return err;
122 }
123 
124 /* for printing sorted or reformatted data, for a window displaying
125    a single series */
126 
single_series_view_print(windata_t * vwin)127 static void single_series_view_print (windata_t *vwin)
128 {
129     series_view *sview = (series_view *) vwin->data;
130     char num_format[32];
131     double x;
132     PRN *prn;
133     int i, t, obslen;
134     int err = 0;
135 
136     if (bufopen(&prn)) {
137 	return;
138     }
139 
140     if (sview->view == VIEW_STANDARD) {
141 	int list[2] = { 1, sview->varnum };
142 
143 	/* regular printout: unsort if need be */
144 	if (sview->sorted) {
145 	    series_view_unsort(sview);
146 	}
147 
148 	err = printdata(list, NULL, dataset, OPT_O, prn);
149 	if (err) {
150 	    gui_errmsg(err);
151 	}
152 	goto finalize;
153     }
154 
155     obslen = max_obs_marker_length(dataset);
156 
157     if (sview->format == 'g') {
158 	sprintf(num_format, "%%#13.%dg\n", sview->digits);
159     } else {
160 	sprintf(num_format, "%%13.%df\n", sview->digits);
161     }
162 
163     pprintf(prn, "\n%*s ", obslen, " ");
164     pprintf(prn, "%13s\n\n", dataset->varname[sview->varnum]);
165 
166     for (i=0; i<sview->npoints; i++) {
167 	t = sview->points[i].obsnum;
168 	x = sview->points[i].val;
169 	print_obs_marker(t, dataset, obslen, prn);
170 	if (na(x)) {
171 	    pputc(prn, '\n');
172 	} else {
173 	    pprintf(prn, num_format, x);
174 	}
175     }
176 
177  finalize:
178 
179     if (!err) {
180 	textview_set_text(vwin->text, gretl_print_get_buffer(prn));
181     }
182 
183     gretl_print_destroy(prn);
184 }
185 
make_obsvec(series_view * sview)186 static int *make_obsvec (series_view *sview)
187 {
188     int *ov;
189     int t;
190 
191     ov = mymalloc((sview->npoints + 1) * sizeof *ov);
192 
193     if (ov != NULL) {
194 	ov[0] = sview->npoints;
195 	for (t=0; t<sview->npoints; t++) {
196 	    ov[t+1] = sview->points[t].obsnum;
197 	}
198     }
199 
200     return ov;
201 }
202 
multi_series_view_print_sorted(windata_t * vwin)203 static void multi_series_view_print_sorted (windata_t *vwin)
204 {
205     series_view *sview = (series_view *) vwin->data;
206     int *obsvec = make_obsvec(sview);
207     PRN *prn;
208     int err = 0;
209 
210     if (obsvec == NULL) {
211 	return;
212     }
213 
214     if (bufopen(&prn)) {
215 	free(obsvec);
216 	return;
217     }
218 
219     err = print_data_in_columns(sview->list, obsvec, dataset,
220 				OPT_NONE, prn);
221     if (err) {
222 	gui_errmsg(err);
223     } else {
224 	const char *buf = gretl_print_get_trimmed_buffer(prn);
225 
226 	textview_set_text(vwin->text, buf);
227     }
228 
229     free(obsvec);
230     gretl_print_destroy(prn);
231 }
232 
multi_series_view_print(windata_t * vwin)233 static void multi_series_view_print (windata_t *vwin)
234 {
235     series_view *sview = (series_view *) vwin->data;
236     PRN *prn;
237     int err = 0;
238 
239     if (bufopen(&prn)) {
240 	return;
241     }
242 
243     if (sview->view == VIEW_STANDARD) {
244 	err = printdata(sview->list, NULL, dataset, OPT_O, prn);
245     } else {
246 	err = print_series_with_format(sview->list, dataset,
247 				       sview->format, sview->digits,
248 				       prn);
249     }
250 
251     if (err) {
252 	gui_errmsg(err);
253     } else {
254 	textview_set_text(vwin->text, gretl_print_get_trimmed_buffer(prn));
255     }
256 
257     gretl_print_destroy(prn);
258 }
259 
series_view_is_sorted(windata_t * vwin)260 int series_view_is_sorted (windata_t *vwin)
261 {
262     series_view *sview = (series_view *) vwin->data;
263 
264     if (sview != NULL) {
265 	return sview->sorted;
266     } else {
267 	return 0;
268     }
269 }
270 
vwin_print_sorted_with_format(windata_t * vwin,PrnFormat fmt)271 PRN *vwin_print_sorted_with_format (windata_t *vwin, PrnFormat fmt)
272 {
273     series_view *sview = (series_view *) vwin->data;
274     int *obsvec;
275     PRN *prn;
276     int err = 0;
277 
278     obsvec = make_obsvec(sview);
279     if (obsvec == NULL) {
280 	return NULL;
281     }
282 
283     if (bufopen(&prn)) {
284 	free(obsvec);
285 	return NULL;
286     }
287 
288     gretl_print_set_format(prn, fmt);
289 
290     if (sview->varnum > 0) {
291 	/* single series, no list */
292 	int list[2] = {1, sview->varnum};
293 
294 	err = print_data_in_columns(list, obsvec, dataset,
295 				    OPT_NONE, prn);
296     } else {
297 	err = print_data_in_columns(sview->list, obsvec, dataset,
298 				    OPT_NONE, prn);
299     }
300 
301     if (err) {
302 	gui_errmsg(err);
303 	gretl_print_destroy(prn);
304 	prn = NULL;
305     }
306 
307     free(obsvec);
308 
309     return prn;
310 }
311 
summary_print_formatted(windata_t * vwin,series_view * sview)312 static void summary_print_formatted (windata_t *vwin, series_view *sview)
313 {
314     Summary *summ = vwin->data;
315     int digits = 0, places = 0;
316     PRN *prn;
317 
318     if (bufopen(&prn)) {
319 	return;
320     }
321 
322     if (sview->view != VIEW_STANDARD && sview->digits > 0) {
323 	if (sview->format == 'g') {
324 	    digits = sview->digits;
325 	} else {
326 	    places = sview->digits;
327 	}
328     }
329 
330     print_summary_single(summ, digits, places, dataset, prn);
331     textview_set_text(vwin->text, gretl_print_get_trimmed_buffer(prn));
332     gretl_print_destroy(prn);
333 }
334 
sort_points(const void * a,const void * b)335 static int sort_points (const void *a, const void *b)
336 {
337     const data_point *pa = (const data_point *) a;
338     const data_point *pb = (const data_point *) b;
339 
340     if (isnan(pa->val) || isnan(pb->val)) {
341 	if (!isnan(pa->val)) {
342 	    return -1;
343 	} else if (!isnan(pb->val)) {
344 	    return 1;
345 	} else {
346 	    return 0;
347 	}
348     } else {
349 	return (pa->val > pb->val) - (pa->val < pb->val);
350     }
351 }
352 
sort_points_down(const void * a,const void * b)353 static int sort_points_down (const void *a, const void *b)
354 {
355     const data_point *pa = (const data_point *) a;
356     const data_point *pb = (const data_point *) b;
357 
358     if (isnan(pa->val) || isnan(pb->val)) {
359 	if (!isnan(pa->val)) {
360 	    return 1;
361 	} else if (!isnan(pb->val)) {
362 	    return -1;
363 	} else {
364 	    return 0;
365 	}
366     } else {
367 	return (pa->val < pb->val) - (pa->val > pb->val);
368     }
369 }
370 
unsort_points(const void * a,const void * b)371 static int unsort_points (const void *a, const void *b)
372 {
373     const data_point *pa = (const data_point *) a;
374     const data_point *pb = (const data_point *) b;
375 
376     return (pa->obsnum > pb->obsnum) - (pa->obsnum < pb->obsnum);
377 }
378 
series_view_unsort(series_view * sview)379 static void series_view_unsort (series_view *sview)
380 {
381     qsort(sview->points, sview->npoints,
382 	  sizeof sview->points[0], unsort_points);
383     sview->sorted = 0;
384 }
385 
series_view_toggle_sort(GtkWidget * w,windata_t * vwin)386 void series_view_toggle_sort (GtkWidget *w, windata_t *vwin)
387 {
388     const char *opts[] = {
389 	N_("Ascending"),
390 	N_("Descending"),
391 	N_("Original order")
392     };
393     series_view *sview = (series_view *) vwin->data;
394     int sort_opt;
395 
396     if (series_view_allocate(sview)) {
397 	return;
398     }
399 
400     sort_opt = radio_dialog(NULL, _("Sort order:"), opts,
401 			    3, 0, 0, vwin->main);
402 
403     if (sort_opt < 0) {
404 	return;
405     } else if (sort_opt == 2) {
406 	/* dataset order */
407 	if (!sview->sorted) {
408 	    return; /* no-op */
409 	} else {
410 	    qsort(sview->points, sview->npoints,
411 		  sizeof sview->points[0], unsort_points);
412 	    sview->sorted = 0;
413 	    sview->view = VIEW_STANDARD;
414 	}
415     } else if (sort_opt == 0) {
416 	qsort(sview->points, sview->npoints,
417 	      sizeof sview->points[0], sort_points);
418 	sview->sorted = 1;
419 	sview->view = VIEW_CUSTOM;
420     } else {
421 	qsort(sview->points, sview->npoints,
422 	      sizeof sview->points[0], sort_points_down);
423 	sview->sorted = 1;
424 	sview->view = VIEW_CUSTOM;
425     }
426 
427     single_series_view_print(vwin);
428 }
429 
select_series_view_sorter(series_view * sview,windata_t * vwin,gretlopt * opt)430 static int select_series_view_sorter (series_view *sview,
431 				      windata_t *vwin,
432 				      gretlopt *opt)
433 {
434     dialog_opts *opts;
435     const char *strs[] = {
436 	N_("Ascending"),
437 	N_("Descending"),
438 	N_("Original order")
439     };
440     gretlopt vals[] = {
441 	OPT_NONE,
442 	OPT_D,
443 	OPT_O
444     };
445     int v = 0;
446 
447     opts = dialog_opts_new(3, OPT_TYPE_RADIO,
448 			   opt, vals, strs);
449 
450     if (opts != NULL) {
451 	v = select_var_from_list_with_opt(sview->list,
452 					  _("Variable to sort by"),
453 					  opts, 0, vwin->main);
454 	dialog_opts_free(opts);
455     }
456 
457     return v;
458 }
459 
multi_series_view_sort_by(GtkWidget * w,windata_t * vwin)460 void multi_series_view_sort_by (GtkWidget *w, windata_t *vwin)
461 {
462     series_view *sview = (series_view *) vwin->data;
463     gretlopt opt = OPT_NONE;
464     int v;
465 
466     if (sview == NULL || sview->list == NULL) {
467 	return;
468     }
469 
470     if (series_view_allocate(sview)) {
471 	return;
472     }
473 
474     v = select_series_view_sorter(sview, vwin, &opt);
475     if (v <= 0) {
476 	/* canceled or failed */
477 	return;
478     }
479 
480     if (opt == OPT_O) {
481 	if (!sview->sorted) {
482 	    return; /* no-op */
483 	} else if (sview->points != NULL) {
484 	    /* toggle back to unsorted */
485 	    qsort(sview->points, sview->npoints,
486 		  sizeof sview->points[0], unsort_points);
487 	    sview->sorted = 0;
488 	    sview->view = VIEW_STANDARD;
489 	    multi_series_view_print(vwin);
490 	}
491     } else {
492 	sview->sortvar = v;
493 	series_view_fill_points(sview);
494 
495 	if (opt == OPT_D) {
496 	    qsort(sview->points, sview->npoints,
497 		  sizeof sview->points[0], sort_points_down);
498 	} else {
499 	    qsort(sview->points, sview->npoints,
500 		  sizeof sview->points[0], sort_points);
501 	}
502 
503 	sview->sorted = 1;
504 	sview->view = VIEW_CUSTOM;
505 	multi_series_view_print_sorted(vwin);
506     }
507 }
508 
series_view_graph(GtkWidget * w,windata_t * vwin)509 void series_view_graph (GtkWidget *w, windata_t *vwin)
510 {
511     series_view *sview = (series_view *) vwin->data;
512 
513     if (sview == NULL || sview->varnum == 0) {
514 	return;
515     }
516 
517     if (dataset_is_time_series(dataset)) {
518 	do_graph_var(sview->varnum);
519     } else {
520 	do_boxplot_var(sview->varnum, OPT_NONE);
521     }
522 }
523 
series_view_edit(GtkWidget * w,windata_t * vwin)524 void series_view_edit (GtkWidget *w, windata_t *vwin)
525 {
526     series_view *sview = (series_view *) vwin->data;
527 
528     if (sview != NULL && sview->varnum > 0 && sview->varnum < dataset->v) {
529 	show_spreadsheet_for_series(sview->varnum);
530     }
531 }
532 
series_view_refresh(GtkWidget * w,windata_t * vwin)533 void series_view_refresh (GtkWidget *w, windata_t *vwin)
534 {
535     series_view *sview = (series_view *) vwin->data;
536 
537     if (sview != NULL && sview->varnum > 0 && sview->varnum < dataset->v) {
538 	int list[2] = {1, sview->varnum};
539 	PRN *prn = NULL;
540 	int err;
541 
542 	if (bufopen(&prn)) {
543 	    return;
544 	}
545 
546 	err = printdata(list, NULL, dataset, OPT_O, prn);
547 
548 	if (err) {
549 	    gui_errmsg(err);
550 	    gretl_print_destroy(prn);
551 	} else {
552 	    /* replace text buffer in sview using prn */
553 	    const char *buf = gretl_print_get_trimmed_buffer(prn);
554 
555 	    textview_set_text(vwin->text, buf);
556 	    gretl_print_destroy(prn);
557 	}
558     }
559 }
560 
series_view_get_list(windata_t * vwin)561 int *series_view_get_list (windata_t *vwin)
562 {
563     series_view *sview = vwin->data;
564     int *list = NULL;
565 
566     if (sview == NULL) {
567 	return NULL;
568     }
569 
570     if (vwin->role == VIEW_SERIES) {
571 	list = gretl_list_new(1);
572 	if (list != NULL) {
573 	    list[1] = sview->varnum;
574 	}
575     } else {
576 	list = gretl_list_copy(sview->list);
577     }
578 
579     return list;
580 }
581 
has_sortable_data(windata_t * vwin)582 int has_sortable_data (windata_t *vwin)
583 {
584     if (vwin != NULL && (vwin->flags & VWIN_MULTI_SERIES)) {
585 	series_view *sv = vwin->data;
586 
587 	return (sv != NULL && sv->list != NULL && sv->list[0] < 5);
588     } else {
589 	return 0;
590     }
591 }
592 
can_format_data(windata_t * vwin)593 int can_format_data (windata_t *vwin)
594 {
595     if (vwin->role == VIEW_SERIES || vwin->role == VIEW_MODELTABLE) {
596 	return 1;
597     } else if (vwin->flags & VWIN_MULTI_SERIES) {
598 	series_view *sview = vwin->data;
599 
600 	return (sview->list != NULL);
601     } else if (vwin->role == SUMMARY && vwin->data != NULL) {
602 	Summary *s = vwin->data;
603 
604 	return (s->list != NULL && s->list[0] == 1);
605     } else {
606 	return 0;
607     }
608 }
609 
series_view_init(series_view * sview)610 static void series_view_init (series_view *sview)
611 {
612     sview->varnum = 0;
613     sview->sortvar = 0;
614     sview->npoints = 0;
615     sview->view = VIEW_STANDARD;
616     sview->digits = 6;
617     sview->format = 'g';
618     sview->sorted = 0;
619     sview->points = NULL;
620     sview->list = NULL;
621 }
622 
series_view_new(int varnum,const int * list)623 static series_view *series_view_new (int varnum, const int *list)
624 {
625     series_view *sview = NULL;
626     int *svlist = NULL;
627 
628     if (varnum == 0 && list == NULL) {
629 	return NULL;
630     }
631 
632     sview = malloc(sizeof *sview);
633     if (sview == NULL) {
634 	return NULL;
635     }
636 
637     if (list != NULL) {
638 	svlist = gretl_list_copy(list);
639 	if (svlist == NULL) {
640 	    free(sview);
641 	    sview = NULL;
642 	}
643     }
644 
645     if (sview != NULL) {
646 	series_view_init(sview);
647 	sview->varnum = varnum;
648 	sview->list = svlist;
649     }
650 
651     return sview;
652 }
653 
series_view_connect(windata_t * vwin,int varnum)654 void series_view_connect (windata_t *vwin, int varnum)
655 {
656     series_view *sview = series_view_new(varnum, NULL);
657 
658     vwin->data = sview;
659 }
660 
multi_series_view_new(const int * list)661 series_view *multi_series_view_new (const int *list)
662 {
663     return series_view_new(0, list);
664 }
665 
666 struct view_toggler {
667     GtkWidget *spin;
668     GtkWidget *combo;
669     char view;
670     int digits;
671     char format;
672     windata_t *target_vwin;
673     series_view *sview;
674 };
675 
676 /* toggle for standard versus custom view */
677 
series_view_toggle_view(GtkWidget * w,struct view_toggler * vt)678 static void series_view_toggle_view (GtkWidget *w, struct view_toggler *vt)
679 {
680     gboolean std = button_is_active(w);
681 
682     vt->view = std ? VIEW_STANDARD : VIEW_CUSTOM;
683     gtk_widget_set_sensitive(vt->spin, !std);
684     if (vt->combo != NULL) {
685 	gtk_widget_set_sensitive(vt->combo, !std);
686     }
687 }
688 
series_view_set_digits(GtkSpinButton * b,int * digits)689 static void series_view_set_digits (GtkSpinButton *b, int *digits)
690 {
691     *digits = gtk_spin_button_get_value_as_int(b);
692 }
693 
series_view_set_fmt(GtkComboBox * cb,char * format)694 static void series_view_set_fmt (GtkComboBox *cb, char *format)
695 {
696     gint i = gtk_combo_box_get_active(cb);
697 
698     *format = (i == 0)? 'g' : 'f';
699 }
700 
reformat_callback(GtkButton * b,struct view_toggler * vt)701 static void reformat_callback (GtkButton *b, struct view_toggler *vt)
702 {
703     windata_t *vwin = vt->target_vwin;
704     series_view *sview = vt->sview;
705 
706     sview->digits = vt->digits;
707     sview->format = vt->format;
708     sview->view = vt->view;
709 
710     if (vwin->role == SUMMARY) {
711 	summary_print_formatted(vwin, sview);
712     } else if (sview->list != NULL) {
713 	multi_series_view_print(vwin);
714     } else {
715 	single_series_view_print(vwin);
716     }
717 }
718 
real_view_format_dialog(windata_t * vwin,series_view * sview)719 static void real_view_format_dialog (windata_t *vwin, series_view *sview)
720 {
721     struct view_toggler vt;
722     GtkWidget *dlg, *vbox;
723     GtkWidget *tmp, *hbox;
724     GtkWidget *b1, *b2;
725     GSList *group;
726     int std;
727 
728     dlg = gretl_dialog_new(_("gretl: data format"), vwin->main,
729 			   GRETL_DLG_BLOCK);
730 
731     vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
732 
733     std = (sview->view == VIEW_STANDARD);
734 
735     vt.view = sview->view;
736     vt.digits = sview->digits;
737     vt.format = sview->format;
738     vt.target_vwin = vwin;
739     vt.sview = sview;
740 
741     hbox = gtk_hbox_new(FALSE, 5);
742     tmp = gtk_label_new(_("Select data format"));
743     gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5);
744     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
745 
746     /* standard format radio option */
747     hbox = gtk_hbox_new(FALSE, 5);
748     b1 = gtk_radio_button_new_with_label(NULL, _("Standard format"));
749     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1), std);
750     gtk_box_pack_start(GTK_BOX(hbox), b1, TRUE, TRUE, 5);
751     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
752 
753     /* custom format radio option */
754     hbox = gtk_hbox_new(FALSE, 5);
755     group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1));
756     b2 = gtk_radio_button_new_with_label(group, _("Show"));
757     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2), !std);
758     gtk_box_pack_start(GTK_BOX(hbox), b2, FALSE, FALSE, 5);
759 
760     /* with spinner for number of digits */
761     vt.spin = gtk_spin_button_new_with_range(1, 15, 1);
762     gtk_spin_button_set_value(GTK_SPIN_BUTTON(vt.spin), sview->digits);
763     g_signal_connect(G_OBJECT(vt.spin), "value-changed",
764 		     G_CALLBACK(series_view_set_digits), &vt.digits);
765     gtk_widget_set_sensitive(vt.spin, !std);
766     gtk_box_pack_start(GTK_BOX(hbox), vt.spin, FALSE, FALSE, 0);
767 
768     /* and selector for digits / decimal places */
769     vt.combo = gtk_combo_box_text_new();
770     combo_box_append_text(vt.combo, _("significant figures"));
771     combo_box_append_text(vt.combo, _("decimal places"));
772     if (sview->format == 'g') {
773 	gtk_combo_box_set_active(GTK_COMBO_BOX(vt.combo), 0);
774     } else {
775 	gtk_combo_box_set_active(GTK_COMBO_BOX(vt.combo), 1);
776     }
777     g_signal_connect(G_OBJECT(GTK_COMBO_BOX(vt.combo)), "changed",
778 		     G_CALLBACK(series_view_set_fmt), &vt.format);
779     gtk_widget_set_sensitive(vt.combo, !std);
780     gtk_box_pack_start(GTK_BOX(hbox), vt.combo, FALSE, FALSE, 5);
781 
782     /* connect toggle signal */
783     g_signal_connect(G_OBJECT(b1), "toggled",
784                      G_CALLBACK(series_view_toggle_view), &vt);
785 
786     /* pack the custom line */
787     gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
788 
789     hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
790 
791     /* Cancel button */
792     cancel_delete_button(hbox, dlg);
793 
794     /* OK button */
795     tmp = ok_button(hbox);
796     g_signal_connect(G_OBJECT(tmp), "clicked",
797 		     G_CALLBACK(reformat_callback), &vt);
798     g_signal_connect(G_OBJECT(tmp), "clicked",
799 		     G_CALLBACK(delete_widget), dlg);
800     gtk_widget_grab_default(tmp);
801 
802     gtk_widget_show_all(dlg);
803 }
804 
series_view_format_dialog(windata_t * vwin)805 void series_view_format_dialog (windata_t *vwin)
806 {
807     static series_view static_sview;
808     series_view *sview;
809 
810     if (vwin->role == SUMMARY) {
811 	static int initted;
812 
813 	if (!initted) {
814 	    series_view_init(&static_sview);
815 	    initted = 1;
816 	}
817 	sview = &static_sview;
818     } else {
819 	sview = (series_view *) vwin->data;
820 
821 	if (series_view_allocate(sview)) {
822 	    return;
823 	}
824     }
825 
826     real_view_format_dialog(vwin, sview);
827 }
828