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