090ad90c5e8223a9efe4b19fb7b90bfbf40c2867
[pspp-builds.git] / src / ui / gui / psppire-dict.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2004, 2006, 2007  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 <gtksheet/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
30 #include "helper.h"
31 #include "message-dialog.h"
32
33
34 enum  {
35   BACKEND_CHANGED,
36
37   VARIABLE_CHANGED,
38   VARIABLE_RESIZED,
39   VARIABLE_INSERTED,
40   VARIABLE_DELETED,
41   VARIABLE_DISPLAY_WIDTH_CHANGED,
42
43   WEIGHT_CHANGED,
44   FILTER_CHANGED,
45   SPLIT_CHANGED,
46   n_SIGNALS
47 };
48
49
50 /* --- prototypes --- */
51 static void psppire_dict_class_init     (PsppireDictClass       *class);
52 static void psppire_dict_init   (PsppireDict            *dict);
53 static void psppire_dict_finalize       (GObject                *object);
54
55 static void dictionary_tree_model_init (GtkTreeModelIface *iface);
56
57
58 /* --- variables --- */
59 static GObjectClass     *parent_class = NULL;
60
61 static guint signals [n_SIGNALS];
62
63 /* --- functions --- */
64 /**
65  * psppire_dict_get_type:
66  * @returns: the type ID for accelerator groups.
67  */
68 GType
69 psppire_dict_get_type (void)
70 {
71   static GType object_type = 0;
72
73   if (!object_type)
74     {
75       static const GTypeInfo object_info = {
76         sizeof (PsppireDictClass),
77         (GBaseInitFunc) NULL,
78         (GBaseFinalizeFunc) NULL,
79         (GClassInitFunc) psppire_dict_class_init,
80         NULL,   /* class_finalize */
81         NULL,   /* class_data */
82         sizeof (PsppireDict),
83         0,      /* n_preallocs */
84         (GInstanceInitFunc) psppire_dict_init,
85       };
86
87       static const GInterfaceInfo tree_model_info = {
88         (GInterfaceInitFunc) dictionary_tree_model_init,
89         NULL,
90         NULL
91       };
92
93       object_type = g_type_register_static (G_TYPE_OBJECT,
94                                             "PsppireDict",
95                                             &object_info, 0);
96
97       g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
98                                    &tree_model_info);
99     }
100
101   return object_type;
102 }
103
104
105 static void
106 psppire_dict_class_init (PsppireDictClass *class)
107 {
108   GObjectClass *object_class = G_OBJECT_CLASS (class);
109
110   parent_class = g_type_class_peek_parent (class);
111
112   object_class->finalize = psppire_dict_finalize;
113
114   signals [BACKEND_CHANGED] =
115     g_signal_new ("backend-changed",
116                   G_TYPE_FROM_CLASS (class),
117                   G_SIGNAL_RUN_FIRST,
118                   0,
119                   NULL, NULL,
120                   g_cclosure_marshal_VOID__VOID,
121                   G_TYPE_NONE,
122                   0);
123
124
125   signals [VARIABLE_CHANGED] =
126     g_signal_new ("variable_changed",
127                   G_TYPE_FROM_CLASS (class),
128                   G_SIGNAL_RUN_FIRST,
129                   0,
130                   NULL, NULL,
131                   g_cclosure_marshal_VOID__INT,
132                   G_TYPE_NONE,
133                   1,
134                   G_TYPE_INT);
135
136
137
138   signals [VARIABLE_INSERTED] =
139     g_signal_new ("variable_inserted",
140                   G_TYPE_FROM_CLASS (class),
141                   G_SIGNAL_RUN_FIRST,
142                   0,
143                   NULL, NULL,
144                   g_cclosure_marshal_VOID__INT,
145                   G_TYPE_NONE,
146                   1,
147                   G_TYPE_INT);
148
149
150   signals [VARIABLE_DELETED] =
151     g_signal_new ("variable-deleted",
152                   G_TYPE_FROM_CLASS (class),
153                   G_SIGNAL_RUN_FIRST,
154                   0,
155                   NULL, NULL,
156                   psppire_marshal_VOID__INT_INT_INT,
157                   G_TYPE_NONE,
158                   3,
159                   G_TYPE_INT,
160                   G_TYPE_INT,
161                   G_TYPE_INT);
162
163
164   signals [VARIABLE_RESIZED] =
165     g_signal_new ("dict-size-changed",
166                   G_TYPE_FROM_CLASS (class),
167                   G_SIGNAL_RUN_FIRST,
168                   0,
169                   NULL, NULL,
170                   psppire_marshal_VOID__INT_INT,
171                   G_TYPE_NONE,
172                   2,
173                   G_TYPE_INT,
174                   G_TYPE_INT);
175
176   signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
177     g_signal_new ("variable-display-width-changed",
178                   G_TYPE_FROM_CLASS (class),
179                   G_SIGNAL_RUN_FIRST,
180                   0,
181                   NULL, NULL,
182                   g_cclosure_marshal_VOID__INT,
183                   G_TYPE_NONE,
184                   1,
185                   G_TYPE_INT);
186
187
188   signals [WEIGHT_CHANGED] =
189     g_signal_new ("weight-changed",
190                   G_TYPE_FROM_CLASS (class),
191                   G_SIGNAL_RUN_FIRST,
192                   0,
193                   NULL, NULL,
194                   g_cclosure_marshal_VOID__INT,
195                   G_TYPE_NONE,
196                   1,
197                   G_TYPE_INT);
198
199
200   signals [FILTER_CHANGED] =
201     g_signal_new ("filter-changed",
202                   G_TYPE_FROM_CLASS (class),
203                   G_SIGNAL_RUN_FIRST,
204                   0,
205                   NULL, NULL,
206                   g_cclosure_marshal_VOID__INT,
207                   G_TYPE_NONE,
208                   1,
209                   G_TYPE_INT);
210
211
212   signals [SPLIT_CHANGED] =
213     g_signal_new ("split-changed",
214                   G_TYPE_FROM_CLASS (class),
215                   G_SIGNAL_RUN_FIRST,
216                   0,
217                   NULL, NULL,
218                   g_cclosure_marshal_VOID__VOID,
219                   G_TYPE_NONE,
220                   0);
221 }
222
223 static void
224 psppire_dict_finalize (GObject *object)
225 {
226   PsppireDict *d = PSPPIRE_DICT (object);
227
228   dict_destroy (d->dict);
229
230   G_OBJECT_CLASS (parent_class)->finalize (object);
231 }
232
233 /* Pass on callbacks from src/data/dictionary, as
234    signals in the Gtk library */
235 static void
236 addcb (struct dictionary *d, int idx, void *pd)
237 {
238   PsppireDict *dict = PSPPIRE_DICT (pd);
239
240   if ( ! dict->disable_insert_signal)
241     g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
242 }
243
244 static void
245 delcb (struct dictionary *d, int dict_idx, int case_idx, int value_cnt,
246        void *pd)
247 {
248   g_signal_emit (pd, signals [VARIABLE_DELETED], 0,
249                  dict_idx, case_idx, value_cnt );
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 delta, void *pd)
260 {
261   g_signal_emit (pd, signals [VARIABLE_RESIZED], 0, idx, delta);
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 (G_TYPE_PSPPIRE_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 /* Return a variable by name.
476    Return NULL if it doesn't exist
477 */
478 struct variable *
479 psppire_dict_lookup_var (const PsppireDict *d, const gchar *name)
480 {
481   g_return_val_if_fail (d, NULL);
482   g_return_val_if_fail (d->dict, NULL);
483
484   return dict_lookup_var (d->dict, name);
485 }
486
487 /* Clears the contents of D */
488 void
489 psppire_dict_clear (PsppireDict *d)
490 {
491   g_return_if_fail (d);
492   g_return_if_fail (d->dict);
493
494   {
495     dict_clear (d->dict);
496   }
497 }
498
499
500 /* Return true is NAME would be a valid name of a variable to add to the
501    dictionary.  False otherwise.
502    If REPORT is true, then invalid names will be reported as such as errors
503 */
504 gboolean
505 psppire_dict_check_name (const PsppireDict *dict,
506                          const gchar *name, gboolean report)
507 {
508   if ( ! var_is_valid_name (name, report ) )
509     return FALSE;
510
511   if (psppire_dict_lookup_var (dict, name))
512     {
513       if ( report )
514         msg (ME,"Duplicate variable name.");
515       return FALSE;
516     }
517
518   return TRUE;
519 }
520
521
522 gint
523 psppire_dict_get_next_value_idx (const PsppireDict *dict)
524 {
525   return dict_get_next_value_idx (dict->dict);
526 }
527
528
529 void
530 psppire_dict_resize_variable (PsppireDict *d, const struct variable *pv,
531                               gint old_size, gint new_size)
532 {
533   gint fv;
534   g_return_if_fail (d);
535   g_return_if_fail (d->dict);
536
537   if ( old_size == new_size )
538     return ;
539
540   fv = var_get_case_index (pv);
541
542   g_signal_emit (d, signals [VARIABLE_RESIZED], 0,
543                  fv + old_size,
544                  new_size - old_size );
545 }
546
547
548 /* Tree Model Stuff */
549
550 static GtkTreeModelFlags tree_model_get_flags (GtkTreeModel *model);
551
552 static gint tree_model_n_columns (GtkTreeModel *model);
553
554 static GType tree_model_column_type (GtkTreeModel *model, gint index);
555
556 static gboolean tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
557                                      GtkTreePath *path);
558
559 static gboolean tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter);
560
561 static GtkTreePath * tree_model_get_path (GtkTreeModel *model,
562                                           GtkTreeIter *iter);
563
564 static void tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
565                                   gint column, GValue *value);
566
567 static gboolean tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
568                                       GtkTreeIter *parent, gint n);
569
570 static gint tree_model_n_children (GtkTreeModel *tree_model,
571                                    GtkTreeIter  *iter);
572
573 static gboolean tree_model_iter_children (GtkTreeModel *,
574                                           GtkTreeIter *,
575                                           GtkTreeIter *);
576
577 static gboolean tree_model_iter_parent (GtkTreeModel *tree_model,
578                                         GtkTreeIter *iter,
579                                         GtkTreeIter *child);
580
581 static gboolean tree_model_iter_has_child  (GtkTreeModel *tree_model,
582                                             GtkTreeIter  *iter);
583
584 static void
585 dictionary_tree_model_init (GtkTreeModelIface *iface)
586 {
587   iface->get_flags = tree_model_get_flags;
588   iface->get_n_columns = tree_model_n_columns;
589   iface->get_column_type = tree_model_column_type;
590   iface->get_iter = tree_model_get_iter;
591   iface->iter_next = tree_model_iter_next;
592   iface->get_path = tree_model_get_path;
593   iface->get_value = tree_model_get_value;
594
595   iface->iter_children = tree_model_iter_children ;
596   iface->iter_has_child = tree_model_iter_has_child ;
597   iface->iter_n_children = tree_model_n_children ;
598   iface->iter_nth_child = tree_model_nth_child ;
599   iface->iter_parent = tree_model_iter_parent ;
600 }
601
602 static gboolean
603 tree_model_iter_has_child  (GtkTreeModel *tree_model,
604                             GtkTreeIter  *iter)
605 {
606   return FALSE;
607 }
608
609 static gboolean
610 tree_model_iter_parent (GtkTreeModel *tree_model,
611                         GtkTreeIter *iter,
612                         GtkTreeIter *child)
613 {
614   return TRUE;
615 }
616
617 static GtkTreeModelFlags
618 tree_model_get_flags (GtkTreeModel *model)
619 {
620   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GtkTreeModelFlags) 0);
621
622   return GTK_TREE_MODEL_LIST_ONLY;
623 }
624
625
626 static gint
627 tree_model_n_columns (GtkTreeModel *model)
628 {
629   return n_DICT_COLS;
630 }
631
632 static GType
633 tree_model_column_type (GtkTreeModel *model, gint index)
634 {
635   g_return_val_if_fail (PSPPIRE_IS_DICT (model), (GType) 0);
636
637   switch (index)
638     {
639     case DICT_TVM_COL_NAME:
640       return G_TYPE_STRING;
641       break;
642     case DICT_TVM_COL_VAR:
643       return G_TYPE_POINTER;
644       break;
645     default:
646       g_return_val_if_reached ((GType)0);
647       break;
648     }
649
650   g_assert_not_reached ();
651   return ((GType)0);
652 }
653
654 static gboolean
655 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
656 {
657   gint *indices, depth;
658   gint n;
659   struct variable *var;
660
661   PsppireDict *dict = PSPPIRE_DICT (model);
662
663   g_return_val_if_fail (path, FALSE);
664
665   indices = gtk_tree_path_get_indices (path);
666   depth = gtk_tree_path_get_depth (path);
667
668   g_return_val_if_fail (depth == 1, FALSE);
669
670   n = indices [0];
671
672   if ( n < 0 || n >= psppire_dict_get_var_cnt (dict))
673     {
674       iter->stamp = 0;
675       iter->user_data = NULL;
676       return FALSE;
677     }
678
679   var = psppire_dict_get_variable (dict, n);
680
681   g_assert (var_get_dict_index (var) == n);
682
683   iter->stamp = dict->stamp;
684   iter->user_data = var;
685
686   return TRUE;
687 }
688
689
690 static gboolean
691 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
692 {
693   PsppireDict *dict = PSPPIRE_DICT (model);
694   struct variable *var;
695   gint idx;
696
697   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
698
699   if ( iter == NULL || iter->user_data == NULL)
700     return FALSE;
701
702   var = iter->user_data;
703
704   idx = var_get_dict_index (var);
705
706   if ( idx + 1 >= psppire_dict_get_var_cnt (dict))
707     {
708       iter->user_data = NULL;
709       iter->stamp = 0;
710       return FALSE;
711     }
712
713   var = psppire_dict_get_variable (dict, idx + 1);
714
715   g_assert (var_get_dict_index (var) == idx + 1);
716
717   iter->user_data = var;
718
719   return TRUE;
720 }
721
722 static GtkTreePath *
723 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
724 {
725   GtkTreePath *path;
726   struct variable *var;
727   PsppireDict *dict = PSPPIRE_DICT (model);
728
729   g_return_val_if_fail (iter->stamp == dict->stamp, FALSE);
730
731   var = iter->user_data;
732
733   path = gtk_tree_path_new ();
734   gtk_tree_path_append_index (path, var_get_dict_index (var));
735
736   return path;
737 }
738
739
740 static void
741 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
742                       gint column, GValue *value)
743 {
744   struct variable *var;
745   PsppireDict *dict = PSPPIRE_DICT (model);
746
747   g_return_if_fail (iter->stamp == dict->stamp);
748
749   var =  iter->user_data;
750
751   switch (column)
752     {
753     case DICT_TVM_COL_NAME:
754       {
755       gchar *name = pspp_locale_to_utf8(var_get_name (var), -1, NULL);
756       g_value_init (value, G_TYPE_STRING);
757       g_value_set_string (value, name);
758       g_free (name);
759       }
760       break;
761     case DICT_TVM_COL_VAR:
762       g_value_init (value, G_TYPE_POINTER);
763       g_value_set_pointer (value, var);
764       break;
765     default:
766       g_return_if_reached ();
767       break;
768     }
769 }
770
771 static gboolean
772 tree_model_iter_children (GtkTreeModel *tree_model,
773                           GtkTreeIter *iter,
774                           GtkTreeIter *parent)
775 {
776   return FALSE;
777 }
778
779 static gint
780 tree_model_n_children (GtkTreeModel *model,
781                        GtkTreeIter  *iter)
782 {
783   PsppireDict *dict = PSPPIRE_DICT (model);
784
785   if ( iter == NULL )
786     return psppire_dict_get_var_cnt (dict);
787
788   return 0;
789 }
790
791 static gboolean
792 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
793                       GtkTreeIter *parent, gint n)
794 {
795   PsppireDict *dict;
796
797   g_return_val_if_fail (PSPPIRE_IS_DICT (model), FALSE);
798
799   dict = PSPPIRE_DICT (model);
800
801   if ( parent )
802     return FALSE;
803
804   if ( n >= psppire_dict_get_var_cnt (dict) )
805     return FALSE;
806
807   iter->stamp = dict->stamp;
808   iter->user_data = psppire_dict_get_variable (dict, n);
809
810   if ( !iter->user_data)
811     return FALSE;
812
813   return TRUE;
814 }
815
816
817 gboolean
818 psppire_dict_rename_var (PsppireDict *dict, struct variable *v,
819                          const gchar *name)
820 {
821   if ( ! var_is_valid_name (name, false))
822     return FALSE;
823
824   /* Make sure no other variable has this name */
825   if ( NULL != psppire_dict_lookup_var (dict, name))
826     return FALSE;
827
828   dict_rename_var (dict->dict, v, name);
829
830   return TRUE;
831 }
832
833
834 struct variable *
835 psppire_dict_get_weight_variable (const PsppireDict *dict)
836 {
837   return dict_get_weight (dict->dict);
838 }
839
840
841
842 #if DEBUGGING
843 void
844 psppire_dict_dump (const PsppireDict *dict)
845 {
846   gint i;
847   const struct dictionary *d = dict->dict;
848
849   for (i = 0; i < dict_get_var_cnt (d); ++i)
850     {
851       const struct variable *v = psppire_dict_get_variable (dict, i);
852       int di = var_get_dict_index (v);
853       g_print ("\"%s\" idx=%d, fv=%d, size=%d\n",
854                var_get_name(v),
855                di,
856                var_get_case_index(v),
857                value_cnt_from_width(var_get_width(v)));
858
859     }
860 }
861 #endif