else if (!indexes)
{
size_t size = layer_axis->n_dimensions * sizeof *pt->current_layer;
- return xmemdup (pt->current_layer, MAX (size, 1));
+ return size ? xmemdup (pt->current_layer, size) : xmalloc (1);
}
else
{
static void
fill_cell (struct table *t, int x1, int y1, int x2, int y2,
const struct table_area_style *style, int style_idx,
- const struct pivot_value *value, struct footnote **footnotes,
+ const struct pivot_value *value,
enum settings_value_show show_values,
enum settings_value_show show_variables,
bool rotate_label)
value->font_style,
rotate_label));
- for (size_t i = 0; i < value->n_footnotes; i++)
- {
- struct footnote *f = footnotes[value->footnotes[i]->idx];
- if (f)
- table_add_footnote (t, x1, y1, f);
- }
+ table_add_footnotes (t, x1, y1,
+ (struct pivot_footnote **) value->footnotes,
+ value->n_footnotes);
if (value->n_subscripts)
table_add_subscripts (t, x1, y1,
const struct table_area_style *label_style,
int label_style_idx,
const struct table_area_style *corner_style,
- struct footnote **footnotes,
enum settings_value_show show_values,
enum settings_value_show show_variables,
bool rotate_inner_labels, bool rotate_outer_labels)
bool rotate = ((rotate_inner_labels && is_inner_row)
|| (rotate_outer_labels && is_outer_row));
fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
- label_style, label_style_idx, c->name, footnotes,
+ label_style, label_style_idx, c->name,
show_values, show_variables, rotate);
if (pivot_category_is_leaf (c) && x2 + 1 <= n_columns)
bb[b][0] = bottom_row - d->label_depth + 1;
bb[b][1] = bottom_row;
fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
- corner_style, PIVOT_AREA_CORNER, d->root->name, footnotes,
+ corner_style, PIVOT_AREA_CORNER, d->root->name,
show_values, show_variables, false);
}
{
struct table *table = table_create (nr, nc, 0, 0, 0, 0);
table->styles[style_idx] = table_area_style_override (
- t->container, &pt->look->areas[style_idx], NULL, NULL, false);
+ table->container, &pt->look->areas[style_idx], NULL, NULL, false);
return table;
}
-static struct footnote **
-add_footnotes (struct footnote **refs, size_t n_refs,
- struct footnote **footnotes, size_t *allocated, size_t *n)
+static void
+add_references (const struct pivot_table *pt, const struct table *table,
+ bool *refs, size_t *n_refs)
{
- for (size_t i = 0; i < n_refs; i++)
- {
- struct footnote *f = refs[i];
- if (f->idx >= *allocated)
- {
- size_t new_allocated = (f->idx + 1) * 2;
- footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
- while (*allocated < new_allocated)
- footnotes[(*allocated)++] = NULL;
- }
- footnotes[f->idx] = f;
- if (f->idx >= *n)
- *n = f->idx + 1;
- }
- return footnotes;
+ if (!table)
+ return;
+
+ for (int y = 0; y < table->n[V]; y++)
+ for (int x = 0; x < table->n[H]; )
+ {
+ struct table_cell cell;
+ table_get_cell (table, x, y, &cell);
+
+ if (x == cell.d[H][0] && y == cell.d[V][0])
+ {
+ for (size_t i = 0; i < cell.n_footnotes; i++)
+ {
+ const struct pivot_footnote *f = cell.footnotes[i];
+ assert (f->idx < pt->n_footnotes);
+ assert (f == pt->footnotes[f->idx]);
+
+ if (!refs[f->idx])
+ {
+ refs[f->idx] = true;
+ (*n_refs)++;
+ }
+ }
+ }
+
+ x = cell.d[TABLE_HORZ][1];
+ }
}
-size_t
-table_collect_footnotes (const struct table *
- struct footnote ***footnotesp)
+static struct pivot_footnote **
+collect_footnotes (const struct pivot_table *pt,
+ const struct table *title,
+ const struct table *layers,
+ const struct table *body,
+ const struct table *caption,
+ size_t *n_footnotesp)
{
- struct footnote **footnotes = NULL;
- size_t allocated = 0;
- size_t n = 0;
-
- struct table *t = item->table;
- for (int y = 0; y < t->n[V]; y++)
+ if (!pt->n_footnotes)
{
- struct table_cell cell;
- for (int x = 0; x < t->n[H]; x = cell.d[TABLE_HORZ][1])
- {
- table_get_cell (t, x, y, &cell);
-
- if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
- footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
- footnotes, &allocated, &n);
- }
+ *n_footnotesp = 0;
+ return NULL;
}
- const struct table_cell *title = table_item_get_title (item);
- if (title)
- footnotes = add_footnotes (title->footnotes, title->n_footnotes,
- footnotes, &allocated, &n);
-
- const struct table_item_layers *layers = table_item_get_layers (item);
- if (layers)
- {
- for (size_t i = 0; i < layers->n_layers; i++)
- footnotes = add_footnotes (layers->layers[i].footnotes,
- layers->layers[i].n_footnotes,
- footnotes, &allocated, &n);
- }
+ bool *refs = xzalloc (pt->n_footnotes);
+ size_t n_refs = 0;
+ add_references (pt, title, refs, &n_refs);
+ add_references (pt, layers, refs, &n_refs);
+ add_references (pt, body, refs, &n_refs);
+ add_references (pt, caption, refs, &n_refs);
- const struct table_cell *caption = table_item_get_caption (item);
- if (caption)
- footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
- footnotes, &allocated, &n);
+ struct pivot_footnote **footnotes = xnmalloc (n_refs, sizeof *footnotes);
+ size_t n_footnotes = 0;
+ for (size_t i = 0; i < pt->n_footnotes; i++)
+ if (refs[i])
+ footnotes[n_footnotes++] = pt->footnotes[i];
+ assert (n_footnotes == n_refs);
- size_t n_nonnull = 0;
- for (size_t i = 0; i < n; i++)
- if (footnotes[i])
- footnotes[n_nonnull++] = footnotes[i];
+ free (refs);
- *footnotesp = footnotes;
- return n_nonnull;
+ *n_footnotesp = n_footnotes;
+ return footnotes;
}
void
struct table **bodyp,
struct table **captionp,
struct table **footnotesp,
- struct footnote ***fp, size_t *nfp)
+ struct pivot_footnote ***fp, size_t *nfp)
{
const size_t *pindexes[PIVOT_N_AXES]
= { [PIVOT_AXIS_LAYER] = layer_indexes };
*body->rule_colors[i] = in->color;
}
- struct footnote **footnotes = XCALLOC (pt->n_footnotes, struct footnote *);
- for (size_t i = 0; i < pt->n_footnotes; i++)
- {
- const struct pivot_footnote *pf = pt->footnotes[i];
-
- if (!pf->show)
- continue;
-
- char *content = pivot_value_to_string (pf->content, pt->show_values,
- pt->show_variables);
- char *marker = pivot_value_to_string (pf->marker, pt->show_values,
- pt->show_variables);
- footnotes[i] = table_create_footnote (
- body, i, content, marker,
- table_area_style_override (body->container,
- &pt->look->areas[PIVOT_AREA_FOOTER],
- pf->content->cell_style,
- pf->content->font_style,
- false));
- free (marker);
- free (content);
- }
-
compose_headings (body,
&pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW],
pt->look->borders,
column_enumeration, data[H],
&pt->look->areas[PIVOT_AREA_COLUMN_LABELS],
PIVOT_AREA_COLUMN_LABELS,
- &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
+ &pt->look->areas[PIVOT_AREA_CORNER],
pt->show_values, pt->show_variables,
pt->rotate_outer_row_labels, false);
row_enumeration, data[V],
&pt->look->areas[PIVOT_AREA_ROW_LABELS],
PIVOT_AREA_ROW_LABELS,
- &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
+ &pt->look->areas[PIVOT_AREA_CORNER],
pt->show_values, pt->show_variables,
false, pt->rotate_inner_column_labels);
x + stub[H], y + stub[V],
x + stub[H], y + stub[V],
&pt->look->areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA,
- value, footnotes,
- pt->show_values, pt->show_variables, false);
+ value, pt->show_values, pt->show_variables, false);
x++;
}
&& stub[H] && stub[V])
fill_cell (body, 0, 0, stub[H] - 1, stub[V] - 1,
&pt->look->areas[PIVOT_AREA_CORNER], PIVOT_AREA_CORNER,
- pt->corner_text, footnotes,
- pt->show_values, pt->show_variables, false);
+ pt->corner_text, pt->show_values, pt->show_variables, false);
if (body->n[H] && body->n[V])
{
if (pt->title && titlep)
{
title = create_aux_table (pt, 1, 1, PIVOT_AREA_TITLE);
- fill_cell (title, 0, 0, 1, 1,
+ fill_cell (title, 0, 0, 0, 0,
&pt->look->areas[PIVOT_AREA_TITLE], PIVOT_AREA_TITLE,
- pt->title, footnotes,
- pt->show_values, pt->show_variables, false);
+ pt->title, pt->show_values, pt->show_variables, false);
}
else
title = NULL;
/* XXX This puts in the layer values, but not the variable names. */
const struct pivot_value *name
= d->data_leaves[layer_indexes[i]]->name;
- fill_cell (layers, 0, y, 1, y + 1,
+ fill_cell (layers, 0, y, 0, y,
&pt->look->areas[PIVOT_AREA_LAYERS], PIVOT_AREA_LAYERS,
- name, footnotes,
- pt->show_values, pt->show_variables, false);
+ name, pt->show_values, pt->show_variables, false);
y++;
}
}
if (pt->caption && captionp)
{
caption = create_aux_table (pt, 1, 1, PIVOT_AREA_CAPTION);
- fill_cell (caption, 0, 0, 1, 1,
+ fill_cell (caption, 0, 0, 0, 0,
&pt->look->areas[PIVOT_AREA_CAPTION], PIVOT_AREA_CAPTION,
- pt->caption, footnotes,
- pt->show_values, pt->show_variables, false);
+ pt->caption, pt->show_values, pt->show_variables, false);
}
else
caption = NULL;
- free (footnotes);
+ /* Footnotes. */
+ size_t nf;
+ struct pivot_footnote **f = collect_footnotes (pt, title, layers, body,
+ caption, &nf);
+ struct table *footnotes;
+ if (nf && footnotesp)
+ {
+ footnotes = create_aux_table (pt, 1, nf, PIVOT_AREA_FOOTER);
+ for (size_t i = 0; i < nf; i++)
+ {
+ struct string s = DS_EMPTY_INITIALIZER;
+ pivot_value_format (f[i]->marker, pt->show_values,
+ pt->show_variables, &s);
+ ds_put_cstr (&s, ". ");
+ pivot_value_format (f[i]->content, pt->show_values,
+ pt->show_variables, &s);
+
+ struct pivot_value *value = pivot_value_new_user_text_nocopy (
+ ds_steal_cstr (&s));
+
+ fill_cell (layers, 0, i, 0, i,
+ &pt->look->areas[PIVOT_AREA_FOOTER], PIVOT_AREA_FOOTER,
+ value, pt->show_values, pt->show_variables, false);
+ }
+ }
+ else
+ footnotes = NULL;
+
+ *titlep = title;
+ if (layersp)
+ *layersp = layers;
*bodyp = body;
+ if (captionp)
+ *captionp = caption;
+ if (footnotesp)
+ *footnotesp = footnotes;
+ if (fp)
+ {
+ *fp = f;
+ *nfp = nf;
+ }
+ else
+ free (f);
}
void