#include "output/driver-provider.h"
#include "output/message-item.h"
#include "output/options.h"
+#include "output/pivot-output.h"
+#include "output/pivot-table.h"
#include "output/render.h"
#include "output/table-item.h"
#include "output/text-item.h"
ascii_output_table_item (struct ascii_driver *a,
const struct table_item *table_item)
{
- struct render_pager *p;
-
update_page_size (a, false);
- if (a->object_cnt++)
- putc ('\n', a->file);
-
- p = render_pager_create (&a->params, table_item);
- for (int i = 0; render_pager_has_next (p); i++)
+ size_t *layer_indexes;
+ PIVOT_OUTPUT_FOR_EACH_LAYER (layer_indexes, table_item->pt, true)
{
- if (i)
- putc ('\n', a->file);
- ascii_output_lines (a, render_pager_draw_next (p, INT_MAX));
+ struct render_pager *p = render_pager_create (&a->params, table_item,
+ layer_indexes);
+ for (int i = 0; render_pager_has_next (p); i++)
+ {
+ if (a->object_cnt++)
+ putc ('\n', a->file);
+
+ ascii_output_lines (a, render_pager_draw_next (p, INT_MAX));
+ }
+ render_pager_destroy (p);
}
- render_pager_destroy (p);
}
static void
#include "output/message-item.h"
#include "output/page-eject-item.h"
#include "output/page-setup-item.h"
+#include "output/pivot-output.h"
+#include "output/pivot-table.h"
#include "output/render.h"
#include "output/table-item.h"
#include "output/text-item.h"
|| a->min_break[H] != b->min_break[H]
|| a->min_break[V] != b->min_break[V]
|| a->use_system_colors != b->use_system_colors
+ || a->object_spacing != b->object_spacing
|| a->font_resolution != b->font_resolution)
return false;
struct output_item *item;
bool print;
+ /* Print mode only. */
+ bool done;
+
/* Table items only. */
size_t *layer_indexes;
struct render_params rp;
struct render_pager *p;
cairo_t *cairo; /* XXX should this be here?! */
-
- /* Chart and page-eject items only. */
- bool done;
};
/* The unit used for internal measurements is inch/(72 * XR_POINT).
size_t *layer_indexes = NULL;
if (is_table_item (item))
{
- layer_indexes = pivot_table_next_layer (table_item->pt, NULL, print);
+ const struct table_item *table_item = to_table_item (item);
+ layer_indexes = pivot_output_next_layer (table_item->pt, NULL, print);
if (!layer_indexes)
return NULL;
}
[RENDER_LINE_DOUBLE] = 2 * LW + LS,
};
- size_t *layer_indexes = NULL;
- if (is_table_item (item)
- pivot_table_next_display_layer (
-
struct xr_fsm *fsm = xmalloc (sizeof *fsm);
*fsm = (struct xr_fsm) {
.style = xr_fsm_style_ref (style),
struct table_item *table_item = to_table_item (item);
fsm->cairo = cr;
- fsm->p = render_pager_create (&fsm->rp, table_item);
+ fsm->p = render_pager_create (&fsm->rp, table_item, fsm->layer_indexes);
fsm->cairo = NULL;
}
return fsm;
}
+struct xr_fsm *
+xr_fsm_create_for_printing (const struct output_item *item,
+ const struct xr_fsm_style *style, cairo_t *cr)
+{
+ return xr_fsm_create (item, style, cr, true);
+}
+
void
xr_fsm_destroy (struct xr_fsm *fsm)
{
{
xr_fsm_style_unref (fsm->style);
output_item_unref (fsm->item);
+ free (fsm->layer_indexes);
render_pager_destroy (fsm->p);
assert (!fsm->cairo);
free (fsm);
}
}
+\f
+/* Scrolling API. */
+
+struct xr_fsm *
+xr_fsm_create_for_scrolling (const struct output_item *item,
+ const struct xr_fsm_style *style, cairo_t *cr)
+{
+ return xr_fsm_create (item, style, cr, false);
+}
-/* This is primarily meant for use with screen rendering since the result is a
- fixed value for charts. */
void
xr_fsm_measure (struct xr_fsm *fsm, cairo_t *cr, int *wp, int *hp)
{
+ assert (!fsm->print);
+
int w, h;
if (is_table_item (fsm->item))
*hp = h;
}
-static int
-xr_fsm_draw_table (struct xr_fsm *fsm, int space)
-{
- return (render_pager_has_next (fsm->p)
- ? render_pager_draw_next (fsm->p, space)
- : 0);
-}
-
-static int
-xr_fsm_draw_chart (struct xr_fsm *fsm, int space)
-{
- const int chart_height = 0.8 * MIN (fsm->rp.size[H], fsm->rp.size[V]);
- if (space < chart_height)
- return 0;
-
- fsm->done = true;
- xr_draw_chart (to_chart_item (fsm->item), fsm->cairo,
- xr_to_pt (fsm->rp.size[H]), xr_to_pt (chart_height));
- return chart_height;
-}
-
-static int
-xr_fsm_draw_eject (struct xr_fsm *fsm, int space)
-{
- if (space >= fsm->rp.size[V])
- fsm->done = true;
- return 0;
-}
-
void
xr_fsm_draw_all (struct xr_fsm *fsm, cairo_t *cr)
{
+ assert (!fsm->print);
xr_fsm_draw_region (fsm, cr, 0, 0, INT_MAX, INT_MAX);
}
xr_fsm_draw_region (struct xr_fsm *fsm, cairo_t *cr,
int x, int y, int w, int h)
{
+ assert (!fsm->print);
if (is_table_item (fsm->item))
{
fsm->cairo = cr;
else
NOT_REACHED ();
}
+\f
+/* Printing API. */
+
+static int
+xr_fsm_draw_table (struct xr_fsm *fsm, int space)
+{
+ struct table_item *table_item = to_table_item (fsm->item);
+ int used = render_pager_draw_next (fsm->p, space);
+ if (!render_pager_has_next (fsm->p))
+ {
+ render_pager_destroy (fsm->p);
+
+ fsm->layer_indexes = pivot_output_next_layer (table_item->pt,
+ fsm->layer_indexes, true);
+ if (fsm->layer_indexes)
+ {
+ fsm->p = render_pager_create (&fsm->rp, table_item,
+ fsm->layer_indexes);
+ if (table_item->pt->look->paginate_layers)
+ used = space;
+ else
+ used += fsm->style->object_spacing;
+ }
+ else
+ {
+ fsm->p = NULL;
+ fsm->done = true;
+ }
+ }
+ return MIN (used, space);
+}
+
+static int
+xr_fsm_draw_chart (struct xr_fsm *fsm, int space)
+{
+ const int chart_height = 0.8 * MIN (fsm->rp.size[H], fsm->rp.size[V]);
+ if (space < chart_height)
+ return 0;
+
+ fsm->done = true;
+ xr_draw_chart (to_chart_item (fsm->item), fsm->cairo,
+ xr_to_pt (fsm->rp.size[H]), xr_to_pt (chart_height));
+ return chart_height;
+}
+
+static int
+xr_fsm_draw_eject (struct xr_fsm *fsm, int space)
+{
+ if (space >= fsm->rp.size[V])
+ fsm->done = true;
+ return 0;
+}
int
xr_fsm_draw_slice (struct xr_fsm *fsm, cairo_t *cr, int space)
{
- if (xr_fsm_is_empty (fsm))
+ assert (fsm->print);
+
+ if (fsm->done)
return 0;
cairo_save (cr);
return used;
}
-
bool
xr_fsm_is_empty (const struct xr_fsm *fsm)
{
- return (is_table_item (fsm->item)
- ? !render_pager_has_next (fsm->p)
- : fsm->done);
+ assert (fsm->print);
+
+ return fsm->done;
}
struct cell_color fg;
bool use_system_colors;
+ int object_spacing;
+
/* Resolution, in units per inch, used for measuring font "points". If
this is 72.0, for example, then 1pt = 1 device unit, which is
appropriate for rendering to a surface created by
if (!page_heading_equals (&a->headings[i], &b->headings[i]))
return false;
- return (a->initial_page_number == b->initial_page_number
- && a->object_spacing == b->object_spacing);
+ return a->initial_page_number == b->initial_page_number;
}
\f
struct xr_pager
&ps->headings[i], -1, fs->size[H], 0,
fs->font_resolution);
if (*h)
- *h += ps->object_spacing;
+ *h += fs->object_spacing;
}
cairo_destroy (cairo);
cairo_surface_destroy (surface);
if (p->heading_heights[1])
xr_render_page_heading (cr, font, &ps->headings[1], page_number,
- fs->size[H], fs->size[V] + ps->object_spacing,
+ fs->size[H], fs->size[V] + fs->object_spacing,
fs->font_resolution);
cairo_surface_t *surface = cairo_get_target (cr);
free (attrs);
}
- int spacing = p->page_style->object_spacing;
+ int spacing = p->fsm_style->object_spacing;
int chunk = xr_fsm_draw_slice (p->fsm, p->cr,
p->fsm_style->size[V] - p->y);
p->y += chunk + spacing;
struct page_heading headings[2]; /* Top and bottom headings. */
int initial_page_number;
- int object_spacing;
/* Whether to include an outline in PDF output. (The only reason I know to
omit it is to avoid a Cairo bug that caused crashes in some cases.) */
},
.initial_page_number = 1,
- .object_spacing = object_spacing,
.include_outline = include_outline,
};
},
.fg = fg,
.use_system_colors = systemcolors,
+ .object_spacing = object_spacing,
.font_resolution = font_resolution,
};
},
.initial_page_number = setup->initial_page_number,
- .object_spacing = setup->object_spacing * 72 * XR_POINT,
.include_outline = old_ps->include_outline,
};
for (size_t i = 0; i < 2; i++)
},
.fg = old_fs->fg,
.use_system_colors = old_fs->use_system_colors,
+ .object_spacing = setup->object_spacing * 72 * XR_POINT,
.font_resolution = old_fs->font_resolution,
};
for (size_t i = 0; i < XR_N_FONTS; i++)
#include "output/options.h"
#include "output/message-item.h"
#include "output/page-eject-item.h"
+#include "output/pivot-output.h"
#include "output/table-item.h"
#include "output/table-provider.h"
}
static void
-csv_submit (struct output_driver *driver,
- const struct output_item *output_item)
+csv_output_table__ (struct csv_driver *csv, const struct table *t,
+ const char *leader)
{
- struct csv_driver *csv = csv_driver_cast (driver);
-
- if (is_table_item (output_item))
+ for (int y = 0; y < t->n[TABLE_VERT]; y++)
{
- struct table_item *table_item = to_table_item (output_item);
- const struct table *t = table_item_get_table (table_item);
- int x, y;
-
- csv_put_separator (csv);
-
- if (csv->titles)
- csv_output_table_cell (csv, table_item_get_title (table_item), "Table");
-
- for (y = 0; y < t->n[TABLE_VERT]; y++)
+ for (int x = 0; x < t->n[TABLE_HORZ]; x++)
{
- for (x = 0; x < t->n[TABLE_HORZ]; x++)
- {
- struct table_cell cell;
+ struct table_cell cell;
- table_get_cell (t, x, y, &cell);
+ table_get_cell (t, x, y, &cell);
- if (x > 0)
- fputs (csv->separator, csv->file);
+ if (x > 0)
+ fputs (csv->separator, csv->file);
- if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
- csv_output_field (csv, "");
- else
- csv_output_table_cell (csv, &cell, NULL);
- }
- putc ('\n', csv->file);
+ if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
+ csv_output_field (csv, "");
+ else
+ csv_output_table_cell (csv, &cell, !x ? leader : NULL);
}
+ putc ('\n', csv->file);
+ }
+}
- if (csv->captions)
- csv_output_table_cell (csv, table_item_get_caption (table_item),
- "Caption");
+static void
+csv_output_table_layer (struct csv_driver *csv, const struct pivot_table *pt,
+ const size_t *layer_indexes)
+{
+ struct table *title, *layers, *body, *caption, *footnotes;
+ pivot_output (pt, layer_indexes, &title, &layers, &body,
+ &caption, &footnotes, NULL, NULL);
+
+ csv_put_separator (csv);
+ csv_output_table__ (csv, title, "Table");
+ csv_output_table__ (csv, layers, "Layer");
+ csv_output_table__ (csv, body, NULL);
+ csv_output_table__ (csv, caption, "Caption");
+ csv_output_table__ (csv, footnotes, "Footnote");
+
+ table_unref (title);
+ table_unref (layers);
+ table_unref (body);
+ table_unref (caption);
+ table_unref (footnotes);
+}
- struct footnote **f;
- size_t n_footnotes = table_collect_footnotes (table_item, &f);
- if (n_footnotes)
- {
- fputs ("\nFootnotes:\n", csv->file);
+static void
+csv_submit (struct output_driver *driver,
+ const struct output_item *output_item)
+{
+ struct csv_driver *csv = csv_driver_cast (driver);
- for (size_t i = 0; i < n_footnotes; i++)
- {
- csv_output_field (csv, f[i]->marker);
- fputs (csv->separator, csv->file);
- csv_output_field (csv, f[i]->content);
- putc ('\n', csv->file);
- }
+ if (is_table_item (output_item))
+ {
+ const struct pivot_table *pt = to_table_item (output_item)->pt;
- free (f);
- }
+ size_t *layer_indexes;
+ PIVOT_OUTPUT_FOR_EACH_LAYER (layer_indexes, pt, true)
+ csv_output_table_layer (csv, pt, layer_indexes);
}
else if (is_text_item (output_item))
{
#include "output/message-item.h"
#include "output/options.h"
#include "output/output-item-provider.h"
+#include "output/pivot-output.h"
+#include "output/pivot-table.h"
#include "output/table-provider.h"
#include "output/table-item.h"
#include "output/text-item.h"
" margin-bottom: 1em\n"
"}\n"
"caption {\n"
- " text-align: left\n"
+ " text-align: left;\n"
"}\n"
"th { font-weight: normal }\n"
"a:link {\n"
}
}
-static void
-put_tfoot (struct html_driver *html, const struct table *t, bool *tfoot)
-{
- if (!*tfoot)
- {
- fputs ("<tfoot>\n", html->file);
- fputs ("<tr>\n", html->file);
- fprintf (html->file, "<td colspan=%d>\n", t->n[H]);
- *tfoot = true;
- }
- else
- fputs ("\n<br>", html->file);
-}
-
static void
html_put_footnote_markers (struct html_driver *html,
struct footnote **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, " ", "<br>");
- html_put_footnote_markers (html, layer->footnotes, layer->n_footnotes);
- }
-}
-
-static void
-html_put_table_cell (struct html_driver *html, const struct table *t,
- const struct table_cell *cell, const char *tag,
- bool border)
+html_put_table_cell (struct html_driver *html, const struct table_cell *cell,
+ const char *tag, const struct table *t)
{
fprintf (html->file, "<%s", tag);
put_style (&style, "font-size", buf);
}
- if (border)
+ if (t && html->borders)
{
put_border (t, cell, &style, V, 0, 0, "top");
put_border (t, cell, &style, H, 0, 0, "left");
}
static void
-html_output_table (struct html_driver *html, const struct table_item *item)
+html_output_table_layer (struct html_driver *html, const struct pivot_table *pt,
+ const size_t *layer_indexes)
{
- const struct table *t = table_item_get_table (item);
- bool tfoot = false;
+ struct table *title, *layers, *body, *caption, *footnotes;
+ pivot_output (pt, layer_indexes, &title, &layers, &body,
+ &caption, &footnotes, NULL, NULL);
fputs ("<table", html->file);
- if (item->notes)
+ if (pt->notes)
{
fputs (" title=\"", html->file);
- escape_string (html->file, item->notes, " ", "\n");
+ escape_string (html->file, pt->notes, " ", "\n");
putc ('"', html->file);
}
fputs (">\n", html->file);
- const struct table_cell *caption = table_item_get_caption (item);
- if (caption)
+ if (title)
{
- put_tfoot (html, t, &tfoot);
- html_put_table_cell (html, t, caption, "span", false);
+ struct table_cell cell;
+ table_get_cell (title, 0, 0, &cell);
+ html_put_table_cell (html, &cell, "caption", NULL);
}
- struct footnote **f;
- size_t n_footnotes = table_collect_footnotes (item, &f);
- for (size_t i = 0; i < n_footnotes; i++)
+ if (layers)
{
- put_tfoot (html, t, &tfoot);
- escape_tag (html->file, "sup", f[i]->marker, " ", "<br>");
- escape_string (html->file, f[i]->content, " ", "<br>");
- }
- free (f);
- if (tfoot)
- {
- fputs ("</td>\n", html->file);
- fputs ("</tr>\n", html->file);
- fputs ("</tfoot>\n", html->file);
- }
+ fputs ("<thead>\n", html->file);
+ for (size_t y = 0; y < layers->n[V]; y++)
+ {
+ fputs ("<tr>\n", html->file);
- const struct table_cell *title = table_item_get_title (item);
- const struct table_item_layers *layers = table_item_get_layers (item);
- if (title || layers)
- {
- fputs ("<caption>", html->file);
- if (title)
- html_put_table_cell (html, t, title, "span", false);
- if (title && layers)
- fputs ("<br>\n", html->file);
- if (layers)
- html_put_table_item_layers (html, layers);
- fputs ("</caption>\n", html->file);
+ struct table_cell cell;
+ table_get_cell (layers, 0, y, &cell);
+ cell.d[H][1] = body->n[H];
+ html_put_table_cell (html, &cell, "td", NULL);
+
+ fputs ("</tr>\n", html->file);
+ }
+ fputs ("</thead>\n", html->file);
}
fputs ("<tbody>\n", html->file);
-
- for (int y = 0; y < t->n[V]; y++)
+ for (int y = 0; y < body->n[V]; y++)
{
fputs ("<tr>\n", html->file);
- for (int x = 0; x < t->n[H]; )
+ for (int x = 0; x < body->n[H]; )
{
struct table_cell cell;
- table_get_cell (t, x, y, &cell);
+ table_get_cell (body, x, y, &cell);
if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
{
- bool is_header = (y < t->h[V][0]
- || y >= t->n[V] - t->h[V][1]
- || x < t->h[H][0]
- || x >= t->n[H] - t->h[H][1]);
+ bool is_header = (y < body->h[V][0]
+ || y >= body->n[V] - body->h[V][1]
+ || x < body->h[H][0]
+ || x >= body->n[H] - body->h[H][1]);
const char *tag = is_header ? "th" : "td";
- html_put_table_cell (html, t, &cell, tag, html->borders);
+ html_put_table_cell (html, &cell, tag, body);
}
x = cell.d[TABLE_HORZ][1];
}
fputs ("</tr>\n", html->file);
}
-
fputs ("</tbody>\n", html->file);
+
+ if (caption || footnotes)
+ {
+ fprintf (html->file, "<tfoot>\n");
+
+ if (caption)
+ {
+ fputs ("<tr>\n", html->file);
+
+ struct table_cell cell;
+ table_get_cell (caption, 0, 0, &cell);
+ cell.d[H][1] = body->n[H];
+ html_put_table_cell (html, &cell, "td", NULL);
+
+ fputs ("</tr>\n", html->file);
+ }
+
+ for (size_t y = 0; y < footnotes->n[V]; y++)
+ {
+ fputs ("<tr>\n", html->file);
+
+ struct table_cell cell;
+ table_get_cell (footnotes, 0, y, &cell);
+ cell.d[H][1] = body->n[H];
+ html_put_table_cell (html, &cell, "td", NULL);
+
+ fputs ("</tr>\n", html->file);
+ }
+ fputs ("</tfoot>\n", html->file);
+ }
+
fputs ("</table>\n\n", html->file);
+
+ table_unref (title);
+ table_unref (layers);
+ table_unref (body);
+ table_unref (caption);
+ table_unref (footnotes);
+}
+
+static void
+html_output_table (struct html_driver *html, const struct table_item *item)
+{
+ size_t *layer_indexes;
+ PIVOT_OUTPUT_FOR_EACH_LAYER (layer_indexes, item->pt, true)
+ html_output_table_layer (html, item->pt, layer_indexes);
}
struct output_driver_factory html_driver_factory =
#include "output/driver-provider.h"
#include "output/message-item.h"
#include "output/options.h"
+#include "output/pivot-table.h"
+#include "output/pivot-output.h"
#include "output/table-item.h"
#include "output/table-provider.h"
#include "output/text-item.h"
}
static void
-write_table_item_layers (struct odt_driver *odt,
- const struct table_item_layers *layers)
+write_table__ (struct odt_driver *odt, const struct table *t)
{
- if (!layers)
- return;
-
- for (size_t i = 0; i < layers->n_layers; i++)
+ if (t)
{
- 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);
+ for (size_t y = 0; y < t->n[V]; y++)
+ {
+ struct table_cell cell;
+ table_get_cell (t, 0, y, &cell);
+ write_table_item_cell (odt, &cell);
+ }
}
}
static void
-write_table (struct odt_driver *odt, const struct table_item *item)
+write_table_layer (struct odt_driver *odt, const struct pivot_table *pt,
+ const size_t *layer_indexes)
{
- const struct table *tab = table_item_get_table (item);
- int r, c;
+ struct table *title, *layers, *body, *caption, *footnotes;
+ pivot_output (pt, layer_indexes, &title, &layers, &body,
+ &caption, &footnotes, NULL, NULL);
/* Write a heading for the table */
- write_table_item_cell (odt, table_item_get_title (item));
- write_table_item_layers (odt, table_item_get_layers (item));
+ write_table__ (odt, title);
+ write_table__ (odt, layers);
/* Start table */
xmlTextWriterStartElement (odt->content_wtr, _xml("table:table"));
/* Start column definitions */
xmlTextWriterStartElement (odt->content_wtr, _xml("table:table-column"));
- xmlTextWriterWriteFormatAttribute (odt->content_wtr, _xml("table:number-columns-repeated"), "%d", tab->n[H]);
+ xmlTextWriterWriteFormatAttribute (odt->content_wtr, _xml("table:number-columns-repeated"), "%d", body->n[H]);
xmlTextWriterEndElement (odt->content_wtr);
/* Deal with row headers */
- if (tab->h[V][0] > 0)
+ if (body->h[V][0] > 0)
xmlTextWriterStartElement (odt->content_wtr, _xml("table:table-header-rows"));
/* Write all the rows */
- for (r = 0 ; r < tab->n[V]; ++r)
+ for (int r = 0 ; r < body->n[V]; ++r)
{
/* Start row definition */
xmlTextWriterStartElement (odt->content_wtr, _xml("table:table-row"));
/* Write all the columns */
- for (c = 0 ; c < tab->n[H] ; ++c)
+ for (int c = 0 ; c < body->n[H] ; ++c)
{
struct table_cell cell;
- table_get_cell (tab, c, r, &cell);
+ table_get_cell (body, c, r, &cell);
if (c == cell.d[H][0] && r == cell.d[V][0])
{
xmlTextWriterStartElement (odt->content_wtr, _xml("text:p"));
- if (r < tab->h[V][0] || c < tab->h[H][0])
+ if (r < body->h[V][0] || c < body->h[H][0])
xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Heading"));
else
xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Contents"));
xmlTextWriterEndElement (odt->content_wtr); /* row */
- int ht = tab->h[V][0];
+ int ht = body->h[V][0];
if (ht > 0 && r == ht - 1)
xmlTextWriterEndElement (odt->content_wtr); /* table-header-rows */
}
xmlTextWriterEndElement (odt->content_wtr); /* table */
/* Write a caption for the table */
- write_table_item_cell (odt, table_item_get_caption (item));
+ write_table__ (odt, caption);
+ write_table__ (odt, footnotes);
+
+ table_unref (title);
+ table_unref (layers);
+ table_unref (body);
+ table_unref (caption);
+ table_unref (footnotes);
+}
+
+static void
+write_table (struct odt_driver *odt, const struct table_item *item)
+{
+ size_t *layer_indexes;
+ PIVOT_OUTPUT_FOR_EACH_LAYER (layer_indexes, item->pt, true)
+ write_table_layer (odt, item->pt, layer_indexes);
}
static void
#define H TABLE_HORZ
#define V TABLE_VERT
+size_t *
+pivot_output_next_layer (const struct pivot_table *pt, size_t *indexes,
+ bool print)
+{
+ const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
+ if (print && pt->look->print_all_layers)
+ return pivot_axis_iterator_next (indexes, layer_axis);
+ else if (!indexes)
+ {
+ size_t size = layer_axis->n_dimensions * sizeof *pt->current_layer;
+ return xmemdup (pt->current_layer, MAX (size, 1));
+ }
+ else
+ {
+ free (indexes);
+ return NULL;
+ }
+}
+
static const struct pivot_category *
find_category (const struct pivot_dimension *d, int dim_index,
const size_t *indexes, int row_ofs)
}
}
-static struct table_cell *
-pivot_value_to_table_cell (const struct pivot_value *value,
- const struct table_area_style *style, int style_idx,
- struct footnote **footnotes,
- enum settings_value_show show_values,
- enum settings_value_show show_variables)
-{
- if (!value)
- return NULL;
-
- struct string s = DS_EMPTY_INITIALIZER;
- int options = format_cell (value, style_idx,
- show_values, show_variables, false, &s);
-
- struct table_cell *cell = xmalloc (sizeof *cell);
- *cell = (struct table_cell) {
- .options = options,
- .text = ds_steal_cstr (&s),
- .style = table_area_style_override (
- NULL, style, value->cell_style, value->font_style, false),
- };
-
- if (value->n_subscripts)
- {
- cell->subscripts = xnmalloc (value->n_subscripts,
- sizeof *cell->subscripts);
- cell->n_subscripts = value->n_subscripts;
- for (size_t i = 0; i < value->n_subscripts; i++)
- cell->subscripts[i] = xstrdup (value->subscripts[i]);
- }
-
- if (value->n_footnotes)
- {
- cell->footnotes = xnmalloc (value->n_footnotes, sizeof *cell->footnotes);
- for (size_t i = 0; i < value->n_footnotes; i++)
- {
- struct footnote *f = footnotes[value->footnotes[i]->idx];
- if (f)
- cell->footnotes[cell->n_footnotes++] = f;
- }
- }
-
- return cell;
-}
-
static int
get_table_rule (const struct table_border_style *styles,
enum pivot_border style_idx)
}
}
-struct table *
-pivot_table_to_table (const struct pivot_table *pt,
- const size_t *layer_indexes)
+static struct table *
+create_aux_table (const struct pivot_table *pt, int nc, int nr,
+ int style_idx)
+{
+ 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);
+ return table;
+}
+
+
+static struct footnote **
+add_footnotes (struct footnote **refs, size_t n_refs,
+ struct footnote **footnotes, size_t *allocated, size_t *n)
+{
+ 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;
+}
+
+size_t
+table_collect_footnotes (const struct table *
+ struct footnote ***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++)
+ {
+ 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);
+ }
+ }
+
+ 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);
+ }
+
+ const struct table_cell *caption = table_item_get_caption (item);
+ if (caption)
+ footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
+ footnotes, &allocated, &n);
+
+ size_t n_nonnull = 0;
+ for (size_t i = 0; i < n; i++)
+ if (footnotes[i])
+ footnotes[n_nonnull++] = footnotes[i];
+
+ *footnotesp = footnotes;
+ return n_nonnull;
+}
+
+void
+pivot_output (const struct pivot_table *pt,
+ const size_t *layer_indexes,
+ struct table **titlep,
+ struct table **layersp,
+ struct table **bodyp,
+ struct table **captionp,
+ struct table **footnotesp,
+ struct footnote ***fp, size_t *nfp)
{
const size_t *pindexes[PIVOT_N_AXES]
= { [PIVOT_AXIS_LAYER] = layer_indexes };
- size_t body[TABLE_N_AXES];
+ size_t data[TABLE_N_AXES];
size_t *column_enumeration = pivot_table_enumerate_axis (
- pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->look->omit_empty, &body[H]);
+ pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->look->omit_empty, &data[H]);
size_t *row_enumeration = pivot_table_enumerate_axis (
- pt, PIVOT_AXIS_ROW, layer_indexes, pt->look->omit_empty, &body[V]);
+ pt, PIVOT_AXIS_ROW, layer_indexes, pt->look->omit_empty, &data[V]);
int stub[TABLE_N_AXES] = {
[H] = pt->axes[PIVOT_AXIS_ROW].label_depth,
[V] = pt->axes[PIVOT_AXIS_COLUMN].label_depth,
};
- struct table *table = table_create (body[H] + stub[H],
- body[V] + stub[V],
- stub[H], 0, stub[V], 0);
-
+ struct table *body = table_create (data[H] + stub[H],
+ data[V] + stub[V],
+ stub[H], 0, stub[V], 0);
for (size_t i = 0; i < PIVOT_N_AREAS; i++)
- table->styles[i] = table_area_style_override (
- table->container, &pt->look->areas[i], NULL, NULL, false);
+ body->styles[i] = table_area_style_override (
+ body->container, &pt->look->areas[i], NULL, NULL, false);
for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
{
const struct table_border_style *in = &pt->look->borders[i];
- table->rule_colors[i] = pool_alloc (table->container,
- sizeof *table->rule_colors[i]);
- struct cell_color *out = table->rule_colors[i];
- out->alpha = in->color.alpha;
- out->r = in->color.r;
- out->g = in->color.g;
- out->b = in->color.b;
+ body->rule_colors[i] = pool_alloc (body->container,
+ sizeof *body->rule_colors[i]);
+ *body->rule_colors[i] = in->color;
}
struct footnote **footnotes = XCALLOC (pt->n_footnotes, struct footnote *);
char *marker = pivot_value_to_string (pf->marker, pt->show_values,
pt->show_variables);
footnotes[i] = table_create_footnote (
- table, i, content, marker,
- table_area_style_override (table->container,
+ body, i, content, marker,
+ table_area_style_override (body->container,
&pt->look->areas[PIVOT_AREA_FOOTER],
pf->content->cell_style,
pf->content->font_style,
free (content);
}
- compose_headings (table,
+ compose_headings (body,
&pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW],
pt->look->borders,
PIVOT_BORDER_DIM_COL_HORZ,
PIVOT_BORDER_DIM_COL_VERT,
PIVOT_BORDER_CAT_COL_HORZ,
PIVOT_BORDER_CAT_COL_VERT,
- column_enumeration, body[H],
+ column_enumeration, data[H],
&pt->look->areas[PIVOT_AREA_COLUMN_LABELS],
PIVOT_AREA_COLUMN_LABELS,
&pt->look->areas[PIVOT_AREA_CORNER], footnotes,
pt->show_values, pt->show_variables,
pt->rotate_outer_row_labels, false);
- compose_headings (table,
+ compose_headings (body,
&pt->axes[PIVOT_AXIS_ROW], V, &pt->axes[PIVOT_AXIS_COLUMN],
pt->look->borders,
PIVOT_BORDER_DIM_ROW_VERT,
PIVOT_BORDER_DIM_ROW_HORZ,
PIVOT_BORDER_CAT_ROW_VERT,
PIVOT_BORDER_CAT_ROW_HORZ,
- row_enumeration, body[V],
+ row_enumeration, data[V],
&pt->look->areas[PIVOT_AREA_ROW_LABELS],
PIVOT_AREA_ROW_LABELS,
&pt->look->areas[PIVOT_AREA_CORNER], footnotes,
{
pivot_table_convert_indexes_ptod (pt, pindexes, dindexes);
const struct pivot_value *value = pivot_table_get (pt, dindexes);
- fill_cell (table,
+ fill_cell (body,
x + stub[H], y + stub[V],
x + stub[H], y + stub[V],
&pt->look->areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA,
if ((pt->corner_text || !pt->look->row_labels_in_corner)
&& stub[H] && stub[V])
- fill_cell (table, 0, 0, stub[H] - 1, stub[V] - 1,
+ 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);
- if (table->n[H] && table->n[V])
+ if (body->n[H] && body->n[V])
{
table_hline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_TOP),
- 0, table->n[H] - 1, 0);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_TOP),
+ 0, body->n[H] - 1, 0);
table_hline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_BOTTOM),
- 0, table->n[H] - 1, table->n[V]);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_BOTTOM),
+ 0, body->n[H] - 1, body->n[V]);
table_vline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_LEFT),
- 0, 0, table->n[V] - 1);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_LEFT),
+ 0, 0, body->n[V] - 1);
table_vline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_RIGHT),
- table->n[H], 0, table->n[V] - 1);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_RIGHT),
+ body->n[H], 0, body->n[V] - 1);
if (stub[V])
table_hline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_TOP),
- 0, table->n[H] - 1, stub[V]);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_TOP),
+ 0, body->n[H] - 1, stub[V]);
if (stub[H])
table_vline (
- table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_LEFT),
- stub[H], 0, table->n[V] - 1);
+ body, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_LEFT),
+ stub[H], 0, body->n[V] - 1);
}
free (column_enumeration);
free (row_enumeration);
+ /* Title. */
+ struct table *title;
+ if (pt->title && titlep)
+ {
+ title = create_aux_table (pt, 1, 1, PIVOT_AREA_TITLE);
+ fill_cell (title, 0, 0, 1, 1,
+ &pt->look->areas[PIVOT_AREA_TITLE], PIVOT_AREA_TITLE,
+ pt->title, footnotes,
+ pt->show_values, pt->show_variables, false);
+ }
+ else
+ title = NULL;
+
+ /* Layers. */
+ const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
+ int n_layers = 0;
+ if (layersp)
+ for (size_t i = 0; i < layer_axis->n_dimensions; i++)
+ {
+ const struct pivot_dimension *d = layer_axis->dimensions[i];
+ if (d->n_leaves)
+ n_layers++;
+ }
+
+ struct table *layers;
+ if (n_layers > 0)
+ {
+ layers = create_aux_table (pt, 1, n_layers, PIVOT_AREA_LAYERS);
+ size_t y = 0;
+ for (size_t i = 0; i < layer_axis->n_dimensions; i++)
+ {
+ const struct pivot_dimension *d = layer_axis->dimensions[i];
+ if (!d->n_leaves)
+ continue;
+
+ /* 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,
+ &pt->look->areas[PIVOT_AREA_LAYERS], PIVOT_AREA_LAYERS,
+ name, footnotes,
+ pt->show_values, pt->show_variables, false);
+ y++;
+ }
+ }
+ else
+ layers = NULL;
+
+ /* Caption. */
+ struct table *caption;
+ if (pt->caption && captionp)
+ {
+ caption = create_aux_table (pt, 1, 1, PIVOT_AREA_CAPTION);
+ fill_cell (caption, 0, 0, 1, 1,
+ &pt->look->areas[PIVOT_AREA_CAPTION], PIVOT_AREA_CAPTION,
+ pt->caption, footnotes,
+ pt->show_values, pt->show_variables, false);
+ }
+ else
+ caption = NULL;
+
free (footnotes);
- return table;
+ *bodyp = body;
}
void
#ifndef OUTPUT_PIVOT_OUTPUT_H
#define OUTPUT_PIVOT_OUTPUT_H 1
+#include <stdbool.h>
#include <stddef.h>
+struct footnote;
struct pivot_table;
-
-struct table *pivot_table_to_table (const struct pivot_table *,
- const size_t *layer_indexes);
+struct table;
+
+#define PIVOT_OUTPUT_FOR_EACH_LAYER(INDEXES, PT, PRINT) \
+ for ((INDEXES) = NULL; \
+ ((INDEXES) = pivot_output_next_layer (PT, INDEXES, PRINT)); )
+size_t *pivot_output_next_layer (const struct pivot_table *,
+ size_t *indexes, bool print);
+
+void pivot_output (const struct pivot_table *,
+ const size_t *layer_indexes,
+ struct table **titlep,
+ struct table **layersp,
+ struct table **bodyp,
+ struct table **captionp,
+ struct table **footnotesp,
+ struct footnote ***fp, size_t *nfp);
#endif /* output/pivot-output.h */
return hmap_is_empty (&table->cells);
}
-size_t *
-pivot_table_next_display_layer (const struct pivot_table *pt, size_t *indexes,
- bool print)
-{
- const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
- if (print && pt->look->print_all_layers)
- return pivot_axis_iterator_next (indexes, layer_axis);
- else if (!indexes)
- {
- size_t size = layer_axis->n_dimensions * sizeof *pt->current_layer;
- return xmemdup (pt->current_layer, MAX (size, 1));
- }
- else
- {
- free (indexes);
- return NULL;
- }
-}
-
static unsigned int
pivot_cell_hash_indexes (const size_t *indexes, size_t n_idx)
{
/* Output. */
void pivot_table_submit (struct pivot_table *);
-/* Layers. */
-#define PIVOT_TABLE_FOR_EACH_DISPLAY_LAYER(INDEXES, PT, PRINT) \
- for ((INDEXES) = NULL; \
- ((INDEXES) = pivot_table_next_display_layer (PT, INDEXES, PRINT)); )
-size_t *pivot_table_next_display_layer (const struct pivot_table *,
- size_t *indexes, bool print);
-
/* Data cells. */
void pivot_table_put (struct pivot_table *, const size_t *dindexes, size_t n,
struct pivot_value *);
#include "libpspp/hash-functions.h"
#include "libpspp/hmap.h"
#include "libpspp/pool.h"
+#include "output/pivot-output.h"
#include "output/pivot-table.h"
#include "output/render.h"
#include "output/table-item.h"
const struct render_params *params;
double scale;
- /* An array of "render_page"s to be rendered, in order, vertically. From
- the user's perspective, there's only one table per render_pager, but the
- implementation treats the title, table body, caption, footnotes,
- etc. each as a table, and that's why we have an array here. */
- struct render_page **pages;
- size_t n_pages, allocated_pages;
+ /* An array of "render_page"s to be rendered, in order, vertically. There
+ may be up to 5 pages, for the pivot table's title, layers, body,
+ captions, and footnotes. */
+ struct render_page *pages[5];
+ size_t n_pages;
size_t cur_page;
struct render_break x_break;
render_pager_add_table (struct render_pager *p, struct table *table,
int min_width)
{
- if (p->n_pages >= p->allocated_pages)
- p->pages = x2nrealloc (p->pages, &p->allocated_pages, sizeof *p->pages);
-
struct render_page *page = render_page_create (p->params, table, min_width);
p->pages[p->n_pages++] = page;
return page;
render_break_init_empty (&p->y_break);
}
-static void
-add_footnote_page (struct render_pager *p, const struct table_item *item)
-{
- struct footnote **f;
- size_t n_footnotes = table_collect_footnotes (item, &f);
- if (!n_footnotes)
- return;
-
- struct table *t = table_create (1, n_footnotes, 0, 0, 0, 0);
-
- for (size_t i = 0; i < n_footnotes; i++)
- {
- table_text_format (t, 0, i, 0, "%s. %s", f[i]->marker, f[i]->content);
- table_add_style (t, 0, i, f[i]->style);
- }
- render_pager_add_table (p, t, 0);
-
- free (f);
-}
-
-static void
-add_table_cell_page (struct render_pager *p, const struct table_cell *cell,
- int min_width)
-{
- if (!cell)
- return;
-
- struct table *tab = table_create (1, 1, 0, 0, 0, 0);
- table_text (tab, 0, 0, 0, cell->text);
- for (size_t i = 0; i < cell->n_footnotes; i++)
- table_add_footnote (tab, 0, 0, cell->footnotes[i]);
- if (cell->style)
- tab->styles[0] = table_area_style_clone (tab->container, cell->style);
- render_pager_add_table (p, tab, min_width);
-}
-
-static void
-add_layers_page (struct render_pager *p,
- const struct table_item_layers *layers, int min_width)
-{
- if (!layers)
- return;
-
- struct table *tab = table_create (1, layers->n_layers, 0, 0, 0, 0);
- for (size_t i = 0; i < layers->n_layers; i++)
- {
- const struct table_item_layer *layer = &layers->layers[i];
- table_text (tab, 0, i, 0, layer->content);
- for (size_t j = 0; j < layer->n_footnotes; j++)
- table_add_footnote (tab, 0, i, layer->footnotes[j]);
- }
- if (layers->style)
- tab->styles[0] = table_area_style_clone (tab->container, layers->style);
- render_pager_add_table (p, tab, min_width);
-}
-
/* Creates and returns a new render_pager for rendering TABLE_ITEM on the
device with the given PARAMS. */
struct render_pager *
render_pager_create (const struct render_params *params,
- const struct table_item *table_item)
+ const struct table_item *table_item,
+ const size_t *layer_indexes)
{
- const struct table *table = table_item_get_table (table_item);
+ const struct pivot_table *pt = table_item->pt;
+ if (!layer_indexes)
+ layer_indexes = pt->current_layer;
+
+ struct table *title, *layers, *body, *caption, *footnotes;
+ pivot_output (pt, layer_indexes, &title, &layers, &body, &caption,
+ &footnotes, NULL, NULL);
/* Figure out the width of the body of the table. Use this to determine the
base scale. */
- struct render_page *page = render_page_create (params, table_ref (table), 0);
- int body_width = table_width (page, H);
+ struct render_page *body_page = render_page_create (params, body, 0);
+ int body_width = table_width (body_page, H);
double scale = 1.0;
if (body_width > params->size[H])
{
else
{
struct render_break b;
- render_break_init (&b, page, H);
+ render_break_init (&b, render_page_ref (body_page), H);
struct render_page *subpage
= render_break_next (&b, params->size[H]);
body_width = subpage ? subpage->cp[H][2 * subpage->n[H] + 1] : 0;
/* Create the pager. */
struct render_pager *p = xmalloc (sizeof *p);
*p = (struct render_pager) { .params = params, .scale = scale };
- add_table_cell_page (p, table_item_get_title (table_item), body_width);
- add_layers_page (p, table_item_get_layers (table_item), body_width);
- render_pager_add_table (p, table_ref (table_item_get_table (table_item)), 0);
- add_table_cell_page (p, table_item_get_caption (table_item), 0);
- add_footnote_page (p, table_item);
+ render_pager_add_table (p, title, body_width);
+ render_pager_add_table (p, layers, body_width);
+ p->pages[p->n_pages++] = body_page;
+ render_pager_add_table (p, caption, 0);
+ render_pager_add_table (p, footnotes, 0);
+ assert (p->n_pages < sizeof p->pages / sizeof *p->pages);
/* If we're shrinking tables to fit the page length, then adjust the scale
factor.
render_break_destroy (&p->y_break);
for (size_t i = 0; i < p->n_pages; i++)
render_page_unref (p->pages[i]);
- free (p->pages);
free (p);
}
}
/* An iterator for breaking render_pages into smaller chunks. */
struct render_pager *render_pager_create (const struct render_params *,
- const struct table_item *);
+ const struct table_item *,
+ const size_t *layer_indexes);
void render_pager_destroy (struct render_pager *);
bool render_pager_has_next (const struct render_pager *);
struct footnote
{
- size_t idx;
+ //size_t idx;
char *content;
char *marker;
struct table_area_style *style;
ds_put_cstr (s, cell->footnotes[i]->marker);
}
}
-
-static struct footnote **
-add_footnotes (struct footnote **refs, size_t n_refs,
- struct footnote **footnotes, size_t *allocated, size_t *n)
-{
- 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;
-}
-
-size_t
-table_collect_footnotes (const struct table_item *item,
- struct footnote ***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++)
- {
- 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);
- }
- }
-
- 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);
- }
-
- const struct table_cell *caption = table_item_get_caption (item);
- if (caption)
- footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
- footnotes, &allocated, &n);
-
- size_t n_nonnull = 0;
- for (size_t i = 0; i < n; i++)
- if (footnotes[i])
- footnotes[n_nonnull++] = footnotes[i];
-
- *footnotesp = footnotes;
- return n_nonnull;
-}
\f
const char *
table_halign_to_string (enum table_halign halign)
}
\f
/* Initializes CELL with the contents of the table cell at column X and row Y
- within TABLE. When CELL is no longer needed, the caller is responsible for
- freeing it by calling table_cell_free(CELL).
-
- The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
+ within TABLE. */
void
table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
{
/* Tables.
-. A table is a rectangular grid of cells. Cells can be joined to form larger
+ A table is a rectangular grid of cells. Cells can be joined to form larger
cells. Rows and columns can be separated by rules of various types. Rows
at the top and bottom of a table and columns at the left and right edges of
a table can be designated as headers, which means that if the table must be
#include "output/message-item.h"
#include "output/options.h"
#include "output/output-item-provider.h"
+#include "output/pivot-output.h"
+#include "output/pivot-table.h"
#include "output/table-provider.h"
#include "output/table-item.h"
#include "output/text-item.h"
}
static void
-tex_output_table (struct tex_driver *tex, const struct table_item *item)
+tex_output_table_layer (struct tex_driver *tex, const struct pivot_table *pt,
+ const size_t *layer_indexes)
{
/* Tables are rendered in TeX with the \halign command.
This is described in the TeXbook Ch. 22 */
-
- const struct table *t = table_item_get_table (item);
+ struct table *title, *layers, *body, *caption;
+ struct footnote **footnotes;
+ size_t n_footnotes;
+ pivot_output (pt, layer_indexes, &title, &layers, &body,
+ &caption, NULL, &footnotes, &n_footnotes);
shipout (&tex->token_list, "\n{\\parindent=0pt\n");
- const struct table_cell *caption = table_item_get_caption (item);
if (caption)
{
shipout (&tex->token_list, "{\\sl ");
- tex_escape_string (tex, caption->text, false);
+ struct table_cell cell;
+ table_get_cell (caption, 0, 0, &cell);
+ tex_put_table_cell (tex, &cell);
shipout (&tex->token_list, "}\n\n");
}
- struct footnote **f;
- size_t n_footnotes = table_collect_footnotes (item, &f);
- const struct table_cell *title = table_item_get_title (item);
- const struct table_item_layers *layers = table_item_get_layers (item);
if (title || layers)
{
if (title)
{
shipout (&tex->token_list, "{\\bf ");
- tex_put_table_cell (tex, title);
- shipout (&tex->token_list, "}");
+ struct table_cell cell;
+ table_get_cell (title, 0, 0, &cell);
+ tex_put_table_cell (tex, &cell);
+ shipout (&tex->token_list, "}\\par\n");
}
+
if (layers)
- abort ();
- shipout (&tex->token_list, "\\par\n");
+ {
+ for (size_t y = 0; y < layers->n[V]; y++)
+ {
+ shipout (&tex->token_list, "{");
+ struct table_cell cell;
+ table_get_cell (layers, 0, y, &cell);
+ tex_put_table_cell (tex, &cell);
+ shipout (&tex->token_list, "}\\par\n");
+ }
+ }
}
shipout (&tex->token_list, "\\offinterlineskip\\halign{\\strut%%\n");
/* Generate the preamble */
- for (int x = 0; x < t->n[H]; ++x)
+ for (int x = 0; x < body->n[H]; ++x)
{
- shipout (&tex->token_list, "{\\vbox{\\cell{%d}#}}", t->n[H]);
+ shipout (&tex->token_list, "{\\vbox{\\cell{%d}#}}", body->n[H]);
- if (x < t->n[H] - 1)
+ if (x < body->n[H] - 1)
{
shipout (&tex->token_list, "\\hskip\\psppcolumnspace\\hfil");
shipout (&tex->token_list, "&\\vrule\n");
}
/* Emit the row data */
- for (int y = 0; y < t->n[V]; y++)
+ for (int y = 0; y < body->n[V]; y++)
{
enum { H = TABLE_HORZ, V = TABLE_VERT };
- bool is_column_header = y < t->h[V][0] || y >= t->n[V] - t->h[V][1];
+ bool is_column_header = y < body->h[V][0] || y >= body->n[V] - body->h[V][1];
int prev_x = -1;
int skipped = 0;
- for (int x = 0; x < t->n[H];)
+ for (int x = 0; x < body->n[H];)
{
struct table_cell cell;
- table_get_cell (t, x, y, &cell);
+ table_get_cell (body, x, y, &cell);
int colspan = table_cell_colspan (&cell);
if (x > 0)
if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
goto next_1;
- /* bool is_header = (y < t->h[V][0] */
- /* || y >= t->n[V] - t->h[V][1] */
- /* || x < t->h[H][0] */
- /* || x >= t->n[H] - t->h[H][1]); */
+ /* bool is_header = (y < body->h[V][0] */
+ /* || y >= body->n[V] - body->h[V][1] */
+ /* || x < body->h[H][0] */
+ /* || x >= body->n[H] - body->h[H][1]); */
enum table_halign halign =
table_halign_interpret (cell.style->cell_style.halign,
for (int i = 0; i < n_footnotes; ++i)
{
shipout (&tex->token_list, "$^{");
- tex_escape_string (tex, f[i]->marker, false);
+ tex_escape_string (tex, footnotes[i]->marker, false);
shipout (&tex->token_list, "}$");
- tex_escape_string (tex, f[i]->content, false);
+ tex_escape_string (tex, footnotes[i]->content, false);
}
- free (f);
shipout (&tex->token_list, "}\n\\vskip 3ex\n\n");
+
+ table_unref (title);
+ table_unref (layers);
+ table_unref (body);
+ table_unref (caption);
+ free (footnotes);
+}
+
+static void
+tex_output_table (struct tex_driver *tex, const struct table_item *item)
+{
+ size_t *layer_indexes;
+ PIVOT_OUTPUT_FOR_EACH_LAYER (layer_indexes, item->pt, true)
+ tex_output_table_layer (tex, item->pt, layer_indexes);
}
struct output_driver_factory tex_driver_factory =
pivot_value_set_font_style (content, &text_item->style);
pivot_table_put1 (table, 0, content);
- return table;
+ return table_item_create (table);
}
\f
static const char *
#include "output/message-item.h"
#include "output/output-item.h"
#include "output/output-item-provider.h"
+#include "output/pivot-table.h"
#include "output/table-item.h"
#include "output/text-item.h"
[XR_FONT_FIXED] = ff,
},
.use_system_colors = true,
+ .object_spacing = XR_POINT * 12,
.font_resolution = 96.0,
};
if (is_table_item (item->item))
{
const struct table_item *ti = to_table_item (item->item);
- gtk_widget_set_tooltip_text (item->drawing_area, ti->notes);
+ gtk_widget_set_tooltip_text (item->drawing_area, ti->pt->notes);
}
{
[V] = { margins[V][0], margins[V][1] },
},
.initial_page_number = 1,
- .object_spacing = 12 * XR_POINT,
};
view->fsm_style = xmalloc (sizeof *view->fsm_style);
},
.fg = CELL_COLOR_BLACK,
.use_system_colors = false,
+ .object_spacing = 12 * XR_POINT,
.font_resolution = 72.0
};