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