table-item: Change title from table_item_text to table_cell.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 28 Dec 2020 18:50:53 +0000 (10:50 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 1 Jan 2021 19:15:05 +0000 (11:15 -0800)
src/output/csv.c
src/output/html.c
src/output/odt.c
src/output/pivot-output.c
src/output/pivot-table.c
src/output/render.c
src/output/table-item.c
src/output/table-item.h
src/output/table-provider.h
src/output/table.c
src/output/tex.c

index 6ff61382d2519de749e5f2b98e0eea3eefba3846..b29a6750538ac87fab0ccec4db1467ed714fbdad 100644 (file)
@@ -197,6 +197,46 @@ csv_output_table_item_text (struct csv_driver *csv,
   putc ('\n', csv->file);
 }
 
+static void
+csv_output_table_cell (struct csv_driver *csv,
+                       const struct table_cell *cell,
+                       const char *leader)
+{
+  if (!cell)
+    return;
+
+  if (!(cell->options & TAB_MARKUP) && !cell->n_footnotes
+      && !cell->n_subscripts && !leader)
+    csv_output_field (csv, cell->text);
+  else
+    {
+      struct string s = DS_EMPTY_INITIALIZER;
+
+      if (leader)
+        ds_put_format (&s, "%s: ", leader);
+
+      if (cell->options & TAB_MARKUP)
+        {
+          char *t = output_get_text_from_markup (cell->text);
+          ds_put_cstr (&s, t);
+          free (t);
+        }
+      else
+        ds_put_cstr (&s, cell->text);
+
+      if (cell->n_subscripts)
+        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);
+      csv_output_field (csv, ds_cstr (&s));
+      ds_destroy (&s);
+
+      if (leader)
+        putc ('\n', csv->file);
+    }
+}
+
 static void
 csv_submit (struct output_driver *driver,
             const struct output_item *output_item)
@@ -212,8 +252,7 @@ csv_submit (struct output_driver *driver,
       csv_put_separator (csv);
 
       if (csv->titles)
-        csv_output_table_item_text (csv, table_item_get_title (table_item),
-                                    "Table");
+        csv_output_table_cell (csv, table_item_get_title (table_item), "Table");
 
       for (y = 0; y < t->n[TABLE_VERT]; y++)
         {
@@ -228,30 +267,8 @@ csv_submit (struct output_driver *driver,
 
               if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
                 csv_output_field (csv, "");
-              else if (!(cell.options & TAB_MARKUP) && !cell.n_footnotes
-                       && !cell.n_subscripts)
-                csv_output_field (csv, cell.text);
               else
-                {
-                  struct string s = DS_EMPTY_INITIALIZER;
-
-                  if (cell.options & TAB_MARKUP)
-                    {
-                      char *t = output_get_text_from_markup (cell.text);
-                      ds_put_cstr (&s, t);
-                      free (t);
-                    }
-                  else
-                    ds_put_cstr (&s, cell.text);
-
-                  if (cell.n_subscripts)
-                    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);
-                  csv_output_field (csv, ds_cstr (&s));
-                  ds_destroy (&s);
-                }
+                csv_output_table_cell (csv, &cell, NULL);
             }
           putc ('\n', csv->file);
         }
index 31fa063f519b24b19806ffa11657960e7ca61f21..576b598427de831a4f8b4a09101d0ee6fa833fc5 100644 (file)
@@ -428,10 +428,17 @@ style_end (struct css_style *cs)
 }
 
 static void
-put_style (struct css_style *st, const char *name, const char *value)
+next_style (struct css_style *st)
 {
   bool first = !st->n_styles++;
-  fprintf (st->file, "%s%s: %s", first ? " style='" : "; ", name, value);
+  fputs (first ? " style='" : "; ", st->file);
+}
+
+static void
+put_style (struct css_style *st, const char *name, const char *value)
+{
+  next_style (st);
+  fprintf (st->file, "%s: %s", name, value);
 }
 
 static bool
