render: Simplify 'pages' array in struct render_pager.
[pspp] / src / output / table.c
index 5087441224a3c75bcea5f2e87ab3eb7fd9521e90..44c33b9d10b36ceabb6df4125d1038567f16076d 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)
@@ -103,13 +184,13 @@ table_cell_format_footnote_markers (const struct table_cell *cell,
     }
 }
 
-static const struct footnote **
-add_footnotes (const struct footnote **refs, size_t n_refs,
-               const struct footnote **footnotes, size_t *allocated, size_t *n)
+static struct footnote **
+add_footnotes (struct footnote **refs, size_t n_refs,
+               struct footnote **footnotes, size_t *allocated, size_t *n)
 {
   for (size_t i = 0; i < n_refs; i++)
     {
-      const struct footnote *f = refs[i];
+      struct footnote *f = refs[i];
       if (f->idx >= *allocated)
         {
           size_t new_allocated = (f->idx + 1) * 2;
@@ -126,9 +207,9 @@ add_footnotes (const struct footnote **refs, size_t n_refs,
 
 size_t
 table_collect_footnotes (const struct table_item *item,
-                         const struct footnote ***footnotesp)
+                         struct footnote ***footnotesp)
 {
-  const struct footnote **footnotes = NULL;
+  struct footnote **footnotes = NULL;
   size_t allocated = 0;
   size_t n = 0;
 
@@ -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);
@@ -160,7 +241,7 @@ table_collect_footnotes (const struct table_item *item,
                                    footnotes, &allocated, &n);
     }
 
-  const struct table_item_text *caption = table_item_get_caption (item);
+  const struct table_cell *caption = table_item_get_caption (item);
   if (caption)
     footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
                                footnotes, &allocated, &n);
@@ -300,6 +381,22 @@ font_style_dump (const struct font_style *f)
     fputs (" underline", stdout);
 }
 
+bool
+font_style_equal (const struct font_style *a, const struct font_style *b)
+{
+  return (a->bold == b->bold
+          && 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])
+          && !strcmp (a->typeface ? a->typeface : "",
+                      b->typeface ? b->typeface : "")
+          && a->size == b->size);
+}
+
 void
 cell_style_dump (const struct cell_style *c)
 {
@@ -661,8 +758,7 @@ table_create_footnote (struct table *table, size_t idx, const char *content,
 /* Attaches a reference to footnote F to the cell at column X, row Y in
    TABLE. */
 void
-table_add_footnote (struct table *table, int x, int y,
-                    const struct footnote *f)
+table_add_footnote (struct table *table, int x, int y, struct footnote *f)
 {
   assert (f->style);
 
@@ -680,7 +776,7 @@ table_add_footnote (struct table *table, int x, int y,
    TABLE->container or have a lifetime that will outlive TABLE. */
 void
 table_add_style (struct table *table, int x, int y,
-                 const struct table_area_style *style)
+                 struct table_area_style *style)
 {
   get_joined_cell (table, x, y)->style = style;
 }
@@ -693,10 +789,7 @@ table_cell_is_empty (const struct table *table, int c, int r)
 }
 \f
 /* Initializes CELL with the contents of the table cell at column X and row Y
-   within TABLE.  When CELL is no longer needed, the caller is responsible for
-   freeing it by calling table_cell_free(CELL).
-
-   The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
+   within TABLE. */
 void
 table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
 {
@@ -707,7 +800,7 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
   unsigned short opt = t->ct[index];
   const void *cc = t->cc[index];
 
-  const struct table_area_style *style
+  struct table_area_style *style
     = t->styles[(opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT];
   if (opt & TAB_JOIN)
     {