parent
583d3ad9dd
commit
5a3da6f4a3
@ -0,0 +1,357 @@
|
||||
From 153993292cc9f11fed8fcba8de45b0c46d5e0ef2 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Stahl <mstahl@redhat.com>
|
||||
Date: Thu, 27 Feb 2014 23:48:59 +0100
|
||||
Subject: [PATCH] RTF import: fix spurious page breaks at doc end (related:
|
||||
rhbz#1065629)
|
||||
|
||||
When a document ends with \sect it's possible that a spurious page break
|
||||
is created. In fact the spurious page break is always created by the
|
||||
RTF importer, sometimes it is deleted again by
|
||||
DomainMapper_Impl::RemoveLastParagraph() and sometimes not.
|
||||
|
||||
It is created because on the final \sect RTFDocumentImpl::sectBreak()
|
||||
still calls startSectionGroup(), and the popState() for the \rtf1 group
|
||||
then calls sectBreak() another time.
|
||||
|
||||
To prevent this, do not call startSectionGroup() from sectBreak() but
|
||||
instead from setNeedSect(), and ensure that it is called as soon as
|
||||
anything after \sect is read.
|
||||
|
||||
One unit test fails because the \page is not handled properly: the
|
||||
conversion to \skbpage \sect \skbnone is not correct, because the \skb*
|
||||
keywords are an exception and affect the \sect that precedes them, not
|
||||
the following one; sending the \skbpage later unfortunately requires
|
||||
additional cleanup later.
|
||||
|
||||
(cherry picked from commit e3f254ab8211fbab7541cde2100a35c875b0c240)
|
||||
|
||||
RTF import: add unit test for page break in continuous section
|
||||
|
||||
(cherry picked from commit f03218f43e8c25c2e136d364455f3cdaf95362b6)
|
||||
|
||||
RTF import: fix paragraphs in header/footer
|
||||
|
||||
(cherry picked from commit 74b3f4f00766d199df3b017d056cf7a00ae52988)
|
||||
|
||||
Change-Id: I3c1a3bceb2c8b75bbecdc748170562451ce5f5c3
|
||||
Reviewed-on: https://gerrit.libreoffice.org/8439
|
||||
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
||||
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
||||
---
|
||||
.../rtfimport/data/cont-section-pagebreak.rtf | 16 +++++
|
||||
sw/qa/extras/rtfimport/data/footer-para.rtf | 5 ++
|
||||
sw/qa/extras/rtfimport/rtfimport.cxx | 42 +++++++++++++
|
||||
writerfilter/source/rtftok/rtfdocumentimpl.cxx | 71 +++++++++++++++-------
|
||||
writerfilter/source/rtftok/rtfdocumentimpl.hxx | 3 +
|
||||
5 files changed, 116 insertions(+), 21 deletions(-)
|
||||
create mode 100644 sw/qa/extras/rtfimport/data/cont-section-pagebreak.rtf
|
||||
create mode 100644 sw/qa/extras/rtfimport/data/footer-para.rtf
|
||||
|
||||
diff --git a/sw/qa/extras/rtfimport/data/cont-section-pagebreak.rtf b/sw/qa/extras/rtfimport/data/cont-section-pagebreak.rtf
|
||||
new file mode 100644
|
||||
index 0000000..888dc2d
|
||||
--- /dev/null
|
||||
+++ b/sw/qa/extras/rtfimport/data/cont-section-pagebreak.rtf
|
||||
@@ -0,0 +1,16 @@
|
||||
+{\rtf1 \ansi
|
||||
+\fet0 \ftnbj \paperw11905 \paperh16837 \margt2267 \margb1133 \margl1417 \margr1417
|
||||
+
|
||||
+\sectd
|
||||
+\sbknone
|
||||
+FIRST
|
||||
+\par
|
||||
+\sect
|
||||
+SECOND
|
||||
+\par
|
||||
+\page
|
||||
+\sect
|
||||
+THIRD
|
||||
+\par
|
||||
+\sect
|
||||
+}
|
||||
diff --git a/sw/qa/extras/rtfimport/data/footer-para.rtf b/sw/qa/extras/rtfimport/data/footer-para.rtf
|
||||
new file mode 100644
|
||||
index 0000000..28863b2
|
||||
--- /dev/null
|
||||
+++ b/sw/qa/extras/rtfimport/data/footer-para.rtf
|
||||
@@ -0,0 +1,5 @@
|
||||
+{\rtf1\fbidis\ansi\ansicpg0\uc0\deff0\deflang0\deflangfe0\paperw11905\paperh16838\margl1200\margr1200\margt1200\margb1200\headery600\footery600\viewscale100\viewzk0\titlepg
|
||||
+{\fonttbl{\f0\fnil Arial;}}
|
||||
+{\footerf
|
||||
+\pard\s0\fi0\li0\qc\ri0\sb0\sa0\itap0 \plain \f0\fs18 All Rights Reserved.\par}
|
||||
+\pard\par}
|
||||
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
|
||||
index 9504027..73bf749 100644
|
||||
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
|
||||
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <com/sun/star/drawing/LineStyle.hpp>
|
||||
#include <com/sun/star/graphic/GraphicType.hpp>
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
+#include <com/sun/star/style/BreakType.hpp>
|
||||
#include <com/sun/star/style/CaseMap.hpp>
|
||||
#include <com/sun/star/style/LineSpacing.hpp>
|
||||
#include <com/sun/star/style/LineSpacingMode.hpp>
|
||||
@@ -1413,6 +1414,47 @@ DECLARE_RTFIMPORT_TEST(testNestedTable, "rhbz1065629.rtf")
|
||||
getProperty<table::BorderLine2>(xCell, "RightBorder"));
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xffffffff),
|
||||
getProperty<sal_Int32>(xCell, "BackColor"));
|
||||
+
|
||||
+ // \sect at the end resulted in spurious page break
|
||||
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
|
||||
+}
|
||||
+
|
||||
+DECLARE_RTFIMPORT_TEST(testContSectionPageBreak, "cont-section-pagebreak.rtf")
|
||||
+{
|
||||
+ uno::Reference<text::XTextRange> xParaSecond = getParagraph(2);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("SECOND"), xParaSecond->getString());
|
||||
+ CPPUNIT_ASSERT_EQUAL(style::BreakType_NONE,
|
||||
+ getProperty<style::BreakType>(xParaSecond, "BreakType"));
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(""),
|
||||
+ getProperty<OUString>(xParaSecond, "PageDescName"));
|
||||
+ // actually not sure how many paragraph there should be between
|
||||
+ // SECOND and THIRD - important is that the page break is on there
|
||||
+ uno::Reference<text::XTextRange> xParaNext = getParagraph(3);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(""), xParaNext->getString());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("Converted1"),
|
||||
+ getProperty<OUString>(xParaNext, "PageDescName"));
|
||||
+ uno::Reference<text::XTextRange> xParaThird = getParagraph(4);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("THIRD"), xParaThird->getString());
|
||||
+ CPPUNIT_ASSERT_EQUAL(style::BreakType_NONE,
|
||||
+ getProperty<style::BreakType>(xParaThird, "BreakType"));
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(""),
|
||||
+ getProperty<OUString>(xParaThird, "PageDescName"));
|
||||
+
|
||||
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
|
||||
+}
|
||||
+
|
||||
+DECLARE_RTFIMPORT_TEST(testFooterPara, "footer-para.rtf")
|
||||
+{
|
||||
+ // check that paragraph properties in footer are imported
|
||||
+ uno::Reference<text::XText> xFooterText =
|
||||
+ getProperty< uno::Reference<text::XText> >(
|
||||
+ getStyles("PageStyles")->getByName("First Page"), "FooterText");
|
||||
+ uno::Reference<text::XTextContent> xParagraph =
|
||||
+ getParagraphOrTable(1, xFooterText);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("All Rights Reserved."),
|
||||
+ uno::Reference<text::XTextRange>(xParagraph, uno::UNO_QUERY)->getString());
|
||||
+ CPPUNIT_ASSERT_EQUAL((sal_Int16)style::ParagraphAdjust_CENTER,
|
||||
+ getProperty</*style::ParagraphAdjust*/sal_Int16>(xParagraph, "ParaAdjust"));
|
||||
}
|
||||
|
||||
DECLARE_RTFIMPORT_TEST(testCp1000016, "hello.rtf")
|
||||
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
|
||||
index d5e7843..0dc20b0 100644
|
||||
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
|
||||
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
|
||||
@@ -279,7 +279,8 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
|
||||
m_aHexBuffer(),
|
||||
m_bMathNor(false),
|
||||
m_bIgnoreNextContSectBreak(false),
|
||||
- m_bNeedSect(true),
|
||||
+ m_nResetBreakOnSectBreak(static_cast<RTFKeyword>(-1)),
|
||||
+ m_bNeedSect(false), // done by checkFirstRun
|
||||
m_bWasInFrame(false),
|
||||
m_bHadPicture(false),
|
||||
m_bHadSect(false),
|
||||
@@ -392,16 +393,15 @@ void RTFDocumentImpl::checkFirstRun()
|
||||
writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aSettingsTableEntries));
|
||||
Mapper().table(NS_ooxml::LN_settings_settings, pTable);
|
||||
// start initial paragraph
|
||||
- if (!m_pSuperstream)
|
||||
- Mapper().startSectionGroup();
|
||||
- Mapper().startParagraphGroup();
|
||||
+ m_bFirstRun = false;
|
||||
+ assert(!m_bNeedSect);
|
||||
+ setNeedSect(); // first call that succeeds
|
||||
|
||||
// set the requested default font, if there are none
|
||||
RTFValue::Pointer_t pFont = m_aDefaultState.aCharacterSprms.find(NS_sprm::LN_CRgFtc0);
|
||||
RTFValue::Pointer_t pCurrentFont = m_aStates.top().aCharacterSprms.find(NS_sprm::LN_CRgFtc0);
|
||||
if (pFont && !pCurrentFont)
|
||||
dispatchValue(RTF_F, pFont->getInt());
|
||||
- m_bFirstRun = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +417,22 @@ void RTFDocumentImpl::setNeedPar(bool bNeedPar)
|
||||
|
||||
void RTFDocumentImpl::setNeedSect(bool bNeedSect)
|
||||
{
|
||||
- m_bNeedSect = bNeedSect;
|
||||
+ // ignore setting before checkFirstRun - every keyword calls setNeedSect!
|
||||
+ if (!m_bNeedSect && bNeedSect && !m_bFirstRun)
|
||||
+ {
|
||||
+ if (!m_pSuperstream) // no sections in header/footer!
|
||||
+ {
|
||||
+ Mapper().startSectionGroup();
|
||||
+ }
|
||||
+ // set flag in substream too - otherwise multiple startParagraphGroup
|
||||
+ m_bNeedSect = bNeedSect;
|
||||
+ Mapper().startParagraphGroup();
|
||||
+ setNeedPar(true);
|
||||
+ }
|
||||
+ else if (m_bNeedSect && !bNeedSect)
|
||||
+ {
|
||||
+ m_bNeedSect = bNeedSect;
|
||||
+ }
|
||||
}
|
||||
|
||||
writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms)
|
||||
@@ -542,6 +557,7 @@ void RTFDocumentImpl::sectBreak(bool bFinal = false)
|
||||
{
|
||||
dispatchFlag(RTF_PARD);
|
||||
dispatchSymbol(RTF_PAR);
|
||||
+ m_bNeedSect = bNeedSect;
|
||||
}
|
||||
while (!m_nHeaderFooterPositions.empty())
|
||||
{
|
||||
@@ -572,12 +588,7 @@ void RTFDocumentImpl::sectBreak(bool bFinal = false)
|
||||
Mapper().endParagraphGroup();
|
||||
if (!m_pSuperstream)
|
||||
Mapper().endSectionGroup();
|
||||
- if (!bFinal)
|
||||
- {
|
||||
- Mapper().startSectionGroup();
|
||||
- Mapper().startParagraphGroup();
|
||||
- }
|
||||
- m_bNeedPar = true;
|
||||
+ m_bNeedPar = false;
|
||||
m_bNeedSect = false;
|
||||
}
|
||||
|
||||
@@ -1345,8 +1356,8 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer,
|
||||
|
||||
int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
|
||||
{
|
||||
- checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
setNeedSect();
|
||||
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
RTFSkipDestination aSkip(*this);
|
||||
switch (nKeyword)
|
||||
{
|
||||
@@ -1867,11 +1878,11 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
|
||||
|
||||
int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
|
||||
{
|
||||
+ setNeedSect();
|
||||
if (nKeyword != RTF_HEXCHAR)
|
||||
checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
else
|
||||
checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
|
||||
- setNeedSect();
|
||||
RTFSkipDestination aSkip(*this);
|
||||
|
||||
if (RTF_LINE == nKeyword)
|
||||
@@ -1944,7 +1955,15 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
|
||||
if (m_bIgnoreNextContSectBreak)
|
||||
m_bIgnoreNextContSectBreak = false;
|
||||
else
|
||||
+ {
|
||||
sectBreak();
|
||||
+ if (m_nResetBreakOnSectBreak != -1)
|
||||
+ { // this should run on _second_ \sect after \page
|
||||
+ dispatchSymbol(m_nResetBreakOnSectBreak); // lazy reset
|
||||
+ m_nResetBreakOnSectBreak = static_cast<RTFKeyword>(-1);
|
||||
+ m_bNeedSect = false; // dispatchSymbol set it
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
break;
|
||||
case RTF_NOBREAK:
|
||||
@@ -2116,19 +2135,24 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
|
||||
RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_sprm::LN_SBkc);
|
||||
// Unless we're on a title page.
|
||||
RTFValue::Pointer_t pTitlePg = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_titlePg);
|
||||
- if ((pBreak.get() && !pBreak->getInt()) && !(pTitlePg.get() && pTitlePg->getInt()))
|
||||
+ if (((pBreak.get() && !pBreak->getInt())
|
||||
+ || m_nResetBreakOnSectBreak == RTF_SBKNONE)
|
||||
+ && !(pTitlePg.get() && pTitlePg->getInt()))
|
||||
{
|
||||
if (m_bWasInFrame)
|
||||
{
|
||||
dispatchSymbol(RTF_PAR);
|
||||
m_bWasInFrame = false;
|
||||
}
|
||||
- dispatchFlag(RTF_SBKPAGE);
|
||||
sectBreak();
|
||||
- dispatchFlag(RTF_SBKNONE);
|
||||
+ // note: this will not affect the following section break
|
||||
+ // but the one just pushed
|
||||
+ dispatchFlag(RTF_SBKPAGE);
|
||||
if (m_bNeedPar)
|
||||
dispatchSymbol(RTF_PAR);
|
||||
m_bIgnoreNextContSectBreak = true;
|
||||
+ // arrange to clean up the syntetic RTF_SBKPAGE
|
||||
+ m_nResetBreakOnSectBreak = RTF_SBKNONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2162,8 +2186,8 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
|
||||
|
||||
int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
|
||||
{
|
||||
- checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
setNeedSect();
|
||||
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
RTFSkipDestination aSkip(*this);
|
||||
int nParam = -1;
|
||||
int nSprm = -1;
|
||||
@@ -2295,6 +2319,10 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
|
||||
}
|
||||
if (nParam >= 0)
|
||||
{
|
||||
+ if (m_nResetBreakOnSectBreak != -1)
|
||||
+ {
|
||||
+ m_nResetBreakOnSectBreak = nKeyword;
|
||||
+ }
|
||||
RTFValue::Pointer_t pValue(new RTFValue(nParam));
|
||||
m_aStates.top().aSectionSprms.set(NS_sprm::LN_SBkc, pValue);
|
||||
return 0;
|
||||
@@ -2902,8 +2930,8 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
|
||||
|
||||
int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
|
||||
{
|
||||
- checkUnicode(/*bUnicode =*/ nKeyword != RTF_U, /*bHex =*/ true);
|
||||
setNeedSect();
|
||||
+ checkUnicode(/*bUnicode =*/ nKeyword != RTF_U, /*bHex =*/ true);
|
||||
RTFSkipDestination aSkip(*this);
|
||||
int nSprm = 0;
|
||||
RTFValue::Pointer_t pIntValue(new RTFValue(nParam));
|
||||
@@ -3869,8 +3897,8 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
|
||||
|
||||
int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam)
|
||||
{
|
||||
- checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
setNeedSect();
|
||||
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
|
||||
RTFSkipDestination aSkip(*this);
|
||||
int nSprm = -1;
|
||||
RTFValue::Pointer_t pBoolValue(new RTFValue(!bParam || nParam != 0));
|
||||
@@ -4721,7 +4749,8 @@ int RTFDocumentImpl::popState()
|
||||
// not in case of other substreams, like headers.
|
||||
if (m_bNeedCr && !(m_nStreamType == NS_rtf::LN_footnote || m_nStreamType == NS_rtf::LN_endnote))
|
||||
dispatchSymbol(RTF_PAR);
|
||||
- sectBreak(true);
|
||||
+ if (m_bNeedSect) // may be set by dispatchSymbol above!
|
||||
+ sectBreak(true);
|
||||
}
|
||||
|
||||
m_aStates.pop();
|
||||
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
|
||||
index 932ec46..fa1f3d6 100644
|
||||
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
|
||||
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
|
||||
@@ -524,6 +524,9 @@ namespace writerfilter {
|
||||
bool m_bMathNor;
|
||||
/// If the next continous section break should be ignored.
|
||||
bool m_bIgnoreNextContSectBreak;
|
||||
+ /// clean up a synthetic page break, see RTF_PAGE
|
||||
+ /// if inactive value is -1, otherwise the RTF_SKB* to restore
|
||||
+ RTFKeyword m_nResetBreakOnSectBreak;
|
||||
/// If a section break is needed before the end of the doc (false right after a section break).
|
||||
bool m_bNeedSect;
|
||||
/// If aFrame.inFrame() was true in the previous state.
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,676 @@
|
||||
From 50945ba67bf6dec66b1ed33011316e0fc9197572 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Stahl <mstahl@redhat.com>
|
||||
Date: Sat, 1 Mar 2014 22:05:51 +0100
|
||||
Subject: [PATCH] writerfilter: salvage a field parameter parsing train wreck
|
||||
|
||||
Field parameters get horribly maimed by lcl_ExtractParameter which
|
||||
clearly has never worked in its 7 years of existence (and looking at the
|
||||
inanity at the call sites makes one wonder what the author was smoking).
|
||||
|
||||
The format is actually quite annoying, since spaces between parameters
|
||||
are optional.
|
||||
|
||||
The old RTF filter was at least able to parse "PAGEREF bookmark" fields,
|
||||
so this fixes such regressions (related: rhbz#1065629).
|
||||
|
||||
(cherry picked from commit 3dc548476c7e88f7a67cc38daf622631a34e34dd)
|
||||
|
||||
Conflicts:
|
||||
writerfilter/source/dmapper/DomainMapper_Impl.cxx
|
||||
|
||||
Change-Id: I9b2e32c3c7264be0fc1077cb8fb3f1bc5c1955bb
|
||||
Reviewed-on: https://gerrit.libreoffice.org/8440
|
||||
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
||||
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
|
||||
---
|
||||
writerfilter/CppunitTest_writerfilter_misc.mk | 36 ++++
|
||||
writerfilter/Module_writerfilter.mk | 1 +
|
||||
writerfilter/qa/cppunittests/misc/misc.cxx | 162 ++++++++++++++++
|
||||
writerfilter/source/dmapper/DomainMapper_Impl.cxx | 224 +++++++++++++++-------
|
||||
writerfilter/source/dmapper/DomainMapper_Impl.hxx | 3 +-
|
||||
5 files changed, 356 insertions(+), 70 deletions(-)
|
||||
create mode 100644 writerfilter/CppunitTest_writerfilter_misc.mk
|
||||
create mode 100644 writerfilter/qa/cppunittests/misc/misc.cxx
|
||||
|
||||
diff --git a/writerfilter/CppunitTest_writerfilter_misc.mk b/writerfilter/CppunitTest_writerfilter_misc.mk
|
||||
new file mode 100644
|
||||
index 0000000..1cdcd80
|
||||
--- /dev/null
|
||||
+++ b/writerfilter/CppunitTest_writerfilter_misc.mk
|
||||
@@ -0,0 +1,36 @@
|
||||
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
+#
|
||||
+# 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/.
|
||||
+#
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_CppunitTest,writerfilter_misc))
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_use_api,writerfilter_misc,\
|
||||
+ offapi \
|
||||
+ udkapi \
|
||||
+))
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_use_external,writerfilter_misc,boost_headers))
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_use_libraries,writerfilter_misc, \
|
||||
+ writerfilter \
|
||||
+ cppu \
|
||||
+ sal \
|
||||
+ $(gb_UWINAPI) \
|
||||
+))
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_set_include,writerfilter_misc, \
|
||||
+ $$(INCLUDE) \
|
||||
+ -I$(SRCDIR)/writerfilter/inc \
|
||||
+))
|
||||
+
|
||||
+$(eval $(call gb_CppunitTest_add_exception_objects,writerfilter_misc, \
|
||||
+ writerfilter/qa/cppunittests/misc/misc \
|
||||
+))
|
||||
+
|
||||
+
|
||||
+# vim: set noet sw=4 ts=4:
|
||||
diff --git a/writerfilter/Module_writerfilter.mk b/writerfilter/Module_writerfilter.mk
|
||||
index 783b6ca..2fcb9e6 100644
|
||||
--- a/writerfilter/Module_writerfilter.mk
|
||||
+++ b/writerfilter/Module_writerfilter.mk
|
||||
@@ -16,6 +16,7 @@ $(eval $(call gb_Module_add_targets,writerfilter,\
|
||||
|
||||
$(eval $(call gb_Module_add_slowcheck_targets,writerfilter,\
|
||||
CppunitTest_writerfilter_rtftok \
|
||||
+ CppunitTest_writerfilter_misc \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
||||
diff --git a/writerfilter/qa/cppunittests/misc/misc.cxx b/writerfilter/qa/cppunittests/misc/misc.cxx
|
||||
new file mode 100644
|
||||
index 0000000..f7031b4
|
||||
--- /dev/null
|
||||
+++ b/writerfilter/qa/cppunittests/misc/misc.cxx
|
||||
@@ -0,0 +1,162 @@
|
||||
+/* -*- 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 <limits>
|
||||
+#include <vector>
|
||||
+
|
||||
+#include <boost/tuple/tuple.hpp>
|
||||
+
|
||||
+#include <cppunit/TestAssert.h>
|
||||
+#include <cppunit/TestFixture.h>
|
||||
+#include <cppunit/extensions/HelperMacros.h>
|
||||
+#include <cppunit/plugin/TestPlugIn.h>
|
||||
+
|
||||
+#include <sal/types.h>
|
||||
+
|
||||
+#include <rtl/ustring.hxx>
|
||||
+
|
||||
+#include <WriterFilterDllApi.hxx>
|
||||
+
|
||||
+
|
||||
+using namespace std;
|
||||
+
|
||||
+
|
||||
+namespace writerfilter { namespace dmapper {
|
||||
+
|
||||
+SAL_DLLPUBLIC_IMPORT // export just for test
|
||||
+boost::tuple<OUString, vector<OUString>, vector<OUString> >
|
||||
+lcl_SplitFieldCommand(const OUString& rCommand);
|
||||
+
|
||||
+} }
|
||||
+
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+class WriterfilterMiscTest
|
||||
+ : public ::CppUnit::TestFixture
|
||||
+{
|
||||
+public:
|
||||
+ virtual void setUp();
|
||||
+ virtual void tearDown();
|
||||
+
|
||||
+ void testFieldParameters();
|
||||
+
|
||||
+ CPPUNIT_TEST_SUITE(WriterfilterMiscTest);
|
||||
+ CPPUNIT_TEST(testFieldParameters);
|
||||
+ CPPUNIT_TEST_SUITE_END();
|
||||
+};
|
||||
+
|
||||
+void WriterfilterMiscTest::setUp()
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void WriterfilterMiscTest::tearDown()
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void WriterfilterMiscTest::testFieldParameters()
|
||||
+{
|
||||
+ using writerfilter::dmapper::lcl_SplitFieldCommand;
|
||||
+ boost::tuple<OUString, vector<OUString>, vector<OUString> > result;
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("PAGEREF last_page");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand(" PAGEREF last_page ");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("pageref last_page");
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("pageref \"last_page\"");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("\"PAGEREF\" \"last_page\" \"\" ");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(2), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(), boost::get<1>(result)[1]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("\"PAGEREF\"\"last_page\" ");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("PAGEREF\"last_page\" ");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("\"PAGEREF\"last_page \"\"");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(2), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(), boost::get<1>(result)[1]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("\"PAGEREF\"last_page \"\"");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(2), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(), boost::get<1>(result)[1]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("pageref \"last\\\\pa\\\"ge\"");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last\\pa\"ge"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT(boost::get<2>(result).empty());
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("PAGEREF\"last_page\"\\*");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<2>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("\\*"), boost::get<2>(result)[0]);
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("PAGEREF last_page \\b foobar ");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(1), boost::get<1>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("last_page"), boost::get<1>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(2), boost::get<2>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("\\B"), boost::get<2>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("foobar"), boost::get<2>(result)[1]);
|
||||
+
|
||||
+ result = lcl_SplitFieldCommand("PAGEREF\\bfoobar\\A\"\"");
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("PAGEREF"), boost::get<0>(result));
|
||||
+ CPPUNIT_ASSERT(boost::get<1>(result).empty());
|
||||
+ CPPUNIT_ASSERT_EQUAL(size_t(4), boost::get<2>(result).size());
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("\\B"), boost::get<2>(result)[0]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("foobar"), boost::get<2>(result)[1]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString("\\A"), boost::get<2>(result)[2]);
|
||||
+ CPPUNIT_ASSERT_EQUAL(OUString(), boost::get<2>(result)[3]);
|
||||
+}
|
||||
+
|
||||
+CPPUNIT_TEST_SUITE_REGISTRATION(WriterfilterMiscTest);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
+
|
||||
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
|
||||
index 6b9562b..c7302cf 100644
|
||||
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
|
||||
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
|
||||
@@ -66,6 +66,7 @@
|
||||
#include <ooxml/OOXMLFastTokens.hxx>
|
||||
|
||||
#include <map>
|
||||
+#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <vcl/outdev.hxx>
|
||||
@@ -2003,37 +2004,133 @@ OUString lcl_ParseFormat( const OUString& rCommand )
|
||||
/*-------------------------------------------------------------------------
|
||||
extract a parameter (with or without quotes) between the command and the following backslash
|
||||
-----------------------------------------------------------------------*/
|
||||
-OUString lcl_ExtractParameter(const OUString& rCommand, sal_Int32 nCommandLength )
|
||||
+static OUString lcl_ExtractToken(OUString const& rCommand,
|
||||
+ sal_Int32 & rIndex, bool & rHaveToken, bool & rIsSwitch)
|
||||
{
|
||||
- sal_Int32 nStartIndex = nCommandLength;
|
||||
- sal_Int32 nEndIndex = 0;
|
||||
- sal_Int32 nQuoteIndex = rCommand.indexOf( '\"', nStartIndex);
|
||||
- if( nQuoteIndex >= 0)
|
||||
+ rHaveToken = false;
|
||||
+ rIsSwitch = false;
|
||||
+
|
||||
+ OUStringBuffer token;
|
||||
+ bool bQuoted(false);
|
||||
+ for (; rIndex < rCommand.getLength(); ++rIndex)
|
||||
{
|
||||
- nStartIndex = nQuoteIndex + 1;
|
||||
- nEndIndex = rCommand.indexOf( '\"', nStartIndex + 1) - 1;
|
||||
+ sal_Unicode const currentChar(rCommand[rIndex]);
|
||||
+ switch (currentChar)
|
||||
+ {
|
||||
+ case '\\':
|
||||
+ {
|
||||
+ if (rIndex == rCommand.getLength() - 1)
|
||||
+ {
|
||||
+ SAL_INFO("writerfilter.dmapper", "field: trailing escape");
|
||||
+ ++rIndex;
|
||||
+ return OUString();
|
||||
+ }
|
||||
+ sal_Unicode const nextChar(rCommand[rIndex+1]);
|
||||
+ if (bQuoted || '\\' == nextChar)
|
||||
+ {
|
||||
+ ++rIndex; // read 2 chars
|
||||
+ token.append(nextChar);
|
||||
+ }
|
||||
+ else // field switch (case insensitive)
|
||||
+ {
|
||||
+ rHaveToken = true;
|
||||
+ if (token.isEmpty())
|
||||
+ {
|
||||
+ rIsSwitch = true;
|
||||
+ rIndex += 2; // read 2 chars
|
||||
+ return rCommand.copy(rIndex - 2, 2).toAsciiUpperCase();
|
||||
+ }
|
||||
+ else
|
||||
+ { // leave rIndex, read it again next time
|
||||
+ return token.makeStringAndClear();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ case '\"':
|
||||
+ if (bQuoted || !token.isEmpty())
|
||||
+ {
|
||||
+ rHaveToken = true;
|
||||
+ if (bQuoted)
|
||||
+ {
|
||||
+ ++rIndex;
|
||||
+ }
|
||||
+ return token.makeStringAndClear();
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ bQuoted = true;
|
||||
+ }
|
||||
+ break;
|
||||
+ case ' ':
|
||||
+ if (bQuoted)
|
||||
+ {
|
||||
+ token.append(' ');
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (!token.isEmpty())
|
||||
+ {
|
||||
+ rHaveToken = true;
|
||||
+ ++rIndex;
|
||||
+ return token.makeStringAndClear();
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ token.append(currentChar);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ assert(rIndex == rCommand.getLength());
|
||||
+ if (bQuoted)
|
||||
+ {
|
||||
+ SAL_INFO("writerfilter.dmapper",
|
||||
+ "field argument with unterminated quote");
|
||||
+ return OUString();
|
||||
}
|
||||
else
|
||||
{
|
||||
- nEndIndex = rCommand.indexOf(" \\", nStartIndex);
|
||||
+ rHaveToken = !token.isEmpty();
|
||||
+ return token.makeStringAndClear();
|
||||
}
|
||||
- OUString sRet;
|
||||
- if( nEndIndex > nStartIndex + 1 )
|
||||
+}
|
||||
+
|
||||
+SAL_DLLPUBLIC_EXPORT // export just for test
|
||||
+boost::tuple<OUString, vector<OUString>, vector<OUString> >
|
||||
+lcl_SplitFieldCommand(const OUString& rCommand)
|
||||
+{
|
||||
+ OUString sType;
|
||||
+ vector<OUString> arguments;
|
||||
+ vector<OUString> switches;
|
||||
+ sal_Int32 nStartIndex(0);
|
||||
+
|
||||
+ do
|
||||
{
|
||||
- //remove spaces at start and end of the result
|
||||
- if(nQuoteIndex <= 0)
|
||||
+ bool bHaveToken;
|
||||
+ bool bIsSwitch;
|
||||
+ OUString const token =
|
||||
+ lcl_ExtractToken(rCommand, nStartIndex, bHaveToken, bIsSwitch);
|
||||
+ assert(nStartIndex <= rCommand.getLength());
|
||||
+ if (bHaveToken)
|
||||
{
|
||||
- const sal_Unicode* pCommandStr = rCommand.getStr();
|
||||
- while( nStartIndex < nEndIndex && pCommandStr[nStartIndex] == ' ')
|
||||
- ++nStartIndex;
|
||||
- while( nEndIndex > nStartIndex && pCommandStr[nEndIndex] == ' ')
|
||||
- --nEndIndex;
|
||||
+ if (sType.isEmpty())
|
||||
+ {
|
||||
+ sType = token.toAsciiUpperCase();
|
||||
+ }
|
||||
+ else if (bIsSwitch || !switches.empty())
|
||||
+ {
|
||||
+ switches.push_back(token);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ arguments.push_back(token);
|
||||
+ }
|
||||
}
|
||||
- sRet = rCommand.copy( nStartIndex, nEndIndex - nStartIndex + 1);
|
||||
- }
|
||||
- return sRet;
|
||||
-}
|
||||
+ } while (nStartIndex < rCommand.getLength());
|
||||
|
||||
+ return boost::make_tuple(sType, arguments, switches);
|
||||
+}
|
||||
|
||||
|
||||
OUString lcl_ExctractAskVariableAndHint( const OUString& rCommand, OUString& rHint )
|
||||
@@ -2480,7 +2577,7 @@ void DomainMapper_Impl::handleAutoNum
|
||||
}
|
||||
|
||||
void DomainMapper_Impl::handleAuthor
|
||||
- (FieldContextPtr pContext,
|
||||
+ (OUString const& rFirstParam,
|
||||
PropertyNameSupplier& rPropNameSupplier,
|
||||
uno::Reference< uno::XInterface > & /*xFieldInterface*/,
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties,
|
||||
@@ -2490,19 +2587,7 @@ void DomainMapper_Impl::handleAuthor
|
||||
xFieldProperties->setPropertyValue
|
||||
( rPropNameSupplier.GetName(PROP_FULL_NAME), uno::makeAny( true ));
|
||||
|
||||
- sal_Int32 nLen = sizeof( " AUTHOR" );
|
||||
- if ( eFieldId != FIELD_AUTHOR )
|
||||
- {
|
||||
- if ( eFieldId == FIELD_USERINITIALS )
|
||||
- nLen = sizeof( " USERINITIALS" );
|
||||
- else if ( eFieldId == FIELD_USERNAME )
|
||||
- nLen = sizeof( " USERNAME" );
|
||||
- }
|
||||
-
|
||||
- OUString sParam =
|
||||
- lcl_ExtractParameter(pContext->GetCommand(), nLen );
|
||||
-
|
||||
- if(!sParam.isEmpty())
|
||||
+ if (!rFirstParam.isEmpty())
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName( PROP_IS_FIXED ),
|
||||
@@ -2513,16 +2598,14 @@ void DomainMapper_Impl::handleAuthor
|
||||
|
||||
void DomainMapper_Impl::handleDocProperty
|
||||
(FieldContextPtr pContext,
|
||||
+ OUString const& rFirstParam,
|
||||
PropertyNameSupplier& rPropNameSupplier,
|
||||
uno::Reference< uno::XInterface > & xFieldInterface,
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties)
|
||||
{
|
||||
//some docproperties should be imported as document statistic fields, some as DocInfo fields
|
||||
//others should be user fields
|
||||
- OUString sParam =
|
||||
- lcl_ExtractParameter(pContext->GetCommand(), sizeof(" DOCPROPERTY") );
|
||||
-
|
||||
- if(!sParam.isEmpty())
|
||||
+ if (!rFirstParam.isEmpty())
|
||||
{
|
||||
#define SET_ARABIC 0x01
|
||||
#define SET_FULL_NAME 0x02
|
||||
@@ -2562,7 +2645,7 @@ void DomainMapper_Impl::handleAuthor
|
||||
for( ; nMap < sizeof(aDocProperties) / sizeof(DocPropertyMap);
|
||||
++nMap )
|
||||
{
|
||||
- if(sParam.equalsAscii(aDocProperties[nMap].pDocPropertyName))
|
||||
+ if (rFirstParam.equalsAscii(aDocProperties[nMap].pDocPropertyName))
|
||||
{
|
||||
sFieldServiceName =
|
||||
OUString::createFromAscii
|
||||
@@ -2589,7 +2672,7 @@ void DomainMapper_Impl::handleAuthor
|
||||
uno::UNO_QUERY_THROW);
|
||||
if( bIsCustomField )
|
||||
xFieldProperties->setPropertyValue(
|
||||
- rPropNameSupplier.GetName(PROP_NAME), uno::makeAny( sParam ));
|
||||
+ rPropNameSupplier.GetName(PROP_NAME), uno::makeAny(rFirstParam));
|
||||
else
|
||||
{
|
||||
if(0 != (aDocProperties[nMap].nFlags & SET_ARABIC))
|
||||
@@ -2889,13 +2972,14 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
try
|
||||
{
|
||||
uno::Reference< uno::XInterface > xFieldInterface;
|
||||
- //at first determine the field type - erase leading and trailing whitespaces
|
||||
- OUString sCommand( pContext->GetCommand().trim() );
|
||||
- sal_Int32 nSpaceIndex = sCommand.indexOf( ' ' );
|
||||
- if( 0 <= nSpaceIndex )
|
||||
- sCommand = sCommand.copy(0, nSpaceIndex).toAsciiUpperCase();
|
||||
|
||||
- FieldConversionMap_t::iterator aIt = aFieldConversionMap.find(sCommand);
|
||||
+ boost::tuple<OUString, vector<OUString>, vector<OUString> > const
|
||||
+ field(lcl_SplitFieldCommand(pContext->GetCommand()));
|
||||
+ OUString const sFirstParam(boost::get<1>(field).empty()
|
||||
+ ? OUString() : boost::get<1>(field).front());
|
||||
+
|
||||
+ FieldConversionMap_t::iterator const aIt =
|
||||
+ aFieldConversionMap.find(boost::get<0>(field));
|
||||
if(aIt != aFieldConversionMap.end())
|
||||
{
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties;
|
||||
@@ -2937,7 +3021,8 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
if ( bCreateEnhancedField )
|
||||
{
|
||||
FieldConversionMap_t aEnhancedFieldConversionMap = lcl_GetEnhancedFieldConversion();
|
||||
- FieldConversionMap_t::iterator aEnhancedIt = aEnhancedFieldConversionMap.find(sCommand);
|
||||
+ FieldConversionMap_t::iterator aEnhancedIt =
|
||||
+ aEnhancedFieldConversionMap.find(boost::get<0>(field));
|
||||
if ( aEnhancedIt != aEnhancedFieldConversionMap.end())
|
||||
sServiceName += OUString::createFromAscii(aEnhancedIt->second.cFieldServiceName );
|
||||
}
|
||||
@@ -2975,7 +3060,9 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
case FIELD_AUTHOR :
|
||||
case FIELD_USERNAME :
|
||||
case FIELD_USERINITIALS :
|
||||
- handleAuthor(pContext, rPropNameSupplier, xFieldInterface, xFieldProperties, aIt->second.eFieldId );
|
||||
+ handleAuthor(sFirstParam, rPropNameSupplier,
|
||||
+ xFieldInterface, xFieldProperties,
|
||||
+ aIt->second.eFieldId);
|
||||
break;
|
||||
case FIELD_DATE:
|
||||
if (xFieldProperties.is())
|
||||
@@ -3014,14 +3101,14 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
}
|
||||
break;
|
||||
case FIELD_DOCPROPERTY :
|
||||
- handleDocProperty(pContext, rPropNameSupplier, xFieldInterface, xFieldProperties);
|
||||
+ handleDocProperty(pContext, sFirstParam, rPropNameSupplier,
|
||||
+ xFieldInterface, xFieldProperties);
|
||||
break;
|
||||
case FIELD_DOCVARIABLE :
|
||||
{
|
||||
- OUString sParam = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" DOCVARIABLE") );
|
||||
//create a user field and type
|
||||
uno::Reference< beans::XPropertySet > xMaster =
|
||||
- FindOrCreateFieldMaster( "com.sun.star.text.FieldMaster.User", sParam );
|
||||
+ FindOrCreateFieldMaster("com.sun.star.text.FieldMaster.User", sFirstParam);
|
||||
uno::Reference< text::XDependentTextField > xDependentField( xFieldInterface, uno::UNO_QUERY_THROW );
|
||||
xDependentField->attachTextFieldMaster( xMaster );
|
||||
m_bSetUserFieldContent = true;
|
||||
@@ -3047,7 +3134,7 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
else
|
||||
{
|
||||
//merge Read_SubF_Ruby into filter/.../util.cxx and reuse that ?
|
||||
- nSpaceIndex = aCommand.indexOf(' ');
|
||||
+ sal_Int32 nSpaceIndex = aCommand.indexOf(' ');
|
||||
if(nSpaceIndex > 0)
|
||||
aCommand = aCommand.copy(nSpaceIndex).trim();
|
||||
if (aCommand.startsWith("\\s"))
|
||||
@@ -3178,8 +3265,7 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
case FIELD_INCLUDEPICTURE: break;
|
||||
case FIELD_KEYWORDS :
|
||||
{
|
||||
- OUString sParam = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" KEYWORDS") );
|
||||
- if(!sParam.isEmpty())
|
||||
+ if (!sFirstParam.isEmpty())
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName( PROP_IS_FIXED ), uno::makeAny( true ));
|
||||
@@ -3209,10 +3295,9 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
case FIELD_MERGEFIELD :
|
||||
{
|
||||
//todo: create a database field and fieldmaster pointing to a column, only
|
||||
- OUString sParam = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" MERGEFIELD") );
|
||||
//create a user field and type
|
||||
uno::Reference< beans::XPropertySet > xMaster =
|
||||
- FindOrCreateFieldMaster( "com.sun.star.text.FieldMaster.Database", sParam );
|
||||
+ FindOrCreateFieldMaster("com.sun.star.text.FieldMaster.Database", sFirstParam);
|
||||
|
||||
// xFieldProperties->setPropertyValue(
|
||||
// "FieldCode",
|
||||
@@ -3243,21 +3328,21 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
if (xFieldProperties.is())
|
||||
{
|
||||
bool bPageRef = aIt->second.eFieldId == FIELD_PAGEREF;
|
||||
- OUString sBookmark = lcl_ExtractParameter(pContext->GetCommand(),
|
||||
- (bPageRef ? sizeof(" PAGEREF") : sizeof(" REF")));
|
||||
|
||||
// Do we need a GetReference (default) or a GetExpression field?
|
||||
uno::Reference< text::XTextFieldsSupplier > xFieldsSupplier( GetTextDocument(), uno::UNO_QUERY );
|
||||
uno::Reference< container::XNameAccess > xFieldMasterAccess = xFieldsSupplier->getTextFieldMasters();
|
||||
|
||||
- if (!xFieldMasterAccess->hasByName("com.sun.star.text.FieldMaster.SetExpression." + sBookmark))
|
||||
+ if (!xFieldMasterAccess->hasByName(
|
||||
+ "com.sun.star.text.FieldMaster.SetExpression."
|
||||
+ + sFirstParam))
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName(PROP_REFERENCE_FIELD_SOURCE),
|
||||
uno::makeAny( sal_Int16(text::ReferenceFieldSource::BOOKMARK)) );
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName(PROP_SOURCE_NAME),
|
||||
- uno::makeAny( sBookmark) );
|
||||
+ uno::makeAny(sFirstParam) );
|
||||
sal_Int16 nFieldPart = (bPageRef ? text::ReferenceFieldPart::PAGE : text::ReferenceFieldPart::TEXT);
|
||||
OUString sValue;
|
||||
if( lcl_FindInCommand( pContext->GetCommand(), 'p', sValue ))
|
||||
@@ -3287,7 +3372,9 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
{
|
||||
xFieldInterface = m_xTextFactory->createInstance("com.sun.star.text.TextField.GetExpression");
|
||||
xFieldProperties.set(xFieldInterface, uno::UNO_QUERY);
|
||||
- xFieldProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_CONTENT), uno::makeAny(sBookmark));
|
||||
+ xFieldProperties->setPropertyValue(
|
||||
+ rPropNameSupplier.GetName(PROP_CONTENT),
|
||||
+ uno::makeAny(sFirstParam));
|
||||
xFieldProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_SUB_TYPE), uno::makeAny(text::SetVariableType::STRING));
|
||||
}
|
||||
}
|
||||
@@ -3354,8 +3441,7 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
case FIELD_STYLEREF : break;
|
||||
case FIELD_SUBJECT :
|
||||
{
|
||||
- OUString sParam = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" SUBJECT") );
|
||||
- if(!sParam.isEmpty())
|
||||
+ if (!sFirstParam.isEmpty())
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName( PROP_IS_FIXED ), uno::makeAny( true ));
|
||||
@@ -3370,8 +3456,7 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
break;
|
||||
case FIELD_TITLE :
|
||||
{
|
||||
- OUString sParam = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" TITLE") );
|
||||
- if(!sParam.isEmpty())
|
||||
+ if (!sFirstParam.isEmpty())
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
rPropNameSupplier.GetName( PROP_IS_FIXED ), uno::makeAny( true ));
|
||||
@@ -3391,10 +3476,11 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
m_xTextFactory->createInstance(
|
||||
OUString::createFromAscii(aIt->second.cFieldServiceName)),
|
||||
uno::UNO_QUERY_THROW);
|
||||
- OUString sTCText = lcl_ExtractParameter(pContext->GetCommand(), sizeof(" TC") );
|
||||
- if( !sTCText.isEmpty())
|
||||
+ if (!sFirstParam.isEmpty())
|
||||
+ {
|
||||
xTC->setPropertyValue(rPropNameSupplier.GetName(PROP_ALTERNATIVE_TEXT),
|
||||
- uno::makeAny(sTCText));
|
||||
+ uno::makeAny(sFirstParam));
|
||||
+ }
|
||||
OUString sValue;
|
||||
// \f TC entry in doc with multiple tables
|
||||
// if( lcl_FindInCommand( pContext->GetCommand(), 'f', sValue ))
|
||||
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
|
||||
index 1ebf067..4686baa 100644
|
||||
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
|
||||
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
|
||||
@@ -576,13 +576,14 @@ public:
|
||||
uno::Reference< uno::XInterface > & xFieldInterface,
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties);
|
||||
void handleAuthor
|
||||
- (FieldContextPtr pContext,
|
||||
+ (OUString const& rFirstParam,
|
||||
PropertyNameSupplier& rPropNameSupplier,
|
||||
uno::Reference< uno::XInterface > & xFieldInterface,
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties,
|
||||
FieldId eFieldId);
|
||||
void handleDocProperty
|
||||
(FieldContextPtr pContext,
|
||||
+ OUString const& rFirstParam,
|
||||
PropertyNameSupplier& rPropNameSupplier,
|
||||
uno::Reference< uno::XInterface > & xFieldInterface,
|
||||
uno::Reference< beans::XPropertySet > xFieldProperties);
|
||||
--
|
||||
1.8.3.1
|
||||
|
Loading…
Reference in new issue