output: Add footnote support.
[pspp] / src / output / tab.c
index 2e788e5a37f9b38faa17f3b17286848bab49747b..8ef077e38fae99f8a8b2d8c54b4c3b22f541e296 100644 (file)
@@ -56,9 +56,12 @@ struct tab_joined_cell
     union
       {
         char *text;
-        struct table *subtable;
+        struct table_item *subtable;
       }
     u;
+
+    size_t n_footnotes;
+    char **footnotes;
   };
 
 static const struct table_class tab_table_class;
@@ -544,6 +547,8 @@ add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
   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->n_footnotes = 0;
+  j->footnotes = NULL;
 
   {
     void **cc = &table->cc[x1 + y1 * table->cf];
@@ -597,17 +602,43 @@ tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2,
   add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
 }
 
+void
+tab_footnote (struct tab_table *table, int x, int y, const char *format, ...)
+{
+  int index = x + y * table->cf;
+  unsigned char opt = table->ct[index];
+  struct tab_joined_cell *j;
+  va_list args;
+
+  if (opt & TAB_JOIN)
+    j = table->cc[index];
+  else
+    {
+      char *text = table->cc[index];
+
+      j = add_joined_cell (table, x, y, x, y, table->ct[index]);
+      j->u.text = text ? text : xstrdup ("");
+    }
+
+  j->footnotes = xrealloc (j->footnotes,
+                           (j->n_footnotes + 1) * sizeof *j->footnotes);
+
+  va_start (args, format);
+  j->footnotes[j->n_footnotes++] = pool_vasprintf (table->container, format, args);
+  va_end (args);
+}
+
 static void
 subtable_unref (void *subtable)
 {
-  table_unref (subtable);
+  table_item_unref (subtable);
 }
 
 /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE
    with options OPT. */
 void
 tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
-              unsigned opt, struct table *subtable)
+              unsigned opt, struct table_item *subtable)
 {
   add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable
     = subtable;
@@ -622,10 +653,11 @@ tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
    as a nested table but its contents become part of TABLE. */
 void
 tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2,
-                   unsigned opt, struct table *subtable)
+                   unsigned opt, struct table_item *subtable)
 {
-  assert (table_nc (subtable) == 1);
-  assert (table_nr (subtable) == 1);
+  const struct table *t UNUSED = table_item_get_table (subtable);
+  assert (table_nc (t) == 1);
+  assert (table_nr (t) == 1);
   tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
 }
 
@@ -751,6 +783,7 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
 
   cell->inline_contents.options = opt;
   cell->inline_contents.table = NULL;
+  cell->inline_contents.n_footnotes = 0;
   cell->destructor = NULL;
 
   if (opt & TAB_JOIN)
@@ -761,7 +794,7 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
           assert (opt & TAB_SUBTABLE);
 
           /* This overwrites all of the members of CELL. */
-          table_get_cell (jc->u.subtable, 0, 0, cell);
+          table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell);
         }
       else
         {
@@ -776,6 +809,9 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
             cell->inline_contents.text = jc->u.text;
         }
 
+      cell->inline_contents.footnotes = jc->footnotes;
+      cell->inline_contents.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];