it works again
authorBen Pfaff <blp@cs.stanford.edu>
Wed, 30 Dec 2020 03:03:36 +0000 (19:03 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Thu, 31 Dec 2020 03:58:11 +0000 (19:58 -0800)
14 files changed:
src/output/ascii.c
src/output/cairo-fsm.c
src/output/csv.c
src/output/html.c
src/output/odt.c
src/output/pivot-output.c
src/output/pivot-output.h
src/output/render.c
src/output/table-item.h
src/output/table-provider.h
src/output/table.c
src/output/table.h
src/output/tex.c
src/output/text-item.c

index 9a08a893317d656b588696e800ed5d179e001661..0a3f501bb78330926c4e2e2aced4ad869d86e285 100644 (file)
@@ -913,7 +913,13 @@ add_markers (const char *text, const struct table_cell *cell)
   for (size_t i = 0; i < cell->n_subscripts; i++)
     ds_put_format (&s, "%c%s", i ? ',' : '_', cell->subscripts[i]);
   for (size_t i = 0; i < cell->n_footnotes; i++)
-    ds_put_format (&s, "[%s]", cell->footnotes[i]->marker);
+    {
+      ds_put_byte (&s, '[');
+      pivot_value_format (cell->footnotes[i]->marker,
+                          SETTINGS_VALUE_SHOW_DEFAULT,
+                          SETTINGS_VALUE_SHOW_DEFAULT, &s);
+      ds_put_byte (&s, ']');
+    }
   return ds_steal_cstr (&s);
 }
 
index 5e6befc3d761093dc15e09b533135d31e6d18e14..698141e080fbb4550885cf73131c8d607c48dcc6 100644 (file)
@@ -765,7 +765,10 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
         {
           if (i)
             ds_put_byte (&tmp, ',');
-          ds_put_cstr (&tmp, cell->footnotes[i]->marker);
+
+          pivot_value_format (cell->footnotes[i]->marker,
+                              SETTINGS_VALUE_SHOW_DEFAULT,
+                              SETTINGS_VALUE_SHOW_DEFAULT, &tmp);
         }
 
       /* Allow footnote markers to occupy the right margin.  That way, numbers
index ab79e32a76c19bcdaa50c86ca5b379cf7d1711de..e6edfc6bfce74401a209a50a3c8b2d96bbecb5cb 100644 (file)
@@ -32,6 +32,7 @@
 #include "output/message-item.h"
 #include "output/page-eject-item.h"
 #include "output/pivot-output.h"
+#include "output/pivot-table.h"
 #include "output/table-item.h"
 #include "output/table-provider.h"
 
@@ -175,13 +176,6 @@ csv_output_lines (struct csv_driver *csv, const char *text_)
     }
 }
 
-static void
-csv_format_footnotes (struct footnote **f, size_t n, struct string *s)
-{
-  for (size_t i = 0; i < n; i++)
-    ds_put_format (s, "[%s]", f[i]->marker);
-}
-
 static void
 csv_output_table_cell (struct csv_driver *csv, const struct table_cell *cell,
                        const char *leader)
@@ -212,7 +206,14 @@ csv_output_table_cell (struct csv_driver *csv, const struct table_cell *cell,
         for (size_t i = 0; i < cell->n_subscripts; i++)
           ds_put_format (&s, "%c%s",
                          i ? ',' : '_', cell->subscripts[i]);
-      csv_format_footnotes (cell->footnotes, cell->n_footnotes, &s);
+      for (size_t i = 0; i < cell->n_footnotes; i++)
+        {
+          ds_put_byte (&s, '[');
+          pivot_value_format (cell->footnotes[i]->marker,
+                              SETTINGS_VALUE_SHOW_DEFAULT,
+                              SETTINGS_VALUE_SHOW_DEFAULT, &s);
+          ds_put_byte (&s, ']');
+        }
       csv_output_field (csv, ds_cstr (&s));
       ds_destroy (&s);
 
index f8213952e1294b0bfe9a359b991c78847c6d706a..2dcdf52f0663fb18b47401b8ecbd3763928be28f 100644 (file)
@@ -481,26 +481,6 @@ put_border (const struct table *table, const struct table_cell *cell,
     }
 }
 
-static void
-html_put_footnote_markers (struct html_driver *html,
-                           struct footnote **footnotes,
-                           size_t n_footnotes)
-{
-  if (n_footnotes > 0)
-    {
-      fputs ("<sup>", html->file);
-      for (size_t i = 0; i < n_footnotes; i++)
-        {
-          const struct footnote *f = footnotes[i];
-
-          if (i > 0)
-            putc (',', html->file);
-          escape_string (html->file, f->marker, " ", "<br>");
-        }
-      fputs ("</sup>", html->file);
-    }
-}
-
 static void
 html_put_table_cell_text (struct html_driver *html,
                           const struct table_cell *cell)
@@ -526,7 +506,22 @@ html_put_table_cell_text (struct html_driver *html,
         }
       fputs ("</sub>", html->file);
     }
-  html_put_footnote_markers (html, cell->footnotes, cell->n_footnotes);
+  if (cell->n_footnotes > 0)
+    {
+      fputs ("<sup>", html->file);
+      for (size_t i = 0; i < cell->n_footnotes; i++)
+        {
+          if (i > 0)
+            putc (',', html->file);
+
+          char *marker = pivot_value_to_string (cell->footnotes[i]->marker,
+                                                SETTINGS_VALUE_SHOW_DEFAULT,
+                                                SETTINGS_VALUE_SHOW_DEFAULT);
+          escape_string (html->file, marker, " ", "<br>");
+          free (marker);
+        }
+      fputs ("</sup>", html->file);
+    }
 }
 
 static void
@@ -704,17 +699,18 @@ html_output_table_layer (struct html_driver *html, const struct pivot_table *pt,
           fputs ("</tr>\n", html->file);
         }
 
-      for (size_t y = 0; y < footnotes->n[V]; y++)
-        {
-          fputs ("<tr>\n", html->file);
+      if (footnotes)
+        for (size_t y = 0; y < footnotes->n[V]; y++)
+          {
+            fputs ("<tr>\n", html->file);
 
-          struct table_cell cell;
-          table_get_cell (footnotes, 0, y, &cell);
-          cell.d[H][1] = body->n[H];
-          html_put_table_cell (html, &cell, "td", NULL);
+            struct table_cell cell;
+            table_get_cell (footnotes, 0, y, &cell);
+            cell.d[H][1] = body->n[H];
+            html_put_table_cell (html, &cell, "td", NULL);
 
-          fputs ("</tr>\n", html->file);
-        }
+            fputs ("</tr>\n", html->file);
+          }
       fputs ("</tfoot>\n", html->file);
     }
 
index 4fdccd1424530a01d4257313914240744514b169..8d890e87e0311e23e3b9d6bde1f1b7abd48059ba 100644 (file)
@@ -149,6 +149,7 @@ write_style_data (struct odt_driver *odt)
     xmlTextWriterEndElement (w); /* style:style */
   }
 
