output: Introduce pivot tables.
[pspp] / src / output / tab.c
index ec00c432226cf4f993c8c5d36367f7b5432160cb..f6f965022e14daaa6fc8d91ab34f8c540cbb906b 100644 (file)
@@ -55,12 +55,7 @@ static const bool debugging = true;
 struct tab_joined_cell
 {
   int d[TABLE_N_AXES][2];       /* Table region, same as struct table_cell. */
-  union
-  {
-    char *text;
-    struct table_item *subtable;
-  }
-    u;
+  char *text;
 
   size_t n_footnotes;
   const struct footnote **footnotes;
@@ -70,14 +65,6 @@ struct tab_joined_cell
 
 static const struct table_class tab_table_class;
 
-struct fmt_spec ugly[n_RC] = {
-  {FMT_F, 8, 0},                /* INTEGER */
-  {FMT_F, 8, 3},                /* WEIGHT (ignored) */
-  {FMT_F, 8, 3},                /* PVALUE */
-  {FMT_F, 8, 3}                 /* OTHER (ignored) */
-};
-
-
 /* Creates and returns a new table with NC columns and NR rows and initially no
    header rows or columns.  The table's cells are initially empty. */
 struct tab_table *
@@ -90,8 +77,6 @@ tab_create (int nc, int nr)
   table_set_nc (&t->table, nc);
   table_set_nr (&t->table, nr);
 
-  t->title = NULL;
-  t->caption = NULL;
   t->cf = nc;
   t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
   t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
@@ -102,124 +87,13 @@ tab_create (int nc, int nr)
   t->rv = pool_nmalloc (t->container, nr, nc + 1);
   memset (t->rv, TAL_0, nr * (nc + 1));
 
-  memset (t->fmtmap, 0, sizeof (*t->fmtmap) * n_RC);
-  t->fmtmap[RC_PVALUE] = ugly[RC_PVALUE];
-  t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER];
-  t->fmtmap[RC_OTHER] = *settings_get_format ();
-
   memset (t->styles, 0, sizeof t->styles);
   memset (t->rule_colors, 0, sizeof t->rule_colors);
 
-  t->col_ofs = t->row_ofs = 0;
-
   return t;
 }
 
 
