Fixed a number of warnings.
[pspp-builds.git] / src / ui / gui / var-type-dialog.c
1 /* 
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2005  Free Software Foundation
4     Written by John Darrington
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19     02110-1301, USA. */
20
21
22 /*  This module describes the behaviour of the Variable Type dialog box used
23     for inputing the variable type in the var sheet */
24
25 #include <gtk/gtk.h>
26 #include <glade/glade.h>
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "var-type-dialog.h"
32
33 #include "psppire-variable.h"
34 #include "helper.h"
35
36 #include <data/variable.h>
37 #include <data/settings.h>
38
39
40 struct tgs
41 {
42   struct var_type_dialog *dialog;
43   gint button;
44 };
45
46
47 struct format_opt {
48   gchar desc[18];
49   struct fmt_spec spec;
50 };
51
52
53 static const struct format_opt format_option[] =
54   {
55     { "dd-mmm-yyyy", {FMT_DATE,  11, 0} },
56     { "dd-mmm-yy",   {FMT_DATE,   9, 0} },
57     { "mm/dd/yyyy",  {FMT_ADATE, 10, 0} },
58     { "mm/dd/yy",    {FMT_ADATE, 8, 0} },
59     { "dd.mm.yyyy",  {FMT_EDATE, 10, 0} },
60     { "dd.mm.yy",    {FMT_EDATE, 8, 0} },
61     { "yyyy/mm/dd",  {FMT_SDATE, 10, 0} },
62     { "yy/mm/dd",    {FMT_SDATE, 8, 0} },
63     { "yyddd",       {FMT_JDATE, 5, 0} },
64     { "yyyyddd",     {FMT_JDATE, 7, 0} },
65     { "q Q yyyy",    {FMT_QYR, 8, 0} },
66     { "q Q yy",      {FMT_QYR, 6, 0} },
67     { "mmm yyyy",    {FMT_MOYR, 8, 0} },
68     { "mmm yy",      {FMT_MOYR, 6, 0} },
69     { "dd WK yyyy",  {FMT_WKYR, 10, 0} },
70     { "dd WK yy",    {FMT_WKYR, 8, 0} },
71     { "dd-mmm-yyyy HH:MM", {FMT_DATETIME, 17, 0}}
72   };
73
74
75 static const struct fmt_spec dollar_format[] = 
76   {
77     {FMT_DOLLAR, 2, 0},
78     {FMT_DOLLAR, 3, 0},
79     {FMT_DOLLAR, 4, 0},
80     {FMT_DOLLAR, 7, 2},
81     {FMT_DOLLAR, 6, 0},
82     {FMT_DOLLAR, 9, 2},
83     {FMT_DOLLAR, 8, 0},
84     {FMT_DOLLAR, 11, 2},
85     {FMT_DOLLAR, 12, 0},
86     {FMT_DOLLAR, 15, 2},
87     {FMT_DOLLAR, 16, 0},
88     {FMT_DOLLAR, 19, 2}
89   };
90
91 static const int cc_format[] = 
92   {
93     FMT_CCA, 
94     FMT_CCB, 
95     FMT_CCC, 
96     FMT_CCD, 
97     FMT_CCE, 
98   };
99
100
101 static void select_treeview_from_format
102  (GtkTreeView *treeview, const struct fmt_spec *fmt);
103
104 static void select_treeview_from_format_type(GtkTreeView *treeview, 
105                                              const int fmt_type);
106
107
108 /* callback for when any of the radio buttons are toggled */
109 static void        
110 on_toggle_1(GtkToggleButton *togglebutton, gpointer user_data)
111 {
112   struct tgs *tgs = user_data;
113
114   if ( gtk_toggle_button_get_active(togglebutton) == FALSE) 
115     return ;
116
117   tgs->dialog->active_button = tgs->button;
118 }
119
120 static void update_width_decimals(const struct var_type_dialog *dialog);
121
122 #define force_max(x, val) if (x > val) x = val
123
124 /* 
125    Set the local format from the variable
126    and force them to have sensible values */
127 static void
128 set_local_width_decimals(struct var_type_dialog *dialog)
129 {
130   dialog->fmt_l = * psppire_variable_get_write_spec(dialog->pv);
131
132   switch (dialog->active_button) 
133     {
134     case BUTTON_STRING:
135       force_max( dialog->fmt_l.w, 255);
136       break;
137     default:
138       force_max( dialog->fmt_l.w, 40);
139       force_max( dialog->fmt_l.d, 16);
140       break;
141     }
142 }
143
144
145 /* callback for when any of the radio buttons are toggled */
146 static void        
147 on_toggle_2(GtkToggleButton *togglebutton, gpointer user_data)
148 {
149   struct var_type_dialog *dialog = user_data;
150   if ( gtk_toggle_button_get_active(togglebutton) == FALSE) 
151     {
152       switch (dialog->active_button) 
153         {
154         case BUTTON_DATE:
155           gtk_widget_hide(dialog->date_format_list);
156           break;
157         case BUTTON_CUSTOM:
158           gtk_widget_hide(dialog->custom_currency_hbox);
159           break;
160         case BUTTON_DOLLAR:
161           gtk_widget_hide(dialog->dollar_window);
162           break;
163         case BUTTON_STRING:
164           gtk_widget_show(dialog->label_decimals);
165           gtk_widget_show(dialog->entry_decimals);
166           break;
167         }
168       return ;
169     }
170
171   set_local_width_decimals(dialog);
172   update_width_decimals(dialog);
173
174   switch (dialog->active_button) 
175     {
176     case BUTTON_STRING:
177       gtk_widget_show(dialog->width_decimals);
178       gtk_widget_hide(dialog->label_decimals);
179       gtk_widget_hide(dialog->entry_decimals);
180       break;
181     case BUTTON_DATE:
182       select_treeview_from_format(dialog->date_format_treeview,
183                                   &format_option[0].spec);
184       gtk_widget_hide(dialog->width_decimals);
185       gtk_widget_show(dialog->date_format_list);
186       break;
187     case BUTTON_DOLLAR:
188       select_treeview_from_format(dialog->dollar_treeview,
189                                   &dollar_format[0]);
190       gtk_widget_show(dialog->dollar_window);
191       gtk_widget_show_all(dialog->width_decimals);
192       break;
193     case BUTTON_CUSTOM:
194       select_treeview_from_format_type(dialog->custom_treeview,
195                                   cc_format[0]);
196
197       gtk_widget_show(dialog->width_decimals);
198       gtk_widget_show(dialog->custom_currency_hbox);
199       break;
200     default:
201       gtk_widget_show_all(dialog->width_decimals);
202       break;
203     }
204 }
205
206
207
208 static gint on_var_type_ok_clicked(GtkWidget *w, gpointer data);
209
210 #define LEN 20
211
212 /* return a string of the form "$#,###.##" according to FMT. 
213    FMT must be of type FMT_DOLLAR
214  */
215 static const gchar *
216 dollar_format_template(const struct fmt_spec *fmt)
217 {
218   static gchar buf[LEN];
219   g_assert( fmt->type == FMT_DOLLAR);
220
221   {
222     gint c ;
223     gint int_part = fmt->w - fmt->d;
224     if ( fmt->d > 0 ) --int_part;
225     g_assert(int_part > 0);
226
227     g_strlcpy(buf, "$", LEN);
228
229     c = int_part - 1;
230     while(c > 0)
231       {
232         g_strlcat(buf, "#", LEN);
233         if(--c % 4 == 0 && c > 0 ) 
234           {
235             g_strlcat(buf, ",", LEN);
236             --c;
237           }
238       }
239     if ( fmt->d > 0 ) 
240       {
241         g_strlcat(buf, ".", LEN);
242         for ( c = 0 ; c < fmt->d ; ++c ) 
243           g_strlcat(buf, "#", LEN);
244       }
245   }
246
247   return buf;
248 }
249
250 static void
251 add_to_group(GtkWidget *w, gpointer data)
252 {
253   GtkSizeGroup *sg = data;
254   
255   gtk_size_group_add_widget(sg, w);
256 }
257
258 /* Set the local width and decimals entry boxes to reflec the local format */
259 static void
260 update_width_decimals(const struct var_type_dialog *dialog)
261 {
262   gchar *text;
263   g_assert(dialog);
264
265   text = g_strdup_printf("%d", dialog->fmt_l.w);
266   gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), text);
267   g_free(text);
268
269   text = g_strdup_printf("%d", dialog->fmt_l.d);
270   gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), text);
271   g_free(text);
272 }
273
274 /* Callback for when the custom treeview row is changed.
275    It sets dialog box to reflect the selected format */
276 static void
277 preview_custom(GtkWidget *w, gpointer data)
278 {
279   const gchar *text ;
280
281   struct var_type_dialog *dialog = data;
282
283   if ( dialog->active_button != BUTTON_CUSTOM ) 
284     return;
285
286   text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_decimals));
287   dialog->fmt_l.d = atoi(text);
288
289   text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_width));
290   dialog->fmt_l.w = atoi(text);
291
292   if ( ! check_output_specifier(&dialog->fmt_l, 0))
293     {
294       gtk_label_set_text(GTK_LABEL(dialog->label_psample), "---");
295       gtk_label_set_text(GTK_LABEL(dialog->label_nsample), "---");
296     }
297   else
298     {
299       gchar *sample_text;
300       union value v;
301       v.f = 1234.56;
302
303       sample_text = value_to_text(v, dialog->fmt_l);
304       gtk_label_set_text(GTK_LABEL(dialog->label_psample), sample_text);
305       g_free(sample_text);
306
307       v.f = -v.f;
308       sample_text = value_to_text(v, dialog->fmt_l);
309       gtk_label_set_text(GTK_LABEL(dialog->label_nsample), sample_text);
310       g_free(sample_text);
311     }
312 }
313
314 /* Callback for when a treeview row is changed.
315    It sets the fmt_l_spec to reflect the selected format */
316 static void
317 set_format_from_treeview(GtkTreeView *treeview, gpointer data)
318 {
319   struct var_type_dialog *dialog = data;
320   GtkTreeIter iter ;
321   GValue the_value = {0}; 
322
323   GtkTreeSelection* sel =  gtk_tree_view_get_selection(treeview);
324
325   GtkTreeModel * model  = gtk_tree_view_get_model(treeview);
326
327   gtk_tree_selection_get_selected (sel, &model, &iter);
328
329   gtk_tree_model_get_value(model, &iter, 1, &the_value);
330
331   dialog->fmt_l = *(struct fmt_spec *) g_value_get_pointer(&the_value);
332 }
333
334
335 /* Callback for when a treeview row is changed.
336    It sets the type of the fmt_l to reflect the selected type */
337 static void
338 set_format_type_from_treeview(GtkTreeView *treeview, gpointer data)
339 {
340   static struct fmt_spec custom_format = {0,0,0};
341   struct var_type_dialog *dialog = data;
342   GtkTreeIter iter ;
343   GValue the_value = {0}; 
344
345   GtkTreeSelection* sel =  gtk_tree_view_get_selection(treeview);
346
347   GtkTreeModel * model  = gtk_tree_view_get_model(treeview);
348
349   gtk_tree_selection_get_selected (sel, &model, &iter);
350
351   gtk_tree_model_get_value(model, &iter, 1, &the_value);
352
353   dialog->fmt_l = custom_format;
354   dialog->fmt_l.type = *(int*) g_value_get_pointer(&the_value);
355
356 }
357
358
359
360
361 /* Create the structure from the XML definitions */
362 struct var_type_dialog *
363 var_type_dialog_create(GladeXML *xml)
364 {
365   gint i;
366   struct var_type_dialog *dialog = g_malloc(sizeof(struct var_type_dialog));
367
368   g_assert(xml);
369
370   dialog->window = get_widget_assert(xml,"var_type_dialog");
371
372   gtk_window_set_transient_for(GTK_WINDOW(dialog->window), 
373                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
374
375   dialog->radioButton[BUTTON_NUMERIC] = 
376     get_widget_assert(xml,"radiobutton1");
377   dialog->radioButton[BUTTON_COMMA] =   
378     get_widget_assert(xml,"radiobutton2");
379   dialog->radioButton[BUTTON_DOT] =     
380     get_widget_assert(xml,"radiobutton3");
381   dialog->radioButton[BUTTON_SCIENTIFIC] = 
382     get_widget_assert(xml,"radiobutton4");
383   dialog->radioButton[BUTTON_DATE] =   
384     get_widget_assert(xml,"radiobutton5");
385   dialog->radioButton[BUTTON_DOLLAR] = 
386     get_widget_assert(xml,"radiobutton6");
387   dialog->radioButton[BUTTON_CUSTOM] = 
388     get_widget_assert(xml,"radiobutton7");
389   dialog->radioButton[BUTTON_STRING] = 
390     get_widget_assert(xml,"radiobutton8");
391
392
393   dialog->date_format_list = get_widget_assert(xml, "scrolledwindow4");
394   dialog->width_decimals = get_widget_assert(xml, "width_decimals");
395   dialog->label_decimals = get_widget_assert(xml, "decimals_label");
396   dialog->entry_decimals = get_widget_assert(xml, "decimals_entry");
397
398   dialog->label_psample = get_widget_assert(xml, "psample_label");
399   dialog->label_nsample = get_widget_assert(xml, "nsample_label");
400
401
402   dialog->entry_width = get_widget_assert(xml,"width_entry");
403
404   dialog->custom_currency_hbox = get_widget_assert(xml,
405                                                    "custom_currency_hbox");
406
407   dialog->dollar_window = get_widget_assert(xml, "dollar_window");
408   dialog->dollar_treeview = 
409     GTK_TREE_VIEW(get_widget_assert(xml, "dollar_treeview"));
410
411   dialog->custom_treeview = 
412     GTK_TREE_VIEW(get_widget_assert(xml, "custom_treeview"));
413
414
415   dialog->ok = get_widget_assert(xml,"var_type_ok");
416
417
418   {
419   GtkTreeIter iter;
420   GtkListStore *list_store ;
421
422   GtkTreeViewColumn *column;
423   GtkCellRenderer *renderer ;
424
425   static struct tgs tgs[num_BUTTONS];
426   /* The "middle_box" is a vbox with serveral children.
427      However only one child is ever shown at a time.
428      We need to make sure that they all have the same width, to avoid
429      upleasant resizing effects */
430   GtkSizeGroup *sizeGroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
431
432   gtk_container_foreach(GTK_CONTAINER(get_widget_assert(xml, "middle_box")), 
433                         add_to_group, sizeGroup);
434
435
436   for (i = 0 ; i < num_BUTTONS; ++i ) 
437     {
438       tgs[i].dialog = dialog;
439       tgs[i].button = i;
440       g_signal_connect(dialog->radioButton[i], "toggled", 
441                        G_CALLBACK(on_toggle_1), &tgs[i]);
442
443       g_signal_connect(dialog->radioButton[i], "toggled", 
444                        G_CALLBACK(on_toggle_2), dialog);
445     }
446
447   /* Populate the date format tree view */
448   dialog->date_format_treeview = GTK_TREE_VIEW(get_widget_assert(xml, 
449                                               "date_format_list_view"));
450
451   renderer = gtk_cell_renderer_text_new();
452   
453   column = gtk_tree_view_column_new_with_attributes ("Title",
454                                                      renderer,
455                                                      "text",
456                                                      0,
457                                                      NULL);
458
459   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->date_format_treeview), 
460                                column);
461
462
463   list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
464
465   for ( i = 0 ; i < sizeof(format_option) / sizeof(format_option[0]) ; ++i ) 
466     {
467       gtk_list_store_append (list_store, &iter);
468       gtk_list_store_set (list_store, &iter,
469                           0, format_option[i].desc,
470                           1, &format_option[i].spec,
471                           -1);
472     }
473
474   gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->date_format_treeview), 
475                           GTK_TREE_MODEL(list_store));
476
477   g_object_unref(list_store);
478
479   g_signal_connect(GTK_OBJECT(dialog->date_format_treeview), "cursor-changed",
480                    GTK_SIGNAL_FUNC(set_format_from_treeview), dialog);
481
482
483   /* populate the dollar treeview */
484
485   renderer = gtk_cell_renderer_text_new();
486   
487   column = gtk_tree_view_column_new_with_attributes ("Title",
488                                                      renderer,
489                                                      "text",
490                                                      0,
491                                                      NULL);
492
493   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->dollar_treeview), 
494                                column);
495
496
497   list_store = gtk_list_store_new (2, G_TYPE_STRING, 
498                                                  G_TYPE_POINTER);
499
500   for ( i = 0 ; i < sizeof(dollar_format)/sizeof(dollar_format[0]) ; ++i ) 
501     {
502       gtk_list_store_append (list_store, &iter);
503       gtk_list_store_set (list_store, &iter,
504                           0, dollar_format_template(&dollar_format[i]),
505                           1, &dollar_format[i],
506                           -1);
507     }
508
509   gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->dollar_treeview), 
510                           GTK_TREE_MODEL(list_store));
511
512   g_object_unref(list_store);
513
514   g_signal_connect(GTK_OBJECT(dialog->dollar_treeview), 
515                    "cursor-changed",
516                    GTK_SIGNAL_FUNC(set_format_from_treeview), dialog);
517
518   g_signal_connect_swapped(GTK_OBJECT(dialog->dollar_treeview), 
519                    "cursor-changed",
520                    GTK_SIGNAL_FUNC(update_width_decimals), dialog);
521
522
523   /* populate the custom treeview */
524
525   renderer = gtk_cell_renderer_text_new();
526   
527   column = gtk_tree_view_column_new_with_attributes ("Title",
528                                                      renderer,
529                                                      "text",
530                                                      0,
531                                                      NULL);
532
533   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->custom_treeview), 
534                                column);
535
536
537   list_store = gtk_list_store_new (2, G_TYPE_STRING, 
538                                                  G_TYPE_POINTER);
539
540   for ( i = 0 ; i < CC_CNT ; ++i ) 
541     {
542       gchar text[4];
543       g_snprintf(text, 4, "CC%c", 'A' + i);
544       gtk_list_store_append (list_store, &iter);
545       gtk_list_store_set (list_store, &iter,
546                           0, text,
547                           1, &cc_format[i],
548                           -1);
549     }
550
551   gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->custom_treeview), 
552                           GTK_TREE_MODEL(list_store));
553
554   g_object_unref(list_store);
555
556
557   g_signal_connect(GTK_OBJECT(dialog->custom_treeview), 
558                    "cursor-changed",
559                    GTK_SIGNAL_FUNC(set_format_type_from_treeview), dialog);
560
561
562   g_signal_connect(GTK_OBJECT(dialog->custom_treeview), 
563                    "cursor-changed",
564                    GTK_SIGNAL_FUNC(preview_custom), dialog);
565
566
567   g_signal_connect(GTK_OBJECT(dialog->entry_width), 
568                    "changed",
569                    GTK_SIGNAL_FUNC(preview_custom), dialog);
570
571
572   g_signal_connect(GTK_OBJECT(dialog->entry_decimals), 
573                    "changed",
574                    GTK_SIGNAL_FUNC(preview_custom), dialog);
575
576
577   /* Connect the OK button */
578   g_signal_connect(dialog->ok, "clicked", G_CALLBACK(on_var_type_ok_clicked), 
579                    dialog);
580
581
582   }
583
584   return dialog;
585 }
586
587
588 /* Set a particular button to be active */
589 void
590 var_type_dialog_set_active_button(struct var_type_dialog *dialog, gint b)
591 {
592   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radioButton[b]),
593                                TRUE);
594   dialog->active_button = b;
595 }
596
597
598
599 /* Set the TREEVIEW list cursor to the item described by FMT */
600 static void
601 select_treeview_from_format(GtkTreeView *treeview, const struct fmt_spec *fmt)
602 {
603   GtkTreePath *path ;
604
605   /*
606     We do this with a linear search through the model --- hardly 
607     efficient, but the list is short ... */
608   GtkTreeIter iter;
609
610   GtkTreeModel * model  = gtk_tree_view_get_model(treeview);
611
612   gboolean success;
613   for (success = gtk_tree_model_get_iter_first(model, &iter);
614        success;
615        success = gtk_tree_model_iter_next(model, &iter))
616     {
617       const struct fmt_spec *spec;
618
619       GValue value = {0};
620
621       gtk_tree_model_get_value(model, &iter, 1, &value);
622           
623       spec = g_value_get_pointer(&value);
624
625       if ( 0 == memcmp(spec, fmt, sizeof (struct fmt_spec)))
626         {
627           break;
628         }
629     }
630         
631   path = gtk_tree_model_get_path(model, &iter);
632   if ( path ) 
633     {
634       gtk_tree_view_set_cursor(treeview, path, 0, 0);
635       gtk_tree_path_free(path);
636     }
637   else
638     g_warning("Unusual date format: %s\n", fmt_to_string(fmt));
639
640 }
641
642
643 /* Set the TREEVIEW list cursor to the item described by FMT_TYPE */
644 static void
645 select_treeview_from_format_type(GtkTreeView *treeview, 
646                                  const int fmt_type)
647 {
648   GtkTreePath *path ;
649  
650  /*
651     We do this with a linear search through the model --- hardly 
652     efficient, but the list is short ... */
653   GtkTreeIter iter;
654
655   GtkTreeModel * model  = gtk_tree_view_get_model(treeview);
656
657   gboolean success;
658   for (success = gtk_tree_model_get_iter_first(model, &iter);
659        success;
660        success = gtk_tree_model_iter_next(model, &iter))
661     {
662       int spec ;
663       
664       GValue value = {0};
665
666       gtk_tree_model_get_value(model, &iter, 1, &value);
667           
668       spec = * ((int *) g_value_get_pointer(&value));
669
670       if ( spec == fmt_type)
671         break;
672     }
673         
674   path = gtk_tree_model_get_path(model, &iter);
675   if ( path ) 
676     {
677       gtk_tree_view_set_cursor(treeview, path, 0, 0);
678       gtk_tree_path_free(path);
679     }
680   else
681     g_warning("Unknown custom type  %d\n", fmt_type);
682
683 }
684
685 /* Set up the state of the dialog box to match the variable VAR */
686 static void
687 var_type_dialog_set_state(struct var_type_dialog *dialog)
688 {
689   const struct fmt_spec *write_spec ;
690   GString *str = g_string_new("");
691
692   g_assert(dialog);
693   g_assert(dialog->pv);
694
695   /* Populate width and decimals */
696   write_spec = psppire_variable_get_write_spec(dialog->pv);
697
698   g_string_printf(str, "%d", write_spec->d);
699
700   gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), 
701                      str->str);
702
703   g_string_printf(str, "%d", write_spec->w);
704
705   gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), 
706                      str->str);
707
708   g_string_free(str, TRUE);
709
710   /* Populate the radio button states */
711   switch (write_spec->type)
712     {
713     case FMT_F:
714       var_type_dialog_set_active_button(dialog, BUTTON_NUMERIC);
715       gtk_widget_show_all(dialog->width_decimals);
716       break;
717     case FMT_A:
718       var_type_dialog_set_active_button(dialog, BUTTON_STRING);
719       gtk_widget_hide(dialog->label_decimals);
720       gtk_widget_hide(dialog->entry_decimals);
721       break;
722     case FMT_COMMA:
723       var_type_dialog_set_active_button(dialog, BUTTON_COMMA);
724       gtk_widget_show_all(dialog->width_decimals);
725       break;
726     case FMT_DOT:
727       var_type_dialog_set_active_button(dialog, BUTTON_DOT);
728       gtk_widget_show_all(dialog->width_decimals);
729       break;
730     case FMT_DOLLAR:
731       var_type_dialog_set_active_button(dialog, BUTTON_DOLLAR);
732       gtk_widget_show_all(dialog->width_decimals);
733       
734       select_treeview_from_format(dialog->dollar_treeview, write_spec);
735       break;
736     case FMT_DATE:      
737     case FMT_EDATE:     
738     case FMT_SDATE:     
739     case FMT_ADATE:     
740     case FMT_JDATE:     
741     case FMT_QYR:       
742     case FMT_MOYR:      
743     case FMT_WKYR:      
744     case FMT_DATETIME:  
745     case FMT_TIME:      
746     case FMT_DTIME:     
747     case FMT_WKDAY:     
748     case FMT_MONTH:     
749       var_type_dialog_set_active_button(dialog, BUTTON_DATE);
750       gtk_widget_hide(dialog->width_decimals);
751       gtk_widget_show(dialog->date_format_list);
752       select_treeview_from_format(dialog->date_format_treeview, write_spec);
753       break;
754     case FMT_CCA:
755     case FMT_CCB:
756     case FMT_CCC:
757     case FMT_CCD:
758     case FMT_CCE:
759       var_type_dialog_set_active_button(dialog, BUTTON_CUSTOM);
760       select_treeview_from_format_type(dialog->custom_treeview, 
761                                        write_spec->type);
762       gtk_widget_show_all(dialog->width_decimals);
763       break;
764     default:
765       gtk_widget_show_all(dialog->width_decimals);
766       break;
767     }
768 }
769
770
771 /* Popup the dialog box */
772 void 
773 var_type_dialog_show(struct var_type_dialog *dialog)
774 {
775   var_type_dialog_set_state(dialog);
776
777   gtk_widget_show(dialog->window);
778 }
779
780 /* Fills F with an output format specification with type TYPE, width
781    W, and D decimals. Iff it's a valid format, then return true.
782 */
783 static bool
784 make_output_format_try (struct fmt_spec *f, int type, int w, int d)
785 {
786   f->type = type;
787   f->w = w;
788   f->d = d;
789   return check_output_specifier (f, true);
790 }
791
792
793
794
795 /* Callbacks for the Variable Type Dialog Box */
796
797 /* Callback for when the var type dialog is closed using the OK button. 
798    It sets the appropriate variable accordingly. */
799 static gint
800 on_var_type_ok_clicked(GtkWidget *w, gpointer data)
801 {
802   struct var_type_dialog *dialog = data;
803
804   g_assert(dialog);
805   g_assert(dialog->pv);
806
807   {
808     gint width = atoi(gtk_entry_get_text
809                       (GTK_ENTRY(dialog->entry_width)));
810
811     gint decimals = atoi(gtk_entry_get_text
812                          (GTK_ENTRY(dialog->entry_decimals)));
813
814     gint new_type = NUMERIC;
815     gint new_width = 0;
816     bool result = false;
817     struct fmt_spec spec;
818     switch (dialog->active_button) 
819       {
820       case BUTTON_STRING:
821         new_type = ALPHA;
822         new_width = width;
823         result = make_output_format_try(&spec, FMT_A, width, 0);
824         break;
825       case BUTTON_NUMERIC:
826         result = make_output_format_try(&spec, FMT_F, width, decimals);
827         break;
828       case BUTTON_COMMA:
829         result = make_output_format_try(&spec, FMT_COMMA, width, decimals);
830         break;
831       case BUTTON_DOT:
832         result = make_output_format_try(&spec, FMT_DOT, width, decimals);
833         break;
834       case BUTTON_SCIENTIFIC:
835         result = make_output_format_try(&spec, FMT_E, width, decimals);
836         break;
837       case BUTTON_DATE:
838       case BUTTON_CUSTOM:
839         g_assert(check_output_specifier(&dialog->fmt_l, TRUE));
840         result = memcpy(&spec, &dialog->fmt_l, sizeof(struct fmt_spec));
841         break;
842       case BUTTON_DOLLAR:
843         result = make_output_format_try(&spec, FMT_DOLLAR, width, decimals);
844         break;
845       default:
846         g_print("Unknown variable type: %d\n", dialog->active_button) ;
847         result = false;
848         break;
849       }
850
851     if ( result == true ) 
852       {
853         psppire_variable_set_type(dialog->pv, new_type);
854         psppire_variable_set_width(dialog->pv, new_width);
855         psppire_variable_set_write_spec(dialog->pv, spec);
856         psppire_variable_set_print_spec(dialog->pv, spec);
857       }
858
859   }
860   gtk_widget_hide(dialog->window);
861
862   return FALSE;
863 }
864
865
866
867 gint
868 on_var_type_cancel_clicked(GtkWidget *w,  gpointer data)
869 {
870   gtk_widget_hide(w);
871
872   return FALSE;
873 }
874