+
   {
     xmlTextWriterStartElement (w, _xml ("style:style"));
     xmlTextWriterWriteAttribute (w, _xml ("style:name"),
@@ -196,6 +197,18 @@ write_style_data (struct odt_driver *odt)
     xmlTextWriterEndElement (w); /* style:style */
   }
 
+  {
+    xmlTextWriterStartElement (w, _xml ("style:style"));
+    xmlTextWriterWriteAttribute (w, _xml ("style:name"), _xml ("superscript"));
+    xmlTextWriterWriteAttribute (w, _xml ("style:family"), _xml ("text"));
+
+    xmlTextWriterStartElement (w, _xml ("style:text-properties"));
+    xmlTextWriterWriteAttribute (w, _xml ("style:text-position"),
+                                 _xml ("super 58%"));
+    xmlTextWriterEndElement (w); /* style:text-properties */
+
+    xmlTextWriterEndElement (w); /* style:style */
+  }
 
   xmlTextWriterEndElement (w); /* office:styles */
   xmlTextWriterEndElement (w); /* office:document-styles */
@@ -404,28 +417,21 @@ write_xml_with_line_breaks (struct odt_driver *odt, const char *line_)
 }
 
 static void
-write_footnote (struct odt_driver *odt, const struct footnote *f)
+write_footnotes (struct odt_driver *odt, struct pivot_footnote **footnotes,
+                size_t n_footnotes)
 {
-  xmlTextWriterStartElement (odt->content_wtr, _xml("text:note"));
-  xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:note-class"),
-                               _xml("footnote"));
-
-  xmlTextWriterStartElement (odt->content_wtr, _xml("text:note-citation"));
-  if (strlen (f->marker) > 1)
-    xmlTextWriterWriteFormatAttribute (odt->content_wtr, _xml("text:label"),
-                                       "(%s)", f->marker);
-  else
-    xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:label"),
-                                 _xml(f->marker));
-  xmlTextWriterEndElement (odt->content_wtr);
-
-  xmlTextWriterStartElement (odt->content_wtr, _xml("text:note-body"));
-  xmlTextWriterStartElement (odt->content_wtr, _xml("text:p"));
-  write_xml_with_line_breaks (odt, f->content);
-  xmlTextWriterEndElement (odt->content_wtr);
-  xmlTextWriterEndElement (odt->content_wtr);
-
-  xmlTextWriterEndElement (odt->content_wtr);
+  for (size_t i = 0; i < n_footnotes; i++)
+    {
+      xmlTextWriterStartElement (odt->content_wtr, _xml("text:span"));
+      xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"),
+                                   _xml("superscript"));
+      char *s = pivot_value_to_string (footnotes[i]->marker,
+                                       SETTINGS_VALUE_SHOW_DEFAULT,
+                                       SETTINGS_VALUE_SHOW_DEFAULT);
+      write_xml_with_line_breaks (odt, s);
+      free (s);
+      xmlTextWriterEndElement (odt->content_wtr);
+    }
 }
 
 static void
