-/* Set the title of table T to TITLE, which is formatted as if
- passed to printf(). */
-void
-tab_title (struct tab_table *t, const char *title, ...)
-{
- va_list args;
-
- assert (t != NULL && title != NULL);
- va_start (args, title);
- t->title = xvasprintf (title, args);
- va_end (args);
-}
-
-/* Set DIM_FUNC as the dimension function for table T. */
-void
-tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux)
-{
- assert (t != NULL && t->dim == NULL);
- t->dim = dim_func;
- t->dim_aux = aux;
-}
-
-/* Returns the natural width of column C in table T for driver D, that
- is, the smallest width necessary to display all its cells without
- wrapping. The width will be no larger than the page width minus
- left and right rule widths. */
-int
-tab_natural_width (struct tab_table *t, struct outp_driver *d, int c)
-{
- int width;
-
- assert (t != NULL && c >= 0 && c < t->nc);
- {
- int r;
-
- for (width = r = 0; r < t->nr; r++)
- {
- struct outp_text text;
- unsigned char opt = t->ct[c + r * t->cf];
- int w;
-
- if (opt & (TAB_JOIN | TAB_EMPTY))
- continue;
-
- text.string = t->cc[c + r * t->cf];
- text.justification = OUTP_LEFT;
- text.font = options_to_font (opt);
- text.h = text.v = INT_MAX;
-
- d->class->text_metrics (d, &text, &w, NULL);
- if (w > width)
- width = w;
- }
- }
-
- if (width == 0)
- {
- /* FIXME: This is an ugly kluge to compensate for the fact
- that we don't let joined cells contribute to column
- widths. */
- width = d->prop_em_width * 8;
- }
-
- {
- const int clamp = d->width - t->wrv[0] - t->wrv[t->nc];
-
- if (width > clamp)
- width = clamp;
- }
-
- return width;
-}
-
-/* Returns the natural height of row R in table T for driver D, that
- is, the minimum height necessary to display the information in the
- cell at the widths set for each column. */
-int
-tab_natural_height (struct tab_table *t, struct outp_driver *d, int r)
-{
- int height;
-
- assert (t != NULL && r >= 0 && r < t->nr);
-
- {
- int c;
-
- for (height = d->font_height, c = 0; c < t->nc; c++)
- {
- struct outp_text text;
- unsigned char opt = t->ct[c + r * t->cf];
- int h;
-
- if (opt & (TAB_JOIN | TAB_EMPTY))
- continue;
-
- text.string = t->cc[c + r * t->cf];
- text.justification = OUTP_LEFT;
- text.font = options_to_font (opt);
- text.h = t->w[c];
- text.v = INT_MAX;
- d->class->text_metrics (d, &text, NULL, &h);
-
- if (h > height)
- height = h;
- }
- }
-
- return height;
-}
-
-/* Callback function to set all columns and rows to their natural
- dimensions. Not really meant to be called directly. */
-void
-tab_natural_dimensions (struct tab_table *t, struct outp_driver *d,
- void *aux UNUSED)
-{
- int i;
-
- assert (t != NULL);
-
- for (i = 0; i < t->nc; i++)
- t->w[i] = tab_natural_width (t, d, i);
-
- for (i = 0; i < t->nr; i++)
- t->h[i] = tab_natural_height (t, d, i);
-}
-
-\f
-/* Cells. */
-
-/* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
- from V, displayed with format spec F. */
-void
-tab_value (struct tab_table *table, int c, int r, unsigned char opt,
- const union value *v, const struct dictionary *dict,
- const struct fmt_spec *f)
-{
- char *contents;
-
- assert (table != NULL && v != NULL && f != NULL);
-#if DEBUGGING
- if (c + table->col_ofs < 0 || r + table->row_ofs < 0
- || c + table->col_ofs >= table->nc
- || r + table->row_ofs >= table->nr)
- {
- printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
- "(%d,%d)\n",
- c, table->col_ofs, c + table->col_ofs,
- r, table->row_ofs, r + table->row_ofs,
- table->nc, table->nr);
- return;
- }
-#endif
-
- contents = data_out_pool (v, dict_get_encoding (dict), f, table->container);
-
- table->cc[c + r * table->cf] = ss_cstr (contents);
- table->ct[c + r * table->cf] = opt;
-}
-
-/* Sets cell (C,R) in TABLE, with options OPT, to have value VAL
- with NDEC decimal places. */
-void
-tab_fixed (struct tab_table *table, int c, int r, unsigned char opt,
- double val, int w, int d)
-{
- char *s, *cp;
-
- struct fmt_spec f;
- union value double_value;
-
- assert (table != NULL && w <= 40);
-
- assert (c >= 0);
- assert (c < table->nc);
- assert (r >= 0);
- assert (r < table->nr);
-
- f = fmt_for_output (FMT_F, w, d);
-
-#if DEBUGGING
- if (c + table->col_ofs < 0 || r + table->row_ofs < 0
- || c + table->col_ofs >= table->nc
- || r + table->row_ofs >= table->nr)
- {
- printf ("tab_fixed(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
- "(%d,%d)\n",
- c, table->col_ofs, c + table->col_ofs,
- r, table->row_ofs, r + table->row_ofs,
- table->nc, table->nr);
- return;
- }
-#endif
-
- double_value.f = val;
- s = data_out_pool (&double_value, LEGACY_NATIVE, &f, table->container);
-
- cp = s;
- while (isspace ((unsigned char) *cp) && cp < &s[w])
- cp++;
- f.w = w - (cp - s);
-
- table->cc[c + r * table->cf] = ss_buffer (cp, f.w);
- table->ct[c + r * table->cf] = opt;
-}
-
-/* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
- formatted by FMT.
- If FMT is null, then the default print format will be used.
-*/
-void
-tab_double (struct tab_table *table, int c, int r, unsigned char opt,
- double val, const struct fmt_spec *fmt)
-{
- struct substring ss;
- union value double_value ;
-
- assert (table != NULL);
-
- assert (c >= 0);
- assert (c < table->nc);
- assert (r >= 0);
- assert (r < table->nr);
-
- if ( fmt == NULL)
- fmt = settings_get_format ();
-
- fmt_check_output (fmt);
-
-#if DEBUGGING
- if (c + table->col_ofs < 0 || r + table->row_ofs < 0
- || c + table->col_ofs >= table->nc
- || r + table->row_ofs >= table->nr)
- {
- printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
- "(%d,%d)\n",
- c, table->col_ofs, c + table->col_ofs,
- r, table->row_ofs, r + table->row_ofs,
- table->nc, table->nr);
- return;
- }
-#endif
-
- double_value.f = val;
- ss = ss_cstr (data_out_pool (&double_value, LEGACY_NATIVE, fmt, table->container));
-
- ss_ltrim (&ss, ss_cstr (" "));
-
- table->cc[c + r * table->cf] = ss;
- table->ct[c + r * table->cf] = opt;
-}
-
-
-static void
-do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
-{
- assert (c >= 0);
- assert (r >= 0);
- assert (c < table->nc);
- assert (r < table->nr);
-
-#if DEBUGGING
- if (c + table->col_ofs < 0 || r + table->row_ofs < 0
- || c + table->col_ofs >= table->nc
- || r + table->row_ofs >= table->nr)
- {
- printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
- "(%d,%d)\n",
- c, table->col_ofs, c + table->col_ofs,
- r, table->row_ofs, r + table->row_ofs,
- table->nc, table->nr);
- return;
- }
-#endif
-
- table->cc[c + r * table->cf] = ss_cstr (text);
- table->ct[c + r * table->cf] = opt;
-}
-
-/* Sets cell (C,R) in TABLE, with options OPT, to have text value
- TEXT. */
-void
-tab_text (struct tab_table *table, int c, int r, unsigned opt,
- const char *text)