-void
-tab_set_format (struct tab_table *t, enum result_class rc,
-                const struct fmt_spec *fmt)
-{
-  t->fmtmap[rc] = *fmt;
-}
-
-
-/* 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.
-
-   This function is obsolete.  Please do not add new uses of it.  (Instead, use
-   table_select() or one of its helper functions.) */
-void
-tab_resize (struct tab_table *t, int nc, int nr)
-{
-  if (nc != -1)
-    {
-      assert (nc + t->col_ofs <= t->cf);
-      table_set_nc (&t->table, nc + t->col_ofs);
-    }
-  if (nr != -1)
-    {
-      assert (nr + t->row_ofs <= tab_nr (t));
-      table_set_nr (&t->table, nr + t->row_ofs);
-    }
-}
-
-/* Changes either or both dimensions of a table and reallocates memory as
-   necessary.
-
-   This function is obsolete.  Please do not add new uses of it.  (Instead, use
-   table_paste() or one of its helper functions to paste multiple tables
-   together into a larger one.) */
-void
-tab_realloc (struct tab_table *t, int nc, int nr)
-{
-  int ro, co;
-
-  ro = t->row_ofs;
-  co = t->col_ofs;
-  if (ro || co)
-    tab_offset (t, 0, 0);
-
-  if (nc == -1)
-    nc = tab_nc (t);
-  if (nr == -1)
-    nr = tab_nr (t);
-
-  assert (nc == tab_nc (t));
-
-  if (nc > t->cf)
-    {
-      int mr1 = MIN (nr, tab_nr (t));
-      int mc1 = MIN (nc, tab_nc (t));
-
-      void **new_cc;
-      unsigned short *new_ct;
-      int r;
-
-      new_cc = pool_calloc (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 * tab_nc (t)],
-                  mc1 * sizeof *t->cc);
-          memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)],
-                  mc1 * sizeof *t->ct);
-          memset (&new_ct[r * nc + tab_nc (t)], 0, nc - tab_nc (t));
-        }
-      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 != tab_nr (t))
-    {
-      t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
-      t->ct = pool_nrealloc (t->container, t->ct, nr * nc, sizeof *t->ct);
-
-      t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
-      t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
-
-      if (nr > tab_nr (t))
-        {
-          memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0,
-                  (nr - tab_nr (t)) * nc);
-          memset (&t->rv[(nc + 1) * tab_nr (t)], TAL_0,
-                  (nr - tab_nr (t)) * (nc + 1));
-        }
-    }
-
-  memset (&t->ct[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->ct);
-  memset (&t->cc[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->cc);
-
-  table_set_nr (&t->table, nr);
-  table_set_nc (&t->table, 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
@@ -242,23 +116,16 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
 {
   if (debugging)
     {
-      if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t)
-          || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
-          || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
+      if (x < 0 || x > tab_nc (t)
+          || y1 < 0 || y1 >= tab_nr (t)
+          || y2 < 0 || y2 >= tab_nr (t))
         {
-          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, tab_nc (t), tab_nr (t));
+          printf (_("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n"),
+                  x, y1, y2, tab_nc (t), tab_nr (t));
           return;
         }
     }
 
-  x += t->col_ofs;
-  y1 += t->row_ofs;
-  y2 += t->row_ofs;
-
   assert (x >= 0);
   assert (x <= tab_nc (t));
   assert (y1 >= 0);
@@ -280,23 +147,16 @@ tab_hline (struct tab_table *t, int style, int x1, int x2, int y)
 {
   if (debugging)
     {
-      if (y + t->row_ofs < 0 || y + t->row_ofs > tab_nr (t)
-          || x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
-          || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t))
+      if (y < 0 || y > tab_nr (t)
+          || x1 < 0 || x1 >= tab_nc (t)
+          || x2 < 0 || x2 >= tab_nc (t))
         {
-          printf (_("bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in "
-                    "table size (%d,%d)\n"),
-                  x1, t->col_ofs, x1 + t->col_ofs,
-                  x2, t->col_ofs, x2 + t->col_ofs,
-                  y, t->row_ofs, y + t->row_ofs, tab_nc (t), tab_nr (t));
+          printf (_("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n"),
+                  x1, x2, y, tab_nc (t), tab_nr (t));
           return;
         }
     }
 
-  x1 += t->col_ofs;
-  x2 += t->col_ofs;
-  y += t->row_ofs;
-
   assert (y >= 0);
   assert (y <= tab_nr (t));
   assert (x2 >= x1);
@@ -323,26 +183,17 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
 {
   if (debugging)
     {
-      if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
-          || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t)
-          || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
-          || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
+      if (x1 < 0 || x1 >= tab_nc (t)
+          || x2 < 0 || x2 >= tab_nc (t)
+          || y1 < 0 || y1 >= tab_nr (t)
+          || y2 < 0 || y2 >= tab_nr (t))
         {
-          printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) "
-                    "in table size (%d,%d)\n"),
-                  x1, t->col_ofs, x1 + t->col_ofs,
-                  y1, t->row_ofs, y1 + t->row_ofs,
-                  x2, t->col_ofs, x2 + t->col_ofs,
-                  y2, t->row_ofs, y2 + t->row_ofs, tab_nc (t), tab_nr (t));
+          printf (_("bad box: (%d,%d)-(%d,%d) in table size (%d,%d)\n"),
+                  x1, y1, x2, y2, tab_nc (t), tab_nr (t));
           NOT_REACHED ();
         }
     }
 
-  x1 += t->col_ofs;
-  x2 += t->col_ofs;
-  y1 += t->row_ofs;
-  y2 += t->row_ofs;
-
   assert (x2 >= x1);
   assert (y2 >= y1);
   assert (x1 >= 0);
@@ -397,81 +248,6 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
 \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 short opt,
