PsppireDataStore (myreversefunc): Insert variables if attempting to access variable...
[pspp] / src / ui / gui / psppire-data-store.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2006, 2008, 2009, 2010, 2011, 2012,
3    2013, 2016, 2017  Free Software Foundation
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <gettext.h>
22 #define _(msgid) gettext (msgid)
23 #define P_(msgid) msgid
24
25 #include <data/datasheet.h>
26 #include <data/data-out.h>
27 #include <data/variable.h>
28
29 #include <ui/gui/psppire-marshal.h>
30
31 #include <pango/pango-context.h>
32
33 #include "psppire-data-store.h"
34 #include <libpspp/i18n.h>
35 #include "helper.h"
36
37 #include <data/dictionary.h>
38 #include <data/missing-values.h>
39 #include <data/value-labels.h>
40 #include <data/data-in.h>
41 #include <data/format.h>
42
43 #include <math/sort.h>
44
45 #include "xalloc.h"
46 #include "xmalloca.h"
47
48 #include "value-variant.h"
49
50 static void psppire_data_store_init            (PsppireDataStore      *data_store);
51 static void psppire_data_store_class_init      (PsppireDataStoreClass *class);
52
53 static void psppire_data_store_finalize        (GObject           *object);
54 static void psppire_data_store_dispose        (GObject           *object);
55
56 static gboolean psppire_data_store_insert_case (PsppireDataStore *ds,
57                                                 struct ccase *cc,
58                                                 casenumber posn);
59
60
61 static gboolean psppire_data_store_data_in (PsppireDataStore *ds,
62                                             casenumber casenum, gint idx,
63                                             struct substring input,
64                                             const struct fmt_spec *fmt);
65
66 static GObjectClass *parent_class = NULL;
67
68
69 enum
70   {
71     ITEMS_CHANGED,
72     CASE_CHANGED,
73     n_SIGNALS
74   };
75
76 static guint signals [n_SIGNALS];
77
78 static gint
79 __tree_model_iter_n_children (GtkTreeModel *tree_model,
80                              GtkTreeIter *iter)
81 {
82   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
83
84   if (store->datasheet == NULL)
85     return 0;
86
87   gint n =  datasheet_get_n_rows (store->datasheet);
88
89   return n;
90 }
91
92 static GtkTreeModelFlags
93 __tree_model_get_flags (GtkTreeModel *model)
94 {
95   g_return_val_if_fail (PSPPIRE_IS_DATA_STORE (model), (GtkTreeModelFlags) 0);
96
97   return GTK_TREE_MODEL_LIST_ONLY;
98 }
99
100 static gint
101 __tree_model_get_n_columns (GtkTreeModel *tree_model)
102 {
103   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
104
105   return psppire_dict_get_var_cnt (store->dict);
106 }
107
108
109 static gboolean
110 __iter_nth_child (GtkTreeModel *tree_model,
111                   GtkTreeIter *iter,
112                   GtkTreeIter *parent,
113                   gint n)
114 {
115   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
116
117   g_assert (parent == NULL);
118   g_return_val_if_fail (store, FALSE);
119
120   if (!store->datasheet || n >= datasheet_get_n_rows (store->datasheet))
121     {
122       iter->stamp = -1;
123       iter->user_data = NULL;
124       return FALSE;
125     }
126
127   iter->user_data = GINT_TO_POINTER (n);
128   iter->stamp = store->stamp;
129
130   return TRUE;
131 }
132
133 gboolean
134 myreversefunc (GtkTreeModel *model, gint col, gint row,
135                const gchar *in, GValue *out)
136 {
137   PsppireDataStore *store  = PSPPIRE_DATA_STORE (model);
138
139   while (col >= psppire_dict_get_var_cnt (store->dict))
140     {
141       const struct variable *var =
142         psppire_dict_insert_variable (store->dict,
143                                       psppire_dict_get_var_cnt (store->dict),
144                                       NULL);
145       g_return_val_if_fail (var, FALSE);
146     }
147
148   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
149   g_return_val_if_fail (variable, FALSE);
150
151   const struct fmt_spec *fmt = var_get_print_format (variable);
152
153   int width = var_get_width (variable);
154
155   union value val;
156   value_init (&val, width);
157   char *xx =
158     data_in (ss_cstr (in), psppire_dict_encoding (store->dict),
159              fmt->type, &val, width, "UTF-8");
160
161   GVariant *vrnt = value_variant_new (&val, width);
162   value_destroy (&val, width);
163
164   g_value_init (out, G_TYPE_VARIANT);
165   g_value_set_variant (out, vrnt);
166   free (xx);
167   return TRUE;
168 }
169
170 static char *
171 unlabeled_value (PsppireDataStore *store, const struct variable *variable, const union value *val)
172 {
173   const struct fmt_spec *fmt = var_get_print_format (variable);
174   return data_out (val, psppire_dict_encoding (store->dict),  fmt);
175 }
176
177 gchar *
178 psppire_data_store_value_to_string (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
179 {
180   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
181   g_return_val_if_fail (variable, g_strdup ("???"));
182
183   GVariant *vrnt = g_value_get_variant (v);
184   union value val;
185   value_variant_get (&val, vrnt);
186
187   char *out = unlabeled_value (store, variable, &val);
188
189   value_destroy_from_variant (&val, vrnt);
190
191   return out;
192 }
193
194 gchar *
195 psppire_data_store_value_to_string_with_labels (gpointer unused, PsppireDataStore *store, gint col, gint row, const GValue *v)
196 {
197   const struct variable *variable = psppire_dict_get_variable (store->dict, col);
198   g_return_val_if_fail (variable, g_strdup ("???"));
199
200   GVariant *vrnt = g_value_get_variant (v);
201   union value val;
202   value_variant_get (&val, vrnt);
203
204   char *out = NULL;
205
206   const struct val_labs *vls = var_get_value_labels (variable);
207   struct val_lab *vl = val_labs_lookup (vls, &val);
208   if (vl != NULL)
209     out = strdup (val_lab_get_label (vl));
210   else
211     out = unlabeled_value (store, variable, &val);
212
213   value_destroy_from_variant (&val, vrnt);
214
215   return out;
216 }
217
218 static void
219 __get_value (GtkTreeModel *tree_model,
220              GtkTreeIter *iter,
221              gint column,
222              GValue *value)
223 {
224   PsppireDataStore *store  = PSPPIRE_DATA_STORE (tree_model);
225
226   g_return_if_fail (iter->stamp == store->stamp);
227
228   const struct variable *variable = psppire_dict_get_variable (store->dict, column);
229   if (NULL == variable)
230     return;
231
232   g_value_init (value, G_TYPE_VARIANT);
233
234   gint row = GPOINTER_TO_INT (iter->user_data);
235
236   struct ccase *cc = datasheet_get_row (store->datasheet, row);
237
238   const union value *val = case_data_idx (cc, var_get_case_index (variable));
239
240   GVariant *vv = value_variant_new (val, var_get_width (variable));
241
242   g_value_set_variant (value, vv);
243
244   case_unref (cc);
245 }
246
247
248 static void
249 __tree_model_init (GtkTreeModelIface *iface)
250 {
251   iface->get_flags       = __tree_model_get_flags;
252   iface->get_n_columns   = __tree_model_get_n_columns ;
253   iface->get_column_type = NULL;
254   iface->get_iter        = NULL;
255   iface->iter_next       = NULL;
256   iface->get_path        = NULL;
257   iface->get_value       = __get_value;
258
259   iface->iter_children   = NULL;
260   iface->iter_has_child  = NULL;
261   iface->iter_n_children = __tree_model_iter_n_children;
262   iface->iter_nth_child  = __iter_nth_child;
263   iface->iter_parent     = NULL;
264 }
265
266
267 GType
268 psppire_data_store_get_type (void)
269 {
270   static GType data_store_type = 0;
271
272   if (!data_store_type)
273     {
274       static const GTypeInfo data_store_info =
275       {
276         sizeof (PsppireDataStoreClass),
277         NULL,           /* base_init */
278         NULL,           /* base_finalize */
279         (GClassInitFunc) psppire_data_store_class_init,
280         NULL,           /* class_finalize */
281         NULL,           /* class_data */
282         sizeof (PsppireDataStore),
283         0,
284         (GInstanceInitFunc) psppire_data_store_init,
285       };
286
287       static const GInterfaceInfo tree_model_info = {
288         (GInterfaceInitFunc) __tree_model_init,
289         NULL,
290         NULL
291       };
292
293       data_store_type = g_type_register_static (G_TYPE_OBJECT,
294                                                 "PsppireDataStore",
295                                                 &data_store_info, 0);
296
297       g_type_add_interface_static (data_store_type, GTK_TYPE_TREE_MODEL,
298                                    &tree_model_info);
299     }
300
301   return data_store_type;
302 }
303
304
305 static void
306 psppire_data_store_class_init (PsppireDataStoreClass *class)
307 {
308   GObjectClass *object_class;
309
310   parent_class = g_type_class_peek_parent (class);
311   object_class = (GObjectClass*) class;
312
313   object_class->finalize = psppire_data_store_finalize;
314   object_class->dispose = psppire_data_store_dispose;
315
316   signals [ITEMS_CHANGED] =
317     g_signal_new ("items-changed",
318                   G_TYPE_FROM_CLASS (class),
319                   G_SIGNAL_RUN_FIRST,
320                   0,
321                   NULL, NULL,
322                   psppire_marshal_VOID__UINT_UINT_UINT,
323                   G_TYPE_NONE,
324                   3,
325                   G_TYPE_UINT,  /* Index of the start of the change */
326                   G_TYPE_UINT,  /* The number of items deleted */
327                   G_TYPE_UINT); /* The number of items inserted */
328
329   signals [CASE_CHANGED] =
330     g_signal_new ("case-changed",
331                   G_TYPE_FROM_CLASS (class),
332                   G_SIGNAL_RUN_FIRST,
333                   0,
334                   NULL, NULL,
335                   g_cclosure_marshal_VOID__INT,
336                   G_TYPE_NONE,
337                   1,
338                   G_TYPE_INT);
339 }
340
341
342
343 casenumber
344 psppire_data_store_get_case_count (const PsppireDataStore *store)
345 {
346   return datasheet_get_n_rows (store->datasheet);
347 }
348
349 size_t
350 psppire_data_store_get_value_count (const PsppireDataStore *store)
351 {
352   return psppire_dict_get_value_cnt (store->dict);
353 }
354
355 const struct caseproto *
356 psppire_data_store_get_proto (const PsppireDataStore *store)
357 {
358   return psppire_dict_get_proto (store->dict);
359 }
360
361 static void
362 psppire_data_store_init (PsppireDataStore *data_store)
363 {
364   data_store->dict = NULL;
365   data_store->datasheet = NULL;
366   data_store->dispose_has_run = FALSE;
367   data_store->stamp = g_random_int ();
368 }
369
370
371 static void
372 psppire_data_store_delete_value (PsppireDataStore *store, gint case_index)
373 {
374   g_return_if_fail (store->datasheet);
375   datasheet_delete_columns (store->datasheet, case_index, 1);
376   datasheet_insert_column (store->datasheet, NULL, -1, case_index);
377 }
378
379
380 /*
381    A callback which occurs after a variable has been deleted.
382  */
383 static void
384 delete_variable_callback (GObject *obj, const struct variable *var UNUSED,
385                           gint dict_index, gint case_index,
386                           gpointer data)
387 {
388   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
389
390   psppire_data_store_delete_value (store, case_index);
391 }
392
393 struct resize_datum_aux
394   {
395     const struct dictionary *dict;
396     const struct variable *new_variable;
397     const struct variable *old_variable;
398   };
399
400 static void
401 resize_datum (const union value *old, union value *new, const void *aux_)
402 {
403   const struct resize_datum_aux *aux = aux_;
404   int new_width = var_get_width (aux->new_variable);
405   const char *enc = dict_get_encoding (aux->dict);
406   const struct fmt_spec *newfmt = var_get_print_format (aux->new_variable);
407   char *s = data_out (old, enc, var_get_print_format (aux->old_variable));
408   enum fmt_type type = (fmt_usable_for_input (newfmt->type)
409                         ? newfmt->type
410                         : FMT_DOLLAR);
411   free (data_in (ss_cstr (s), enc, type, new, new_width, enc));
412   free (s);
413 }
414
415 static void
416 variable_changed_callback (GObject *obj, gint var_num, guint what, const struct variable *oldvar,
417                            gpointer data)
418 {
419   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
420   struct variable *variable = psppire_dict_get_variable (store->dict, var_num);
421
422   if (what & VAR_TRAIT_WIDTH)
423     {
424       int posn = var_get_case_index (variable);
425       struct resize_datum_aux aux;
426       aux.old_variable = oldvar;
427       aux.new_variable = variable;
428       aux.dict = store->dict->dict;
429       datasheet_resize_column (store->datasheet, posn, var_get_width (variable),
430                                resize_datum, &aux);
431     }
432 }
433
434 static void
435 insert_variable_callback (GObject *obj, gint var_num, gpointer data)
436 {
437   struct variable *variable;
438   PsppireDataStore *store;
439   gint posn;
440
441   g_return_if_fail (data);
442
443   store  = PSPPIRE_DATA_STORE (data);
444
445   variable = psppire_dict_get_variable (store->dict, var_num);
446   posn = var_get_case_index (variable);
447   psppire_data_store_insert_value (store, var_get_width (variable), posn);
448 }
449
450 /**
451  * psppire_data_store_new:
452  * @dict: The dictionary for this data_store.
453  *
454  *
455  * Return value: a new #PsppireDataStore
456  **/
457 PsppireDataStore *
458 psppire_data_store_new (PsppireDict *dict)
459 {
460   PsppireDataStore *retval;
461
462   retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
463
464   psppire_data_store_set_dictionary (retval, dict);
465
466   return retval;
467 }
468
469 void
470 psppire_data_store_set_reader (PsppireDataStore *ds,
471                                struct casereader *reader)
472 {
473   gint i;
474   gint old_n = 0;
475   if ( ds->datasheet)
476     {
477       old_n = datasheet_get_n_rows (ds->datasheet);
478       datasheet_destroy (ds->datasheet);
479     }
480
481   ds->datasheet = datasheet_create (reader);
482
483   gint new_n = datasheet_get_n_rows (ds->datasheet);
484
485   if ( ds->dict )
486     for (i = 0 ; i < n_dict_signals; ++i )
487       {
488         if ( ds->dict_handler_id [i] > 0)
489           {
490             g_signal_handler_unblock (ds->dict,
491                                       ds->dict_handler_id[i]);
492           }
493       }
494
495   g_signal_emit (ds, signals[ITEMS_CHANGED], 0, 0, old_n, new_n);
496 }
497
498
499 /**
500  * psppire_data_store_replace_set_dictionary:
501  * @data_store: The variable store
502  * @dict: The dictionary to set
503  *
504  * If a dictionary is already associated with the data-store, then it will be
505  * destroyed.
506  **/
507 void
508 psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *dict)
509 {
510   int i;
511
512   /* Disconnect any existing handlers */
513   if ( data_store->dict )
514     for (i = 0 ; i < n_dict_signals; ++i )
515       {
516         g_signal_handler_disconnect (data_store->dict,
517                                      data_store->dict_handler_id[i]);
518       }
519
520   data_store->dict = dict;
521
522   if ( dict != NULL)
523     {
524
525       data_store->dict_handler_id [VARIABLE_INSERTED] =
526         g_signal_connect (dict, "variable-inserted",
527                           G_CALLBACK (insert_variable_callback),
528                           data_store);
529
530       data_store->dict_handler_id [VARIABLE_DELETED] =
531         g_signal_connect (dict, "variable-deleted",
532                           G_CALLBACK (delete_variable_callback),
533                           data_store);
534
535       data_store->dict_handler_id [VARIABLE_CHANGED] =
536         g_signal_connect (dict, "variable-changed",
537                           G_CALLBACK (variable_changed_callback),
538                           data_store);
539     }
540
541
542
543   /* The entire model has changed */
544
545   if ( data_store->dict )
546     for (i = 0 ; i < n_dict_signals; ++i )
547       {
548         if ( data_store->dict_handler_id [i] > 0)
549           {
550             g_signal_handler_block (data_store->dict,
551                                     data_store->dict_handler_id[i]);
552           }
553       }
554 }
555
556 static void
557 psppire_data_store_finalize (GObject *object)
558 {
559   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
560
561   if (ds->datasheet)
562     {
563       datasheet_destroy (ds->datasheet);
564       ds->datasheet = NULL;
565     }
566
567   /* must chain up */
568   (* parent_class->finalize) (object);
569 }
570
571
572 static void
573 psppire_data_store_dispose (GObject *object)
574 {
575   PsppireDataStore *ds = PSPPIRE_DATA_STORE (object);
576
577   if (ds->dispose_has_run)
578     return;
579
580   psppire_data_store_set_dictionary (ds, NULL);
581
582   /* must chain up */
583   (* parent_class->dispose) (object);
584
585   ds->dispose_has_run = TRUE;
586 }
587
588
589
590 /* Insert a blank case before POSN */
591 gboolean
592 psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
593 {
594   gboolean result;
595   const struct caseproto *proto;
596   struct ccase *cc;
597   g_return_val_if_fail (ds, FALSE);
598
599   proto = datasheet_get_proto (ds->datasheet);
600   g_return_val_if_fail (caseproto_get_n_widths (proto) > 0, FALSE);
601   g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
602
603   cc = case_create (proto);
604   case_set_missing (cc);
605
606   result = psppire_data_store_insert_case (ds, cc, posn);
607
608   case_unref (cc);
609
610   return result;
611 }
612
613 gboolean
614 psppire_data_store_get_value (PsppireDataStore *store,
615                               glong row, const struct variable *var,
616                               union value *val)
617 {
618   g_return_val_if_fail (store != NULL, FALSE);
619   g_return_val_if_fail (store->datasheet != NULL, FALSE);
620   g_return_val_if_fail (var != NULL, FALSE);
621
622   if (row < 0 || row >= datasheet_get_n_rows (store->datasheet))
623     return FALSE;
624
625   int width = var_get_width (var);
626   value_init (val, width);
627   datasheet_get_value (store->datasheet, row, var_get_case_index (var), val);
628
629   return TRUE;
630 }
631
632
633
634 gchar *
635 psppire_data_store_get_string (PsppireDataStore *store,
636                                glong row, const struct variable *var,
637                                bool use_value_label)
638 {
639   gchar *string;
640   union value v;
641   int width = var_get_width (var);
642   if (! psppire_data_store_get_value (store, row, var, &v))
643     return NULL;
644
645   string = NULL;
646   if (use_value_label)
647     {
648       const char *label = var_lookup_value_label (var, &v);
649       if (label != NULL)
650         string = g_strdup (label);
651     }
652   if (string == NULL)
653     string = value_to_text (v, var);
654
655   value_destroy (&v, width);
656
657   return string;
658 }
659
660
661 /* Attempts to update that part of the variable store which corresponds to VAR
662    within ROW with the value TEXT.
663
664    If USE_VALUE_LABEL is true, and TEXT is a value label for the column's
665    variable, then stores the value from that value label instead of the literal
666    TEXT.
667
668    Returns true if anything was updated, false otherwise.  */
669 gboolean
670 psppire_data_store_set_string (PsppireDataStore *store,
671                                const gchar *text,
672                                glong row, const struct variable *var,
673                                gboolean use_value_label)
674 {
675   gint case_index;
676   glong n_cases;
677   gboolean ok;
678
679   n_cases = psppire_data_store_get_case_count (store);
680   if (row > n_cases)
681     return FALSE;
682   if (row == n_cases)
683     psppire_data_store_insert_new_case (store, row);
684
685   case_index = var_get_case_index (var);
686   if (use_value_label)
687     {
688       const struct val_labs *vls = var_get_value_labels (var);
689       const union value *value = vls ? val_labs_find_value (vls, text) : NULL;
690       if (value)
691         ok = datasheet_put_value (store->datasheet, row, case_index, value);
692       else
693         ok = FALSE;
694     }
695   else
696     ok = psppire_data_store_data_in (store, row, case_index, ss_cstr (text),
697                                      var_get_print_format (var));
698
699   if (ok)
700     g_signal_emit (store, signals [CASE_CHANGED], 0, row);
701   return ok;
702 }
703
704
705
706 void
707 psppire_data_store_clear (PsppireDataStore *ds)
708 {
709   datasheet_destroy (ds->datasheet);
710   ds->datasheet = NULL;
711
712   psppire_dict_clear (ds->dict);
713
714   g_signal_emit (ds, signals [ITEMS_CHANGED], 0, 0, -1, 0);
715 }
716
717
718
719 /* Return a casereader made from this datastore */
720 struct casereader *
721 psppire_data_store_get_reader (PsppireDataStore *ds)
722 {
723   int i;
724   struct casereader *reader ;
725
726   if ( ds->dict )
727     for (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_case_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, const 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, &value, width,
858                         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_case_index (filter),
913                               &val) )
914     return FALSE;
915
916   return (val.f == 0.0);
917 }