@@ -439,8 +445,7 @@ write_table_item_cell (struct odt_driver *odt,
   xmlTextWriterWriteFormatAttribute (odt->content_wtr,
                                      _xml("text:outline-level"), "%d", 2);
   xmlTextWriterWriteString (odt->content_wtr, _xml (cell->text));
-  for (size_t i = 0; i < cell->n_footnotes; i++)
-    write_footnote (odt, cell->footnotes[i]);
+  write_footnotes (odt, cell->footnotes, cell->n_footnotes);
   xmlTextWriterEndElement (odt->content_wtr);
 }
 
@@ -535,8 +540,7 @@ write_table_layer (struct odt_driver *odt, const struct pivot_table *pt,
               else
                 write_xml_with_line_breaks (odt, cell.text);
 
-              for (int i = 0; i < cell.n_footnotes; i++)
-                write_footnote (odt, cell.footnotes[i]);
+              write_footnotes (odt, cell.footnotes, cell.n_footnotes);
 
               xmlTextWriterEndElement (odt->content_wtr); /* text:p */
               xmlTextWriterEndElement (odt->content_wtr); /* table:table-cell */
index 2d88610eae72db4ebe6b86cee146a21afa5d8dba..8c1aacc0a7ce8867871989516e0d01706f45db4c 100644 (file)
@@ -46,7 +46,7 @@ pivot_output_next_layer (const struct pivot_table *pt, size_t *indexes,
   else if (!indexes)
     {
       size_t size = layer_axis->n_dimensions * sizeof *pt->current_layer;
-      return xmemdup (pt->current_layer, MAX (size, 1));
+      return size ? xmemdup (pt->current_layer, size) : xmalloc (1);
     }
   else
     {
@@ -135,7 +135,7 @@ format_cell (const struct pivot_value *value, int style_idx,
 static void
 fill_cell (struct table *t, int x1, int y1, int x2, int y2,
            const struct table_area_style *style, int style_idx,
-           const struct pivot_value *value, struct footnote **footnotes,
+           const struct pivot_value *value,
            enum settings_value_show show_values,
            enum settings_value_show show_variables,
            bool rotate_label)
@@ -155,12 +155,9 @@ fill_cell (struct table *t, int x1, int y1, int x2, int y2,
                                                     value->font_style,
                                                     rotate_label));
 
-      for (size_t i = 0; i < value->n_footnotes; i++)
-        {
-          struct footnote *f = footnotes[value->footnotes[i]->idx];
-          if (f)
-            table_add_footnote (t, x1, y1, f);
-        }
+      table_add_footnotes (t, x1, y1,
+                           (struct pivot_footnote **) value->footnotes,
+                           value->n_footnotes);
 
       if (value->n_subscripts)
         table_add_subscripts (t, x1, y1,
@@ -200,7 +197,6 @@ compose_headings (struct table *t,
                   const struct table_area_style *label_style,
                   int label_style_idx,
                   const struct table_area_style *corner_style,
-                  struct footnote **footnotes,
                   enum settings_value_show show_values,
                   enum settings_value_show show_variables,
                   bool rotate_inner_labels, bool rotate_outer_labels)
@@ -255,7 +251,7 @@ compose_headings (struct table *t,
                   bool rotate = ((rotate_inner_labels && is_inner_row)
                                  || (rotate_outer_labels && is_outer_row));
                   fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
-                             label_style, label_style_idx, c->name, footnotes,
+                             label_style, label_style_idx, c->name,
                              show_values, show_variables, rotate);
 
                   if (pivot_category_is_leaf (c) && x2 + 1 <= n_columns)
@@ -293,7 +289,7 @@ compose_headings (struct table *t,
           bb[b][0] = bottom_row - d->label_depth + 1;
           bb[b][1] = bottom_row;
           fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
-                     corner_style, PIVOT_AREA_CORNER, d->root->name, footnotes,
+                     corner_style, PIVOT_AREA_CORNER, d->root->name,
                      show_values, show_variables, false);
         }
 
@@ -311,80 +307,76 @@ create_aux_table (const struct pivot_table *pt, int nc, int nr,
 {
   struct table *table = table_create (nr, nc, 0, 0, 0, 0);
   table->styles[style_idx] = table_area_style_override (
-      t->container, &pt->look->areas[style_idx], NULL, NULL, false);
+      table->container, &pt->look->areas[style_idx], NULL, NULL, false);
   return table;
 }
 
 
-static struct footnote **
-add_footnotes (struct footnote **refs, size_t n_refs,
-               struct footnote **footnotes, size_t *allocated, size_t *n)
+static void
+add_references (const struct pivot_table *pt, const struct table *table,
+                bool *refs, size_t *n_refs)
 {
-  for (size_t i = 0; i < n_refs; i++)
-    {
-      struct footnote *f = refs[i];
-      if (f->idx >= *allocated)
-        {
-          size_t new_allocated = (f->idx + 1) * 2;
-          footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
-          while (*allocated < new_allocated)
-            footnotes[(*allocated)++] = NULL;
-        }
-      footnotes[f->idx] = f;
-      if (f->idx >= *n)
-        *n = f->idx + 1;
-    }
-  return footnotes;
+  if (!table)
+    return;
+
+  for (int y = 0; y < table->n[V]; y++)
+    for (int x = 0; x < table->n[H]; )
+      {
+        struct table_cell cell;
+        table_get_cell (table, x, y, &cell);
+
+        if (x == cell.d[H][0] && y == cell.d[V][0])
+          {
+            for (size_t i = 0; i < cell.n_footnotes; i++)
+              {
+                const struct pivot_footnote *f = cell.footnotes[i];
+                assert (f->idx < pt->n_footnotes);
+                assert (f == pt->footnotes[f->idx]);
+
+                if (!refs[f->idx])
+                  {
+                    refs[f->idx] = true;
+                    (*n_refs)++;
+                  }
+              }
+          }
+
+        x = cell.d[TABLE_HORZ][1];
+      }
 }
 
-size_t
-table_collect_footnotes (const struct table *
-                         struct footnote ***footnotesp)
+static struct pivot_footnote **
+collect_footnotes (const struct pivot_table *pt,
+                   const struct table *title,
+                   const struct table *layers,
+                   const struct table *body,
+                   const struct table *caption,
+                   size_t *n_footnotesp)
 {
-  struct footnote **footnotes = NULL;
-  size_t allocated = 0;
-  size_t n = 0;
-
-  struct table *t = item->table;
-  for (int y = 0; y < t->n[V]; y++)
+  if (!pt->n_footnotes)
     {
-      struct table_cell cell;
-      for (int x = 0; x < t->n[H]; x = cell.d[TABLE_HORZ][1])
-        {
-          table_get_cell (t, x, y, &cell);
-
-          if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
-            footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
-                                       footnotes, &allocated, &n);
-        }
+      *n_footnotesp = 0;
+      return NULL;
     }
 
-  const struct table_cell *title = table_item_get_title (item);
-  if (title)
-    footnotes = add_footnotes (title->footnotes, title->n_footnotes,
-                               footnotes, &allocated, &n);
-
-  const struct table_item_layers *layers = table_item_get_layers (item);
-  if (layers)
-    {
-      for (size_t i = 0; i < layers->n_layers; i++)
-        footnotes = add_footnotes (layers->layers[i].footnotes,
-                                   layers->layers[i].n_footnotes,
-                                   footnotes, &allocated, &n);
-    }
+  bool *refs = xzalloc (pt->n_footnotes);
+  size_t n_refs = 0;
+  add_references (pt, title, refs, &n_refs);
+  add_references (pt, layers, refs, &n_refs);
+  add_references (pt, body, refs, &n_refs);
+  add_references (pt, caption, refs, &n_refs);
 
-  const struct table_cell *caption = table_item_get_caption (item);
-  if (caption)
-    footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
-                               footnotes, &allocated, &n);
+  struct pivot_footnote **footnotes = xnmalloc (n_refs, sizeof *footnotes);
+  size_t n_footnotes = 0;
+  for (size_t i = 0; i < pt->n_footnotes; i++)
+    if (refs[i])
+      footnotes[n_footnotes++] = pt->footnotes[i];
+  assert (n_footnotes == n_refs);
 
-  size_t n_nonnull = 0;
-  for (size_t i = 0; i < n; i++)
-    if (footnotes[i])
-      footnotes[n_nonnull++] = footnotes[i];
+  free (refs);
 
-  *footnotesp = footnotes;
-  return n_nonnull;
+  *n_footnotesp = n_footnotes;
+  return footnotes;
 }
 
 void
@@ -395,7 +387,7 @@ pivot_output (const struct pivot_table *pt,
               struct table **bodyp,
               struct table **captionp,
               struct table **footnotesp,
-              struct footnote ***fp, size_t *nfp)
+              struct pivot_footnote ***fp, size_t *nfp)
 {
   const size_t *pindexes[PIVOT_N_AXES]
     = { [PIVOT_AXIS_LAYER] = layer_indexes };
@@ -425,29 +417,6 @@ pivot_output (const struct pivot_table *pt,
       *body->rule_colors[i] = in->color;
     }
 
-  struct footnote **footnotes = XCALLOC (pt->n_footnotes,  struct footnote *);
-  for (size_t i = 0; i < pt->n_footnotes; i++)
-    {
-      const struct pivot_footnote *pf = pt->footnotes[i];
-
-      if (!pf->show)
-        continue;
-
-      char *content = pivot_value_to_string (pf->content, pt->show_values,
-                                             pt->show_variables);
-      char *marker = pivot_value_to_string (pf->marker, pt->show_values,
-                                            pt->show_variables);
-      footnotes[i] = table_create_footnote (
-        body, i, content, marker,
-        table_area_style_override (body->container,
-                                   &pt->look->areas[PIVOT_AREA_FOOTER],
-                                   pf->content->cell_style,
-                                   pf->content->font_style,
-                                   false));
-      free (marker);
-      free (content);
-    }
-
   compose_headings (body,
                     &pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW],
                     pt->look->borders,
@@ -458,7 +427,7 @@ pivot_output (const struct pivot_table *pt,
                     column_enumeration, data[H],
                     &pt->look->areas[PIVOT_AREA_COLUMN_LABELS],
                     PIVOT_AREA_COLUMN_LABELS,
-                    &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
+                    &pt->look->areas[PIVOT_AREA_CORNER],
                     pt->show_values, pt->show_variables,
                     pt->rotate_outer_row_labels, false);
 
@@ -472,7 +441,7 @@ pivot_output (const struct pivot_table *pt,
                     row_enumeration, data[V],
                     &pt->look->areas[PIVOT_AREA_ROW_LABELS],
                     PIVOT_AREA_ROW_LABELS,
-                    &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
+                    &pt->look->areas[PIVOT_AREA_CORNER],
                     pt->show_values, pt->show_variables,
                     false, pt->rotate_inner_column_labels);
 
@@ -492,8 +461,7 @@ pivot_output (const struct pivot_table *pt,
                      x + stub[H], y + stub[V],
                      x + stub[H], y + stub[V],
                      &pt->look->areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA,
-                     value, footnotes,
-                     pt->show_values, pt->show_variables, false);
+                     value, pt->show_values, pt->show_variables, false);
 
           x++;
         }
