PSPPIRE: Avoid some segmentation faults when corrupt data is encountered.
[pspp] / src / ui / gui / psppire-data-store.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2006, 2008, 2009, 2010, 2011, 2012,
3    2013, 2016, 2017  Free Software Foundation
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 #include <config.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <gettext.h>
22 #define _(msgid) gettext (msgid)
23 #define P_(msgid) msgid
24
25 #include <data/datasheet.h>
26 #include <data/data-out.h>
27 #include <data/variable.h>
28
29 #include <ui/gui/psppire-marshal.h>
30
31 #include <pango/pango-context.h>
32
33 #include "psppire-data-store.h"
34 #include <libpspp/i18n.h>
35 #include "helper.h"
36
37 #include <data/dictionary.h>
38 #include <data/missing-values.h>
39 #include <data/value-labels.h>
40 #include <data/data-in.h>
41 #include <data/format.h>
42
43 #include <math/sort.h>
44
45 #include "xalloc.h"
46 #include "xmalloca.h"
47
48 #include "value-variant.h"
49
50 static void psppire_data_store_init            (PsppireDataStore      *data_store);
51 static void psppire_data_store_class_init      (PsppireDataStoreClass *class);
52
53 static void psppire_data_store_finalize        (GObject           *object);
54 static void psppire_data_store_dispose        (GObject           *object);
55
56 static gboolean psppire_data_store_insert_case (PsppireDataStore *ds,
57                                                 struct ccase *cc,
58                                                 casenumber posn);
59
60
61 static gboolean psppire_data_store_data_in (PsppireDataStore *ds,
62                                             casenumber casenum, gint idx,
63                                             struct substring input,
64                                             const struct fmt_spec *fmt);
65
66 static GObjectClass *parent_class = NULL;
67
68
69 enum
70   {
71     ITEMS_CHANGED,
72     CASE_CHANGED,
73     n_SIGNALS
74   };
75
76 static guint signals [n_SIGNALS];
77
78 static gint
79 __tree_model_iter_n_children (GtkTreeModel *tree_model,
80                              GtkTreeIter *iter)
81 {
82   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
83
84   if (store->datasheet == NULL)
85     return 0;
86
87   gint n =  datasheet_get_n_rows (store->datasheet);
88
89   return n;
90 }
91
92 static GtkTreeModelFlags
93 __tree_model_get_flags (GtkTreeModel *model)
94 {
95   g_return_val_if_fail (PSPPIRE_IS_DATA_STORE (model), (GtkTreeModelFlags) 0);
96
97   return GTK_TREE_MODEL_LIST_ONLY;
98 }
99
100 static gint
101 __tree_model_get_n_columns (GtkTreeModel *tree_model)
102 {
103   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
104
105   return psppire_dict_get_var_cnt (store->dict);
106 }
107
108
109 static gboolean
110 __iter_nth_child (GtkTreeModel *tree_model,
111                   GtkTreeIter *iter,
112                   GtkTreeIter *parent,
113                   gint n)
114 {
115   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
116
117   g_assert (parent == NULL);
118   g_return_val_if_fail (store, FALSE);
119
120   if (!store->datasheet || n >= datasheet_get_n_rows (store->datasheet))
121     {
122       iter->stamp = -1;
123       iter->user_data = NULL;
124       return FALSE;
125     }
126
127   iter->user_data = GINT_TO_POINTER (n);
128   iter->stamp = store->stamp;
129
130   return TRUE;
131 }
132
133 /* Set the contents of OUT to reflect the information provided by IN, COL, and
134    ROW, for MODEL.  Returns TRUE if successful. */
135 gboolean
136 psppire_data_store_string_to_value (GtkTreeModel *model, gint col, gint row,
137                                     const gchar *in, GValue *out)
138 {
139   PsppireDataStore *store = PSPPIRE_DATA_STORE (model);
140
141   while (col >= psppire_dict_get_var_cnt (store->dict))
142     {
143       const struct variable *var =
144         psppire_dict_insert_variable (store->dict,
145                                       psppire_dict_get_var_cnt (store->dict),
146                                       NULL);
147       g_return_val_if_fail (var, FALSE);
148     }
149
150   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
151   g_return_val_if_fail (variable, FALSE);
152
153   const struct fmt_spec *fmt = var_get_print_format (variable);
154
155   int width = var_get_width (variable);
156
157   union value val;
158   value_init (&val, width);
159   char *xx =
160     data_in (ss_cstr (in), psppire_dict_encoding (store->dict),
161              fmt->type, &val, width, "UTF-8");
162
163   GVariant *vrnt = value_variant_new (&val, width);
164   value_destroy (&val, width);
165
166   g_value_init (out, G_TYPE_VARIANT);
167   g_value_set_variant (out, vrnt);
168   free (xx);
169   return TRUE;
170 }
171
172 static char *
173 unlabeled_value (PsppireDataStore *store, const struct variable *variable, const union value *val)
174 {
175   const struct fmt_spec *fmt = var_get_print_format (variable);
176   return data_out (val, psppire_dict_encoding (store->dict),  fmt);
177 }
178
179 gchar *
180 psppire_data_store_value_to_string (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
181 {
182   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
183   g_return_val_if_fail (variable, g_strdup ("???"));
184
185   GVariant *vrnt = g_value_get_variant (v);
186   g_return_val_if_fail (vrnt, g_strdup ("???"));
187
188   union value val;
189   value_variant_get (&val, vrnt);
190
191   char *out = unlabeled_value (store, variable, &val);
192
193   value_destroy_from_variant (&val, vrnt);
194
195   return out;
196 }
197
198 gchar *
199 psppire_data_store_value_to_string_with_labels (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
200 {
201   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
202   g_return_val_if_fail (variable, g_strdup ("???"));
203
204   GVariant *vrnt = g_value_get_variant (v);
205   union value val;
206   value_variant_get (&val, vrnt);
207
208   char *out = NULL;
209
210   const struct val_labs *vls = var_get_value_labels (variable);
211   struct val_lab *vl = val_labs_lookup (vls, &val);
212   if (vl != NULL)
213     out = strdup (val_lab_get_label (vl));
214   else
215     out = unlabeled_value (store, variable, &val);
216
217   value_destroy_from_variant (&val, vrnt);
218
219   return out;
220 }
221
222 static void
223 __get_value (GtkTreeModel *tree_model,
224              GtkTreeIter *iter,
225              gint column,
226              GValue *value)
227 {
228   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
229
230   g_return_if_fail (iter->stamp == store->stamp);
231
232   const struct variable *variable = psppire_dict_get_variable (store->dict, column);
233   if (NULL == variable)
234     return;
235
236   gint row = GPOINTER_TO_INT (iter->user_data);
237
238   struct ccase *cc = datasheet_get_row (store->datasheet, row);
239
240   g_return_if_fail (cc);
241
242   g_value_init (value, G_TYPE_VARIANT);
243
244   const union value *val = case_data_idx (cc, var_get_case_index (variable));
245
246   GVariant *vv = value_variant_new (val, var_get_width (variable));
247
248   g_value_set_variant (value, vv);
249
250   case_unref (cc);
251 }
252
253
254 static void
255 __tree_model_init (GtkTreeModelIface *iface)
256 {
257   iface->get_flags       = __tree_model_get_flags;
258   iface->get_n_columns   = __tree_model_get_n_columns ;
259   iface->get_column_type = NULL;
260   iface->get_iter        = NULL;
261   iface->iter_next       = NULL;
262   iface->get_path        = NULL;
263   iface->get_value       = __get_value;
264
265   iface->iter_children   = NULL;
266   iface->iter_has_child  = NULL;
267   iface->iter_n_children = __tree_model_iter_n_children;
268   iface->iter_nth_child  = __iter_nth_child;
269   iface->iter_parent     = NULL;
270 }
271
272
273 GType
274 psppire_data_store_get_type (void)
275 {
276   static GType data_store_type = 0;
277
278   if (!data_store_type)
279     {
280       static const GTypeInfo data_store_info =
281       {
282         sizeof (PsppireDataStoreClass),
283         NULL,           /* base_init */
284         NULL,           /* base_finalize */
285         (GClassInitFunc) psppire_data_store_class_init,
286         NULL,           /* class_finalize */
287         NULL,           /* class_data */
288         sizeof (PsppireDataStore),
289         0,
290         (GInstanceInitFunc) psppire_data_store_init,
291       };
292
293       static const GInterfaceInfo tree_model_info = {
294         (GInterfaceInitFunc) __tree_model_init,
295         NULL,
296         NULL
297       };
298
299       data_store_type = g_type_register_static (G_TYPE_OBJECT,
300                                                 "PsppireDataStore",
301                                                 &data_store_info, 0);
302
303       g_type_add_interface_static (data_store_type, GTK_TYPE_TREE_MODEL,
304                                    &tree_model_info);
305     }
306
307   return data_store_type;
308 }
309
310
311 static void
312 psppire_data_store_class_init (PsppireDataStoreClass *class)
313 {
314   GObjectClass *object_class;
315
316   parent_class = g_type_class_peek_parent (class);
317   object_class = (GObjectClass*) class;
318
319   object_class->finalize = psppire_data_store_finalize;
320   object_class->dispose = psppire_data_store_dispose;
321
322   signals [ITEMS_CHANGED] =
323     g_signal_new ("items-changed",
324                   G_TYPE_FROM_CLASS (class),
325                   G_SIGNAL_RUN_FIRST,
326                   0,
327                   NULL, NULL,
328                   psppire_marshal_VOID__UINT_UINT_UINT,
329                   G_TYPE_NONE,
330                   3,
331                   G_TYPE_UINT,  /* Index of the start of the change */
332                   G_TYPE_UINT,  /* The number of items deleted */
333                   G_TYPE_UINT); /* The number of items inserted */
334
335   signals [CASE_CHANGED] =
336     g_signal_new ("case-changed",
337                   G_TYPE_FROM_CLASS (class),
338                   G_SIGNAL_RUN_FIRST,
339                   0,
340                   NULL, NULL,
341                   g_cclosure_marshal_VOID__INT,
342                   G_TYPE_NONE,
343                   1,
344                   G_TYPE_INT);
345 }
346
347
348
349 casenumber
350 psppire_data_store_get_case_count (const PsppireDataStore *store)
351 {
352   return datasheet_get_n_rows (store->datasheet);
353 }
354
355 size_t
356 psppire_data_store_get_value_count (const PsppireDataStore *store)
357 {
358   return psppire_dict_get_value_cnt (store->dict);
359 }
360
361 const struct caseproto *
362 psppire_data_store_get_proto (const PsppireDataStore *store)
363 {
364   return psppire_dict_get_proto (store->dict);
365 }
366
367 static void
368 psppire_data_store_init (PsppireDataStore *data_store)
369 {
370   data_store->dict = NULL;
371   data_store->datasheet = NULL;
372   data_store->dispose_has_run = FALSE;
373   data_store->stamp = g_random_int ();
374 }
375
376
377 static void
378 psppire_data_store_delete_value (PsppireDataStore *store, gint case_index)
379 {
380   g_return_if_fail (store->datasheet);
381   datasheet_delete_columns (store->datasheet, case_index, 1);
382   datasheet_insert_column (store->datasheet, NULL, -1, case_index);
383 }
384
385
386 /*
387    A callback which occurs after a variable has been deleted.
388  */
389 static void
390 delete_variable_callback (GObject *obj, const struct variable *var UNUSED,
391                           gint dict_index, gint case_index,
392                           gpointer data)
393 {
394   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
395
396   psppire_data_store_delete_value (store, case_index);
397 }
398
399 struct resize_datum_aux
400   {
401     const struct dictionary *dict;
402     const struct variable *new_variable;
403     const struct variable *old_variable;
404   };
405
406 static void
407 resize_datum (const union value *old, union value *new, const void *aux_)
408 {
409   const struct resize_datum_aux *aux = aux_;
410   int new_width = var_get_width (aux->new_variable);
411   const char *enc = dict_get_encoding (aux->dict);
412   const struct fmt_spec *newfmt = var_get_print_format (aux->new_variable);
413   char *s = data_out (old, enc, var_get_print_format (aux->old_variable));
414   enum fmt_type type = (fmt_usable_for_input (newfmt->type)
415                         ? newfmt->type
416                         : FMT_DOLLAR);
417   free (data_in (ss_cstr (s), enc, type, new, new_width, enc));
418   free (s);
419 }
420
421 static void
422 variable_changed_callback (GObject *obj, gint var_num, guint what, const struct variable *oldvar,
423                            gpointer data)
424 {
425   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
426   struct variable *variable = psppire_dict_get_variable (store->dict, var_num);
427
428   if (what & VAR_TRAIT_WIDTH)
429     {
430       int posn = var_get_case_index (variable);
431       struct resize_datum_aux aux;
432       aux.old_variable = oldvar;
433       aux.new_variable = variable;
434       aux.dict = store->dict->dict;
435       datasheet_resize_column (store->datasheet, posn, var_get_width (variable),
436                                resize_datum, &aux);
437     }
438 }
439
440 static void
441 insert_variable_callback (GObject *obj, gint var_num, gpointer data)
442 {
443   struct variable *variable;
444   PsppireDataStore *store;
445   gint posn;
446
447   g_return_if_fail (data);
448
449   store  = PSPPIRE_DATA_STORE (data);
450
451   variable = psppire_dict_get_variable (store->dict, var_num);
452   posn = var_get_case_index (variable);
453   psppire_data_store_insert_value (store, var_get_width (variable), posn);
454 }
455
456 /**
457  * psppire_data_store_new:
458  * @dict: The dictionary for this data_store.
459  *
460  *
461  * Return value: a new #PsppireDataStore
462  **/
463 PsppireDataStore *
464 psppire_data_store_new (PsppireDict *dict)
465 {
466   PsppireDataStore *retval;
467
468   retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
469
470   psppire_data_store_set_dictionary (retval, dict);
471
472   return retval;
473 }
474
475 void
476 psppire_data_store_set_reader (PsppireDataStore *ds,
477                                struct casereader *reader)
478 {
479   gint i;
480   gint old_n = 0;
481   if ( ds->datasheet)
482     {
483       old_n = datasheet_get_n_rows (ds->datasheet);
484       datasheet_destroy (ds->datasheet);
485     }
486
487   ds->datasheet = datasheet_create (reader);
488
489   gint new_n = datasheet_get_n_rows (ds->datasheet);
490
491   if ( ds->dict )
492     for (i = 0 ; i < n_dict_signals; ++i )
493       {
494         if ( ds->dict_handler_id [i] > 0)
495           {
496             g_signal_handler_unblock (ds->dict,
497                                       ds->dict_handler_id[i]);
498           }
499       }
500
501   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, 0, old_n, new_n);
502 }
503
504
505 /**
506  * psppire_data_store_replace_set_dictionary:
507  * @data_store: The variable store
508  * @dict: The dictionary to set
509  *
510  * If a dictionary is already associated with the data-store, then it will be
511  * destroyed.
512  **/
513 void
514 psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *dict)
515 {
516   int i;
517
518   /* Disconnect any existing handlers */
519   if ( data_store->dict )
520     for (i = 0 ; i < n_dict_signals; ++i )
521       {
522         g_signal_handler_disconnect (data_store->dict,
523                                      data_store->dict_handler_id[i]);
524       }
525
526   data_store->dict = dict;
527
528   if ( dict != NULL)
529     {
530
531       data_store->dict_handler_id [VARIABLE_INSERTED] =
532         g_signal_connect (dict, "variable-inserted",
533                           G_CALLBACK (insert_variable_callback),
534                           data_store);
535
536       data_store->dict_handler_id [VARIABLE_DELETED] =
537         g_signal_connect (dict, "variable-deleted",
538                           G_CALLBACK (delete_variable_callback),
539                           data_store);
540
541       data_store->dict_handler_id [VARIABLE_CHANGED] =
542         g_signal_connect (dict, "variable-changed",
543                           G_CALLBACK (variable_changed_callback),
544                           data_store);
545     }
546
547
548
549   /* The entire model has changed */
550
551   if ( data_store->dict )
552     for (i = 0 ; i < n_dict_signals; ++i )
553       {
554         if ( data_store->dict_handler_id [i] > 0)
555           {
556             g_signal_handler_block (data_store->dict,
557                                     data_store->dict_handler_id[i]);
558           }
559       }
560 }
561
562 static void
563 psppire_data_store_finalize (GObject *object)
564 {
565   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
566
567   if (ds->datasheet)
568     {
569       datasheet_destroy (ds->datasheet);
570       ds->datasheet = NULL;
571     }
572
573   /* must chain up */
574   (* parent_class->finalize) (object);
575 }
576
577
578 static void
579 psppire_data_store_dispose (GObject *object)
580 {
581   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
582
583   if (ds->dispose_has_run)
584     return;
585
586   psppire_data_store_set_dictionary (ds, NULL);
587
588   /* must chain up */
589   (* parent_class->dispose) (object);
590
591   ds->dispose_has_run = TRUE;
592 }
593
594
595
596 /* Insert a blank case before POSN */
597 gboolean
598 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
599 {
600   gboolean result;
601   const struct caseproto *proto;
602   struct ccase *cc;
603   g_return_val_if_fail (ds, FALSE);
604
605   proto = datasheet_get_proto (ds->datasheet);
606   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
607   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
608
609   cc = case_create (proto);
610   case_set_missing (cc);
611
612   result = psppire_data_store_insert_case (ds, cc, posn);
613
614   case_unref (cc);
615
616   return result;
617 }
618
619 gboolean
620 psppire_data_store_get_value (PsppireDataStore *store,
621                               glong row, const struct variable *var,
622                               union value *val)
623 {
624   g_return_val_if_fail (store != NULL, FALSE);
625   g_return_val_if_fail (store->datasheet != NULL, FALSE);
626   g_return_val_if_fail (var != NULL, FALSE);
627
628   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
629     return FALSE;
630
631   int width = var_get_width (var);
632   value_init (val, width);
633   datasheet_get_value (store->datasheet, row, var_get_case_index (var), val);
634
635   return TRUE;
636 }
637
638
639
640 gchar *
641 psppire_data_store_get_string (PsppireDataStore *store,
642                                glong row, const struct variable *var,
643                                bool use_value_label)
644 {
645   gchar *string;
646   union value v;
647   int width = var_get_width (var);
648   if (! psppire_data_store_get_value (store, row, var, &v))
649     return NULL;
650
651   string = NULL;
652   if (use_value_label)
653     {
654       const char *label = var_lookup_value_label (var, &v);
655       if (label != NULL)
656         string = g_strdup (label);
657     }
658   if (string == NULL)
659     string = value_to_text (v, var);
660
661   value_destroy (&v, width);
662
663   return string;
664 }
665
666
667 /* Attempts to update that part of the variable store which corresponds to VAR
668    within ROW with the value TEXT.
669
670    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
671    variable, then stores the value from that value label instead of the literal
672    TEXT.
673
674    Returns true if anything was updated, false otherwise.  */
675 gboolean
676 psppire_data_store_set_string (PsppireDataStore *store,
677                                const gchar *text,
678                                glong row, const struct variable *var,
679                                gboolean use_value_label)
680 {
681   gint case_index;
682   glong n_cases;
683   gboolean ok;
684
685   n_cases = psppire_data_store_get_case_count (store);
686   if (row > n_cases)
687     return FALSE;
688   if (row == n_cases)
689     psppire_data_store_insert_new_case (store, row);
690
691   case_index = var_get_case_index (var);
692   if (use_value_label)
693     {
694       const struct val_labs *vls = var_get_value_labels (var);
695       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
696       if (value)
697         ok = datasheet_put_value (store->datasheet, row, case_index, value);
698       else
699         ok = FALSE;
700     }
701   else
702     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
703                                      var_get_print_format (var));
704
705   if (ok)
706     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
707   return ok;
708 }
709
710
711
712 void
713 psppire_data_store_clear (PsppireDataStore *ds)
714 {
715   datasheet_destroy (ds->datasheet);
716   ds->datasheet = NULL;
717
718   psppire_dict_clear (ds->dict);
719
720   g_signal_emit (ds, signals [ITEMS_CHANGED], 0, 0, -1, 0);
721 }
722
723
724
725 /* Return a casereader made from this datastore */
726 struct casereader *
727 psppire_data_store_get_reader (PsppireDataStore *ds)
728 {
729   int i;
730   struct casereader *reader ;
731
732   if ( ds->dict )
733     for (i = 0 ; i < n_dict_signals; ++i )
734       {
735         g_signal_handler_block (ds->dict,
736                                 ds->dict_handler_id[i]);
737       }
738
739   reader = datasheet_make_reader (ds->datasheet);
740
741   /* We must not reference this again */
742   ds->datasheet = NULL;
743
744   return reader;
745 }
746
747 /* Returns the CASENUMth case, or a null pointer on failure.
748  */
749 struct ccase *
750 psppire_data_store_get_case (const PsppireDataStore *ds,
751                              casenumber casenum)
752 {
753   g_return_val_if_fail (ds, FALSE);
754   g_return_val_if_fail (ds->datasheet, FALSE);
755
756   return datasheet_get_row (ds->datasheet, casenum);
757 }
758
759
760 gboolean
761 psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
762                                  casenumber n_cases)
763 {
764   g_return_val_if_fail (ds, FALSE);
765   g_return_val_if_fail (ds->datasheet, FALSE);
766
767   g_return_val_if_fail (first + n_cases <=
768                         psppire_data_store_get_case_count (ds), FALSE);
769
770
771   datasheet_delete_rows (ds->datasheet, first, n_cases);
772
773   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, first, n_cases, 0);
774
775   return TRUE;
776 }
777
778
779
780 /* Insert case CC into the case file before POSN */
781 static gboolean
782 psppire_data_store_insert_case (PsppireDataStore *ds,
783                                 struct ccase *cc,
784                                 casenumber posn)
785 {
786   bool result ;
787
788   g_return_val_if_fail (ds, FALSE);
789   g_return_val_if_fail (ds->datasheet, FALSE);
790
791   cc = case_ref (cc);
792   result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
793
794   if ( result )
795     {
796       g_signal_emit (ds, signals[ITEMS_CHANGED], 0, posn, 0, 1);
797     }
798   else
799     g_warning ("Cannot insert case at position %ld\n", posn);
800
801   return result;
802 }
803
804
805 /* Set the value of VAR in case CASENUM to V.
806    V must be the correct width for IDX.
807    Returns true if successful, false on I/O error. */
808 gboolean
809 psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
810                               const struct variable *var, const union value *v)
811 {
812   glong n_cases;
813   bool ok;
814
815   g_return_val_if_fail (ds, FALSE);
816   g_return_val_if_fail (ds->datasheet, FALSE);
817
818   n_cases = psppire_data_store_get_case_count (ds);
819   if ( casenum > n_cases)
820     return FALSE;
821
822   if (casenum == n_cases)
823     psppire_data_store_insert_new_case (ds, casenum);
824
825   ok = datasheet_put_value (ds->datasheet, casenum, var_get_case_index (var),
826                             v);
827   if (ok)
828     {
829       g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
830       g_signal_emit (ds, signals [ITEMS_CHANGED], 0, casenum, 1, 1);
831     }
832
833   return ok;
834 }
835
836
837
838
839 /* Set the IDXth value of case C using D_IN */
840 static gboolean
841 psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
842                             struct substring input, const struct fmt_spec *fmt)
843 {
844   union value value;
845   int width;
846   bool ok;
847
848   PsppireDict *dict;
849
850   g_return_val_if_fail (ds, FALSE);
851   g_return_val_if_fail (ds->datasheet, FALSE);
852
853   g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
854
855   dict = ds->dict;
856
857   width = fmt_var_width (fmt);
858   g_return_val_if_fail (caseproto_get_width (
859                           datasheet_get_proto (ds->datasheet), idx) == width,
860                         FALSE);
861   value_init (&value, width);
862   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
863         && data_in_msg (input, UTF8, fmt->type, &value, width,
864                         dict_get_encoding (dict->dict))
865         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
866   value_destroy (&value, width);
867
868   return ok;
869 }
870
871 /* Resize the cases in the casefile, by inserting a value of the
872    given WIDTH into every one of them at the position immediately
873    preceding WHERE.
874 */
875 gboolean
876 psppire_data_store_insert_value (PsppireDataStore *ds,
877                                  gint width, gint where)
878 {
879   union value value;
880
881   g_return_val_if_fail (ds, FALSE);
882
883   g_assert (width >= 0);
884
885   if ( ! ds->datasheet )
886     ds->datasheet = datasheet_create (NULL);
887
888   value_init (&value, width);
889   value_set_missing (&value, width);
890
891   datasheet_insert_column (ds->datasheet, &value, width, where);
892   value_destroy (&value, width);
893
894   return TRUE;
895 }
896
897 gboolean
898 psppire_data_store_filtered (PsppireDataStore *ds,
899                              glong row)
900 {
901   union value val;
902
903   const struct dictionary *dict;
904   const struct variable *filter;
905
906   if ( row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
907     return FALSE;
908
909   dict = ds->dict->dict;
910   g_return_val_if_fail (dict, FALSE);
911   filter = dict_get_filter (dict);
912   if ( ! filter)
913     return FALSE;
914
915   g_return_val_if_fail (var_is_numeric (filter), FALSE);
916   value_init (&val, 0);
917   if ( ! datasheet_get_value (ds->datasheet, row,
918                               var_get_case_index (filter),
919                               &val) )
920     return FALSE;
921
922   return (val.f == 0.0);
923 }