-           const union value *v, const struct variable *var,
-           const struct fmt_spec *f)
-{
-  char *contents;
-
-  if (debugging)
-    {
-      if (c + table->col_ofs < 0 || r + table->row_ofs < 0
-          || c + table->col_ofs >= tab_nc (table)
-          || r + table->row_ofs >= tab_nr (table))
-        {
-          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,
-                  tab_nc (table), tab_nr (table));
-          return;
-        }
-    }
-
-  contents = data_out_stretchy (v, var_get_encoding (var),
-                                f != NULL ? f : var_get_print_format (var),
-                                table->container);
-
-  table->cc[c + r * table->cf] = contents;
-  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 short opt,
-            double val, const struct fmt_spec *fmt, enum result_class rc)
-{
-  union value double_value;
-  char *s;
-
-  assert (c >= 0);
-  assert (c < tab_nc (table));
-  assert (r >= 0);
-  assert (r < tab_nr (table));
-
-  if (fmt == NULL)
-    fmt = &table->fmtmap[rc];
-
-  fmt_check_output (fmt);
-
-  if (debugging)
-    {
-      if (c + table->col_ofs < 0 || r + table->row_ofs < 0
-          || c + table->col_ofs >= tab_nc (table)
-          || r + table->row_ofs >= tab_nr (table))
-        {
-          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,
-                  tab_nc (table), tab_nr (table));
-          return;
-        }
-    }
-
-  double_value.f = val;
-  s = data_out_stretchy (&double_value, C_ENCODING, fmt, table->container);
-  table->cc[c + r * table->cf] = s + strspn (s, " ");
-  table->ct[c + r * table->cf] = opt;
-}
-
-
 static void
 do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
 {
@@ -482,15 +258,10 @@ do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
 
   if (debugging)
     {
-      if (c + table->col_ofs < 0 || r + table->row_ofs < 0
-          || c + table->col_ofs >= tab_nc (table)
-          || r + table->row_ofs >= tab_nr (table))
+      if (c < 0 || r < 0 || c >= tab_nc (table) || r >= tab_nr (table))
         {
-          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,
-                  tab_nc (table), tab_nr (table));
+          printf ("tab_text(): bad cell (%d,%d) in table size (%d,%d)\n",
+                  c, r, tab_nc (table), tab_nr (table));
           return;
         }
     }
@@ -528,27 +299,23 @@ add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
 {
   struct tab_joined_cell *j;
 
-  assert (x1 + table->col_ofs >= 0);
-  assert (y1 + table->row_ofs >= 0);
+  assert (x1 >= 0);
+  assert (y1 >= 0);
   assert (y2 >= y1);
   assert (x2 >= x1);
-  assert (y2 + table->row_ofs < tab_nr (table));
-  assert (x2 + table->col_ofs < tab_nc (table));
+  assert (y2 < tab_nr (table));
+  assert (x2 < tab_nc (table));
 
   if (debugging)
     {
-      if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table)
-          || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table)
-          || x2 < x1 || x2 + table->col_ofs >= tab_nc (table)
-          || y2 < y1 || y2 + table->row_ofs >= tab_nr (table))
+      if (x1 < 0 || x1 >= tab_nc (table)
+          || y1 < 0 || y1 >= tab_nr (table)
+          || x2 < x1 || x2 >= tab_nc (table)
+          || y2 < y1 || y2 >= tab_nr (table))
         {
           printf ("tab_joint_text(): bad cell "
-                  "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n",
-                  x1, table->col_ofs, x1 + table->col_ofs,
-                  y1, table->row_ofs, y1 + table->row_ofs,
-                  x2, table->col_ofs, x2 + table->col_ofs,
-                  y2, table->row_ofs, y2 + table->row_ofs,
-                  tab_nc (table), tab_nr (table));
+                  "(%d,%d)-(%d,%d) in table size (%d,%d)\n",
+                  x1, y1, x2, y2, tab_nc (table), tab_nr (table));
           return NULL;
         }
     }
@@ -556,10 +323,10 @@ add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
   tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
 
   j = pool_alloc (table->container, sizeof *j);
-  j->d[TABLE_HORZ][0] = x1 + table->col_ofs;
-  j->d[TABLE_VERT][0] = y1 + table->row_ofs;
-  j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs;
-  j->d[TABLE_VERT][1] = ++y2 + table->row_ofs;
+  j->d[TABLE_HORZ][0] = x1;
+  j->d[TABLE_VERT][0] = y1;
+  j->d[TABLE_HORZ][1] = ++x2;
+  j->d[TABLE_VERT][1] = ++y2;
   j->n_footnotes = 0;
   j->footnotes = NULL;
   j->style = NULL;
@@ -599,24 +366,7 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
   if (x1 == x2 && y1 == y2)
     do_tab_text (table, x1, y1, opt, s);
   else
