X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fvariable.c;h=72d9ade6759cfd33e1ed855e5deac987fd18d3f5;hb=828ac3a76939787e683e4cc498eb0dfb0b4f6f25;hp=17a1542cbc3d7a7bf7f20d2ce3ce7747647d4c78;hpb=97fed7964411b7bed4d8ad5bc895966de7e6b2b3;p=pspp diff --git a/src/data/variable.c b/src/data/variable.c index 17a1542cbc..72d9ade675 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -1,5 +1,5 @@ /* 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 @@ -26,6 +26,7 @@ #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" @@ -53,6 +54,7 @@ struct variable 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. */ @@ -90,9 +92,7 @@ var_create (const char *name, int width) 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); @@ -102,13 +102,8 @@ var_create (const char *name, int 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; } @@ -133,7 +128,7 @@ var_clone (const struct variable *old_var) var_set_print_format (new_var, var_get_print_format (old_var)); var_set_write_format (new_var, var_get_write_format (old_var)); var_set_value_labels (new_var, var_get_value_labels (old_var)); - var_set_label (new_var, var_get_label (old_var), NULL, false); + var_set_label (new_var, var_get_label (old_var), false); var_set_measure (new_var, var_get_measure (old_var)); var_set_display_width (new_var, var_get_display_width (old_var)); var_set_alignment (new_var, var_get_alignment (old_var)); @@ -157,7 +152,9 @@ var_destroy (struct variable *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); } } @@ -171,6 +168,8 @@ var_get_name (const struct variable *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. */ @@ -182,6 +181,8 @@ var_set_name (struct variable *v, const char *name) free (v->name); v->name = xstrdup (name); + ds_destroy (&v->name_and_label); + ds_init_empty (&v->name_and_label); dict_var_changed (v); } @@ -467,6 +468,19 @@ var_lookup_value_label (const struct variable *v, const union value *value) 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. @@ -476,15 +490,33 @@ void 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; + }; } /* Print and write formats. */ @@ -503,9 +535,12 @@ var_get_print_format (const struct variable *v) 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. */ @@ -522,9 +557,12 @@ var_get_write_format (const struct variable *v) 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, @@ -549,14 +587,51 @@ var_default_formats (int width) ? fmt_for_output (FMT_F, 8, 2) : fmt_for_output (FMT_A, width, 0)); } + + + +/* 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. */ @@ -571,22 +646,21 @@ var_get_label (const struct variable *v) empty string (after stripping white space), then V's variable label (if any) is removed. - Variable labels are limited to 255 bytes in the dictionary encoding, which - should be specified as DICT_ENCODING. If LABEL fits within this limit, this - function returns true. Otherwise, the variable label is set to a truncated - value, this function returns false and, if ISSUE_WARNING is true, issues a - warning. */ + Variable labels are limited to 255 bytes in V's encoding (as returned by + var_get_encoding()). If LABEL fits within this limit, this function returns + true. Otherwise, the variable label is set to a truncated value, this + function returns false and, if ISSUE_WARNING is true, issues a warning. */ bool -var_set_label (struct variable *v, const char *label, - const char *dict_encoding, bool issue_warning) +var_set_label (struct variable *v, const char *label, bool issue_warning) { bool truncated = false; free (v->label); v->label = NULL; - if (label != NULL) + if (label != NULL && label[strspn (label, CC_SPACES)]) { + const char *dict_encoding = var_get_encoding (v); struct substring s = ss_cstr (label); size_t trunc_len; @@ -606,11 +680,12 @@ var_set_label (struct variable *v, const char *label, } } - ss_trim (&s, ss_cstr (CC_SPACES)); - if (!ss_is_empty (s)) v->label = ss_xstrdup (s); } + ds_destroy (&v->name_and_label); + ds_init_empty (&v->name_and_label); + dict_var_changed (v); return truncated; @@ -620,7 +695,7 @@ var_set_label (struct variable *v, const char *label, void var_clear_label (struct variable *v) { - var_set_label (v, NULL, NULL, false); + var_set_label (v, NULL, false); } /* Returns true if V has a variable V, @@ -639,6 +714,26 @@ measure_is_valid (enum measure m) 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) @@ -676,14 +771,12 @@ var_get_display_width (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 @@ -703,6 +796,26 @@ alignment_is_valid (enum alignment a) 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)