output: Remove support for bottom and right side headers.
[pspp] / src / output / table.c
index bf22d2da5af8809de3f2b5d3e7b51e8d6aab70c0..3d07eb40d47563b27c059ee36d0473ce94d85c47 100644 (file)
@@ -201,8 +201,8 @@ font_style_dump (const struct font_style *f)
   cell_color_dump (&f->fg[0]);
   putchar ('/');
   cell_color_dump (&f->bg[0]);
-  if (!cell_color_equal (&f->fg[0], &f->fg[1])
-      || !cell_color_equal (&f->bg[0], &f->bg[1]))
+  if (!cell_color_equal (f->fg[0], f->fg[1])
+      || !cell_color_equal (f->bg[0], f->bg[1]))
     {
       printf (" alt=");
       cell_color_dump (&f->fg[1]);
@@ -224,10 +224,10 @@ font_style_equal (const struct font_style *a, const struct font_style *b)
           && a->italic == b->italic
           && a->underline == b->underline
           && a->markup == b->markup
-          && cell_color_equal (&a->fg[0], &b->fg[0])
-          && cell_color_equal (&a->fg[1], &b->fg[1])
-          && cell_color_equal (&a->bg[0], &b->bg[0])
-          && cell_color_equal (&a->bg[1], &b->bg[1])
+          && cell_color_equal (a->fg[0], b->fg[0])
+          && cell_color_equal (a->fg[1], b->fg[1])
+          && cell_color_equal (a->bg[0], b->bg[0])
+          && cell_color_equal (a->bg[1], b->bg[1])
           && !strcmp (a->typeface ? a->typeface : "",
                       b->typeface ? b->typeface : "")
           && a->size == b->size);
@@ -245,184 +245,65 @@ cell_style_dump (const struct cell_style *c)
           c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
 }
 \f
-
-static const bool debugging = true;
-
 /* Creates and returns a new table with NC columns and NR rows and initially no
    header rows or columns.
 
    Sets the number of header rows on each side of TABLE to HL on the
-   left, HR on the right, HT on the top, HB on the bottom.  Header rows
+   left, HT on the top.  Header rows
    are repeated when a table is broken across multiple columns or
    multiple pages.
 
    The table's cells are initially empty. */
 struct table *
-table_create (int nc, int nr, int hl, int hr, int ht, int hb)
+table_create (int nc, int nr, int hl, int ht)
 {
-  struct table *t;
-
-  t = pool_create_container (struct table, container);
-  t->n[TABLE_HORZ] = nc;
-  t->n[TABLE_VERT] = nr;
-  t->h[TABLE_HORZ][0] = hl;
-  t->h[TABLE_HORZ][1] = hr;
-  t->h[TABLE_VERT][0] = ht;
-  t->h[TABLE_VERT][1] = hb;
-  t->ref_cnt = 1;
-
-  t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
-  t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
-
-  t->rh = pool_nmalloc (t->container, nc, nr + 1);
-  memset (t->rh, TABLE_STROKE_NONE, nc * (nr + 1));
-
-  t->rv = pool_nmalloc (t->container, nr, nc + 1);
-  memset (t->rv, TABLE_STROKE_NONE, nr * (nc + 1));
-
-  memset (t->styles, 0, sizeof t->styles);
-  memset (t->rule_colors, 0, sizeof t->rule_colors);
-
+  struct pool *pool = pool_create ();
+  struct table *t = pool_alloc (pool, sizeof *t);
+  *t = (struct table) {
+    .container = pool,
+    .n = { [H] = nc, [V] = nr },
+    .h = { [H] = hl, [V] = ht },
+    .ref_cnt = 1,
+    .cc = pool_calloc (pool, nr * nc, sizeof *t->cc),
+    .cp = pool_calloc (pool, nr * nc, sizeof *t->cp),
+    .rh = pool_calloc (pool, nc, nr + 1),
+    .rv = pool_calloc (pool, nr, nc + 1),
+  };
   return t;
 }
 \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. */
+   from Y1 to Y2 inclusive in style STYLE. */
 void
 table_vline (struct table *t, int style, int x, int y1, int y2)
 {
-  if (debugging)
+  if (x < 0 || x > t->n[H] || y1 < 0 || y1 > y2 || y2 >= t->n[V])
     {
-      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, t->n[H], t->n[V]);
-          return;
-        }
+      printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
+              x, y1, y2, t->n[H], t->n[V]);
+      abort ();
     }
 
-  assert (x >= 0);
-  assert (x <= t->n[H]);
-  assert (y1 >= 0);
-  assert (y2 >= y1);
-  assert (y2 <= t->n[V]);
-
-  if (style != -1)
-    {
-      int y;
-      for (y = y1; y <= y2; y++)
-        t->rv[x + (t->n[H] + 1) * y] = style;
-    }
+  for (int y = y1; y <= y2; y++)
+    t->rv[x + (t->n[H] + 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. */
+   to X2 inclusive in style STYLE. */
 void
 table_hline (struct table *t, int style, int x1, int x2, int y)
 {
-  if (debugging)
-    {
-      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, t->n[H], t->n[V]);
-          return;
-        }
-    }
-
-  assert (y >= 0);
-  assert (y <= t->n[V]);
-  assert (x2 >= x1);
-  assert (x1 >= 0);
-  assert (x2 < t->n[H]);
-
-  if (style != -1)
-    {
-      int x;
-      for (x = x1; x <= x2; x++)
-        t->rh[x + t->n[H] * 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
-table_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
-           int x1, int y1, int x2, int y2)
-{
-  if (debugging)
+  if (y < 0 || y > t->n[V] || x1 < 0 || x1 > x2 || x2 >= t->n[H])
     {
-      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, t->n[H], t->n[V]);
-          NOT_REACHED ();
-        }
+      printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
+              x1, x2, y, t->n[H], t->n[V]);
+      abort ();
     }
 
