#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)
{
size_t n = 0;
struct table *t = item->table;
- for (int y = 0; y < table_nr (t); y++)
+ for (int y = 0; y < t->n[V]; y++)
{
struct table_cell cell;
- for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
+ for (int x = 0; x < t->n[H]; x = cell.d[TABLE_HORZ][1])
{
table_get_cell (t, x, y, &cell);
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);
{
if (debugging)
{
- if (x < 0 || x > table_nc (t)
- || y1 < 0 || y1 >= table_nr (t)
- || y2 < 0 || y2 >= table_nr (t))
+ if (x < 0 || x > t->n[H]
+ || y1 < 0 || y1 >= t->n[V]
+ || y2 < 0 || y2 >= t->n[V])
{
printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
- x, y1, y2, table_nc (t), table_nr (t));
+ x, y1, y2, t->n[H], t->n[V]);
return;
}
}
assert (x >= 0);
- assert (x <= table_nc (t));
+ assert (x <= t->n[H]);
assert (y1 >= 0);
assert (y2 >= y1);
- assert (y2 <= table_nr (t));
+ assert (y2 <= t->n[V]);
if (style != -1)
{
int y;
for (y = y1; y <= y2; y++)
- t->rv[x + (table_nc (t) + 1) * y] = style;
+ t->rv[x + (t->n[H] + 1) * y] = style;
}
}
{
if (debugging)
{
- if (y < 0 || y > table_nr (t)
- || x1 < 0 || x1 >= table_nc (t)
- || x2 < 0 || x2 >= table_nc (t))
+ if (y < 0 || y > t->n[V]
+ || x1 < 0 || x1 >= t->n[H]
+ || x2 < 0 || x2 >= t->n[H])
{
printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
- x1, x2, y, table_nc (t), table_nr (t));
+ x1, x2, y, t->n[H], t->n[V]);
return;
}
}
assert (y >= 0);
- assert (y <= table_nr (t));
+ assert (y <= t->n[V]);
assert (x2 >= x1);
assert (x1 >= 0);
- assert (x2 < table_nc (t));
+ assert (x2 < t->n[H]);
if (style != -1)
{
int x;
for (x = x1; x <= x2; x++)
- t->rh[x + table_nc (t) * y] = style;
+ t->rh[x + t->n[H] * y] = style;
}
}
{
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))
+ if (x1 < 0 || x1 >= t->n[H]
+ || x2 < 0 || x2 >= t->n[H]
+ || y1 < 0 || y1 >= t->n[V]
+ || y2 < 0 || y2 >= t->n[V])
{
printf ("bad box: (%d,%d)-(%d,%d) in table size (%d,%d)\n",
- x1, y1, x2, y2, table_nc (t), table_nr (t));
+ x1, y1, x2, y2, t->n[H], t->n[V]);
NOT_REACHED ();
}
}
assert (y2 >= y1);
assert (x1 >= 0);
assert (y1 >= 0);
- assert (x2 < table_nc (t));
- assert (y2 < table_nr (t));
+ assert (x2 < t->n[H]);
+ assert (y2 < t->n[V]);
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;
+ t->rh[x + t->n[H] * y1] = f_h;
+ t->rh[x + t->n[H] * (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;
+ t->rv[x1 + (t->n[H] + 1) * y] = f_v;
+ t->rv[(x2 + 1) + (t->n[H] + 1) * y] = f_v;
}
}
int x;
for (x = x1; x <= x2; x++)
- t->rh[x + table_nc (t) * y] = i_h;
+ t->rh[x + t->n[H] * y] = i_h;
}
}
if (i_v != -1)
int y;
for (y = y1; y <= y2; y++)
- t->rv[x + (table_nc (t) + 1) * y] = i_v;
+ t->rv[x + (t->n[H] + 1) * y] = i_v;
}
}
}
{
assert (c >= 0);
assert (r >= 0);
- assert (c < table_nc (table));
- assert (r < table_nr (table));
+ assert (c < table->n[H]);
+ assert (r < table->n[V]);
if (debugging)
{
- if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table))
+ if (c < 0 || r < 0 || c >= table->n[H] || r >= table->n[V])
{
printf ("table_text(): bad cell (%d,%d) in table size (%d,%d)\n",
- c, r, table_nc (table), table_nr (table));
+ c, r, table->n[H], table->n[V]);
return;
}
}
- table->cc[c + r * table_nc (table)] = text;
- table->ct[c + r * table_nc (table)] = opt;
+ table->cc[c + r * table->n[H]] = text;
+ table->ct[c + r * table->n[H]] = opt;
}
/* Sets cell (C,R) in TABLE, with options OPT, to have text value
assert (y1 >= 0);
assert (y2 >= y1);
assert (x2 >= x1);
- assert (y2 < table_nr (table));
- assert (x2 < table_nc (table));
+ assert (y2 < table->n[V]);
+ assert (x2 < table->n[H]);
if (debugging)
{
- 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))
+ if (x1 < 0 || x1 >= table->n[H]
+ || y1 < 0 || y1 >= table->n[V]
+ || x2 < x1 || x2 >= table->n[H]
+ || y2 < y1 || y2 >= table->n[V])
{
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));
+ x1, y1, x2, y2, table->n[H], table->n[V]);
return NULL;
}
}
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);
+ *cell = (struct table_cell) {
+ .d = { [TABLE_HORZ] = { x1, ++x2 },
+ [TABLE_VERT] = { y1, ++y2 } },
+ .options = opt,
+ };
+
+ void **cc = &table->cc[x1 + y1 * table->n[H]];
+ unsigned short *ct = &table->ct[x1 + y1 * table->n[H]];
+ const int ofs = table->n[H] - (x2 - x1);
for (int y = y1; y < y2; y++)
{
for (int x = x1; x < x2; x++)
add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
}
+static struct table_cell *
+get_joined_cell (struct table *table, int x, int y)
+{
+ int index = x + y * table->n[H];
+ 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, "");
+ }
+ return cell;
+}
+
+/* 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);
+
+ 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]);
+}
+
+/* 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.
+
+ 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 area_style *style)
+ const char *marker, struct table_area_style *style)
{
assert (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);
- 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, "");
- }
+ struct table_cell *cell = get_joined_cell (table, x, y);
cell->footnotes = pool_realloc (
table->container, 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 area_style *style)
+ const struct table_area_style *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->style = style;
+ get_joined_cell (table, x, y)->style = style;
}
+/* 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);
+ int index = x + y * t->n[H];
unsigned short opt = t->ct[index];
const void *cc = t->cc[index];
- const struct area_style *style
+ const struct table_area_style *style
= t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT];
if (opt & TAB_JOIN)
{
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]);
+ ? table->rh[x + table->n[H] * y]
+ : table->rv[x + (table->n[H] + 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;