/* PSPP - a program for statistical analysis.
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2011, 2014, 2016 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
#include <config.h>
-#include <output/table.h>
-#include <output/table-provider.h>
+#include "output/table.h"
+#include "output/table-provider.h"
#include <assert.h>
#include <stdlib.h>
-#include <libpspp/cast.h>
-#include <libpspp/compiler.h>
+#include "libpspp/cast.h"
+#include "libpspp/compiler.h"
+#include "libpspp/pool.h"
+#include "libpspp/str.h"
+#include "output/table-item.h"
#include "gl/xalloc.h"
{
assert (table->ref_cnt > 0);
if (--table->ref_cnt == 0)
- table->class->destroy (table);
+ table->klass->destroy (table);
}
}
void
table_init (struct table *table, const struct table_class *class)
{
- table->class = class;
+ table->klass = class;
table->n[TABLE_HORZ] = table->n[TABLE_VERT] = 0;
table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
table->n[TABLE_VERT] = nr;
}
\f
+struct cell_style *
+cell_style_clone (struct pool *pool, const struct cell_style *old)
+{
+ struct cell_style *new = pool_malloc (pool, sizeof *new);
+ *new = *old;
+ if (new->font)
+ new->font = pool_strdup (pool, new->font);
+ return new;
+}
+
+void
+cell_style_free (struct cell_style *style)
+{
+ if (style)
+ {
+ free (style->font);
+ free (style);
+ }
+}
+
/* 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).
{
assert (x >= 0 && x < table->n[TABLE_HORZ]);
assert (y >= 0 && y < table->n[TABLE_VERT]);
- table->class->get_cell (table, x, y, cell);
+
+ static const struct cell_style default_style = CELL_STYLE_INITIALIZER;
+ cell->style = &default_style;
+
+ table->klass->get_cell (table, x, y, cell);
}
/* Frees CELL, which should have been initialized by calling
between that cell and cell (0,1); and so on, up to (0,NR), which runs
horizontally below cell (0,NR-1). */
int
-table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
+table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
- return table->class->get_rule (table, axis, x, y);
+ *color = CELL_COLOR_BLACK;
+ return table->klass->get_rule (table, axis, x, y, color);
+}
+
+void
+cell_contents_format_footnote_markers (const struct cell_contents *c,
+ struct string *s)
+{
+ for (size_t i = 0; i < c->n_footnotes; i++)
+ {
+ if (i)
+ ds_put_byte (s, ',');
+ ds_put_cstr (s, c->footnotes[i]->marker);
+ }
+}
+
+static const struct footnote **
+add_footnotes (const struct footnote **refs, size_t n_refs,
+ const struct footnote **footnotes, size_t *allocated, size_t *n)
+{
+ for (size_t i = 0; i < n_refs; i++)
+ {
+ const 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,
+ const struct footnote ***footnotesp)
+{
+ const struct footnote **footnotes = NULL;
+ size_t allocated = 0;
+ size_t n = 0;
+
+ struct table *t = item->table;
+ for (int y = 0; y < table_nr (t); y++)
+ {
+ struct table_cell cell;
+ for (int x = 0; x < table_nc (t); 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])
+ for (size_t i = 0; i < cell.n_contents; i++)
+ {
+ const struct cell_contents *c = &cell.contents[i];
+ footnotes = add_footnotes (c->footnotes, c->n_footnotes,
+ footnotes, &allocated, &n);
+ }
+ table_cell_free (&cell);
+ }
+ }
+
+ const struct table_item_text *title = table_item_get_title (item);
+ if (title)
+ footnotes = add_footnotes (title->footnotes, title->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,
+ footnotes, &allocated, &n);
+
+ *footnotesp = footnotes;
+ return n;
}
\f
struct table_unshared
static struct table_unshared *
table_unshared_cast (const struct table *table)
{
- assert (table->class == &table_unshared_class);
+ assert (table->klass == &table_unshared_class);
return UP_CAST (table, struct table_unshared, table);
}
static int
table_unshared_get_rule (const struct table *tiu_,
- enum table_axis axis, int x, int y)
+ enum table_axis axis, int x, int y,
+ struct cell_color *color)
{
struct table_unshared *tiu = table_unshared_cast (tiu_);
- return table_get_rule (tiu->subtable, axis, x, y);
+ return table_get_rule (tiu->subtable, axis, x, y, color);
}
static const struct table_class table_unshared_class =
static struct table_string *
table_string_cast (const struct table *table)
{
- assert (table->class == &table_string_class);
+ assert (table->klass == &table_string_class);
return UP_CAST (table, struct table_string, table);
}
cell->d[TABLE_HORZ][1] = 1;
cell->d[TABLE_VERT][0] = 0;
cell->d[TABLE_VERT][1] = 1;
- cell->contents = ts->string;
- cell->options = ts->options;
+ cell->contents = &cell->inline_contents;
+ cell->inline_contents.options = ts->options;
+ cell->inline_contents.text = ts->string;
+ cell->inline_contents.n_footnotes = 0;
+ cell->n_contents = 1;
cell->destructor = NULL;
}
static int
table_string_get_rule (const struct table *ts UNUSED,
- enum table_axis axis UNUSED, int x UNUSED, int y UNUSED)
+ enum table_axis axis UNUSED, int x UNUSED, int y UNUSED,
+ struct cell_color *color UNUSED)
{
return TAL_0;
}