#include "libpspp/pool.h"
#include "libpspp/str.h"
#include "output/table-item.h"
-#include "output/tab.h"
+#include "output/table.h"
#include "output/text-item.h"
#include "gl/xalloc.h"
return table->ref_cnt > 1;
}
\f
-struct area_style *
-area_style_clone (struct pool *pool, const struct area_style *old)
+struct table_area_style *
+table_area_style_clone (struct pool *pool, const struct table_area_style *old)
{
- struct area_style *new = pool_malloc (pool, sizeof *new);
+ struct table_area_style *new = pool_malloc (pool, sizeof *new);
*new = *old;
if (new->font_style.typeface)
new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
}
void
-area_style_free (struct area_style *style)
+table_area_style_free (struct table_area_style *style)
{
if (style)
{
struct table *
table_from_string (const char *text)
{
- struct table *t = tab_create (1, 1, 0, 0, 0, 0);
- tab_text (t, 0, 0, TAB_LEFT, text);
+ struct table *t = table_create (1, 1, 0, 0, 0, 0);
+ t->styles[0] = pool_alloc (t->container, sizeof *t->styles[0]);
+ *t->styles[0] = (struct table_area_style) {
+ TABLE_AREA_STYLE_INITIALIZER__,
+ .cell_style.halign = TABLE_HALIGN_LEFT,
+ .cell_style.valign = TABLE_VALIGN_TOP
+ };
+ table_text (t, 0, 0, 0 << TAB_STYLE_SHIFT, text);
return t;
}
\f
}
void
-font_style_copy (struct font_style *dst, const struct font_style *src)
+font_style_copy (struct pool *container,
+ struct font_style *dst, const struct font_style *src)
{
*dst = *src;
if (dst->typeface)
- dst->typeface = xstrdup (dst->typeface);
+ dst->typeface = pool_strdup (container, dst->typeface);
}
void
}
void
-area_style_copy (struct area_style *dst, const struct area_style *src)
+table_area_style_copy (struct pool *container, struct table_area_style *dst,
+ const struct table_area_style *src)
{
- font_style_copy (&dst->font_style, &src->font_style);
+ font_style_copy (container, &dst->font_style, &src->font_style);
dst->cell_style = src->cell_style;
}
void
-area_style_uninit (struct area_style *area)
+table_area_style_uninit (struct table_area_style *area)
{
if (area)
font_style_uninit (&area->font_style);
static const bool debugging = true;
-/* Joined cell. */
-struct tab_joined_cell
-{
- int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */
- char *text;
-
- size_t n_footnotes;
- const struct footnote **footnotes;
-
- const struct area_style *style;
-};
-
/* Creates and returns a new table with NC columns and NR rows and initially no
header rows or columns.
The table's cells are initially empty. */
struct table *
-tab_create (int nc, int nr, int hl, int hr, int ht, int hb)
+table_create (int nc, int nr, int hl, int hr, int ht, int hb)
{
struct table *t;
t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
t->rh = pool_nmalloc (t->container, nc, nr + 1);
- memset (t->rh, TAL_0, nc * (nr + 1));
+ memset (t->rh, TABLE_STROKE_NONE, nc * (nr + 1));
t->rv = pool_nmalloc (t->container, nr, nc + 1);
- memset (t->rv, TAL_0, nr * (nc + 1));
+ memset (t->rv, TABLE_STROKE_NONE, nr * (nc + 1));
memset (t->styles, 0, sizeof t->styles);
memset (t->rule_colors, 0, sizeof t->rule_colors);
/* Draws a vertical line to the left of cells at horizontal position X
from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
void
-tab_vline (struct table *t, int style, int x, int y1, int y2)
+table_vline (struct table *t, int style, int x, int y1, int y2)
{
if (debugging)
{
/* Draws a horizontal line above cells at vertical position Y from X1
to X2 inclusive in style STYLE, if style is not -1. */
void
-tab_hline (struct table *t, int style, int x1, int x2, int y)
+table_hline (struct table *t, int style, int x1, int x2, int y)
{
if (debugging)
{
drawing those lines. This is distinct from 0, which draws a null
line. */
void
-tab_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
- int x1, int y1, int x2, int y2)
+table_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
+ int x1, int y1, int x2, int y2)
{
if (debugging)
{
/* Cells. */
static void
-do_tab_text (struct table *table, int c, int r, unsigned opt, char *text)
+do_table_text (struct table *table, int c, int r, unsigned opt, char *text)
{
assert (c >= 0);
assert (r >= 0);
{
if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table))
{
- printf ("tab_text(): bad cell (%d,%d) in table size (%d,%d)\n",
+ printf ("table_text(): bad cell (%d,%d) in table size (%d,%d)\n",
c, r, table_nc (table), table_nr (table));
return;
}
/* Sets cell (C,R) in TABLE, with options OPT, to have text value
TEXT. */
void
-tab_text (struct table *table, int c, int r, unsigned opt,
+table_text (struct table *table, int c, int r, unsigned opt,
const char *text)
{
- do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
+ do_table_text (table, c, r, opt, pool_strdup (table->container, text));
}
/* Sets cell (C,R) in TABLE, with options OPT, to have text value
FORMAT, which is formatted as if passed to printf. */
void
-tab_text_format (struct table *table, int c, int r, unsigned opt,
- const char *format, ...)
+table_text_format (struct table *table, int c, int r, unsigned opt,
+ const char *format, ...)
{
va_list args;
va_start (args, format);
- do_tab_text (table, c, r, opt,
- pool_vasprintf (table->container, format, args));
+ do_table_text (table, c, r, opt,
+ pool_vasprintf (table->container, format, args));
va_end (args);
}
-static struct tab_joined_cell *
+static struct table_cell *
add_joined_cell (struct table *table, int x1, int y1, int x2, int y2,
unsigned opt)
{
- struct tab_joined_cell *j;
-
assert (x1 >= 0);
assert (y1 >= 0);
assert (y2 >= y1);
|| x2 < x1 || x2 >= table_nc (table)
|| y2 < y1 || y2 >= table_nr (table))
{
- printf ("tab_joint_text(): bad cell "
+ printf ("table_joint_text(): bad cell "
"(%d,%d)-(%d,%d) in table size (%d,%d)\n",
x1, y1, x2, y2, table_nc (table), table_nr (table));
return NULL;
}
}
- tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
-
- j = pool_alloc (table->container, sizeof *j);
- j->d[TABLE_HORZ][0] = x1;
- j->d[TABLE_VERT][0] = y1;
- j->d[TABLE_HORZ][1] = ++x2;
- j->d[TABLE_VERT][1] = ++y2;
- j->n_footnotes = 0;
- j->footnotes = NULL;
- j->style = NULL;
-
- {
- void **cc = &table->cc[x1 + y1 * table_nc (table)];
- unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)];
- const int ofs = table_nc (table) - (x2 - x1);
+ table_box (table, -1, -1, TABLE_STROKE_NONE, TABLE_STROKE_NONE,
+ x1, y1, x2, y2);
- int y;
+ struct table_cell *cell = pool_alloc (table->container, sizeof *cell);
+ *cell = (struct table_cell) {
+ .d = { [TABLE_HORZ] = { x1, ++x2 },
+ [TABLE_VERT] = { y1, ++y2 } },
+ .options = opt,
+ };
- for (y = y1; y < y2; y++)
- {
- int x;
-
- for (x = x1; x < x2; x++)
- {
- *cc++ = j;
- *ct++ = opt | TAB_JOIN;
- }
+ void **cc = &table->cc[x1 + y1 * table_nc (table)];
+ unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)];
+ const int ofs = table_nc (table) - (x2 - x1);
+ for (int y = y1; y < y2; y++)
+ {
+ for (int x = x1; x < x2; x++)
+ {
+ *cc++ = cell;
+ *ct++ = opt | TAB_JOIN;
+ }
- cc += ofs;
- ct += ofs;
- }
- }
+ cc += ofs;
+ ct += ofs;
+ }
- return j;
+ return cell;
}
/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
options OPT to have text value TEXT. */
void
-tab_joint_text (struct table *table, int x1, int y1, int x2, int y2,
- unsigned opt, const char *text)
+table_joint_text (struct table *table, int x1, int y1, int x2, int y2,
+ unsigned opt, const char *text)
{
char *s = pool_strdup (table->container, text);
if (x1 == x2 && y1 == y2)
- do_tab_text (table, x1, y1, opt, s);
+ do_table_text (table, x1, y1, opt, s);
else
add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
}
-struct footnote *
-tab_create_footnote (struct table *table, size_t idx, const char *content,
- const char *marker, struct area_style *style)
-{
- struct footnote *f = pool_alloc (table->container, sizeof *f);
- f->idx = idx;
- f->content = pool_strdup (table->container, content);
- f->marker = pool_strdup (table->container, marker);
- f->style = style;
- return f;
-}
-
-void
-tab_add_footnote (struct table *table, int x, int y,
- const struct footnote *f)
+static struct table_cell *
+get_joined_cell (struct table *table, int x, int y)
{
int index = x + y * table_nc (table);
unsigned short opt = table->ct[index];
- struct tab_joined_cell *j;
+ struct table_cell *cell;
if (opt & TAB_JOIN)
- j = table->cc[index];
+ cell = table->cc[index];
else
{
char *text = table->cc[index];
- j = add_joined_cell (table, x, y, x, y, table->ct[index]);
- j->text = text ? text : xstrdup ("");
+ cell = add_joined_cell (table, x, y, x, y, table->ct[index]);
+ cell->text = text ? text : pool_strdup (table->container, "");
}
+ return cell;
+}
- j->footnotes = pool_realloc (table->container, j->footnotes,
- (j->n_footnotes + 1) * sizeof *j->footnotes);
+/* Sets the subscripts for column X, row Y in TABLE. */
+void
+table_add_subscripts (struct table *table, int x, int y,
+ char **subscripts, size_t n_subscripts)
+{
+ struct table_cell *cell = get_joined_cell (table, x, y);
- j->footnotes[j->n_footnotes++] = f;
+ cell->n_subscripts = n_subscripts;
+ cell->subscripts = pool_nalloc (table->container, n_subscripts,
+ sizeof *cell->subscripts);
+ for (size_t i = 0; i < n_subscripts; i++)
+ cell->subscripts[i] = pool_strdup (table->container, subscripts[i]);
}
+/* Sets the superscript for column X, row Y in TABLE. */
void
-tab_add_style (struct table *table, int x, int y,
- const struct area_style *style)
+table_add_superscript (struct table *table, int x, int y,
+ const char *superscript)
{
- int index = x + y * table_nc (table);
- unsigned short opt = table->ct[index];
- struct tab_joined_cell *j;
+ get_joined_cell (table, x, y)->superscript
+ = pool_strdup (table->container, superscript);
+}
- if (opt & TAB_JOIN)
- j = table->cc[index];
- else
- {
- char *text = table->cc[index];
+/* Create a footnote in TABLE with MARKER (e.g. "a") as its marker and CONTENT
+ as its content. The footnote will be styled as STYLE, which is mandatory.
+ IDX must uniquely identify the footnote within TABLE.
- j = add_joined_cell (table, x, y, x, y, table->ct[index]);
- j->text = text ? text : xstrdup ("");
- }
+ Returns the new footnote. The return value is the only way to get to the
+ footnote later, so it is important for the caller to remember it. */
+struct footnote *
+table_create_footnote (struct table *table, size_t idx, const char *content,
+ const char *marker, struct table_area_style *style)
+{
+ assert (style);
- j->style = style;
+ struct footnote *f = pool_alloc (table->container, sizeof *f);
+ f->idx = idx;
+ f->content = pool_strdup (table->container, content);
+ f->marker = pool_strdup (table->container, marker);
+ f->style = style;
+ return f;
}
+/* Attaches a reference to footnote F to the cell at column X, row Y in
+ TABLE. */
+void
+table_add_footnote (struct table *table, int x, int y,
+ const struct footnote *f)
+{
+ assert (f->style);
+
+ struct table_cell *cell = get_joined_cell (table, x, y);
+
+ cell->footnotes = pool_realloc (
+ table->container, cell->footnotes,
+ (cell->n_footnotes + 1) * sizeof *cell->footnotes);
+
+ cell->footnotes[cell->n_footnotes++] = f;
+}
+
+/* Overrides the style for column X, row Y in TABLE with STYLE.
+ Does not make a copy of STYLE, so it should either be allocated from
+ TABLE->container or have a lifetime that will outlive TABLE. */
+void
+table_add_style (struct table *table, int x, int y,
+ const struct table_area_style *style)
+{
+ get_joined_cell (table, x, y)->style = style;
+}
+
+/* Returns true if column C, row R has no contents, otherwise false. */
bool
-tab_cell_is_empty (const struct table *table, int c, int r)
+table_cell_is_empty (const struct table *table, int c, int r)
{
return table->cc[c + r * table_nc (table)] == NULL;
}
This function is obsolete. Please do not add new uses of it. Instead, use
a text_item (see output/text-item.h). */
void
-tab_output_text (int options UNUSED, const char *string)
+table_output_text (int options UNUSED, const char *string)
{
text_item_submit (text_item_create (TEXT_ITEM_LOG, string));
}
-/* Same as tab_output_text(), but FORMAT is passed through printf-like
+/* Same as table_output_text(), but FORMAT is passed through printf-like
formatting before output. */
void
-tab_output_text_format (int options, const char *format, ...)
+table_output_text_format (int options, const char *format, ...)
{
va_list args;
char *text;
text = xvasprintf (format, args);
va_end (args);
- tab_output_text (options, text);
+ table_output_text (options, text);
free (text);
}
unsigned short opt = t->ct[index];
const void *cc = t->cc[index];
- cell->options = opt;
- cell->n_footnotes = 0;
-
- int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
- const struct area_style *style = t->styles[style_idx];
- if (style)
- cell->style = style;
- else
- {
- static const struct area_style styles[3][3] = {
-#define S(H,V) [H][V] = { AREA_STYLE_INITIALIZER__, \
- .cell_style.halign = H, \
- .cell_style.valign = V }
- S(TABLE_HALIGN_LEFT, TABLE_VALIGN_TOP),
- S(TABLE_HALIGN_LEFT, TABLE_VALIGN_CENTER),
- S(TABLE_HALIGN_LEFT, TABLE_VALIGN_BOTTOM),
- S(TABLE_HALIGN_CENTER, TABLE_VALIGN_TOP),
- S(TABLE_HALIGN_CENTER, TABLE_VALIGN_CENTER),
- S(TABLE_HALIGN_CENTER, TABLE_VALIGN_BOTTOM),
- S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_TOP),
- S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_CENTER),
- S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_BOTTOM),
- };
-
- enum table_halign halign
- = ((opt & TAB_HALIGN) == TAB_LEFT ? TABLE_HALIGN_LEFT
- : (opt & TAB_HALIGN) == TAB_CENTER ? TABLE_HALIGN_CENTER
- : TABLE_HALIGN_RIGHT);
- enum table_valign valign
- = ((opt & TAB_VALIGN) == TAB_TOP ? TABLE_VALIGN_TOP
- : (opt & TAB_VALIGN) == TAB_MIDDLE ? TABLE_VALIGN_CENTER
- : TABLE_VALIGN_BOTTOM);
-
- cell->style = &styles[halign][valign];
- }
-
+ const struct table_area_style *style
+ = t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT];
if (opt & TAB_JOIN)
{
- const struct tab_joined_cell *jc = cc;
- cell->text = jc->text;
-
- cell->footnotes = jc->footnotes;
- cell->n_footnotes = jc->n_footnotes;
-
- cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
- cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
- cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
- cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
-
- if (jc->style)
- cell->style = jc->style;
+ const struct table_cell *jc = cc;
+ *cell = *jc;
+ if (!cell->style)
+ cell->style = style;
}
else
- {
- cell->d[TABLE_HORZ][0] = x;
- cell->d[TABLE_HORZ][1] = x + 1;
- cell->d[TABLE_VERT][0] = y;
- cell->d[TABLE_VERT][1] = y + 1;
- cell->text = CONST_CAST (char *, cc ? cc : "");
- }
+ *cell = (struct table_cell) {
+ .d = { [TABLE_HORZ] = { x, x + 1 },
+ [TABLE_VERT] = { y, y + 1 } },
+ .options = opt,
+ .text = CONST_CAST (char *, cc ? cc : ""),
+ .style = style,
+ };
+
+ assert (cell->style);
}
/* Returns one of the TAL_* enumeration constants (declared in output/table.h)