-  assert (x2 >= x1);
-  assert (y2 >= y1);
-  assert (x1 >= 0);
-  assert (y1 >= 0);
-  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 + 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 + (t->n[H] + 1) * y] = f_v;
-          t->rv[(x2 + 1) + (t->n[H] + 1) * y] = f_v;
-        }
-    }
-
-  if (i_h != -1)
-    {
-      int y;
-
-      for (y = y1 + 1; y <= y2; y++)
-        {
-          int x;
-
-          for (x = x1; x <= x2; x++)
-            t->rh[x + t->n[H] * y] = i_h;
-        }
-    }
-  if (i_v != -1)
-    {
-      int x;
-
-      for (x = x1 + 1; x <= x2; x++)
-        {
-          int y;
-
-          for (y = y1; y <= y2; y++)
-            t->rv[x + (t->n[H] + 1) * y] = i_v;
-        }
-    }
+  for (int x = x1; x <= x2; x++)
+    t->rh[x + t->n[H] * y] = style;
 }
 \f
 /* Cells. */
@@ -430,21 +311,37 @@ table_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
 /* Fill TABLE cells (X1,X2)-(Y1,Y2), inclusive, with VALUE and OPT. */
 void
 table_put (struct table *table, int x1, int y1, int x2, int y2,
-           unsigned opt, const struct pivot_value *value)
+           unsigned int opt, const struct pivot_value *value)
 {
   assert (0 <= x1 && x1 <= x2 && x2 < table->n[H]);
   assert (0 <= y1 && y1 <= y2 && y2 < table->n[V]);
 
+  const bool debugging = false;
+  if (debugging)
+    {
+      printf ("put ");
+      if (x1 == x2)
+        printf ("%d", x1);
+      else
+        printf ("%d-%d", x1, x2);
+      printf (",");
+      if (y1 == y2)
+        printf ("%d", y1);
+      else
+        printf ("%d-%d", y1, y2);
+
+      char *value_s = value ? pivot_value_to_string (value, NULL) : NULL;
+      printf (": \"%s\"\n", value_s ? value_s : "");
+      free (value_s);
+    }
+
   if (x1 == x2 && y1 == y2)
     {
       table->cc[x1 + y1 * table->n[H]] = CONST_CAST (struct pivot_value *, value);
-      table->ct[x1 + y1 * table->n[H]] = opt;
+      table->cp[x1 + y1 * table->n[H]] = opt;
     }
   else
     {
-      table_box (table, -1, -1, TABLE_STROKE_NONE, TABLE_STROKE_NONE,
-                 x1, y1, x2, y2);
-
       struct table_cell *cell = pool_alloc (table->container, sizeof *cell);
       *cell = (struct table_cell) {
         .d = { [H] = { x1, x2 + 1 }, [V] = { y1, y2 + 1 } },
@@ -456,11 +353,11 @@ table_put (struct table *table, int x1, int y1, int x2, int y2,
         {
           size_t ofs = x1 + y * table->n[H];
           void **cc = &table->cc[ofs];
-          unsigned short *ct = &table->ct[ofs];
+          unsigned char *ct = &table->cp[ofs];
           for (int x = x1; x <= x2; x++)
             {
               *cc++ = cell;
-              *ct++ = opt | TAB_JOIN;
+              *ct++ = opt | TABLE_CELL_JOIN;
             }
         }
     }
@@ -497,11 +394,11 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
   assert (y >= 0 && y < t->n[TABLE_VERT]);
 
   int index = x + y * t->n[H];
-  unsigned short opt = t->ct[index];
+  unsigned char opt = t->cp[index];
   const void *cc = t->cc[index];
 
   struct table_area_style *style
-    = t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT];
+    = t->styles[(opt & TABLE_CELL_STYLE_MASK) >> TABLE_CELL_STYLE_SHIFT];
 
   static const struct pivot_value empty_value = {
     .text = {
@@ -513,7 +410,7 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
     },
   };
 
-  if (opt & TAB_JOIN)
+  if (opt & TABLE_CELL_JOIN)
     {
       const struct table_cell *jc = cc;
       *cell = *jc;
@@ -527,12 +424,13 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
   else
     {
       const struct pivot_value *v = cc ? cc : &empty_value;
+      const struct pivot_value_ex *ex = pivot_value_ex (v);
       *cell = (struct table_cell) {
         .d = { [H] = { x, x + 1 }, [V] = { y, y + 1 } },
         .options = opt,
         .value = v,
-        .font_style = v->font_style ? v->font_style : &style->font_style,
-        .cell_style = v->cell_style ? v->cell_style : &style->cell_style,
+        .font_style = ex->font_style ? ex->font_style : &style->font_style,
+        .cell_style = ex->cell_style ? ex->cell_style : &style->cell_style,
       };
     }
 
@@ -540,8 +438,9 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
   assert (cell->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.
+/* Returns one of the TABLE_STROKE_* 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) =
@@ -577,18 +476,17 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
    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)
+struct table_border_style
+table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
 {
   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->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;
-  return (raw & TAB_RULE_TYPE_MASK) >> TAB_RULE_TYPE_SHIFT;
+  size_t border_idx = (axis == TABLE_VERT
+                      ? table->rh[x + table->n[H] * y]
+                      : table->rv[x + (table->n[H] + 1) * y]);
+  return (border_idx < table->n_borders
+          ? table->borders[border_idx]
+          : (struct table_border_style) { TABLE_STROKE_NONE,
+                                          CELL_COLOR_BLACK });
 }