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