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