return (struct fmt_spec) { .type = FMT_PCT, .w = 40, .d = 1 };
case CTF_GENERAL:
- return *var_get_print_format (var);
+ return var_get_print_format (var);
default:
NOT_REACHED ();
if (!parse_format_specifier (lexer, format))
return false;
- char *error = fmt_check_output__ (format);
+ char *error = fmt_check_output__ (*format);
if (!error)
- error = fmt_check_type_compat__ (format, NULL, VAL_NUMERIC);
+ error = fmt_check_type_compat__ (*format, NULL, VAL_NUMERIC);
if (error)
{
lex_next_error (lexer, -1, -1, "%s", error);
if (!parse_variables (lexer, dict, &vars, &n_vars, PV_NO_SCRATCH))
return false;
- const struct fmt_spec *common_format = var_get_print_format (vars[0]);
+ struct fmt_spec common_format = var_get_print_format (vars[0]);
+ bool has_common_format = true;
for (size_t i = 1; i < n_vars; i++)
{
- const struct fmt_spec *f = var_get_print_format (vars[i]);
- if (f->type != common_format->type)
+ struct fmt_spec f = var_get_print_format (vars[i]);
+ if (f.type != common_format.type)
{
- common_format = NULL;
+ has_common_format = false;
break;
}
}
bool parse_strings
- = (common_format
- && (fmt_get_category (common_format->type)
+ = (has_common_format
+ && (fmt_get_category (common_format.type)
& (FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT)));
struct ctables_categories *c = xmalloc (sizeof *c);
switch (cat->type)
{
case CCT_POSTCOMPUTE:
- cat->parse_format = parse_strings ? common_format->type : FMT_F;
+ cat->parse_format = parse_strings ? common_format.type : FMT_F;
struct msg_location *cats_location
= lex_ofs_location (lexer, cats_start_ofs, cats_end_ofs);
bool ok = ctables_recursive_check_postcompute (
{
double n;
if (!parse_category_string (cat->location, cat->string, dict,
- common_format->type, &n))
+ common_format.type, &n))
goto error;
ss_dealloc (&cat->string);
n[0] = -DBL_MAX;
else if (!parse_category_string (cat->location,
cat->srange[0], dict,
- common_format->type, &n[0]))
+ common_format.type, &n[0]))
goto error;
if (!cat->srange[1].string)
n[1] = DBL_MAX;
else if (!parse_category_string (cat->location,
cat->srange[1], dict,
- common_format->type, &n[1]))
+ common_format.type, &n[1]))
goto error;
ss_dealloc (&cat->srange[0]);
}
static char *
-ctables_format (double d, const struct fmt_spec *format,
+ctables_format (double d, struct fmt_spec format,
const struct fmt_settings *settings)
{
const union value v = { .f = d };
value = pivot_value_new_user_text (ct->missing, SIZE_MAX);
else if (is_ctables_format)
value = pivot_value_new_user_text_nocopy (
- ctables_format (d, &format, &ct->ctables_formats));
+ ctables_format (d, format, &ct->ctables_formats));
else
{
value = pivot_value_new_number (d);
ctables_section_recurse_add_empty_categories (
struct ctables_section *s,
const struct ctables_category **cats[PIVOT_N_AXES], struct ccase *c,
- enum pivot_axis_type a, size_t a_idx)
+ enum pivot_axis_type a, size_t a_idx, bool add)
{
if (a >= PIVOT_N_AXES)
- ctables_cell_insert__ (s, c, cats);
+ {
+ if (add)
+ ctables_cell_insert__ (s, c, cats);
+ }
else if (!s->nests[a] || a_idx >= s->nests[a]->n)
- ctables_section_recurse_add_empty_categories (s, cats, c, a + 1, 0);
+ ctables_section_recurse_add_empty_categories (s, cats, c, a + 1, 0, add);
else
{
const struct variable *var = s->nests[a]->vars[a_idx];
- const struct ctables_categories *categories = s->table->categories[
- var_get_dict_index (var)];
+ size_t idx = var_get_dict_index (var);
+ bool show_empty = s->table->show_empty[idx];
+ if (show_empty)
+ add = true;
+
+ const struct ctables_categories *categories = s->table->categories[idx];
int width = var_get_width (var);
const struct hmap *occurrences = &s->occurrences[a][a_idx];
const struct ctables_occurrence *o;
value_clone (value, &o->value, width);
cats[a][a_idx] = ctables_categories_match (categories, value, var);
assert (cats[a][a_idx] != NULL);
- ctables_section_recurse_add_empty_categories (s, cats, c, a, a_idx + 1);
+ ctables_section_recurse_add_empty_categories (s, cats, c,
+ a, a_idx + 1, add);
}
for (size_t i = 0; i < categories->n_cats; i++)
{
const struct ctables_category *cat = &categories->cats[i];
- if (cat->type == CCT_POSTCOMPUTE)
+ if (cat->type == CCT_POSTCOMPUTE
+ || (show_empty && cat->type == CCT_SUBTOTAL))
{
cats[a][a_idx] = cat;
- ctables_section_recurse_add_empty_categories (s, cats, c, a, a_idx + 1);
+ ctables_section_recurse_add_empty_categories (s, cats, c,
+ a, a_idx + 1, true);
}
}
}
static void
ctables_section_add_empty_categories (struct ctables_section *s)
{
- bool show_empty = false;
for (size_t a = 0; a < PIVOT_N_AXES; a++)
if (s->nests[a])
for (size_t k = 0; k < s->nests[a]->n; k++)
size_t idx = var_get_dict_index (var);
const struct ctables_categories *cats = s->table->categories[idx];
if (s->table->show_empty[idx])
- {
- show_empty = true;
- ctables_add_category_occurrences (var, &s->occurrences[a][k], cats);
- }
+ ctables_add_category_occurrences (var, &s->occurrences[a][k], cats);
}
- if (!show_empty)
- return;
const struct ctables_category *layer_cats[s->nests[PIVOT_AXIS_LAYER]->n];
const struct ctables_category *row_cats[s->nests[PIVOT_AXIS_ROW]->n];
[PIVOT_AXIS_COLUMN] = column_cats,
};
struct ccase *c = case_create (dict_get_proto (s->table->ctables->dict));
- ctables_section_recurse_add_empty_categories (s, cats, c, 0, 0);
+ ctables_section_recurse_add_empty_categories (s, cats, c, 0, 0, false);
case_unref (c);
}