@@ -506,8 +474,7 @@ pivot_output (const struct pivot_table *pt,
       && stub[H] && stub[V])
     fill_cell (body, 0, 0, stub[H] - 1, stub[V] - 1,
                &pt->look->areas[PIVOT_AREA_CORNER], PIVOT_AREA_CORNER,
-               pt->corner_text, footnotes,
-               pt->show_values, pt->show_variables, false);
+               pt->corner_text, pt->show_values, pt->show_variables, false);
 
   if (body->n[H] && body->n[V])
     {
@@ -542,10 +509,9 @@ pivot_output (const struct pivot_table *pt,
   if (pt->title && titlep)
     {
       title = create_aux_table (pt, 1, 1, PIVOT_AREA_TITLE);
-      fill_cell (title, 0, 0, 1, 1,
+      fill_cell (title, 0, 0, 0, 0,
                  &pt->look->areas[PIVOT_AREA_TITLE], PIVOT_AREA_TITLE,
-                 pt->title, footnotes,
-                 pt->show_values, pt->show_variables, false);
+                 pt->title, pt->show_values, pt->show_variables, false);
     }
   else
     title = NULL;
@@ -575,10 +541,9 @@ pivot_output (const struct pivot_table *pt,
           /* XXX This puts in the layer values, but not the variable names. */
           const struct pivot_value *name
             = d->data_leaves[layer_indexes[i]]->name;
-          fill_cell (layers, 0, y, 1, y + 1,
+          fill_cell (layers, 0, y, 0, y,
                      &pt->look->areas[PIVOT_AREA_LAYERS], PIVOT_AREA_LAYERS,
-                     name, footnotes,
-                     pt->show_values, pt->show_variables, false);
+                     name, pt->show_values, pt->show_variables, false);
           y++;
         }
     }
@@ -590,17 +555,57 @@ pivot_output (const struct pivot_table *pt,
   if (pt->caption && captionp)
     {
       caption = create_aux_table (pt, 1, 1, PIVOT_AREA_CAPTION);
-      fill_cell (caption, 0, 0, 1, 1,
+      fill_cell (caption, 0, 0, 0, 0,
                  &pt->look->areas[PIVOT_AREA_CAPTION], PIVOT_AREA_CAPTION,
-                 pt->caption, footnotes,
-                 pt->show_values, pt->show_variables, false);
+                 pt->caption, pt->show_values, pt->show_variables, false);
     }
   else
     caption = NULL;
 
-  free (footnotes);
+  /* Footnotes. */
+  size_t nf;
+  struct pivot_footnote **f = collect_footnotes (pt, title, layers, body,
+                                                 caption, &nf);
+  struct table *footnotes;
+  if (nf && footnotesp)
+    {
+      footnotes = create_aux_table (pt, 1, nf, PIVOT_AREA_FOOTER);
 
+      for (size_t i = 0; i < nf; i++)
+        {
+          struct string s = DS_EMPTY_INITIALIZER;
+          pivot_value_format (f[i]->marker, pt->show_values,
+                              pt->show_variables, &s);
+          ds_put_cstr (&s, ". ");
+          pivot_value_format (f[i]->content, pt->show_values,
+                              pt->show_variables, &s);
+
+          struct pivot_value *value = pivot_value_new_user_text_nocopy (
+            ds_steal_cstr (&s));
+
+          fill_cell (layers, 0, i, 0, i,
+                     &pt->look->areas[PIVOT_AREA_FOOTER], PIVOT_AREA_FOOTER,
+                     value, pt->show_values, pt->show_variables, false);
+        }
+    }
+  else
+    footnotes = NULL;
+
+  *titlep = title;
+  if (layersp)
+    *layersp = layers;
   *bodyp = body;
+  if (captionp)
+    *captionp = caption;
+  if (footnotesp)
+    *footnotesp = footnotes;
+  if (fp)
+    {
+      *fp = f;
+      *nfp = nf;
+    }
+  else
+    free (f);
 }
 
 void
index 38d595a8e051aaeb0e4f4b55ee300f56b35a32ed..17118dfb21a8d0786575be74dc15547ac4e1e905 100644 (file)
@@ -20,7 +20,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 
-struct footnote;
+struct pivot_footnote;
 struct pivot_table;
 struct table;
 
@@ -37,6 +37,6 @@ void pivot_output (const struct pivot_table *,
                    struct table **bodyp,
                    struct table **captionp,
                    struct table **footnotesp,
-                   struct footnote ***fp, size_t *nfp);
+                   struct pivot_footnote ***fp, size_t *nfp);
 
 #endif /* output/pivot-output.h */
