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