mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-24 10:40:48 +00:00
Fix bug #13069.
Use XML parser to handle <mtext> issues. Some of the config/qt.m4 code by JMarc.
This commit is contained in:
parent
b5260a3a0f
commit
fafe3ea5d7
14
config/qt.m4
14
config/qt.m4
@ -28,10 +28,10 @@ AC_DEFUN([QT_CHECK_COMPILE],
|
|||||||
qt_guilibs="'-lQtCore -lQtGui' '-lQtCore4 -lQtGui4'"
|
qt_guilibs="'-lQtCore -lQtGui' '-lQtCore4 -lQtGui4'"
|
||||||
if test $USE_QT6 = "yes" ; then
|
if test $USE_QT6 = "yes" ; then
|
||||||
qt_corelibs="-lQt6Core"
|
qt_corelibs="-lQt6Core"
|
||||||
qt_guilibs="-lQt6Core -lQt6Concurrent -lQt6Gui -lQt6Svg -lQt6Widgets"
|
qt_guilibs="-lQt6Core -lQt6Concurrent -lQt6Gui -lQt6Svg -lQt6Xml -lQt6Widgets"
|
||||||
else
|
else
|
||||||
qt_corelibs="-lQt5Core"
|
qt_corelibs="-lQt5Core"
|
||||||
qt_guilibs="-lQt5Core -lQt5Concurrent -lQt5Gui -lQt5Svg -lQt5Widgets"
|
qt_guilibs="-lQt5Core -lQt5Concurrent -lQt5Gui -lQt5Svg -lQt5Xml -lQt5Widgets"
|
||||||
fi
|
fi
|
||||||
for libname in $qt_corelibs '-framework QtCore'
|
for libname in $qt_corelibs '-framework QtCore'
|
||||||
do
|
do
|
||||||
@ -43,8 +43,8 @@ AC_DEFUN([QT_CHECK_COMPILE],
|
|||||||
done
|
done
|
||||||
qt_cv_libname=
|
qt_cv_libname=
|
||||||
for libname in $qt_guilibs \
|
for libname in $qt_guilibs \
|
||||||
'-framework QtCore -framework QtConcurrent -framework QtSvg -framework QtWidgets -framework QtMacExtras -framework QtGui'\
|
'-framework QtCore -framework QtConcurrent -framework QtSvg -framework QtXml -framework QtWidgets -framework QtMacExtras -framework QtGui'\
|
||||||
'-framework QtCore -framework QtConcurrent -framework QtSvg -framework QtSvgWidgets -framework QtWidgets -framework QtGui'\
|
'-framework QtCore -framework QtConcurrent -framework QtSvg -framework QtSvgWidgets -framework QtXml -framework QtWidgets -framework QtGui'\
|
||||||
'-framework QtCore -framework QtGui'
|
'-framework QtCore -framework QtGui'
|
||||||
do
|
do
|
||||||
QT_TRY_LINK($libname)
|
QT_TRY_LINK($libname)
|
||||||
@ -264,7 +264,7 @@ AC_DEFUN([QT_DO_PKG_CONFIG],
|
|||||||
export PKG_CONFIG_PATH
|
export PKG_CONFIG_PATH
|
||||||
fi
|
fi
|
||||||
qt_corelibs="Qt5Core"
|
qt_corelibs="Qt5Core"
|
||||||
qt_guilibs="Qt5Core Qt5Concurrent Qt5Gui Qt5Svg Qt5Widgets"
|
qt_guilibs="Qt5Core Qt5Concurrent Qt5Gui Qt5Svg Qt5Widgets Qt5Xml"
|
||||||
lyx_use_x11extras=false
|
lyx_use_x11extras=false
|
||||||
PKG_CHECK_EXISTS(Qt5X11Extras, [lyx_use_x11extras=true], [])
|
PKG_CHECK_EXISTS(Qt5X11Extras, [lyx_use_x11extras=true], [])
|
||||||
if $lyx_use_x11extras; then
|
if $lyx_use_x11extras; then
|
||||||
@ -339,7 +339,7 @@ AC_DEFUN([QT_DO_MANUAL_CONFIG],
|
|||||||
QT_CORE_LDFLAGS=
|
QT_CORE_LDFLAGS=
|
||||||
if test -n "$qt_cv_includes"; then
|
if test -n "$qt_cv_includes"; then
|
||||||
QT_INCLUDES="-I$qt_cv_includes"
|
QT_INCLUDES="-I$qt_cv_includes"
|
||||||
for i in Qt QtCore QtGui QtWidgets QtSvg QtConcurrent QtSvgWidgets QtMacExtras; do
|
for i in Qt QtCore QtGui QtWidgets QtSvg QtConcurrent QtSvgWidgets QtXml QtMacExtras; do
|
||||||
QT_INCLUDES="$QT_INCLUDES -I$qt_cv_includes/$i"
|
QT_INCLUDES="$QT_INCLUDES -I$qt_cv_includes/$i"
|
||||||
if test "$lyx_use_packaging" = "macosx" ; then
|
if test "$lyx_use_packaging" = "macosx" ; then
|
||||||
QT_INCLUDES="$QT_INCLUDES -I$qt_cv_libraries/${i}.framework/Headers"
|
QT_INCLUDES="$QT_INCLUDES -I$qt_cv_libraries/${i}.framework/Headers"
|
||||||
@ -435,6 +435,8 @@ qtHaveModule(concurrent) {QT += concurrent} else {MISSING += concurrent}
|
|||||||
qtHaveModule(gui) {QT += gui} else {MISSING += gui}
|
qtHaveModule(gui) {QT += gui} else {MISSING += gui}
|
||||||
qtHaveModule(gui-private) {QT += gui-private} else {MISSING += gui-private}
|
qtHaveModule(gui-private) {QT += gui-private} else {MISSING += gui-private}
|
||||||
qtHaveModule(svg) {QT += svg} else {MISSING += svg}
|
qtHaveModule(svg) {QT += svg} else {MISSING += svg}
|
||||||
|
qtHaveModule(svgwidgets) {QT += svgwidgets} else {MISSING += svgwidgets}
|
||||||
|
qtHaveModule(xml) {QT += xml} else {MISSING += xml}
|
||||||
qtHaveModule(widgets) {QT += widgets} else {MISSING += widgets}
|
qtHaveModule(widgets) {QT += widgets} else {MISSING += widgets}
|
||||||
EOF2
|
EOF2
|
||||||
if test "$qt_major" = 6; then
|
if test "$qt_major" = 6; then
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <QtXml/QDomDocument>
|
||||||
|
#include <QtXml/QDomElement>
|
||||||
|
#include "support/qstring_helpers.h"
|
||||||
|
|
||||||
using namespace lyx::support;
|
using namespace lyx::support;
|
||||||
|
|
||||||
namespace lyx {
|
namespace lyx {
|
||||||
@ -62,6 +66,10 @@ namespace {
|
|||||||
void splitAndWrapInMText(MathMLStream & ms, MathData const & cell,
|
void splitAndWrapInMText(MathMLStream & ms, MathData const & cell,
|
||||||
const std::string & attributes)
|
const std::string & attributes)
|
||||||
{
|
{
|
||||||
|
// The goal of this function is to take an XML fragment and wrap
|
||||||
|
// anything that is outside of any tag in <mtext></mtext> tags,
|
||||||
|
// then wrap the whole thing in an <mrow></mrow> tag with attributes
|
||||||
|
|
||||||
// First, generate the inset into a string of its own.
|
// First, generate the inset into a string of its own.
|
||||||
docstring inset_contents;
|
docstring inset_contents;
|
||||||
{
|
{
|
||||||
@ -74,52 +82,45 @@ void splitAndWrapInMText(MathMLStream & ms, MathData const & cell,
|
|||||||
inset_contents = ostmp.str();
|
inset_contents = ostmp.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// No tags are allowed within <m:mtext>: split the string if there are tags.
|
// We use the QT XML library. It's easier if we deal with an XML "document"
|
||||||
std::vector<docstring> parts;
|
// rather than "fragment", so we wrap it in a fake root node (which we will
|
||||||
while (true) {
|
// remove at the end).
|
||||||
std::size_t angle_pos = inset_contents.find('<');
|
docstring inset_contents_xml = "<root>" + inset_contents + "</root>";
|
||||||
if (angle_pos == docstring::npos)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// String structure:
|
// Parse the XML into a DOM
|
||||||
// - prefix: pure text, no tag
|
QDomDocument xml;
|
||||||
// - tag to split: something like <m:mn>1</m:mn> or more complicated
|
xml.setContent(toqstr(inset_contents_xml));
|
||||||
// (like nested tags), with or without name space
|
|
||||||
// - rest to be taken care of in the next iteration
|
|
||||||
|
|
||||||
// Push the part before the tag.
|
QDomElement docElem = xml.documentElement();
|
||||||
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
|
// Iterate through the children of our fake root element.
|
||||||
// before > or the first attribute of the tag), then the matching end
|
QDomNode n = docElem.firstChild();
|
||||||
// tag, then proceed with pushing.
|
while (!n.isNull()) {
|
||||||
const std::size_t tag_name_end =
|
// try to convert the child into a text element
|
||||||
std::min(inset_contents.find(' ', 1), inset_contents.find('>', 1));
|
// (i.e. some text that is outside of an XML tag)
|
||||||
const std::size_t tag_name_length = tag_name_end - 1;
|
QDomText text = n.toText();
|
||||||
const docstring tag_name = inset_contents.substr(1, tag_name_length);
|
if (!text.isNull()) {
|
||||||
|
// if the result is not null, then the child was indeed
|
||||||
const std::size_t end_tag_start =
|
// bare text, so we need to wrap it in mtext tags
|
||||||
inset_contents.find(tag_name, tag_name_end + 1);
|
// make an mtext element
|
||||||
const std::size_t end_tag = inset_contents.find('>', end_tag_start);
|
QDomElement wrapper = xml.createElement(toqstr(ms.namespacedTag("mtext")));
|
||||||
|
// put the mtext element in the document right before the text
|
||||||
parts.emplace_back(inset_contents.substr(0, end_tag + 1));
|
docElem.insertBefore(wrapper,n);
|
||||||
inset_contents = inset_contents.substr(end_tag + 1);
|
// move the text node inside the mtext element (this has the side
|
||||||
|
// effect of removing it from where it was as a child of the root)
|
||||||
|
wrapper.appendChild(n);
|
||||||
|
n = wrapper.nextSibling();
|
||||||
|
} else {
|
||||||
|
// if the text is null, then we have something besides a text
|
||||||
|
// element (i.e. a tag), so we don't need to do anything and just
|
||||||
|
// move onto the next child
|
||||||
|
n = n.nextSibling();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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);
|
ms << MTag("mrow", attributes);
|
||||||
for (std::size_t i = 0; i < parts.size(); i += 2) {
|
docstring interior = qstring_to_ucs4(xml.toString(-1));
|
||||||
ms << MTag("mtext")
|
ms << interior.substr(6,interior.length()-13); // chop off the initial <root> and final </root> tags
|
||||||
<< parts[i]
|
|
||||||
<< ETag("mtext");
|
|
||||||
if (parts.size() > i + 1)
|
|
||||||
ms << parts[i + 1];
|
|
||||||
}
|
|
||||||
ms << ETag("mrow");
|
ms << ETag("mrow");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user