@@ -452,20 +459,23 @@ format_color (const struct cell_color color,
 }
 
 static void
-put_border (struct css_style *st, int style, const struct cell_color *color,
+put_border (const struct table *table, const struct table_cell *cell,
+            struct css_style *style,
+            enum table_axis axis, int h, int v,
             const char *border_name)
 {
-  const char *css = border_to_css (style);
+  struct cell_color color;
+  const char *css = border_to_css (
+    table_get_rule (table, axis, cell->d[H][h], cell->d[V][v], &color));
   if (css)
     {
-      if (st->n_styles++ > 0)
-        fputs ("; ", st->file);
-      fprintf (st->file, "border-%s: %s", border_name, css);
+      next_style (style);
+      fprintf (style->file, "border-%s: %s", border_name, css);
 
       char buf[32];
-      if (format_color (*color, (struct cell_color) CELL_COLOR_BLACK,
+      if (format_color (color, (struct cell_color) CELL_COLOR_BLACK,
                         buf, sizeof buf))
-        fprintf (st->file, " %s", buf);
+        fprintf (style->file, " %s", buf);
     }
 }
 
@@ -554,12 +564,106 @@ html_put_table_item_layers (struct html_driver *html,
     }
 }
 
+static void
+html_put_table_cell (struct html_driver *html, const struct table *t,
+                     const struct table_cell *cell, const char *tag,
+                     bool border)
+{
+  fprintf (html->file, "<%s", tag);
+
+  struct css_style style;
+  style_start (&style, html->file);
+  enum table_halign halign = table_halign_interpret (
+    cell->style->cell_style.halign, cell->options & TAB_NUMERIC);
+
+  switch (halign)
+    {
+    case TABLE_HALIGN_RIGHT:
+      put_style (&style, "text-align", "right");
+      break;
+    case TABLE_HALIGN_CENTER:
+      put_style (&style, "text-align", "center");
+      break;
+    default:
+      /* Do nothing */
+      break;
+    }
+
+  if (cell->options & TAB_ROTATE)
+    put_style (&style, "writing-mode", "sideways-lr");
+
+  if (cell->style->cell_style.valign != TABLE_VALIGN_TOP)
+    {
+      put_style (&style, "vertical-align",
+                 (cell->style->cell_style.valign == TABLE_VALIGN_BOTTOM
+                  ? "bottom" : "middle"));
+    }
+
+  const struct font_style *fs = &cell->style->font_style;
+  char bgcolor[32];
+  if (format_color (fs->bg[cell->d[V][0] % 2],
+                    (struct cell_color) CELL_COLOR_WHITE,
+                    bgcolor, sizeof bgcolor))
+    put_style (&style, "background", bgcolor);
+
+  char fgcolor[32];
+  if (format_color (fs->fg[cell->d[V][0] % 2],
+                    (struct cell_color) CELL_COLOR_BLACK,
+                    fgcolor, sizeof fgcolor))
+    put_style (&style, "color", fgcolor);
+
+  if (fs->typeface)
+    {
+      put_style (&style, "font-family", "\"");
+      escape_string (html->file, fs->typeface, " ", "\n");
+      putc ('"', html->file);
+    }
+  if (fs->bold)
+    put_style (&style, "font-weight", "bold");
+  if (fs->italic)
+    put_style (&style, "font-style", "italic");
+  if (fs->underline)
+    put_style (&style, "text-decoration", "underline");
+  if (fs->size)
+    {
+      char buf[32];
+      snprintf (buf, sizeof buf, "%dpt", fs->size);
+      put_style (&style, "font-size", buf);
+    }
+
+  if (border)
+    {
+      put_border (t, cell, &style, V, 0, 0, "top");
+      put_border (t, cell, &style, H, 0, 0, "left");
+
+      if (cell->d[V][1] == t->n[V])
+        put_border (t, cell, &style, V, 0, 1, "bottom");
+      if (cell->d[H][1] == t->n[H])
+        put_border (t, cell, &style, H, 1, 0, "right");
+    }
+  style_end (&style);
+
+  int colspan = table_cell_colspan (cell);
+  if (colspan > 1)
+    fprintf (html->file, " colspan=\"%d\"", colspan);
+
+  int rowspan = table_cell_rowspan (cell);
+  if (rowspan > 1)
+    fprintf (html->file, " rowspan=\"%d\"", rowspan);
+
+  putc ('>', html->file);
+
+  html_put_table_cell_text (html, cell);
+
+  /* output </th> or </td>. */
+  fprintf (html->file, "</%s>\n", tag);
+}
+
 static void
 html_output_table (struct html_driver *html, const struct table_item *item)
 {
   const struct table *t = table_item_get_table (item);
   bool tfoot = false;
-  int y;
 
   fputs ("<table", html->file);
   if (item->notes)
@@ -593,13 +697,13 @@ html_output_table (struct html_driver *html, const struct table_item *item)
       fputs ("</tfoot>\n", html->file);
     }
 
-  const struct table_item_text *title = table_item_get_title (item);
+  const struct table_cell *title = table_item_get_title (item);
   const struct table_item_layers *layers = table_item_get_layers (item);
   if (title || layers)
     {
       fputs ("<caption>", html->file);
       if (title)
-        html_put_table_item_text (html, title);
+        html_put_table_cell (html, t, title, "span", false);
       if (title && layers)
         fputs ("<br>\n", html->file);
       if (layers)
@@ -609,132 +713,23 @@ html_output_table (struct html_driver *html, const struct table_item *item)
 
   fputs ("<tbody>\n", html->file);
 
-  for (y = 0; y < t->n[V]; y++)
+  for (int y = 0; y < t->n[V]; y++)
     {
-      int x;
-
       fputs ("<tr>\n", html->file);
-      for (x = 0; x < t->n[H];)
+      for (int x = 0; x < t->n[H]; )
         {
           struct table_cell cell;
-          const char *tag;
-
           table_get_cell (t, x, y, &cell);
-          if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
-            goto next_1;
-
-          /* output <td> or <th> tag. */
-          bool is_header = (y < t->h[V][0]
-                            || y >= t->n[V] - t->h[V][1]
-                            || x < t->h[H][0]
-                            || x >= t->n[H] - t->h[H][1]);
-          tag = is_header ? "th" : "td";
-          fprintf (html->file, "<%s", tag);
-
-          struct css_style style;
-          style_start (&style, html->file);
-          enum table_halign halign = table_halign_interpret (
-            cell.style->cell_style.halign, cell.options & TAB_NUMERIC);
-
-          switch (halign)
-            {
-            case TABLE_HALIGN_RIGHT:
-              put_style (&style, "text-align", "right");
-              break;
-            case TABLE_HALIGN_CENTER:
-              put_style (&style, "text-align", "center");
-              break;
-            default:
-              /* Do nothing */
-              break;
-            }
-
-          if (cell.options & TAB_ROTATE)
-            put_style (&style, "writing-mode", "sideways-lr");
-
-          if (cell.style->cell_style.valign != TABLE_VALIGN_TOP)
-            {
-              put_style (&style, "vertical-align",
-                         (cell.style->cell_style.valign == TABLE_VALIGN_BOTTOM
-                          ? "bottom" : "middle"));
-            }
-
-          const struct font_style *fs = &cell.style->font_style;
-          char bgcolor[32];
-          if (format_color (fs->bg[y % 2],
-                            (struct cell_color) CELL_COLOR_WHITE,
-                            bgcolor, sizeof bgcolor))
-            put_style (&style, "background", bgcolor);
-
-          char fgcolor[32];
-          if (format_color (fs->fg[y % 2],
-                            (struct cell_color) CELL_COLOR_BLACK,
-                            fgcolor, sizeof fgcolor))
-            put_style (&style, "color", fgcolor);
-
-          if (fs->typeface)
-            {
-              put_style (&style, "font-family", "\"");
-              escape_string (html->file, fs->typeface, " ", "\n");
-              putc ('"', html->file);
-            }
-          if (fs->bold)
-            put_style (&style, "font-weight", "bold");
-          if (fs->italic)
-            put_style (&style, "font-style", "italic");
-          if (fs->underline)
-            put_style (&style, "text-decoration", "underline");
-          if (fs->size)
+          if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
             {
-              char buf[32];
-              snprintf (buf, sizeof buf, "%dpt", fs->size);
-              put_style (&style, "font-size", buf);
+              bool is_header = (y < t->h[V][0]
+                                || y >= t->n[V] - t->h[V][1]
+                                || x < t->h[H][0]
+                                || x >= t->n[H] - t->h[H][1]);
+              const char *tag = is_header ? "th" : "td";
+              html_put_table_cell (html, t, &cell, tag, html->borders);
             }
 
-          int colspan = table_cell_colspan (&cell);
-          int rowspan = table_cell_rowspan (&cell);
-
-         if (html->borders)
-           {
-             /* Cell borders. */
-              struct cell_color color;
-
-             int top = table_get_rule (t, TABLE_VERT, x, y, &color);
-              put_border (&style, top, &color, "top");
-
-             if (y + rowspan == t->n[V])
-               {
-                 int bottom = table_get_rule (t, TABLE_VERT, x, y + rowspan,
-                                           &color);
-                  put_border (&style, bottom, &color, "bottom");
-               }
-
-             int left = table_get_rule (t, TABLE_HORZ, x, y, &color);
-              put_border (&style, left, &color, "left");
-
-             if (x + colspan == t->n[H])
-               {
-                 int right = table_get_rule (t, TABLE_HORZ, x + colspan, y,
-                                          &color);
-                  put_border (&style, right, &color, "right");
-               }
-           }
-          style_end (&style);
-
-          if (colspan > 1)
-            fprintf (html->file, " colspan=\"%d\"", colspan);
-
-          if (rowspan > 1)
-            fprintf (html->file, " rowspan=\"%d\"", rowspan);
-
-          putc ('>', html->file);
-
-          html_put_table_cell_text (html, &cell);
-
-          /* output </th> or </td>. */
-          fprintf (html->file, "</%s>\n", tag);
-
-        next_1:
           x = cell.d[TABLE_HORZ][1];
         }
       fputs ("</tr>\n", html->file);
index 65c46e1c67c03396448417334d6a3a56b80d5835..97109cef4276a4bbd830c2fd9b4a6a79f1aa9016 100644 (file)
@@ -442,6 +442,22 @@ write_table_item_text (struct odt_driver *odt,
   xmlTextWriterEndElement (odt->content_wtr);
 }
 
+static void
+write_table_item_cell (struct odt_driver *odt,
+                       const struct table_cell *cell)
+{
+  if (!cell)
+    return;
+
+  xmlTextWriterStartElement (odt->content_wtr, _xml("text:h"));
+  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]);
+  xmlTextWriterEndElement (odt->content_wtr);
+}
+
 static void
 write_table_item_layers (struct odt_driver *odt,
                          const struct table_item_layers *layers)
@@ -469,7 +485,7 @@ write_table (struct odt_driver *odt, const struct table_item *item)
   int r, c;
 
   /* Write a heading for the table */
-  write_table_item_text (odt, table_item_get_title (item));
+  write_table_item_cell (odt, table_item_get_title (item));
   write_table_item_layers (odt, table_item_get_layers (item));
 
   /* Start table */
index aaa0633e8db962bf92b05abad12b2c6dc28c24ce..f9f497439d18b03a2e01faa4714563ba11790738 100644 (file)
@@ -93,6 +93,27 @@ table_area_style_override (struct pool *pool,
   return out;
 }
 
+static int
+format_cell (const struct pivot_value *value, int style_idx,
+             enum settings_value_show show_values,
+             enum settings_value_show show_variables,
+             bool rotate_label, struct string *s)
+{
+  int options = style_idx << TAB_STYLE_SHIFT;
+  if (value)
+    {
+      bool numeric = pivot_value_format_body (value, show_values,
+                                              show_variables, s);
+      if (numeric)
+        options |= TAB_NUMERIC;
+      if (value->font_style && value->font_style->markup)
+        options |= TAB_MARKUP;
+      if (rotate_label)
+        options |= TAB_ROTATE;
+    }
+  return options;
+}
+
 static void
 fill_cell (struct table *t, int x1, int y1, int x2, int y2,
            const struct table_area_style *style, int style_idx,
@@ -101,21 +122,10 @@ fill_cell (struct table *t, int x1, int y1, int x2, int y2,
            enum settings_value_show show_variables,
            bool rotate_label)
 {
-
   struct string s = DS_EMPTY_INITIALIZER;
-  int opts = style_idx << TAB_STYLE_SHIFT;
-  if (value)
-    {
-      bool numeric = pivot_value_format_body (value, show_values,
-                                              show_variables, &s);
-      if (numeric)
-        opts |= TAB_NUMERIC;
-      if (value->font_style && value->font_style->markup)
-        opts |= TAB_MARKUP;
-      if (rotate_label)
-        opts |= TAB_ROTATE;
-    }
-  table_joint_text (t, x1, y1, x2, y2, opts, ds_cstr (&s));
+  int options = format_cell (value, style_idx,
+                             show_values, show_variables, rotate_label, &s);
+  table_joint_text (t, x1, y1, x2, y2, options, ds_cstr (&s));
   ds_destroy (&s);
 
   if (value)
@@ -140,6 +150,51 @@ fill_cell (struct table *t, int x1, int y1, int x2, int y2,
     }
 }
 
+static struct table_cell *
+pivot_value_to_table_cell (const struct pivot_value *value,
+                           const struct table_area_style *style, int style_idx,
+                           struct footnote **footnotes,
+                           enum settings_value_show show_values,
+                           enum settings_value_show show_variables)
+{
+  if (!value)
+    return NULL;
+
+  struct string s = DS_EMPTY_INITIALIZER;
+  int options = format_cell (value, style_idx,
+                             show_values, show_variables, false, &s);
+
+  struct table_cell *cell = xmalloc (sizeof *cell);
+  *cell = (struct table_cell) {
+    .options = options,
+    .text = ds_steal_cstr (&s),
+    .style = table_area_style_override (
+      NULL, style, value->cell_style, value->font_style, false),
+  };
+
+  if (value->n_subscripts)
+    {
+      cell->subscripts = xnmalloc (value->n_subscripts,
+                                   sizeof *cell->subscripts);
+      cell->n_subscripts = value->n_subscripts;
+      for (size_t i = 0; i < value->n_subscripts; i++)
+        cell->subscripts[i] = xstrdup (value->subscripts[i]);
+    }
+
+  if (value->n_footnotes)
+    {
+      cell->footnotes = xnmalloc (value->n_footnotes, sizeof *cell->footnotes);
+      for (size_t i = 0; i < value->n_footnotes; i++)
+        {
+          struct footnote *f = footnotes[value->footnotes[i]->idx];
+          if (f)
+            cell->footnotes[cell->n_footnotes++] = f;
+        }
+    }
+
+  return cell;
+}
+
 static struct table_item_text *
 pivot_value_to_table_item_text (const struct pivot_value *value,
                                 const struct table_area_style *area,
@@ -567,11 +622,11 @@ pivot_table_submit_layer (const struct pivot_table *pt,
 
   if (pt->title && pt->show_title)
     {
-      struct table_item_text *title = pivot_value_to_table_item_text (
-        pt->title, &pt->look->areas[PIVOT_AREA_TITLE], footnotes,
-        pt->show_values, pt->show_variables);
+      struct table_cell *title = pivot_value_to_table_cell (
+        pt->title, &pt->look->areas[PIVOT_AREA_TITLE], PIVOT_AREA_TITLE,
+        footnotes, pt->show_values, pt->show_variables);
       table_item_set_title (ti, title);
-      table_item_text_destroy (title);
+      table_cell_destroy (title);
     }
 
   const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
index 3fd336690820c8409c4b6b653cc88081e2d54b5d..b185d3ea8ac4c9ff8440cb5bc4561ed096f47a7c 100644 (file)
@@ -1904,7 +1904,10 @@ interpret_show (enum settings_value_show global_show,
 /* Appends a text representation of the body of VALUE to OUT.  SHOW_VALUES and
    SHOW_VARIABLES control whether variable and value labels are included.
 
-   The "body" omits subscripts and superscripts and footnotes. */
+   The "body" omits subscripts and superscripts and footnotes.
+
+   Returns true if OUT is a number (or a number plus a value label), false
+   otherwise.  */
 bool
 pivot_value_format_body (const struct pivot_value *value,
                          enum settings_value_show show_values,
index 41daea37e002c55580d91d00cb6c44c1fb4e7303..b3ef3062511c9daec499e335cab93d032001848e 100644 (file)
@@ -1535,6 +1535,22 @@ add_footnote_page (struct render_pager *p, const struct table_item *item)
   free (f);
 }
 
+static void
+add_table_cell_page (struct render_pager *p, const struct table_cell *cell,
+                     int min_width)
+{
+  if (!cell)
+    return;
+
+  struct table *tab = table_create (1, 1, 0, 0, 0, 0);
+  table_text (tab, 0, 0, 0, cell->text);
+  for (size_t i = 0; i < cell->n_footnotes; i++)
+    table_add_footnote (tab, 0, 0, cell->footnotes[i]);
+  if (cell->style)
+    tab->styles[0] = table_area_style_clone (tab->container, cell->style);
+  render_pager_add_table (p, tab, min_width);
+}
+
 static void
 add_text_page (struct render_pager *p, const struct table_item_text *t,
                int min_width)
@@ -1605,7 +1621,7 @@ render_pager_create (const struct render_params *params,
   /* Create the pager. */
   struct render_pager *p = xmalloc (sizeof *p);
   *p = (struct render_pager) { .params = params, .scale = scale };
-  add_text_page (p, table_item_get_title (table_item), body_width);
+  add_table_cell_page (p, table_item_get_title (table_item), body_width);
   add_layers_page (p, table_item_get_layers (table_item), body_width);
   render_pager_add_table (p, table_ref (table_item_get_table (table_item)), 0);
   add_text_page (p, table_item_get_caption (table_item), 0);
index bc154d5462ab0f7b9072688dfc15bee91f178164..93cbde70ed64f8f214d4388a3b5211ddf4ad665d 100644 (file)
@@ -26,6 +26,7 @@
 #include "output/output-item-provider.h"
 #include "output/pivot-table.h"
 #include "output/table-item.h"
+#include "output/table-provider.h"
 
 #include "gl/xalloc.h"
 
@@ -145,7 +146,7 @@ table_item_get_table (const struct table_item *table_item)
 
 /* Returns ITEM's title, which is a null pointer if no title has been
    set. */
-const struct table_item_text *
+const struct table_cell *
 table_item_get_title (const struct table_item *item)
 {
   return item->title;
@@ -156,12 +157,11 @@ table_item_get_title (const struct table_item *item)
 
    This function may only be used on a table_item that is unshared. */
 void
-table_item_set_title (struct table_item *item,
-                      const struct table_item_text *title)
+table_item_set_title (struct table_item *item, const struct table_cell *title)
 {
   assert (!table_item_is_shared (item));
-  table_item_text_destroy (item->title);
-  item->title = table_item_text_clone (title);
+  table_cell_destroy (item->title);
+  item->title = table_cell_clone (title);
 }
 
 /* Returns ITEM's layers, which will be a null pointer if no layers have been
@@ -240,8 +240,8 @@ static const char *
 table_item_get_label (const struct output_item *output_item)
 {
   const struct table_item *item = to_table_item (output_item);
-  return (item->title && item->title->content
-          ? item->title->content
+  return (item->title && item->title->text
+          ? item->title->text
           : _("Table"));
 }
 
@@ -249,7 +249,7 @@ static void
 table_item_destroy (struct output_item *output_item)
 {
   struct table_item *item = to_table_item (output_item);
-  table_item_text_destroy (item->title);
+  table_cell_destroy (item->title);
   table_item_text_destroy (item->caption);
   table_item_layers_destroy (item->layers);
   free (item->notes);
index a4435a0f5971f6e5cf506dcd6aaf60f11c468ebe..57d18b75cc28c26c32e0d2c5580fbe372111998d 100644 (file)
@@ -72,7 +72,7 @@ struct table_item
   {
     struct output_item output_item;   /* Superclass. */
     struct table *table;              /* The table to be rendered. */
-    struct table_item_text *title;    /* Null if there is no title. */
+    struct table_cell *title;         /* Null if there is no title. */
     struct table_item_text *caption;  /* Null if there is no caption. */
     struct table_item_layers *layers; /* Null if there is no layer info. */
     char *notes;                      /* Shown as tooltip. */
@@ -83,9 +83,8 @@ struct table_item *table_item_create (struct table *);
 
 const struct table *table_item_get_table (const struct table_item *);
 
-const struct table_item_text *table_item_get_title (const struct table_item *);
-void table_item_set_title (struct table_item *,
-                           const struct table_item_text *);
+const struct table_cell *table_item_get_title (const struct table_item *);
+void table_item_set_title (struct table_item *, const struct table_cell *);
 
 const struct table_item_layers *table_item_get_layers (
   const struct table_item *);
index 2b14c98d1c29e9838b8550d621c2cd7d6ac229ef..6aa59d86484d24bca72a6bfb5903a8bb2b393d26 100644 (file)
@@ -33,6 +33,9 @@ struct footnote
     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
   {
index 090625ff70999d8c6feaec8a176e638537fa2c77..5430cd5ffb8537d273bd486f2738034324002a2f 100644 (file)
@@ -91,6 +91,87 @@ table_area_style_free (struct table_area_style *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)
@@ -146,7 +227,7 @@ table_collect_footnotes (const struct table_item *item,
         }
     }
 
-  const struct table_item_text *title = table_item_get_title (item);
+  const struct table_cell *title = table_item_get_title (item);
   if (title)
     footnotes = add_footnotes (title->footnotes, title->n_footnotes,
                                footnotes, &allocated, &n);
index 15540cd1e28a411c617a90a48e4ff1cae60e3b33..cd90c3ab468855bedf7fce436954e00f8a9ad72c 100644 (file)
@@ -394,11 +394,10 @@ tex_put_footnote_markers (struct tex_driver *tex,
 }
 
 static void
-tex_put_table_item_text (struct tex_driver *tex,
-                          const struct table_item_text *text)
+tex_put_table_cell (struct tex_driver *tex, const struct table_cell *cell)
 {
-  tex_escape_string (tex, text->content, false);
-  tex_put_footnote_markers (tex, text->footnotes, text->n_footnotes);
+  tex_escape_string (tex, cell->text, false);
+  tex_put_footnote_markers (tex, cell->footnotes, cell->n_footnotes);
 }
 
 static void
@@ -421,14 +420,14 @@ tex_output_table (struct tex_driver *tex, const struct table_item *item)
   struct footnote **f;
   size_t n_footnotes = table_collect_footnotes (item, &f);
 
-  const struct table_item_text *title = table_item_get_title (item);
+  const struct table_cell *title = table_item_get_title (item);
   const struct table_item_layers *layers = table_item_get_layers (item);
   if (title || layers)
     {
       if (title)
         {
           shipout (&tex->token_list, "{\\bf ");
-          tex_put_table_item_text (tex, title);
+          tex_put_table_cell (tex, title);
           shipout (&tex->token_list, "}");
         }
       if (layers)