index 00ef896105189045c129ff33215649a8a377576a..b4c22b516306b761b459d986693b09c237b32c83 100644 (file)
@@ -1495,13 +1495,12 @@ struct render_pager
     struct render_break y_break;
   };
 
-static const struct render_page *
+static void
 render_pager_add_table (struct render_pager *p, struct table *table,
                         int min_width)
 {
-  struct render_page *page = render_page_create (p->params, table, min_width);
-  p->pages[p->n_pages++] = page;
-  return page;
+  if (table)
+    p->pages[p->n_pages++] = render_page_create (p->params, table, min_width);
 }
 
 static void
index 96394c4182eb7addf4ab21ed1e0ed30864d433e1..be0987659684ef68fdeba2f23e9d80d9e0506074 100644 (file)
@@ -98,5 +98,5 @@ table_item_is_shared (const struct table_item *instance)
 }
 
 void table_item_submit (struct table_item *);
-\f
+
 #endif /* output/table-item.h */
index 30dcdff75f26dfd604b67f94a1428d608d17ed1a..f62d074bee528f1fd7d8139a427079874cadda91 100644 (file)
@@ -25,17 +25,6 @@ struct string;
 
 enum table_halign table_halign_interpret (enum table_halign, bool numeric);
 
-struct footnote
-  {
-    //size_t idx;
-    char *content;
-    char *marker;
-    struct table_area_style *style;
-  };
-
-struct footnote *footnote_clone (const struct footnote *);
-void footnote_destroy (struct footnote *);
-
 /* A cell in a table. */
 struct table_cell
   {
@@ -60,7 +49,7 @@ struct table_cell
     char *text;                 /* A paragraph of text. */
     char **subscripts;
     size_t n_subscripts;
-    struct footnote **footnotes;
+    struct pivot_footnote **footnotes;
     size_t n_footnotes;
     struct table_area_style *style;
   };
