supply g_memdup2() for glib before 2.68.
[pspp] / src / ui / gui / psppire-val-chooser.c
index 605cea3303766c36f7c70acfae20d33a36cbad54..543fb3f246ab7a9160316763e1519a3aece260cf 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2011  Free Software Foundation
+   Copyright (C) 2011, 2014, 2022  Free Software Foundation
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include <config.h>
 
+#include <float.h>
 #include <gtk/gtk.h>
+#include "dialog-common.h"
 #include "psppire-val-chooser.h"
 
 #include "libpspp/str.h"
-
+#include "ui/gui/glibfix.h"
 
 #include "ui/syntax-gen.h"
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-static void psppire_val_chooser_base_finalize (PsppireValChooserClass *, gpointer);
-static void psppire_val_chooser_base_init     (PsppireValChooserClass *class);
 static void psppire_val_chooser_class_init    (PsppireValChooserClass *class);
 static void psppire_val_chooser_init          (PsppireValChooser      *vc);
 
 static void psppire_val_chooser_realize       (GtkWidget *w);
 
-
-
-GType
-psppire_val_chooser_get_type (void)
-{
-  static GType psppire_val_chooser_type = 0;
-
-  if (!psppire_val_chooser_type)
-    {
-      static const GTypeInfo psppire_val_chooser_info =
-      {
-       sizeof (PsppireValChooserClass),
-       (GBaseInitFunc) psppire_val_chooser_base_init,
-        (GBaseFinalizeFunc) psppire_val_chooser_base_finalize,
-       (GClassInitFunc)psppire_val_chooser_class_init,
-       (GClassFinalizeFunc) NULL,
-       NULL,
-        sizeof (PsppireValChooser),
-       0,
-       (GInstanceInitFunc) psppire_val_chooser_init,
-      };
-
-      psppire_val_chooser_type =
-       g_type_register_static (GTK_TYPE_FRAME, "PsppireValChooser",
-                               &psppire_val_chooser_info, 0);
-    }
-
-  return psppire_val_chooser_type;
-}
-
+G_DEFINE_TYPE (PsppireValChooser, psppire_val_chooser, GTK_TYPE_FRAME)
 
 static void
 psppire_val_chooser_finalize (GObject *object)
@@ -81,7 +52,7 @@ enum
 };
 
 
-enum 
+enum
   {
     VC_VALUE,
     VC_SYSMIS,
@@ -114,7 +85,7 @@ psppire_val_chooser_set_property (GObject         *object,
       gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_SYSMIS].rb), !vr->input_var_is_string);
       gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_MISSING].rb), !vr->input_var_is_string);
       gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_RANGE].rb), !vr->input_var_is_string);
-      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_LOW_UP].rb), !vr->input_var_is_string);      
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_LOW_UP].rb), !vr->input_var_is_string);
       gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_HIGH_DOWN].rb), !vr->input_var_is_string);
       break;
     default:
@@ -143,6 +114,7 @@ psppire_val_chooser_get_property (GObject         *object,
       break;
     case PROP_IS_STRING:
       g_value_set_boolean (value, vr->input_var_is_string);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -156,6 +128,8 @@ static void
 psppire_val_chooser_class_init (PsppireValChooserClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = psppire_val_chooser_finalize;
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
   GParamSpec *is_string_spec =
@@ -190,24 +164,6 @@ psppire_val_chooser_class_init (PsppireValChooserClass *class)
 }
 
 
-static void
-psppire_val_chooser_base_init (PsppireValChooserClass *class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-
-  object_class->finalize = psppire_val_chooser_finalize;
-}
-
-
-
-static void
-psppire_val_chooser_base_finalize (PsppireValChooserClass *class,
-                                gpointer class_data)
-{
-
-}
-
-
 /* Set the focus of B to follow the sensitivity of A */
 static void
 focus_follows_sensitivity (GtkWidget *a, GParamSpec *pspec, GtkWidget *b)
@@ -235,7 +191,7 @@ static void simple_set (PsppireValChooser *vr, struct old_value *ov, const struc
 {
   const gchar *text = gtk_entry_get_text (rw->e1);
 
-  if ( vr->input_var_is_string)
+  if (vr->input_var_is_string)
     {
       ov->type = OV_STRING;
       ov->v.s = g_strdup (text);
@@ -250,7 +206,7 @@ static void simple_set (PsppireValChooser *vr, struct old_value *ov, const struc
 static void lo_up_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets  *rw)
 {
   const gchar *text = gtk_entry_get_text (rw->e1);
-  
+
   ov->type = OV_LOW_UP;
   ov->v.range[1] = g_strtod (text, 0);
 }
@@ -259,7 +215,7 @@ static void lo_up_set (PsppireValChooser *vr, struct old_value *ov, const struct
 static void hi_down_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
 {
   const gchar *text = gtk_entry_get_text (rw->e1);
-  
+
   ov->type = OV_HIGH_DOWN;
   ov->v.range[0] = g_strtod (text, 0);
 }
@@ -287,14 +243,14 @@ static void range_set (PsppireValChooser *vr, struct old_value *ov, const struct
 
   ov->type = OV_RANGE;
   ov->v.range[0] = g_strtod (text, 0);
-  
+
   text = gtk_entry_get_text (rw->e2);
   ov->v.range[1] = g_strtod (text, 0);
 }
 
 static GtkWidget * range_entry (struct layout *l, struct range_widgets *rw)
 {
-  GtkWidget *vbox = gtk_vbox_new (3, FALSE);
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
   GtkWidget *entrylo = gtk_entry_new ();
   GtkWidget *label = gtk_label_new (_("through"));
   GtkWidget *entryhi = gtk_entry_new ();
@@ -302,7 +258,11 @@ static GtkWidget * range_entry (struct layout *l, struct range_widgets *rw)
   rw->e1 = GTK_ENTRY (entrylo);
   rw->e2 = GTK_ENTRY (entryhi);
 
-  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+  g_object_set (G_OBJECT (label),
+               "valign", GTK_ALIGN_CENTER,
+               "halign", GTK_ALIGN_START,
+               NULL);
+
 
   g_signal_connect (vbox, "notify::sensitive", G_CALLBACK (focus_follows_sensitivity), entrylo);
 
@@ -323,7 +283,7 @@ static GtkWidget * simple_entry (struct layout *l, struct range_widgets *rw)
 }
 
 
-static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]= 
+static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]=
   {
     {N_("_Value:"),                    simple_entry, simple_set },
     {N_("_System Missing"),            NULL,         sysmis_set },
@@ -334,24 +294,18 @@ static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]=
     {N_("_All other values"),          NULL,         else_set   }
   };
 
-static void
-set_sensitivity_from_toggle (GtkToggleButton *togglebutton,  GtkWidget *w)
-{
-  gboolean active = gtk_toggle_button_get_active (togglebutton);
-
-  gtk_widget_set_sensitive (w, active);
-}
-
 static void
 psppire_val_chooser_init (PsppireValChooser *vr)
 {
   gint i;
-  GtkWidget *aln = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
-  GtkWidget *table = gtk_table_new (11, 2, FALSE);
+  GtkWidget *grid = gtk_grid_new ();
   GSList *group = NULL;
   gint row = 0;
 
-  gtk_alignment_set_padding (GTK_ALIGNMENT (aln), 0, 0, 5, 5);
+  g_object_set (G_OBJECT (grid),
+               "margin-start", 5,
+               "margin-end", 5,
+               NULL);
 
   vr->input_var_is_string = FALSE;
 
@@ -361,23 +315,28 @@ psppire_val_chooser_init (PsppireValChooser *vr)
       vr->rw[i].label = GTK_LABEL (gtk_label_new (gettext (l->label)));
       gtk_label_set_use_underline (vr->rw[i].label, TRUE);
       vr->rw[i].rb = GTK_TOGGLE_BUTTON (gtk_radio_button_new (group));
-      gtk_label_set_mnemonic_widget (vr->rw[i].label, vr->rw[i].rb);
+      gtk_label_set_mnemonic_widget (vr->rw[i].label, GTK_WIDGET (vr->rw[i].rb));
 
-      gtk_misc_set_alignment (GTK_MISC (vr->rw[i].label), 0, 0.5);
+      g_object_set (G_OBJECT (vr->rw[i].label),
+                   "valign", GTK_ALIGN_CENTER,
+                   "halign", GTK_ALIGN_START,
+                   NULL);
 
       group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (vr->rw[i].rb));
 
       /* Attach the buttons */
-      gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (vr->rw[i].rb),
-                       0, 1,   row, row + 1,
-                       0, GTK_EXPAND | GTK_FILL,
-                       0, 0);
+      gtk_grid_attach (GTK_GRID (grid), GTK_WIDGET (vr->rw[i].rb),
+                      0, row, 1, 1);
+
+      gtk_widget_set_hexpand (GTK_WIDGET (vr->rw[i].rb), FALSE);
 
       /* Attach the labels */
-      gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (vr->rw[i].label),
-                       1, 2,   row, row + 1,
-                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
-                       0, 0);
+      gtk_grid_attach (GTK_GRID (grid), GTK_WIDGET (vr->rw[i].label),
+                       1, row, 1, 1);
+
+      gtk_widget_set_hexpand (GTK_WIDGET (vr->rw[i].label), TRUE);
+
+
       ++row;
 
       if (l->fill)
