-#include "table.h"
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <libpspp/alloc.h>
-#include <libpspp/compiler.h>
-#include <data/format.h>
-#include <libpspp/magic.h>
-#include <libpspp/misc.h>
-#include "minmax.h"
-#include "output.h"
-#include <libpspp/pool.h>
-#include "manager.h"
-#include <data/variable.h>
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-\f
-struct som_table_class tab_table_class;
-static char *command_name;
-
-/* Returns the font to use for a cell with the given OPTIONS. */
-static enum outp_font
-options_to_font (unsigned options)
-{
- return (options & TAB_FIX ? OUTP_FIXED
- : options & TAB_EMPH ? OUTP_EMPHASIS
- : OUTP_PROPORTIONAL);
-}
-
-/* Creates a table with NC columns and NR rows. */
-struct tab_table *
-tab_create (int nc, int nr, int reallocable UNUSED)
-{
- struct tab_table *t;
-
- t = pool_create_container (struct tab_table, container);
- t->col_style = TAB_COL_NONE;
- t->col_group = 0;
- ls_null (&t->title);
- t->flags = SOMF_NONE;
- t->nr = nr;
- t->nc = t->cf = nc;
- t->l = t->r = t->t = t->b = 0;
-
- t->cc = pool_nmalloc (t->container, nr * nc, sizeof *t->cc);
- t->ct = pool_malloc (t->container, nr * nc);
- memset (t->ct, TAB_EMPTY, nc * nr);
-
- t->rh = pool_nmalloc (t->container, nc, nr + 1);
- memset (t->rh, 0, nc * (nr + 1));
-
- t->hrh = pool_nmalloc (t->container, nr + 1, sizeof *t->hrh);
- memset (t->hrh, 0, sizeof *t->hrh * (nr + 1));
-
- t->rv = pool_nmalloc (t->container, nr, nc + 1);
- memset (t->rv, UCHAR_MAX, nr * (nc + 1));
-
- t->wrv = pool_nmalloc (t->container, nc + 1, sizeof *t->wrv);
- memset (t->wrv, 0, sizeof *t->wrv * (nc + 1));
-
- t->dim = NULL;
- t->w = t->h = NULL;
- t->col_ofs = t->row_ofs = 0;
-
- return t;
-}
-
-/* Destroys table T. */
-void
-tab_destroy (struct tab_table *t)
-{
- assert (t != NULL);
- pool_destroy (t->container);
-}
-
-/* Sets the width and height of a table, in columns and rows,
- respectively. Use only to reduce the size of a table, since it
- does not change the amount of allocated memory. */
-void
-tab_resize (struct tab_table *t, int nc, int nr)
-{
- assert (t != NULL);
- if (nc != -1)
- {
- assert (nc + t->col_ofs <= t->cf);
- t->nc = nc + t->col_ofs;
- }
- if (nr != -1)
- {
- assert (nr + t->row_ofs <= t->nr);
- t->nr = nr + t->row_ofs;
- }
-}
-
-/* Changes either or both dimensions of a table. Consider using the
- above routine instead if it won't waste a lot of space.
-
- Changing the number of columns in a table is particularly expensive
- in space and time. Avoid doing such. FIXME: In fact, transferring
- of rules isn't even implemented yet. */
-void
-tab_realloc (struct tab_table *t, int nc, int nr)
-{
- int ro, co;
-
- assert (t != NULL);
- ro = t->row_ofs;
- co = t->col_ofs;
- if (ro || co)
- tab_offset (t, 0, 0);
-
- if (nc == -1)
- nc = t->nc;
- if (nr == -1)
- nr = t->nr;
-
- assert (nc == t->nc);
-
- if (nc > t->cf)
- {
- int mr1 = min (nr, t->nr);
- int mc1 = min (nc, t->nc);
-
- struct fixed_string *new_cc;
- unsigned char *new_ct;
- int r;
-
- new_cc = pool_nmalloc (t->container, nr * nc, sizeof *new_cc);
- new_ct = pool_malloc (t->container, nr * nc);
- for (r = 0; r < mr1; r++)
- {
- memcpy (&new_cc[r * nc], &t->cc[r * t->nc], mc1 * sizeof *t->cc);
- memcpy (&new_ct[r * nc], &t->ct[r * t->nc], mc1);
- memset (&new_ct[r * nc + t->nc], TAB_EMPTY, nc - t->nc);
- }
- pool_free (t->container, t->cc);
- pool_free (t->container, t->ct);
- t->cc = new_cc;
- t->ct = new_ct;
- t->cf = nc;
- }
- else if (nr != t->nr)
- {
- t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
- t->ct = pool_realloc (t->container, t->ct, nr * nc);
-
- t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
- t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
-
- if (nr > t->nr)
- {
- memset (&t->rh[nc * (t->nr + 1)], TAL_0, (nr - t->nr) * nc);
- memset (&t->rv[(nc + 1) * t->nr], UCHAR_MAX,
- (nr - t->nr) * (nc + 1));
- }
- }
-
- memset (&t->ct[nc * t->nr], TAB_EMPTY, nc * (nr - t->nr));
-
- t->nr = nr;
- t->nc = nc;
-
- if (ro || co)
- tab_offset (t, co, ro);
-}
-
-/* Sets the number of header rows on each side of TABLE to L on the
- left, R on the right, T on the top, B on the bottom. Header rows
- are repeated when a table is broken across multiple columns or
- multiple pages. */
-void
-tab_headers (struct tab_table *table, int l, int r, int t, int b)
-{
- assert (table != NULL);
- assert (l < table->nc);
- assert (r < table->nc);
- assert (t < table->nr);
- assert (b < table->nr);
-
-
- table->l = l;
- table->r = r;
- table->t = t;
- table->b = b;
-}
-
-/* Set up table T so that, when it is an appropriate size, it will be
- displayed across the page in columns.
-
- STYLE is a TAB_COL_* constant. GROUP is the number of rows to take
- as a unit. */
-void
-tab_columns (struct tab_table *t, int style, int group)
-{
- assert (t != NULL);
- t->col_style = style;
- t->col_group = group;
-}
-\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. */
-void
-tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
-{
- assert (t != NULL);
-
-#if DEBUGGING
- if (x + t->col_ofs < 0 || x + t->col_ofs > t->nc
- || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= t->nr
- || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= t->nr)
- {
- printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in "
- "table size (%d,%d)\n"),
- x, t->col_ofs, x + t->col_ofs,
- y1, t->row_ofs, y1 + t->row_ofs,
- y2, t->row_ofs, y2 + t->row_ofs,
- t->nc, t->nr);
- return;
- }
-#endif
-
- x += t->col_ofs;
- y1 += t->row_ofs;
- y2 += t->row_ofs;
-
- assert (x > 0);
- assert (x < t->nc);
- assert (y1 >= 0);
- assert (y2 >= y1);
- assert (y2 <= t->nr);
-
- if (style != -1)
- {
- int y;
- for (y = y1; y <= y2; y++)
- t->rv[x + (t->cf + 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. */
-void
-tab_hline (struct tab_table * t, int style, int x1, int x2, int y)
-{
- assert (t != NULL);
-
- x1 += t->col_ofs;
- x2 += t->col_ofs;
- y += t->row_ofs;
-
- assert (y >= 0);
- assert (y < t->nr);
- assert (x2 >= x1 );
- assert (x1 >= 0 );
- assert (x2 < t->nc);
-
- if (style != -1)
- {
- int x;
- for (x = x1; x <= x2; x++)
- t->rh[x + t->cf * 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
-tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
- int x1, int y1, int x2, int y2)
-{
- assert (t != NULL);