Quelle txtparai.cxx
Sprache: C
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include "txtparai.hxx"
#include <string_view>
#include "XMLFootnoteImportContext.hxx"
#include "XMLTextFrameContext.hxx"
#include "xmlimp.hxx"
#include <sal/log.hxx>
using namespace com::sun::star;
namespace
{
/// Looks for rName in rStyles and fills rPropertyList based on that
/// (rAutomaticStyles and rNamedStyles are a list of possible parents).
void FillStyle(
const OUString& rName, std::map<OUString, librevenge::RVNGPropertyL
ist>& rStyles,
std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
librevenge::RVNGPropertyList& rPropertyList)
{
auto itStyle = rStyles.find(rName);
if (itStyle == rStyles.end())
return ;
const librevenge::RVNGPropertyList& rStyle = itStyle->second;
if (rStyle["style:parent-style-name" ])
{
// The style has a parent.
OUString aParent = OStringToOUString(rStyle["style:parent-style-name" ]->getStr().cstr(),
RTL_TEXTENCODING_UTF8);
if (!aParent.isEmpty())
writerperfect::exp::FillStyles(aParent, rAutomaticStyles, rNamedStyles, rPropertyList);
}
// Apply properties from named style.
librevenge::RVNGPropertyList::Iter itProp(rStyle);
for (itProp.rewind(); itProp.next();)
{
if (std::string_view("style:parent-style-name" ) != itProp.key())
rPropertyList.insert(itProp.key(), itProp()->clone());
}
}
}
namespace writerperfect::exp
{
namespace
{
/// Handler for <text:sequence>.
class XMLTextSequenceContext : public XMLImportContext
{
public :
XMLTextSequenceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
void SAL_CALL characters(const OUString& rChars) override;
private :
librevenge::RVNGPropertyList m_aPropertyList;
};
}
XMLTextSequenceContext::XMLTextSequenceContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
void XMLTextSequenceContext::characters(const OUString& rChars)
{
GetImport().GetGenerator().openSpan(m_aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <text:span>.
class XMLSpanContext : public XMLImportContext
{
public :
XMLSpanContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
rtl::Reference<XMLImportContext>
CreateChildContext(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL characters(const OUString& rChars) override;
private :
librevenge::RVNGPropertyList m_aPropertyList;
};
}
XMLSpanContext::XMLSpanContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
rtl::Reference<XMLImportContext> XMLSpanContext::CreateChildContext(
const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}
void XMLSpanContext::startElement(
const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
{
const OUString aAttributeName = xAttribs->getNameByIndex(i);
const OUString aAttributeValue = xAttribs->getValueByIndex(i);
if (aAttributeName == "text:style-name" )
FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
GetImport().GetTextStyles(), m_aPropertyList);
else
{
OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
m_aPropertyList.insert(sName.getStr(), sValue.getStr());
}
}
}
void XMLSpanContext::characters(const OUString& rChars)
{
GetImport().GetGenerator().openSpan(m_aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <text:ruby>.
class XMLRubyContext : public XMLImportContext
{
public :
XMLRubyContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
rtl::Reference<XMLImportContext>
CreateChildContext(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL endElement(const OUString& rName) override;
void SetRubyText(const OUString& rRubyText) { m_sRubyText = rRubyText; }
OUString& GetRubyBase() { return m_sRubyBase; }
private :
OUString m_sRubyText;
OUString m_sRubyBase;
librevenge::RVNGPropertyList m_aPropertyList;
};
/// Handler for <text:ruby-text>.
class XMLRubyTextContext : public XMLImportContext
{
public :
XMLRubyTextContext(XMLImport& rImport, XMLRubyContext& rParent)
: XMLImportContext(rImport)
, m_rParent(rParent)
{
}
void SAL_CALL characters(const OUString& rChars) override { m_rParent.SetRubyText(rChars); }
private :
XMLRubyContext& m_rParent;
};
/// Handler for <text:ruby-base>.
class XMLRubyBaseContext : public XMLImportContext
{
public :
XMLRubyBaseContext(XMLImport& rImport, XMLRubyContext& rParent)
: XMLImportContext(rImport)
, m_rParent(rParent)
{
}
void SAL_CALL characters(const OUString& rChars) override { m_rParent.GetRubyBase() += rChars; }
private :
XMLRubyContext& m_rParent;
};
}
XMLRubyContext::XMLRubyContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
rtl::Reference<XMLImportContext> XMLRubyContext::CreateChildContext(
const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
if (rName == "text:ruby-base" )
return new XMLRubyBaseContext(GetImport(), *this );
if (rName == "text:ruby-text" )
return new XMLRubyTextContext(GetImport(), *this );
return nullptr;
}
void XMLRubyContext::endElement(const OUString& /*rName*/)
{
OString sRubyText = OUStringToOString(m_sRubyText, RTL_TEXTENCODING_UTF8);
OString sRubyBase = OUStringToOString(m_sRubyBase, RTL_TEXTENCODING_UTF8);
if (sRubyText.getLength())
m_aPropertyList.insert("text:ruby-text" , sRubyText.getStr());
GetImport().GetGenerator().openSpan(m_aPropertyList);
GetImport().GetGenerator().insertText(sRubyBase.getStr());
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Base class for contexts that represent a single character only.
class XMLCharContext : public XMLImportContext
{
public :
XMLCharContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
const librevenge::RVNGPropertyList& GetPropertyList() const { return m_aPropertyList; }
private :
librevenge::RVNGPropertyList m_aPropertyList;
};
}
XMLCharContext::XMLCharContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
namespace
{
/// Handler for <text:line-break>.
class XMLLineBreakContext : public XMLCharContext
{
public :
XMLLineBreakContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}
XMLLineBreakContext::XMLLineBreakContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLCharContext(rImport, rPropertyList)
{
}
void XMLLineBreakContext::startElement(
const OUString& /*rName*/,
const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
GetImport().GetGenerator().openSpan(GetPropertyList());
GetImport().GetGenerator().insertLineBreak();
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <text:s>.
class XMLSpaceContext : public XMLCharContext
{
public :
XMLSpaceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}
XMLSpaceContext::XMLSpaceContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLCharContext(rImport, rPropertyList)
{
}
void XMLSpaceContext::startElement(
const OUString& /*rName*/,
const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
GetImport().GetGenerator().openSpan(GetPropertyList());
GetImport().GetGenerator().insertSpace();
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <text:tab>.
class XMLTabContext : public XMLCharContext
{
public :
XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}
XMLTabContext::XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
: XMLCharContext(rImport, rPropertyList)
{
}
void XMLTabContext::startElement(
const OUString& /*rName*/,
const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
GetImport().GetGenerator().openSpan(GetPropertyList());
GetImport().GetGenerator().insertTab();
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <draw:a>.
class XMLTextFrameHyperlinkContext : public XMLImportContext
{
public :
XMLTextFrameHyperlinkContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList);
rtl::Reference<XMLImportContext>
CreateChildContext(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL endElement(const OUString& rName) override;
void SAL_CALL characters(const OUString& rChars) override;
private :
librevenge::RVNGPropertyList m_aPropertyList;
PopupState m_ePopupState = PopupState::NONE;
};
}
XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
rtl::Reference<XMLImportContext> XMLTextFrameHyperlinkContext::CreateChildContext(
const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}
void XMLTextFrameHyperlinkContext::startElement(
const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
librevenge::RVNGPropertyList aPropertyList;
for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
{
const OUString aAttributeName = xAttribs->getNameByIndex(i);
const OUString aAttributeValue = xAttribs->getValueByIndex(i);
if (aAttributeName == "text:style-name" )
// This affects the nested span's properties.
FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
GetImport().GetTextStyles(), m_aPropertyList);
else
{
if (aAttributeName == "xlink:href" )
{
m_ePopupState = GetImport().FillPopupData(aAttributeValue, aPropertyList);
if (m_ePopupState != PopupState::NotConsumed)
continue ;
}
// This affects the link's properties.
OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
aPropertyList.insert(sName.getStr(), sValue.getStr());
}
}
if (m_ePopupState != PopupState::Ignore)
GetImport().GetGenerator().openLink(aPropertyList);
}
void XMLTextFrameHyperlinkContext::endElement(const OUString& /*rName*/)
{
if (m_ePopupState != PopupState::Ignore)
GetImport().GetGenerator().closeLink();
}
void XMLTextFrameHyperlinkContext::characters(const OUString& rChars)
{
GetImport().GetGenerator().openSpan(m_aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
GetImport().GetGenerator().closeSpan();
}
namespace
{
/// Handler for <text:a>.
class XMLHyperlinkContext : public XMLImportContext
{
public :
XMLHyperlinkContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
rtl::Reference<XMLImportContext>
CreateChildContext(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL
startElement(const OUString& rName,
const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
void SAL_CALL endElement(const OUString& rName) override;
void SAL_CALL characters(const OUString& rChars) override;
private :
librevenge::RVNGPropertyList m_aPropertyList;
PopupState m_ePopupState = PopupState::NONE;
};
}
XMLHyperlinkContext::XMLHyperlinkContext(XMLImport& rImport,
const librevenge::RVNGPropertyList& rPropertyList)
: XMLImportContext(rImport)
{
// Inherit properties from parent.
librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
for (itProp.rewind(); itProp.next();)
m_aPropertyList.insert(itProp.key(), itProp()->clone());
}
rtl::Reference<XMLImportContext> XMLHyperlinkContext::CreateChildContext(
const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}
void XMLHyperlinkContext::startElement(
const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
librevenge::RVNGPropertyList aPropertyList;
for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
{
const OUString aAttributeName = xAttribs->getNameByIndex(i);
const OUString aAttributeValue = xAttribs->getValueByIndex(i);
if (aAttributeName == "text:style-name" )
// This affects the nested span's properties.
FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
GetImport().GetTextStyles(), m_aPropertyList);
else
{
if (aAttributeName == "xlink:href" )
{
m_ePopupState = GetImport().FillPopupData(aAttributeValue, aPropertyList);
if (m_ePopupState != PopupState::NotConsumed)
continue ;
}
// This affects the link's properties.
OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
aPropertyList.insert(sName.getStr(), sValue.getStr());
}
}
if (m_ePopupState != PopupState::Ignore)
GetImport().GetGenerator().openLink(aPropertyList);
}
void XMLHyperlinkContext::endElement(const OUString& /*rName*/)
{
if (m_ePopupState != PopupState::Ignore)
GetImport().GetGenerator().closeLink();
}
void XMLHyperlinkContext::characters(const OUString& rChars)
{
GetImport().GetGenerator().openSpan(m_aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
GetImport().GetGenerator().closeSpan();
}
XMLParaContext::XMLParaContext(XMLImport& rImport, bool bTopLevel)
: XMLImportContext(rImport)
, m_bTopLevel(bTopLevel)
{
}
rtl::Reference<XMLImportContext> XMLParaContext::CreateChildContext(
const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
if (rName == "text:a" )
return new XMLHyperlinkContext(GetImport(), m_aTextPropertyList);
if (rName == "draw:a" )
return new XMLTextFrameHyperlinkContext(GetImport(), m_aTextPropertyList);
if (rName == "text:ruby" )
return new XMLRubyContext(GetImport(), m_aTextPropertyList);
return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aTextPropertyList);
}
void XMLParaContext::startElement(
const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
librevenge::RVNGPropertyList aPropertyList;
for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
{
const OUString aAttributeName = xAttribs->getNameByIndex(i);
const OUString aAttributeValue = xAttribs->getValueByIndex(i);
if (aAttributeName == "text:style-name" )
{
m_aStyleName = aAttributeValue;
FillStyles(m_aStyleName, GetImport().GetAutomaticParagraphStyles(),
GetImport().GetParagraphStyles(), aPropertyList);
FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(),
GetImport().GetTextStyles(), m_aTextPropertyList);
if (m_bTopLevel)
GetImport().HandlePageSpan(aPropertyList);
}
else
{
OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
aPropertyList.insert(sName.getStr(), sValue.getStr());
}
}
GetImport().GetGenerator().openParagraph(aPropertyList);
}
void XMLParaContext::endElement(const OUString& /*rName*/)
{
GetImport().GetGenerator().closeParagraph();
}
void XMLParaContext::characters(const OUString& rChars)
{
librevenge::RVNGPropertyList aPropertyList;
if (!m_aStyleName.isEmpty())
FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(), GetImport().GetTextStyles(),
aPropertyList);
GetImport().GetGenerator().openSpan(aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
GetImport().GetGenerator().closeSpan();
}
rtl::Reference<XMLImportContext>
CreateParagraphOrSpanChildContext(XMLImport& rImport, const OUString& rName,
const librevenge::RVNGPropertyList& rTextPropertyList)
{
if (rName == "text:span" )
return new XMLSpanContext(rImport, rTextPropertyList);
if (rName == "text:line-break" )
return new XMLLineBreakContext(rImport, rTextPropertyList);
if (rName == "text:s" )
return new XMLSpaceContext(rImport, rTextPropertyList);
if (rName == "text:tab" )
return new XMLTabContext(rImport, rTextPropertyList);
if (rName == "draw:frame" )
return new XMLTextFrameContext(rImport);
if (rName == "text:sequence" )
return new XMLTextSequenceContext(rImport, rTextPropertyList);
if (rName == "text:note" )
return new XMLFootnoteImportContext(rImport);
SAL_WARN("writerperfect" , "CreateParagraphOrSpanChildContext: unhandled " << rName);
return nullptr;
}
void FillStyles(const OUString& rName,
std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
librevenge::RVNGPropertyList& rPropertyList)
{
FillStyle(rName, rAutomaticStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
FillStyle(rName, rNamedStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
}
} // namespace writerperfect
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=97 H=96 G=96
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland
2026-04-04