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