#include "libpspp/compiler.h"
#include "libpspp/pool.h"
#include "libpspp/str.h"
-#include "output/table-item.h"
+#include "output/output-item.h"
+#include "output/pivot-table.h"
#include "output/table.h"
-#include "output/text-item.h"
#include "gl/xalloc.h"
+/* This file uses TABLE_HORZ and TABLE_VERT enough to warrant abbreviating. */
+#define H TABLE_HORZ
+#define V TABLE_VERT
+
/* Increases TABLE's reference count, indicating that it has an additional
owner. An table that is shared among multiple owners must not be
modified. */
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)
{
free (style);
}
}
-
-void
-table_cell_format_footnote_markers (const struct table_cell *cell,
- struct string *s)
-{
- for (size_t i = 0; i < cell->n_footnotes; i++)
- {
- if (i)
- ds_put_byte (s, ',');
- ds_put_cstr (s, cell->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])
- footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
- footnotes, &allocated, &n);
- }
- }
-
- 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_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,
- 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
-/* Returns a table that contains a single cell, whose contents are the
- left-aligned TEXT. */
-struct table *
-table_from_string (const char *text)
-{
- struct table *t = table_create (1, 1, 0, 0, 0, 0);
- t->styles[0] = xmalloc (sizeof *t->styles[0]);
- *t->styles[0] = (struct area_style) {
- 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
const char *
table_halign_to_string (enum table_halign halign)
}
void
-area_style_copy (struct pool *container,
- 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 (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);
cell_color_dump (&f->fg[0]);
putchar ('/');
cell_color_dump (&f->bg[0]);
- if (!cell_color_equal (&f->fg[0], &f->fg[1])
- || !cell_color_equal (&f->bg[0], &f->bg[1]))
+ if (!cell_color_equal (f->fg[0], f->fg[1])
+ || !cell_color_equal (f->bg[0], f->bg[1]))
{
printf (" alt=");
cell_color_dump (&f->fg[1]);
fputs (" underline", stdout);
}
+bool
+font_style_equal (const struct font_style *a, const struct font_style *b)
+{
+ return (a->bold == b->bold
+ && a->italic == b->italic
+ && a->underline == b->underline
+ && a->markup == b->markup
+ && cell_color_equal (a->fg[0], b->fg[0])
+ && cell_color_equal (a->fg[1], b->fg[1])
+ && cell_color_equal (a->bg[0], b->bg[0])
+ && cell_color_equal (a->bg[1], b->bg[1])
+ && !strcmp (a->typeface ? a->typeface : "",
+ b->typeface ? b->typeface : "")
+ && a->size == b->size);
+}
+
void
cell_style_dump (const struct cell_style *c)
{
c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
}
\f
-
-static const bool debugging = true;
-
/* Creates and returns a new table with NC columns and NR rows and initially no
header rows or columns.
Sets the number of header rows on each side of TABLE to HL on the
- left, HR on the right, HT on the top, HB on the bottom. Header rows
+ left, HT on the top. Header rows
are repeated when a table is broken across multiple columns or
multiple pages.
The table's cells are initially empty. */
struct table *
-table_create (int nc, int nr, int hl, int hr, int ht, int hb)
-{
- struct table *t;
-
- t = pool_create_container (struct table, container);
- t->n[TABLE_HORZ] = nc;
- t->n[TABLE_VERT] = nr;
- t->h[TABLE_HORZ][0] = hl;
- t->h[TABLE_HORZ][1] = hr;
- t->h[TABLE_VERT][0] = ht;
- t->h[TABLE_VERT][1] = hb;
- t->ref_cnt = 1;
-
- t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
- t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
-
- t->rh = pool_nmalloc (t->container, nc, nr + 1);
- memset (t->rh, TABLE_STROKE_NONE, nc * (nr + 1));
-
- t->rv = pool_nmalloc (t->container, 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);
-
+table_create (int nc, int nr, int hl, int ht)
+{
+ struct pool *pool = pool_create ();
+ struct table *t = pool_alloc (pool, sizeof *t);
+ *t = (struct table) {
+ .container = pool,
+ .n = { [H] = nc, [V] = nr },
+ .h = { [H] = hl, [V] = ht },
+ .ref_cnt = 1,
+ .cc = pool_calloc (pool, nr * nc, sizeof *t->cc),
+ .cp = pool_calloc (pool, nr * nc, sizeof *t->cp),
+ .rh = pool_calloc (pool, nc, nr + 1),
+ .rv = pool_calloc (pool, nr, nc + 1),
+ };
return t;
}
\f
/* Rules. */
/* 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. */
+ from Y1 to Y2 inclusive in style STYLE. */
void
table_vline (struct table *t, int style, int x, int y1, int y2)
{
- if (debugging)
+ if (x < 0 || x > t->n[H] || y1 < 0 || y1 > y2 || y2 >= t->n[V])
{
- if (x < 0 || x > table_nc (t)
- || y1 < 0 || y1 >= table_nr (t)
- || y2 < 0 || y2 >= table_nr (t))
- {
- printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
- x, y1, y2, table_nc (t), table_nr (t));
- return;
- }
+ printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
+ x, y1, y2, t->n[H], t->n[V]);
+ abort ();
}
- assert (x >= 0);
- assert (x <= table_nc (t));
- assert (y1 >= 0);
- assert (y2 >= y1);
- assert (y2 <= table_nr (t));
-
- if (style != -1)
- {
- int y;
- for (y = y1; y <= y2; y++)
- t->rv[x + (table_nc (t) + 1) * y] = style;
- }
+ for (int y = y1; y <= y2; y++)
+ t->rv[x + (t->n[H] + 1) * y] = style;
}
/* Draws a horizontal line above cells at vertical position Y from X1
- to X2 inclusive in style STYLE, if style is not -1. */
+ to X2 inclusive in style STYLE. */
void
table_hline (struct table *t, int style, int x1, int x2, int y)
{
- if (debugging)
+ if (y < 0 || y > t->n[V] || x1 < 0 || x1 > x2 || x2 >= t->n[H])
{
- if (y < 0 || y > table_nr (t)
- || x1 < 0 || x1 >= table_nc (t)
- || x2 < 0 || x2 >= table_nc (t))
- {
- printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
- x1, x2, y, table_nc (t), table_nr (t));
- return;
- }
+ printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
+ x1, x2, y, t->n[H], t->n[V]);
+ abort ();
}
- assert (y >= 0);
- assert (y <= table_nr (t));
- assert (x2 >= x1);
- assert (x1 >= 0);
- assert (x2 < table_nc (t));
-
- if (style != -1)
- {
- int x;
- for (x = x1; x <= x2; x++)
- t->rh[x + table_nc (t) * y] = style;
- }
-}
-
-/* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
- lines of style F_H and vertical lines of style F_V. Fills the
- interior of the box with horizontal lines of style I_H and vertical
- lines of style I_V. Any of the line styles may be -1 to avoid
- drawing those lines. This is distinct from 0, which draws a null
- line. */
-void
-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)
- {
- if (x1 < 0 || x1 >= table_nc (t)
- || x2 < 0 || x2 >= table_nc (t)
- || y1 < 0 || y1 >= table_nr (t)
- || y2 < 0 || y2 >= table_nr (t))
- {
- printf ("bad box: (%d,%d)-(%d,%d) in table size (%d,%d)\n",
- x1, y1, x2, y2, table_nc (t), table_nr (t));
- NOT_REACHED ();
- }
- }
-
- assert (x2 >= x1);
- assert (y2 >= y1);
- assert (x1 >= 0);
- assert (y1 >= 0);
- assert (x2 < table_nc (t));
- assert (y2 < table_nr (t));
-
- if (f_h != -1)
- {
- int x;
- for (x = x1; x <= x2; x++)
- {
- t->rh[x + table_nc (t) * y1] = f_h;
- t->rh[x + table_nc (t) * (y2 + 1)] = f_h;
- }
- }
- if (f_v != -1)
- {
- int y;
- for (y = y1; y <= y2; y++)
- {
- t->rv[x1 + (table_nc (t) + 1) * y] = f_v;
- t->rv[(x2 + 1) + (table_nc (t) + 1) * y] = f_v;
- }
- }
-
- if (i_h != -1)
- {
- int y;
-
- for (y = y1 + 1; y <= y2; y++)
- {
- int x;
-
- for (x = x1; x <= x2; x++)
- t->rh[x + table_nc (t) * y] = i_h;
- }
- }
- if (i_v != -1)
- {
- int x;
-
- for (x = x1 + 1; x <= x2; x++)
- {
- int y;
-
- for (y = y1; y <= y2; y++)
- t->rv[x + (table_nc (t) + 1) * y] = i_v;
- }
- }
+ for (int x = x1; x <= x2; x++)
+ t->rh[x + t->n[H] * y] = style;
}
\f
/* Cells. */
-static void
-do_table_text (struct table *table, int c, int r, unsigned opt, char *text)
+/* Fill TABLE cells (X1,X2)-(Y1,Y2), inclusive, with VALUE and OPT. */
+void
+table_put (struct table *table, int x1, int y1, int x2, int y2,
+ unsigned int opt, const struct pivot_value *value)
{
- assert (c >= 0);
- assert (r >= 0);
- assert (c < table_nc (table));
- assert (r < table_nr (table));
+ assert (0 <= x1 && x1 <= x2 && x2 < table->n[H]);
+ assert (0 <= y1 && y1 <= y2 && y2 < table->n[V]);
+ const bool debugging = false;
if (debugging)
{
- if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table))
- {
- printf ("table_text(): bad cell (%d,%d) in table size (%d,%d)\n",
- c, r, table_nc (table), table_nr (table));
- return;
- }
+ printf ("put ");
+ if (x1 == x2)
+ printf ("%d", x1);
+ else
+ printf ("%d-%d", x1, x2);
+ printf (",");
+ if (y1 == y2)
+ printf ("%d", y1);
+ else
+ printf ("%d-%d", y1, y2);
+
+ char *value_s = value ? pivot_value_to_string (value, NULL) : NULL;
+ printf (": \"%s\"\n", value_s ? value_s : "");
+ free (value_s);
}
- table->cc[c + r * table_nc (table)] = text;
- table->ct[c + r * table_nc (table)] = opt;
-}
-
-/* Sets cell (C,R) in TABLE, with options OPT, to have text value
- TEXT. */
-void
-table_text (struct table *table, int c, int r, unsigned opt,
- const char *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
-table_text_format (struct table *table, int c, int r, unsigned opt,
- const char *format, ...)
-{
- va_list args;
-
- va_start (args, format);
- do_table_text (table, c, r, opt,
- pool_vasprintf (table->container, format, args));
- va_end (args);
-}
-
-static struct table_cell *
-add_joined_cell (struct table *table, int x1, int y1, int x2, int y2,
- unsigned opt)
-{
- assert (x1 >= 0);
- assert (y1 >= 0);
- assert (y2 >= y1);
- assert (x2 >= x1);
- assert (y2 < table_nr (table));
- assert (x2 < table_nc (table));
-
- if (debugging)
+ if (x1 == x2 && y1 == y2)
{
- if (x1 < 0 || x1 >= table_nc (table)
- || y1 < 0 || y1 >= table_nr (table)
- || x2 < x1 || x2 >= table_nc (table)
- || y2 < y1 || y2 >= table_nr (table))
- {
- 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;
- }
+ table->cc[x1 + y1 * table->n[H]] = CONST_CAST (struct pivot_value *, value);
+ table->cp[x1 + y1 * table->n[H]] = opt;
}
-
- table_box (table, -1, -1, TABLE_STROKE_NONE, TABLE_STROKE_NONE,
- x1, y1, x2, y2);
-
- struct table_cell *cell = pool_alloc (table->container, sizeof *cell);
- cell->d[TABLE_HORZ][0] = x1;
- cell->d[TABLE_VERT][0] = y1;
- cell->d[TABLE_HORZ][1] = ++x2;
- cell->d[TABLE_VERT][1] = ++y2;
- cell->options = opt;
- cell->footnotes = NULL;
- cell->n_footnotes = 0;
- cell->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);
- for (int y = y1; y < y2; y++)
+ else
{
- for (int x = x1; x < x2; x++)
+ struct table_cell *cell = pool_alloc (table->container, sizeof *cell);
+ *cell = (struct table_cell) {
+ .d = { [H] = { x1, x2 + 1 }, [V] = { y1, y2 + 1 } },
+ .options = opt,
+ .value = value,
+ };
+
+ for (int y = y1; y <= y2; y++)
{
- *cc++ = cell;
- *ct++ = opt | TAB_JOIN;
+ size_t ofs = x1 + y * table->n[H];
+ void **cc = &table->cc[ofs];
+ unsigned char *ct = &table->cp[ofs];
+ for (int x = x1; x <= x2; x++)
+ {
+ *cc++ = cell;
+ *ct++ = opt | TABLE_CELL_JOIN;
+ }
}
-
- cc += ofs;
- ct += ofs;
}
-
- return cell;
}
-/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
- options OPT to have text value TEXT. */
-void
-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_table_text (table, x1, y1, opt, s);
- else
- add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
-}
-
-struct footnote *
-table_create_footnote (struct table *table, size_t idx, const char *content,
- const char *marker, struct area_style *style)
-{
- assert (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
-table_add_footnote (struct table *table, int x, int y,
- const struct footnote *f)
+static void
+free_value (void *value_)
{
- assert (f->style);
-
- int index = x + y * table_nc (table);
- unsigned short opt = table->ct[index];
- struct table_cell *cell;
-
- if (opt & TAB_JOIN)
- cell = table->cc[index];
- else
- {
- char *text = table->cc[index];
-
- cell = add_joined_cell (table, x, y, x, y, table->ct[index]);
- cell->text = text ? text : pool_strdup (table->container, "");
- }
-
- cell->footnotes = pool_realloc (
- table->container, cell->footnotes,
- (cell->n_footnotes + 1) * sizeof *cell->footnotes);
-
- cell->footnotes[cell->n_footnotes++] = f;
+ struct pivot_value *value = value_;
+ pivot_value_destroy (value);
}
void
-table_add_style (struct table *table, int x, int y,
- const struct area_style *style)
+table_put_owned (struct table *table, int x1, int y1, int x2, int y2,
+ unsigned opt, struct pivot_value *value)
{
- int index = x + y * table_nc (table);
- unsigned short opt = table->ct[index];
- struct table_cell *cell;
-
- if (opt & TAB_JOIN)
- cell = table->cc[index];
- else
- {
- char *text = table->cc[index];
-
- cell = add_joined_cell (table, x, y, x, y, table->ct[index]);
- cell->text = text ? text : pool_strdup (table->container, "");
- }
-
- cell->style = style;
+ table_put (table, x1, y1, x2, y2, opt, value);
+ pool_register (table->container, free_value, value);
}
+/* Returns true if column C, row R has no contents, otherwise false. */
bool
table_cell_is_empty (const struct table *table, int c, int r)
{
- return table->cc[c + r * table_nc (table)] == NULL;
-}
-\f
-/* Editing. */
-
-/* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
- bits.
-
- This function is obsolete. Please do not add new uses of it. Instead, use
- a text_item (see output/text-item.h). */
-void
-table_output_text (int options UNUSED, const char *string)
-{
- text_item_submit (text_item_create (TEXT_ITEM_LOG, string));
-}
-
-/* Same as table_output_text(), but FORMAT is passed through printf-like
- formatting before output. */
-void
-table_output_text_format (int options, const char *format, ...)
-{
- va_list args;
- char *text;
-
- va_start (args, format);
- text = xvasprintf (format, args);
- va_end (args);
-
- table_output_text (options, text);
-
- free (text);
+ return table->cc[c + r * table->n[H]] == NULL;
}
\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)
{
assert (x >= 0 && x < t->n[TABLE_HORZ]);
assert (y >= 0 && y < t->n[TABLE_VERT]);
- int index = x + y * table_nc (t);
- unsigned short opt = t->ct[index];
+ int index = x + y * t->n[H];
+ unsigned char opt = t->cp[index];
const void *cc = t->cc[index];
- const struct area_style *style
- = t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT];
- if (opt & TAB_JOIN)
+ struct table_area_style *style
+ = t->styles[(opt & TABLE_CELL_STYLE_MASK) >> TABLE_CELL_STYLE_SHIFT];
+
+ static const struct pivot_value empty_value = {
+ .text = {
+ .type = PIVOT_VALUE_TEXT,
+ .local = (char *) "",
+ .c = (char *) "",
+ .id = (char *) "",
+ .user_provided = true,
+ },
+ };
+
+ if (opt & TABLE_CELL_JOIN)
{
const struct table_cell *jc = cc;
*cell = *jc;
- if (!cell->style)
- cell->style = style;
+ if (!cell->value)
+ cell->value = &empty_value;
+ if (!cell->font_style)
+ cell->font_style = &style->font_style;
+ if (!cell->cell_style)
+ cell->cell_style = &style->cell_style;
}
else
- *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);
+ {
+ const struct pivot_value *v = cc ? cc : &empty_value;
+ const struct pivot_value_ex *ex = pivot_value_ex (v);
+ *cell = (struct table_cell) {
+ .d = { [H] = { x, x + 1 }, [V] = { y, y + 1 } },
+ .options = opt,
+ .value = v,
+ .font_style = ex->font_style ? ex->font_style : &style->font_style,
+ .cell_style = ex->cell_style ? ex->cell_style : &style->cell_style,
+ };
+ }
+
+ assert (cell->font_style);
+ assert (cell->cell_style);
}
-/* Returns one of the TAL_* enumeration constants (declared in output/table.h)
- representing a rule running alongside one of the cells in TABLE.
+/* Returns one of the TABLE_STROKE_* enumeration constants (declared in
+ output/table.h) representing a rule running alongside one of the cells in
+ TABLE.
Suppose NC is the number of columns in TABLE and NR is the number of rows.
Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
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,
- struct cell_color *color)
+struct table_border_style
+table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
{
assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
- uint8_t raw = (axis == TABLE_VERT
- ? table->rh[x + table_nc (table) * y]
- : table->rv[x + (table_nc (table) + 1) * y]);
- struct cell_color *p = table->rule_colors[(raw & TAB_RULE_STYLE_MASK)
- >> TAB_RULE_STYLE_SHIFT];
- *color = p ? *p : (struct cell_color) CELL_COLOR_BLACK;
- return (raw & TAB_RULE_TYPE_MASK) >> TAB_RULE_TYPE_SHIFT;
+ size_t border_idx = (axis == TABLE_VERT
+ ? table->rh[x + table->n[H] * y]
+ : table->rv[x + (table->n[H] + 1) * y]);
+ return (border_idx < table->n_borders
+ ? table->borders[border_idx]
+ : (struct table_border_style) { TABLE_STROKE_NONE,
+ CELL_COLOR_BLACK });
}