+ 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_footnote (struct odt_driver *odt, const struct footnote *f)
+{
+ 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);
+}
+
+static void
+write_table_item_text (struct odt_driver *odt,
+ const struct table_item_text *text)
+{
+ if (!text)
+ return;
+
+ xmlTextWriterStartElement (odt->content_wtr, _xml("text:h"));
+ xmlTextWriterWriteFormatAttribute (odt->content_wtr,
+ _xml("text:outline-level"), "%d", 2);
+ xmlTextWriterWriteString (odt->content_wtr, _xml (text->content));
+ for (size_t i = 0; i < text->n_footnotes; i++)
+ write_footnote (odt, text->footnotes[i]);
+ xmlTextWriterEndElement (odt->content_wtr);
+}
+
+static void
+write_table_item_layers (struct odt_driver *odt,
+ const struct table_item_layers *layers)
+{
+ if (!layers)
+ return;
+
+ for (size_t i = 0; i < layers->n_layers; i++)