@@ -68,9 +57,6 @@ struct table_cell
 struct table_cell *table_cell_clone (const struct table_cell *);
 void table_cell_destroy (struct table_cell *);
 
-void table_cell_format_footnote_markers (const struct table_cell *,
-                                         struct string *);
-
 /* Returns the number of columns that CELL spans.  This is 1 for an ordinary
    cell and greater than one for a cell that joins multiple columns. */
 static inline int
@@ -100,6 +86,5 @@ table_cell_is_joined (const struct table_cell *cell)
 void table_get_cell (const struct table *, int x, int y, struct table_cell *);
 int table_get_rule (const struct table *, enum table_axis, int x, int y,
                     struct cell_color *);
-size_t table_collect_footnotes (const struct table_item *, struct footnote ***);
 
 #endif /* output/table-provider.h */
index 925b707100cf78653650da1c2327e75ec36aae9d..52e42207b4baae6544c6be35a79b2647c5c650bb 100644 (file)
@@ -90,99 +90,6 @@ table_area_style_free (struct table_area_style *style)
       free (style);
     }
 }
-
-struct footnote *
-footnote_clone (const struct footnote *old)
-{
-  struct footnote *new = xmalloc (sizeof *new);
-  *new = (struct footnote) {
-    .idx = old->idx,
-    .content = old->content ? xstrdup (old->content) : NULL,
-    .marker = old->marker ? xstrdup (old->marker) : NULL,
-    .style = old->style ? table_area_style_clone (NULL, old->style) : NULL,
-  };
-  return new;
-}
-
-void
-footnote_destroy (struct footnote *f)
-{
-  if (f)
-    {
-      free (f->content);
-      free (f->marker);
-      if (f->style)
-        {
-          table_area_style_uninit (f->style);
-          free (f->style);
-        }
-      free (f);
-    }
-}
-
-struct table_cell *
-table_cell_clone (const struct table_cell *old)
-{
-  struct table_cell *new = xmalloc (sizeof *new);
-  *new = *old;
-  new->text = xstrdup (new->text);
-
-  if (old->n_subscripts)
-    {
-      new->subscripts = xnmalloc (old->n_subscripts, sizeof *new->subscripts);
-      for (size_t i = 0; i < old->n_subscripts; i++)
-        new->subscripts[i] = xstrdup (old->subscripts[i]);
-    }
-  else
-    new->subscripts = NULL;
-
-  if (old->n_footnotes)
-    {
-      new->footnotes = xnmalloc (old->n_footnotes, sizeof *new->footnotes);
-      for (size_t i = 0; i < old->n_footnotes; i++)
-        new->footnotes[i] = footnote_clone (old->footnotes[i]);
-    }
-  else
-    new->footnotes = NULL;
-
-  if (old->style)
-    new->style = table_area_style_clone (NULL, old->style);
-
-  return new;
-}
-
-void
-table_cell_destroy (struct table_cell *cell)
-{
-  if (!cell)
-    return;
-
-  free (cell->text);
-  for (size_t i = 0; i < cell->n_subscripts; i++)
-    free (cell->subscripts[i]);
-  free (cell->subscripts);
-  for (size_t i = 0; i < cell->n_footnotes; i++)
-    footnote_destroy (cell->footnotes[i]);
-  free (cell->footnotes);
-  if (cell->style)
-    {
-      table_area_style_uninit (cell->style);
-      free (cell->style);
-    }
-  free (cell);
-}
-
-void
-table_cell_format_footnote_markers (const struct table_cell *cell,
-                                    struct string *s)
-{
-  for (size_t i = 0; i < cell->n_footnotes; i++)
-    {
-      if (i)
-        ds_put_byte (s, ',');
-      ds_put_cstr (s, cell->footnotes[i]->marker);
-    }
-}
 \f
 const char *
 table_halign_to_string (enum table_halign halign)