@@ -386,8 +345,10 @@ psppire_val_chooser_init (PsppireValChooser *vr)
 
          gtk_widget_set_sensitive (fill, FALSE);
 
-         gtk_table_attach_defaults (GTK_TABLE (table), fill, 1, 2,
-                                row, row + 1);
+         gtk_grid_attach (GTK_GRID (grid), fill, 1, row, 1, 1);
+
+         gtk_widget_set_hexpand (fill, TRUE);
+
          ++row;
 
          g_signal_connect (vr->rw[i].rb, "toggled", G_CALLBACK (set_sensitivity_from_toggle), fill);
@@ -396,21 +357,11 @@ psppire_val_chooser_init (PsppireValChooser *vr)
 
   gtk_frame_set_shadow_type (GTK_FRAME (vr), GTK_SHADOW_ETCHED_IN);
 
-  gtk_container_add (GTK_CONTAINER (aln), table);
-  gtk_container_add (GTK_CONTAINER (vr), aln);
+  gtk_container_add (GTK_CONTAINER (vr), grid);
 
-  gtk_widget_show_all (aln);
-}
-
-
-GtkWidget*
-psppire_val_chooser_new (void)
-{
-  return GTK_WIDGET (g_object_new (psppire_val_chooser_get_type (), NULL));
+  gtk_widget_show_all (grid);
 }
 
