html_put_footnote_markers (html, text->footnotes, text->n_footnotes);
}
+static void
+html_put_table_item_layers (struct html_driver *html,
+ const struct table_item_layers *layers)
+{
+ for (size_t i = 0; i < layers->n_layers; i++)
+ {
+ if (i)
+ fputs ("<BR>\n", html->file);
+
+ const struct table_item_layer *layer = &layers->layers[i];
+ escape_string (html->file, layer->content, strlen (layer->content),
+ " ", "<BR>");
+ html_put_footnote_markers (html, layer->footnotes, layer->n_footnotes);
+ }
+}
+
static void
html_output_table (struct html_driver *html, const struct table_item *item)
{
fputs ("<TBODY VALIGN=\"TOP\">\n", html->file);
const struct table_item_text *title = table_item_get_title (item);
- const struct table_item_text *layers = table_item_get_layers (item);
+ const struct table_item_layers *layers = table_item_get_layers (item);
if (title || layers)
{
fputs (" <CAPTION>", html->file);
if (title && layers)
fputs ("<BR>\n", html->file);
if (layers)
- html_put_table_item_text (html, layers);
+ html_put_table_item_layers (html, layers);
fputs ("</CAPTION>\n", html->file);
}
xmlTextWriterEndElement (odt->content_wtr);
}
+static void
+write_table_item_layers (struct odt_driver *odt,
+ const struct table_item_layers *layers)
+{
+ if (!layers)
+ return;
+
+ for (size_t i = 0; i < layers->n_layers; i++)
+ {
+ const struct table_item_layer *layer = &layers->layers[i];
+ xmlTextWriterStartElement (odt->content_wtr, _xml("text:h"));
+ xmlTextWriterWriteFormatAttribute (odt->content_wtr,
+ _xml("text:outline-level"), "%d", 2);
+ xmlTextWriterWriteString (odt->content_wtr, _xml (layer->content) );
+ for (size_t i = 0; i < layer->n_footnotes; i++)
+ write_footnote (odt, layer->footnotes[i]);
+ xmlTextWriterEndElement (odt->content_wtr);
+ }
+}
+
static void
write_table (struct odt_driver *odt, const struct table_item *item)
{
/* Write a heading for the table */
write_table_item_text (odt, table_item_get_title (item));
- write_table_item_text (odt, table_item_get_layers (item));
+ write_table_item_layers (odt, table_item_get_layers (item));
/* Start table */
xmlTextWriterStartElement (odt->content_wtr, _xml("table:table"));
const size_t *pindexes[PIVOT_N_AXES]
= { [PIVOT_AXIS_LAYER] = layer_indexes };
- struct string layer_label = DS_EMPTY_INITIALIZER;
- const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
- for (size_t i = 0; i < layer_axis->n_dimensions; i++)
- {
- const struct pivot_dimension *d = layer_axis->dimensions[i];
- if (d->n_leaves)
- {
- if (!ds_is_empty (&layer_label))
- ds_put_byte (&layer_label, '\n');
- pivot_value_format (d->root->name, pt->show_values,
- pt->show_variables, &layer_label);
- ds_put_cstr (&layer_label, ": ");
- pivot_value_format (d->data_leaves[layer_indexes[i]]->name,
- pt->show_values, pt->show_variables,
- &layer_label);
- }
- }
-
size_t body[TABLE_N_AXES];
size_t *column_enumeration = pivot_table_enumerate_axis (
pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->omit_empty, &body[H]);
table_item_text_destroy (title);
}
- if (!ds_is_empty (&layer_label))
+ const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
+ struct table_item_layers *layers = NULL;
+ for (size_t i = 0; i < layer_axis->n_dimensions; i++)
{
- struct table_item_text *layers = table_item_text_create (
- ds_cstr (&layer_label));
- layers->style = area_style_override (NULL, &pt->areas[PIVOT_AREA_LAYERS],
- NULL, NULL);
- table_item_set_layers (ti, layers);
- table_item_text_destroy (layers);
+ const struct pivot_dimension *d = layer_axis->dimensions[i];
+ if (d->n_leaves)
+ {
+ if (!layers)
+ {
+ layers = xzalloc (sizeof *layers);
+ layers->style = area_style_override (
+ NULL, &pt->areas[PIVOT_AREA_LAYERS], NULL, NULL);
+ layers->layers = xnmalloc (layer_axis->n_dimensions,
+ sizeof *layers->layers);
+ }
- ds_destroy (&layer_label);
+ const struct pivot_value *name
+ = d->data_leaves[layer_indexes[i]]->name;
+ struct table_item_layer *layer = &layers->layers[layers->n_layers++];
+ struct string s = DS_EMPTY_INITIALIZER;
+ pivot_value_format_body (name, pt->show_values, pt->show_variables,
+ &s);
+ layer->content = ds_steal_cstr (&s);
+ layer->n_footnotes = name->n_footnotes;
+ layer->footnotes = xnmalloc (layer->n_footnotes,
+ sizeof *layer->footnotes);
+ for (size_t i = 0; i < name->n_footnotes; i++)
+ layer->footnotes[i] = footnotes[name->footnotes[i]->idx];
+ }
+ }
+ if (layers)
+ {
+ table_item_set_layers (ti, layers);
+ table_item_layers_destroy (layers);
}
if (pt->caption)
render_pager_add_table (p, &tab->table, min_width);
}
+static void
+add_layers_page (struct render_pager *p,
+ const struct table_item_layers *layers, int min_width)
+{
+ if (!layers)
+ return;
+
+ struct tab_table *tab = tab_create (1, layers->n_layers);
+ for (size_t i = 0; i < layers->n_layers; i++)
+ {
+ const struct table_item_layer *layer = &layers->layers[i];
+ tab_text (tab, 0, i, 0, layer->content);
+ for (size_t j = 0; j < layer->n_footnotes; j++)
+ tab_add_footnote (tab, 0, i, layer->footnotes[j]);
+ }
+ if (layers->style)
+ tab->styles[0] = area_style_clone (tab->container, layers->style);
+ render_pager_add_table (p, &tab->table, min_width);
+}
+
/* Creates and returns a new render_pager for rendering TABLE_ITEM on the
device with the given PARAMS. */
struct render_pager *
add_text_page (p, table_item_get_title (table_item), title_width);
/* Layers. */
- add_text_page (p, table_item_get_layers (table_item), title_width);
+ add_layers_page (p, table_item_get_layers (table_item), title_width);
/* Body. */
render_pager_add_table (p, table_ref (table_item_get_table (table_item)), 0);
#include "libpspp/cast.h"
#include "output/driver.h"
#include "output/output-item-provider.h"
+#include "output/pivot-table.h"
#include "output/table-item.h"
#include "gl/xalloc.h"
}
}
+void
+table_item_layer_copy (struct table_item_layer *dst,
+ const struct table_item_layer *src)
+{
+ dst->content = xstrdup (src->content);
+ dst->footnotes = xmemdup (src->footnotes,
+ src->n_footnotes * sizeof *src->footnotes);
+ dst->n_footnotes = src->n_footnotes;
+}
+
+void
+table_item_layer_uninit (struct table_item_layer *layer)
+{
+ if (layer)
+ {
+ free (layer->content);
+ free (layer->footnotes);
+ }
+}
+
+struct table_item_layers *
+table_item_layers_clone (const struct table_item_layers *old)
+{
+ if (!old)
+ return NULL;
+
+ struct table_item_layers *new = xmalloc (sizeof *new);
+ *new = (struct table_item_layers) {
+ .layers = xnmalloc (old->n_layers, sizeof *new->layers),
+ .n_layers = old->n_layers,
+ .style = area_style_clone (NULL, old->style),
+ };
+ for (size_t i = 0; i < new->n_layers; i++)
+ table_item_layer_copy (&new->layers[i], &old->layers[i]);
+ return new;
+}
+
+void
+table_item_layers_destroy (struct table_item_layers *layers)
+{
+ if (layers)
+ {
+ for (size_t i = 0; i < layers->n_layers; i++)
+ table_item_layer_uninit (&layers->layers[i]);
+ free (layers->layers);
+ area_style_free (layers->style);
+ free (layers);
+ }
+}
+
/* Initializes ITEM as a table item for rendering TABLE. The new table item
initially has the specified TITLE and CAPTION, which may each be NULL. The
caller retains ownership of TITLE and CAPTION. */
/* Returns ITEM's layers, which will be a null pointer if no layers have been
set. */
-const struct table_item_text *
+const struct table_item_layers *
table_item_get_layers (const struct table_item *item)
{
return item->layers;
This function may only be used on a table_item that is unshared. */
void
table_item_set_layers (struct table_item *item,
- const struct table_item_text *layers)
+ const struct table_item_layers *layers)
{
assert (!table_item_is_shared (item));
- table_item_text_destroy (item->layers);
- item->layers = table_item_text_clone (layers);
+ table_item_layers_destroy (item->layers);
+ item->layers = table_item_layers_clone (layers);
}
/* Returns ITEM's caption, which is a null pointer if no caption has been
{
struct table_item *item = to_table_item (output_item);
table_item_text_destroy (item->title);
- table_item_text_destroy (item->layers);
table_item_text_destroy (item->caption);
+ table_item_layers_destroy (item->layers);
table_unref (item->table);
free (item);
}
struct table_item_text *table_item_text_clone (const struct table_item_text *);
void table_item_text_destroy (struct table_item_text *);
+struct table_item_layer
+ {
+ char *content;
+ const struct footnote **footnotes;
+ size_t n_footnotes;
+ };
+
+void table_item_layer_copy (struct table_item_layer *,
+ const struct table_item_layer *);
+void table_item_layer_uninit (struct table_item_layer *);
+
+struct table_item_layers
+ {
+ struct table_item_layer *layers;
+ size_t n_layers;
+ struct area_style *style;
+ };
+
+struct table_item_layers *table_item_layers_clone (
+ const struct table_item_layers *);
+void table_item_layers_destroy (struct table_item_layers *);
+
/* A table item.
The members of struct table_item should not be accessed directly. Use one
struct output_item output_item; /* Superclass. */
struct table *table; /* The table to be rendered. */
struct table_item_text *title; /* Null if there is no title. */
- struct table_item_text *layers; /* Null if there is no layer info. */
struct table_item_text *caption; /* Null if there is no caption. */
+ struct table_item_layers *layers; /* Null if there is no layer info. */
};
struct table_item *table_item_create (struct table *, const char *title,
void table_item_set_title (struct table_item *,
const struct table_item_text *);
-const struct table_item_text *table_item_get_layers (
+const struct table_item_layers *table_item_get_layers (
const struct table_item *);
void table_item_set_layers (struct table_item *,
- const struct table_item_text *);
+ const struct table_item_layers *);
const struct table_item_text *table_item_get_caption (
const struct table_item *);
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);
+ }
+
const struct table_item_text *caption = table_item_get_caption (item);
if (caption)
footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,