Fix bug encodig missing value keys in gui
[pspp] / src / ui / gui / psppire-dict.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2004, 2006, 2007, 2009  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <string.h>
19 #include <stdlib.h>
20
21 #include <gtk/gtk.h>
22 #include <ui/gui/psppire-marshal.h>
23
24 #include "psppire-dict.h"
25 #include <data/dictionary.h>
26 #include <data/missing-values.h>
27 #include <data/value-labels.h>
28 #include <data/variable.h>
29 #include <libpspp/i18n.h>
30
31 #include "helper.h"
32 #include "message-dialog.h"
33
34
35 enum  {
36   BACKEND_CHANGED,
37
38   VARIABLE_CHANGED,
39   VARIABLE_RESIZED,
40   VARIABLE_INSERTED,
41   VARIABLE_DELETED,
42   VARIABLE_DISPLAY_WIDTH_CHANGED,
43
44   WEIGHT_CHANGED,
45   FILTER_CHANGED,
46   SPLIT_CHANGED,
47   n_SIGNALS
48 };
49
50
51 /* --- prototypes --- */
52 static void psppire_dict_class_init     (PsppireDictClass       *class);
53 static void psppire_dict_init   (PsppireDict            *dict);
54 static void psppire_dict_finalize       (GObject                *object);
55
56 static void dictionary_tree_model_init (GtkTreeModelIface *iface);
57
58
59 /* --- variables --- */
60 static GObjectClass     *parent_class = NULL;
61
62 static guint signals [n_SIGNALS];
63
64 /* --- functions --- */
65 /**
66  * psppire_dict_get_type:
67  * @returns: the type ID for accelerator groups.
68  */
69 GType
70 psppire_dict_get_type (void)
71 {
72   static GType object_type = 0;
73
74   if (!object_type)
75     {
76       static const GTypeInfo object_info = {
77         sizeof (PsppireDictClass),
78         (GBaseInitFunc) NULL,
79         (GBaseFinalizeFunc) NULL,
80         (GClassInitFunc) psppire_dict_class_init,
81         NULL,   /* class_finalize */
82         NULL,   /* class_data */
83         sizeof (PsppireDict),
84         0,      /* n_preallocs */
85         (GInstanceInitFunc) psppire_dict_init,
86       };
87
88       static const GInterfaceInfo tree_model_info = {
89         (GInterfaceInitFunc) dictionary_tree_model_init,
90         NULL,
91         NULL
92       };
93
94       object_type = g_type_register_static (G_TYPE_OBJECT,
95                                             "PsppireDict",
96                                             &object_info, 0);
97
98       g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
99                                    &tree_model_info);
100     }
101
102   return object_type;
103 }
104
105
106 static void
107 psppire_dict_class_init (PsppireDictClass *class)
108 {
109   GObjectClass *object_class = G_OBJECT_CLASS (class);
110
111   parent_class = g_type_class_peek_parent (class);
112
113   object_class->finalize = psppire_dict_finalize;
114
115   signals [BACKEND_CHANGED] =
116     g_signal_new ("backend-changed",
117                   G_TYPE_FROM_CLASS (class),
118                   G_SIGNAL_RUN_FIRST,
119                   0,
120                   NULL, NULL,
121                   g_cclosure_marshal_VOID__VOID,
122                   G_TYPE_NONE,
123                   0);
124
125
126   signals [VARIABLE_CHANGED] =
127     g_signal_new ("variable_changed",
128                   G_TYPE_FROM_CLASS (class),
129                   G_SIGNAL_RUN_FIRST,
130                   0,
131                   NULL, NULL,
132                   g_cclosure_marshal_VOID__INT,
133                   G_TYPE_NONE,
134                   1,
135                   G_TYPE_INT);
136
137
138
139   signals [VARIABLE_INSERTED] =
140     g_signal_new ("variable_inserted",
141                   G_TYPE_FROM_CLASS (class),
142                   G_SIGNAL_RUN_FIRST,
143                   0,
144                   NULL, NULL,
145                   g_cclosure_marshal_VOID__INT,
146                   G_TYPE_NONE,
147                   1,
148                   G_TYPE_INT);
149
150
151   signals [VARIABLE_DELETED] =
152     g_signal_new ("variable-deleted",
153                   G_TYPE_FROM_CLASS (class),
154                   G_SIGNAL_RUN_FIRST,
155                   0,
156                   NULL, NULL,
157                   psppire_marshal_VOID__INT_INT_INT,
158                   G_TYPE_NONE,
159                   3,
160                   G_TYPE_INT,
161                   G_TYPE_INT,
162                   G_TYPE_INT);
163
164
165   signals [VARIABLE_RESIZED] =
166     g_signal_new ("dict-size-changed",
167                   G_TYPE_FROM_CLASS (class),
168                   G_SIGNAL_RUN_FIRST,
169                   0,
170                   NULL, NULL,
171                   psppire_marshal_VOID__INT_INT,
172                   G_TYPE_NONE,
173                   2,
174                   G_TYPE_INT,
175                   G_TYPE_INT);
176
177   signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
178     g_signal_new ("variable-display-width-changed",
179                   G_TYPE_FROM_CLASS (class),
180                   G_SIGNAL_RUN_FIRST,
181                   0,
182                   NULL, NULL,
183                   g_cclosure_marshal_VOID__INT,
184                   G_TYPE_NONE,
185                   1,
186                   G_TYPE_INT);
187
188
189   signals [WEIGHT_CHANGED] =
190     g_signal_new ("weight-changed",
191                   G_TYPE_FROM_CLASS (class),
192                   G_SIGNAL_RUN_FIRST,
193                   0,
194                   NULL, NULL,
195                   g_cclosure_marshal_VOID__INT,
196                   G_TYPE_NONE,
197                   1,
198                   G_TYPE_INT);
199
200
201   signals [FILTER_CHANGED] =
202     g_signal_new ("filter-changed",
203                   G_TYPE_FROM_CLASS (class),
204                   G_SIGNAL_RUN_FIRST,
205                   0,
206                   NULL, NULL,
207                   g_cclosure_marshal_VOID__INT,
208                   G_TYPE_NONE,
209                   1,
210                   G_TYPE_INT);
211
212
213   signals [SPLIT_CHANGED] =
214     g_signal_new ("split-changed",
215                   G_TYPE_FROM_CLASS (class),
216                   G_SIGNAL_RUN_FIRST,
217                   0,
218                   NULL, NULL,
219                   g_cclosure_marshal_VOID__VOID,
220                   G_TYPE_NONE,
221                   0);
222 }
223
224 static void
225 psppire_dict_finalize (GObject *object)
226 {
227   PsppireDict *d = PSPPIRE_DICT (object);
228
229   dict_destroy (d->dict);
230
231   G_OBJECT_CLASS (parent_class)->finalize (object);
232 }
233
234 /* Pass on callbacks from src/data/dictionary, as
235    signals in the Gtk library */
236 static void
237 addcb (struct dictionary *d, int idx, void *pd)
238 {
239   PsppireDict *dict = PSPPIRE_DICT (pd);
240
241   if ( ! dict->disable_insert_signal)
242     g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
243 }
244
245 static void
246 delcb (struct dictionary *d, int dict_idx, int case_idx, int width, void *pd)
247 {
248   g_signal_emit (pd, signals [VARIABLE_DELETED], 0,
249                  dict_idx, case_idx, width );
250 }
251
252 static void
253 mutcb (struct dictionary *d, int idx, void *pd)
254 {
255   g_signal_emit (pd, signals [VARIABLE_CHANGED], 0, idx);
256 }
257
258 static void
259 resize_cb (struct dictionary *d, int idx, int old_width, void *pd)
260 {
261   g_signal_emit (pd, signals [VARIABLE_RESIZED], 0, idx, old_width);
262 }
263
264 static void
265 weight_changed_callback (struct dictionary *d, int idx, void *pd)
266 {
267   g_signal_emit (pd, signals [WEIGHT_CHANGED], 0, idx);
268 }
269
270 static void
271 filter_changed_callback (struct dictionary *d, int idx, void *pd)
272 {
273   g_signal_emit (pd, signals [FILTER_CHANGED], 0, idx);
274 }
275
276 static void
277 split_changed_callback (struct dictionary *d, void *pd)
278 {
279   g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
280 }
281
282 static void
283 variable_display_width_callback (struct dictionary *d, int idx, void *pd)
284 {
285   g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
286 }
287
288
289
290 static const struct dict_callbacks gui_callbacks =
291   {
292     addcb,
293     delcb,
294     mutcb,
295     resize_cb,
296     weight_changed_callback,
297     filter_changed_callback,
298     split_changed_callback,
299     variable_display_width_callback
300   };
301
302 static void
303 psppire_dict_init (PsppireDict *psppire_dict)
304 {
305   psppire_dict->stamp = g_random_int ();
306   psppire_dict->disable_insert_signal = FALSE;
307 }
308
309 /**
310  * psppire_dict_new_from_dict:
311  * @returns: a new #PsppireDict object
312  *
313  * Creates a new #PsppireDict.
314  */
315 PsppireDict*
316 psppire_dict_new_from_dict (struct dictionary *d)
317 {
318   PsppireDict *new_dict = g_object_new (PSPPIRE_TYPE_DICT, NULL);
319   new_dict->dict = d;
320
321   dict_set_callbacks (new_dict->dict, &gui_callbacks, new_dict);
322
323   return new_dict;
324 }
325
326
327 void
328 psppire_dict_replace_dictionary (PsppireDict *dict, struct dictionary *d)
329 {
330   struct variable *var =  dict_get_weight (d);
331
332   dict->dict = d;
333
334   weight_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
335
336   var = dict_get_filter (d);
337   filter_changed_callback (d, var ? var_get_dict_index (var) : -1, dict);
338
339   split_changed_callback (d, dict);
340
341   dict_set_callbacks (dict->dict, &gui_callbacks, dict);
342
343   g_signal_emit (dict, signals [BACKEND_CHANGED], 0);
344 }
345
346
347 /* Returns a valid name for a new variable in DICT.
348    The return value is statically allocated */
349 static gchar *
350 auto_generate_var_name (PsppireDict *dict)
351 {
352   gint d = 0;
353   static gchar name[10];
354
355   while (g_snprintf (name, 10, "VAR%05d",d++),
356          psppire_dict_lookup_var (dict, name))
357     ;
358
359   return name;
360 }
361
362 /* Insert a new variable at posn IDX, with the name NAME.
363    If NAME is null, then a name will be automatically assigned.
364 */
365 void
366 psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name)
367 {
368   struct variable *var ;
369   g_return_if_fail (idx >= 0);
370   g_return_if_fail (d);
371   g_return_if_fail (PSPPIRE_IS_DICT (d));
372
373   if ( ! name )
374     name = auto_generate_var_name (d);
375
376   d->disable_insert_signal = TRUE;
377
378   var = dict_create_var (d->dict, name, 0);
379
380   dict_reorder_var (d->dict, var, idx);
381
382   d->disable_insert_signal = FALSE;
383
384   g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
385 }
386
387 /* Delete N variables beginning at FIRST */
388 void
389 psppire_dict_delete_variables (PsppireDict *d, gint first, gint n)
390 {
391   gint idx;
392   g_return_if_fail (d);
393   g_return_if_fail (d->dict);
394   g_return_if_fail (PSPPIRE_IS_DICT (d));
395
396   for (idx = 0 ; idx < n ; ++idx )
397     {
398       struct variable *var;
399
400       /* Do nothing if it's out of bounds */
401       if ( first >= dict_get_var_cnt (d->dict))
402         break;
403
404       var = dict_get_var (d->dict, first);
405       dict_delete_var (d->dict, var);
406     }
407 }
408
409
410 gboolean
411 psppire_dict_set_name (PsppireDict* d, gint idx, const gchar *name)
412 {
413   struct variable *var;
414   g_assert (d);
415   g_assert (PSPPIRE_IS_DICT (d));
416
417   if ( ! var_is_valid_name (name, false))
418     return FALSE;
419
420   if ( idx < dict_get_var_cnt (d->dict))
421     {
422       /* This is an existing variable? */
423       var = dict_get_var (d->dict, idx);
424       dict_rename_var (d->dict, var, name);
425     }
426   else
427     {
428       /* new variable */
429       dict_create_var (d->dict, name, 0);
430     }
431
432   return TRUE;
433 }
434
435
436
437 /* Return the IDXth variable.
438    Will return NULL if IDX  exceeds the number of variables in the dictionary.
439  */
440 struct variable *
441 psppire_dict_get_variable (const PsppireDict *d, gint idx)
442 {
443   g_return_val_if_fail (d, NULL);
444   g_return_val_if_fail (d->dict, NULL);
445
446   if ( dict_get_var_cnt (d->dict) <= idx )
447     return NULL;
448
449   return dict_get_var (d->dict, idx);
450 }
451
452
453 /* Return the number of variables in the dictionary */
454 gint
455 psppire_dict_get_var_cnt (const PsppireDict *d)
456 {
457   g_return_val_if_fail (d, -1);
458   g_return_val_if_fail (d->dict, -1);
459
460   return dict_get_var_cnt (d->dict);
461 }
462
463
464 /* Return the number of `union value's in the dictionary */
465 size_t
466 psppire_dict_get_value_cnt (const PsppireDict *d)
467 {
468   g_return_val_if_fail (d, -1);
469   g_return_val_if_fail (d->dict, -1);
470
471   return dict_get_next_value_idx (d->dict);
472 }
473
474
475 /* Returns the prototype for the cases that match the dictionary */
476 const struct caseproto *
477 psppire_dict_get_proto (const PsppireDict *d)
478 {
479   g_return_val_if_fail (d, NULL);
480   g_return_val_if_fail (d->dict, NULL);
481
482   return dict_get_proto (d->dict);
483 }
484
485
486 /* Return a variable by name.
487    Return NULL if it doesn't exist
488 */
489 struct variable *
490 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
491 {
492   g_return_val_if_fail (d, NULL);
493   g_return_val_if_fail (d->dict, NULL);
494
495   return dict_lookup_var (d->dict, name);
496 }
497
498 /* Clears the contents of D */
499 void
500 psppire_dict_clear (PsppireDict *d)
501 {
502   g_return_if_fail (d);
503   g_return_if_fail (d->dict);
504
505   {
506     dict_clear (d->dict);
507   }
508 }
509
510
511 /* Return true is NAME would be a valid name of a variable to add to the
512    dictionary.  False otherwise.
513    If REPORT is true, then invalid names will be reported as such as errors
514 */
515 gboolean
516 psppire_dict_check_name (const PsppireDict *dict,
517                          const gchar *name, gboolean report)
518 {
519   if ( ! var_is_valid_name (name, report ) )
520     return FALSE;
521
522   if (psppire_dict_lookup_var (dict, name))
523     {
524       if ( report )
525         msg (ME,"Duplicate variable name.");
526       return FALSE;
527     }
528
529   return TRUE;
530 }
531
532
533 gint
534 psppire_dict_get_next_value_idx (const PsppireDict *dict)
535 {
536   return dict_get_next_value_idx (dict->dict);
537 }
538
539
540 void
541 psppire_dict_resize_variable (PsppireDict *d, const struct variable *pv,
542                               gint old_size, gint new_size)
543 {
544   g_return_if_fail (d);
545   g_return_if_fail (d->dict);
546
547   if ( old_size == new_size )
548     return ;
549
550   g_signal_emit (d, signals [VARIABLE_RESIZED], 0,
551                  var_get_dict_index (pv),
552                  new_size - old_size );
553 }
554
555
556 /* Tree Model Stuff */
557
558 static GtkTreeModelFlags tree_model_get_flags (GtkTreeModel *model);
559
560 static gint tree_model_n_columns (GtkTreeModel *model);
561
562 static GType tree_model_column_type (GtkTreeModel *model, gint index);
563
564 static gboolean tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
565                                      GtkTreePath *path);
566
567 static gboolean tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter);
568
569 static GtkTreePath * tree_model_get_path (GtkTreeModel *model,
570                                           GtkTreeIter *iter);
571
572 static void tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
573                                   gint column, GValue *value);
574
575 static gboolean tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
576                                       GtkTreeIter *parent, gint n);
577
578 static gint tree_model_n_children (GtkTreeModel *tree_model,
579                                    GtkTreeIter  *iter);
580
581 static gboolean tree_model_iter_children (GtkTreeModel *,
582                                           GtkTreeIter *,
583                                           GtkTreeIter *);
584
585 static gboolean tree_model_iter_parent (GtkTreeModel *tree_model,
586                                         GtkTreeIter *iter,
587                                         GtkTreeIter *child);
588
589 static gboolean tree_model_iter_has_child  (GtkTreeModel *tree_model,
590                                             GtkTreeIter  *iter);
591
592 static void
593 dictionary_tree_model_init (GtkTreeModelIface *iface)
594 {
595   iface->get_flags = tree_model_get_flags;
596   iface->get_n_columns = tree_model_n_columns;
597   iface->get_column_type = tree_model_column_type;
598   iface->get_iter = tree_model_get_iter;
599   iface->iter_next = tree_model_iter_next;
600   iface->get_path = tree_model_get_path;
601   iface->get_value = tree_model_get_value;
602
603   iface->iter_children = tree_model_iter_children ;
604   iface->iter_has_child = tree_model_iter_has_child ;
605   iface->iter_n_children = tree_model_n_children ;
606   iface->iter_nth_child = tree_model_nth_child ;
607   iface->iter_parent = tree_model_iter_parent ;
608 }
609
610 static gboolean
611 tree_model_iter_has_child  (GtkTreeModel *tree_model,
612                             GtkTreeIter  *iter)
613 {
614   return FALSE;
615 }
616
617 static gboolean
618 tree_model_iter_parent (GtkTreeModel *tree_model,
619                         GtkTreeIter *iter,
620                         GtkTreeIter *child)
621 {
622   return TRUE;
623 }
624
625 static GtkTreeModelFlags
626 tree_model_get_flags (GtkTreeModel *model)
627 {
628   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GtkTreeModelFlags) 0);
629
630   return GTK_TREE_MODEL_LIST_ONLY;
631 }
632
633
634 static gint
635 tree_model_n_columns (GtkTreeModel *model)
636 {
637   return n_DICT_COLS;
638 }
639
640 static GType
641 tree_model_column_type (GtkTreeModel *model, gint index)
642 {
643   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GType) 0);
644
645   switch (index)
646     {
647     case DICT_TVM_COL_NAME:
648       return G_TYPE_STRING;
649       break;
650     case DICT_TVM_COL_VAR:
651       return G_TYPE_POINTER;
652       break;
653     default:
654       g_return_val_if_reached ((GType)0);
655       break;
656     }
657
658   g_assert_not_reached ();
659   return ((GType)0);
660 }
661
662 static gboolean
663 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
664 {
665   gint *indices, depth;
666   gint n;
667   struct variable *var;
668
669   PsppireDict *dict = PSPPIRE_DICT (model);
670
671   g_return_val_if_fail (path, FALSE);
672
673   indices = gtk_tree_path_get_indices (path);
674   depth = gtk_tree_path_get_depth (path);
675
676   g_return_val_if_fail (depth == 1, FALSE);
677
678   n = indices [0];
679
680   if ( n < 0 || n >= psppire_dict_get_var_cnt (dict))
681     {
682       iter->stamp = 0;
683       iter->user_data = NULL;
684       return FALSE;
685     }
686
687   var = psppire_dict_get_variable (dict, n);
688
689   g_assert (var_get_dict_index (var) == n);
690
691   iter->stamp = dict->stamp;
692   iter->user_data = var;
693
694   return TRUE;
695 }
696
697
698 static gboolean
699 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
700 {
701   PsppireDict *dict = PSPPIRE_DICT (model);
702   struct variable *var;
703   gint idx;
704
705   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
706
707   if ( iter == NULL || iter->user_data == NULL)
708     return FALSE;
709
710   var = iter->user_data;
711
712   idx = var_get_dict_index (var);
713
714   if ( idx + 1 >= psppire_dict_get_var_cnt (dict))
715     {
716       iter->user_data = NULL;
717       iter->stamp = 0;
718       return FALSE;
719     }
720
721   var = psppire_dict_get_variable (dict, idx + 1);
722
723   g_assert (var_get_dict_index (var) == idx + 1);
724
725   iter->user_data = var;
726
727   return TRUE;
728 }
729
730 static GtkTreePath *
731 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
732 {
733   GtkTreePath *path;
734   struct variable *var;
735   PsppireDict *dict = PSPPIRE_DICT (model);
736
737   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
738
739   var = iter->user_data;
740
741   path = gtk_tree_path_new ();
742   gtk_tree_path_append_index (path, var_get_dict_index (var));
743
744   return path;
745 }
746
747
748 static void
749 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
750                       gint column, GValue *value)
751 {
752   struct variable *var;
753   PsppireDict *dict = PSPPIRE_DICT (model);
754
755   g_return_if_fail (iter->stamp == dict->stamp);
756
757   var =  iter->user_data;
758
759   switch (column)
760     {
761     case DICT_TVM_COL_NAME:
762       {
763         g_value_init (value, G_TYPE_STRING);
764         g_value_set_string (value, var_get_name (var));
765       }
766       break;
767     case DICT_TVM_COL_VAR:
768       g_value_init (value, G_TYPE_POINTER);
769       g_value_set_pointer (value, var);
770       break;
771     default:
772       g_return_if_reached ();
773       break;
774     }
775 }
776
777 static gboolean
778 tree_model_iter_children (GtkTreeModel *tree_model,
779                           GtkTreeIter *iter,
780                           GtkTreeIter *parent)
781 {
782   return FALSE;
783 }
784
785 static gint
786 tree_model_n_children (GtkTreeModel *model,
787                        GtkTreeIter  *iter)
788 {
789   PsppireDict *dict = PSPPIRE_DICT (model);
790
791   if ( iter == NULL )
792     return psppire_dict_get_var_cnt (dict);
793
794   return 0;
795 }
796
797 static gboolean
798 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
799                       GtkTreeIter *parent, gint n)
800 {
801   PsppireDict *dict;
802
803   g_return_val_if_fail (PSPPIRE_IS_DICT (model), FALSE);
804
805   dict = PSPPIRE_DICT (model);
806
807   if ( parent )
808     return FALSE;
809
810   if ( n >= psppire_dict_get_var_cnt (dict) )
811     return FALSE;
812
813   iter->stamp = dict->stamp;
814   iter->user_data = psppire_dict_get_variable (dict, n);
815
816   if ( !iter->user_data)
817     return FALSE;
818
819   return TRUE;
820 }
821
822
823 gboolean
824 psppire_dict_rename_var (PsppireDict *dict, struct variable *v,
825                          const gchar *name)
826 {
827   if ( ! var_is_valid_name (name, false))
828     return FALSE;
829
830   /* Make sure no other variable has this name */
831   if ( NULL != psppire_dict_lookup_var (dict, name))
832     return FALSE;
833
834   dict_rename_var (dict->dict, v, name);
835
836   return TRUE;
837 }
838
839
840 struct variable *
841 psppire_dict_get_weight_variable (const PsppireDict *dict)
842 {
843   return dict_get_weight (dict->dict);
844 }
845
846
847
848 #if DEBUGGING
849 void
850 psppire_dict_dump (const PsppireDict *dict)
851 {
852   gint i;
853   const struct dictionary *d = dict->dict;
854
855   for (i = 0; i < dict_get_var_cnt (d); ++i)
856     {
857       const struct variable *v = psppire_dict_get_variable (dict, i);
858       int di = var_get_dict_index (v);
859       g_print ("\"%s\" idx=%d, fv=%d\n",
860                var_get_name(v),
861                di,
862                var_get_case_index(v));
863
864     }
865 }
866 #endif
867
868
869
870
871 const gchar *
872 psppire_dict_encoding (const PsppireDict *dict)
873 {
874   return dict_get_encoding (dict->dict);
875 }