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