-    add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
-}
-
-/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
-   with options OPT to have text value FORMAT, which is formatted
-   as if passed to printf. */
-void
-tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2,
-                       int y2, unsigned opt, const char *format, ...)
-{
-  va_list args;
-  char *s;
-
-  va_start (args, format);
-  s = pool_vasprintf (table->container, format, args);
-  va_end (args);
-
-  add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
+    add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
 }
 
 struct footnote *
@@ -646,7 +396,7 @@ tab_add_footnote (struct tab_table *table, int x, int y,
       char *text = table->cc[index];
 
       j = add_joined_cell (table, x, y, x, y, table->ct[index]);
-      j->u.text = text ? text : xstrdup ("");
+      j->text = text ? text : xstrdup ("");
     }
 
   j->footnotes = pool_realloc (table->container, j->footnotes,
@@ -670,7 +420,7 @@ tab_add_style (struct tab_table *table, int x, int y,
       char *text = table->cc[index];
 
       j = add_joined_cell (table, x, y, x, y, table->ct[index]);
-      j->u.text = text ? text : xstrdup ("");
+      j->text = text ? text : xstrdup ("");
     }
 
   j->style = style;
@@ -682,85 +432,8 @@ tab_cell_is_empty (const struct tab_table *table, int c, int r)
   return table->cc[c + r * table->cf] == NULL;
 }
 \f
-/* Miscellaneous. */
-
-/* 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;
-
-  free (t->title);
-  va_start (args, title);
-  t->title = xvasprintf (title, args);
-  va_end (args);
-}
-
-/* Set the caption of table T to CAPTION, which is formatted as if
-   passed to printf(). */
-void
-tab_caption (struct tab_table *t, const char *caption, ...)
-{
-  va_list args;
-
-  free (t->caption);
-  va_start (args, caption);
-  t->caption = xvasprintf (caption, args);
-  va_end (args);
-}
-
-/* Easy, type-safe way to submit a tab table to som. */
-void
-tab_submit (struct tab_table *t)
-{
-  table_item_submit (table_item_create (&t->table, t->title, t->caption));
-}
-\f
 /* Editing. */
 
-/* Set table row and column offsets for all functions that affect
-   cells or rules. */
-void
-tab_offset (struct tab_table *t, int col, int row)
-{
-  int diff = 0;
-
-  if (debugging)
-    {
-      if (row < -1 || row > tab_nr (t))
-        {
-          printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
-          NOT_REACHED ();
-        }
-      if (col < -1 || col > tab_nc (t))
-        {
-          printf ("tab_offset(): col=%d in %d-column table\n", col,
-                  tab_nc (t));
-          NOT_REACHED ();
-        }
-    }
-
-  if (row != -1)
-    diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
-  if (col != -1)
-    diff += (col - t->col_ofs), t->col_ofs = col;
-
-  t->cc += diff;
-  t->ct += diff;
-}
-
-/* Increment the row offset by one. If the table is too small,
-   increase its size. */
-void
-tab_next_row (struct tab_table *t)
-{
-  t->cc += t->cf;
-  t->ct += t->cf;
-  if (++t->row_ofs >= tab_nr (t))
-    tab_realloc (t, -1, tab_nr (t) * 4 / 3);
-}
-\f
 /* Writes STRING to the output.  OPTIONS may be any valid combination of TAB_*
    bits.
 
@@ -769,8 +442,7 @@ tab_next_row (struct tab_table *t)
 void
 tab_output_text (int options, const char *string)
 {
-  enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_TITLE
-                              : options & TAB_FIX ? TEXT_ITEM_LOG
+  enum text_item_type type = (options & TAB_FIX ? TEXT_ITEM_LOG
                               : TEXT_ITEM_PARAGRAPH);
   text_item_submit (text_item_create (type, string));
 }
@@ -798,10 +470,6 @@ static void
 tab_destroy (struct table *table)
 {
   struct tab_table *t = tab_cast (table);
-  free (t->title);
-  t->title = NULL;
-  free (t->caption);
-  t->caption = NULL;
   pool_destroy (t->container);
 }
 
@@ -854,7 +522,7 @@ tab_get_cell (const struct table *table, int x, int y,
   if (opt & TAB_JOIN)
     {
       const struct tab_joined_cell *jc = cc;
-      cell->text = jc->u.text;
+      cell->text = jc->text;
 
       cell->footnotes = jc->footnotes;
       cell->n_footnotes = jc->n_footnotes;