You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
29 KiB
677 lines
29 KiB
11 years ago
|
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
|
||
|
|