@@ -664,40 +571,20 @@ table_add_subscripts (struct table *table, int x, int y,
     cell->subscripts[i] = pool_strdup (table->container, subscripts[i]);
 }
 
-/* Create a footnote in TABLE with MARKER (e.g. "a") as its marker and CONTENT
-   as its content.  The footnote will be styled as STYLE, which is mandatory.
-   IDX must uniquely identify the footnote within TABLE.
-
-   Returns the new footnote.  The return value is the only way to get to the
-   footnote later, so it is important for the caller to remember it. */
-struct footnote *
-table_create_footnote (struct table *table, size_t idx, const char *content,
-                       const char *marker, struct table_area_style *style)
-{
-  assert (style);
-
-  struct footnote *f = pool_alloc (table->container, sizeof *f);
-  f->idx = idx;
-  f->content = pool_strdup (table->container, content);
-  f->marker = pool_strdup (table->container, marker);
-  f->style = style;
-  return f;
-}
-
-/* Attaches a reference to footnote F to the cell at column X, row Y in
-   TABLE. */
+/* Attaches a reference to the NF footnotes at F to the cell at column X, row Y
+   in TABLE. */
 void
-table_add_footnote (struct table *table, int x, int y, struct footnote *f)
+table_add_footnotes (struct table *table, int x, int y,
+                     struct pivot_footnote **f, size_t nf)
 {
-  assert (f->style);
-
   struct table_cell *cell = get_joined_cell (table, x, y);
 
   cell->footnotes = pool_realloc (
     table->container, cell->footnotes,
-    (cell->n_footnotes + 1) * sizeof *cell->footnotes);
+    (cell->n_footnotes + nf) * sizeof *cell->footnotes);
 
