/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "data/format.h"
#include "data/identifier.h"
#include "data/missing-values.h"
+#include "data/settings.h"
#include "data/value-labels.h"
#include "data/vardict.h"
#include "libpspp/assertion.h"
struct fmt_spec write; /* Default format for WRITE. */
struct val_labs *val_labs; /* Value labels. */
char *label; /* Variable label. */
+ struct string name_and_label; /* The name and label in the same string */
/* GUI information. */
enum measure measure; /* Nominal, ordinal, or continuous. */
char **short_names;
size_t short_name_cnt;
- /* Each command may use these fields as needed. */
- void *aux;
- void (*aux_dtor) (struct variable *);
-
/* Custom attributes. */
struct attrset attributes;
};
assert (width >= 0 && width <= MAX_STRING);
- v = xmalloc (sizeof *v);
- v->vardict = NULL;
- v->name = NULL;
+ v = xzalloc (sizeof *v);
var_set_name (v, name);
v->width = width;
mv_init (&v->miss, width);
v->measure = var_default_measure (type);
v->display_width = var_default_display_width (width);
v->print = v->write = var_default_formats (width);
- v->val_labs = NULL;
- v->label = NULL;
- v->short_names = NULL;
- v->short_name_cnt = 0;
- v->aux = NULL;
- v->aux_dtor = NULL;
attrset_init (&v->attributes);
+ ds_init_empty (&v->name_and_label);
return v;
}
assert (!var_has_vardict (v));
mv_destroy (&v->miss);
var_clear_short_names (v);
- var_clear_aux (v);
val_labs_destroy (v->val_labs);
var_clear_label (v);
+ attrset_destroy (var_get_attributes (v));
free (v->name);
+ ds_destroy (&v->name_and_label);
free (v);
}
}
return v->name;
}
+
+
/* Sets V's name to NAME, a UTF-8 encoded string.
Do not use this function for a variable in a dictionary. Use
dict_rename_var instead. */
free (v->name);
v->name = xstrdup (name);
+ ds_destroy (&v->name_and_label);
+ ds_init_empty (&v->name_and_label);
dict_var_changed (v);
}
const struct variable *a = a_;
const struct variable *b = b_;
- return strcasecmp (a->name, b->name);
+ return utf8_strcasecmp (a->name, b->name);
}
/* A hsh_hash_func that hashes variable V based on its name. */
{
const struct variable *v = v_;
- return hash_case_string (v->name, 0);
+ return utf8_hash_case_string (v->name, 0);
}
/* A hsh_compare_func that orders pointers to variables A and B
struct variable *const *a = a_;
struct variable *const *b = b_;
- return strcasecmp (var_get_name (*a), var_get_name (*b));
+ return utf8_strcasecmp (var_get_name (*a), var_get_name (*b));
}
/* A hsh_compare_func that orders pointers to variables A and B
{
struct variable *const *v = v_;
- return hash_case_string (var_get_name (*v), 0);
+ return utf8_hash_case_string (var_get_name (*v), 0);
}
\f
/* Returns the type of variable V. */
return val_labs_find (v->val_labs, value);
}
+/*
+ Append to STR the string representation of VALUE for variable V.
+ STR must be a pointer to an initialised struct string.
+*/
+static void
+append_value (const struct variable *v, const union value *value,
+ struct string *str)
+{
+ char *s = data_out (value, var_get_encoding (v), &v->print);
+ ds_put_cstr (str, s);
+ free (s);
+}
+
/* Append STR with a string representing VALUE for variable V.
That is, if VALUE has a label, append that label,
otherwise format VALUE and append the formatted string.
var_append_value_name (const struct variable *v, const union value *value,
struct string *str)
{
+ enum settings_value_style style = settings_get_value_style ();
const char *name = var_lookup_value_label (v, value);
- if (name == NULL)
+
+ switch (style)
{
- char *s = data_out (value, var_get_encoding (v), &v->print);
- ds_put_cstr (str, s);
- free (s);
- }
- else
- ds_put_cstr (str, name);
+ case SETTINGS_VAL_STYLE_VALUES:
+ append_value (v, value, str);
+ break;
+
+ case SETTINGS_VAL_STYLE_LABELS:
+ if (name == NULL)
+ append_value (v, value, str);
+ else
+ ds_put_cstr (str, name);
+ break;
+
+ case SETTINGS_VAL_STYLE_BOTH:
+ default:
+ append_value (v, value, str);
+ if (name != NULL)
+ {
+ ds_put_cstr (str, " (");
+ ds_put_cstr (str, name);
+ ds_put_cstr (str, ")");
+ }
+ break;
+ };
}
\f
/* Print and write formats. */
void
var_set_print_format (struct variable *v, const struct fmt_spec *print)
{
- assert (fmt_check_width_compat (print, v->width));
- v->print = *print;
- dict_var_changed (v);
+ if (!fmt_equal (&v->print, print))
+ {
+ assert (fmt_check_width_compat (print, v->width));
+ v->print = *print;
+ dict_var_changed (v);
+ }
}
/* Returns V's write format specification. */
void
var_set_write_format (struct variable *v, const struct fmt_spec *write)
{
- assert (fmt_check_width_compat (write, v->width));
- v->write = *write;
- dict_var_changed (v);
+ if (!fmt_equal (&v->write, write))
+ {
+ assert (fmt_check_width_compat (write, v->width));
+ v->write = *write;
+ dict_var_changed (v);
+ }
}
/* Sets V's print and write format specifications to FORMAT,
? fmt_for_output (FMT_F, 8, 2)
: fmt_for_output (FMT_A, width, 0));
}
+
+
\f
+
+/* Update the combined name and label string if necessary */
+static void
+update_vl_string (const struct variable *v)
+{
+ /* Cast away const! */
+ struct string *str = (struct string *) &v->name_and_label;
+
+ if (ds_is_empty (str))
+ {
+ if (v->label)
+ ds_put_format (str, _("%s (%s)"), v->label, v->name);
+ else
+ ds_put_cstr (str, v->name);
+ }
+}
+
+
/* Return a string representing this variable, in the form most
appropriate from a human factors perspective, that is, its
variable label if it has one, otherwise its name. */
const char *
var_to_string (const struct variable *v)
{
- return v->label != NULL ? v->label : v->name;
+ enum settings_var_style style = settings_get_var_style ();
+
+ switch (style)
+ {
+ case SETTINGS_VAR_STYLE_NAMES:
+ return v->name;
+ break;
+ case SETTINGS_VAR_STYLE_LABELS:
+ return v->label != NULL ? v->label : v->name;
+ break;
+ case SETTINGS_VAR_STYLE_BOTH:
+ update_vl_string (v);
+ return ds_cstr (&v->name_and_label);
+ break;
+ default:
+ NOT_REACHED ();
+ break;
+ };
}
/* Returns V's variable label, or a null pointer if it has none. */
v->label = ss_xstrdup (s);
}
+ ds_destroy (&v->name_and_label);
+ ds_init_empty (&v->name_and_label);
+
dict_var_changed (v);
return truncated;
return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE;
}
+/* Returns a string version of measurement level M, for display to a user. */
+const char *
+measure_to_string (enum measure m)
+{
+ switch (m)
+ {
+ case MEASURE_NOMINAL:
+ return _("Nominal");
+
+ case MEASURE_ORDINAL:
+ return _("Ordinal");
+
+ case MEASURE_SCALE:
+ return _("Scale");
+
+ default:
+ return "Invalid";
+ }
+}
+
/* Returns V's measurement level. */
enum measure
var_get_measure (const struct variable *v)
void
var_set_display_width (struct variable *v, int new_width)
{
- int old_width = v->display_width;
-
- v->display_width = new_width;
-
- if ( old_width != new_width)
- dict_var_display_width_changed (v);
-
- dict_var_changed (v);
+ if (v->display_width != new_width)
+ {
+ v->display_width = new_width;
+ dict_var_display_width_changed (v);
+ dict_var_changed (v);
+ }
}
/* Returns the default display width for a variable of the given
return a == ALIGN_LEFT || a == ALIGN_RIGHT || a == ALIGN_CENTRE;
}
+/* Returns a string version of alignment A, for display to a user. */
+const char *
+alignment_to_string (enum alignment a)
+{
+ switch (a)
+ {
+ case ALIGN_LEFT:
+ return _("Left");
+
+ case ALIGN_RIGHT:
+ return _("Right");
+
+ case ALIGN_CENTRE:
+ return _("Center");
+
+ default:
+ return "Invalid";
+ }
+}
+
/* Returns V's display alignment, which applies only to GUIs. */
enum alignment
var_get_alignment (const struct variable *v)
for (i = old_cnt; i < var->short_name_cnt; i++)
var->short_names[i] = NULL;
}
- var->short_names[idx] = xstrdup (short_name);
- str_uppercase (var->short_names[idx]);
+ var->short_names[idx] = utf8_to_upper (short_name);
}
dict_var_changed (var);
return vardict_get_case_index (v->vardict);
}
\f
-/* Returns V's auxiliary data, or a null pointer if none has been
- attached. */
-void *
-var_get_aux (const struct variable *v)
-{
- return v->aux;
-}
-
-/* Assign auxiliary data AUX to variable V, which must not
- already have auxiliary data. Before V's auxiliary data is
- cleared, AUX_DTOR(V) will be called. (var_dtor_free, below,
- may be appropriate for use as AUX_DTOR.) */
-void *
-var_attach_aux (const struct variable *v_,
- void *aux, void (*aux_dtor) (struct variable *))
-{
- struct variable *v = CONST_CAST (struct variable *, v_);
- assert (v->aux == NULL);
- assert (aux != NULL);
- v->aux = aux;
- v->aux_dtor = aux_dtor;
- return aux;
-}
-
-/* Remove auxiliary data, if any, from V, and return it, without
- calling any associated destructor. */
-void *
-var_detach_aux (struct variable *v)
-{
- void *aux = v->aux;
- assert (aux != NULL);
- v->aux = NULL;
- return aux;
-}
-
-/* Clears auxiliary data, if any, from V, and calls any
- associated destructor. */
-void
-var_clear_aux (struct variable *v)
-{
- if (v->aux != NULL)
- {
- if (v->aux_dtor != NULL)
- v->aux_dtor (v);
- v->aux = NULL;
- }
-}
-
-/* This function is appropriate for use an auxiliary data
- destructor (passed as AUX_DTOR to var_attach_aux()) for the
- case where the auxiliary data should be passed to free(). */
-void
-var_dtor_free (struct variable *v)
-{
- free (v->aux);
-}
-\f
/* Returns variable V's attribute set. The caller may examine or
modify the attribute set, but must not destroy it. Destroying
V, or calling var_set_attributes() on V, will also destroy its