-
-
 static void
 psppire_val_chooser_realize (GtkWidget *w)
 {
@@ -433,9 +384,9 @@ psppire_val_chooser_realize (GtkWidget *w)
 static struct old_value *
 old_value_copy (struct old_value *ov)
 {
-  struct old_value *copy = g_memdup (ov, sizeof (*copy));
+  struct old_value *copy = g_memdup2 (ov, sizeof (*copy));
 
-  if ( ov->type == OV_STRING )
+  if (ov->type == OV_STRING)
     copy->v.s = g_strdup (ov->v.s);
 
   return copy;
@@ -459,7 +410,7 @@ old_value_to_string (const GValue *src, GValue *dest)
     {
     case OV_NUMERIC:
       {
-       gchar *text = g_strdup_printf ("%g", ov->v.v);
+       gchar *text = g_strdup_printf ("%.*g", DBL_DIG + 1, ov->v.v);
        g_value_set_string (dest, text);
        g_free (text);
       }
@@ -483,10 +434,10 @@ old_value_to_string (const GValue *src, GValue *dest)
 
        g_unichar_to_utf8 (0x2013, en_dash);
 
-       text = g_strdup_printf ("%g %s %g",
-                                      ov->v.range[0],
-                                      en_dash,
-                                      ov->v.range[1]);
+       text = g_strdup_printf ("%.*g %s %.*g",
+                                DBL_DIG + 1, ov->v.range[0],
+                                en_dash,
+                                DBL_DIG + 1, ov->v.range[1]);
        g_value_set_string (dest, text);
        g_free (text);
       }
@@ -498,9 +449,9 @@ old_value_to_string (const GValue *src, GValue *dest)
 
        g_unichar_to_utf8 (0x2013, en_dash);
 
-       text = g_strdup_printf ("LOWEST %s %g",
+       text = g_strdup_printf ("LOWEST %s %.*g",
                                en_dash,
-                               ov->v.range[1]);
+                               DBL_DIG + 1, ov->v.range[1]);
 
        g_value_set_string (dest, text);
        g_free (text);
@@ -513,8 +464,8 @@ old_value_to_string (const GValue *src, GValue *dest)
 
        g_unichar_to_utf8 (0x2013, en_dash);
 
-       text = g_strdup_printf ("%g %s HIGHEST",
-                               ov->v.range[0],
+       text = g_strdup_printf ("%.*g %s HIGHEST",
+                               DBL_DIG + 1, ov->v.range[0],
                                en_dash);
 
        g_value_set_string (dest, text);
@@ -533,7 +484,7 @@ old_value_get_type (void)
 {
   static GType t = 0;
 
-  if (t == 0 )
+  if (t == 0)
     {
       t = g_boxed_type_register_static  ("psppire-recode-old-values",
                                         (GBoxedCopyFunc) old_value_copy,
@@ -550,46 +501,46 @@ old_value_get_type (void)
 
 /* Generate a syntax fragment for NV and append it to STR */
 void
-old_value_append_syntax (GString *str, const struct old_value *ov)
+old_value_append_syntax (struct string *str, const struct old_value *ov)
 {
   switch (ov->type)
     {
     case OV_NUMERIC:
-      g_string_append_printf (str, "%g", ov->v.v);
+      ds_put_c_format (str, "%.*g", DBL_DIG + 1, ov->v.v);
       break;
     case OV_STRING:
       {
        struct string ds = DS_EMPTY_INITIALIZER;
        syntax_gen_string (&ds, ss_cstr (ov->v.s));
-       g_string_append (str, ds_cstr (&ds));
+       ds_put_cstr (str, ds_cstr (&ds));
        ds_destroy (&ds);
       }
       break;
     case OV_MISSING:
-      g_string_append (str, "MISSING");
+      ds_put_cstr (str, "MISSING");
       break;
     case OV_SYSMIS:
-      g_string_append (str, "SYSMIS");
+      ds_put_cstr (str, "SYSMIS");
       break;
     case OV_ELSE:
-      g_string_append (str, "ELSE");
+      ds_put_cstr (str, "ELSE");
       break;
     case OV_RANGE:
-      g_string_append_printf (str, "%g THRU %g",
-                             ov->v.range[0],
-                             ov->v.range[1]);
+      ds_put_c_format (str, "%.*g THRU %.*g",
+                       DBL_DIG + 1, ov->v.range[0],
+                       DBL_DIG + 1, ov->v.range[1]);
       break;
     case OV_LOW_UP:
-      g_string_append_printf (str, "LOWEST THRU %g",
-                             ov->v.range[1]);
+      ds_put_c_format (str, "LOWEST THRU %.*g",
+                       DBL_DIG + 1, ov->v.range[1]);
       break;
     case OV_HIGH_DOWN:
-      g_string_append_printf (str, "%g THRU HIGHEST",
-                             ov->v.range[0]);
+      ds_put_c_format (str, "%.*g THRU HIGHEST",
+                       DBL_DIG + 1, ov->v.range[0]);
       break;
     default:
       g_warning ("Invalid type in old recode value");
-      g_string_append (str, "???");
+      ds_put_cstr (str, "???");
       break;
     };
 }
@@ -604,13 +555,12 @@ psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov)
 
   for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
     {
-      if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (vr->rw[i].rb)))
+      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (vr->rw[i].rb)))
        {
+         range_opt[i].set (vr, ov, &vr->rw[i]);
          break;
        }
     }
-
-  range_opt[i].set (vr, ov, &vr->rw[i]);
 }
 
 /* This might need to be changed to something less naive.
@@ -619,7 +569,7 @@ psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov)
 static gchar *
 num_to_string (gdouble x)
 {
-  return g_strdup_printf ("%g", x);
+  return g_strdup_printf ("%.*g", DBL_DIG + 1, x);
 }
 
 
@@ -628,7 +578,7 @@ void
 psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *ov)
 {
   gint i;
-  if ( !ov )
+  if (!ov)
     return;
 
   for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
@@ -646,14 +596,14 @@ psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *o
       gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
       gtk_entry_set_text (vr->rw[0].e1, ov->v.s);
       break;
-      
+
     case OV_NUMERIC:
       {
        gchar *str;
        gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
-       
+
        str = num_to_string (ov->v.v);
-       
+
        gtk_entry_set_text (vr->rw[0].e1, str);
        g_free (str);
       }