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