dictionary: Always compact immediately upon deletion of a variable.
[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                                             struct fmt_spec);
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   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   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_vars (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_values (PsppireDataStore *store, gint case_index,
356                                   guint n)
357 {
358   g_return_if_fail (store->datasheet);
359   g_return_if_fail (case_index < datasheet_get_n_columns (store->datasheet));
360
361   datasheet_delete_columns (store->datasheet, case_index, n);
362 }
363
364
365 /*
366    A callback which occurs after variables have been deleted.
367  */
368 static void
369 delete_variables_callback (GObject *obj, gint dict_index, unsigned int n, gpointer data)
370 {
371   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
372
373   psppire_data_store_delete_values (store, dict_index, n);
374 }
375
376 struct resize_datum_aux
377   {
378     const struct dictionary *dict;
379     const struct variable *new_variable;
380     const struct variable *old_variable;
381   };
382
383 static void
384 resize_datum (const union value *old, union value *new, const void *aux_)
385 {
386   const struct resize_datum_aux *aux = aux_;
387   int new_width = var_get_width (aux->new_variable);
388   const char *enc = dict_get_encoding (aux->dict);
389   struct fmt_spec newfmt = var_get_print_format (aux->new_variable);
390   char *s = data_out (old, enc, var_get_print_format (aux->old_variable),
391                       settings_get_fmt_settings ());
392   enum fmt_type type = (fmt_usable_for_input (newfmt.type)
393                         ? newfmt.type
394                         : FMT_DOLLAR);
395   free (data_in (ss_cstr (s), enc, type, settings_get_fmt_settings (),
396                  new, new_width, enc));
397   free (s);
398 }
399
400 static void
401 variable_changed_callback (GObject *obj, gint var_num, guint what, const struct variable *oldvar,
402                            gpointer data)
403 {
404   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
405   struct variable *variable = psppire_dict_get_variable (store->dict, var_num);
406
407   if (what & VAR_TRAIT_WIDTH)
408     {
409       int posn = var_get_case_index (variable);
410       struct resize_datum_aux aux;
411       aux.old_variable = oldvar;
412       aux.new_variable = variable;
413       aux.dict = store->dict->dict;
414       datasheet_resize_column (store->datasheet, posn, var_get_width (variable),
415                                resize_datum, &aux);
416     }
417 }
418
419 static void
420 insert_variable_callback (GObject *obj, gint var_num, gpointer data)
421 {
422   struct variable *variable;
423   PsppireDataStore *store;
424   gint posn;
425
426   g_return_if_fail (data);
427
428   store  = PSPPIRE_DATA_STORE (data);
429
430   variable = psppire_dict_get_variable (store->dict, var_num);
431   posn = var_get_case_index (variable);
432   psppire_data_store_insert_value (store, var_get_width (variable), posn);
433 }
434
435 /**
436  * psppire_data_store_new:
437  * @dict: The dictionary for this data_store.
438  *
439  *
440  * Return value: a new #PsppireDataStore
441  **/
442 PsppireDataStore *
443 psppire_data_store_new (PsppireDict *dict)
444 {
445   PsppireDataStore *retval;
446
447   retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
448
449   psppire_data_store_set_dictionary (retval, dict);
450
451   return retval;
452 }
453
454 void
455 psppire_data_store_set_reader (PsppireDataStore *ds,
456                                struct casereader *reader)
457 {
458   gint i;
459   gint old_n = 0;
460   if (ds->datasheet)
461     {
462       old_n = datasheet_get_n_rows (ds->datasheet);
463       datasheet_destroy (ds->datasheet);
464     }
465
466   ds->datasheet = datasheet_create (reader);
467
468   gint new_n = datasheet_get_n_rows (ds->datasheet);
469
470   if (ds->dict)
471     for (i = 0 ; i < n_dict_signals; ++i)
472       {
473         if (ds->dict_handler_id [i] > 0)
474           {
475             g_signal_handler_unblock (ds->dict,
476                                       ds->dict_handler_id[i]);
477           }
478       }
479
480   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, 0, old_n, new_n);
481 }
482
483
484 /**
485  * psppire_data_store_replace_set_dictionary:
486  * @data_store: The variable store
487  * @dict: The dictionary to set
488  *
489  * If a dictionary is already associated with the data-store, then it will be
490  * destroyed.
491  **/
492 void
493 psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *dict)
494 {
495   int i;
496
497   /* Disconnect any existing handlers */
498   if (data_store->dict)
499     for (i = 0 ; i < n_dict_signals; ++i)
500       {
501         g_signal_handler_disconnect (data_store->dict,
502                                      data_store->dict_handler_id[i]);
503       }
504
505   data_store->dict = dict;
506
507   if (dict != NULL)
508     {
509
510       data_store->dict_handler_id [VARIABLE_INSERTED] =
511         g_signal_connect (dict, "variable-inserted",
512                           G_CALLBACK (insert_variable_callback),
513                           data_store);
514
515       data_store->dict_handler_id [VARIABLES_DELETED] =
516         g_signal_connect (dict, "variables-deleted",
517                           G_CALLBACK (delete_variables_callback),
518                           data_store);
519
520       data_store->dict_handler_id [VARIABLE_CHANGED] =
521         g_signal_connect (dict, "variable-changed",
522                           G_CALLBACK (variable_changed_callback),
523                           data_store);
524     }
525
526
527
528   /* The entire model has changed */
529
530   if (data_store->dict)
531     for (i = 0 ; i < n_dict_signals; ++i)
532       {
533         if (data_store->dict_handler_id [i] > 0)
534           {
535             g_signal_handler_block (data_store->dict,
536                                     data_store->dict_handler_id[i]);
537           }
538       }
539 }
540
541 static void
542 psppire_data_store_finalize (GObject *object)
543 {
544   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
545
546   if (ds->datasheet)
547     {
548       datasheet_destroy (ds->datasheet);
549       ds->datasheet = NULL;
550     }
551
552   /* must chain up */
553   (* parent_class->finalize) (object);
554 }
555
556
557 static void
558 psppire_data_store_dispose (GObject *object)
559 {
560   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
561
562   if (ds->dispose_has_run)
563     return;
564
565   psppire_data_store_set_dictionary (ds, NULL);
566
567   /* must chain up */
568   (* parent_class->dispose) (object);
569
570   ds->dispose_has_run = TRUE;
571 }
572
573
574
575 /* Insert a blank case before POSN */
576 gboolean
577 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
578 {
579   gboolean result;
580   const struct caseproto *proto;
581   struct ccase *cc;
582   g_return_val_if_fail (ds, FALSE);
583
584   proto = datasheet_get_proto (ds->datasheet);
585   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
586   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
587
588   cc = case_create (proto);
589   case_set_missing (cc);
590
591   result = psppire_data_store_insert_case (ds, cc, posn);
592
593   case_unref (cc);
594
595   return result;
596 }
597
598 gboolean
599 psppire_data_store_get_value (PsppireDataStore *store,
600                               glong row, const struct variable *var,
601                               union value *val)
602 {
603   g_return_val_if_fail (store != NULL, FALSE);
604   g_return_val_if_fail (store->datasheet != NULL, FALSE);
605   g_return_val_if_fail (var != NULL, FALSE);
606
607   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
608     return FALSE;
609
610   int width = var_get_width (var);
611   value_init (val, width);
612   datasheet_get_value (store->datasheet, row, var_get_case_index (var), val);
613
614   return TRUE;
615 }
616
617
618
619 gchar *
620 psppire_data_store_get_string (PsppireDataStore *store,
621                                glong row, const struct variable *var,
622                                bool use_value_label)
623 {
624   gchar *string;
625   union value v;
626   int width = var_get_width (var);
627   if (! psppire_data_store_get_value (store, row, var, &v))
628     return NULL;
629
630   string = NULL;
631   if (use_value_label)
632     {
633       const char *label = var_lookup_value_label (var, &v);
634       if (label != NULL)
635         string = g_strdup (label);
636     }
637   if (string == NULL)
638     string = value_to_text (v, var);
639
640   value_destroy (&v, width);
641
642   return string;
643 }
644
645
646 /* Attempts to update that part of the variable store which corresponds to VAR
647    within ROW with the value TEXT.
648
649    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
650    variable, then stores the value from that value label instead of the literal
651    TEXT.
652
653    Returns true if anything was updated, false otherwise.  */
654 gboolean
655 psppire_data_store_set_string (PsppireDataStore *store,
656                                const gchar *text,
657                                glong row, const struct variable *var,
658                                gboolean use_value_label)
659 {
660   gint case_index;
661   glong n_cases;
662   gboolean ok;
663
664   n_cases = psppire_data_store_get_case_count (store);
665   if (row > n_cases)
666     return FALSE;
667   if (row == n_cases)
668     psppire_data_store_insert_new_case (store, row);
669
670   case_index = var_get_case_index (var);
671   if (use_value_label)
672     {
673       const struct val_labs *vls = var_get_value_labels (var);
674       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
675       if (value)
676         ok = datasheet_put_value (store->datasheet, row, case_index, value);
677       else
678         ok = FALSE;
679     }
680   else
681     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
682                                      var_get_print_format (var));
683
684   if (ok)
685     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
686   return ok;
687 }
688
689
690
691 void
692 psppire_data_store_clear (PsppireDataStore *ds)
693 {
694   datasheet_destroy (ds->datasheet);
695   ds->datasheet = NULL;
696
697   psppire_dict_clear (ds->dict);
698
699   g_signal_emit (ds, signals [ITEMS_CHANGED], 0, 0, -1, 0);
700 }
701
702
703
704 /* Return a casereader made from this datastore */
705 struct casereader *
706 psppire_data_store_get_reader (PsppireDataStore *ds)
707 {
708   struct casereader *reader ;
709
710   if (ds->dict)
711     for (int i = 0 ; i < n_dict_signals; ++i)
712       {
713         g_signal_handler_block (ds->dict,
714                                 ds->dict_handler_id[i]);
715       }
716
717   reader = datasheet_make_reader (ds->datasheet);
718
719   /* We must not reference this again */
720   ds->datasheet = NULL;
721
722   return reader;
723 }
724
725 /* Returns the CASENUMth case, or a null pointer on failure.
726  */
727 struct ccase *
728 psppire_data_store_get_case (const PsppireDataStore *ds,
729                              casenumber casenum)
730 {
731   g_return_val_if_fail (ds, FALSE);
732   g_return_val_if_fail (ds->datasheet, FALSE);
733
734   return datasheet_get_row (ds->datasheet, casenum);
735 }
736
737
738 gboolean
739 psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
740                                  casenumber n_cases)
741 {
742   g_return_val_if_fail (ds, FALSE);
743   g_return_val_if_fail (ds->datasheet, FALSE);
744
745   g_return_val_if_fail (first + n_cases <=
746                         psppire_data_store_get_case_count (ds), FALSE);
747
748
749   datasheet_delete_rows (ds->datasheet, first, n_cases);
750
751   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, first, n_cases, 0);
752
753   return TRUE;
754 }
755
756
757
758 /* Insert case CC into the case file before POSN */
759 static gboolean
760 psppire_data_store_insert_case (PsppireDataStore *ds,
761                                 struct ccase *cc,
762                                 casenumber posn)
763 {
764   bool result ;
765
766   g_return_val_if_fail (ds, FALSE);
767   g_return_val_if_fail (ds->datasheet, FALSE);
768
769   cc = case_ref (cc);
770   result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
771
772   if (result)
773     {
774       g_signal_emit (ds, signals[ITEMS_CHANGED], 0, posn, 0, 1);
775     }
776   else
777     g_warning ("Cannot insert case at position %ld\n", posn);
778
779   return result;
780 }
781
782
783 /* Set the value of VAR in case CASENUM to V.
784    V must be the correct width for IDX.
785    Returns true if successful, false on I/O error. */
786 gboolean
787 psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
788                               const struct variable *var, const union value *v)
789 {
790   glong n_cases;
791   bool ok;
792
793   g_return_val_if_fail (ds, FALSE);
794   g_return_val_if_fail (ds->datasheet, FALSE);
795
796   n_cases = psppire_data_store_get_case_count (ds);
797   if (casenum > n_cases)
798     return FALSE;
799
800   if (casenum == n_cases)
801     psppire_data_store_insert_new_case (ds, casenum);
802
803   ok = datasheet_put_value (ds->datasheet, casenum, var_get_case_index (var),
804                             v);
805   if (ok)
806     {
807       g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
808       g_signal_emit (ds, signals [ITEMS_CHANGED], 0, casenum, 1, 1);
809     }
810
811   return ok;
812 }
813
814
815
816
817 /* Set the IDXth value of case C using D_IN */
818 static gboolean
819 psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
820                             struct substring input, struct fmt_spec fmt)
821 {
822   union value value;
823   int width;
824   bool ok;
825
826   PsppireDict *dict;
827
828   g_return_val_if_fail (ds, FALSE);
829   g_return_val_if_fail (ds->datasheet, FALSE);
830
831   g_return_val_if_fail (idx < datasheet_get_n_columns (ds->datasheet), FALSE);
832
833   dict = ds->dict;
834
835   width = fmt_var_width (fmt);
836   g_return_val_if_fail (caseproto_get_width (
837                           datasheet_get_proto (ds->datasheet), idx) == width,
838                         FALSE);
839   value_init (&value, width);
840   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
841         && data_in_msg (input, UTF8, fmt.type, settings_get_fmt_settings (),
842                         &value, width, dict_get_encoding (dict->dict))
843         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
844   value_destroy (&value, width);
845
846   return ok;
847 }
848
849 /* Resize the cases in the casefile, by inserting a value of the
850    given WIDTH into every one of them at the position immediately
851    preceding WHERE.
852 */
853 gboolean
854 psppire_data_store_insert_value (PsppireDataStore *ds,
855                                  gint width, gint where)
856 {
857   union value value;
858
859   g_return_val_if_fail (ds, FALSE);
860
861   g_assert (width >= 0);
862
863   if (! ds->datasheet)
864     ds->datasheet = datasheet_create (NULL);
865
866   value_init (&value, width);
867   value_set_missing (&value, width);
868
869   datasheet_insert_column (ds->datasheet, &value, width, where);
870   value_destroy (&value, width);
871
872   return TRUE;
873 }
874
875 gboolean
876 psppire_data_store_filtered (PsppireDataStore *ds,
877                              glong row)
878 {
879   union value val;
880
881   const struct dictionary *dict;
882   const struct variable *filter;
883
884   if (row < 0 || row >= datasheet_get_n_rows (ds->datasheet))
885     return FALSE;
886
887   dict = ds->dict->dict;
888   g_return_val_if_fail (dict, FALSE);
889   filter = dict_get_filter (dict);
890   if (! filter)
891     return FALSE;
892
893   g_return_val_if_fail (var_is_numeric (filter), FALSE);
894   value_init (&val, 0);
895   if (! datasheet_get_value (ds->datasheet, row,
896                               var_get_case_index (filter),
897                               &val))
898     return FALSE;
899
900   return (val.f == 0.0);
901 }