summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--RepositoryExternal.mk1
-rw-r--r--chart2/qa/extras/chart2import.cxx2
-rw-r--r--chart2/qa/extras/xshape/chart2xshape.cxx4
-rw-r--r--comphelper/qa/unit/test_traceevent.cxx67
-rw-r--r--comphelper/source/misc/lok.cxx40
-rw-r--r--comphelper/source/misc/traceevent.cxx16
-rw-r--r--configure.ac2
-rw-r--r--desktop/qa/data/table-selection.odtbin0 -> 10324 bytes
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx125
-rw-r--r--desktop/source/lib/init.cxx223
-rw-r--r--editeng/source/uno/unotext.cxx14
-rw-r--r--external/gpgmepp/ExternalProject_gpgmepp.mk2
-rw-r--r--external/libassuan/ExternalProject_libassuan.mk2
-rw-r--r--external/libgpg-error/ExternalProject_libgpg-error.mk2
-rw-r--r--framework/source/helper/statusindicator.cxx2
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.h6
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.hxx10
-rw-r--r--include/comphelper/lok.hxx11
-rw-r--r--include/comphelper/profilezone.hxx4
-rw-r--r--include/comphelper/traceevent.hxx76
-rw-r--r--include/oox/core/contexthandler2.hxx19
-rw-r--r--include/oox/core/fragmenthandler2.hxx11
-rw-r--r--include/oox/drawingml/graphicshapecontext.hxx1
-rw-r--r--include/oox/drawingml/shape.hxx1
-rw-r--r--include/oox/export/drawingml.hxx31
-rw-r--r--include/oox/export/shapes.hxx2
-rw-r--r--include/oox/ole/oleobjecthelper.hxx1
-rw-r--r--include/oox/ppt/pptshape.hxx9
-rw-r--r--include/sfx2/lokhelper.hxx5
-rw-r--r--include/sfx2/viewsh.hxx5
-rw-r--r--include/vcl/outdev.hxx2
-rw-r--r--oox/inc/drawingml/textbody.hxx19
-rw-r--r--oox/inc/drawingml/textcharacterproperties.hxx4
-rw-r--r--oox/inc/drawingml/textfield.hxx13
-rw-r--r--oox/inc/drawingml/textliststyle.hxx10
-rw-r--r--oox/inc/drawingml/textparagraph.hxx11
-rw-r--r--oox/inc/drawingml/textrun.hxx6
-rw-r--r--oox/source/core/contexthandler2.cxx85
-rw-r--r--oox/source/core/fragmenthandler2.cxx70
-rw-r--r--oox/source/drawingml/graphicshapecontext.cxx11
-rw-r--r--oox/source/drawingml/textbody.cxx22
-rw-r--r--oox/source/drawingml/textbodycontext.cxx5
-rw-r--r--oox/source/drawingml/textcharacterpropertiescontext.cxx26
-rw-r--r--oox/source/drawingml/textfield.cxx142
-rw-r--r--oox/source/drawingml/textliststyle.cxx2
-rw-r--r--oox/source/drawingml/textliststylecontext.cxx1
-rw-r--r--oox/source/drawingml/textparagraph.cxx11
-rw-r--r--oox/source/export/drawingml.cxx177
-rw-r--r--oox/source/export/shapes.cxx4
-rw-r--r--oox/source/ppt/pptshape.cxx113
-rw-r--r--oox/source/ppt/pptshapepropertiescontext.cxx5
-rw-r--r--sc/source/core/data/global.cxx3
-rw-r--r--sc/source/filter/oox/worksheetfragment.cxx6
-rw-r--r--sc/source/ui/dbgui/scuiasciiopt.cxx24
-rw-r--r--sc/source/ui/drawfunc/fusel.cxx3
-rw-r--r--sc/source/ui/inc/scuiasciiopt.hxx4
-rw-r--r--sc/source/ui/view/cellsh.cxx3
-rw-r--r--sc/source/ui/view/gridwin5.cxx4
-rw-r--r--sc/source/ui/view/viewfunc.cxx3
-rw-r--r--sc/uiconfig/scalc/ui/textimportcsv.ui45
-rw-r--r--sd/qa/unit/data/odp/numfmt.odpbin10608 -> 11438 bytes
-rw-r--r--sd/qa/unit/data/pptx/numfmt.pptxbin41105 -> 44390 bytes
-rw-r--r--sd/qa/unit/data/pptx/pass/ofz35597-1.pptxbin0 -> 23316 bytes
-rw-r--r--sd/qa/unit/data/pptx/slidenum_field.pptxbin34130 -> 32715 bytes
-rw-r--r--sd/qa/unit/data/pptx/tdf142716.pptxbin0 -> 23281 bytes
-rw-r--r--sd/qa/unit/data/pptx/tdf143222.pptxbin0 -> 53172 bytes
-rwxr-xr-xsd/qa/unit/data/pptx/tdf59323.pptxbin0 -> 39322 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx103
-rw-r--r--sd/qa/unit/export-tests.cxx18
-rw-r--r--sd/qa/unit/import-tests.cxx2
-rw-r--r--sd/source/filter/eppt/epptooxml.hxx13
-rw-r--r--sd/source/filter/eppt/pptx-epptooxml.cxx327
-rw-r--r--sd/source/filter/pdf/sdpdffilter.cxx5
-rw-r--r--sfx2/source/control/unoctitm.cxx19
-rw-r--r--sfx2/source/notebookbar/SfxNotebookBar.cxx3
-rw-r--r--sfx2/source/view/lokhelper.cxx25
-rw-r--r--sfx2/source/view/viewsh.cxx1
-rw-r--r--svx/source/svdraw/svdmrkv.cxx2
-rw-r--r--sw/source/core/crsr/crsrsh.cxx8
-rw-r--r--sw/source/core/layout/layact.cxx9
-rw-r--r--sw/source/uibase/shells/textsh1.cxx2
-rw-r--r--sw/source/uibase/uiview/uivwimp.cxx2
m---------translations0
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/inc/jsdialog/enabled.hxx20
-rw-r--r--vcl/jsdialog/enabled.cxx72
-rw-r--r--vcl/source/bitmap/BitmapScaleSuperFilter.cxx5
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx4
-rw-r--r--vcl/source/outdev/textline.cxx101
-rw-r--r--vcl/source/uitest/uiobject.cxx2
-rw-r--r--vcl/source/window/builder.cxx53
-rw-r--r--vcl/source/window/mouse.cxx3
-rw-r--r--vcl/source/window/window.cxx5
94 files changed, 1724 insertions, 613 deletions
diff --git a/.gitignore b/.gitignore
index fc0482e11d52..bffebfaa22de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -179,3 +179,7 @@ LibreOffice.VC.VC.opendb
# vim-ide-integration
/compile_commands.json
+
+#android builds
+/android/jniLibs/
+/android/obj/ \ No newline at end of file
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 7a4fd496d654..a937feead3cb 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -1279,6 +1279,7 @@ $(call gb_LinkTarget_use_external,$(1),freetype_headers)
$(call gb_LinkTarget_set_include,$(1),\
-I$(call gb_UnpackedTarball_get_dir,cairo) \
-I$(call gb_UnpackedTarball_get_dir,cairo)/src \
+ -I$(call gb_UnpackedTarball_get_dir,pixman)/pixman \
$$(INCLUDE) \
)
$(call gb_LinkTarget_add_libs,$(1),\
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index 82e534f4dfcb..99879c2ba397 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -794,7 +794,7 @@ void Chart2ImportTest::testBnc864396()
void Chart2ImportTest::testBnc889755()
{
load("/chart2/qa/extras/data/pptx/", "bnc889755.pptx");
- uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 6), uno::UNO_QUERY_THROW);
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 5), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
uno::Reference< chart2::XInternalDataProvider > xDataProvider( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
diff --git a/chart2/qa/extras/xshape/chart2xshape.cxx b/chart2/qa/extras/xshape/chart2xshape.cxx
index e68deadc2294..9b31f4d4195d 100644
--- a/chart2/qa/extras/xshape/chart2xshape.cxx
+++ b/chart2/qa/extras/xshape/chart2xshape.cxx
@@ -183,8 +183,8 @@ void Chart2XShapeTest::testTdf76649TrendLineBug()
void Chart2XShapeTest::testTdf88154LabelRotatedLayout()
{
load("chart2/qa/extras/xshape/data/pptx/", "tdf88154_LabelRotatedLayout.pptx");
- uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromDrawImpress(0,6);
- uno::Reference< qa::XDumper > xDumper( xChartDoc, UNO_QUERY_THROW );
+ uno::Reference<chart::XChartDocument> xChartDoc = getChartDocFromDrawImpress(0, 5);
+ uno::Reference<qa::XDumper> xDumper(xChartDoc, UNO_QUERY_THROW);
OUString rDump = xDumper->dump();
OString aXmlDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8);
xmlDocPtr pXmlDoc = xmlParseDoc(reinterpret_cast<const xmlChar*>(aXmlDump.getStr()));
diff --git a/comphelper/qa/unit/test_traceevent.cxx b/comphelper/qa/unit/test_traceevent.cxx
index 8bd34595e397..6f768c09d466 100644
--- a/comphelper/qa/unit/test_traceevent.cxx
+++ b/comphelper/qa/unit/test_traceevent.cxx
@@ -40,17 +40,12 @@ void trace_event_test()
// This will not generate any 'b' and 'e' events either
auto pAsync1(std::make_shared<comphelper::AsyncEvent>("async1"));
- std::weak_ptr<comphelper::AsyncEvent> pAsync2;
{
// No 'X' by this either
comphelper::ProfileZone aZone1("block1");
// Now we turn on recording
comphelper::TraceEvent::startRecording();
-
- // As this is nested in the parent that was created with recording turned off,
- // this will not generate any 'b' and 'e' events either even if recording is now on.
- pAsync2 = comphelper::AsyncEvent::createWithParent("async2in1", pAsync1);
}
// This will generate an 'i' event for instant1
@@ -70,20 +65,13 @@ void trace_event_test()
// Leaving this scope will generate an 'X' event for block2
}
- // Verify that the weak_ptr to pAsync2 has expired as its parent pAsync1 has been finished off
- CPPUNIT_ASSERT(pAsync2.expired());
-
// This will generate a 'b' event for async3
auto pAsync3(std::make_shared<comphelper::AsyncEvent>(
"async3", std::map<OUString, OUString>({ { "foo", "bar" }, { "tem", "42" } })));
- std::weak_ptr<comphelper::AsyncEvent> pAsync4;
-
{
comphelper::ProfileZone aZone3("block3");
- pAsync4 = comphelper::AsyncEvent::createWithParent("async4in3", pAsync3);
-
// Leaving this scope will generate an 'X' event for block3
}
@@ -96,32 +84,8 @@ void trace_event_test()
comphelper::TraceEvent::addInstantEvent(
"instant2", std::map<OUString, OUString>({ { "foo2", "bar2" }, { "tem2", "42" } }));
- std::weak_ptr<comphelper::AsyncEvent> pAsync5;
- {
- auto pAsync4Locked = pAsync4.lock();
- CPPUNIT_ASSERT(pAsync4Locked);
- // This will generate a 'b' event for async5in4
- pAsync5 = comphelper::AsyncEvent::createWithParent("async5in4", pAsync4Locked);
- }
-
- CPPUNIT_ASSERT(!pAsync5.expired());
-
- // This will generate a 'b' event for async6in5
- std::weak_ptr<comphelper::AsyncEvent> pAsync6(
- comphelper::AsyncEvent::createWithParent("async6in5", pAsync5.lock()));
- CPPUNIT_ASSERT(!pAsync6.expired());
-
- // This will generate an 'e' event for async6in5 and async5in4
- pAsync5.lock()->finish();
-
- pAsync7Locked = comphelper::AsyncEvent::createWithParent("async7in3", pAsync3).lock();
-
- CPPUNIT_ASSERT(pAsync6.expired());
-
// Leaving this scope will generate 'X' events for test2 and a
- // 'e' event for async4in3, async7in3, and async3. The
- // pAsync7Locked pointer will now point to an AsyncEvent
- // object that has already had its 'e' event generated.
+ // 'e' event for async4in3, async7in3, and async3.
}
// This incorrect use of overlapping (not nested) ProfileZones
@@ -130,9 +94,6 @@ void trace_event_test()
auto p2 = new comphelper::ProfileZone("error2");
delete p1;
delete p2;
-
- // Nothing is generated from this
- pAsync7Locked.reset();
}
}
@@ -145,28 +106,20 @@ void TestTraceEvent::test()
std::cerr << s << "\n";
}
- CPPUNIT_ASSERT_EQUAL(17, static_cast<int>(aEvents.size()));
+ CPPUNIT_ASSERT_EQUAL(9, static_cast<int>(aEvents.size()));
CPPUNIT_ASSERT(aEvents[0].startsWith("{\"name:\"instant1\",\"ph\":\"i\","));
- CPPUNIT_ASSERT(aEvents[1].startsWith("{\"name\":\"async2.5\",\"ph\":\"b\",\"id\":1,"));
+ CPPUNIT_ASSERT(aEvents[1].startsWith("{\"name\":\"async2.5\",\"ph\":\"S\",\"id\":1,"));
CPPUNIT_ASSERT(aEvents[2].startsWith("{\"name\":\"block2\",\"ph\":\"X\","));
CPPUNIT_ASSERT(aEvents[3].startsWith(
- "{\"name\":\"async3\",\"ph\":\"b\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},"));
- CPPUNIT_ASSERT(aEvents[4].startsWith("{\"name\":\"async4in3\",\"ph\":\"b\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[5].startsWith("{\"name\":\"block3\",\"ph\":\"X\","));
- CPPUNIT_ASSERT(aEvents[6].startsWith("{\"name\":\"async2.5\",\"ph\":\"e\",\"id\":1,"));
- CPPUNIT_ASSERT(aEvents[7].startsWith(
+ "{\"name\":\"async3\",\"ph\":\"S\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},"));
+ CPPUNIT_ASSERT(aEvents[4].startsWith("{\"name\":\"block3\",\"ph\":\"X\","));
+ CPPUNIT_ASSERT(aEvents[5].startsWith("{\"name\":\"async2.5\",\"ph\":\"F\",\"id\":1,"));
+ CPPUNIT_ASSERT(aEvents[6].startsWith(
"{\"name:\"instant2\",\"ph\":\"i\",\"args\":{\"foo2\":\"bar2\",\"tem2\":\"42\"},"));
- CPPUNIT_ASSERT(aEvents[8].startsWith("{\"name\":\"async5in4\",\"ph\":\"b\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[9].startsWith("{\"name\":\"async6in5\",\"ph\":\"b\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[10].startsWith("{\"name\":\"async6in5\",\"ph\":\"e\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[11].startsWith("{\"name\":\"async5in4\",\"ph\":\"e\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[12].startsWith("{\"name\":\"async7in3\",\"ph\":\"b\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[13].startsWith("{\"name\":\"test2\",\"ph\":\"X\""));
- CPPUNIT_ASSERT(aEvents[14].startsWith("{\"name\":\"async4in3\",\"ph\":\"e\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[15].startsWith("{\"name\":\"async7in3\",\"ph\":\"e\",\"id\":2,"));
- CPPUNIT_ASSERT(aEvents[16].startsWith(
- "{\"name\":\"async3\",\"ph\":\"e\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},"));
+ CPPUNIT_ASSERT(aEvents[7].startsWith("{\"name\":\"test2\",\"ph\":\"X\""));
+ CPPUNIT_ASSERT(aEvents[8].startsWith(
+ "{\"name\":\"async3\",\"ph\":\"F\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},"));
}
CPPUNIT_TEST_SUITE_REGISTRATION(TestTraceEvent);
diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx
index 208fe7bb25df..d7b34bccafee 100644
--- a/comphelper/source/misc/lok.cxx
+++ b/comphelper/source/misc/lok.cxx
@@ -10,6 +10,7 @@
#include <comphelper/lok.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <sal/log.hxx>
+#include <algorithm>
#include <iostream>
#include <map>
@@ -38,6 +39,8 @@ static bool g_bLocalRendering(false);
static Compat g_eCompatFlags(Compat::none);
+static std::vector<OUString> g_vFreemiumDenyList;
+
namespace
{
@@ -261,31 +264,56 @@ bool isWhitelistedLanguage(const OUString& lang)
#endif
}
-static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent)(nullptr);
+static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText)(nullptr);
static void *pStatusIndicatorCallbackData(nullptr);
-void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent), void *data)
+void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText), void *data)
{
pStatusIndicatorCallback = callback;
pStatusIndicatorCallbackData = data;
}
-void statusIndicatorStart()
+void statusIndicatorStart(const OUString& sText)
{
if (pStatusIndicatorCallback)
- pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0);
+ pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0, sText.toUtf8().getStr());
}
void statusIndicatorSetValue(int percent)
{
if (pStatusIndicatorCallback)
- pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent);
+ pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent, nullptr);
}
void statusIndicatorFinish()
{
if (pStatusIndicatorCallback)
- pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0);
+ pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0, nullptr);
+}
+
+void setFreemiumDenyList(const char* freemiumDenyList)
+{
+ if(!g_vFreemiumDenyList.empty())
+ return;
+
+ OUString DenyListString(freemiumDenyList, strlen(freemiumDenyList), RTL_TEXTENCODING_UTF8);
+
+ OUString command = DenyListString.getToken(0, ' ');
+ for (size_t i = 1; !command.isEmpty(); i++)
+ {
+ g_vFreemiumDenyList.emplace_back(command);
+ command = DenyListString.getToken(i, ' ');
+ }
+}
+
+const std::vector<OUString>& getFreemiumDenyList()
+{
+ return g_vFreemiumDenyList;
+}
+
+bool isCommandFreemiumDenied(const OUString& command)
+{
+ return std::find(g_vFreemiumDenyList.begin(), g_vFreemiumDenyList.end(), command) != g_vFreemiumDenyList.end();
}
} // namespace LibreOfficeKit
diff --git a/comphelper/source/misc/traceevent.cxx b/comphelper/source/misc/traceevent.cxx
index 793fea6cdb0e..c379bbb97f7e 100644
--- a/comphelper/source/misc/traceevent.cxx
+++ b/comphelper/source/misc/traceevent.cxx
@@ -24,6 +24,10 @@ std::atomic<bool> TraceEvent::s_bRecording = (getenv("TRACE_EVENT_RECORDING") !=
#else
std::atomic<bool> TraceEvent::s_bRecording = false;
#endif
+
+std::size_t TraceEvent::s_nBufferSize = 0;
+void (*TraceEvent::s_pBufferFullCallback)() = nullptr;
+
int AsyncEvent::s_nIdCounter = 0;
int ProfileZone::s_nNesting = 0;
@@ -38,6 +42,12 @@ void TraceEvent::addRecording(const OUString& sObject)
osl::MutexGuard aGuard(g_aMutex);
g_aRecording.emplace_back(sObject);
+
+ if (s_nBufferSize > 0 && g_aRecording.size() >= s_nBufferSize)
+ {
+ if (s_pBufferFullCallback != nullptr)
+ (*s_pBufferFullCallback)();
+ }
}
void TraceEvent::addInstantEvent(const char* sName, const std::map<OUString, OUString>& args)
@@ -72,6 +82,12 @@ void TraceEvent::startRecording()
void TraceEvent::stopRecording() { s_bRecording = false; }
+void TraceEvent::setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)())
+{
+ s_nBufferSize = bufferSize;
+ s_pBufferFullCallback = bufferFullCallback;
+}
+
std::vector<OUString> TraceEvent::getEventVectorAndClear()
{
bool bRecording;
diff --git a/configure.ac b/configure.ac
index 2b09b68ee759..6b404c016888 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ dnl in order to create a configure script.
# several non-alphanumeric characters, those are split off and used only for the
# ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea.
-AC_INIT([Collabora Office],[6.4.10.41],[],[],[https://collaboraoffice.com/])
+AC_INIT([Collabora Office],[6.4.10.45],[],[],[https://collaboraoffice.com/])
dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just fine if it is installed
dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails hard
diff --git a/desktop/qa/data/table-selection.odt b/desktop/qa/data/table-selection.odt
new file mode 100644
index 000000000000..c19f8c79fc3a
--- /dev/null
+++ b/desktop/qa/data/table-selection.odt
Binary files differ
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index af9b93620351..d41777c5e77b 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -226,6 +226,8 @@ public:
void testMetricField();
void testMultiDocuments();
void testJumpCursor();
+ void testNoDuplicateTableSelection();
+ void testMultiViewTableSelection();
void testABI();
CPPUNIT_TEST_SUITE(DesktopLOKTest);
@@ -289,6 +291,8 @@ public:
CPPUNIT_TEST(testMetricField);
CPPUNIT_TEST(testMultiDocuments);
CPPUNIT_TEST(testJumpCursor);
+ CPPUNIT_TEST(testNoDuplicateTableSelection);
+ CPPUNIT_TEST(testMultiViewTableSelection);
CPPUNIT_TEST(testABI);
CPPUNIT_TEST_SUITE_END();
@@ -1946,6 +1950,8 @@ class ViewCallback
int mnView;
public:
OString m_aCellFormula;
+ int m_nTableSelectionCount;
+ bool m_bEmptyTableSelection;
bool m_bTilesInvalidated;
bool m_bZeroCursor;
tools::Rectangle m_aOwnCursor;
@@ -1954,6 +1960,8 @@ public:
ViewCallback(LibLODocument_Impl* pDocument)
: mpDocument(pDocument),
+ m_nTableSelectionCount(0),
+ m_bEmptyTableSelection(false),
m_bTilesInvalidated(false),
m_bZeroCursor(false)
{
@@ -2017,6 +2025,12 @@ public:
m_aCellFormula = aPayload;
}
break;
+ case LOK_CALLBACK_TABLE_SELECTED:
+ {
+ m_bEmptyTableSelection = (std::string(pPayload).compare("{\n}\n") == 0);
+ ++m_nTableSelectionCount;
+ }
+ break;
}
}
};
@@ -3089,6 +3103,113 @@ void DesktopLOKTest::testJumpCursor()
comphelper::LibreOfficeKit::setTiledAnnotations(true);
}
+static void lcl_repeatKeyStroke(LibLODocument_Impl *pDocument, int nCharCode, int nKeyCode, size_t nCount)
+{
+ for (size_t nCtr = 0; nCtr < nCount; ++nCtr)
+ {
+ pDocument->m_pDocumentClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, nCharCode, nKeyCode);
+ pDocument->m_pDocumentClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, nCharCode, nKeyCode);
+ }
+}
+
+void DesktopLOKTest::testNoDuplicateTableSelection()
+{
+ comphelper::LibreOfficeKit::setActive();
+ LibLODocument_Impl* pDocument = loadDoc("table-selection.odt");
+
+ // Create view 1.
+ pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
+ ViewCallback aView1(pDocument);
+
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection);
+
+ aView1.m_nTableSelectionCount = 0;
+ // Go to Table1.
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection);
+
+ aView1.m_nTableSelectionCount = 0;
+ // Move to the last row in Table1.
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 2);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(0, aView1.m_nTableSelectionCount);
+
+ // Go outside Table1.
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection);
+}
+
+void DesktopLOKTest::testMultiViewTableSelection()
+{
+ comphelper::LibreOfficeKit::setActive();
+ LibLODocument_Impl* pDocument = loadDoc("table-selection.odt");
+
+ // Create view 1.
+ pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
+ ViewCallback aView1(pDocument);
+ int nView1 = pDocument->m_pDocumentClass->getView(pDocument);
+
+ // Create view 2.
+ pDocument->m_pDocumentClass->createView(pDocument);
+ pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
+ ViewCallback aView2(pDocument);
+ int nView2 = pDocument->m_pDocumentClass->getView(pDocument);
+
+ // switch to view 1.
+ pDocument->m_pDocumentClass->setView(pDocument, nView1);
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount);
+ CPPUNIT_ASSERT_EQUAL(1, aView2.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection);
+ CPPUNIT_ASSERT(aView2.m_bEmptyTableSelection);
+
+ aView1.m_nTableSelectionCount = 0;
+ aView2.m_nTableSelectionCount = 0;
+
+ pDocument->m_pDocumentClass->setView(pDocument, nView1);
+ // Go to Table1.
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount);
+ CPPUNIT_ASSERT_EQUAL(0, aView2.m_nTableSelectionCount);
+
+ aView1.m_nTableSelectionCount = 0;
+ // Switch to view 2
+ pDocument->m_pDocumentClass->setView(pDocument, nView2);
+ // Go to Table2 in view 2.
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 7);
+ Scheduler::ProcessEventsToIdle();
+ // View1 should not get any table selection messages.
+ CPPUNIT_ASSERT_EQUAL(0, aView1.m_nTableSelectionCount);
+ // View2 will first get table selection of Table1, then emty selection, and finally on 7th down arrow keypress,
+ // it will get table-selection of Table2. So in total it should get 3 table selections.
+ CPPUNIT_ASSERT_EQUAL(3, aView2.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(!aView2.m_bEmptyTableSelection);
+
+ aView1.m_nTableSelectionCount = 0;
+ aView2.m_nTableSelectionCount = 0;
+
+ // Switch to view 1
+ pDocument->m_pDocumentClass->setView(pDocument, nView1);
+ // Go out of Table1 and re-enter..
+ lcl_repeatKeyStroke(pDocument, 0, KEY_UP, 1);
+ lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1);
+ Scheduler::ProcessEventsToIdle();
+ // View1 should get one empty table selection, then get Table1 selection.
+ CPPUNIT_ASSERT_EQUAL(2, aView1.m_nTableSelectionCount);
+ // View2 should not get any table selection.
+ CPPUNIT_ASSERT_EQUAL(0, aView2.m_nTableSelectionCount);
+ CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection);
+}
+
namespace {
constexpr size_t classOffset(int i)
@@ -3186,10 +3307,12 @@ void DesktopLOKTest::testABI()
CPPUNIT_ASSERT_EQUAL(documentClassOffset(59), offsetof(struct _LibreOfficeKitDocumentClass, completeFunction));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(60), offsetof(struct _LibreOfficeKitDocumentClass, setWindowTextSelection));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(61), offsetof(struct _LibreOfficeKitDocumentClass, sendFormFieldEvent));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), offsetof(struct _LibreOfficeKitDocumentClass, setFreemiumDenyList));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(63), offsetof(struct _LibreOfficeKitDocumentClass, setFreemiumView));
// Extending is fine, update this, and add new assert for the offsetof the
// new method
- CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), sizeof(struct _LibreOfficeKitDocumentClass));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(64), sizeof(struct _LibreOfficeKitDocumentClass));
}
CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest);
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 8428dc2343d4..b80eb0f3171e 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -217,8 +217,14 @@ public:
SetTimeout(dumpTimeoutMS);
Start();
}
+
virtual void Invoke() override
{
+ flushRecordings();
+ }
+
+ static void flushRecordings()
+ {
const css::uno::Sequence<OUString> aEvents =
comphelper::TraceEvent::getRecordingAndClear();
OStringBuffer aOutput;
@@ -1077,6 +1083,10 @@ static void doc_postKeyEvent(LibreOfficeKitDocument* pThis,
int nType,
int nCharCode,
int nKeyCode);
+static void doc_setFreemiumDenyList(const char* freemiumDenyList);
+
+static void doc_setFreemiumView(int nViewId, bool isFreemium);
+
static void doc_postWindowExtTextInputEvent(LibreOfficeKitDocument* pThis,
unsigned nWindowId,
int nType,
@@ -1251,6 +1261,26 @@ rtl::Reference<LOKClipboard> forceSetClipboardForCurrentView(LibreOfficeKitDocum
#endif
+const vcl::Font* FindFont(const OUString& rFontName)
+{
+ SfxObjectShell* pDocSh = SfxObjectShell::Current();
+ const SvxFontListItem* pFonts
+ = static_cast<const SvxFontListItem*>(pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST));
+ const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr;
+ if (pList && !rFontName.isEmpty())
+ if (sal_Handle hMetric = pList->GetFirstFontMetric(rFontName))
+ return &FontList::GetFontMetric(hMetric);
+ return nullptr;
+}
+
+vcl::Font FindFont_FallbackToDefault(const OUString& rFontName)
+{
+ if (auto pFound = FindFont(rFontName))
+ return *pFound;
+
+ return OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE, LANGUAGE_NONE,
+ GetDefaultFontFlags::NONE);
+}
} // anonymous namespace
LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XComponent> &xComponent, int nDocumentId)
@@ -1340,6 +1370,9 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
m_pDocumentClass->sendFormFieldEvent = doc_sendFormFieldEvent;
+ m_pDocumentClass->setFreemiumDenyList = doc_setFreemiumDenyList;
+ m_pDocumentClass->setFreemiumView = doc_setFreemiumView;
+
gDocumentClass = m_pDocumentClass;
}
pClass = m_pDocumentClass.get();
@@ -1394,6 +1427,7 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li
m_states.emplace(LOK_CALLBACK_CELL_ADDRESS, "NIL");
m_states.emplace(LOK_CALLBACK_CURSOR_VISIBLE, "NIL");
m_states.emplace(LOK_CALLBACK_SET_PART, "NIL");
+ m_states.emplace(LOK_CALLBACK_TABLE_SELECTED, "NIL");
Start();
}
@@ -1496,6 +1530,8 @@ void CallbackFlushHandler::queue(const int type, const char* data)
case LOK_CALLBACK_WINDOW:
case LOK_CALLBACK_CALC_FUNCTION_LIST:
case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY:
+ case LOK_CALLBACK_REFERENCE_MARKS:
+ case LOK_CALLBACK_CELL_AUTO_FILL_AREA:
{
const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
[type] (const queue_type::value_type& elem) { return (elem.Type == type); });
@@ -2743,6 +2779,7 @@ static void doc_iniUnoCommands ()
OUString(".uno:IncrementIndent"),
OUString(".uno:Italic"),
OUString(".uno:JustifyPara"),
+ OUString(".uno:JumpToMark"),
OUString(".uno:OutlineFont"),
OUString(".uno:LeftPara"),
OUString(".uno:LanguageStatus"),
@@ -3554,6 +3591,17 @@ static void doc_postKeyEvent(LibreOfficeKitDocument* pThis, int nType, int nChar
}
}
+static void doc_setFreemiumDenyList(const char* freemiumDenyList)
+{
+ comphelper::LibreOfficeKit::setFreemiumDenyList(freemiumDenyList);
+}
+
+static void doc_setFreemiumView(int nViewId, bool isFreemium)
+{
+ SolarMutexGuard aGuard;
+ SfxLokHelper::setFreemiumView(nViewId, isFreemium);
+}
+
static void doc_postWindowExtTextInputEvent(LibreOfficeKitDocument* pThis, unsigned nWindowId, int nType, const char* pText)
{
comphelper::ProfileZone aZone("doc_postWindowExtTextInputEvent");
@@ -3904,6 +3952,7 @@ static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const c
{
if (strcmp(pValue, "start") == 0)
{
+ comphelper::TraceEvent::setBufferSizeAndCallback(100, TraceEventDumper::flushRecordings);
comphelper::TraceEvent::startRecording();
if (traceEventDumper == nullptr)
traceEventDumper = new TraceEventDumper();
@@ -4749,43 +4798,25 @@ static char* getFonts (const char* pCommand)
static char* getFontSubset (const OString& aFontName)
{
OUString aFoundFont(::rtl::Uri::decode(OStringToOUString(aFontName, RTL_TEXTENCODING_UTF8), rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8));
- SfxObjectShell* pDocSh = SfxObjectShell::Current();
- const SvxFontListItem* pFonts = static_cast<const SvxFontListItem*>(
- pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST));
- const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr;
boost::property_tree::ptree aTree;
aTree.put("commandName", ".uno:FontSubset");
boost::property_tree::ptree aValues;
- if ( pList && !aFoundFont.isEmpty() )
+ if (const vcl::Font* pFont = FindFont(aFoundFont))
{
- sal_uInt16 nFontCount = pList->GetFontNameCount();
- sal_uInt16 nItFont = 0;
- for (; nItFont < nFontCount; ++nItFont)
- {
- if (aFoundFont == pList->GetFontName(nItFont).GetFamilyName())
- {
- break;
- }
- }
+ FontCharMapRef xFontCharMap (new FontCharMap());
+ auto aDevice(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
- if ( nItFont < nFontCount )
- {
- FontCharMapRef xFontCharMap (new FontCharMap());
- auto aDevice(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
- const vcl::Font& aFont(pList->GetFontName(nItFont));
-
- aDevice->SetFont(aFont);
- aDevice->GetFontCharMap(xFontCharMap);
- SubsetMap aSubMap(xFontCharMap);
+ aDevice->SetFont(*pFont);
+ aDevice->GetFontCharMap(xFontCharMap);
+ SubsetMap aSubMap(xFontCharMap);
- for (auto const& subset : aSubMap.GetSubsetMap())
- {
- boost::property_tree::ptree aChild;
- aChild.put("", static_cast<int>(ublock_getCode(subset.GetRangeMin())));
- aValues.push_back(std::make_pair("", aChild));
- }
+ for (auto const& subset : aSubMap.GetSubsetMap())
+ {
+ boost::property_tree::ptree aChild;
+ aChild.put("", static_cast<int>(ublock_getCode(subset.GetRangeMin())));
+ aValues.push_back(std::make_pair("", aChild));
}
}
@@ -5406,98 +5437,80 @@ unsigned char* doc_renderFontOrientation(SAL_UNUSED_PARAMETER LibreOfficeKitDocu
SolarMutexGuard aGuard;
SetLastExceptionMsg();
- OString aSearchedFontName(pFontName);
- OUString aText(OStringToOUString(pChar, RTL_TEXTENCODING_UTF8));
- SfxObjectShell* pDocSh = SfxObjectShell::Current();
- const SvxFontListItem* pFonts = static_cast<const SvxFontListItem*>(
- pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST));
- const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr;
-
const int nDefaultFontSize = 25;
- if ( pList )
- {
- sal_uInt16 nFontCount = pList->GetFontNameCount();
- for (sal_uInt16 i = 0; i < nFontCount; ++i)
- {
- const FontMetric& rFontMetric = pList->GetFontName(i);
- const OUString& aFontName = rFontMetric.GetFamilyName();
- if (aSearchedFontName != aFontName.toUtf8())
- continue;
-
- if (aText.isEmpty())
- aText = rFontMetric.GetFamilyName();
+ auto aFont = FindFont_FallbackToDefault(OStringToOUString(pFontName, RTL_TEXTENCODING_UTF8));
- auto aDevice(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
- ::tools::Rectangle aRect;
- vcl::Font aFont(rFontMetric);
- aFont.SetFontSize(Size(0, nDefaultFontSize));
- aFont.SetOrientation(pOrientation);
- aDevice->SetFont(aFont);
- aDevice->GetTextBoundRect(aRect, aText);
- if (aRect.IsEmpty())
- break;
+ OUString aText(OStringToOUString(pChar, RTL_TEXTENCODING_UTF8));
+ if (aText.isEmpty())
+ aText = aFont.GetFamilyName();
+
+ auto aDevice(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
+ ::tools::Rectangle aRect;
+ aFont.SetFontSize(Size(0, nDefaultFontSize));
+ aFont.SetOrientation(pOrientation);
+ aDevice->SetFont(aFont);
+ aDevice->GetTextBoundRect(aRect, aText);
+ if (aRect.IsEmpty())
+ return nullptr;
- int nFontWidth = aRect.BottomRight().X() + 1;
- int nFontHeight = aRect.BottomRight().Y() + 1;
+ int nFontWidth = aRect.BottomRight().X() + 1;
+ int nFontHeight = aRect.BottomRight().Y() + 1;
- if (!(nFontWidth > 0 && nFontHeight > 0))
- break;
+ if (!(nFontWidth > 0 && nFontHeight > 0))
+ return nullptr;
- if (*pFontWidth > 0 && *pFontHeight > 0)
- {
- double fScaleX = *pFontWidth / static_cast<double>(nFontWidth) / 1.5;
- double fScaleY = *pFontHeight / static_cast<double>(nFontHeight) / 1.5;
+ if (*pFontWidth > 0 && *pFontHeight > 0)
+ {
+ double fScaleX = *pFontWidth / static_cast<double>(nFontWidth) / 1.5;
+ double fScaleY = *pFontHeight / static_cast<double>(nFontHeight) / 1.5;
- double fScale = std::min(fScaleX, fScaleY);
+ double fScale = std::min(fScaleX, fScaleY);
- if (fScale >= 1.0)
- {
- int nFontSize = fScale * nDefaultFontSize;
- aFont.SetFontSize(Size(0, nFontSize));
- aDevice->SetFont(aFont);
- }
+ if (fScale >= 1.0)
+ {
+ int nFontSize = fScale * nDefaultFontSize;
+ aFont.SetFontSize(Size(0, nFontSize));
+ aDevice->SetFont(aFont);
+ }
- aRect = tools::Rectangle(0, 0, *pFontWidth, *pFontHeight);
+ aRect = tools::Rectangle(0, 0, *pFontWidth, *pFontHeight);
- nFontWidth = *pFontWidth;
- nFontHeight = *pFontHeight;
+ nFontWidth = *pFontWidth;
+ nFontHeight = *pFontHeight;
- }
+ }
- unsigned char* pBuffer = static_cast<unsigned char*>(malloc(4 * nFontWidth * nFontHeight));
- if (!pBuffer)
- break;
+ unsigned char* pBuffer = static_cast<unsigned char*>(malloc(4 * nFontWidth * nFontHeight));
+ if (!pBuffer)
+ return nullptr;
- memset(pBuffer, 0, nFontWidth * nFontHeight * 4);
- aDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
- aDevice->SetOutputSizePixelScaleOffsetAndBuffer(
- Size(nFontWidth, nFontHeight), Fraction(1.0), Point(),
- pBuffer);
+ memset(pBuffer, 0, nFontWidth * nFontHeight * 4);
+ aDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+ aDevice->SetOutputSizePixelScaleOffsetAndBuffer(
+ Size(nFontWidth, nFontHeight), Fraction(1.0), Point(),
+ pBuffer);
- if (*pFontWidth > 0 && *pFontHeight > 0)
- {
- DrawTextFlags const nStyle =
- DrawTextFlags::Center
- | DrawTextFlags::VCenter
- | DrawTextFlags::MultiLine
- | DrawTextFlags::WordBreak;// | DrawTextFlags::WordBreakHyphenation ;
+ if (*pFontWidth > 0 && *pFontHeight > 0)
+ {
+ DrawTextFlags const nStyle =
+ DrawTextFlags::Center
+ | DrawTextFlags::VCenter
+ | DrawTextFlags::MultiLine
+ | DrawTextFlags::WordBreak;// | DrawTextFlags::WordBreakHyphenation ;
- aDevice->DrawText(aRect, aText, nStyle);
- }
- else
- {
- *pFontWidth = nFontWidth;
- *pFontHeight = nFontHeight;
+ aDevice->DrawText(aRect, aText, nStyle);
+ }
+ else
+ {
+ *pFontWidth = nFontWidth;
+ *pFontHeight = nFontHeight;
- aDevice->DrawText(Point(0,0), aText);
- }
+ aDevice->DrawText(Point(0,0), aText);
+ }
- return pBuffer;
- }
- }
- return nullptr;
+ return pBuffer;
}
@@ -6042,7 +6055,7 @@ static void lo_runLoop(LibreOfficeKit* /*pThis*/,
static bool bInitialized = false;
-static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit::statusIndicatorCallbackType type, int percent)
+static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit::statusIndicatorCallbackType type, int percent, const char* pText)
{
LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(data);
@@ -6052,7 +6065,7 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
switch (type)
{
case comphelper::LibreOfficeKit::statusIndicatorCallbackType::Start:
- pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_START, nullptr, pLib->mpCallbackData);
+ pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_START, pText, pLib->mpCallbackData);
break;
case comphelper::LibreOfficeKit::statusIndicatorCallbackType::SetValue:
pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE,
diff --git a/editeng/source/uno/unotext.cxx b/editeng/source/uno/unotext.cxx
index 4796732b2c74..246bdc370be6 100644
--- a/editeng/source/uno/unotext.cxx
+++ b/editeng/source/uno/unotext.cxx
@@ -1736,13 +1736,6 @@ void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRan
if( !xRange.is() )
return;
- ESelection aSelection;
- if (GetEditSource())
- {
- ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
- SetSelection( aSelection );
- }
-
SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRange>( xRange );
if(pRange)
{
@@ -1757,6 +1750,13 @@ void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRan
pRange->setString( aString );
pRange->CollapseToEnd();
+
+ ESelection aSelection;
+ if (GetEditSource())
+ {
+ ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
+ SetSelection( aSelection );
+ }
}
}
diff --git a/external/gpgmepp/ExternalProject_gpgmepp.mk b/external/gpgmepp/ExternalProject_gpgmepp.mk
index 8ecdf60e6f87..d7835622ca21 100644
--- a/external/gpgmepp/ExternalProject_gpgmepp.mk
+++ b/external/gpgmepp/ExternalProject_gpgmepp.mk
@@ -39,7 +39,7 @@ $(call gb_ExternalProject_get_state_target,gpgmepp,build): $(call gb_Executable_
$(gb_COMPILEROPTFLAGS),$(gb_COMPILERNOOPTFLAGS)) \
$(if $(call gb_Module__symbols_enabled,gpgmepp),$(gb_DEBUGINFO_FLAGS))' \
--host=$(gb_ExternalProject_gpgmepp_host) \
- RC='windres -O COFF --target=$(gb_ExternalProject_gpgmepp_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \
+ RC='windres -O COFF --target=$(gb_ExternalProject_gpgmepp_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \
MAKE=$(MAKE) \
&& $(MAKE) \
)
diff --git a/external/libassuan/ExternalProject_libassuan.mk b/external/libassuan/ExternalProject_libassuan.mk
index 83d79a520988..899c21e4cec9 100644
--- a/external/libassuan/ExternalProject_libassuan.mk
+++ b/external/libassuan/ExternalProject_libassuan.mk
@@ -34,7 +34,7 @@ $(call gb_ExternalProject_get_state_target,libassuan,build): $(call gb_Executabl
GPG_ERROR_CFLAGS="$(GPG_ERROR_CFLAGS)" \
GPG_ERROR_LIBS="$(GPG_ERROR_LIBS)" \
--host=$(gb_ExternalProject_libassuan_host) \
- RC='windres -O COFF --target=$(gb_ExternalProject_libassuan_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \
+ RC='windres -O COFF --target=$(gb_ExternalProject_libassuan_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \
MAKE=$(MAKE) \
&& $(MAKE) \
)
diff --git a/external/libgpg-error/ExternalProject_libgpg-error.mk b/external/libgpg-error/ExternalProject_libgpg-error.mk
index 1fcd63180e20..e5155aad94c1 100644
--- a/external/libgpg-error/ExternalProject_libgpg-error.mk
+++ b/external/libgpg-error/ExternalProject_libgpg-error.mk
@@ -28,7 +28,7 @@ $(call gb_ExternalProject_get_state_target,libgpg-error,build): $(call gb_Execut
--disable-doc \
--disable-tests \
--host=$(gb_ExternalProject_libgpg-error_host) \
- RC='windres -O COFF --target=$(gb_ExternalProject_libgpg-error_target) --preprocessor='\''$(call gb_Executable_get_target,cpp) -+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)'\' \
+ RC='windres -O COFF --target=$(gb_ExternalProject_libgpg-error_target) --preprocessor=$(call gb_Executable_get_target,cpp) --preprocessor-arg=-+ -DRC_INVOKED -DWINAPI_FAMILY=0 $(SOLARINC)' \
&& $(MAKE) \
)
else
diff --git a/framework/source/helper/statusindicator.cxx b/framework/source/helper/statusindicator.cxx
index 25d67694c5df..12ea12b79476 100644
--- a/framework/source/helper/statusindicator.cxx
+++ b/framework/source/helper/statusindicator.cxx
@@ -41,7 +41,7 @@ void SAL_CALL StatusIndicator::start(const OUString& sText ,
m_nRange = nRange;
m_nLastCallbackPercent = -1;
- comphelper::LibreOfficeKit::statusIndicatorStart();
+ comphelper::LibreOfficeKit::statusIndicatorStart(sText);
}
#if !defined(IOS) && !defined(ANDROID)
css::uno::Reference< css::task::XStatusIndicatorFactory > xFactory(m_xFactory);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 82738d65ff93..8383aeb9d920 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -458,6 +458,12 @@ struct _LibreOfficeKitDocumentClass
void (*sendFormFieldEvent) (LibreOfficeKitDocument* pThis,
const char* pArguments);
+ /// @see lok::Document::setFreemiumDenyList
+ void (*setFreemiumDenyList) (const char* freemiumDenyList);
+
+ /// @see lok::Document::setFreemiumView
+ void (*setFreemiumView) (int nViewId, bool isFreemium);
+
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 4a58c4f2ee9d..59143ac98185 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -790,6 +790,16 @@ public:
mpDoc->pClass->sendFormFieldEvent(mpDoc, pArguments);
}
+ void setFreemiumDenyList(const char* freemiumDenyList)
+ {
+ mpDoc->pClass->setFreemiumDenyList(freemiumDenyList);
+ }
+
+ void setFreemiumView(int nViewId, bool isFreemium)
+ {
+ mpDoc->pClass->setFreemiumView(nViewId, isFreemium);
+ }
+
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index e9fb004511e5..50e9dfecb9c5 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -12,6 +12,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
+#include <vector>
class LanguageTag;
@@ -31,8 +32,9 @@ COMPHELPER_DLLPUBLIC void setActive(bool bActive = true);
enum class statusIndicatorCallbackType { Start, SetValue, Finish };
-COMPHELPER_DLLPUBLIC void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent), void *data);
-
+COMPHELPER_DLLPUBLIC void setStatusIndicatorCallback(
+ void (*callback)(void* data, statusIndicatorCallbackType type, int percent, const char* pText),
+ void* data);
// Functions that can be called from arbitrary places in LibreOffice.
@@ -104,10 +106,13 @@ COMPHELPER_DLLPUBLIC bool isWhitelistedLanguage(const OUString& lang);
// Status indicator handling. Even if in theory there could be several status indicators active at
// the same time, in practice there is only one at a time, so we don't handle any identification of
// status indicator in this API.
-COMPHELPER_DLLPUBLIC void statusIndicatorStart();
+COMPHELPER_DLLPUBLIC void statusIndicatorStart(const OUString& sText);
COMPHELPER_DLLPUBLIC void statusIndicatorSetValue(int percent);
COMPHELPER_DLLPUBLIC void statusIndicatorFinish();
+COMPHELPER_DLLPUBLIC void setFreemiumDenyList(const char* freemiumDenyList);
+COMPHELPER_DLLPUBLIC const std::vector<OUString>& getFreemiumDenyList();
+COMPHELPER_DLLPUBLIC bool isCommandFreemiumDenied(const OUString& command);
}
}
diff --git a/include/comphelper/profilezone.hxx b/include/comphelper/profilezone.hxx
index 36730e7f8af6..43c792e0fcf7 100644
--- a/include/comphelper/profilezone.hxx
+++ b/include/comphelper/profilezone.hxx
@@ -36,9 +36,7 @@ class COMPHELPER_DLLPUBLIC ProfileZone : public NamedEvent
{
if (s_bRecording)
{
- TimeValue systemTime;
- osl_getSystemTime( &systemTime );
- m_nCreateTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000;
+ m_nCreateTime = getNow();
m_nNesting = s_nNesting++;
}
diff --git a/include/comphelper/traceevent.hxx b/include/comphelper/traceevent.hxx
index cc3c390d7e59..ec95f46bd62c 100644
--- a/include/comphelper/traceevent.hxx
+++ b/include/comphelper/traceevent.hxx
@@ -43,6 +43,9 @@ private:
return -1;
}
+ static std::size_t s_nBufferSize;
+ static void (*s_pBufferFullCallback)();
+
protected:
static std::atomic<bool> s_bRecording; // true during recording
@@ -99,6 +102,7 @@ public:
static void startRecording();
static void stopRecording();
+ static void setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)());
static std::vector<OUString> getEventVectorAndClear();
@@ -123,33 +127,21 @@ protected:
}
};
-// An AsyncEvent generates a 'b' (begin) event when constructed and an 'e' (end) event when it
-// itself or its nesting parent (if there is one) is destructed (or earlier, if requested)
-
-// There are two kinds of async event pairs: Freestanding ones that are not related to other events
-// at all, and nested ones that have to be nested between the 'b' and 'e' events of a parent Async
-// event.
+// An AsyncEvent generates an 'S' (start) event when constructed and a 'F' (finish) event when it
+// is destructed.
-// To generate a pair of 'b' and 'e' events, create an AsyncEvent object using the AsyncEvent(const
-// char* sName) constructor when you want the 'b' event to be generated, and destroy it when you
-// want the corresponding 'e' event to be generated.
+// The Trace Event specification claims that these event types are deprecated and replaces by
+// nestable 'b' (begin) and 'e' (end) events, but Chrome does not seem to support those.
-// To generate a pair of 'b' and 'e' events that is nested inside an outer 'b' and 'e' event pair,
-// create an AsyncEvent object using the createWithParent() function. It returns a weak reference
-// (weak_ptr) to the AsyncEvent. The parent keeps a strong reference (shared_ptr) to it.
-
-// The 'e' event will be generated when the parent is about to go away, before the parent's 'e'
-// event. When the parent has gone away, the weak reference will have expired. You can also generate
-// it explicitly by calling the finish() function. (But in that case you could as well have used a
-// freestanding AsyncEvent object, I think.)
+// To generate a pair of 'S' and 'F' events, create an AsyncEvent object using the AsyncEvent(const
+// char* sName) constructor when you want the 'S' event to be generated, and destroy it when you
+// want the corresponding 'F' event to be generated.
class COMPHELPER_DLLPUBLIC AsyncEvent : public NamedEvent,
public std::enable_shared_from_this<AsyncEvent>
{
static int s_nIdCounter;
int m_nId;
- std::vector<std::shared_ptr<AsyncEvent>> m_aChildren;
- std::weak_ptr<AsyncEvent> m_pParent;
bool m_bBeginRecorded;
AsyncEvent(const char* sName, int nId, const std::map<OUString, OUString>& args)
@@ -161,12 +153,12 @@ class COMPHELPER_DLLPUBLIC AsyncEvent : public NamedEvent,
{
long long nNow = getNow();
- // Generate a "Begin " (type b) event
+ // Generate a "Start" (type S) event
TraceEvent::addRecording("{"
"\"name\":\""
+ OUString(m_sName, strlen(m_sName), RTL_TEXTENCODING_UTF8)
+ "\","
- "\"ph\":\"b\""
+ "\"ph\":\"S\""
","
"\"id\":"
+ OUString::number(m_nId) + m_sArgs
@@ -189,21 +181,13 @@ class COMPHELPER_DLLPUBLIC AsyncEvent : public NamedEvent,
{
m_bBeginRecorded = false;
- // In case somebody is holding on to a hard reference to a child we need to tell the
- // children to finish up explicitly, we can't rely on our pointers to them being the
- // only ones.
- for (auto& i : m_aChildren)
- i->generateEnd();
-
- m_aChildren.clear();
-
long long nNow = getNow();
- // Generate a "Env " (type e) event
+ // Generate a "Finish" (type F) event
TraceEvent::addRecording("{"
"\"name\":\""
+ OUString(m_sName, strlen(m_sName), RTL_TEXTENCODING_UTF8)
+ "\","
- "\"ph\":\"e\""
+ "\"ph\":\"F\""
","
"\"id\":"
+ OUString::number(m_nId) + m_sArgs
@@ -228,35 +212,7 @@ public:
~AsyncEvent() { generateEnd(); }
- static std::weak_ptr<AsyncEvent>
- createWithParent(const char* sName, std::shared_ptr<AsyncEvent> pParent,
- const std::map<OUString, OUString>& args = std::map<OUString, OUString>())
- {
- std::shared_ptr<AsyncEvent> pResult;
-
- if (s_bRecording && pParent->m_bBeginRecorded)
- {
- pResult.reset(new AsyncEvent(sName, pParent->m_nId, args));
- pParent->m_aChildren.push_back(pResult);
- pResult->m_pParent = pParent;
- }
-
- return pResult;
- }
-
- void finish()
- {
- generateEnd();
-
- auto pParent = m_pParent.lock();
- if (!pParent)
- return;
-
- pParent->m_aChildren.erase(std::remove(pParent->m_aChildren.begin(),
- pParent->m_aChildren.end(), shared_from_this()),
- pParent->m_aChildren.end());
- m_pParent.reset();
- }
+ void finish() { generateEnd(); }
};
} // namespace comphelper
diff --git a/include/oox/core/contexthandler2.hxx b/include/oox/core/contexthandler2.hxx
index 678aed1380c2..279459075980 100644
--- a/include/oox/core/contexthandler2.hxx
+++ b/include/oox/core/contexthandler2.hxx
@@ -73,7 +73,7 @@ struct ElementInfo;
class OOX_DLLPUBLIC ContextHandler2Helper
{
public:
- explicit ContextHandler2Helper( bool bEnableTrimSpace );
+ explicit ContextHandler2Helper( bool bEnableTrimSpace, XmlFilterBase& rFilter );
explicit ContextHandler2Helper( const ContextHandler2Helper& rParent );
virtual ~ContextHandler2Helper();
@@ -202,6 +202,21 @@ protected:
/** Must be called from endRecord() in derived classes. */
void implEndRecord( sal_Int32 nRecId );
+ bool prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs );
+ XmlFilterBase& getDocFilter() const { return mrFilter; }
+
+ enum class MCE_STATE
+ {
+ Started,
+ FoundChoice
+ };
+
+ MCE_STATE getMCEState() const { return aMceState.back(); }
+ void setMCEState( MCE_STATE aState ) { aMceState.back() = aState; }
+ void addMCEState( MCE_STATE aState ) { aMceState.push_back( aState ); }
+ void removeMCEState() { aMceState.pop_back(); }
+ bool isMCEStateEmpty() { return aMceState.empty(); }
+
private:
ContextHandler2Helper& operator=( const ContextHandler2Helper& ) = delete;
@@ -215,9 +230,11 @@ private:
ContextStackRef mxContextStack; ///< Stack of all processed elements.
size_t const mnRootStackSize; ///< Stack size on construction time.
+ std::vector<MCE_STATE> aMceState;
protected:
bool mbEnableTrimSpace; ///< True = trim whitespace in characters().
+ XmlFilterBase& mrFilter;
};
class OOX_DLLPUBLIC ContextHandler2 : public ContextHandler, public ContextHandler2Helper
diff --git a/include/oox/core/fragmenthandler2.hxx b/include/oox/core/fragmenthandler2.hxx
index 7c64c200041d..162ec8565fdb 100644
--- a/include/oox/core/fragmenthandler2.hxx
+++ b/include/oox/core/fragmenthandler2.hxx
@@ -48,17 +48,6 @@ class XmlFilterBase;
class OOX_DLLPUBLIC FragmentHandler2 : public FragmentHandler, public ContextHandler2Helper
{
-protected:
- enum class MCE_STATE
- {
- Started,
- FoundChoice
- };
- ::std::vector<MCE_STATE> aMceState;
-
- bool prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs );
-
-
public:
explicit FragmentHandler2(
XmlFilterBase& rFilter,
diff --git a/include/oox/drawingml/graphicshapecontext.hxx b/include/oox/drawingml/graphicshapecontext.hxx
index 14b49f23615c..c27a8e6cfa8d 100644
--- a/include/oox/drawingml/graphicshapecontext.hxx
+++ b/include/oox/drawingml/graphicshapecontext.hxx
@@ -62,6 +62,7 @@ public:
OleObjectGraphicDataContext( ::oox::core::ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr );
virtual ~OleObjectGraphicDataContext() override;
virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) override;
+ virtual void onEndElement() override;
private:
::oox::vml::OleObjectInfo& mrOleObjectInfo;
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 5b6fd21ce00d..37e2fe433a3f 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -178,6 +178,7 @@ public:
ShapeStyleRefMap& getShapeStyleRefs() { return maShapeStyleRefs; }
const ShapeStyleRefMap& getShapeStyleRefs() const { return maShapeStyleRefs; }
const ShapeStyleRef* getShapeStyleRef( sal_Int32 nRefType ) const;
+ bool hasShapeStyleRefs() const { return !maShapeStyleRefs.empty(); }
// addShape is creating and inserting the corresponding XShape.
void addShape(
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index fb7b7877138c..fa309108c055 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -45,6 +45,8 @@
class Graphic;
class SdrObjCustomShape;
+enum class SvxDateFormat;
+enum class SvxTimeFormat;
namespace com { namespace sun { namespace star {
namespace awt {
@@ -156,6 +158,22 @@ protected:
const css::uno::Reference< css::beans::XPropertyState >& rXPropState,
const OUString& aName, css::beans::PropertyState& eState );
OUString GetFieldValue( const css::uno::Reference< css::text::XTextRange >& rRun, bool& bIsURLField );
+ /** Gets OOXML datetime field type from LO Date format
+
+ @param eDate LO Date format
+ */
+ static OUString GetDatetimeTypeFromDate(SvxDateFormat eDate);
+ /** Gets OOXML datetime field type from LO Time format
+
+ @param eTime LO Time format
+ */
+ static OUString GetDatetimeTypeFromTime(SvxTimeFormat eTime);
+ /** Gets OOXML datetime field type from combination of LO Time and Date formats
+
+ @param eDate LO Date format
+ @param eTime LO Time format
+ */
+ static OUString GetDatetimeTypeFromDateTime(SvxDateFormat eDate, SvxTimeFormat eTime);
/// Output the media (including copying a video from vnd.sun.star.Package: to the output if necessary).
void WriteMediaNonVisualProperties(const css::uno::Reference<css::drawing::XShape>& xShape);
@@ -241,10 +259,19 @@ public:
void WriteTransformation(const tools::Rectangle& rRectangle,
sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, sal_Int32 nRotation = 0, bool bIsGroupShape = false);
- void WriteText( const css::uno::Reference< css::uno::XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText = true, sal_Int32 nXmlNamespace = 0);
+ void WriteText( const css::uno::Reference< css::uno::XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText = true, sal_Int32 nXmlNamespace = 0, bool bWritePropertiesAsLstStyles = false);
+
+ /** Populates the lstStyle with the shape's text run and paragraph properties */
+ void WriteLstStyles(const css::uno::Reference<css::text::XTextContent>& rParagraph,
+ bool& rbOverridingCharHeight, sal_Int32& rnCharHeight,
+ const css::uno::Reference<css::beans::XPropertySet>& rXShapePropSet);
void WriteParagraph( const css::uno::Reference< css::text::XTextContent >& rParagraph,
bool& rbOverridingCharHeight, sal_Int32& rnCharHeight );
- void WriteParagraphProperties(const css::uno::Reference< css::text::XTextContent >& rParagraph, float fFirstCharHeight);
+ /** Writes paragraph properties
+
+ @returns true if any paragraph properties were written
+ */
+ bool WriteParagraphProperties(const css::uno::Reference< css::text::XTextContent >& rParagraph, float fFirstCharHeight, const sal_Int32 nElement = XML_pPr );
void WriteParagraphNumbering(const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, float fFirstCharHeight,
sal_Int16 nLevel );
void WriteParagraphTabStops(const css::uno::Reference<css::beans::XPropertySet>& rXPropSet);
diff --git a/include/oox/export/shapes.hxx b/include/oox/export/shapes.hxx
index a8ea2d5c6005..aae207ff1464 100644
--- a/include/oox/export/shapes.hxx
+++ b/include/oox/export/shapes.hxx
@@ -179,7 +179,7 @@ public:
* @return <tt>*this</tt>
*/
ShapeExport& WriteShape( const css::uno::Reference< css::drawing::XShape >& xShape );
- ShapeExport& WriteTextBox( const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nXmlNamespace );
+ ShapeExport& WriteTextBox( const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles = false );
virtual ShapeExport&
WriteTextShape( const css::uno::Reference< css::drawing::XShape >& xShape );
ShapeExport&
diff --git a/include/oox/ole/oleobjecthelper.hxx b/include/oox/ole/oleobjecthelper.hxx
index 604785f305b6..a133bd650443 100644
--- a/include/oox/ole/oleobjecthelper.hxx
+++ b/include/oox/ole/oleobjecthelper.hxx
@@ -48,6 +48,7 @@ struct OOX_DLLPUBLIC OleObjectInfo
bool mbLinked; ///< True = linked OLE object, false = embedded OLE object.
bool mbShowAsIcon; ///< True = show as icon, false = show contents.
bool mbAutoUpdate;
+ bool mbHasPicture; ///<Ole object requires a picture element according to spec.>
explicit OleObjectInfo();
};
diff --git a/include/oox/ppt/pptshape.hxx b/include/oox/ppt/pptshape.hxx
index c5d9e7be5548..71af3a08e291 100644
--- a/include/oox/ppt/pptshape.hxx
+++ b/include/oox/ppt/pptshape.hxx
@@ -51,6 +51,10 @@ class PPTShape final : public oox::drawingml::Shape
bool mbReferenced; // placeholdershapes on Layout are displayed only, if they are not referenced
// placeholdershapes on Slide are displayed always
oox::drawingml::ShapePtr mpPlaceholder;
+ /// Set if spPr tag is non empty for the shape
+ bool mbHasNoninheritedShapeProperties;
+
+ bool IsPlaceHolderCandidate(const SlidePersist& rSlidePersist) const;
public:
@@ -74,6 +78,11 @@ public:
void setPlaceholder( oox::drawingml::ShapePtr pPlaceholder ) { mpPlaceholder = pPlaceholder; }
void setModelId( const OUString& rId ) { msModelId = rId; }
+ /// Flags shape as having a non-empty spPr tag
+ void setHasNoninheritedShapeProperties() { mbHasNoninheritedShapeProperties = true; }
+ /// Returns whether or not the shape had a non-empty spPr tag
+ bool hasNonInheritedShapeProperties() const { return mbHasNoninheritedShapeProperties; }
+
static oox::drawingml::ShapePtr findPlaceholder( const sal_Int32 nFirstSubType,
const sal_Int32 nSecondSubType, const OptValue< sal_Int32 >& oSubTypeIndex,
std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly = false );
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 3e37b8b68597..9c91a1724844 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -53,13 +53,16 @@ public:
static void destroyView(int nId);
/// Set a view shell as current one.
static void setView(int nId);
+ /// Get view shell with id
+ static SfxViewShell* getViewOfId(int nId);
/// Get the currently active view.
static int getView(const SfxViewShell* pViewShell = nullptr);
/// Get the number of views of the current DocId.
static std::size_t getViewsCount(int nDocId);
/// Get viewIds of views of the current DocId.
static bool getViewIds(int nDocId, int* pArray, size_t nSize);
-
+ /// Set View Freemium
+ static void setFreemiumView(int nViewId, bool isFreemium);
/// Get the document id for a view
static int getDocumentIdOfView(int nViewId);
/// Get the default language that should be used for views
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index dedef69a65b9..a34e0629185e 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -160,6 +160,7 @@ friend class SfxPrinterController;
LanguageTag maLOKLanguageTag;
LanguageTag maLOKLocale;
LOKDeviceFormFactor maLOKDeviceFormFactor;
+ bool mbLOKIsFreemiumView;
/// Used to set the DocId at construction time. See SetCurrentDocId.
static ViewShellDocId mnCurrentDocId;
@@ -385,6 +386,10 @@ public:
bool isLOKMobilePhone() const { return maLOKDeviceFormFactor == LOKDeviceFormFactor::MOBILE; }
virtual tools::Rectangle getLOKVisibleArea() const { return tools::Rectangle(); }
+
+ // Fremium view settings
+ void setFreemiumView(bool isFreemium) { mbLOKIsFreemiumView = isFreemium; }
+ bool isFreemiumView() { return mbLOKIsFreemiumView; }
};
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index d9b6651e0c9e..137eda8f533f 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -854,6 +854,8 @@ private:
SAL_DLLPRIVATE void ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly);
///@}
+ SAL_DLLPRIVATE void ImplDrawWaveLineBezier(long nStartX, long nStartY, long nEndX, long nEndY, long nWaveHeight, double fOrientation, long nLineWidth);
+
/** @name Curved shape functions
*/
diff --git a/oox/inc/drawingml/textbody.hxx b/oox/inc/drawingml/textbody.hxx
index 8cc3a70b254a..54f40b9098b8 100644
--- a/oox/inc/drawingml/textbody.hxx
+++ b/oox/inc/drawingml/textbody.hxx
@@ -68,6 +68,23 @@ public:
bool isEmpty() const;
OUString toString() const;
+ /** Returns whether the textbody had a rPr tag in it that alters it visually
+ *
+ * For instance _lang_ doesn't have a visual effect.
+ */
+ bool hasVisualRunProperties() const;
+
+ /// Returns whether the textbody had a pPr tag in it
+ bool hasParagraphProperties() const;
+
+ /// Returns whether the textbody had a non-empty bodyPr tag in it
+ bool hasNoninheritedBodyProperties() const { return mbHasNoninheritedBodyProperties; }
+ /// Flags textbody as having a non-empty bodyPr tag
+ void setHasNoninheritedBodyProperties() { mbHasNoninheritedBodyProperties = true; }
+
+ /// Returns whether the textbody had a non-empty lstStyle tag in it
+ bool hasListStyleOnImport() const { return maTextListStyle.hasListStyleOnImport(); }
+
void ApplyStyleEmpty(
const ::oox::core::XmlFilterBase& rFilterBase,
const css::uno::Reference < css::text::XText > & xText,
@@ -76,6 +93,8 @@ public:
protected:
TextParagraphVector maParagraphs;
TextBodyProperties maTextProperties;
+ /// Set if bodyPr tag in this textbody is non-empty during import
+ bool mbHasNoninheritedBodyProperties;
TextListStyle maTextListStyle;
Text3DProperties ma3DProperties;
};
diff --git a/oox/inc/drawingml/textcharacterproperties.hxx b/oox/inc/drawingml/textcharacterproperties.hxx
index a034121e47d0..147a9847781d 100644
--- a/oox/inc/drawingml/textcharacterproperties.hxx
+++ b/oox/inc/drawingml/textcharacterproperties.hxx
@@ -59,6 +59,8 @@ struct TextCharacterProperties
OptValue< bool > moUnderlineLineFollowText;
OptValue< bool > moUnderlineFillFollowText;
FillProperties maFillProperties;
+ /// Set if there was a property set that alters run visually during import
+ bool mbHasVisualRunProperties;
std::vector<css::beans::PropertyValue> maTextEffectsProperties;
@@ -79,6 +81,8 @@ struct TextCharacterProperties
void pushToPropSet(
PropertySet& rPropSet,
const ::oox::core::XmlFilterBase& rFilter ) const;
+
+ TextCharacterProperties() : mbHasVisualRunProperties(false) {}
};
diff --git a/oox/inc/drawingml/textfield.hxx b/oox/inc/drawingml/textfield.hxx
index 7cc15a04fce4..f70f0989ac7b 100644
--- a/oox/inc/drawingml/textfield.hxx
+++ b/oox/inc/drawingml/textfield.hxx
@@ -24,6 +24,9 @@
#include <drawingml/textparagraphproperties.hxx>
#include <memory>
+enum class SvxTimeFormat;
+enum class SvxDateFormat;
+
namespace oox { namespace drawingml {
struct TextCharacterProperties;
@@ -49,6 +52,16 @@ public:
const TextCharacterProperties& rTextCharacterStyle,
float nDefaultCharHeight) const override;
+ /** Gets the corresponding LO Date format for given OOXML datetime field type
+ *
+ * @param rDateTimeType PPTX datetime field type e.g. datetime3
+ */
+ static SvxDateFormat getLODateFormat( std::u16string_view rDateTimeType );
+ /** Gets the corresponding LO Time format for given OOXML datetime field type
+ *
+ * @param rDateTimeType PPTX datetime field type e.g. datetime3
+ */
+ static SvxTimeFormat getLOTimeFormat( std::u16string_view rDateTimeType );
private:
TextParagraphProperties maTextParagraphProperties;
OUString msType;
diff --git a/oox/inc/drawingml/textliststyle.hxx b/oox/inc/drawingml/textliststyle.hxx
index 94b6b10dc569..d4b5297ffb6d 100644
--- a/oox/inc/drawingml/textliststyle.hxx
+++ b/oox/inc/drawingml/textliststyle.hxx
@@ -45,6 +45,14 @@ public:
const TextParagraphPropertiesVector& getAggregationListStyle() const { return maAggregationListStyle; };
TextParagraphPropertiesVector& getAggregationListStyle() { return maAggregationListStyle; };
+ /// Flags ListStyle as having a non-empty lstStyle tag on import
+ void setHasListStyleOnImport() { mbHasListStyleOnImport = true; }
+ /** Returns whether the lstStyle tag was non-empty on import
+ *
+ * @return true if list style has it's own noninherited properties.
+ */
+ bool hasListStyleOnImport() const { return mbHasListStyleOnImport; }
+
#ifdef DBG_UTIL
void dump() const;
#endif
@@ -53,6 +61,8 @@ private:
TextParagraphPropertiesVector maListStyle;
TextParagraphPropertiesVector maAggregationListStyle;
+ /// Set if ListStyle has a non-empty lstStyle tag on import
+ bool mbHasListStyleOnImport;
};
} }
diff --git a/oox/inc/drawingml/textparagraph.hxx b/oox/inc/drawingml/textparagraph.hxx
index ec0d57686e1b..27c7cb251271 100644
--- a/oox/inc/drawingml/textparagraph.hxx
+++ b/oox/inc/drawingml/textparagraph.hxx
@@ -52,6 +52,10 @@ public:
TextParagraphProperties& getProperties() { return maProperties; }
const TextParagraphProperties& getProperties() const { return maProperties; }
+ /// Flags the textparagraph as having a pPr tag in it
+ void setHasProperties() { mbHasProperties = true; }
+ /// Returns whether the textparagraph had an pPr tag in it during import
+ bool hasProperties() const { return mbHasProperties; }
TextCharacterProperties& getEndProperties() { return maEndProperties; }
const TextCharacterProperties& getEndProperties() const { return maEndProperties; }
@@ -78,8 +82,15 @@ public:
}
formulaimport::XmlStreamBuilder & GetMathXml();
+ /** Returns whether textparagraph had a rPr tag in it that alters it visually
+ *
+ * For instance _lang_ doesn't have a visual effect.
+ */
+ bool hasVisualRunProperties() const;
+
private:
TextParagraphProperties maProperties;
+ bool mbHasProperties;
TextCharacterProperties maEndProperties;
TextRunVector maRuns;
// temporarily store this here
diff --git a/oox/inc/drawingml/textrun.hxx b/oox/inc/drawingml/textrun.hxx
index 8d3e2c499bc6..4df18764ea08 100644
--- a/oox/inc/drawingml/textrun.hxx
+++ b/oox/inc/drawingml/textrun.hxx
@@ -43,6 +43,12 @@ public:
void setLineBreak() { mbIsLineBreak = true; }
bool isLineBreak() const { return mbIsLineBreak; }
+ /** Returns whether the textrun had properties that alter it visually in its rPr tag
+ *
+ * For instance _lang_ doesn't have a visual effect.
+ */
+ bool hasVisualRunProperties() const { return maTextCharacterProperties.mbHasVisualRunProperties; }
+
virtual sal_Int32 insertAt(
const ::oox::core::XmlFilterBase& rFilterBase,
const css::uno::Reference < css::text::XText >& xText,
diff --git a/oox/source/core/contexthandler2.cxx b/oox/source/core/contexthandler2.cxx
index ab9cea4a49fc..bde8d5abdb53 100644
--- a/oox/source/core/contexthandler2.cxx
+++ b/oox/source/core/contexthandler2.cxx
@@ -18,16 +18,20 @@
*/
#include <oox/core/contexthandler2.hxx>
+#include <oox/core/xmlfilterbase.hxx>
#include <oox/helper/attributelist.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
namespace oox {
namespace core {
using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::xml::sax;
/** Information about a processed element. */
@@ -40,10 +44,11 @@ struct ElementInfo
explicit ElementInfo() : maChars( 0), mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {}
};
-ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
+ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace, XmlFilterBase& rFilter ) :
mxContextStack( new ContextStack ),
mnRootStackSize( 0 ),
- mbEnableTrimSpace( bEnableTrimSpace )
+ mbEnableTrimSpace( bEnableTrimSpace ),
+ mrFilter( rFilter )
{
pushElementInfo( XML_ROOT_CONTEXT );
}
@@ -51,7 +56,8 @@ ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) :
mxContextStack( rParent.mxContextStack ),
mnRootStackSize( rParent.mxContextStack->size() ),
- mbEnableTrimSpace( rParent.mbEnableTrimSpace )
+ mbEnableTrimSpace( rParent.mbEnableTrimSpace ),
+ mrFilter(rParent.mrFilter)
{
}
@@ -188,6 +194,13 @@ ContextHandler2::~ContextHandler2()
Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext(
sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
{
+ if( getNamespace( nElement ) == NMSP_mce ) // TODO for checking 'Ignorable'
+ {
+ if( prepareMceContext( nElement, AttributeList( rxAttribs ) ) )
+ return this;
+ return nullptr;
+ }
+
return implCreateChildContext( nElement, rxAttribs );
}
@@ -207,6 +220,72 @@ void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement )
implEndElement( nElement );
}
+bool ContextHandler2Helper::prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ switch( nElement )
+ {
+ case MCE_TOKEN( AlternateContent ):
+ addMCEState( MCE_STATE::Started );
+ break;
+
+ case MCE_TOKEN( Choice ):
+ {
+ if (isMCEStateEmpty() || getMCEState() != MCE_STATE::Started)
+ return false;
+
+ OUString aRequires = rAttribs.getString( XML_Requires, "none" );
+
+ // At this point we can't access namespaces as the correct xml filter
+ // is long gone. For now let's decide depending on a list of supported
+ // namespaces like we do in writerfilter
+
+ std::vector<OUString> aSupportedNS =
+ {
+ "a14", // Impress needs this to import math formulas.
+ "p14",
+ "p15",
+ "x12ac",
+ "v"
+ };
+
+ Reference<XServiceInfo> xModel(getDocFilter().getModel(), UNO_QUERY);
+ if (xModel.is() && xModel->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
+ {
+ // No a14 for Calc documents, it would cause duplicated shapes as-is.
+ auto it = std::find(aSupportedNS.begin(), aSupportedNS.end(), "a14");
+ if (it != aSupportedNS.end())
+ {
+ aSupportedNS.erase(it);
+ }
+ }
+
+ if (std::find(aSupportedNS.begin(), aSupportedNS.end(), aRequires) != aSupportedNS.end())
+ setMCEState( MCE_STATE::FoundChoice ) ;
+ else
+ return false;
+ }
+ break;
+
+ case MCE_TOKEN( Fallback ):
+ if( !isMCEStateEmpty() && getMCEState() == MCE_STATE::Started )
+ break;
+ return false;
+ default:
+ {
+ OUString str = rAttribs.getString( MCE_TOKEN( Ignorable ), OUString() );
+ if( !str.isEmpty() )
+ {
+ // Sequence< css::xml::FastAttribute > attrs = rAttribs.getFastAttributeList()->getFastAttributes();
+ // printf("MCE: %s\n", OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ // TODO: Check & Get the namespaces in "Ignorable"
+ // printf("NS: %d : %s\n", attrs.getLength(), OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ return false;
+ }
+ return true;
+}
+
// oox.core.RecordContext interface -------------------------------------------
ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
diff --git a/oox/source/core/fragmenthandler2.cxx b/oox/source/core/fragmenthandler2.cxx
index 79b58ce70f0e..cbad55571b09 100644
--- a/oox/source/core/fragmenthandler2.cxx
+++ b/oox/source/core/fragmenthandler2.cxx
@@ -34,7 +34,7 @@ using ::com::sun::star::uno::Sequence;
FragmentHandler2::FragmentHandler2( XmlFilterBase& rFilter, const OUString& rFragmentPath, bool bEnableTrimSpace ) :
FragmentHandler( rFilter, rFragmentPath ),
- ContextHandler2Helper( bEnableTrimSpace )
+ ContextHandler2Helper( bEnableTrimSpace, rFilter )
{
}
@@ -54,72 +54,6 @@ void SAL_CALL FragmentHandler2::endDocument()
finalizeImport();
}
-bool FragmentHandler2::prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs )
-{
- switch( nElement )
- {
- case MCE_TOKEN( AlternateContent ):
- aMceState.push_back( MCE_STATE::Started );
- break;
-
- case MCE_TOKEN( Choice ):
- {
- if (aMceState.empty() || aMceState.back() != MCE_STATE::Started)
- return false;
-
- OUString aRequires = rAttribs.getString( XML_Requires, "none" );
-
- // At this point we can't access namespaces as the correct xml filter
- // is long gone. For now let's decide depending on a list of supported
- // namespaces like we do in writerfilter
-
- std::vector<OUString> aSupportedNS =
- {
- "a14", // Impress needs this to import math formulas.
- "p14",
- "p15",
- "x12ac",
- "v",
- };
-
- uno::Reference<lang::XServiceInfo> xModel(getFilter().getModel(), uno::UNO_QUERY);
- if (xModel.is() && xModel->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
- {
- // No a14 for Calc documents, it would cause duplicated shapes as-is.
- auto it = std::find(aSupportedNS.begin(), aSupportedNS.end(), "a14");
- if (it != aSupportedNS.end())
- {
- aSupportedNS.erase(it);
- }
- }
-
- if (std::find(aSupportedNS.begin(), aSupportedNS.end(), aRequires) != aSupportedNS.end())
- aMceState.back() = MCE_STATE::FoundChoice;
- else
- return false;
- }
- break;
-
- case MCE_TOKEN( Fallback ):
- if( !aMceState.empty() && aMceState.back() == MCE_STATE::Started )
- break;
- return false;
- default:
- {
- OUString str = rAttribs.getString( MCE_TOKEN( Ignorable ), OUString() );
- if( !str.isEmpty() )
- {
- // Sequence< css::xml::FastAttribute > attrs = rAttribs.getFastAttributeList()->getFastAttributes();
- // printf("MCE: %s\n", OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
- // TODO: Check & Get the namespaces in "Ignorable"
- // printf("NS: %d : %s\n", attrs.getLength(), OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
- }
- }
- return false;
- }
- return true;
-}
-
// com.sun.star.xml.sax.XFastContextHandler interface -------------------------
Reference< XFastContextHandler > SAL_CALL FragmentHandler2::createFastChildContext(
@@ -151,7 +85,7 @@ void SAL_CALL FragmentHandler2::endFastElement( sal_Int32 nElement )
switch( nElement )
{
case MCE_TOKEN( AlternateContent ):
- aMceState.pop_back();
+ removeMCEState();
break;
}
diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx
index 1c22a33b9ca1..67f1a8bc6633 100644
--- a/oox/source/drawingml/graphicshapecontext.cxx
+++ b/oox/source/drawingml/graphicshapecontext.cxx
@@ -219,6 +219,7 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
mrOleObjectInfo.maName = rAttribs.getXString( XML_name, OUString() );
mrOleObjectInfo.maProgId = rAttribs.getXString( XML_progId, OUString() );
mrOleObjectInfo.mbShowAsIcon = rAttribs.getBool( XML_showAsIcon, false );
+ mrOleObjectInfo.mbHasPicture = false; // Initialize as false
return this;
}
break;
@@ -232,6 +233,7 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
mrOleObjectInfo.mbAutoUpdate = rAttribs.getBool( XML_updateAutomatic, false );
break;
case PPT_TOKEN( pic ):
+ mrOleObjectInfo.mbHasPicture = true; // Set true if ole object has picture element.
return new GraphicShapeContext( *this, mpMasterShapePtr, mpShapePtr );
break;
}
@@ -240,6 +242,15 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
return nullptr;
}
+void OleObjectGraphicDataContext::onEndElement()
+{
+ if( getCurrentElement() == PPT_TOKEN( oleObj ) && !isMCEStateEmpty() )
+ {
+ if( getMCEState() == MCE_STATE::FoundChoice && !mrOleObjectInfo.mbHasPicture )
+ setMCEState( MCE_STATE::Started );
+ }
+}
+
DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr )
: ShapeContext( rParent, ShapePtr(), pShapePtr )
{
diff --git a/oox/source/drawingml/textbody.cxx b/oox/source/drawingml/textbody.cxx
index 80ebb4d2287d..323d654ce971 100644
--- a/oox/source/drawingml/textbody.cxx
+++ b/oox/source/drawingml/textbody.cxx
@@ -32,10 +32,12 @@ using namespace ::com::sun::star::beans;
namespace oox { namespace drawingml {
TextBody::TextBody()
+ : mbHasNoninheritedBodyProperties( false )
{
}
TextBody::TextBody( const TextBodyPtr& pBody )
+ : mbHasNoninheritedBodyProperties( false )
{
if( pBody.get() ) {
maTextProperties = pBody->maTextProperties;
@@ -104,6 +106,26 @@ OUString TextBody::toString() const
return OUString();
}
+bool TextBody::hasVisualRunProperties() const
+{
+ for ( auto& pTextParagraph : getParagraphs() )
+ {
+ if ( pTextParagraph->hasVisualRunProperties() )
+ return true;
+ }
+ return false;
+}
+
+bool TextBody::hasParagraphProperties() const
+{
+ for ( auto& pTextParagraph : getParagraphs() )
+ {
+ if ( pTextParagraph->hasProperties() )
+ return true;
+ }
+ return false;
+}
+
void TextBody::ApplyStyleEmpty(
const ::oox::core::XmlFilterBase& rFilterBase,
const Reference < XText > & xText,
diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx
index cbd1e420ee5a..3e0637c87f91 100644
--- a/oox/source/drawingml/textbodycontext.cxx
+++ b/oox/source/drawingml/textbodycontext.cxx
@@ -28,6 +28,8 @@
#include <oox/drawingml/shape.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
+#include <oox/helper/attributelist.hxx>
+#include <sax/fastattribs.hxx>
#include <oox/mathml/import.hxx>
@@ -86,6 +88,7 @@ ContextHandlerRef TextParagraphContext::onCreateContext( sal_Int32 aElementToken
}
case A_TOKEN( pPr ):
case W_TOKEN( pPr ):
+ mrParagraph.setHasProperties();
return new TextParagraphPropertiesContext( *this, rAttribs, mrParagraph.getProperties() );
case A_TOKEN( endParaRPr ):
return new TextCharacterPropertiesContext( *this, rAttribs, mrParagraph.getEndProperties() );
@@ -175,6 +178,8 @@ ContextHandlerRef TextBodyContext::onCreateContext( sal_Int32 aElementToken, con
switch( aElementToken )
{
case A_TOKEN( bodyPr ): // CT_TextBodyPropertyBag
+ if (sax_fastparser::FastAttributeList::castToFastAttributeList(rAttribs.getFastAttributeList())->getFastAttributeTokens().size() > 0)
+ mrTextBody.setHasNoninheritedBodyProperties();
if ( mpShapePtr )
return new TextBodyPropertiesContext( *this, rAttribs, mpShapePtr );
else
diff --git a/oox/source/drawingml/textcharacterpropertiescontext.cxx b/oox/source/drawingml/textcharacterpropertiescontext.cxx
index 236219d844cf..2bc7be3633c1 100644
--- a/oox/source/drawingml/textcharacterpropertiescontext.cxx
+++ b/oox/source/drawingml/textcharacterpropertiescontext.cxx
@@ -29,6 +29,8 @@
#include "hyperlinkcontext.hxx"
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
+#include <sax/fastattribs.hxx>
+#include <sax/fastparser.hxx>
#include <sal/log.hxx>
@@ -47,8 +49,16 @@ TextCharacterPropertiesContext::TextCharacterPropertiesContext(
: ContextHandler2( rParent )
, mrTextCharacterProperties( rTextCharacterProperties )
{
- if ( rAttribs.hasAttribute( XML_lang ) )
+ int nVisualTokenAmount = sax_fastparser::FastAttributeList::castToFastAttributeList(
+ rAttribs.getFastAttributeList() )->getFastAttributeTokens().size();
+
+ if ( rAttribs.hasAttribute( XML_lang ) ){
mrTextCharacterProperties.moLang = rAttribs.getString( XML_lang );
+ --nVisualTokenAmount; // Not a visual attribute
+ }
+ if ( rAttribs.hasAttribute( XML_altLang )){
+ --nVisualTokenAmount; // Not a visual attribute
+ }
if ( rAttribs.hasAttribute( XML_sz ) )
mrTextCharacterProperties.moHeight = rAttribs.getInteger( XML_sz );
if ( rAttribs.hasAttribute( XML_spc ) )
@@ -66,6 +76,17 @@ TextCharacterPropertiesContext::TextCharacterPropertiesContext(
mrTextCharacterProperties.moItalic = rAttribs.getBool( XML_i );
if( rAttribs.hasAttribute( XML_cap ) )
mrTextCharacterProperties.moCaseMap = rAttribs.getToken( XML_cap );
+ if ( rAttribs.hasAttribute( XML_dirty ) )
+ {
+ --nVisualTokenAmount; // Not a visual attribute
+ }
+ if ( rAttribs.hasAttribute( XML_smtClean ) )
+ {
+ --nVisualTokenAmount; // Not a visual attribute
+ }
+
+ if ( nVisualTokenAmount > 0 )
+ mrTextCharacterProperties.mbHasVisualRunProperties = true;
/* TODO / unhandled so far:
A_TOKEN( kern )
@@ -87,6 +108,9 @@ TextCharacterPropertiesContext::~TextCharacterPropertiesContext()
ContextHandlerRef TextCharacterPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
{
+ if( aElementToken != A_TOKEN(lang) )
+ mrTextCharacterProperties.mbHasVisualRunProperties = true;
+
switch( aElementToken )
{
// TODO unsupported yet
diff --git a/oox/source/drawingml/textfield.cxx b/oox/source/drawingml/textfield.cxx
index 61b50e8ef549..a8e058603f7a 100644
--- a/oox/source/drawingml/textfield.cxx
+++ b/oox/source/drawingml/textfield.cxx
@@ -34,6 +34,7 @@
#include <drawingml/textparagraphproperties.hxx>
#include <drawingml/textcharacterproperties.hxx>
#include <tools/diagnose_ex.h>
+#include <editeng/flditem.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
@@ -73,68 +74,28 @@ void lclCreateTextFields( std::vector< Reference< XTextField > > & aFields,
aFields.emplace_back( xIface, UNO_QUERY );
return;
}
- bool bIsDate = true;
- int idx = p.toInt32();
- sal_uInt16 nNumFmt;
- xIface = xFactory->createInstance( "com.sun.star.text.TextField.DateTime" );
- aFields.emplace_back( xIface, UNO_QUERY );
- Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW );
-
- // here we should format the field properly. waiting after #i81091.
- switch( idx )
+
+ SvxDateFormat eDateFormat = TextField::getLODateFormat(sType);
+ if (eDateFormat != SvxDateFormat::AppDefault)
{
- case 1: // Date dd/mm/yyyy
- // this is the default format...
- nNumFmt = 5;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- case 2: // Date Day, Month dd, yyyy
- break;
- case 3: // Date dd Month yyyy
- nNumFmt = 3;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- case 4: // Date Month dd, yyyy
- break;
- case 5: // Date dd-Mon-yy
- break;
- case 6: // Date Month yy
- break;
- case 7: // Date Mon-yy
- break;
- case 8: // DateTime dd/mm/yyyy H:MM PM
- lclCreateTextFields( aFields, xModel, "datetime12" );
- break;
- case 9: // DateTime dd/mm/yy H:MM:SS PM
- lclCreateTextFields( aFields, xModel, "datetime13" );
- break;
- case 10: // Time H:MM
- bIsDate = false;
- nNumFmt = 3;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- case 11: // Time H:MM:SS
- bIsDate = false;
- // this is the default format
- nNumFmt = 2;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- case 12: // Time H:MM PM
- bIsDate = false;
- nNumFmt = 6;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- case 13: // Time H:MM:SS PM
- bIsDate = false;
- nNumFmt = 7;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
- break;
- default:
- nNumFmt = 2;
- xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
+ xIface = xFactory->createInstance( "com.sun.star.text.TextField.DateTime" );
+ aFields.emplace_back( xIface, UNO_QUERY );
+ Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW );
+ xProps->setPropertyValue("NumberFormat", Any(static_cast<sal_Int32>(eDateFormat)));
+ xProps->setPropertyValue("IsDate", Any(true));
+ xProps->setPropertyValue("IsFixed", Any(false));
+ }
+
+ SvxTimeFormat eTimeFormat = TextField::getLOTimeFormat(sType);
+ if (eTimeFormat != SvxTimeFormat::AppDefault)
+ {
+ xIface = xFactory->createInstance( "com.sun.star.text.TextField.DateTime" );
+ aFields.emplace_back( xIface, UNO_QUERY );
+ Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW );
+ xProps->setPropertyValue("NumberFormat", Any(static_cast<sal_Int32>(eTimeFormat)));
+ xProps->setPropertyValue("IsDate", Any(false));
+ xProps->setPropertyValue("IsFixed", Any(false));
}
- xProps->setPropertyValue( "IsDate", makeAny( bIsDate ) );
- xProps->setPropertyValue( "IsFixed", makeAny( false ) );
}
catch(const Exception &)
{
@@ -247,6 +208,67 @@ sal_Int32 TextField::insertAt(
return nCharHeight;
}
+SvxDateFormat TextField::getLODateFormat(std::u16string_view rDateTimeType)
+{
+ OString aDateTimeNum = OUStringToOString(rDateTimeType.substr(8), RTL_TEXTENCODING_UTF8);
+
+ if( aDateTimeNum.isEmpty() ) // "datetime"
+ return SvxDateFormat::StdSmall;
+
+ int nDateTimeNum = aDateTimeNum.toInt32();
+
+ switch( nDateTimeNum )
+ {
+ case 1: // Date dd/mm/yyyy
+ case 8: // DateTime dd/mm/yyyy H:MM PM
+ case 9: // DateTime dd/mm/yyyy H:MM:SS PM
+ return SvxDateFormat::B;
+ case 2: // Date Day, Month dd, yyyy
+ return SvxDateFormat::StdBig;
+ case 3: // Date dd Month yyyy
+ case 4: // Date Month dd, yyyy - no exact map
+ case 6: // Date Month yy - no exact map
+ return SvxDateFormat::D;
+ case 5: // Date dd-Mon-yy - no exact map
+ case 7: // Date Mon-yy - no exact map
+ return SvxDateFormat::C;
+ case 10: // Time H:MM - not a date format
+ case 11: // Time H:MM:SS - not a date format
+ case 12: // Time H:MM PM - not a date format
+ case 13: // Time H:MM:SS PM - not a date format
+ default:
+ return SvxDateFormat::AppDefault;
+ }
+}
+
+SvxTimeFormat TextField::getLOTimeFormat(std::u16string_view rDateTimeType)
+{
+ OString aDateTimeNum = OUStringToOString(rDateTimeType.substr(8), RTL_TEXTENCODING_UTF8);
+ int nDateTimeNum = aDateTimeNum.toInt32();
+
+ switch( nDateTimeNum )
+ {
+ case 8: // DateTime dd/mm/yyyy H:MM PM
+ case 12: // Time H:MM PM
+ return SvxTimeFormat::HH12_MM;
+ case 9: // DateTime dd/mm/yyyy H:MM:SS PM
+ case 13: // Time H:MM:SS PM
+ return SvxTimeFormat::HH12_MM_SS;
+ case 10: // Time H:MM
+ return SvxTimeFormat::HH24_MM;
+ case 11: // Time H:MM:SS
+ return SvxTimeFormat::Standard;
+ case 1: // Date dd/mm/yyyy
+ case 2: // Date Day, Month dd, yyyy
+ case 3: // Date dd Month yyyy
+ case 4: // Date Month dd, yyyy
+ case 5: // Date dd-Mon-yy
+ case 6: // Date Month yy
+ case 7: // Date Mon-yy
+ default:
+ return SvxTimeFormat::AppDefault;
+ }
+}
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/textliststyle.cxx b/oox/source/drawingml/textliststyle.cxx
index 15475ddcacb0..645cd64b4792 100644
--- a/oox/source/drawingml/textliststyle.cxx
+++ b/oox/source/drawingml/textliststyle.cxx
@@ -23,6 +23,7 @@
namespace oox { namespace drawingml {
TextListStyle::TextListStyle()
+ : mbHasListStyleOnImport(false)
{
for ( int i = 0; i < 9; i++ )
{
@@ -36,6 +37,7 @@ TextListStyle::~TextListStyle()
}
TextListStyle::TextListStyle(const TextListStyle& rStyle)
+ : mbHasListStyleOnImport(false)
{
assert(rStyle.maListStyle.size() == 9);
assert(rStyle.maAggregationListStyle.size() == 9);
diff --git a/oox/source/drawingml/textliststylecontext.cxx b/oox/source/drawingml/textliststylecontext.cxx
index 9c43e7206f1b..dee3a71e3f80 100644
--- a/oox/source/drawingml/textliststylecontext.cxx
+++ b/oox/source/drawingml/textliststylecontext.cxx
@@ -42,6 +42,7 @@ TextListStyleContext::~TextListStyleContext()
ContextHandlerRef TextListStyleContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
{
+ mrTextListStyle.setHasListStyleOnImport();
switch( aElementToken )
{
case A_TOKEN( defPPr ): // CT_TextParagraphProperties
diff --git a/oox/source/drawingml/textparagraph.cxx b/oox/source/drawingml/textparagraph.cxx
index b5635b58f2e9..c85878715310 100644
--- a/oox/source/drawingml/textparagraph.cxx
+++ b/oox/source/drawingml/textparagraph.cxx
@@ -38,6 +38,7 @@ using namespace ::com::sun::star::beans;
namespace oox { namespace drawingml {
TextParagraph::TextParagraph()
+ : mbHasProperties( false )
{
}
@@ -195,6 +196,16 @@ formulaimport::XmlStreamBuilder & TextParagraph::GetMathXml()
return *m_pMathXml;
}
+bool TextParagraph::hasVisualRunProperties() const
+{
+ for ( auto& pTextRun : getRuns() )
+ {
+ if ( pTextRun->hasVisualRunProperties() )
+ return true;
+ }
+ return false;
+}
+
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index fd4f67732607..dacfe516585c 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -1781,7 +1781,7 @@ void DrawingML::WriteRunProperties( const Reference< XPropertySet >& rRun, bool
else if (GetProperty(rXPropSet, "CharHeight"))
{
nSize = static_cast<sal_Int32>(100*(*o3tl::doAccess<float>(mAny)));
- if ( nElement == XML_rPr )
+ if ( nElement == XML_rPr || nElement == XML_defRPr )
{
rbOverridingCharHeight = true;
rnCharHeight = nSize;
@@ -2138,40 +2138,13 @@ OUString DrawingML::GetFieldValue( const css::uno::Reference< css::text::XTextRa
{
sal_Int32 nNumFmt = -1;
rXPropSet->getPropertyValue(UNO_TC_PROP_NUMFORMAT) >>= nNumFmt;
- switch(static_cast<SvxDateFormat>(nNumFmt))
- {
- case SvxDateFormat::StdSmall:
- case SvxDateFormat::A: aFieldValue = "datetime"; // 13/02/96
- break;
- case SvxDateFormat::B: aFieldValue = "datetime1"; // 13/02/1996
- break;
- case SvxDateFormat::StdBig:
- case SvxDateFormat::D: aFieldValue = "datetime3"; // 13 February 1996
- break;
- default: break;
- }
+ aFieldValue = GetDatetimeTypeFromDate(static_cast<SvxDateFormat>(nNumFmt));
}
else if(aFieldKind == "ExtTime")
{
sal_Int32 nNumFmt = -1;
rXPropSet->getPropertyValue(UNO_TC_PROP_NUMFORMAT) >>= nNumFmt;
- switch(static_cast<SvxTimeFormat>(nNumFmt))
- {
- case SvxTimeFormat::Standard:
- case SvxTimeFormat::HH24_MM_SS:
- aFieldValue = "datetime11"; // 13:49:38
- break;
- case SvxTimeFormat::HH24_MM:
- aFieldValue = "datetime10"; // 13:49
- break;
- case SvxTimeFormat::HH12_MM:
- aFieldValue = "datetime12"; // 01:49 PM
- break;
- case SvxTimeFormat::HH12_MM_SS:
- aFieldValue = "datetime13"; // 01:49:38 PM
- break;
- default: break;
- }
+ aFieldValue = GetDatetimeTypeFromTime(static_cast<SvxTimeFormat>(nNumFmt));
}
else if(aFieldKind == "ExtFile")
{
@@ -2198,6 +2171,85 @@ OUString DrawingML::GetFieldValue( const css::uno::Reference< css::text::XTextRa
return aFieldValue;
}
+OUString DrawingML::GetDatetimeTypeFromDate(SvxDateFormat eDate)
+{
+ return GetDatetimeTypeFromDateTime(eDate, SvxTimeFormat::AppDefault);
+}
+
+OUString DrawingML::GetDatetimeTypeFromTime(SvxTimeFormat eTime)
+{
+ return GetDatetimeTypeFromDateTime(SvxDateFormat::AppDefault, eTime);
+}
+
+OUString DrawingML::GetDatetimeTypeFromDateTime(SvxDateFormat eDate, SvxTimeFormat eTime)
+{
+ OUString aDateField;
+ switch (eDate)
+ {
+ case SvxDateFormat::StdSmall:
+ case SvxDateFormat::A:
+ aDateField = "datetime";
+ break;
+ case SvxDateFormat::B:
+ aDateField = "datetime1"; // 13/02/1996
+ break;
+ case SvxDateFormat::C:
+ aDateField = "datetime5";
+ break;
+ case SvxDateFormat::D:
+ aDateField = "datetime3"; // 13 February 1996
+ break;
+ case SvxDateFormat::StdBig:
+ case SvxDateFormat::E:
+ case SvxDateFormat::F:
+ aDateField = "datetime2";
+ break;
+ default:
+ break;
+ }
+
+ OUString aTimeField;
+ switch (eTime)
+ {
+ case SvxTimeFormat::Standard:
+ case SvxTimeFormat::HH24_MM_SS:
+ case SvxTimeFormat::HH24_MM_SS_00:
+ aTimeField = "datetime11"; // 13:49:38
+ break;
+ case SvxTimeFormat::HH24_MM:
+ aTimeField = "datetime10"; // 13:49
+ break;
+ case SvxTimeFormat::HH12_MM:
+ case SvxTimeFormat::HH12_MM_AMPM:
+ aTimeField = "datetime12"; // 01:49 PM
+ break;
+ case SvxTimeFormat::HH12_MM_SS:
+ case SvxTimeFormat::HH12_MM_SS_AMPM:
+ case SvxTimeFormat::HH12_MM_SS_00:
+ case SvxTimeFormat::HH12_MM_SS_00_AMPM:
+ aTimeField = "datetime13"; // 01:49:38 PM
+ break;
+ default:
+ break;
+ }
+
+ if (!aDateField.isEmpty() && aTimeField.isEmpty())
+ return aDateField;
+ else if (!aTimeField.isEmpty() && aDateField.isEmpty())
+ return aTimeField;
+ else if (!aDateField.isEmpty() && !aTimeField.isEmpty())
+ {
+ if (aTimeField == "datetime11" || aTimeField == "datetime13")
+ // only datetime format that has Date and HH:MM:SS
+ return "datetime9"; // dd/mm/yyyy H:MM:SS
+ else
+ // only datetime format that has Date and HH:MM
+ return "datetime8"; // dd/mm/yyyy H:MM
+ }
+ else
+ return "";
+}
+
void DrawingML::WriteRun( const Reference< XTextRange >& rRun,
bool& rbOverridingCharHeight, sal_Int32& rnCharHeight)
{
@@ -2623,14 +2675,14 @@ void DrawingML::WriteLinespacing( const LineSpacing& rSpacing )
}
}
-void DrawingML::WriteParagraphProperties( const Reference< XTextContent >& rParagraph, float fFirstCharHeight)
+bool DrawingML::WriteParagraphProperties( const Reference< XTextContent >& rParagraph, float fFirstCharHeight, sal_Int32 nElement)
{
Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
PropertyState eState;
if( !rXPropSet.is() || !rXPropState.is() )
- return;
+ return false;
sal_Int16 nLevel = -1;
if (GetProperty(rXPropSet, "NumberingLevel"))
@@ -2681,14 +2733,14 @@ void DrawingML::WriteParagraphProperties( const Reference< XTextContent >& rPara
|| bHasLinespacing )
{
if (nParaLeftMargin) // For Paragraph
- mpFS->startElementNS( XML_a, XML_pPr,
+ mpFS->startElementNS( XML_a, nElement,
XML_lvl, nLevel > 0 ? OString::number(nLevel).getStr() : nullptr,
XML_marL, nParaLeftMargin > 0 ? OString::number(oox::drawingml::convertHmmToEmu(nParaLeftMargin)).getStr() : nullptr,
XML_indent, nParaFirstLineIndent ? OString::number(oox::drawingml::convertHmmToEmu(nParaFirstLineIndent)).getStr() : nullptr,
XML_algn, GetAlignment( nAlignment ),
XML_rtl, bRtl ? ToPsz10(bRtl) : nullptr );
else
- mpFS->startElementNS( XML_a, XML_pPr,
+ mpFS->startElementNS( XML_a, nElement,
XML_lvl, nLevel > 0 ? OString::number(nLevel).getStr() : nullptr,
XML_marL, nLeftMargin > 0 ? OString::number(oox::drawingml::convertHmmToEmu(nLeftMargin)).getStr() : nullptr,
XML_indent, nLineIndentation ? OString::number(oox::drawingml::convertHmmToEmu(nLineIndentation)).getStr() : nullptr,
@@ -2726,7 +2778,51 @@ void DrawingML::WriteParagraphProperties( const Reference< XTextContent >& rPara
WriteParagraphNumbering( rXPropSet, fFirstCharHeight, nLevel );
WriteParagraphTabStops( rXPropSet );
- mpFS->endElementNS( XML_a, XML_pPr );
+ // do not end element for lstStyles since, defRPr should be stacked inside it
+ if( nElement != XML_lvl1pPr )
+ mpFS->endElementNS( XML_a, nElement );
+
+ return true;
+ }
+ return false;
+}
+
+void DrawingML::WriteLstStyles(const css::uno::Reference<css::text::XTextContent>& rParagraph,
+ bool& rbOverridingCharHeight, sal_Int32& rnCharHeight,
+ const css::uno::Reference<css::beans::XPropertySet>& /*rXShapePropSet*/)
+{
+ Reference<XEnumerationAccess> access(rParagraph, UNO_QUERY);
+ if (!access.is())
+ return;
+
+ Reference<XEnumeration> enumeration(access->createEnumeration());
+ if (!enumeration.is())
+ return;
+
+
+ Reference<XTextRange> rRun;
+
+ if (enumeration->hasMoreElements())
+ {
+ Any aAny(enumeration->nextElement());
+ if (aAny >>= rRun)
+ {
+ float fFirstCharHeight = rnCharHeight / 1000.;
+ Reference<XPropertySet> xFirstRunPropSet(rRun, UNO_QUERY);
+ Reference<XPropertySetInfo> xFirstRunPropSetInfo
+ = xFirstRunPropSet->getPropertySetInfo();
+
+ if (xFirstRunPropSetInfo->hasPropertyByName("CharHeight"))
+ fFirstCharHeight = xFirstRunPropSet->getPropertyValue("CharHeight").get<float>();
+
+ mpFS->startElementNS(XML_a, XML_lstStyle);
+ if( !WriteParagraphProperties(rParagraph, fFirstCharHeight, XML_lvl1pPr) )
+ mpFS->startElementNS(XML_a, XML_lvl1pPr);
+ WriteRunProperties(xFirstRunPropSet, false, XML_defRPr, true, rbOverridingCharHeight,
+ rnCharHeight, GetScriptType(rRun->getString()));
+ mpFS->endElementNS(XML_a, XML_lvl1pPr);
+ mpFS->endElementNS(XML_a, XML_lstStyle);
+ }
}
}
@@ -2770,7 +2866,7 @@ void DrawingML::WriteParagraph( const Reference< XTextContent >& rParagraph,
mpFS->endElementNS( XML_a, XML_p );
}
-void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
+void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles )
{
Reference< XText > xXText( rXIface, UNO_QUERY );
Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
@@ -3048,6 +3144,7 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
bool bOverridingCharHeight = false;
sal_Int32 nCharHeight = -1;
+ bool bFirstParagraph = true;
while( enumeration->hasMoreElements() )
{
@@ -3055,7 +3152,13 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
Any any ( enumeration->nextElement() );
if( any >>= paragraph)
- WriteParagraph( paragraph, bOverridingCharHeight, nCharHeight );
+ {
+ if (bFirstParagraph && bWritePropertiesAsLstStyles)
+ WriteLstStyles(paragraph, bOverridingCharHeight, nCharHeight, rXPropSet);
+
+ WriteParagraph(paragraph, bOverridingCharHeight, nCharHeight);
+ bFirstParagraph = false;
+ }
}
}
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 60b88181b5dc..1eb48b0efc5c 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -1591,7 +1591,7 @@ ShapeExport& ShapeExport::WriteShape( const Reference< XShape >& xShape )
return *this;
}
-ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace )
+ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles )
{
// In case this shape has an associated textbox, then export that, and we're done.
if (GetDocumentType() == DOCUMENT_DOCX && GetTextExport())
@@ -1616,7 +1616,7 @@ ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, s
pFS->startElementNS(nXmlNamespace,
(GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx));
- WriteText( xIface, m_presetWarp, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX) );
+ WriteText( xIface, m_presetWarp, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX), true, 0, bWritePropertiesAsLstStyles );
pFS->endElementNS( nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx) );
if (GetDocumentType() == DOCUMENT_DOCX)
WriteText( xIface, m_presetWarp, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace );
diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx
index 71b94c727132..533b49ac8b6f 100644
--- a/oox/source/ppt/pptshape.cxx
+++ b/oox/source/ppt/pptshape.cxx
@@ -20,8 +20,12 @@
#include <oox/ppt/pptshape.hxx>
#include <oox/core/xmlfilterbase.hxx>
#include <drawingml/textbody.hxx>
+#include <drawingml/textparagraph.hxx>
+#include <drawingml/textfield.hxx>
#include <drawingml/table/tableproperties.hxx>
+#include <editeng/flditem.hxx>
+#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
@@ -50,6 +54,7 @@ PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const sal_Char
: Shape( pServiceName )
, meShapeLocation( eShapeLocation )
, mbReferenced( false )
+, mbHasNoninheritedShapeProperties( false )
{
}
@@ -85,6 +90,19 @@ static const char* lclDebugSubType( sal_Int32 nType )
return "unknown - please extend lclDebugSubType";
}
+namespace
+{
+bool ShapeHasNoVisualPropertiesOnImport(const oox::ppt::PPTShape& rPPTShape)
+{
+ return !rPPTShape.hasNonInheritedShapeProperties()
+ && !rPPTShape.hasShapeStyleRefs()
+ && !rPPTShape.getTextBody()->hasVisualRunProperties()
+ && !rPPTShape.getTextBody()->hasNoninheritedBodyProperties()
+ && !rPPTShape.getTextBody()->hasListStyleOnImport()
+ && !rPPTShape.getTextBody()->hasParagraphProperties();
+}
+}
+
oox::drawingml::TextListStylePtr PPTShape::getSubTypeTextListStyle( const SlidePersist& rSlidePersist, sal_Int32 nSubType )
{
oox::drawingml::TextListStylePtr pTextListStyle;
@@ -110,6 +128,23 @@ oox::drawingml::TextListStylePtr PPTShape::getSubTypeTextListStyle( const SlideP
return pTextListStyle;
}
+bool PPTShape::IsPlaceHolderCandidate(const SlidePersist& rSlidePersist) const
+{
+ if (meShapeLocation != Slide)
+ return false;
+ if (rSlidePersist.isNotesPage())
+ return false;
+ auto pTextBody = getTextBody();
+ if (!pTextBody)
+ return false;
+ auto rParagraphs = pTextBody->getParagraphs();
+ if (rParagraphs.size() != 1)
+ return false;
+ if (rParagraphs.front()->getRuns().size() != 1)
+ return false;
+ return ShapeHasNoVisualPropertiesOnImport(*this);
+}
+
void PPTShape::addShape(
oox::core::XmlFilterBase& rFilterBase,
const SlidePersist& rSlidePersist,
@@ -178,6 +213,34 @@ void PPTShape::addShape(
}
break;
case XML_dt :
+ if (IsPlaceHolderCandidate(rSlidePersist))
+ {
+ TextRunPtr& pTextRun = getTextBody()->getParagraphs().front()->getRuns().front();
+ oox::drawingml::TextField* pTextField = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
+ if (pTextField)
+ {
+ OUString aType = pTextField->getType();
+ if ( aType.startsWith("datetime") )
+ {
+ SvxDateFormat eDateFormat = drawingml::TextField::getLODateFormat(aType);
+ SvxTimeFormat eTimeFormat = drawingml::TextField::getLOTimeFormat(aType);
+ Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
+
+ if( eDateFormat != SvxDateFormat::AppDefault
+ || eTimeFormat != SvxTimeFormat::AppDefault )
+ {
+ // DateTimeFormat property looks for the date in 4 LSBs
+ // and looks for time format in the 4 bits after that
+ sal_Int32 nDateTimeFormat = static_cast<sal_Int32>(eDateFormat) |
+ static_cast<sal_Int32>(eTimeFormat) << 4;
+ xPropertySet->setPropertyValue( "IsDateTimeVisible", Any(true) );
+ xPropertySet->setPropertyValue( "IsDateTimeFixed", Any(false) );
+ xPropertySet->setPropertyValue( "DateTimeFormat", Any(nDateTimeFormat) );
+ return;
+ }
+ }
+ }
+ }
sServiceName = "com.sun.star.presentation.DateTimeShape";
bClearText = true;
break;
@@ -186,10 +249,40 @@ void PPTShape::addShape(
bClearText = true;
break;
case XML_ftr :
+ if (IsPlaceHolderCandidate(rSlidePersist))
+ {
+ const OUString& rFooterText = getTextBody()->toString();
+
+ if( !rFooterText.isEmpty() )
+ {
+ // if it is possible to get the footer as a property the LO way,
+ // get it and discard the shape
+ Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
+ xPropertySet->setPropertyValue( "IsFooterVisible", Any( true ) );
+ xPropertySet->setPropertyValue( "FooterText", Any(rFooterText) );
+ return;
+ }
+ }
sServiceName = "com.sun.star.presentation.FooterShape";
bClearText = true;
break;
case XML_sldNum :
+ if (IsPlaceHolderCandidate(rSlidePersist))
+ {
+ TextRunPtr& pTextRun
+ = getTextBody()->getParagraphs().front()->getRuns().front();
+ oox::drawingml::TextField* pTextField
+ = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
+ if (pTextField && pTextField->getType() == "slidenum")
+ {
+ // if it is possible to get the slidenum placeholder as a property
+ // do that and discard the shape
+ Reference<XPropertySet> xPropertySet(rSlidePersist.getPage(),
+ UNO_QUERY);
+ xPropertySet->setPropertyValue("IsPageNumberVisible", Any(true));
+ return;
+ }
+ }
sServiceName = "com.sun.star.presentation.SlideNumberShape";
bClearText = true;
break;
@@ -408,6 +501,26 @@ void PPTShape::addShape(
}
}
+ // we will be losing whatever information there is in the footer placeholder on master/layout slides
+ // since they should have the "<footer>" textfield in them in order to make LibreOffice process them as expected
+ // likewise DateTime placeholder data on master/layout slides will be lost and replaced
+ if( (mnSubType == XML_ftr || mnSubType == XML_dt) && meShapeLocation != Slide )
+ {
+ OUString aFieldType;
+ if( mnSubType == XML_ftr )
+ aFieldType = "com.sun.star.presentation.TextField.Footer";
+ else
+ aFieldType = "com.sun.star.presentation.TextField.DateTime";
+ Reference < XTextField > xField( xServiceFact->createInstance( aFieldType ), UNO_QUERY );
+ Reference < XText > xText(mxShape, UNO_QUERY);
+ if(xText.is())
+ {
+ xText->setString("");
+ Reference < XTextCursor > xTextCursor = xText->createTextCursor();
+ xText->insertTextContent( xTextCursor, xField, false);
+ }
+ }
+
// if this is a group shape, we have to add also each child shape
Reference<XShapes> xShapes(xShape, UNO_QUERY);
if (xShapes.is())
diff --git a/oox/source/ppt/pptshapepropertiescontext.cxx b/oox/source/ppt/pptshapepropertiescontext.cxx
index b2dfcbce8980..a65a02d93e1c 100644
--- a/oox/source/ppt/pptshapepropertiescontext.cxx
+++ b/oox/source/ppt/pptshapepropertiescontext.cxx
@@ -35,6 +35,7 @@
#include <oox/token/namespaces.hxx>
#include <oox/token/properties.hxx>
#include <oox/token/tokens.hxx>
+#include <oox/ppt/pptshape.hxx>
using namespace oox::core;
using namespace ::com::sun::star;
@@ -54,6 +55,10 @@ PPTShapePropertiesContext::PPTShapePropertiesContext( ContextHandler2Helper cons
ContextHandlerRef PPTShapePropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
{
+ PPTShape* pPPTShape = dynamic_cast<PPTShape*>(&mrShape);
+ if (pPPTShape)
+ pPPTShape->setHasNoninheritedShapeProperties();
+
switch( aElementToken )
{
case A_TOKEN( xfrm ):
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 050fd823b4ee..ec9cebf3e66d 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -780,7 +780,8 @@ void ScGlobal::OpenURL(const OUString& rURL, const OUString& rTarget, bool bIgno
// OpenURL is always called in the GridWindow by mouse clicks in some way or another.
// That's why pScActiveViewShell and nScClickMouseModifier are correct.
- if (!bIgnoreSettings && !ShouldOpenURL())
+ // Fragments pointing into the current document should be always opened.
+ if (!bIgnoreSettings && !(ShouldOpenURL() || rURL.startsWith("#")))
return;
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
diff --git a/sc/source/filter/oox/worksheetfragment.cxx b/sc/source/filter/oox/worksheetfragment.cxx
index 775e9ad9a3a7..58c35f862115 100644
--- a/sc/source/filter/oox/worksheetfragment.cxx
+++ b/sc/source/filter/oox/worksheetfragment.cxx
@@ -467,17 +467,17 @@ ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const
case XLS_TOKEN( oleObjects ):
if ( getCurrentElement() == XLS_TOKEN( controls ) )
{
- if( aMceState.empty() || aMceState.back() == MCE_STATE::Started )
+ if( isMCEStateEmpty() || getMCEState() == MCE_STATE::Started )
{
if ( getCurrentElement() == XLS_TOKEN( oleObjects ) ) importOleObject( rAttribs );
else
importControl( rAttribs );
}
- else if ( !aMceState.empty() && aMceState.back() == MCE_STATE::FoundChoice )
+ else if ( !isMCEStateEmpty() && getMCEState() == MCE_STATE::FoundChoice )
{
// reset the handling within 'Choice'
// this will force attempted handling in Fallback
- aMceState.back() = MCE_STATE::Started;
+ setMCEState( MCE_STATE::Started );
}
}
break;
diff --git a/sc/source/ui/dbgui/scuiasciiopt.cxx b/sc/source/ui/dbgui/scuiasciiopt.cxx
index 3a55f96b77b5..d665795b8224 100644
--- a/sc/source/ui/dbgui/scuiasciiopt.cxx
+++ b/sc/source/ui/dbgui/scuiasciiopt.cxx
@@ -288,14 +288,12 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, const OUString& aDatNa
, mcTextSep(ScAsciiOptions::cDefaultTextSep)
, meCall(eCall)
, mbDetectSpaceSep(eCall != SC_TEXTTOCOLUMNS)
- , mxFtCharSet(m_xBuilder->weld_label("textcharset"))
, mxLbCharSet(new SvxTextEncodingBox(m_xBuilder->weld_combo_box("charset")))
, mxFtCustomLang(m_xBuilder->weld_label("textlanguage"))
, mxLbCustomLang(new SvxLanguageBox(m_xBuilder->weld_combo_box("language")))
, mxFtRow(m_xBuilder->weld_label("textfromrow"))
, mxNfRow(m_xBuilder->weld_spin_button("fromrow"))
- , mxRbFixed(m_xBuilder->weld_radio_button("tofixedwidth"))
- , mxRbSeparated(m_xBuilder->weld_radio_button("toseparatedby"))
+ , mxRbSeparated(m_xBuilder->weld_check_button("toseparatedby"))
, mxCkbTab(m_xBuilder->weld_check_button("tab"))
, mxCkbSemicolon(m_xBuilder->weld_check_button("semicolon"))
, mxCkbComma(m_xBuilder->weld_check_button("comma"))
@@ -363,7 +361,7 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, const OUString& aDatNa
if (bSkipEmptyCells)
mxCkbSkipEmptyCells->set_active(true);
if (bFixedWidth && !bIsTSV)
- mxRbFixed->set_active(true);
+ mxRbSeparated->set_active(false);
if (nFromRow != 1)
mxNfRow->set_value(nFromRow);
@@ -488,10 +486,9 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, const OUString& aDatNa
mxTableBox->SetColTypeHdl( LINK( this, ScImportAsciiDlg, ColTypeHdl ) );
mxRbSeparated->connect_clicked( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) );
- mxRbFixed->connect_clicked( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) );
SetupSeparatorCtrls();
- RbSepFixHdl(*mxRbFixed);
+ RbSepFixHdl( *mxRbSeparated );
UpdateVertical();
@@ -499,7 +496,6 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, const OUString& aDatNa
if (meCall == SC_TEXTTOCOLUMNS)
{
- mxFtCharSet->set_sensitive(false);
mxLbCharSet->set_sensitive(false);
mxFtCustomLang->set_sensitive(false);
mxLbCustomLang->set_active_id(LANGUAGE_SYSTEM);
@@ -539,7 +535,7 @@ bool ScImportAsciiDlg::GetLine( sal_uLong nLine, OUString &rText, sal_Unicode& r
return false;
bool bRet = true;
- bool bFixed = mxRbFixed->get_active();
+ bool bFixed = !mxRbSeparated->get_active();
if (!mpRowPosArray)
mpRowPosArray.reset( new sal_uLong[ASCIIDLG_MAXROWS + 2] );
@@ -602,7 +598,7 @@ void ScImportAsciiDlg::GetOptions( ScAsciiOptions& rOpt )
rOpt.SetCharSet( meCharSet );
rOpt.SetCharSetSystem( mbCharSetSystem );
rOpt.SetLanguage(mxLbCustomLang->get_active_id());
- rOpt.SetFixedLen( mxRbFixed->get_active() );
+ rOpt.SetFixedLen( !mxRbSeparated->get_active() );
rOpt.SetStartRow( mxNfRow->get_value() );
mxTableBox->FillColumnData( rOpt );
if( mxRbSeparated->get_active() )
@@ -622,7 +618,7 @@ void ScImportAsciiDlg::SaveParameters()
{
lcl_SaveSeparators( maFieldSeparators, mxCbTextSep->get_active_text(), mxCkbAsOnce->get_active(),
mxCkbQuotedAsText->get_active(), mxCkbDetectNumber->get_active(),
- mxRbFixed->get_active(),
+ !mxRbSeparated->get_active(),
mxNfRow->get_value(),
mxLbCharSet->get_active(),
static_cast<sal_uInt16>(mxLbCustomLang->get_active_id()),
@@ -698,10 +694,10 @@ void ScImportAsciiDlg::UpdateVertical()
IMPL_LINK(ScImportAsciiDlg, RbSepFixHdl, weld::Button&, rButton, void)
{
- if (&rButton == mxRbFixed.get() || &rButton == mxRbSeparated.get())
+ if (&rButton == mxRbSeparated.get())
{
weld::WaitObject aWaitObj(m_xDialog.get());
- if( mxRbFixed->get_active() )
+ if( !mxRbSeparated->get_active() )
mxTableBox->SetFixedWidthMode();
else
mxTableBox->SetSeparatorsMode();
@@ -727,7 +723,7 @@ IMPL_LINK( ScImportAsciiDlg, SeparatorEditHdl, weld::Entry&, rEdit, void )
void ScImportAsciiDlg::SeparatorHdl(const weld::Widget* pCtrl)
{
OSL_ENSURE( pCtrl, "ScImportAsciiDlg::SeparatorHdl - missing sender" );
- OSL_ENSURE( !mxRbFixed->get_active(), "ScImportAsciiDlg::SeparatorHdl - not allowed in fixed width" );
+ OSL_ENSURE( mxRbSeparated->get_active(), "ScImportAsciiDlg::SeparatorHdl - not allowed in fixed width" );
/* #i41550# First update state of the controls. The GetSeparators()
function needs final state of the check boxes. */
@@ -780,7 +776,7 @@ IMPL_LINK_NOARG(ScImportAsciiDlg, UpdateTextHdl, ScCsvTableBox&, void)
// when the dialog wasn't already presented to the user.
// As a side effect this has the benefit that the check is only done on the
// first set of visible lines.
- sal_Unicode cDetectSep = (mbDetectSpaceSep && !mxRbFixed->get_active() && !mxCkbSpace->get_active() ? 0 : 0xffff);
+ sal_Unicode cDetectSep = (mbDetectSpaceSep && mxRbSeparated->get_active() && !mxCkbSpace->get_active() ? 0 : 0xffff);
sal_Int32 nBaseLine = mxTableBox->GetGrid().GetFirstVisLine();
sal_Int32 nRead = mxTableBox->GetGrid().GetVisLineCount();
diff --git a/sc/source/ui/drawfunc/fusel.cxx b/sc/source/ui/drawfunc/fusel.cxx
index e3c306574a73..8f4badd28ecb 100644
--- a/sc/source/ui/drawfunc/fusel.cxx
+++ b/sc/source/ui/drawfunc/fusel.cxx
@@ -222,7 +222,8 @@ bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
}
// open hyperlink, if found at object or in object's text
- if ( !sURL.isEmpty() && ScGlobal::ShouldOpenURL() )
+ // Fragments pointing into the current document should be always opened.
+ if ( !sURL.isEmpty() && (ScGlobal::ShouldOpenURL() || sURL.startsWith("#")) )
{
ScGlobal::OpenURL( sURL, sTarget );
rViewShell.FakeButtonUp( rViewShell.GetViewData().GetActivePart() );
diff --git a/sc/source/ui/inc/scuiasciiopt.hxx b/sc/source/ui/inc/scuiasciiopt.hxx
index b8cb2bcc6794..569a67c9b241 100644
--- a/sc/source/ui/inc/scuiasciiopt.hxx
+++ b/sc/source/ui/inc/scuiasciiopt.hxx
@@ -54,7 +54,6 @@ class ScImportAsciiDlg : public weld::GenericDialogController
ScImportAsciiCall const meCall; /// How the dialog is called (see asciiopt.hxx)
bool mbDetectSpaceSep; /// Whether to detect a possible space separator.
- std::unique_ptr<weld::Label> mxFtCharSet;
std::unique_ptr<SvxTextEncodingBox> mxLbCharSet;
std::unique_ptr<weld::Label> mxFtCustomLang;
std::unique_ptr<SvxLanguageBox> mxLbCustomLang;
@@ -62,8 +61,7 @@ class ScImportAsciiDlg : public weld::GenericDialogController
std::unique_ptr<weld::Label> mxFtRow;
std::unique_ptr<weld::SpinButton> mxNfRow;
- std::unique_ptr<weld::RadioButton> mxRbFixed;
- std::unique_ptr<weld::RadioButton> mxRbSeparated;
+ std::unique_ptr<weld::CheckButton> mxRbSeparated;
std::unique_ptr<weld::CheckButton> mxCkbTab;
std::unique_ptr<weld::CheckButton> mxCkbSemicolon;
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 67908ba1ba68..6b1fc8cf7ef0 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -254,7 +254,8 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
if (nWhich == FID_INS_COLUMNS_AFTER)
eAction = sc::ColRowEditAction::InsertColumnsAfter;
- bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
+ bDisable = (!bSimpleArea && eMarkType != SC_MARK_SIMPLE_FILTERED)
+ || GetViewData()->SimpleRowMarked();
if (!bEditable && nRow1 == 0 && nRow2 == pDoc->MaxRow())
{
// See if row insertions are allowed.
diff --git a/sc/source/ui/view/gridwin5.cxx b/sc/source/ui/view/gridwin5.cxx
index b940ffe200b1..40746907fafc 100644
--- a/sc/source/ui/view/gridwin5.cxx
+++ b/sc/source/ui/view/gridwin5.cxx
@@ -292,7 +292,9 @@ void ScGridWindow::RequestHelp(const HelpEvent& rHEvt)
pObj = pHit;
}
ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj );
- if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
+ // Fragments pointing into the current document need no tooltip
+ // describing the ctrl-click functionality.
+ if ( pInfo && (pInfo->GetHlink().getLength() > 0) && !pInfo->GetHlink().startsWith("#") )
{
aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
aHelpText = SfxHelp::GetURLHelpText(pInfo->GetHlink());
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index e5b1da40162c..774f3a27aa26 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1605,7 +1605,8 @@ void ScViewFunc::OnLOKSetWidthOrHeight(SCCOLROW nStart, bool bWidth)
bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )
{
ScRange aRange;
- if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
+ ScMarkType eMarkType = GetViewData().GetSimpleArea(aRange);
+ if (eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED)
{
ScDocShell* pDocSh = GetViewData().GetDocShell();
const ScMarkData& rMark = GetViewData().GetMarkData();
diff --git a/sc/uiconfig/scalc/ui/textimportcsv.ui b/sc/uiconfig/scalc/ui/textimportcsv.ui
index 948c5334aaf9..a58d50994397 100644
--- a/sc/uiconfig/scalc/ui/textimportcsv.ui
+++ b/sc/uiconfig/scalc/ui/textimportcsv.ui
@@ -111,7 +111,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
@@ -119,20 +118,6 @@
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
- <object class="GtkLabel" id="textcharset">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes" context="textimportcsv|textcharset">Ch_aracter set:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">charset</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
<object class="GtkLabel" id="textlanguage">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -166,8 +151,9 @@
<property name="can_focus">False</property>
</object>
<packing>
- <property name="left_attach">1</property>
+ <property name="left_attach">0</property>
<property name="top_attach">0</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -201,7 +187,7 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes" context="textimportcsv|label1">Import</property>
+ <property name="label" translatable="yes" context="textimportcsv|label1">Character encoding</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@@ -227,7 +213,6 @@
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
@@ -242,25 +227,8 @@
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<child>
- <object class="GtkRadioButton" id="tofixedwidth">
- <property name="label" translatable="yes" context="textimportcsv|tofixedwidth">_Fixed width</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- <property name="group">toseparatedby</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkRadioButton" id="toseparatedby">
- <property name="label" translatable="yes" context="textimportcsv|toseparatedby">_Separated by</property>
+ <object class="GtkCheckButton" id="toseparatedby">
+ <property name="label" translatable="yes" context="textimportcsv|toseparatedby">_Use separators</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -287,7 +255,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
@@ -534,7 +501,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box3">
<property name="visible">True</property>
@@ -624,7 +590,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box4">
<property name="visible">True</property>
diff --git a/sd/qa/unit/data/odp/numfmt.odp b/sd/qa/unit/data/odp/numfmt.odp
index 6fd32ce0a66d..51227ea091d9 100644
--- a/sd/qa/unit/data/odp/numfmt.odp
+++ b/sd/qa/unit/data/odp/numfmt.odp
Binary files differ
diff --git a/sd/qa/unit/data/pptx/numfmt.pptx b/sd/qa/unit/data/pptx/numfmt.pptx
index aca6927101d6..f855fbbeb12c 100644
--- a/sd/qa/unit/data/pptx/numfmt.pptx
+++ b/sd/qa/unit/data/pptx/numfmt.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/pass/ofz35597-1.pptx b/sd/qa/unit/data/pptx/pass/ofz35597-1.pptx
new file mode 100644
index 000000000000..e7fcacc25482
--- /dev/null
+++ b/sd/qa/unit/data/pptx/pass/ofz35597-1.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/slidenum_field.pptx b/sd/qa/unit/data/pptx/slidenum_field.pptx
index f3c184056905..3388568831d7 100644
--- a/sd/qa/unit/data/pptx/slidenum_field.pptx
+++ b/sd/qa/unit/data/pptx/slidenum_field.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/tdf142716.pptx b/sd/qa/unit/data/pptx/tdf142716.pptx
new file mode 100644
index 000000000000..4ef29e389449
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf142716.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/tdf143222.pptx b/sd/qa/unit/data/pptx/tdf143222.pptx
new file mode 100644
index 000000000000..63938d1bdc71
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf143222.pptx
Binary files differ
diff --git a/sd/qa/unit/data/pptx/tdf59323.pptx b/sd/qa/unit/data/pptx/tdf59323.pptx
new file mode 100755
index 000000000000..0660c0af4f23
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf59323.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 27d42132557f..a6279f8eadf1 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -12,6 +12,7 @@
#include <comphelper/sequence.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/editobj.hxx>
+#include <editeng/flditem.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/numitem.hxx>
#include <editeng/unoprnms.hxx>
@@ -20,6 +21,7 @@
#include <svx/svdomedia.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlndsit.hxx>
+#include <svx/svdoole2.hxx>
#include <rtl/ustring.hxx>
#include <com/sun/star/drawing/XDrawPage.hpp>
@@ -189,6 +191,8 @@ public:
void testTdf132282();
void testTdf128213ShapeRot();
void testTdf96061_textHighlight();
+ void testTdf59323_slideFooters();
+ void testTdf143222_embeddedWorksheet();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
@@ -296,6 +300,8 @@ public:
CPPUNIT_TEST(testTdf132282);
CPPUNIT_TEST(testTdf128213ShapeRot);
CPPUNIT_TEST(testTdf96061_textHighlight);
+ CPPUNIT_TEST(testTdf59323_slideFooters);
+ CPPUNIT_TEST(testTdf143222_embeddedWorksheet);
CPPUNIT_TEST_SUITE_END();
@@ -749,26 +755,33 @@ void matchNumberFormat( int nPage, uno::Reference< text::XTextField > const & xF
xPropSet->getPropertyValue("NumberFormat") >>= nNumFmt;
switch( nPage )
{
- case 0: // 13/02/96
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(2), nNumFmt);
+ case 0: // 13/02/96 (StdSmall)
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(SvxDateFormat::StdSmall), nNumFmt);
break;
case 1: // 13/02/1996
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(5), nNumFmt);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(SvxDateFormat::B), nNumFmt);
break;
- case 2: // 13 February 1996
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(3), nNumFmt);
+ case 2: // Tuesday, June 29, 2021 (StdBig)
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(SvxDateFormat::StdBig), nNumFmt);
break;
- case 3: // 13:49:38
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(2), nNumFmt);
+ case 3: // 13:49:38 (Standard)
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(SvxTimeFormat::Standard), nNumFmt);
break;
case 4: // 13:49
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(3), nNumFmt);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(SvxTimeFormat::HH24_MM), nNumFmt);
break;
case 5: // 01:49 PM
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(6), nNumFmt);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(SvxTimeFormat::HH12_MM), nNumFmt);
break;
case 6: // 01:49:38 PM
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(7), nNumFmt);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Time fields don't match", sal_Int32(SvxTimeFormat::HH12_MM_SS), nNumFmt);
+ break;
+ case 7: // June 29, 2021
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(SvxDateFormat::D), nNumFmt);
+ break;
+ case 8: // Jun 29, 2021
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Number formats of Date fields don't match", sal_Int32(SvxDateFormat::C), nNumFmt);
+ break;
}
}
@@ -780,7 +793,7 @@ void SdOOXMLExportTest2::testDatetimeFieldNumberFormat()
xDocShRef = saveAndReload( xDocShRef.get(), PPTX );
- for(sal_uInt16 i = 0; i <= 6; ++i)
+ for(sal_uInt16 i = 0; i <= 8; ++i)
{
matchNumberFormat( i, getTextFieldFromPage(0, 0, 0, i, xDocShRef) );
}
@@ -794,7 +807,7 @@ void SdOOXMLExportTest2::testDatetimeFieldNumberFormatPPTX()
xDocShRef = saveAndReload( xDocShRef.get(), PPTX );
- for(sal_uInt16 i = 0; i <= 6; ++i)
+ for(sal_uInt16 i = 0; i <= 8; ++i)
{
matchNumberFormat( i, getTextFieldFromPage(0, 0, 0, i, xDocShRef) );
}
@@ -2788,6 +2801,72 @@ void SdOOXMLExportTest2::testTdf96061_textHighlight()
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aColor);
}
+void SdOOXMLExportTest2::testTdf59323_slideFooters()
+{
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf59323.pptx"), PPTX);
+
+ utl::TempFile tempFile;
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocShRef->GetDoc()->getUnoModel(),
+ uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xDoc->getDrawPages()->getCount());
+
+ for (int nPageIndex = 0; nPageIndex < 3; nPageIndex++)
+ {
+ uno::Reference<drawing::XDrawPage> xPage(getPage(0, xDocShRef));
+ uno::Reference<beans::XPropertySet> xPropSet(xPage, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(true, xPropSet->getPropertyValue("IsFooterVisible").get<bool>());
+ CPPUNIT_ASSERT_EQUAL(true, xPropSet->getPropertyValue("IsDateTimeVisible").get<bool>());
+ CPPUNIT_ASSERT_EQUAL(true, xPropSet->getPropertyValue("IsPageNumberVisible").get<bool>());
+ }
+
+ // Test placeholder indexes
+ xmlDocPtr pXmlDocMaster = parseExport(tempFile, "ppt/slideMasters/slideMaster1.xml");
+ assertXPath(pXmlDocMaster, "//p:ph [@type='dt']", "idx", "1");
+ assertXPath(pXmlDocMaster, "//p:ph [@type='ftr']", "idx", "2");
+ assertXPath(pXmlDocMaster, "//p:ph [@type='sldNum']", "idx", "3");
+
+ xmlDocPtr pXmlDocSlide1 = parseExport(tempFile, "ppt/slides/slide1.xml");
+ assertXPath(pXmlDocSlide1, "//p:ph [@type='dt']", "idx", "1");
+ assertXPath(pXmlDocSlide1, "//p:ph [@type='ftr']", "idx", "2");
+ assertXPath(pXmlDocSlide1, "//p:ph [@type='sldNum']", "idx", "3");
+
+ // Test if datetime fields have text in them
+ // This is needed for backwards compatibility
+ assertXPath(pXmlDocSlide1, "//a:fld [@type='datetime1']/a:t");
+
+ xDocShRef->DoClose();
+}
+
+void SdOOXMLExportTest2::testTdf143222_embeddedWorksheet()
+{
+ // Check import of embedded worksheet in slide.
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tdf143222.pptx"), PPTX);
+
+ const SdrPage* pPage = GetPage(1, xDocShRef.get());
+ const SdrOle2Obj* pOleObj = static_cast<SdrOle2Obj*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object", pOleObj != nullptr);
+
+ // Without the fix we lost the graphic of ole object.
+ const Graphic* pGraphic = pOleObj->GetGraphic();
+ CPPUNIT_ASSERT_MESSAGE("no graphic", pGraphic != nullptr);
+
+ // Check export of embedded worksheet in slide.
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX);
+
+ pPage = GetPage(1, xDocShRef.get());
+ pOleObj = static_cast<SdrOle2Obj*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object after the export", pOleObj != nullptr);
+
+ pGraphic = pOleObj->GetGraphic();
+ CPPUNIT_ASSERT_MESSAGE("no graphic after the export", pGraphic != nullptr);
+ xDocShRef->DoClose();
+}
+
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index fdad324b216a..f246f6568534 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -56,6 +56,7 @@ public:
void testImageWithSpecialID();
void testTdf62176();
void testTransparentBackground();
+ void testTdf142716();
void testEmbeddedPdf();
void testEmbeddedText();
void testTransparenText();
@@ -90,6 +91,7 @@ public:
CPPUNIT_TEST(testImageWithSpecialID);
CPPUNIT_TEST(testTdf62176);
CPPUNIT_TEST(testTransparentBackground);
+ CPPUNIT_TEST(testTdf142716);
CPPUNIT_TEST(testEmbeddedPdf);
CPPUNIT_TEST(testEmbeddedText);
CPPUNIT_TEST(testTransparenText);
@@ -282,6 +284,22 @@ void SdExportTest::testTransparentBackground()
xDocShRef->DoClose();
}
+void SdExportTest::testTdf142716()
+{
+ ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf142716.pptx"), PPTX);
+ xDocShRef = saveAndReload( xDocShRef.get(), PPTX );
+
+ const SdrPage *pPage = GetPage( 1, xDocShRef );
+ const SdrTextObj *pObj = dynamic_cast<SdrTextObj *>( pPage->GetObj( 0 ) );
+
+ OUString sText = pObj->GetOutlinerParaObject()->GetTextObject().GetText(0);
+
+ // Without fix "yyy" part will be lost.
+ CPPUNIT_ASSERT_EQUAL( OUString( "xxx and yyy" ), sText);
+
+ xDocShRef->DoClose();
+}
+
void SdExportTest::testMediaEmbedding()
{
if (!OpenGLWrapper::isVCLOpenGLEnabled())
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 32779db85579..2e7cbf2690f2 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -1702,7 +1702,7 @@ void SdImportTest::testTdf95932()
sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf95932.pptx"), PPTX);
const SdrPage *pPage = GetPage( 1, xDocShRef );
- SdrObject *const pObj = pPage->GetObj(2);
+ SdrObject *const pObj = pPage->GetObj(1);
CPPUNIT_ASSERT(pObj);
const XFillStyleItem& rStyleItem = dynamic_cast<const XFillStyleItem&>(
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index d4f2b618f25d..eefec66f0432 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -119,6 +119,15 @@ private:
static void WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId);
+ /** Create a new placeholder index for a master placeholder shape
+
+ @param rXShape Master placeholder shape
+ @returns Placeholder index
+ */
+ unsigned CreateNewPlaceholderIndex(const css::uno::Reference<css::drawing::XShape>& rXShape);
+ css::uno::Reference<css::drawing::XShape> GetReferencedPlaceholderXShape(const PlaceholderType eType, PageType ePageType) const;
+ void WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType);
+
/// Should we export as .pptm, ie. do we contain macros?
bool mbPptm;
@@ -141,6 +150,10 @@ private:
::oox::drawingml::ShapeExport::ShapeHashMap maShapeMap;
+ unsigned mnPlaceholderIndexMax; ///< Last used placeholder index
+ /// Map of placeholder indexes for Master placeholders
+ std::unordered_map< css::uno::Reference<css::drawing::XShape>, unsigned > maPlaceholderShapeToIndexMap;
+
struct AuthorComments {
sal_Int32 nId;
sal_Int32 nLastIndex;
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 8a7db7302ff0..5e93fbb446bf 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -28,6 +28,7 @@
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/storagehelper.hxx>
+#include <comphelper/xmltools.hxx>
#include <sax/fshelper.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
@@ -52,6 +53,10 @@
#include "pptx-animations.hxx"
#include "../ppt/pptanimations.hxx"
+#include <svx/svdpage.hxx>
+#include <svx/unoapi.hxx>
+#include <sdpage.hxx>
+
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XStorageBasedDocument.hpp>
#include <utility>
@@ -109,7 +114,11 @@ public:
ShapeExport& WriteTextShape(const Reference< XShape >& xShape) override;
ShapeExport& WriteUnknownShape(const Reference< XShape >& xShape) override;
ShapeExport& WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder);
+ /** Writes a placeholder shape that references the placeholder on the master slide */
+ ShapeExport& WritePlaceholderReferenceShape(PlaceholderType ePlaceholder, unsigned nReferencedPlaceholderIdx, PageType ePageType, Reference<XPropertySet>& rXPagePropSet);
ShapeExport& WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj);
+ /** Writes textbody of a placeholder that references the placeholder on the master slide */
+ ShapeExport& WritePlaceholderReferenceTextBody(PlaceholderType ePlaceholder, PageType ePageType, const Reference<XPropertySet> xPagePropSet);
// helper parts
bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster);
@@ -128,8 +137,35 @@ void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUStr
pFS->endElement(FSNS(XML_p, XML_stSnd));
pFS->endElement(FSNS(XML_p, XML_sndAc));
}
-}
+const char* getPlaceholderTypeName(PlaceholderType ePlaceholder)
+{
+ switch (ePlaceholder)
+ {
+ case SlideImage:
+ return "sldImg";
+ case Notes:
+ return "body";
+ case Header:
+ return "hdr";
+ case Footer:
+ return "ftr";
+ case SlideNumber:
+ return "sldNum";
+ case DateAndTime:
+ return "dt";
+ case Outliner:
+ return "body";
+ case Title:
+ return "title";
+ case Subtitle:
+ return "subTitle";
+ default:
+ SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
+ return "";
+ }
+}
+}
}
}
@@ -335,6 +371,7 @@ PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContex
, mnAnimationNodeIdMax(1)
, mnDiagramId(1)
, mbCreateNotes(false)
+ , mnPlaceholderIndexMax(1)
{
comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
mbPptm = aArgumentsMap.getUnpackedValueOrDefault("IsPPTM", false);
@@ -1412,6 +1449,8 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType
}
}
+ if ( ePageType == NORMAL || ePageType == LAYOUT )
+ WritePlaceholderReferenceShapes(aDML, ePageType);
pFS->endElementNS(XML_p, XML_spTree);
}
@@ -1449,41 +1488,22 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
mpFS->endElementNS(XML_p, XML_cNvSpPr);
mpFS->startElementNS(XML_p, XML_nvPr);
- const char* pType = nullptr;
- switch (ePlaceholder)
+ bool bUsePlaceholderIndex
+ = ePlaceholder == Footer || ePlaceholder == DateAndTime || ePlaceholder == SlideNumber;
+ const char* pType = getPlaceholderTypeName(ePlaceholder);
+
+ SAL_INFO("sd.eppt", "write placeholder " << pType);
+ if (bUsePlaceholderIndex)
{
- case SlideImage:
- pType = "sldImg";
- break;
- case Notes:
- pType = "body";
- break;
- case Header:
- pType = "hdr";
- break;
- case Footer:
- pType = "ftr";
- break;
- case SlideNumber:
- pType = "sldNum";
- break;
- case DateAndTime:
- pType = "dt";
- break;
- case Outliner:
- pType = "body";
- break;
- case Title:
- pType = "title";
- break;
- case Subtitle:
- pType = "subTitle";
- break;
- default:
- SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
+ mpFS->singleElementNS(
+ XML_p, XML_ph, XML_type, pType, XML_idx,
+ OString::number(
+ static_cast<PowerPointExport*>(GetFB())->CreateNewPlaceholderIndex(xShape)));
+ }
+ else
+ {
+ mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
}
- SAL_INFO("sd.eppt", "write placeholder " << pType);
- mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
mpFS->endElementNS(XML_p, XML_nvPr);
mpFS->endElementNS(XML_p, XML_nvSpPr);
@@ -1496,13 +1516,150 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
WriteBlipFill(xProps, "Graphic");
mpFS->endElementNS(XML_p, XML_spPr);
- WriteTextBox(xShape, XML_p);
+ WriteTextBox(xShape, XML_p, bUsePlaceholderIndex);
+
+ mpFS->endElementNS(XML_p, XML_sp);
+
+ return *this;
+}
+
+ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceShape(
+ PlaceholderType ePlaceholder, unsigned nReferencedPlaceholderIdx, PageType ePageType,
+ Reference<XPropertySet>& rXPagePropSet)
+{
+ mpFS->startElementNS(XML_p, XML_sp);
+
+ // non visual shape properties
+ mpFS->startElementNS(XML_p, XML_nvSpPr);
+ const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
+ GetFS()->singleElementNS(XML_p, XML_cNvPr, XML_id, OString::number(mnShapeIdMax), XML_name,
+ aPlaceholderID.getStr());
+
+ mpFS->startElementNS(XML_p, XML_cNvSpPr);
+ mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
+ mpFS->endElementNS(XML_p, XML_cNvSpPr);
+ mpFS->startElementNS(XML_p, XML_nvPr);
+
+ const char* pType = getPlaceholderTypeName(ePlaceholder);
+ mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType, XML_idx,
+ OString::number(nReferencedPlaceholderIdx));
+ mpFS->endElementNS(XML_p, XML_nvPr);
+ mpFS->endElementNS(XML_p, XML_nvSpPr);
+
+ // visual shape properties
+ mpFS->startElementNS(XML_p, XML_spPr);
+ mpFS->endElementNS(XML_p, XML_spPr);
+
+ WritePlaceholderReferenceTextBody(ePlaceholder, ePageType, rXPagePropSet);
mpFS->endElementNS(XML_p, XML_sp);
return *this;
}
+ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceTextBody(
+ PlaceholderType ePlaceholder, PageType ePageType, const Reference<XPropertySet> xPagePropSet)
+{
+ mpFS->startElementNS(XML_p, XML_txBody);
+ mpFS->singleElementNS(XML_a, XML_bodyPr);
+ mpFS->startElementNS(XML_a, XML_p);
+
+ switch (ePlaceholder)
+ {
+ case Header:
+ break;
+ case Footer:
+ {
+ OUString aFooterText;
+ if (ePageType == LAYOUT)
+ {
+ aFooterText = "Footer";
+ }
+ else
+ {
+ xPagePropSet->getPropertyValue("FooterText") >>= aFooterText;
+ }
+ mpFS->startElementNS(XML_a, XML_r);
+ mpFS->startElementNS(XML_a, XML_t);
+ mpFS->writeEscaped(aFooterText);
+ mpFS->endElementNS(XML_a, XML_t);
+ mpFS->endElementNS(XML_a, XML_r);
+ break;
+ }
+ case SlideNumber:
+ {
+ OUString aSlideNum;
+ sal_Int32 nSlideNum = 0;
+ if (ePageType == LAYOUT)
+ {
+ aSlideNum = "<#>";
+ }
+ else
+ {
+ xPagePropSet->getPropertyValue("Number") >>= nSlideNum;
+ aSlideNum = OUString::number(nSlideNum);
+ }
+ OString aUUID(comphelper::xml::generateGUIDString());
+ mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID.getStr(), XML_type, "slidenum");
+ mpFS->startElementNS(XML_a, XML_t);
+ mpFS->writeEscaped(aSlideNum);
+ mpFS->endElementNS(XML_a, XML_t);
+ mpFS->endElementNS(XML_a, XML_fld);
+ break;
+ }
+ case DateAndTime:
+ {
+ OUString aDateTimeType = "datetime1";
+ bool bIsDateTimeFixed = false;
+ xPagePropSet->getPropertyValue("IsDateTimeFixed") >>= bIsDateTimeFixed;
+
+ // Ideally "Date" should be replaced with the formatted date text
+ // but since variable datetime overrides the text, this seems fine for now.
+ OUString aDateTimeText = "Date";
+
+ if(ePageType != LAYOUT && !bIsDateTimeFixed)
+ {
+ sal_Int32 nDateTimeFormat = 0;
+ xPagePropSet->getPropertyValue("DateTimeFormat") >>= nDateTimeFormat;
+
+ // 4 LSBs represent the date
+ SvxDateFormat eDate = static_cast<SvxDateFormat>(nDateTimeFormat & 0x0f);
+ // the 4 bits after the date bits represent the time
+ SvxTimeFormat eTime = static_cast<SvxTimeFormat>(nDateTimeFormat >> 4);
+ aDateTimeType = GetDatetimeTypeFromDateTime(eDate, eTime);
+
+ if (aDateTimeType == "datetime")
+ aDateTimeType = "datetime1";
+ }
+
+ if(!bIsDateTimeFixed)
+ {
+ OString aUUID(comphelper::xml::generateGUIDString());
+ mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID.getStr(), XML_type, aDateTimeType.toUtf8());
+ }
+ else
+ {
+ xPagePropSet->getPropertyValue("DateTimeText") >>= aDateTimeText;
+ mpFS->startElementNS(XML_a, XML_r);
+ }
+
+ mpFS->startElementNS(XML_a, XML_t);
+ mpFS->writeEscaped(aDateTimeText);
+ mpFS->endElementNS(XML_a, XML_t);
+
+ mpFS->endElementNS(XML_a, bIsDateTimeFixed ? XML_r : XML_fld);
+ break;
+ }
+ default:
+ SAL_INFO("sd.eppt", "warning: no defined textbody for referenced placeholder type: "
+ << ePlaceholder);
+ }
+ mpFS->endElementNS(XML_a, XML_p);
+ mpFS->endElementNS(XML_p, XML_txBody);
+
+ return *this;
+}
+
#define SYS_COLOR_SCHEMES " <a:dk1>\
<a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
</a:dk1>\
@@ -2011,6 +2168,106 @@ void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExpor
pFS->endElementNS(XML_p, XML_graphicFrame);
}
+void PowerPointExport::WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType)
+{
+ bool bCheckProps = ePageType == NORMAL;
+ Reference<XShape> xShape;
+ Any aAny;
+ OUString aText;
+ if (ePageType == LAYOUT
+ || (bCheckProps && PropValue::GetPropertyValue(aAny, mXPagePropSet, "IsFooterVisible", true)
+ && aAny == true && GetPropertyValue(aAny, mXPagePropSet, "FooterText", true)
+ && (aAny >>= aText) && !aText.isEmpty()))
+ {
+ if ((xShape = GetReferencedPlaceholderXShape(Footer, ePageType)))
+ rDML.WritePlaceholderReferenceShape(Footer,
+ maPlaceholderShapeToIndexMap.find(xShape)->second,
+ ePageType, mXPagePropSet);
+ }
+
+ if (ePageType == LAYOUT
+ || (bCheckProps
+ && PropValue::GetPropertyValue(aAny, mXPagePropSet, "IsPageNumberVisible", true)
+ && aAny == true))
+ {
+ if ((xShape = GetReferencedPlaceholderXShape(SlideNumber, ePageType)))
+ rDML.WritePlaceholderReferenceShape(SlideNumber,
+ maPlaceholderShapeToIndexMap.find(xShape)->second,
+ ePageType, mXPagePropSet);
+ }
+
+ if (ePageType == LAYOUT
+ || (bCheckProps
+ && PropValue::GetPropertyValue(aAny, mXPagePropSet, "IsDateTimeVisible", true)
+ && aAny == true
+ && ((GetPropertyValue(aAny, mXPagePropSet, "DateTimeText", true) && (aAny >>= aText)
+ && !aText.isEmpty())
+ || mXPagePropSet->getPropertyValue("IsDateTimeFixed") == false)))
+ {
+ if ((xShape = GetReferencedPlaceholderXShape(DateAndTime, ePageType)))
+ rDML.WritePlaceholderReferenceShape(DateAndTime,
+ maPlaceholderShapeToIndexMap.find(xShape)->second,
+ ePageType, mXPagePropSet);
+ }
+}
+
+unsigned PowerPointExport::CreateNewPlaceholderIndex(const css::uno::Reference<XShape> &rXShape)
+{
+ maPlaceholderShapeToIndexMap.insert({rXShape, mnPlaceholderIndexMax});
+ return mnPlaceholderIndexMax++;
+}
+
+Reference<XShape> PowerPointExport::GetReferencedPlaceholderXShape(const PlaceholderType eType,
+ PageType ePageType) const
+{
+ PresObjKind ePresObjKind = PresObjKind::PRESOBJ_NONE;
+ switch (eType)
+ {
+ case oox::core::None:
+ break;
+ case oox::core::SlideImage:
+ break;
+ case oox::core::Notes:
+ break;
+ case oox::core::Header:
+ ePresObjKind = PresObjKind::PRESOBJ_HEADER;
+ break;
+ case oox::core::Footer:
+ ePresObjKind = PresObjKind::PRESOBJ_FOOTER;
+ break;
+ case oox::core::SlideNumber:
+ ePresObjKind = PresObjKind::PRESOBJ_SLIDENUMBER;
+ break;
+ case oox::core::DateAndTime:
+ ePresObjKind = PresObjKind::PRESOBJ_DATETIME;
+ break;
+ case oox::core::Outliner:
+ break;
+ case oox::core::Title:
+ ePresObjKind = PresObjKind::PRESOBJ_TITLE;
+ break;
+ case oox::core::Subtitle:
+ break;
+ }
+ if (ePresObjKind != PresObjKind::PRESOBJ_NONE)
+ {
+ SdPage* pMasterPage;
+ if (ePageType == LAYOUT)
+ {
+ // since Layout pages do not have drawpages themselves - mXDrawPage is still the master they reference to..
+ pMasterPage = SdPage::getImplementation(mXDrawPage);
+ }
+ else
+ {
+ pMasterPage
+ = &static_cast<SdPage&>(SdPage::getImplementation(mXDrawPage)->TRG_GetMasterPage());
+ }
+ if (SdrObject* pMasterFooter = pMasterPage->GetPresObj(ePresObjKind))
+ return GetXShapeForSdrObject(pMasterFooter);
+ }
+ return nullptr;
+}
+
// UNO component
extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx
index 6bc036f7fa21..290eea440e3c 100644
--- a/sd/source/filter/pdf/sdpdffilter.cxx
+++ b/sd/source/filter/pdf/sdpdffilter.cxx
@@ -71,12 +71,17 @@ bool SdPdfFilter::Import()
// Create the page and insert the Graphic.
SdPage* pPage = mrDocument.GetSdPage(nPageNumber, PageKind::Standard);
+ if (!pPage) // failed to duplicate page, out of memory?
+ return false;
// Make the page size match the rendered image.
pPage->SetSize(aSizeHMM);
SdrGrafObj* pSdrGrafObj = new SdrGrafObj(pPage->getSdrModelFromSdrPage(), rGraphic,
tools::Rectangle(Point(), aSizeHMM));
+ if (!pSdrGrafObj) // out of memory
+ return false;
+
pPage->InsertObject(pSdrGrafObj);
for (auto const& rPDFAnnotation : rPDFGraphicResult.maAnnotations)
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 694959d327e6..f43ad32ca6ab 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -71,6 +71,7 @@
#include <unotools/pathoptions.hxx>
#include <osl/time.h>
#include <sfx2/lokhelper.hxx>
+#include <basic/sberrors.hxx>
#include <iostream>
#include <map>
@@ -616,6 +617,24 @@ void SfxDispatchController_Impl::dispatch( const css::util::URL& aURL,
collectUIInformation(aURL, aArgs);
SolarMutexGuard aGuard;
+
+ if (comphelper::LibreOfficeKit::isActive() &&
+ SfxViewShell::Current()->isFreemiumView() &&
+ comphelper::LibreOfficeKit::isCommandFreemiumDenied(aURL.Complete))
+ {
+ boost::property_tree::ptree aTree;
+ aTree.put("code", "");
+ aTree.put("kind", "freemiumdeny");
+ aTree.put("cmd", aURL.Complete);
+ aTree.put("message", "Blocked Freemium feature");
+ aTree.put("viewID", SfxViewShell::Current()->GetViewShellId().get());
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ SfxViewShell::Current()->libreOfficeKitViewCallback(LOK_CALLBACK_ERROR, aStream.str().c_str());
+ return;
+ }
+
if (
!(pDispatch &&
(
diff --git a/sfx2/source/notebookbar/SfxNotebookBar.cxx b/sfx2/source/notebookbar/SfxNotebookBar.cxx
index 0fdb739cd3f0..cc06c280f71a 100644
--- a/sfx2/source/notebookbar/SfxNotebookBar.cxx
+++ b/sfx2/source/notebookbar/SfxNotebookBar.cxx
@@ -382,7 +382,8 @@ bool SfxNotebookBar::StateMethod(SystemWindow* pSysWindow,
// * in LOK: Paste Special feature was incorrectly initialized
// Skip first request so Notebookbar will be initialized after document was loaded
static std::map<const void*, bool> bSkippedFirstInit;
- if (comphelper::LibreOfficeKit::isActive() && bSkippedFirstInit.find(pViewShell) == bSkippedFirstInit.end())
+ if (comphelper::LibreOfficeKit::isActive() && eApp == vcl::EnumContext::Application::Writer
+ && bSkippedFirstInit.find(pViewShell) == bSkippedFirstInit.end())
{
bSkippedFirstInit[pViewShell] = true;
return false;
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 9208c6e35476..04ea9b8a25f5 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -177,6 +177,23 @@ void SfxLokHelper::setView(int nId)
}
+SfxViewShell* SfxLokHelper::getViewOfId(int nId)
+{
+ SfxApplication* pApp = SfxApplication::Get();
+ if (pApp == nullptr)
+ return nullptr;
+
+ const ViewShellId nViewShellId(nId);
+ SfxViewShellArr_Impl& rViewArr = pApp->GetViewShells_Impl();
+ for (SfxViewShell* pViewShell : rViewArr)
+ {
+ if (pViewShell->GetViewShellId() == nViewShellId)
+ return pViewShell;
+ }
+
+ return nullptr;
+}
+
int SfxLokHelper::getView(const SfxViewShell* pViewShell)
{
if (!pViewShell)
@@ -717,6 +734,14 @@ void SfxLokHelper::postKeyEventAsync(const VclPtr<vcl::Window> &xWindow,
postEventAsync(pLOKEv);
}
+void SfxLokHelper::setFreemiumView(int nViewId, bool isFreemium)
+{
+ SfxViewShell* pViewShell = SfxLokHelper::getViewOfId(nViewId);
+
+ if(pViewShell)
+ pViewShell->setFreemiumView(isFreemium);
+}
+
void SfxLokHelper::postExtTextEventAsync(const VclPtr<vcl::Window> &xWindow,
int nType, const OUString &rText)
{
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index d7790fcdb6f5..2b97061fa8da 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -1087,6 +1087,7 @@ SfxViewShell::SfxViewShell
, maLOKLanguageTag(LANGUAGE_NONE)
, maLOKLocale(LANGUAGE_NONE)
, maLOKDeviceFormFactor(LOKDeviceFormFactor::UNKNOWN)
+, mbLOKIsFreemiumView(false)
{
SetMargin( pViewFrame->GetMargin_Impl() );
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 61f7d472ecd6..738faec6175f 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -1108,7 +1108,7 @@ void SdrMarkView::SetMarkHandlesForLOKit(tools::Rectangle const & rRect, SfxView
boost::property_tree::write_json(aStream, aTableJsonTree);
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, aStream.str().c_str());
}
- else
+ else if (!getSdrModelFromSdrView().IsWriter())
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, "{}");
}
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 7d3b70dbf363..fd0e4aef29a8 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -72,6 +72,7 @@
#include <tabcol.hxx>
#include <wrtsh.hxx>
#include <undobj.hxx>
+#include <view.hxx>
#include <boost/property_tree/json_parser.hpp>
using namespace com::sun::star;
@@ -2033,10 +2034,13 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
void SwCursorShell::sendLOKCursorUpdates()
{
- SwWrtShell* pShell = GetDoc()->GetDocShell()->GetWrtShell();
- if (!pShell)
+ SwView* pView = static_cast<SwView*>(GetSfxViewShell());
+ // The view may not have a writer shell if the view's ctor did not finish yet.
+ if (!pView || !pView->GetWrtShellPtr())
return;
+ SwWrtShell* pShell = &pView->GetWrtShell();
+
SwFrame* pCurrentFrame = GetCurrFrame();
SelectionType eType = pShell->GetSelectionType();
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index 04201e1c6f5e..0c8ac383c6cb 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -40,6 +40,7 @@
#include <sfx2/event.hxx>
#include <ftnidx.hxx>
+#include <comphelper/profilezone.hxx>
#include <vcl/svapp.hxx>
#include <editeng/opaqitem.hxx>
#include <SwSmartTagMgr.hxx>
@@ -320,6 +321,8 @@ bool SwLayAction::RemoveEmptyBrowserPages()
void SwLayAction::Action(OutputDevice* pRenderContext)
{
+ comphelper::ProfileZone("SwLayAction::Action");
+
m_bActionInProgress = true;
//TurboMode? Hands-off during idle-format
@@ -1173,6 +1176,8 @@ bool SwLayAction::IsShortCut( SwPageFrame *&prPage )
// introduce support for vertical layout
bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLay, bool bAddRect )
{
+ comphelper::ProfileZone("SwLayAction::FormatLayout");
+
// save page for loop control
if( pLay->IsPageFrame() && static_cast<SwPageFrame*>(pLay) != m_pCurPage )
{
@@ -1596,6 +1601,8 @@ bool SwLayAction::FormatLayoutTab( SwTabFrame *pTab, bool bAddRect )
bool SwLayAction::FormatContent( const SwPageFrame *pPage )
{
+ comphelper::ProfileZone("SwLayAction::FormatContent");
+
const SwContentFrame *pContent = pPage->ContainsContent();
const SwViewShell *pSh = m_pRoot->GetCurrShell();
const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
@@ -2129,6 +2136,8 @@ SwLayIdle::SwLayIdle( SwRootFrame *pRt, SwViewShellImp *pI ) :
, m_bIndicator( false )
#endif
{
+ comphelper::ProfileZone("SwLayIdle::SwLayIdle");
+
SAL_INFO("sw.idle", "SwLayIdle() entry");
pImp->m_pIdleAct = this;
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index 44fa64318acb..3ea93b2c5ee4 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1493,7 +1493,7 @@ void SwTextShell::Execute(SfxRequest &rReq)
OUString sWord(xSpellAlt->getWord());
linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic( xDictionary,
sWord, false, OUString() );
- if (linguistic::DictionaryError::NONE != nAddRes && !xDictionary->getEntry(sWord).is())
+ if (linguistic::DictionaryError::NONE != nAddRes && xDictionary.is() && !xDictionary->getEntry(sWord).is())
{
SvxDicError(rWrtSh.GetView().GetFrameWeld(), nAddRes);
}
diff --git a/sw/source/uibase/uiview/uivwimp.cxx b/sw/source/uibase/uiview/uivwimp.cxx
index 9dc6d467f941..ee6b5d66de1c 100644
--- a/sw/source/uibase/uiview/uivwimp.cxx
+++ b/sw/source/uibase/uiview/uivwimp.cxx
@@ -292,6 +292,8 @@ SwClipboardChangeListener::~SwClipboardChangeListener()
void SAL_CALL SwClipboardChangeListener::disposing( const EventObject& /*rEventObject*/ )
{
+ SolarMutexGuard aGuard;
+ pView = nullptr; // so we don't touch the view if changedContents somehow fires afterwards
}
void SAL_CALL SwClipboardChangeListener::changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject )
diff --git a/translations b/translations
-Subproject 0c8c6b0d6280466e025e5b5bcfb4d2db1399c87
+Subproject 4e10551a479b63802742d5fef9b1426cacf2eee
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 15a083df19a6..082cc64dcef4 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -473,6 +473,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/backendtest/outputdevice/polyline \
vcl/backendtest/outputdevice/polyline_b2d \
vcl/backendtest/outputdevice/rectangle \
+ vcl/jsdialog/enabled \
vcl/jsdialog/jsdialogbuilder \
vcl/jsdialog/executor \
))
diff --git a/vcl/inc/jsdialog/enabled.hxx b/vcl/inc/jsdialog/enabled.hxx
new file mode 100644
index 000000000000..34116b41c009
--- /dev/null
+++ b/vcl/inc/jsdialog/enabled.hxx
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace jsdialog
+{
+bool isBuilderEnabled(const OUString& rUIFile, bool bMobile);
+bool isInterimBuilderEnabledForNotebookbar(const OUString& rUIFile);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx
new file mode 100644
index 000000000000..a82f75ea6e30
--- /dev/null
+++ b/vcl/jsdialog/enabled.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <jsdialog/enabled.hxx>
+
+namespace jsdialog
+{
+bool isBuilderEnabled(const OUString& rUIFile, bool bMobile)
+{
+ if (bMobile)
+ {
+ if (rUIFile == "modules/swriter/ui/wordcount-mobile.ui"
+ || rUIFile == "svx/ui/findreplacedialog-mobile.ui"
+ || rUIFile == "modules/swriter/ui/watermarkdialog.ui"
+ || rUIFile == "modules/scalc/ui/validationdialog.ui"
+ || rUIFile == "modules/scalc/ui/validationcriteriapage.ui"
+ || rUIFile == "modules/scalc/ui/validationhelptabpage-mobile.ui"
+ || rUIFile == "modules/scalc/ui/erroralerttabpage-mobile.ui"
+ || rUIFile == "modules/scalc/ui/validationdialog.ui")
+ {
+ return true;
+ }
+ }
+
+ if (rUIFile == "modules/scalc/ui/pivottablelayoutdialog.ui"
+ || rUIFile == "modules/scalc/ui/selectsource.ui"
+ || rUIFile == "modules/scalc/ui/managenamesdialog.ui"
+ || rUIFile == "modules/scalc/ui/definename.ui"
+ || rUIFile == "modules/scalc/ui/correlationdialog.ui"
+ || rUIFile == "modules/scalc/ui/samplingdialog.ui"
+ || rUIFile == "modules/scalc/ui/descriptivestatisticsdialog.ui"
+ || rUIFile == "modules/scalc/ui/analysisofvariancedialog.ui"
+ || rUIFile == "modules/scalc/ui/covariancedialog.ui"
+ || rUIFile == "modules/scalc/ui/exponentialsmoothingdialog.ui"
+ || rUIFile == "modules/scalc/ui/movingaveragedialog.ui"
+ || rUIFile == "modules/scalc/ui/regressiondialog.ui"
+ || rUIFile == "modules/scalc/ui/ttestdialog.ui"
+ || rUIFile == "modules/scalc/ui/ttestdialog.ui"
+ || rUIFile == "modules/scalc/ui/ztestdialog.ui"
+ || rUIFile == "modules/scalc/ui/chisquaretestdialog.ui"
+ || rUIFile == "modules/scalc/ui/fourieranalysisdialog.ui"
+ || rUIFile == "modules/scalc/ui/datafielddialog.ui"
+ || rUIFile == "modules/scalc/ui/pivotfielddialog.ui"
+ || rUIFile == "modules/scalc/ui/datafieldoptionsdialog.ui"
+ || rUIFile == "svx/ui/fontworkgallerydialog.ui"
+ || rUIFile == "cui/ui/macroselectordialog.ui" || rUIFile == "uui/ui/macrowarnmedium.ui"
+ || rUIFile == "modules/scalc/ui/textimportcsv.ui")
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool isInterimBuilderEnabledForNotebookbar(const OUString& rUIFile)
+{
+ if (rUIFile == "svx/ui/stylespreview.ui" || rUIFile == "modules/scalc/ui/numberbox.ui")
+ {
+ return true;
+ }
+
+ return false;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
index bd6b7bd00b56..af57c98e7dcd 100644
--- a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
+++ b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <comphelper/profilezone.hxx>
#include <comphelper/threadpool.hxx>
#include <tools/helpers.hxx>
@@ -127,6 +128,7 @@ public:
void scaleUp32bit(ScaleContext &rCtx, long nStartY, long nEndY)
{
+ comphelper::ProfileZone pz("BitmapScaleSuperFilter::scaleUp32bit");
const int nColorComponents = 4;
const long nStartX = 0;
@@ -261,6 +263,7 @@ void scaleUpPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
void scaleUp24bit(ScaleContext &rCtx, long nStartY, long nEndY)
{
+ comphelper::ProfileZone pz("BitmapScaleSuperFilter::scaleUp24bit");
const int nColorComponents = 3;
const long nStartX = 0;
@@ -351,6 +354,7 @@ void scaleUpNonPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
void scaleDown32bit(ScaleContext &rCtx, long nStartY, long nEndY)
{
+ comphelper::ProfileZone pz("BitmapScaleSuperFilter::scaleDown32bit");
const int constColorComponents = 4;
const long nStartX = 0;
@@ -746,6 +750,7 @@ void scaleDownPaletteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
void scaleDown24bit(ScaleContext &rCtx, long nStartY, long nEndY)
{
+ comphelper::ProfileZone pz("BitmapScaleSuperFilter::scaleDown24bit");
const int constColorComponents = 3;
const long nStartX = 0;
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3cf733449d31..70038fa3fb2d 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -4155,9 +4155,6 @@ void PDFWriterImpl::createDefaultRadioButtonAppearance( PDFWidget& rBox, const P
pop();
- OStringBuffer aDA( 256 );
- appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
- rBox.m_aDAString = aDA.makeStringAndClear();
//to encrypt this (el)
rBox.m_aMKDict = "/CA";
//after this assignment, to m_aMKDic cannot be added anything
@@ -4170,6 +4167,7 @@ void PDFWriterImpl::createDefaultRadioButtonAppearance( PDFWidget& rBox, const P
SvMemoryStream* pCheckStream = new SvMemoryStream( 256, 256 );
beginRedirect( pCheckStream, aCheckRect );
+ OStringBuffer aDA( 256 );
aDA.append( "/Tx BMC\nq BT\n" );
appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
aDA.append( ' ' );
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index e52b02410ebd..452a9dbfdfe9 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -25,6 +25,7 @@
#include <vcl/outdev.hxx>
#include <vcl/settings.hxx>
#include <vcl/virdev.hxx>
+#include <vcl/lazydelete.hxx>
#include <tools/helpers.hxx>
@@ -33,10 +34,70 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/WaveLine.hxx>
+#include <boost/functional/hash.hpp>
+#include <o3tl/lru_map.hxx>
#define UNDERLINE_LAST LINESTYLE_BOLDWAVE
#define STRIKEOUT_LAST STRIKEOUT_X
+struct WavyLineCache final
+{
+ WavyLineCache () : m_aItems( 10 ) {}
+
+ bool find( Color aLineColor, size_t nLineWidth, size_t nWaveHeight, size_t nWordWidth, BitmapEx& rOutput )
+ {
+ Key aKey = { nWaveHeight, aLineColor.mValue };
+ auto item = m_aItems.find( aKey );
+ if ( item == m_aItems.end() )
+ return false;
+ // needs update
+ if ( item->second.m_aLineWidth != nLineWidth || item->second.m_aWordWidth < nWordWidth )
+ {
+ return false;
+ }
+ rOutput = item->second.m_Bitmap;
+ return true;
+ }
+
+ void insert( const BitmapEx& aBitmap, const Color& aLineColor, const size_t nLineWidth, const size_t nWaveHeight, const size_t nWordWidth, BitmapEx& rOutput )
+ {
+ Key aKey = { nWaveHeight, aLineColor.mValue };
+ m_aItems.insert( std::pair< Key, WavyLineCacheItem>( aKey, { nLineWidth, nWordWidth, aBitmap } ) );
+ rOutput = aBitmap;
+ }
+
+ private:
+ struct WavyLineCacheItem
+ {
+ size_t m_aLineWidth;
+ size_t m_aWordWidth;
+ BitmapEx m_Bitmap;
+ };
+
+ struct Key
+ {
+ size_t m_aFirst;
+ size_t m_aSecond;
+ bool operator ==( const Key& rOther ) const
+ {
+ return ( m_aFirst == rOther.m_aFirst && m_aSecond == rOther.m_aSecond );
+ }
+ };
+
+ struct Hash
+ {
+ size_t operator() ( const Key& rKey ) const
+ {
+ size_t aSeed = 0;
+ boost::hash_combine(aSeed, rKey.m_aFirst);
+ boost::hash_combine(aSeed, rKey.m_aSecond);
+ return aSeed;
+ }
+ };
+
+ o3tl::lru_map< Key, WavyLineCacheItem, Hash > m_aItems;
+};
+
void OutputDevice::ImplInitTextLineSize()
{
mpFontInstance->mxFontMetric->ImplInitTextLineSize( this );
@@ -1000,6 +1061,43 @@ void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, lo
nLineWidth = 1;
}
+ if ( fOrientation == 0.0 )
+ {
+ static vcl::DeleteOnDeinit< WavyLineCache > snLineCache( new WavyLineCache() );
+ if ( !snLineCache.get() )
+ return;
+ WavyLineCache& rLineCache = *snLineCache.get();
+ BitmapEx aWavylinebmp;
+ if ( !rLineCache.find( GetLineColor(), nLineWidth, nWaveHeight, nEndX - nStartX, aWavylinebmp ) )
+ {
+ size_t nWordLength = nEndX - nStartX;
+ // start with something big to avoid updating it frequently
+ nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
+ ScopedVclPtrInstance< VirtualDevice > pVirtDev( *this, DeviceFormat::DEFAULT,
+ DeviceFormat::DEFAULT );
+ pVirtDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
+ pVirtDev->SetOutputSizePixel( Size( nWordLength, nWaveHeight * 2 ), false );
+ pVirtDev->SetLineColor( GetLineColor() );
+ pVirtDev->SetBackground( Wallpaper( COL_TRANSPARENT ) );
+ pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, nWaveHeight, fOrientation, nLineWidth );
+ rLineCache.insert( pVirtDev->GetBitmapEx( Point( 0, 0 ), pVirtDev->GetOutputSize() ), GetLineColor(), nLineWidth, nWaveHeight, nWordLength, aWavylinebmp );
+ }
+ if ( aWavylinebmp.ImplGetBitmapSalBitmap() != nullptr )
+ {
+ Size _size( nEndX - nStartX, aWavylinebmp.GetSizePixel().Height() );
+ DrawBitmapEx(Point( rStartPos.X(), rStartPos.Y() ), PixelToLogic( _size ), Point(), _size, aWavylinebmp);
+ }
+ return;
+ }
+
+ ImplDrawWaveLineBezier( nStartX, nStartY, nEndX, nEndY, nWaveHeight, fOrientation, nLineWidth );
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos, nLineWidth );
+}
+
+void OutputDevice::ImplDrawWaveLineBezier(long nStartX, long nStartY, long nEndX, long nEndY, long nWaveHeight, double fOrientation, long nLineWidth)
+{
const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, nEndY + nWaveHeight);
const basegfx::B2DPolygon aWaveLinePolygon = basegfx::createWaveLinePolygon(aWaveLineRectangle);
const basegfx::B2DHomMatrix aRotationMatrix = basegfx::utils::createRotateAroundPoint(nStartX, nStartY, basegfx::deg2rad(-fOrientation));
@@ -1018,9 +1116,6 @@ void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, lo
basegfx::deg2rad(15.0),
bPixelSnapHairline,
this);
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos, nLineWidth );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx
index c10cc5f21d9d..08e2dc01fb9c 100644
--- a/vcl/source/uitest/uiobject.cxx
+++ b/vcl/source/uitest/uiobject.cxx
@@ -395,7 +395,7 @@ vcl::Window* findChild(vcl::Window* pParent, const OUString& rID, bool bRequireV
for (size_t i = 0; i < nCount; ++i)
{
vcl::Window* pChild = pParent->GetChild(i);
- if (pChild && pChild->get_id() == rID
+ if (pChild && !pChild->isDisposed() && pChild->get_id() == rID
&& (!bRequireVisible || pChild->IsVisible()))
return pChild;
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 901725d94859..8bd423b77cbc 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -15,6 +15,7 @@
#include <comphelper/lok.hxx>
#include <i18nutil/unicode.hxx>
+#include <jsdialog/enabled.hxx>
#include <officecfg/Office/Common.hxx>
#include <osl/module.hxx>
#include <sal/log.hxx>
@@ -154,50 +155,7 @@ weld::Builder* Application::CreateBuilder(weld::Widget* pParent, const OUString
bool bUseJSBuilder = false;
if (comphelper::LibreOfficeKit::isActive())
- {
- if (bMobile)
- {
- if (rUIFile == "modules/swriter/ui/wordcount-mobile.ui" ||
- rUIFile == "svx/ui/findreplacedialog-mobile.ui" ||
- rUIFile == "modules/swriter/ui/watermarkdialog.ui" ||
- rUIFile == "modules/scalc/ui/validationdialog.ui" ||
- rUIFile == "modules/scalc/ui/validationcriteriapage.ui" ||
- rUIFile == "modules/scalc/ui/validationhelptabpage-mobile.ui" ||
- rUIFile == "modules/scalc/ui/erroralerttabpage-mobile.ui" ||
- rUIFile == "modules/scalc/ui/validationdialog.ui")
- {
- bUseJSBuilder = true;
- }
- }
-
- if (rUIFile == "modules/scalc/ui/pivottablelayoutdialog.ui"
- || rUIFile == "modules/scalc/ui/selectsource.ui"
- || rUIFile == "modules/scalc/ui/managenamesdialog.ui"
- || rUIFile == "modules/scalc/ui/definename.ui"
- || rUIFile == "modules/scalc/ui/correlationdialog.ui"
- || rUIFile == "modules/scalc/ui/samplingdialog.ui"
- || rUIFile == "modules/scalc/ui/descriptivestatisticsdialog.ui"
- || rUIFile == "modules/scalc/ui/analysisofvariancedialog.ui"
- || rUIFile == "modules/scalc/ui/covariancedialog.ui"
- || rUIFile == "modules/scalc/ui/exponentialsmoothingdialog.ui"
- || rUIFile == "modules/scalc/ui/movingaveragedialog.ui"
- || rUIFile == "modules/scalc/ui/regressiondialog.ui"
- || rUIFile == "modules/scalc/ui/ttestdialog.ui"
- || rUIFile == "modules/scalc/ui/ttestdialog.ui"
- || rUIFile == "modules/scalc/ui/ztestdialog.ui"
- || rUIFile == "modules/scalc/ui/chisquaretestdialog.ui"
- || rUIFile == "modules/scalc/ui/fourieranalysisdialog.ui"
- || rUIFile == "modules/scalc/ui/datafielddialog.ui"
- || rUIFile == "modules/scalc/ui/pivotfielddialog.ui"
- || rUIFile == "modules/scalc/ui/datafieldoptionsdialog.ui"
- || rUIFile == "svx/ui/fontworkgallerydialog.ui"
- || rUIFile == "cui/ui/macroselectordialog.ui"
- || rUIFile == "uui/ui/macrowarnmedium.ui"
- || rUIFile == "modules/scalc/ui/textimportcsv.ui")
- {
- bUseJSBuilder = true;
- }
- }
+ bUseJSBuilder = jsdialog::isBuilderEnabled(rUIFile, bMobile);
if (bUseJSBuilder)
return JSInstanceBuilder::CreateDialogBuilder(pParent, VclBuilderContainer::getUIRootDir(), rUIFile);
@@ -208,14 +166,11 @@ weld::Builder* Application::CreateBuilder(weld::Widget* pParent, const OUString
weld::Builder* Application::CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile, sal_uInt64 nLOKWindowId)
{
// Notebookbar sub controls
- if (comphelper::LibreOfficeKit::isActive()
- && (rUIFile == "svx/ui/stylespreview.ui"
- || rUIFile == "modules/scalc/ui/numberbox.ui"))
+ if (comphelper::LibreOfficeKit::isActive() && jsdialog::isInterimBuilderEnabledForNotebookbar(rUIFile))
{
return JSInstanceBuilder::CreateNotebookbarBuilder(pParent, VclBuilderContainer::getUIRootDir(), rUIFile, css::uno::Reference<css::frame::XFrame>(), nLOKWindowId);
}
- else if (comphelper::LibreOfficeKit::isActive()
- && (rUIFile == "modules/scalc/ui/filterdropdown.ui"))
+ else if (comphelper::LibreOfficeKit::isActive() && (rUIFile == "modules/scalc/ui/filterdropdown.ui"))
{
return JSInstanceBuilder::CreateAutofilterWindowBuilder(pParent, VclBuilderContainer::getUIRootDir(), rUIFile);
}
diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx
index 513b186b2dc7..e1f9c9e6777e 100644
--- a/vcl/source/window/mouse.cxx
+++ b/vcl/source/window/mouse.cxx
@@ -467,7 +467,8 @@ void Window::ReleaseMouse()
{
ImplSVData* pSVData = ImplGetSVData();
pSVData->mpWinData->mpCaptureWin = nullptr;
- mpWindowImpl->mpFrame->CaptureMouse( false );
+ if (mpWindowImpl && mpWindowImpl->mpFrame)
+ mpWindowImpl->mpFrame->CaptureMouse( false );
ImplGenerateMouseMove();
}
}
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 0143bf85ee2f..60160d46b71a 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -3889,7 +3889,10 @@ void Window::set_id(const OUString& rID)
const OUString& Window::get_id() const
{
- return mpWindowImpl->maID;
+ if (mpWindowImpl)
+ return mpWindowImpl->maID;
+ static OUString empty;
+ return empty;
}
FactoryFunction Window::GetUITestFactory() const