#include "frontends/Painter.h"
#include <algorithm>
+#include <iostream>
#include <ostream>
using namespace lyx::support;
}
+namespace {
+void splitAndWrapInMText(MathMLStream & ms, MathData const & cell,
+ const std::string & attributes)
+{
+ // First, generate the inset into a string of its own.
+ docstring inset_contents;
+ {
+ odocstringstream ostmp;
+ MathMLStream mstmp(ostmp, ms.xmlns());
+
+ SetMode textmode(mstmp, true);
+ mstmp << cell;
+
+ inset_contents = ostmp.str();
+ }
+
+ std::cout << '"' << to_ascii(inset_contents) << '"' << std::endl;
+
+ // No tags are allowed within <m:mtext>: split the string if there are tags.
+ std::vector<docstring> parts;
+ while (true) {
+ std::size_t angle_pos = inset_contents.find('<');
+ if (angle_pos == docstring::npos)
+ break;
+
+ // String structure:
+ // - prefix: pure text, no tag
+ // - tag to split: something like <m:mn>1</m:mn> or more complicated
+ // (like nested tags), with or without name space
+ // - rest to be taken care of in the next iteration
+
+ // Push the part before the tag.
+ parts.emplace_back(inset_contents.substr(0, angle_pos));
+ inset_contents = inset_contents.substr(angle_pos);
+ // Now, inset_contents starts with the tag to isolate, so that
+ // inset_contents[0] == '<'
+
+ // Push the tag, up to its end. Process: find the tag name (either
+ // before > or the first attribute of the tag), then the matching end
+ // tag, then proceed with pushing.
+ const std::size_t tag_name_end =
+ std::min(inset_contents.find(' ', 1), inset_contents.find('>', 1));
+ const std::size_t tag_name_length = tag_name_end - 1;
+ const docstring tag_name = inset_contents.substr(1, tag_name_length);
+
+ const std::size_t end_tag_start =
+ inset_contents.find(tag_name, tag_name_end + 1);
+ const std::size_t end_tag = inset_contents.find('>', end_tag_start);
+
+ parts.emplace_back(inset_contents.substr(0, end_tag + 1));
+ inset_contents = inset_contents.substr(end_tag + 1);
+ }
+ parts.emplace_back(inset_contents);
+
+ // Finally, output the complete inset: escape the test in <m:mtext>, leave
+ // the other tags untouched.
+ ms << MTag("mrow", attributes);
+ for (int i = 0; i < parts.size(); i += 2) {
+ ms << MTag("mtext")
+ << parts[i]
+ << ETag("mtext");
+ if (parts.size() > i + 1)
+ ms << parts[i + 1];
+ }
+ ms << ETag("mrow");
+}
+}
+
+
void InsetMathBox::mathmlize(MathMLStream & ms) const
{
// FIXME XHTML
// Need to do something special for tags here.
// Probably will have to involve deferring them, which
// means returning something from this routine.
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='mathbox'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='mathbox'");
}
void InsetMathFBox::mathmlize(MathMLStream & ms) const
{
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='fbox'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='fbox'");
}
{
// FIXME We could do something with the other arguments.
std::string const cssclass = framebox_ ? "framebox" : "makebox";
- SetMode textmode(ms, true);
- ms << MTag("mtext", "class='" + cssclass + "'")
- << cell(2)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(2), "class='" + cssclass + "'");
}
void InsetMathBoxed::mathmlize(MathMLStream & ms) const
{
- ms << MTag("mtext", "class='boxed'")
- << cell(0)
- << ETag("mtext");
+ splitAndWrapInMText(ms, cell(0), "class='boxed'");
}