+ if (!strchr (line_, '\n'))
+ xmlTextWriterWriteString (writer, _xml(line_));
+ else
+ {
+ char *line = xstrdup (line_);
+ char *newline;
+ char *p;
+
+ for (p = line; *p; p = newline + 1)
+ {
+ newline = strchr (p, '\n');
+
+ if (!newline)
+ {
+ xmlTextWriterWriteString (writer, _xml(p));
+ free (line);
+ return;
+ }
+
+ if (newline > p && newline[-1] == '\r')
+ newline[-1] = '\0';
+ else
+ *newline = '\0';
+ xmlTextWriterWriteString (writer, _xml(p));
+ xmlTextWriterWriteElement (writer, _xml("text:line-break"), _xml(""));
+ }
+ }
+}
+
+static void
+write_footnotes (struct odt_driver *odt,
+ const struct pivot_table *pt,
+ const size_t *footnote_indexes,
+ size_t n_footnotes)
+{
+ for (size_t i = 0; i < n_footnotes; i++)
+ {
+ const struct pivot_footnote *f = pt->footnotes[footnote_indexes[i]];
+ if (f->show)
+ {
+ xmlTextWriterStartElement (odt->content_wtr, _xml("text:span"));
+ xmlTextWriterWriteAttribute (odt->content_wtr,
+ _xml("text:style-name"),
+ _xml("superscript"));
+ char *s = pivot_footnote_marker_string (f, pt);
+ write_xml_with_line_breaks (odt, s);
+ free (s);
+ xmlTextWriterEndElement (odt->content_wtr);
+ }
+ }
+}
+
+static void
+write_table_item_cell (struct odt_driver *odt,
+ const struct pivot_table *pt,
+ const struct table_cell *cell)
+{
+ struct string body = DS_EMPTY_INITIALIZER;
+ pivot_value_format_body (cell->value, pt, &body);
+ xmlTextWriterWriteString (odt->content_wtr, _xml (ds_cstr (&body)));
+ ds_destroy (&body);
+
+ const struct pivot_value_ex *ex = pivot_value_ex (cell->value);
+ write_footnotes (odt, pt, ex->footnote_indexes, ex->n_footnotes);
+}
+
+static void
+write_table__ (struct odt_driver *odt, const struct pivot_table *pt,
+ const struct table *t)
+{
+ if (t)