summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx11
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx180
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx5
3 files changed, 125 insertions, 71 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 49d11cf3be87..9bbbedf64f9c 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3418,11 +3418,12 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
// If the paragraph contains only the section properties and it has
// no runs, we should not create a paragraph for it in Writer, unless that would remove the whole section.
SectionPropertyMap* pSectionContext = m_pImpl->GetSectionContext();
- bool bRemove = !m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr()
- && !bSingleParagraphAfterRedline
- && !m_pImpl->GetIsDummyParaAddedForTableInSection()
- && !( pSectionContext && pSectionContext->GetBreakType() != -1 && pContext && pContext->isSet(PROP_BREAK_TYPE) )
- && !m_pImpl->GetIsPreviousParagraphFramed();
+ bool bRemove = (!m_pImpl->GetParaChanged() && m_pImpl->GetRemoveThisPara()) ||
+ (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr()
+ && !bSingleParagraphAfterRedline
+ && !m_pImpl->GetIsDummyParaAddedForTableInSection()
+ && !( pSectionContext && pSectionContext->GetBreakType() != -1 && pContext && pContext->isSet(PROP_BREAK_TYPE) )
+ && !m_pImpl->GetIsPreviousParagraphFramed());
const bool bNoNumbering = bRemove || (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr() && bSingleParagraph);
PropertyMapPtr xContext = bNoNumbering ? m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) : PropertyMapPtr();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 88b985bcfc0b..b938343bb7ef 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -41,6 +41,8 @@
#include <com/sun/star/text/ChapterFormat.hpp>
#include <com/sun/star/text/FilenameDisplayFormat.hpp>
#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
+#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
#include <com/sun/star/text/XFootnote.hpp>
#include <com/sun/star/text/XLineNumberingProperties.hpp>
#include <com/sun/star/style/XStyle.hpp>
@@ -96,6 +98,7 @@
#include <unotools/configmgr.hxx>
#include <unotools/mediadescriptor.hxx>
#include <tools/diagnose_ex.h>
+#include <tools/lineend.hxx>
#include <sal/log.hxx>
@@ -1800,6 +1803,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
SetIsPreviousParagraphFramed(false);
m_bParaChanged = false;
+ m_bRemoveThisParagraph = false;
if( !IsInHeaderFooter() && !IsInShape() && (!pParaContext || !pParaContext->IsFrameMode()) )
{ // If the paragraph is in a frame, shape or header/footer, it's not a paragraph of the section itself.
SetIsFirstParagraphInSection(false);
@@ -1883,7 +1887,7 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, const Proper
uno::Reference< text::XTextCursor > xTOCTextCursor = xTextAppend->getEnd()->getText( )->createTextCursor( );
assert(xTOCTextCursor.is());
xTOCTextCursor->gotoEnd(false);
- if (m_bStartIndex || m_bStartBibliography || m_bStartGenericField)
+ if (m_bStartGenericField)
xTOCTextCursor->goLeft(1, false);
xTextRange = xTextAppend->insertTextPortion(rString, aValues, xTOCTextCursor);
SAL_WARN_IF(!xTextRange.is(), "writerfilter.dmapper", "insertTextPortion failed");
@@ -2128,8 +2132,38 @@ uno::Reference< beans::XPropertySet > DomainMapper_Impl::appendTextSectionAfter(
xCursor->gotoEnd( true );
//the paragraph after this new section is already inserted
xCursor->goLeft(1, true);
+ css::uno::Reference<css::text::XTextRange> xTextRange(xCursor, css::uno::UNO_QUERY_THROW);
+
+ if (css::uno::Reference<css::text::XDocumentIndexesSupplier> xIndexSupplier{
+ GetTextDocument(), css::uno::UNO_QUERY })
+ {
+ css::uno::Reference<css::text::XTextRangeCompare> xCompare(
+ xTextAppend, css::uno::UNO_QUERY);
+ const auto xIndexAccess = xIndexSupplier->getDocumentIndexes();
+ for (sal_Int32 i = xIndexAccess->getCount(); i > 0; --i)
+ {
+ if (css::uno::Reference<css::text::XDocumentIndex> xIndex{
+ xIndexAccess->getByIndex(i - 1), css::uno::UNO_QUERY })
+ {
+ const auto xIndexTextRange = xIndex->getAnchor();
+ if (xCompare->compareRegionStarts(xTextRange, xIndexTextRange) == 0
+ && xCompare->compareRegionEnds(xTextRange, xIndexTextRange) == 0)
+ {
+ // The boundaries coincide with an index: trying to attach a section
+ // to the range will insert the section inside the index. goRight will
+ // extend the range outside of the index, so that created section will
+ // be around it. Alternatively we could return index section itself
+ // instead : xRet.set(xIndex, uno::UNO_QUERY) - to set its properties,
+ // like columns/fill.
+ xCursor->goRight(1, true);
+ break;
+ }
+ }
+ }
+ }
+
uno::Reference< text::XTextContent > xSection( m_xTextFactory->createInstance("com.sun.star.text.TextSection"), uno::UNO_QUERY_THROW );
- xSection->attach( uno::Reference< text::XTextRange >( xCursor, uno::UNO_QUERY_THROW) );
+ xSection->attach( xTextRange );
xRet.set(xSection, uno::UNO_QUERY );
}
catch(const uno::Exception&)
@@ -4125,10 +4159,12 @@ OUString DomainMapper_Impl::extractTocTitle()
else
xCursor->gotoEnd( true );
- //the paragraph after this new section is already inserted
- xCursor->goLeft(1, true);
+ // the paragraph after this new section might have been already inserted
+ OUString sResult = xCursor->getString();
+ if (sResult.endsWith(SAL_NEWLINE_STRING))
+ sResult = sResult.copy(0, sResult.getLength() - SAL_N_ELEMENTS(SAL_NEWLINE_STRING) + 1);
- return xCursor->getString();
+ return sResult;
}
catch(const uno::Exception&)
{
@@ -4137,12 +4173,48 @@ OUString DomainMapper_Impl::extractTocTitle()
return OUString();
}
+css::uno::Reference<css::beans::XPropertySet>
+DomainMapper_Impl::StartIndexSectionChecked(const OUString& sServiceName)
+{
+ if (m_bParaChanged)
+ {
+ finishParagraph(GetTopContextOfType(CONTEXT_PARAGRAPH), false); // resets m_bParaChanged
+ PopProperties(CONTEXT_PARAGRAPH);
+ PushProperties(CONTEXT_PARAGRAPH);
+ SetIsFirstRun(true);
+ // The first paragraph of the index that is continuation of just finished one needs to be
+ // removed when finished (unless more content will arrive, which will set m_bParaChanged)
+ m_bRemoveThisParagraph = true;
+ }
+ const auto& xTextAppend = GetTopTextAppend();
+ const auto xTextRange = xTextAppend->getEnd();
+ const auto xRet = createSectionForRange(xTextRange, xTextRange, sServiceName, false);
+ if (!m_aTextAppendStack.top().xInsertPosition)
+ {
+ try
+ {
+ m_bStartedTOC = true;
+ uno::Reference<text::XTextCursor> xTOCTextCursor
+ = xTextRange->getText()->createTextCursor();
+ assert(xTOCTextCursor.is());
+ xTOCTextCursor->gotoEnd(false);
+ mxTOCTextCursor = xTOCTextCursor;
+ m_aTextAppendStack.push(TextAppendContext(xTextAppend, xTOCTextCursor));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("writerfilter.dmapper",
+ "DomainMapper_Impl::StartIndexSectionChecked:");
+ }
+ }
+ return xRet;
+}
+
void DomainMapper_Impl::handleToc
(const FieldContextPtr& pContext,
const OUString & sTOCServiceName)
{
OUString sValue;
- m_bStartTOC = true;
if (IsInHeaderFooter())
m_bStartTOCHeaderFooter = true;
bool bTableOfFigures = false;
@@ -4259,34 +4331,21 @@ void DomainMapper_Impl::handleToc
if (m_xTextFactory.is() && ! m_aTextAppendStack.empty())
{
+ const auto& xTextAppend = GetTopTextAppend();
if (aTocTitle.isEmpty() || bTableOfFigures)
{
// reset marker of the TOC title
- m_xStdEntryStart = uno::Reference< text::XTextRange >();
-
- xTOC.set(
- m_xTextFactory->createInstance
- ( bTableOfFigures ?
- "com.sun.star.text.IllustrationsIndex"
- : sTOCServiceName),
- uno::UNO_QUERY_THROW);
-
- OUString const sMarker("Y");
- //insert index
- uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
- uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
- if (xTextAppend.is())
- {
- uno::Reference< text::XTextCursor > xCrsr = xTextAppend->getText()->createTextCursor();
- uno::Reference< text::XText > xText = xTextAppend->getText();
- if(xCrsr.is() && xText.is())
- {
- xCrsr->gotoEnd(false);
- xText->insertString(xCrsr, sMarker, false);
- xText->insertTextContent(uno::Reference< text::XTextRange >( xCrsr, uno::UNO_QUERY_THROW ), xToInsert, false);
- xTOCMarkerCursor = xCrsr;
- }
- }
+ m_xStdEntryStart.clear();
+
+ // Create section before setting m_bStartTOC: finishing paragraph
+ // inside StartIndexSectionChecked could do the wrong thing otherwise
+ xTOC = StartIndexSectionChecked(bTableOfFigures ? "com.sun.star.text.IllustrationsIndex"
+ : sTOCServiceName);
+
+ const auto xTextCursor = xTextAppend->getText()->createTextCursor();
+ if (xTextCursor)
+ xTextCursor->gotoEnd(false);
+ xTOCMarkerCursor = xTextCursor;
}
else
{
@@ -4295,7 +4354,6 @@ void DomainMapper_Impl::handleToc
xTOC = createSectionForRange(m_xStdEntryStart, xTextRangeEndOfTocHeader, sTOCServiceName, false);
// init [xTOCMarkerCursor]
- uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend;
uno::Reference< text::XText > xText = xTextAppend->getText();
uno::Reference< text::XTextCursor > xCrsr = xText->createTextCursor();
xTOCMarkerCursor = xCrsr;
@@ -4306,6 +4364,8 @@ void DomainMapper_Impl::handleToc
}
}
+ m_bStartTOC = true;
+
if (xTOC.is())
xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::makeAny(aTocTitle));
@@ -4443,14 +4503,12 @@ void DomainMapper_Impl::handleBibliography
(const FieldContextPtr& pContext,
const OUString & sTOCServiceName)
{
- uno::Reference< beans::XPropertySet > xTOC;
+ // Create section before setting m_bStartTOC and m_bStartBibliography: finishing paragraph
+ // inside StartIndexSectionChecked could do the wrong thing otherwise
+ const auto xTOC = StartIndexSectionChecked(sTOCServiceName);
m_bStartTOC = true;
m_bStartBibliography = true;
- if (m_xTextFactory.is())
- xTOC.set(
- m_xTextFactory->createInstance(
- sTOCServiceName),
- uno::UNO_QUERY_THROW);
+
if (xTOC.is())
xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::makeAny(OUString()));
@@ -4465,18 +4523,15 @@ void DomainMapper_Impl::handleIndex
(const FieldContextPtr& pContext,
const OUString & sTOCServiceName)
{
- uno::Reference< beans::XPropertySet > xTOC;
+ // Create section before setting m_bStartTOC and m_bStartIndex: finishing paragraph
+ // inside StartIndexSectionChecked could do the wrong thing otherwise
+ const auto xTOC = StartIndexSectionChecked(sTOCServiceName);
+
m_bStartTOC = true;
m_bStartIndex = true;
OUString sValue;
OUString sIndexEntryType = "I"; // Default value for field flag '\f' is 'I'.
-
- if (m_xTextFactory.is())
- xTOC.set(
- m_xTextFactory->createInstance(
- sTOCServiceName),
- uno::UNO_QUERY_THROW);
if (xTOC.is())
{
xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::makeAny(OUString()));
@@ -5628,33 +5683,26 @@ void DomainMapper_Impl::PopFieldContext()
uno::Reference< text::XTextContent > xToInsert( pContext->GetTOC(), uno::UNO_QUERY );
if( xToInsert.is() )
{
- if(xTOCMarkerCursor.is() || m_bStartIndex || m_bStartBibliography)
+ if (m_bStartedTOC || m_bStartIndex || m_bStartBibliography)
{
- if (m_bStartIndex || m_bStartBibliography)
- {
- if (mxTOCTextCursor.is())
- {
- mxTOCTextCursor->goLeft(1,true);
- mxTOCTextCursor->setString(OUString());
- }
- xTextAppend->finishParagraph( uno::Sequence< beans::PropertyValue >() );
- }
- else
+ // inside Std, last empty paragraph is also part of index
+ if (!m_bParaChanged && !m_xStdEntryStart)
{
- if (!m_xStdEntryStart.is())
- {
- xTOCMarkerCursor->goLeft(1,true);
- xTOCMarkerCursor->setString(OUString());
- xTOCMarkerCursor->goLeft(1,true);
- xTOCMarkerCursor->setString(OUString());
- }
+ // End of index is the first item on a new paragraph - this paragraph
+ // should not be part of index
+ auto xCursor
+ = xTextAppend->createTextCursorByRange(xTextAppend->getEnd());
+ xCursor->gotoEnd(false);
+ xCursor->goLeft(1, true);
+ // delete
+ xCursor->setString(OUString());
+ // But a new paragraph should be started after the index instead
+ xTextAppend->finishParagraph(css::beans::PropertyValues());
}
- }
- if (m_bStartedTOC || m_bStartIndex || m_bStartBibliography)
- {
m_bStartedTOC = false;
m_aTextAppendStack.pop();
m_bTextInserted = false;
+ m_bParaChanged = true; // the paragraph must stay anyway
}
m_bStartTOC = false;
m_bStartIndex = false;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 53cf5e20a140..8780bc1d51fd 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -546,6 +546,8 @@ private:
bool m_bSdt;
bool m_bIsFirstRun;
bool m_bIsOutsideAParagraph;
+ /// This is a continuation of already finished paragraph - e.g., first in an index section
+ bool m_bRemoveThisParagraph = false;
css::uno::Reference< css::text::XTextCursor > xTOCMarkerCursor;
css::uno::Reference< css::text::XTextCursor > mxTOCTextCursor;
@@ -652,6 +654,7 @@ public:
/// Getter method for m_bSdt.
bool GetSdt() const { return m_bSdt;}
bool GetParaChanged() const { return m_bParaChanged;}
+ bool GetRemoveThisPara() const { return m_bRemoveThisParagraph; }
void deferBreak( BreakType deferredBreakType );
bool isBreakDeferred( BreakType deferredBreakType );
@@ -1047,6 +1050,8 @@ public:
private:
void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType eType);
+ // Start a new index section; if needed, finish current paragraph
+ css::uno::Reference<css::beans::XPropertySet> StartIndexSectionChecked(const OUString& sServiceName);
std::vector<css::uno::Reference< css::drawing::XShape > > m_vTextFramesForChaining ;
/// Current paragraph had at least one field in it.
bool m_bParaHadField;