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