gui: Fix behavior of print preview in psppire-output-window.
[pspp] / src / data / dictionary.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
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 "data/dictionary.h"
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <unistr.h>
25
26 #include "data/attributes.h"
27 #include "data/case.h"
28 #include "data/identifier.h"
29 #include "data/mrset.h"
30 #include "data/settings.h"
31 #include "data/value-labels.h"
32 #include "data/vardict.h"
33 #include "data/variable.h"
34 #include "data/vector.h"
35 #include "libpspp/array.h"
36 #include "libpspp/assertion.h"
37 #include "libpspp/compiler.h"
38 #include "libpspp/hash-functions.h"
39 #include "libpspp/hmap.h"
40 #include "libpspp/i18n.h"
41 #include "libpspp/message.h"
42 #include "libpspp/misc.h"
43 #include "libpspp/pool.h"
44 #include "libpspp/str.h"
45 #include "libpspp/string-array.h"
46
47 #include "gl/intprops.h"
48 #include "gl/minmax.h"
49 #include "gl/xalloc.h"
50 #include "gl/xmemdup0.h"
51
52 #include "gettext.h"
53 #define _(msgid) gettext (msgid)
54
55 /* A dictionary. */
56 struct dictionary
57   {
58     struct vardict_info *var;   /* Variables. */
59     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
60     struct caseproto *proto;    /* Prototype for dictionary cases
61                                    (updated lazily). */
62     struct hmap name_map;       /* Variable index by name. */
63     int next_value_idx;         /* Index of next `union value' to allocate. */
64     const struct variable **split;    /* SPLIT FILE vars. */
65     size_t split_cnt;           /* SPLIT FILE count. */
66     struct variable *weight;    /* WEIGHT variable. */
67     struct variable *filter;    /* FILTER variable. */
68     casenumber case_limit;      /* Current case limit (N command). */
69     char *label;                /* File label. */
70     struct string_array documents; /* Documents. */
71     struct vector **vector;     /* Vectors of variables. */
72     size_t vector_cnt;          /* Number of vectors. */
73     struct attrset attributes;  /* Custom attributes. */
74     struct mrset **mrsets;      /* Multiple response sets. */
75     size_t n_mrsets;            /* Number of multiple response sets. */
76
77     char *encoding;             /* Character encoding of string data */
78
79     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
80                                                modification */
81     void *cb_data ;                  /* Data passed to callbacks */
82
83     void (*changed) (struct dictionary *, void *); /* Generic change callback */
84     void *changed_data;
85   };
86
87 static void dict_unset_split_var (struct dictionary *, struct variable *);
88 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
89
90 /* Returns the encoding for data in dictionary D.  The return value is a
91    nonnull string that contains an IANA character set name. */
92 const char *
93 dict_get_encoding (const struct dictionary *d)
94 {
95   return d->encoding ;
96 }
97
98 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
99    encoding, false otherwise.  If ISSUE_ERROR is true, issues an explanatory
100    error message on failure. */
101 bool
102 dict_id_is_valid (const struct dictionary *dict, const char *id,
103                   bool issue_error)
104 {
105   return id_is_valid (id, dict->encoding, issue_error);
106 }
107
108 void
109 dict_set_change_callback (struct dictionary *d,
110                           void (*changed) (struct dictionary *, void*),
111                           void *data)
112 {
113   d->changed = changed;
114   d->changed_data = data;
115 }
116
117 /* Discards dictionary D's caseproto.  (It will be regenerated
118    lazily, on demand.) */
119 static void
120 invalidate_proto (struct dictionary *d)
121 {
122   caseproto_unref (d->proto);
123   d->proto = NULL;
124 }
125
126 /* Print a representation of dictionary D to stdout, for
127    debugging purposes. */
128 void
129 dict_dump (const struct dictionary *d)
130 {
131   int i;
132   for (i = 0 ; i < d->var_cnt ; ++i )
133     {
134       const struct variable *v = d->var[i].var;
135       printf ("Name: %s;\tdict_idx: %zu; case_idx: %zu\n",
136               var_get_name (v),
137               var_get_dict_index (v),
138               var_get_case_index (v));
139
140     }
141 }
142
143 /* Associate CALLBACKS with DICT.  Callbacks will be invoked whenever
144    the dictionary or any of the variables it contains are modified.
145    Each callback will get passed CALLBACK_DATA.
146    Any callback may be NULL, in which case it'll be ignored.
147 */
148 void
149 dict_set_callbacks (struct dictionary *dict,
150                     const struct dict_callbacks *callbacks,
151                     void *callback_data)
152 {
153   dict->callbacks = callbacks;
154   dict->cb_data = callback_data;
155 }
156
157 /* Shallow copy the callbacks from SRC to DEST */
158 void
159 dict_copy_callbacks (struct dictionary *dest,
160                      const struct dictionary *src)
161 {
162   dest->callbacks = src->callbacks;
163   dest->cb_data = src->cb_data;
164 }
165
166 /* Creates and returns a new dictionary with the specified ENCODING. */
167 struct dictionary *
168 dict_create (const char *encoding)
169 {
170   struct dictionary *d = xzalloc (sizeof *d);
171
172   d->encoding = xstrdup (encoding);
173   hmap_init (&d->name_map);
174   attrset_init (&d->attributes);
175
176   return d;
177 }
178
179 /* Creates and returns a (deep) copy of an existing
180    dictionary.
181
182    The new dictionary's case indexes are copied from the old
183    dictionary.  If the new dictionary won't be used to access
184    cases produced with the old dictionary, then the new
185    dictionary's case indexes should be compacted with
186    dict_compact_values to save space.
187
188    Callbacks are not cloned. */
189 struct dictionary *
190 dict_clone (const struct dictionary *s)
191 {
192   struct dictionary *d;
193   size_t i;
194
195   d = dict_create (s->encoding);
196
197   /* Set the new dictionary's encoding early so that string length limitations
198      are interpreted correctly. */
199   d->encoding = xstrdup (s->encoding);
200
201   for (i = 0; i < s->var_cnt; i++)
202     {
203       struct variable *sv = s->var[i].var;
204       struct variable *dv = dict_clone_var_assert (d, sv);
205       size_t i;
206
207       for (i = 0; i < var_get_short_name_cnt (sv); i++)
208         var_set_short_name (dv, i, var_get_short_name (sv, i));
209
210       var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
211     }
212
213   d->next_value_idx = s->next_value_idx;
214
215   d->split_cnt = s->split_cnt;
216   if (d->split_cnt > 0)
217     {
218       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
219       for (i = 0; i < d->split_cnt; i++)
220         d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
221     }
222
223   if (s->weight != NULL)
224     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
225
226   if (s->filter != NULL)
227     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
228
229   d->case_limit = s->case_limit;
230   dict_set_label (d, dict_get_label (s));
231   dict_set_documents (d, dict_get_documents (s));
232
233   d->vector_cnt = s->vector_cnt;
234   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
235   for (i = 0; i < s->vector_cnt; i++)
236     d->vector[i] = vector_clone (s->vector[i], s, d);
237
238   dict_set_attributes (d, dict_get_attributes (s));
239
240   for (i = 0; i < s->n_mrsets; i++)
241     {
242       const struct mrset *old = s->mrsets[i];
243       struct mrset *new;
244       size_t j;
245
246       /* Clone old mrset, then replace vars from D by vars from S. */
247       new = mrset_clone (old);
248       for (j = 0; j < new->n_vars; j++)
249         new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
250
251       dict_add_mrset (d, new);
252     }
253
254   return d;
255 }
256
257 /* Clears the contents from a dictionary without destroying the
258    dictionary itself. */
259 void
260 dict_clear (struct dictionary *d)
261 {
262   /* FIXME?  Should we really clear case_limit, label, documents?
263      Others are necessarily cleared by deleting all the variables.*/
264   while (d->var_cnt > 0 )
265     {
266       dict_delete_var (d, d->var[d->var_cnt - 1].var);
267     }
268
269   free (d->var);
270   d->var = NULL;
271   d->var_cnt = d->var_cap = 0;
272   invalidate_proto (d);
273   hmap_clear (&d->name_map);
274   d->next_value_idx = 0;
275   dict_set_split_vars (d, NULL, 0);
276   dict_set_weight (d, NULL);
277   dict_set_filter (d, NULL);
278   d->case_limit = 0;
279   free (d->label);
280   d->label = NULL;
281   string_array_clear (&d->documents);
282   dict_clear_vectors (d);
283   attrset_clear (&d->attributes);
284 }
285
286 /* Destroys the aux data for every variable in D, by calling
287    var_clear_aux() for each variable. */
288 void
289 dict_clear_aux (struct dictionary *d)
290 {
291   int i;
292
293   for (i = 0; i < d->var_cnt; i++)
294     var_clear_aux (d->var[i].var);
295 }
296
297 /* Clears a dictionary and destroys it. */
298 void
299 dict_destroy (struct dictionary *d)
300 {
301   if (d != NULL)
302     {
303       /* In general, we don't want callbacks occuring, if the dictionary
304          is being destroyed */
305       d->callbacks  = NULL ;
306
307       dict_clear (d);
308       hmap_destroy (&d->name_map);
309       attrset_destroy (&d->attributes);
310       dict_clear_mrsets (d);
311       free (d->encoding);
312       free (d);
313     }
314 }
315
316 /* Returns the number of variables in D. */
317 size_t
318 dict_get_var_cnt (const struct dictionary *d)
319 {
320   return d->var_cnt;
321 }
322
323 /* Returns the variable in D with dictionary index IDX, which
324    must be between 0 and the count returned by
325    dict_get_var_cnt(), exclusive. */
326 struct variable *
327 dict_get_var (const struct dictionary *d, size_t idx)
328 {
329   assert (idx < d->var_cnt);
330
331   return d->var[idx].var;
332 }
333
334 /* Sets *VARS to an array of pointers to variables in D and *CNT
335    to the number of variables in *D.  All variables are returned
336    except for those, if any, in the classes indicated by EXCLUDE.
337    (There is no point in putting DC_SYSTEM in EXCLUDE as
338    dictionaries never include system variables.) */
339 void
340 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
341                size_t *cnt, enum dict_class exclude)
342 {
343   dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude);
344 }
345
346 /* Sets *VARS to an array of pointers to variables in D and *CNT
347    to the number of variables in *D.  All variables are returned
348    except for those, if any, in the classes indicated by EXCLUDE.
349    (There is no point in putting DC_SYSTEM in EXCLUDE as
350    dictionaries never include system variables.) */
351 void
352 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
353                        size_t *cnt, enum dict_class exclude)
354 {
355   size_t count;
356   size_t i;
357
358   assert (exclude == (exclude & DC_ALL));
359
360   count = 0;
361   for (i = 0; i < d->var_cnt; i++)
362     {
363       enum dict_class class = var_get_dict_class (d->var[i].var);
364       if (!(class & exclude))
365         count++;
366     }
367
368   *vars = xnmalloc (count, sizeof **vars);
369   *cnt = 0;
370   for (i = 0; i < d->var_cnt; i++)
371     {
372       enum dict_class class = var_get_dict_class (d->var[i].var);
373       if (!(class & exclude))
374         (*vars)[(*cnt)++] = d->var[i].var;
375     }
376   assert (*cnt == count);
377 }
378
379 static struct variable *
380 add_var (struct dictionary *d, struct variable *v)
381 {
382   struct vardict_info *vardict;
383
384   /* Update dictionary. */
385   if (d->var_cnt >= d->var_cap)
386     {
387       size_t i;
388
389       d->var = x2nrealloc (d->var, &d->var_cap, sizeof *d->var);
390       hmap_clear (&d->name_map);
391       for (i = 0; i < d->var_cnt; i++)
392         {
393           var_set_vardict (d->var[i].var, &d->var[i]);
394           hmap_insert_fast (&d->name_map, &d->var[i].name_node,
395                             d->var[i].name_node.hash);
396         }
397     }
398
399   vardict = &d->var[d->var_cnt++];
400   vardict->dict = d;
401   vardict->var = v;
402   hmap_insert (&d->name_map, &vardict->name_node,
403                hash_case_string (var_get_name (v), 0));
404   vardict->case_index = d->next_value_idx;
405   var_set_vardict (v, vardict);
406
407   if ( d->changed ) d->changed (d, d->changed_data);
408   if ( d->callbacks &&  d->callbacks->var_added )
409     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
410
411   d->next_value_idx++;
412   invalidate_proto (d);
413
414   return v;
415 }
416
417 /* Creates and returns a new variable in D with the given NAME
418    and WIDTH.  Returns a null pointer if the given NAME would
419    duplicate that of an existing variable in the dictionary. */
420 struct variable *
421 dict_create_var (struct dictionary *d, const char *name, int width)
422 {
423   return (dict_lookup_var (d, name) == NULL
424           ? dict_create_var_assert (d, name, width)
425           : NULL);
426 }
427
428 /* Creates and returns a new variable in D with the given NAME
429    and WIDTH.  Assert-fails if the given NAME would duplicate
430    that of an existing variable in the dictionary. */
431 struct variable *
432 dict_create_var_assert (struct dictionary *d, const char *name, int width)
433 {
434   assert (dict_lookup_var (d, name) == NULL);
435   return add_var (d, var_create (name, width));
436 }
437
438 /* Creates and returns a new variable in D, as a copy of existing variable
439    OLD_VAR, which need not be in D or in any dictionary.  Returns a null
440    pointer if OLD_VAR's name would duplicate that of an existing variable in
441    the dictionary. */
442 struct variable *
443 dict_clone_var (struct dictionary *d, const struct variable *old_var)
444 {
445   return dict_clone_var_as (d, old_var, var_get_name (old_var));
446 }
447
448 /* Creates and returns a new variable in D, as a copy of existing variable
449    OLD_VAR, which need not be in D or in any dictionary.  Assert-fails if
450    OLD_VAR's name would duplicate that of an existing variable in the
451    dictionary. */
452 struct variable *
453 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var)
454 {
455   return dict_clone_var_as_assert (d, old_var, var_get_name (old_var));
456 }
457
458 /* Creates and returns a new variable in D with name NAME, as a copy of
459    existing variable OLD_VAR, which need not be in D or in any dictionary.
460    Returns a null pointer if the given NAME would duplicate that of an existing
461    variable in the dictionary. */
462 struct variable *
463 dict_clone_var_as (struct dictionary *d, const struct variable *old_var,
464                    const char *name)
465 {
466   return (dict_lookup_var (d, name) == NULL
467           ? dict_clone_var_as_assert (d, old_var, name)
468           : NULL);
469 }
470
471 /* Creates and returns a new variable in D with name NAME, as a copy of
472    existing variable OLD_VAR, which need not be in D or in any dictionary.
473    Assert-fails if the given NAME would duplicate that of an existing variable
474    in the dictionary. */
475 struct variable *
476 dict_clone_var_as_assert (struct dictionary *d, const struct variable *old_var,
477                           const char *name)
478 {
479   struct variable *new_var = var_clone (old_var);
480   assert (dict_lookup_var (d, name) == NULL);
481   var_set_name (new_var, name);
482   return add_var (d, new_var);
483 }
484
485 /* Returns the variable named NAME in D, or a null pointer if no
486    variable has that name. */
487 struct variable *
488 dict_lookup_var (const struct dictionary *d, const char *name)
489 {
490   struct vardict_info *vardict;
491
492   HMAP_FOR_EACH_WITH_HASH (vardict, struct vardict_info, name_node,
493                            hash_case_string (name, 0), &d->name_map)
494     {
495       struct variable *var = vardict->var;
496       if (!strcasecmp (var_get_name (var), name))
497         return var;
498     }
499
500   return NULL;
501 }
502
503 /* Returns the variable named NAME in D.  Assert-fails if no
504    variable has that name. */
505 struct variable *
506 dict_lookup_var_assert (const struct dictionary *d, const char *name)
507 {
508   struct variable *v = dict_lookup_var (d, name);
509   assert (v != NULL);
510   return v;
511 }
512
513 /* Returns true if variable V is in dictionary D,
514    false otherwise. */
515 bool
516 dict_contains_var (const struct dictionary *d, const struct variable *v)
517 {
518   return (var_has_vardict (v)
519           && vardict_get_dictionary (var_get_vardict (v)) == d);
520 }
521
522 /* Compares two double pointers to variables, which should point
523    to elements of a struct dictionary's `var' member array. */
524 static int
525 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
526 {
527   struct variable *const *a = a_;
528   struct variable *const *b = b_;
529
530   return *a < *b ? -1 : *a > *b;
531 }
532
533 static void
534 unindex_var (struct dictionary *d, struct vardict_info *vardict)
535 {
536   hmap_delete (&d->name_map, &vardict->name_node);
537 }
538
539 /* This function assumes that vardict->name_node.hash is valid, that is, that
540    its name has not changed since it was hashed (rename_var() updates this
541    hash along with the name itself). */
542 static void
543 reindex_var (struct dictionary *d, struct vardict_info *vardict)
544 {
545   struct variable *var = vardict->var;
546
547   var_set_vardict (var, vardict);
548   hmap_insert_fast (&d->name_map, &vardict->name_node,
549                     vardict->name_node.hash);
550
551   if ( d->changed ) d->changed (d, d->changed_data);
552   if ( d->callbacks &&  d->callbacks->var_changed )
553     d->callbacks->var_changed (d, var_get_dict_index (var), d->cb_data);
554 }
555
556 /* Sets the case_index in V's vardict to CASE_INDEX. */
557 static void
558 set_var_case_index (struct variable *v, int case_index)
559 {
560   var_get_vardict (v)->case_index = case_index;
561 }
562
563 /* Removes the dictionary variables with indexes from FROM to TO (exclusive)
564    from name_map. */
565 static void
566 unindex_vars (struct dictionary *d, size_t from, size_t to)
567 {
568   size_t i;
569
570   for (i = from; i < to; i++)
571     unindex_var (d, &d->var[i]);
572 }
573
574 /* Re-sets the dict_index in the dictionary variables with
575    indexes from FROM to TO (exclusive). */
576 static void
577 reindex_vars (struct dictionary *d, size_t from, size_t to)
578 {
579   size_t i;
580
581   for (i = from; i < to; i++)
582     reindex_var (d, &d->var[i]);
583 }
584
585 /* Deletes variable V from dictionary D and frees V.
586
587    This is a very bad idea if there might be any pointers to V
588    from outside D.  In general, no variable in the active dataset's
589    dictionary should be deleted when any transformations are
590    active on the dictionary's dataset, because those
591    transformations might reference the deleted variable.  The
592    safest time to delete a variable is just after a procedure has
593    been executed, as done by DELETE VARIABLES.
594
595    Pointers to V within D are not a problem, because
596    dict_delete_var() knows to remove V from split variables,
597    weights, filters, etc. */
598 void
599 dict_delete_var (struct dictionary *d, struct variable *v)
600 {
601   int dict_index = var_get_dict_index (v);
602   const int case_index = var_get_case_index (v);
603   const int width = var_get_width (v);
604
605   assert (dict_contains_var (d, v));
606
607   /* Delete aux data. */
608   var_clear_aux (v);
609
610   dict_unset_split_var (d, v);
611   dict_unset_mrset_var (d, v);
612
613   if (d->weight == v)
614     dict_set_weight (d, NULL);
615
616   if (d->filter == v)
617     dict_set_filter (d, NULL);
618
619   dict_clear_vectors (d);
620
621   /* Remove V from var array. */
622   unindex_vars (d, dict_index, d->var_cnt);
623   remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
624   d->var_cnt--;
625
626   /* Update dict_index for each affected variable. */
627   reindex_vars (d, dict_index, d->var_cnt);
628
629   /* Free memory. */
630   var_clear_vardict (v);
631   var_destroy (v);
632
633   if ( d->changed ) d->changed (d, d->changed_data);
634
635   invalidate_proto (d);
636   if (d->callbacks &&  d->callbacks->var_deleted )
637     d->callbacks->var_deleted (d, dict_index, case_index, width, d->cb_data);
638 }
639
640 /* Deletes the COUNT variables listed in VARS from D.  This is
641    unsafe; see the comment on dict_delete_var() for details. */
642 void
643 dict_delete_vars (struct dictionary *d,
644                   struct variable *const *vars, size_t count)
645 {
646   /* FIXME: this can be done in O(count) time, but this algorithm
647      is O(count**2). */
648   assert (count == 0 || vars != NULL);
649
650   while (count-- > 0)
651     dict_delete_var (d, *vars++);
652 }
653
654 /* Deletes the COUNT variables in D starting at index IDX.  This
655    is unsafe; see the comment on dict_delete_var() for
656    details. */
657 void
658 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
659 {
660   /* FIXME: this can be done in O(count) time, but this algorithm
661      is O(count**2). */
662   assert (idx + count <= d->var_cnt);
663
664   while (count-- > 0)
665     dict_delete_var (d, d->var[idx].var);
666 }
667
668 /* Deletes scratch variables from dictionary D. */
669 void
670 dict_delete_scratch_vars (struct dictionary *d)
671 {
672   int i;
673
674   /* FIXME: this can be done in O(count) time, but this algorithm
675      is O(count**2). */
676   for (i = 0; i < d->var_cnt; )
677     if (var_get_dict_class (d->var[i].var) == DC_SCRATCH)
678       dict_delete_var (d, d->var[i].var);
679     else
680       i++;
681 }
682
683 /* Moves V to 0-based position IDX in D.  Other variables in D,
684    if any, retain their relative positions.  Runs in time linear
685    in the distance moved. */
686 void
687 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
688 {
689   size_t old_index = var_get_dict_index (v);
690
691   assert (new_index < d->var_cnt);
692
693   unindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
694   move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index);
695   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
696 }
697
698 /* Reorders the variables in D, placing the COUNT variables
699    listed in ORDER in that order at the beginning of D.  The
700    other variables in D, if any, retain their relative
701    positions. */
702 void
703 dict_reorder_vars (struct dictionary *d,
704                    struct variable *const *order, size_t count)
705 {
706   struct vardict_info *new_var;
707   size_t i;
708
709   assert (count == 0 || order != NULL);
710   assert (count <= d->var_cnt);
711
712   new_var = xnmalloc (d->var_cap, sizeof *new_var);
713
714   /* Add variables in ORDER to new_var. */
715   for (i = 0; i < count; i++)
716     {
717       struct vardict_info *old_var;
718
719       assert (dict_contains_var (d, order[i]));
720
721       old_var = var_get_vardict (order[i]);
722       new_var[i] = *old_var;
723       old_var->dict = NULL;
724     }
725
726   /* Add remaining variables to new_var. */
727   for (i = 0; i < d->var_cnt; i++)
728     if (d->var[i].dict != NULL)
729       new_var[count++] = d->var[i];
730   assert (count == d->var_cnt);
731
732   /* Replace old vardicts by new ones. */
733   free (d->var);
734   d->var = new_var;
735
736   hmap_clear (&d->name_map);
737   reindex_vars (d, 0, d->var_cnt);
738 }
739
740 /* Changes the name of variable V that is currently in a dictionary to
741    NEW_NAME. */
742 static void
743 rename_var (struct variable *v, const char *new_name)
744 {
745   struct vardict_info *vardict = var_get_vardict (v);
746   var_clear_vardict (v);
747   var_set_name (v, new_name);
748   vardict->name_node.hash = hash_case_string (new_name, 0);
749   var_set_vardict (v, vardict);
750 }
751
752 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
753    a variable named NEW_NAME is already in D, except that
754    NEW_NAME may be the same as V's existing name. */
755 void
756 dict_rename_var (struct dictionary *d, struct variable *v,
757                  const char *new_name)
758 {
759   assert (!strcasecmp (var_get_name (v), new_name)
760           || dict_lookup_var (d, new_name) == NULL);
761
762   unindex_var (d, var_get_vardict (v));
763   rename_var (v, new_name);
764   reindex_var (d, var_get_vardict (v));
765
766   if (settings_get_algorithm () == ENHANCED)
767     var_clear_short_names (v);
768
769   if ( d->changed ) d->changed (d, d->changed_data);
770   if ( d->callbacks &&  d->callbacks->var_changed )
771     d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
772 }
773
774 /* Renames COUNT variables specified in VARS to the names given
775    in NEW_NAMES within dictionary D.  If the renaming would
776    result in a duplicate variable name, returns false and stores a
777    name that would be duplicated into *ERR_NAME (if ERR_NAME is
778    non-null).  Otherwise, the renaming is successful, and true
779    is returned. */
780 bool
781 dict_rename_vars (struct dictionary *d,
782                   struct variable **vars, char **new_names, size_t count,
783                   char **err_name)
784 {
785   struct pool *pool;
786   char **old_names;
787   size_t i;
788
789   assert (count == 0 || vars != NULL);
790   assert (count == 0 || new_names != NULL);
791
792   /* Save the names of the variables to be renamed. */
793   pool = pool_create ();
794   old_names = pool_nalloc (pool, count, sizeof *old_names);
795   for (i = 0; i < count; i++)
796     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
797
798   /* Remove the variables to be renamed from the name hash,
799      and rename them. */
800   for (i = 0; i < count; i++)
801     {
802       unindex_var (d, var_get_vardict (vars[i]));
803       rename_var (vars[i], new_names[i]);
804     }
805
806   /* Add the renamed variables back into the name hash,
807      checking for conflicts. */
808   for (i = 0; i < count; i++)
809     {
810       if (dict_lookup_var (d, var_get_name (vars[i])) != NULL)
811         {
812           /* There is a name conflict.
813              Back out all the name changes that have already
814              taken place, and indicate failure. */
815           size_t fail_idx = i;
816           if (err_name != NULL)
817             *err_name = new_names[i];
818
819           for (i = 0; i < fail_idx; i++)
820             unindex_var (d, var_get_vardict (vars[i]));
821
822           for (i = 0; i < count; i++)
823             {
824               rename_var (vars[i], old_names[i]);
825               reindex_var (d, var_get_vardict (vars[i]));
826             }
827
828           pool_destroy (pool);
829           return false;
830         }
831       reindex_var (d, var_get_vardict (vars[i]));
832     }
833
834   /* Clear short names. */
835   if (settings_get_algorithm () == ENHANCED)
836     for (i = 0; i < count; i++)
837       var_clear_short_names (vars[i]);
838
839   pool_destroy (pool);
840   return true;
841 }
842
843 /* Returns true if a variable named NAME may be inserted in DICT;
844    that is, if there is not already a variable with that name in
845    DICT and if NAME is not a reserved word.  (The caller's checks
846    have already verified that NAME is otherwise acceptable as a
847    variable name.) */
848 static bool
849 var_name_is_insertable (const struct dictionary *dict, const char *name)
850 {
851   return (dict_lookup_var (dict, name) == NULL
852           && lex_id_to_token (ss_cstr (name)) == T_ID);
853 }
854
855 static char *
856 make_hinted_name (const struct dictionary *dict, const char *hint)
857 {
858   size_t hint_len = strlen (hint);
859   bool dropped = false;
860   char *root, *rp;
861   size_t ofs;
862   int mblen;
863
864   /* The allocation size here is OK: characters that are copied directly fit
865      OK, and characters that are not copied directly are replaced by a single
866      '_' byte.  If u8_mbtouc() replaces bad input by 0xfffd, then that will get
867      replaced by '_' too.  */
868   root = rp = xmalloc (hint_len + 1);
869   for (ofs = 0; ofs < hint_len; ofs += mblen)
870     {
871       ucs4_t uc;
872
873       mblen = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, hint + ofs),
874                          hint_len - ofs);
875       if (rp == root
876           ? lex_uc_is_id1 (uc) && uc != '$'
877           : lex_uc_is_idn (uc))
878         {
879           if (dropped)
880             {
881               *rp++ = '_';
882               dropped = false;
883             }
884           rp += u8_uctomb (CHAR_CAST (uint8_t *, rp), uc, 6);
885         }
886       else if (rp != root)
887         dropped = true;
888     }
889   *rp = '\0';
890
891   if (root[0] != '\0')
892     {
893       unsigned long int i;
894
895       if (var_name_is_insertable (dict, root))
896         return root;
897
898       for (i = 0; i < ULONG_MAX; i++)
899         {
900           char suffix[INT_BUFSIZE_BOUND (i) + 1];
901           char *name;
902
903           suffix[0] = '_';
904           if (!str_format_26adic (i + 1, &suffix[1], sizeof suffix - 1))
905             NOT_REACHED ();
906
907           name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
908           if (var_name_is_insertable (dict, name))
909             {
910               free (root);
911               return name;
912             }
913           free (name);
914         }
915     }
916
917   free (root);
918
919   return NULL;
920 }
921
922 static char *
923 make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
924 {
925   unsigned long int number;
926
927   for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
928        number < ULONG_MAX;
929        number++)
930     {
931       char name[3 + INT_STRLEN_BOUND (number) + 1];
932
933       sprintf (name, "VAR%03lu", number);
934       if (dict_lookup_var (dict, name) == NULL)
935         {
936           if (num_start != NULL)
937             *num_start = number + 1;
938           return xstrdup (name);
939         }
940     }
941
942   NOT_REACHED ();
943 }
944
945
946 /* Devises and returns a variable name unique within DICT.  The variable name
947    is owned by the caller, which must free it with free() when it is no longer
948    needed.
949
950    HINT, if it is non-null, is used as a suggestion that will be
951    modified for suitability as a variable name and for
952    uniqueness.
953
954    If HINT is null or entirely unsuitable, a name in the form
955    "VAR%03d" will be generated, where the smallest unused integer
956    value is used.  If NUM_START is non-null, then its value is
957    used as the minimum numeric value to check, and it is updated
958    to the next value to be checked.
959 */
960 char *
961 dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
962                            unsigned long int *num_start)
963 {
964   if (hint != NULL)
965     {
966       char *hinted_name = make_hinted_name (dict, hint);
967       if (hinted_name != NULL)
968         return hinted_name;
969     }
970   return make_numeric_name (dict, num_start);
971 }
972
973 /* Returns the weighting variable in dictionary D, or a null
974    pointer if the dictionary is unweighted. */
975 struct variable *
976 dict_get_weight (const struct dictionary *d)
977 {
978   assert (d->weight == NULL || dict_contains_var (d, d->weight));
979
980   return d->weight;
981 }
982
983 /* Returns the value of D's weighting variable in case C, except
984    that a negative weight is returned as 0.  Returns 1 if the
985    dictionary is unweighted.  Will warn about missing, negative,
986    or zero values if *WARN_ON_INVALID is true.  The function will
987    set *WARN_ON_INVALID to false if an invalid weight is
988    found. */
989 double
990 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
991                       bool *warn_on_invalid)
992 {
993   assert (c != NULL);
994
995   if (d->weight == NULL)
996     return 1.0;
997   else
998     {
999       double w = case_num (c, d->weight);
1000       if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
1001         w = 0.0;
1002       if ( w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid ) {
1003           *warn_on_invalid = false;
1004           msg (SW, _("At least one case in the data file had a weight value "
1005                      "that was user-missing, system-missing, zero, or "
1006                      "negative.  These case(s) were ignored."));
1007       }
1008       return w;
1009     }
1010 }
1011
1012 /* Sets the weighting variable of D to V, or turning off
1013    weighting if V is a null pointer. */
1014 void
1015 dict_set_weight (struct dictionary *d, struct variable *v)
1016 {
1017   assert (v == NULL || dict_contains_var (d, v));
1018   assert (v == NULL || var_is_numeric (v));
1019
1020   d->weight = v;
1021
1022   if (d->changed) d->changed (d, d->changed_data);
1023   if ( d->callbacks &&  d->callbacks->weight_changed )
1024     d->callbacks->weight_changed (d,
1025                                   v ? var_get_dict_index (v) : -1,
1026                                   d->cb_data);
1027 }
1028
1029 /* Returns the filter variable in dictionary D (see cmd_filter())
1030    or a null pointer if the dictionary is unfiltered. */
1031 struct variable *
1032 dict_get_filter (const struct dictionary *d)
1033 {
1034   assert (d->filter == NULL || dict_contains_var (d, d->filter));
1035
1036   return d->filter;
1037 }
1038
1039 /* Sets V as the filter variable for dictionary D.  Passing a
1040    null pointer for V turn off filtering. */
1041 void
1042 dict_set_filter (struct dictionary *d, struct variable *v)
1043 {
1044   assert (v == NULL || dict_contains_var (d, v));
1045   assert (v == NULL || var_is_numeric (v));
1046
1047   d->filter = v;
1048
1049   if (d->changed) d->changed (d, d->changed_data);
1050   if ( d->callbacks && d->callbacks->filter_changed )
1051     d->callbacks->filter_changed (d,
1052                                   v ? var_get_dict_index (v) : -1,
1053                                   d->cb_data);
1054 }
1055
1056 /* Returns the case limit for dictionary D, or zero if the number
1057    of cases is unlimited. */
1058 casenumber
1059 dict_get_case_limit (const struct dictionary *d)
1060 {
1061   return d->case_limit;
1062 }
1063
1064 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
1065    0 for CASE_LIMIT to indicate no limit. */
1066 void
1067 dict_set_case_limit (struct dictionary *d, casenumber case_limit)
1068 {
1069   d->case_limit = case_limit;
1070 }
1071
1072 /* Returns the prototype used for cases created by dictionary D. */
1073 const struct caseproto *
1074 dict_get_proto (const struct dictionary *d_)
1075 {
1076   struct dictionary *d = CONST_CAST (struct dictionary *, d_);
1077   if (d->proto == NULL)
1078     {
1079       size_t i;
1080
1081       d->proto = caseproto_create ();
1082       d->proto = caseproto_reserve (d->proto, d->var_cnt);
1083       for (i = 0; i < d->var_cnt; i++)
1084         d->proto = caseproto_set_width (d->proto,
1085                                         var_get_case_index (d->var[i].var),
1086                                         var_get_width (d->var[i].var));
1087     }
1088   return d->proto;
1089 }
1090
1091 /* Returns the case index of the next value to be added to D.
1092    This value is the number of `union value's that need to be
1093    allocated to store a case for dictionary D. */
1094 int
1095 dict_get_next_value_idx (const struct dictionary *d)
1096 {
1097   return d->next_value_idx;
1098 }
1099
1100 /* Returns the number of bytes needed to store a case for
1101    dictionary D. */
1102 size_t
1103 dict_get_case_size (const struct dictionary *d)
1104 {
1105   return sizeof (union value) * dict_get_next_value_idx (d);
1106 }
1107
1108 /* Reassigns values in dictionary D so that fragmentation is
1109    eliminated. */
1110 void
1111 dict_compact_values (struct dictionary *d)
1112 {
1113   size_t i;
1114
1115   d->next_value_idx = 0;
1116   for (i = 0; i < d->var_cnt; i++)
1117     {
1118       struct variable *v = d->var[i].var;
1119       set_var_case_index (v, d->next_value_idx++);
1120     }
1121   invalidate_proto (d);
1122 }
1123
1124 /* Returns the number of values occupied by the variables in
1125    dictionary D.  All variables are considered if EXCLUDE_CLASSES
1126    is 0, or it may contain one or more of (1u << DC_ORDINARY),
1127    (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
1128    corresponding type of variable.
1129
1130    The return value may be less than the number of values in one
1131    of dictionary D's cases (as returned by
1132    dict_get_next_value_idx) even if E is 0, because there may be
1133    gaps in D's cases due to deleted variables. */
1134 size_t
1135 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1136 {
1137   size_t i;
1138   size_t cnt;
1139
1140   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1141                                | (1u << DC_SYSTEM)
1142                                | (1u << DC_SCRATCH))) == 0);
1143
1144   cnt = 0;
1145   for (i = 0; i < d->var_cnt; i++)
1146     {
1147       enum dict_class class = var_get_dict_class (d->var[i].var);
1148       if (!(exclude_classes & (1u << class)))
1149         cnt++;
1150     }
1151   return cnt;
1152 }
1153
1154 /* Returns the case prototype that would result after deleting
1155    all variables from D that are not in one of the
1156    EXCLUDE_CLASSES and compacting the dictionary with
1157    dict_compact().
1158
1159    The caller must unref the returned caseproto when it is no
1160    longer needed. */
1161 struct caseproto *
1162 dict_get_compacted_proto (const struct dictionary *d,
1163                           unsigned int exclude_classes)
1164 {
1165   struct caseproto *proto;
1166   size_t i;
1167
1168   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1169                                | (1u << DC_SYSTEM)
1170                                | (1u << DC_SCRATCH))) == 0);
1171
1172   proto = caseproto_create ();
1173   for (i = 0; i < d->var_cnt; i++)
1174     {
1175       struct variable *v = d->var[i].var;
1176       if (!(exclude_classes & (1u << var_get_dict_class (v))))
1177         proto = caseproto_add_width (proto, var_get_width (v));
1178     }
1179   return proto;
1180 }
1181 \f
1182 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
1183    dict_get_split_cnt() to determine how many SPLIT FILE vars
1184    there are.  Returns a null pointer if and only if there are no
1185    SPLIT FILE vars. */
1186 const struct variable *const *
1187 dict_get_split_vars (const struct dictionary *d)
1188 {
1189   return d->split;
1190 }
1191
1192 /* Returns the number of SPLIT FILE vars. */
1193 size_t
1194 dict_get_split_cnt (const struct dictionary *d)
1195 {
1196   return d->split_cnt;
1197 }
1198
1199 /* Removes variable V, which must be in D, from D's set of split
1200    variables. */
1201 static void
1202 dict_unset_split_var (struct dictionary *d, struct variable *v)
1203 {
1204   int orig_count;
1205
1206   assert (dict_contains_var (d, v));
1207
1208   orig_count = d->split_cnt;
1209   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1210                                &v, compare_var_ptrs, NULL);
1211   if (orig_count != d->split_cnt)
1212     {
1213       if (d->changed) d->changed (d, d->changed_data);
1214       /* We changed the set of split variables so invoke the
1215          callback. */
1216       if (d->callbacks &&  d->callbacks->split_changed)
1217         d->callbacks->split_changed (d, d->cb_data);
1218     }
1219 }
1220
1221 /* Sets CNT split vars SPLIT in dictionary D. */
1222 void
1223 dict_set_split_vars (struct dictionary *d,
1224                      struct variable *const *split, size_t cnt)
1225 {
1226   assert (cnt == 0 || split != NULL);
1227
1228   d->split_cnt = cnt;
1229   if ( cnt > 0 )
1230    {
1231     d->split = xnrealloc (d->split, cnt, sizeof *d->split) ;
1232     memcpy (d->split, split, cnt * sizeof *d->split);
1233    }
1234   else
1235    {
1236     free (d->split);
1237     d->split = NULL;
1238    }
1239
1240   if (d->changed) d->changed (d, d->changed_data);
1241   if ( d->callbacks &&  d->callbacks->split_changed )
1242     d->callbacks->split_changed (d, d->cb_data);
1243 }
1244
1245 /* Returns the file label for D, or a null pointer if D is
1246    unlabeled (see cmd_file_label()). */
1247 const char *
1248 dict_get_label (const struct dictionary *d)
1249 {
1250   return d->label;
1251 }
1252
1253 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1254    characters.
1255
1256    Removes D's label if LABEL is null or the empty string. */
1257 void
1258 dict_set_label (struct dictionary *d, const char *label)
1259 {
1260   free (d->label);
1261   d->label = label != NULL && label[0] != '\0' ? xstrndup (label, 60) : NULL;
1262 }
1263
1264 /* Returns the documents for D, as an UTF-8 encoded string_array.  The
1265    return value is always nonnull; if there are no documents then the
1266    string_arary is empty.*/
1267 const struct string_array *
1268 dict_get_documents (const struct dictionary *d)
1269 {
1270   return &d->documents;
1271 }
1272
1273 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1274 void
1275 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1276 {
1277   size_t i;
1278
1279   dict_clear_documents (d);
1280
1281   for (i = 0; i < new_docs->n; i++)
1282     dict_add_document_line (d, new_docs->strings[i], false);
1283 }
1284
1285 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1286    into individual lines at new-line characters.  Each line is truncated to at
1287    most DOC_LINE_LENGTH bytes in D's encoding. */
1288 void
1289 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1290 {
1291   const char *s;
1292
1293   dict_clear_documents (d);
1294   for (s = new_docs; *s != '\0'; )
1295     {
1296       size_t len = strcspn (s, "\n");
1297       char *line = xmemdup0 (s, len);
1298       dict_add_document_line (d, line, false);
1299       free (line);
1300
1301       s += len;
1302       if (*s == '\n')
1303         s++;
1304     }
1305 }
1306
1307 /* Drops the documents from dictionary D. */
1308 void
1309 dict_clear_documents (struct dictionary *d)
1310 {
1311   string_array_clear (&d->documents);
1312 }
1313
1314 /* Appends the UTF-8 encoded LINE to the documents in D.  LINE will be
1315    truncated so that it is no more than 80 bytes in the dictionary's
1316    encoding.  If this causes some text to be lost, and ISSUE_WARNING is true,
1317    then a warning will be issued. */
1318 bool
1319 dict_add_document_line (struct dictionary *d, const char *line,
1320                         bool issue_warning)
1321 {
1322   size_t trunc_len;
1323   bool truncated;
1324
1325   trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1326   truncated = line[trunc_len] != '\0';
1327   if (truncated && issue_warning)
1328     {
1329       /* Note to translators: "bytes" is correct, not characters */
1330       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1331     }
1332
1333   string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1334
1335   return !truncated;
1336 }
1337
1338 /* Returns the number of document lines in dictionary D. */
1339 size_t
1340 dict_get_document_line_cnt (const struct dictionary *d)
1341 {
1342   return d->documents.n;
1343 }
1344
1345 /* Returns document line number IDX in dictionary D.  The caller must not
1346    modify or free the returned string. */
1347 const char *
1348 dict_get_document_line (const struct dictionary *d, size_t idx)
1349 {
1350   assert (idx < d->documents.n);
1351   return d->documents.strings[idx];
1352 }
1353
1354 /* Creates in D a vector named NAME that contains the CNT
1355    variables in VAR.  Returns true if successful, or false if a
1356    vector named NAME already exists in D. */
1357 bool
1358 dict_create_vector (struct dictionary *d,
1359                     const char *name,
1360                     struct variable **var, size_t cnt)
1361 {
1362   size_t i;
1363
1364   assert (cnt > 0);
1365   for (i = 0; i < cnt; i++)
1366     assert (dict_contains_var (d, var[i]));
1367
1368   if (dict_lookup_vector (d, name) == NULL)
1369     {
1370       d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1371       d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1372       return true;
1373     }
1374   else
1375     return false;
1376 }
1377
1378 /* Creates in D a vector named NAME that contains the CNT
1379    variables in VAR.  A vector named NAME must not already exist
1380    in D. */
1381 void
1382 dict_create_vector_assert (struct dictionary *d,
1383                            const char *name,
1384                            struct variable **var, size_t cnt)
1385 {
1386   assert (dict_lookup_vector (d, name) == NULL);
1387   dict_create_vector (d, name, var, cnt);
1388 }
1389
1390 /* Returns the vector in D with index IDX, which must be less
1391    than dict_get_vector_cnt (D). */
1392 const struct vector *
1393 dict_get_vector (const struct dictionary *d, size_t idx)
1394 {
1395   assert (idx < d->vector_cnt);
1396
1397   return d->vector[idx];
1398 }
1399
1400 /* Returns the number of vectors in D. */
1401 size_t
1402 dict_get_vector_cnt (const struct dictionary *d)
1403 {
1404   return d->vector_cnt;
1405 }
1406
1407 /* Looks up and returns the vector within D with the given
1408    NAME. */
1409 const struct vector *
1410 dict_lookup_vector (const struct dictionary *d, const char *name)
1411 {
1412   size_t i;
1413   for (i = 0; i < d->vector_cnt; i++)
1414     if (!strcasecmp (vector_get_name (d->vector[i]), name))
1415       return d->vector[i];
1416   return NULL;
1417 }
1418
1419 /* Deletes all vectors from D. */
1420 void
1421 dict_clear_vectors (struct dictionary *d)
1422 {
1423   size_t i;
1424
1425   for (i = 0; i < d->vector_cnt; i++)
1426     vector_destroy (d->vector[i]);
1427   free (d->vector);
1428
1429   d->vector = NULL;
1430   d->vector_cnt = 0;
1431 }
1432 \f
1433 /* Multiple response sets. */
1434
1435 /* Returns the multiple response set in DICT with index IDX, which must be
1436    between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1437 const struct mrset *
1438 dict_get_mrset (const struct dictionary *dict, size_t idx)
1439 {
1440   assert (idx < dict->n_mrsets);
1441   return dict->mrsets[idx];
1442 }
1443
1444 /* Returns the number of multiple response sets in DICT. */
1445 size_t
1446 dict_get_n_mrsets (const struct dictionary *dict)
1447 {
1448   return dict->n_mrsets;
1449 }
1450
1451 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1452    returns its index; otherwise, returns SIZE_MAX. */
1453 static size_t
1454 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1455 {
1456   size_t i;
1457
1458   for (i = 0; i < dict->n_mrsets; i++)
1459     if (!strcasecmp (name, dict->mrsets[i]->name))
1460       return i;
1461
1462   return SIZE_MAX;
1463 }
1464
1465 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1466    returns it; otherwise, returns NULL. */
1467 const struct mrset *
1468 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1469 {
1470   size_t idx = dict_lookup_mrset_idx (dict, name);
1471   return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1472 }
1473
1474 /* Adds MRSET to DICT, replacing any existing set with the same name.  Returns
1475    true if a set was replaced, false if none existed with the specified name.
1476
1477    Ownership of MRSET is transferred to DICT. */
1478 bool
1479 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1480 {
1481   size_t idx;
1482
1483   assert (mrset_ok (mrset, dict));
1484
1485   idx = dict_lookup_mrset_idx (dict, mrset->name);
1486   if (idx == SIZE_MAX)
1487     {
1488       dict->mrsets = xrealloc (dict->mrsets,
1489                                (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1490       dict->mrsets[dict->n_mrsets++] = mrset;
1491       return true;
1492     }
1493   else
1494     {
1495       mrset_destroy (dict->mrsets[idx]);
1496       dict->mrsets[idx] = mrset;
1497       return false;
1498     }
1499 }
1500
1501 /* Looks for a multiple response set in DICT named NAME.  If found, removes it
1502    from DICT and returns true.  If none is found, returns false without
1503    modifying DICT.
1504
1505    Deleting one multiple response set causes the indexes of other sets within
1506    DICT to change. */
1507 bool
1508 dict_delete_mrset (struct dictionary *dict, const char *name)
1509 {
1510   size_t idx = dict_lookup_mrset_idx (dict, name);
1511   if (idx != SIZE_MAX)
1512     {
1513       mrset_destroy (dict->mrsets[idx]);
1514       dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1515       return true;
1516     }
1517   else
1518     return false;
1519 }
1520
1521 /* Deletes all multiple response sets from DICT. */
1522 void
1523 dict_clear_mrsets (struct dictionary *dict)
1524 {
1525   size_t i;
1526
1527   for (i = 0; i < dict->n_mrsets; i++)
1528     mrset_destroy (dict->mrsets[i]);
1529   free (dict->mrsets);
1530   dict->mrsets = NULL;
1531   dict->n_mrsets = 0;
1532 }
1533
1534 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1535 static void
1536 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1537 {
1538   size_t i;
1539
1540   assert (dict_contains_var (dict, var));
1541
1542   for (i = 0; i < dict->n_mrsets; )
1543     {
1544       struct mrset *mrset = dict->mrsets[i];
1545       size_t j;
1546
1547       for (j = 0; j < mrset->n_vars; )
1548         if (mrset->vars[j] == var)
1549           remove_element (mrset->vars, mrset->n_vars--,
1550                           sizeof *mrset->vars, j);
1551         else
1552           j++;
1553
1554       if (mrset->n_vars < 2)
1555         {
1556           mrset_destroy (mrset);
1557           dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1558         }
1559       else
1560         i++;
1561     }
1562 }
1563 \f
1564 /* Returns D's attribute set.  The caller may examine or modify
1565    the attribute set, but must not destroy it.  Destroying D or
1566    calling dict_set_attributes for D will also destroy D's
1567    attribute set. */
1568 struct attrset *
1569 dict_get_attributes (const struct dictionary *d) 
1570 {
1571   return CONST_CAST (struct attrset *, &d->attributes);
1572 }
1573
1574 /* Replaces D's attributes set by a copy of ATTRS. */
1575 void
1576 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1577 {
1578   attrset_destroy (&d->attributes);
1579   attrset_clone (&d->attributes, attrs);
1580 }
1581
1582 /* Returns true if D has at least one attribute in its attribute
1583    set, false if D's attribute set is empty. */
1584 bool
1585 dict_has_attributes (const struct dictionary *d) 
1586 {
1587   return attrset_count (&d->attributes) > 0;
1588 }
1589
1590 /* Called from variable.c to notify the dictionary that some property of
1591    the variable has changed */
1592 void
1593 dict_var_changed (const struct variable *v)
1594 {
1595   if ( var_has_vardict (v))
1596     {
1597       const struct vardict_info *vardict = var_get_vardict (v);
1598       struct dictionary *d = vardict->dict;
1599
1600       if ( NULL == d)
1601         return;
1602
1603       if (d->changed ) d->changed (d, d->changed_data);
1604       if ( d->callbacks && d->callbacks->var_changed )
1605         d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
1606     }
1607 }
1608
1609
1610 /* Called from variable.c to notify the dictionary that the variable's width
1611    has changed */
1612 void
1613 dict_var_resized (const struct variable *v, int old_width)
1614 {
1615   if ( var_has_vardict (v))
1616     {
1617       const struct vardict_info *vardict = var_get_vardict (v);
1618       struct dictionary *d;
1619
1620       d = vardict->dict;
1621
1622       if (d->changed) d->changed (d, d->changed_data);
1623
1624       invalidate_proto (d);
1625       if ( d->callbacks && d->callbacks->var_resized )
1626         d->callbacks->var_resized (d, var_get_dict_index (v), old_width,
1627                                    d->cb_data);
1628     }
1629 }
1630
1631 /* Called from variable.c to notify the dictionary that the variable's display width
1632    has changed */
1633 void
1634 dict_var_display_width_changed (const struct variable *v)
1635 {
1636   if ( var_has_vardict (v))
1637     {
1638       const struct vardict_info *vardict = var_get_vardict (v);
1639       struct dictionary *d;
1640
1641       d = vardict->dict;
1642
1643       if (d->changed) d->changed (d, d->changed_data);
1644       if ( d->callbacks && d->callbacks->var_display_width_changed )
1645         d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data);
1646     }
1647 }
1648 \f
1649 /* Dictionary used to contain "internal variables". */
1650 static struct dictionary *internal_dict;
1651
1652 /* Create a variable of the specified WIDTH to be used for internal
1653    calculations only.  The variable is assigned case index CASE_IDX. */
1654 struct variable *
1655 dict_create_internal_var (int case_idx, int width)
1656 {
1657   if (internal_dict == NULL)
1658     internal_dict = dict_create ("UTF-8");
1659
1660   for (;;)
1661     {
1662       static int counter = INT_MAX / 2;
1663       struct variable *var;
1664       char name[64];
1665
1666       if (++counter == INT_MAX)
1667         counter = INT_MAX / 2;
1668
1669       sprintf (name, "$internal%d", counter);
1670       var = dict_create_var (internal_dict, name, width);
1671       if (var != NULL)
1672         {
1673           set_var_case_index (var, case_idx);
1674           return var;
1675         }
1676     }
1677 }
1678
1679 /* Destroys VAR, which must have been created with
1680    dict_create_internal_var(). */
1681 void
1682 dict_destroy_internal_var (struct variable *var)
1683 {
1684   if (var != NULL)
1685     {
1686       dict_delete_var (internal_dict, var);
1687
1688       /* Destroy internal_dict if it has no variables left, just so that
1689          valgrind --leak-check --show-reachable won't show internal_dict. */
1690       if (dict_get_var_cnt (internal_dict) == 0)
1691         {
1692           dict_destroy (internal_dict);
1693           internal_dict = NULL;
1694         }
1695     }
1696 }
1697 \f
1698 int
1699 vardict_get_dict_index (const struct vardict_info *vardict)
1700 {
1701   return vardict - vardict->dict->var;
1702 }