+
+struct text_item *
+text_item_unshare (struct text_item *old)
+{
+ assert (old->output_item.ref_cnt > 0);
+ if (!text_item_is_shared (old))
+ return old;
+ text_item_unref (old);
+
+ struct text_item *new = xmalloc (sizeof *new);
+ *new = (struct text_item) {
+ .output_item = OUTPUT_ITEM_CLONE_INITIALIZER (&old->output_item),
+ .text = pivot_value_clone (old->text),
+ .type = old->type,
+ };
+ return new;
+}
+
+static bool
+nullable_font_style_equal (const struct font_style *a,
+ const struct font_style *b)
+{
+ return a && b ? font_style_equal (a, b) : !a && !b;
+}
+
+/* Attempts to append the text in SRC to DST. If successful, returns true,
+ otherwise false.
+
+ Only TEXT_ITEM_SYNTAX and TEXT_ITEM_LOG items can be combined, and not with
+ each other.
+
+ DST must not be shared. */
+bool
+text_item_append (struct text_item *dst, const struct text_item *src)
+{
+ assert (!text_item_is_shared (dst));
+ if (dst->type != src->type
+ || (dst->type != TEXT_ITEM_SYNTAX && dst->type != TEXT_ITEM_LOG)
+ || strcmp (output_item_get_label (&dst->output_item),
+ output_item_get_label (&src->output_item))
+ || !nullable_font_style_equal (dst->text->font_style,
+ src->text->font_style)
+ || (dst->text->font_style && dst->text->font_style->markup)
+ || src->text->type != PIVOT_VALUE_TEXT
+ || dst->text->type != PIVOT_VALUE_TEXT)
+ return false;
+ else
+ {
+ char *new_text = xasprintf ("%s\n%s", dst->text->text.local,
+ src->text->text.local);
+
+ free (dst->text->text.local);
+ if (dst->text->text.c != dst->text->text.local)
+ free (dst->text->text.c);
+ if (dst->text->text.id != dst->text->text.local
+ && dst->text->text.id != dst->text->text.c)
+ free (dst->text->text.id);
+
+ dst->text->text.local = new_text;
+ dst->text->text.c = new_text;
+ dst->text->text.id = new_text;
+
+ return true;
+ }
+}
+
+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, text_item_table_look ());
+
+ struct pivot_dimension *d = pivot_dimension_create (
+ table, PIVOT_AXIS_ROW, N_("Text"));
+ d->hide_all_labels = true;
+ pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
+
+ pivot_table_put1 (table, 0, pivot_value_clone (text_item->text));
+
+ text_item_unref (text_item);
+
+ return table_item_create (table);
+}