+/* 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);
+}
+\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. */
+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];
+ const void *cc = t->cc[index];
+
+ cell->options = opt;
+ cell->n_footnotes = 0;
+
+ int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
+ cell->style = t->styles[style_idx];
+
+ if (opt & TAB_JOIN)
+ {
+ const struct table_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;
+ }
+ 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 : "");
+ }
+
+ assert (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.
+
+ 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) =
+ (0,0), the return value is the rule that runs vertically on the left side of
+ cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
+ cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
+ cell (NC-1,0).
+
+ The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
+ within a 7x7 table. The '|' characters at the intersection of the X labels
+ and Y labels show the rule whose style would be returned by calling
+ table_get_rule with those X and Y values:
+
+ 0 1 2 3 4 5 6 7
+ +--+--+--+--+--+--+--+
+ 0 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 1 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 2 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 3 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 4 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 5 | | | | | | | |
+ +--+--+--+--+--+--+--+
+ 6 | | | | | | | |
+ +--+--+--+--+--+--+--+
+
+ Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
+ (X,Y) = (0,0), the return value is the rule that runs horizontally above
+ 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)
+{
+ 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;
+}