-  cell->footnotes[cell->n_footnotes++] = f;
+  for (size_t i = 0; i < nf; i++)
+    cell->footnotes[cell->n_footnotes++] = f[i];
 }
 
 /* Overrides the style for column X, row Y in TABLE with STYLE.
index 5c47ffe88c0c68e7a49ee0788c91d9b926af2f1a..ed9badf5d15aa9c4d2449825b54bf84b5fb26331 100644 (file)
@@ -37,6 +37,7 @@
 
 struct casereader;
 struct fmt_spec;
+struct pivot_footnote;
 struct pool;
 struct table_item;
 struct variable;
@@ -268,16 +269,8 @@ void table_joint_text (struct table *, int x1, int y1, int x2, int y2,
 void table_add_subscripts (struct table *, int x, int y,
                            char **subscripts, size_t n_subscripts);
 
-/* Footnotes.
-
-   Use table_create_footnote() to create the footnotes themselves, then use
-   table_add_footnote() to create a reference from a table cell to a footnote.
-   There are two steps because a footnote may have multiple references. */
-struct footnote *table_create_footnote (struct table *, size_t idx,
-                                        const char *content,
-                                        const char *marker,
-                                        struct table_area_style *);
-void table_add_footnote (struct table *, int x, int y, struct footnote *);
+void table_add_footnotes (struct table *, int x, int y,
+                          struct pivot_footnote **f, size_t nf);
 
 void table_add_style (struct table *, int x, int y, struct table_area_style *);
 
index cc46ee32272eca101e0f6b379d25ccf92b83367e..bf5eb7115ea540a7e65cbd4debb33970d26b32f3 100644 (file)
@@ -380,16 +380,18 @@ tex_submit (struct output_driver *driver,
 
 static void
 tex_put_footnote_markers (struct tex_driver *tex,
-                          struct footnote **footnotes,
+                          struct pivot_footnote **footnotes,
                           size_t n_footnotes)
 {
   if (n_footnotes > 0)
     shipout (&tex->token_list, "$^{");
   for (size_t i = 0; i < n_footnotes; i++)
     {
-      const struct footnote *f = footnotes[i];
-
-      tex_escape_string (tex, f->marker, true);
+      char *marker = pivot_value_to_string (footnotes[i]->marker,
+                                            SETTINGS_VALUE_SHOW_DEFAULT,
+                                            SETTINGS_VALUE_SHOW_DEFAULT);
+      tex_escape_string (tex, marker, true);
+      free (marker);
     }
   if (n_footnotes > 0)
     shipout (&tex->token_list, "}$");
@@ -409,7 +411,7 @@ tex_output_table_layer (struct tex_driver *tex, const struct pivot_table *pt,
   /* Tables are rendered in TeX with the \halign command.
      This is described in the TeXbook Ch. 22 */
   struct table *title, *layers, *body, *caption;
-  struct footnote **footnotes;
+  struct pivot_footnote **footnotes;
   size_t n_footnotes;
   pivot_output (pt, layer_indexes, &title, &layers, &body,
                 &caption, NULL, &footnotes, &n_footnotes);
@@ -543,10 +545,20 @@ tex_output_table_layer (struct tex_driver *tex, const struct pivot_table *pt,
 
   for (int i = 0; i < n_footnotes; ++i)
     {
+      char *marker = pivot_value_to_string (footnotes[i]->marker,
+                                            SETTINGS_VALUE_SHOW_DEFAULT,
+                                            SETTINGS_VALUE_SHOW_DEFAULT);
+      char *content = pivot_value_to_string (footnotes[i]->content,
+                                            SETTINGS_VALUE_SHOW_DEFAULT,
+                                            SETTINGS_VALUE_SHOW_DEFAULT);
+
       shipout (&tex->token_list, "$^{");
-      tex_escape_string (tex, footnotes[i]->marker, false);
+      tex_escape_string (tex, marker, false);
       shipout (&tex->token_list, "}$");
-      tex_escape_string (tex, footnotes[i]->content, false);
+      tex_escape_string (tex, content, false);
+
+      free (content);
+      free (marker);
     }
 
   shipout (&tex->token_list, "}\n\\vskip 3ex\n\n");
index 167c4caadf53133b27c477b6ca12fe1a95360fe6..49c9f225c06a21a6b95557ddf7ce7bc2a0caff96 100644 (file)
@@ -159,11 +159,28 @@ text_item_append (struct text_item *dst, const struct text_item *src)
     }
 }
 
+static const struct pivot_table_look *
+text_item_table_look (void)
+{
+  static struct pivot_table_look *look;
+  if (!look)
+    {
+      look = pivot_table_look_new_builtin_default ();
+
+      for (int a = 0; a < PIVOT_N_AREAS; a++)
+        memset (look->areas[a].cell_style.margin, 0,
+                sizeof look->areas[a].cell_style.margin);
+      for (int b = 0; b < PIVOT_N_BORDERS; b++)
+        look->borders[b].stroke = TABLE_STROKE_NONE;
+    }
+  return look;
+}
+
 struct table_item *
 text_item_to_table_item (struct text_item *text_item)
 {
   struct pivot_table *table = pivot_table_create__ (NULL, "Text");
-  pivot_table_set_look (table, pivot_table_look_builtin_default ());
+  pivot_table_set_look (table, text_item_table_look ());
 
   struct pivot_dimension *d = pivot_dimension_create (
     table, PIVOT_AXIS_ROW, N_("Text"));