summaryrefslogtreecommitdiffstats
path: root/io
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--io/CppunitTest_io_textinputstream.mk27
-rw-r--r--io/IwyuFilter_io.yaml36
-rw-r--r--io/Library_io.mk47
-rw-r--r--io/Makefile14
-rw-r--r--io/Module_io.mk20
-rw-r--r--io/README3
-rw-r--r--io/qa/textinputstream.cxx126
-rw-r--r--io/source/TextInputStream/TextInputStream.cxx418
-rw-r--r--io/source/TextOutputStream/TextOutputStream.cxx260
-rw-r--r--io/source/acceptor/acc_pipe.cxx190
-rw-r--r--io/source/acceptor/acc_socket.cxx356
-rw-r--r--io/source/acceptor/acceptor.cxx274
-rw-r--r--io/source/acceptor/acceptor.hxx76
-rw-r--r--io/source/connector/connector.cxx191
-rw-r--r--io/source/connector/connector.hxx95
-rw-r--r--io/source/connector/ctr_pipe.cxx97
-rw-r--r--io/source/connector/ctr_socket.cxx233
-rw-r--r--io/source/io.component58
-rw-r--r--io/source/services.cxx101
-rw-r--r--io/source/services.hxx102
-rw-r--r--io/source/stm/odata.cxx1284
-rw-r--r--io/source/stm/omark.cxx801
-rw-r--r--io/source/stm/opipe.cxx380
-rw-r--r--io/source/stm/opump.cxx458
-rw-r--r--io/source/stm/streamhelper.cxx173
-rw-r--r--io/source/stm/streamhelper.hxx88
-rw-r--r--io/test/makefile.mk83
-rw-r--r--io/test/stm/datatest.cxx1074
-rw-r--r--io/test/stm/exports.dxp2
-rw-r--r--io/test/stm/makefile.mk89
-rw-r--r--io/test/stm/marktest.cxx644
-rw-r--r--io/test/stm/pipetest.cxx420
-rw-r--r--io/test/stm/pumptest.cxx430
-rw-r--r--io/test/stm/testfactreg.cxx199
-rw-r--r--io/test/stm/testfactreg.hxx111
-rw-r--r--io/test/testcomponent.cxx206
-rw-r--r--io/test/testconnection.cxx265
-rw-r--r--ios/.gitignore9
-rw-r--r--ios/CustomTarget_iOS_link.mk90
-rw-r--r--ios/CustomTarget_iOS_setup.mk127
-rw-r--r--ios/DISCLAIMER_WARNING11
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/project.pbxproj635
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme98
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Release.xcscheme91
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/AppDelegate.swift117
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/Contents.json116
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-1024.pngbin0 -> 29447 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-120.pngbin0 -> 7627 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-152.pngbin0 -> 9043 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-167.pngbin0 -> 10012 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-180.pngbin0 -> 11718 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-20.pngbin0 -> 1204 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-29.pngbin0 -> 1674 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-40.pngbin0 -> 2194 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-58.pngbin0 -> 3212 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-60.pngbin0 -> 3425 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-76.pngbin0 -> 4366 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-80.pngbin0 -> 4458 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-87.pngbin0 -> 4744 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/Contents.json23
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back.pngbin0 -> 805 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@2x.pngbin0 -> 1111 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@3x.pngbin0 -> 1813 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/Contents.json6
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/drawing-template.icnsbin0 -> 46225 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/drawing.icnsbin0 -> 43334 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/empty-document.icobin0 -> 35123 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/empty-template.icobin0 -> 35123 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/extension.icnsbin0 -> 39192 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/formula.icnsbin0 -> 43893 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/main.icnsbin0 -> 83974 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/master-document.icnsbin0 -> 40262 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/oasis-database.icnsbin0 -> 269094 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/oasis-drawing-template.icobin0 -> 58428 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/oasis-drawing.icnsbin0 -> 218393 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/oasis-formula.icobin0 -> 47043 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/oasis-master-document-template.icnsbin0 -> 118979 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/oasis-master-document.icobin0 -> 38441 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/oasis-presentation-template.icnsbin0 -> 277602 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/oasis-presentation.icobin0 -> 44754 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/oasis-spreadsheet-template.icnsbin0 -> 292177 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/oasis-spreadsheet.icnsbin0 -> 168743 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/oasis-text-template.icobin0 -> 54827 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/oasis-text.icobin0 -> 46469 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/oasis-web-template.icnsbin0 -> 333385 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/open.icobin0 -> 35123 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/presentation-template.icobin0 -> 54551 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/presentation.icobin0 -> 44754 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/soffice.icobin0 -> 35123 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/spreadsheet-template.icnsbin0 -> 46239 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/spreadsheet.icnsbin0 -> 43146 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/text-template.icnsbin0 -> 43403 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/Contents.json12
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/text.icnsbin0 -> 40399 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/Contents.json23
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/intro.pngbin0 -> 71016 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/Contents.json23
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu.pngbin0 -> 586 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@2x.pngbin0 -> 648 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@3x.pngbin0 -> 722 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/ButtonScrollView.swift145
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/DocumentActions.swift75
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/DocumentController.swift598
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/DocumentOverlaysView.swift68
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/DocumentTiledView.swift244
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Info.plist1812
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/AsyncUtil.swift92
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift592
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/DocumentHolder.swift345
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/LOKitThread.swift139
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitIOSTests.swift102
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitWrapper.swift231
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/RenderCache.swift78
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LOKit/Util.swift43
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight-Prefix.pch22
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.entitlements18
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/.xccurrentversion5
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/LibreOfficeLight.xcdatamodel/contents4
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/PropertiesController.swift99
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/Root.plist38
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/en.lproj/Root.stringsbin0 -> 546 bytes
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/UIViewExtensions.swift74
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/ViewPrintManager.swift27
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/ViewProperties.swift30
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/en.lproj/LaunchScreen.xib109
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/en.lproj/Main.storyboard501
-rw-r--r--ios/LibreOfficeLight/LibreOfficeLight/lokit-Bridging-Header.h16
-rw-r--r--ios/Makefile13
-rw-r--r--ios/Module_ios.mk25
-rw-r--r--ios/README49
-rw-r--r--ios/UnitTest/UnitTest.xcodeproj/project.pbxproj814
-rw-r--r--ios/UnitTest/UnitTest/AppDelegate.h16
-rw-r--r--ios/UnitTest/UnitTest/AppDelegate.m52
-rw-r--r--ios/UnitTest/UnitTest/Assets.xcassets/AppIcon.appiconset/Contents.json98
-rw-r--r--ios/UnitTest/UnitTest/Assets.xcassets/Contents.json6
-rw-r--r--ios/UnitTest/UnitTest/Base.lproj/LaunchScreen.storyboard25
-rw-r--r--ios/UnitTest/UnitTest/Base.lproj/Main.storyboard24
-rw-r--r--ios/UnitTest/UnitTest/Info.plist47
-rw-r--r--ios/UnitTest/UnitTest/ViewController.h14
-rw-r--r--ios/UnitTest/UnitTest/ViewController.mm76
-rw-r--r--ios/UnitTest/UnitTest/main.m18
-rw-r--r--ios/source/LibreOfficeKit.c119
-rw-r--r--ios/source/LibreOfficeKit.h34
-rw-r--r--ios/welcome.odtbin0 -> 297986 bytes
172 files changed, 18085 insertions, 0 deletions
diff --git a/io/CppunitTest_io_textinputstream.mk b/io/CppunitTest_io_textinputstream.mk
new file mode 100644
index 000000000..a18e64378
--- /dev/null
+++ b/io/CppunitTest_io_textinputstream.mk
@@ -0,0 +1,27 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,io_textinputstream))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,io_textinputstream, \
+ io/qa/textinputstream \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,io_textinputstream, \
+ cppu \
+ cppuhelper \
+ sal \
+ unotest \
+))
+
+$(eval $(call gb_CppunitTest_use_udk_api,io_textinputstream))
+
+$(eval $(call gb_CppunitTest_use_ure,io_textinputstream))
+
+# vim: set noet sw=4 ts=4:
diff --git a/io/IwyuFilter_io.yaml b/io/IwyuFilter_io.yaml
new file mode 100644
index 000000000..9d4609898
--- /dev/null
+++ b/io/IwyuFilter_io.yaml
@@ -0,0 +1,36 @@
+---
+assumeFilename: io/source/services.cxx
+blacklist:
+ io/source/acceptor/acceptor.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/connector/connector.hxx:
+ # Base class needs full type
+ - com/sun/star/connection/XConnection.hpp
+ - com/sun/star/connection/XConnectionBroadcaster.hpp
+ # Don't replace with impl. detail
+ - osl/socket.hxx
+ - osl/pipe.hxx
+ io/source/connector/connector.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/TextInputStream/TextInputStream.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/TextOutputStream/TextOutputStream.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/stm/odata.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/stm/opipe.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ io/source/stm/opump.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
+ # Don't replace with URE API impl. detail
+ - cppuhelper/interfacecontainer.hxx
+ io/source/stm/omark.cxx:
+ # Avoid loplugin:unreffun error
+ - services.hxx
diff --git a/io/Library_io.mk b/io/Library_io.mk
new file mode 100644
index 000000000..8f85ca8b4
--- /dev/null
+++ b/io/Library_io.mk
@@ -0,0 +1,47 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,io))
+
+$(eval $(call gb_Library_use_external,io,boost_headers))
+
+$(eval $(call gb_Library_use_udk_api,io))
+
+$(eval $(call gb_Library_use_libraries,io,\
+ cppu \
+ cppuhelper \
+ sal \
+ tl \
+))
+
+$(eval $(call gb_Library_set_componentfile,io,io/source/io))
+
+$(eval $(call gb_Library_set_include,io,\
+ -I$(SRCDIR)/io/source \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Library_add_exception_objects,io,\
+ io/source/services \
+ io/source/acceptor/acc_pipe \
+ io/source/acceptor/acc_socket \
+ io/source/acceptor/acceptor \
+ io/source/connector/connector \
+ io/source/connector/ctr_pipe \
+ io/source/connector/ctr_socket \
+ io/source/stm/odata \
+ io/source/stm/omark \
+ io/source/stm/opipe \
+ io/source/stm/opump \
+ io/source/stm/streamhelper \
+ io/source/TextInputStream/TextInputStream \
+ io/source/TextOutputStream/TextOutputStream \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/io/Makefile b/io/Makefile
new file mode 100644
index 000000000..0997e6284
--- /dev/null
+++ b/io/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/io/Module_io.mk b/io/Module_io.mk
new file mode 100644
index 000000000..c9751d9be
--- /dev/null
+++ b/io/Module_io.mk
@@ -0,0 +1,20 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Module_Module,io))
+
+$(eval $(call gb_Module_add_targets,io,\
+ Library_io \
+))
+
+$(eval $(call gb_Module_add_subsequentcheck_targets,io,\
+ CppunitTest_io_textinputstream \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/io/README b/io/README
new file mode 100644
index 000000000..229153f04
--- /dev/null
+++ b/io/README
@@ -0,0 +1,3 @@
+Simple IO wrapper UNO components
+
+
diff --git a/io/qa/textinputstream.cxx b/io/qa/textinputstream.cxx
new file mode 100644
index 000000000..dfeb478f9
--- /dev/null
+++ b/io/qa/textinputstream.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/TextInputStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XTextInputStream2.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <osl/mutex.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <unotest/bootstrapfixturebase.hxx>
+
+namespace {
+
+class Input: public cppu::WeakImplHelper<css::io::XInputStream> {
+public:
+ Input(): open_(true), index_(0) {}
+
+private:
+ virtual ~Input() override {}
+
+ sal_Int32 SAL_CALL readBytes(css::uno::Sequence<sal_Int8> &, sal_Int32)
+ override
+ { CPPUNIT_FAIL("readLine is supposed to call readSomeBytes instead"); }
+
+ sal_Int32 SAL_CALL readSomeBytes(
+ css::uno::Sequence<sal_Int8 > & aData, sal_Int32 nMaxBytesToRead) override
+ {
+ assert(nMaxBytesToRead >= 0);
+ osl::MutexGuard g(mutex_);
+ checkClosed();
+ assert(index_ >= 0 && index_ <= SIZE);
+ sal_Int32 n = std::min<sal_Int32>(
+ std::min<sal_Int32>(nMaxBytesToRead, 2), SIZE - index_);
+ assert(n >= 0 && n <= SIZE - index_);
+ aData.realloc(n);
+ std::memcpy(aData.getArray(), data + index_, n);
+ index_ += n;
+ assert(index_ >= 0 && index_ <= SIZE);
+ return n;
+ }
+
+ void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
+ {
+ assert(nBytesToSkip >= 0);
+ osl::MutexGuard g(mutex_);
+ checkClosed();
+ assert(index_ >= 0 && index_ <= SIZE);
+ index_ += std::min<sal_Int32>(nBytesToSkip, SIZE - index_);
+ assert(index_ >= 0 && index_ <= SIZE);
+ }
+
+ sal_Int32 SAL_CALL available() override
+ {
+ osl::MutexGuard g(mutex_);
+ checkClosed();
+ assert(index_ >= 0 && index_ <= SIZE);
+ return SIZE - index_;
+ }
+
+ void SAL_CALL closeInput() override
+ {
+ osl::MutexGuard g(mutex_);
+ checkClosed();
+ open_ = true;
+ }
+
+ void checkClosed() {
+ if (!open_) {
+ throw css::io::NotConnectedException(
+ "test input stream already closed");
+ }
+ }
+
+ static sal_Int32 const SIZE = 9;
+ static char const data[SIZE];
+
+ osl::Mutex mutex_;
+ bool open_;
+ sal_Int32 index_;
+};
+
+char const Input::data[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+
+class Test: public test::BootstrapFixtureBase {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testReadLine);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testReadLine();
+};
+
+void Test::testReadLine() {
+ css::uno::Reference<css::io::XTextInputStream2> s(
+ css::io::TextInputStream::create(getComponentContext()));
+ s->setInputStream(new Input);
+ OUString l(s->readLine());
+ CPPUNIT_ASSERT_EQUAL(OUString("123456789"), l);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/TextInputStream/TextInputStream.cxx b/io/source/TextInputStream/TextInputStream.cxx
new file mode 100644
index 000000000..fc860b106
--- /dev/null
+++ b/io/source/TextInputStream/TextInputStream.cxx
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string.h>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <rtl/textenc.h>
+#include <rtl/tencinfo.h>
+
+#include <com/sun/star/io/BufferSizeExceededException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/XTextInputStream2.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <services.hxx>
+
+#include <vector>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+#define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextInputStream"
+#define SERVICE_NAME "com.sun.star.io.TextInputStream"
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::io;
+
+namespace io_TextInputStream
+{
+
+// Implementation XTextInputStream
+
+#define INITIAL_UNICODE_BUFFER_CAPACITY 0x100
+#define READ_BYTE_COUNT 0x100
+
+namespace {
+
+class OTextInputStream : public WeakImplHelper< XTextInputStream2, XServiceInfo >
+{
+ Reference< XInputStream > mxStream;
+
+ // Encoding
+ bool mbEncodingInitialized;
+ rtl_TextToUnicodeConverter mConvText2Unicode;
+ rtl_TextToUnicodeContext mContextText2Unicode;
+ Sequence<sal_Int8> mSeqSource;
+
+ // Internal buffer for characters that are already converted successfully
+ std::vector<sal_Unicode> mvBuffer;
+ sal_Int32 mnCharsInBuffer;
+ bool mbReachedEOF;
+
+ /// @throws IOException
+ /// @throws RuntimeException
+ OUString implReadString( const Sequence< sal_Unicode >& Delimiters,
+ bool bRemoveDelimiter, bool bFindLineEnd );
+ /// @throws IOException
+ /// @throws RuntimeException
+ sal_Int32 implReadNext();
+
+public:
+ OTextInputStream();
+ virtual ~OTextInputStream() override;
+
+ // Methods XTextInputStream
+ virtual OUString SAL_CALL readLine( ) override;
+ virtual OUString SAL_CALL readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter ) override;
+ virtual sal_Bool SAL_CALL isEOF( ) override;
+ virtual void SAL_CALL setEncoding( const OUString& Encoding ) override;
+
+ // Methods XInputStream
+ virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override;
+ virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override;
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
+ virtual sal_Int32 SAL_CALL available( ) override;
+ virtual void SAL_CALL closeInput( ) override;
+
+ // Methods XActiveDataSink
+ virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream ) override;
+ virtual Reference< XInputStream > SAL_CALL getInputStream() override;
+
+ // Methods XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+};
+
+}
+
+OTextInputStream::OTextInputStream()
+ : mbEncodingInitialized(false)
+ , mConvText2Unicode(nullptr)
+ , mContextText2Unicode(nullptr)
+ , mSeqSource(READ_BYTE_COUNT)
+ , mvBuffer(INITIAL_UNICODE_BUFFER_CAPACITY, 0)
+ , mnCharsInBuffer(0)
+ , mbReachedEOF(false)
+{
+}
+
+OTextInputStream::~OTextInputStream()
+{
+ if( mbEncodingInitialized )
+ {
+ rtl_destroyTextToUnicodeContext( mConvText2Unicode, mContextText2Unicode );
+ rtl_destroyTextToUnicodeConverter( mConvText2Unicode );
+ }
+}
+
+
+// XTextInputStream
+
+OUString OTextInputStream::readLine( )
+{
+ static Sequence< sal_Unicode > aDummySeq;
+ return implReadString( aDummySeq, true, true );
+}
+
+OUString OTextInputStream::readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter )
+{
+ return implReadString( Delimiters, bRemoveDelimiter, false );
+}
+
+sal_Bool OTextInputStream::isEOF()
+{
+ bool bRet = false;
+ if( mnCharsInBuffer == 0 && mbReachedEOF )
+ bRet = true;
+ return bRet;
+}
+
+
+OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimiters,
+ bool bRemoveDelimiter, bool bFindLineEnd )
+{
+ OUString aRetStr;
+ if( !mbEncodingInitialized )
+ {
+ setEncoding( "utf8" );
+ }
+ if( !mbEncodingInitialized )
+ return aRetStr;
+
+ // Only for bFindLineEnd
+ sal_Unicode cLineEndChar1 = 0x0D;
+ sal_Unicode cLineEndChar2 = 0x0A;
+
+ sal_Int32 nBufferReadPos = 0;
+ sal_Int32 nCopyLen = 0;
+ bool bFound = false;
+ bool bFoundFirstLineEndChar = false;
+ sal_Unicode cFirstLineEndChar = 0;
+ while( !bFound )
+ {
+ // Still characters available?
+ if( nBufferReadPos == mnCharsInBuffer )
+ {
+ // Already reached EOF? Then we can't read any more
+ if( mbReachedEOF )
+ break;
+
+ // No, so read new characters
+ if( !implReadNext() )
+ break;
+ }
+
+ // Now there should be characters available
+ // (otherwise the loop should have been broken before)
+ sal_Unicode c = mvBuffer[ nBufferReadPos++ ];
+
+ if( bFindLineEnd )
+ {
+ if( bFoundFirstLineEndChar )
+ {
+ bFound = true;
+ nCopyLen = nBufferReadPos - 2;
+ if( c == cLineEndChar1 || c == cLineEndChar2 )
+ {
+ // Same line end char -> new line break
+ if( c == cFirstLineEndChar )
+ {
+ nBufferReadPos--;
+ }
+ }
+ else
+ {
+ // No second line end char
+ nBufferReadPos--;
+ }
+ }
+ else if( c == cLineEndChar1 || c == cLineEndChar2 )
+ {
+ bFoundFirstLineEndChar = true;
+ cFirstLineEndChar = c;
+ }
+ }
+ else if( comphelper::findValue(Delimiters, c) != -1 )
+ {
+ bFound = true;
+ nCopyLen = nBufferReadPos;
+ if( bRemoveDelimiter )
+ nCopyLen--;
+ }
+ }
+
+ // Nothing found? Return all
+ if( !nCopyLen && !bFound && mbReachedEOF )
+ nCopyLen = nBufferReadPos;
+
+ // Create string
+ if( nCopyLen )
+ aRetStr = OUString( mvBuffer.data(), nCopyLen );
+
+ // Copy rest of buffer
+ memmove( mvBuffer.data(), mvBuffer.data() + nBufferReadPos,
+ (mnCharsInBuffer - nBufferReadPos) * sizeof( sal_Unicode ) );
+ mnCharsInBuffer -= nBufferReadPos;
+
+ return aRetStr;
+}
+
+
+sal_Int32 OTextInputStream::implReadNext()
+{
+ sal_Int32 nFreeBufferSize = mvBuffer.size() - mnCharsInBuffer;
+ if( nFreeBufferSize < READ_BYTE_COUNT )
+ mvBuffer.resize(mvBuffer.size() * 2);
+ nFreeBufferSize = mvBuffer.size() - mnCharsInBuffer;
+
+ try
+ {
+ sal_Int32 nRead = mxStream->readSomeBytes( mSeqSource, READ_BYTE_COUNT );
+ sal_Int32 nTotalRead = nRead;
+ if( nRead == 0 )
+ mbReachedEOF = true;
+
+ // Try to convert
+ sal_uInt32 uiInfo;
+ sal_Size nSrcCvtBytes = 0;
+ sal_Size nTargetCount = 0;
+ sal_Size nSourceCount = 0;
+ while( true )
+ {
+ const sal_Int8 *pbSource = mSeqSource.getConstArray();
+
+ // All invalid characters are transformed to the unicode undefined char
+ nTargetCount += rtl_convertTextToUnicode(
+ mConvText2Unicode,
+ mContextText2Unicode,
+ reinterpret_cast<const char*>(&( pbSource[nSourceCount] )),
+ nTotalRead - nSourceCount,
+ mvBuffer.data() + mnCharsInBuffer + nTargetCount,
+ nFreeBufferSize - nTargetCount,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
+ &uiInfo,
+ &nSrcCvtBytes );
+ nSourceCount += nSrcCvtBytes;
+
+ bool bCont = false;
+ if( uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL )
+ {
+ mvBuffer.resize(mvBuffer.size() * 2);
+ bCont = true;
+ }
+
+ if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL )
+ {
+ // read next byte
+ static Sequence< sal_Int8 > aOneByteSeq( 1 );
+ nRead = mxStream->readSomeBytes( aOneByteSeq, 1 );
+ if( nRead == 0 )
+ {
+ mbReachedEOF = true;
+ break;
+ }
+
+ sal_Int32 nOldLen = mSeqSource.getLength();
+ nTotalRead++;
+ if( nTotalRead > nOldLen )
+ {
+ mSeqSource.realloc( nTotalRead );
+ }
+ mSeqSource.getArray()[ nOldLen ] = aOneByteSeq.getConstArray()[ 0 ];
+ bCont = true;
+ }
+
+ if( bCont )
+ continue;
+ break;
+ }
+
+ mnCharsInBuffer += nTargetCount;
+ return nTargetCount;
+ }
+ catch( NotConnectedException& )
+ {
+ throw IOException();
+ //throw IOException( L"OTextInputStream::implReadString failed" );
+ }
+ catch( BufferSizeExceededException& )
+ {
+ throw IOException();
+ }
+}
+
+void OTextInputStream::setEncoding( const OUString& Encoding )
+{
+ OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
+ rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
+ if( RTL_TEXTENCODING_DONTKNOW == encoding )
+ return;
+
+ mbEncodingInitialized = true;
+ mConvText2Unicode = rtl_createTextToUnicodeConverter( encoding );
+ mContextText2Unicode = rtl_createTextToUnicodeContext( mConvText2Unicode );
+}
+
+
+// XInputStream
+
+sal_Int32 OTextInputStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+{
+ return mxStream->readBytes( aData, nBytesToRead );
+}
+
+sal_Int32 OTextInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+{
+ return mxStream->readSomeBytes( aData, nMaxBytesToRead );
+}
+
+void OTextInputStream::skipBytes( sal_Int32 nBytesToSkip )
+{
+ mxStream->skipBytes( nBytesToSkip );
+}
+
+sal_Int32 OTextInputStream::available( )
+{
+ return mxStream->available();
+}
+
+void OTextInputStream::closeInput( )
+{
+ mxStream->closeInput();
+}
+
+
+// XActiveDataSink
+
+void OTextInputStream::setInputStream( const Reference< XInputStream >& aStream )
+{
+ mxStream = aStream;
+}
+
+Reference< XInputStream > OTextInputStream::getInputStream()
+{
+ return mxStream;
+}
+
+
+Reference< XInterface > TextInputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference< XComponentContext > &)
+{
+ return Reference < XInterface >( static_cast<OWeakObject *>(new OTextInputStream()) );
+}
+
+OUString TextInputStream_getImplementationName()
+{
+ return IMPLEMENTATION_NAME;
+}
+
+Sequence< OUString > TextInputStream_getSupportedServiceNames()
+{
+ Sequence< OUString > seqNames { SERVICE_NAME };
+ return seqNames;
+}
+
+OUString OTextInputStream::getImplementationName()
+{
+ return TextInputStream_getImplementationName();
+}
+
+sal_Bool OTextInputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > OTextInputStream::getSupportedServiceNames()
+{
+ return TextInputStream_getSupportedServiceNames();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/TextOutputStream/TextOutputStream.cxx b/io/source/TextOutputStream/TextOutputStream.cxx
new file mode 100644
index 000000000..22b4de2f1
--- /dev/null
+++ b/io/source/TextOutputStream/TextOutputStream.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <rtl/textenc.h>
+#include <rtl/tencinfo.h>
+
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/XTextOutputStream2.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <services.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+#define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextOutputStream"
+#define SERVICE_NAME "com.sun.star.io.TextOutputStream"
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::io;
+
+namespace io_TextOutputStream
+{
+
+// Implementation XTextOutputStream
+
+namespace {
+
+class OTextOutputStream : public WeakImplHelper< XTextOutputStream2, XServiceInfo >
+{
+ Reference< XOutputStream > mxStream;
+
+ // Encoding
+ bool mbEncodingInitialized;
+ rtl_UnicodeToTextConverter mConvUnicode2Text;
+ rtl_UnicodeToTextContext mContextUnicode2Text;
+
+ Sequence<sal_Int8> implConvert( const OUString& rSource );
+ /// @throws IOException
+ void checkOutputStream() const;
+
+public:
+ OTextOutputStream();
+ virtual ~OTextOutputStream() override;
+
+ // Methods XTextOutputStream
+ virtual void SAL_CALL writeString( const OUString& aString ) override;
+ virtual void SAL_CALL setEncoding( const OUString& Encoding ) override;
+
+ // Methods XOutputStream
+ virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) override;
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL closeOutput( ) override;
+
+ // Methods XActiveDataSource
+ virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream ) override;
+ virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) override;
+
+ // Methods XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+};
+
+}
+
+OTextOutputStream::OTextOutputStream()
+ : mbEncodingInitialized(false)
+ , mConvUnicode2Text(nullptr)
+ , mContextUnicode2Text(nullptr)
+{
+}
+
+OTextOutputStream::~OTextOutputStream()
+{
+ if( mbEncodingInitialized )
+ {
+ rtl_destroyUnicodeToTextContext( mConvUnicode2Text, mContextUnicode2Text );
+ rtl_destroyUnicodeToTextConverter( mConvUnicode2Text );
+ }
+}
+
+Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource )
+{
+ const sal_Unicode *puSource = rSource.getStr();
+ sal_Int32 nSourceSize = rSource.getLength();
+
+ sal_Size nTargetCount = 0;
+ sal_Size nSourceCount = 0;
+
+ sal_uInt32 uiInfo;
+ sal_Size nSrcCvtChars;
+
+ // take nSourceSize * 3 as preference
+ // this is an upper boundary for converting to utf8,
+ // which most often used as the target.
+ sal_Int32 nSeqSize = nSourceSize * 3;
+
+ Sequence<sal_Int8> seqText( nSeqSize );
+ char *pTarget = reinterpret_cast<char *>(seqText.getArray());
+ while( true )
+ {
+ nTargetCount += rtl_convertUnicodeToText(
+ mConvUnicode2Text,
+ mContextUnicode2Text,
+ &( puSource[nSourceCount] ),
+ nSourceSize - nSourceCount ,
+ &( pTarget[nTargetCount] ),
+ nSeqSize - nTargetCount,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT ,
+ &uiInfo,
+ &nSrcCvtChars);
+ nSourceCount += nSrcCvtChars;
+
+ if( uiInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
+ {
+ nSeqSize *= 2;
+ seqText.realloc( nSeqSize ); // double array size
+ pTarget = reinterpret_cast<char*>(seqText.getArray());
+ continue;
+ }
+ break;
+ }
+
+ // reduce the size of the buffer (fast, no copy necessary)
+ seqText.realloc( nTargetCount );
+ return seqText;
+}
+
+
+// XTextOutputStream
+
+void OTextOutputStream::writeString( const OUString& aString )
+{
+ checkOutputStream();
+ if( !mbEncodingInitialized )
+ {
+ setEncoding( "utf8" );
+ }
+ if( !mbEncodingInitialized )
+ return;
+
+ Sequence<sal_Int8> aByteSeq = implConvert( aString );
+ mxStream->writeBytes( aByteSeq );
+}
+
+void OTextOutputStream::setEncoding( const OUString& Encoding )
+{
+ OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
+ rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
+ if( RTL_TEXTENCODING_DONTKNOW == encoding )
+ return;
+
+ mbEncodingInitialized = true;
+ mConvUnicode2Text = rtl_createUnicodeToTextConverter( encoding );
+ mContextUnicode2Text = rtl_createUnicodeToTextContext( mConvUnicode2Text );
+}
+
+
+// XOutputStream
+void OTextOutputStream::writeBytes( const Sequence< sal_Int8 >& aData )
+{
+ checkOutputStream();
+ mxStream->writeBytes( aData );
+}
+
+void OTextOutputStream::flush( )
+{
+ checkOutputStream();
+ mxStream->flush();
+}
+
+void OTextOutputStream::closeOutput( )
+{
+ checkOutputStream();
+ mxStream->closeOutput();
+}
+
+
+void OTextOutputStream::checkOutputStream() const
+{
+ if (! mxStream.is() )
+ throw IOException("output stream is not initialized, you have to use setOutputStream first");
+}
+
+
+// XActiveDataSource
+
+void OTextOutputStream::setOutputStream( const Reference< XOutputStream >& aStream )
+{
+ mxStream = aStream;
+}
+
+Reference< XOutputStream > OTextOutputStream::getOutputStream()
+{
+ return mxStream;
+}
+
+
+Reference< XInterface > TextOutputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference< XComponentContext > &)
+{
+ return Reference < XInterface >( static_cast<OWeakObject *>(new OTextOutputStream()) );
+}
+
+OUString TextOutputStream_getImplementationName()
+{
+ return IMPLEMENTATION_NAME;
+}
+
+
+Sequence< OUString > TextOutputStream_getSupportedServiceNames()
+{
+ Sequence< OUString > seqNames { SERVICE_NAME };
+ return seqNames;
+}
+
+OUString OTextOutputStream::getImplementationName()
+{
+ return TextOutputStream_getImplementationName();
+}
+
+sal_Bool OTextOutputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > OTextOutputStream::getSupportedServiceNames()
+{
+ return TextOutputStream_getSupportedServiceNames();
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/acceptor/acc_pipe.cxx b/io/source/acceptor/acc_pipe.cxx
new file mode 100644
index 000000000..b06b0aa67
--- /dev/null
+++ b/io/source/acceptor/acc_pipe.cxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/security.hxx>
+#include "acceptor.hxx"
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/connection/ConnectionSetupException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <cppuhelper/implbase.hxx>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::connection;
+using namespace ::com::sun::star::io;
+
+
+namespace io_acceptor
+{
+ namespace {
+
+ class PipeConnection :
+ public WeakImplHelper< XConnection >
+ {
+ public:
+ explicit PipeConnection( const OUString &sConnectionDescription);
+
+ virtual sal_Int32 SAL_CALL read( Sequence< sal_Int8 >& aReadBytes, sal_Int32 nBytesToRead ) override;
+ virtual void SAL_CALL write( const Sequence< sal_Int8 >& aData ) override;
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL close( ) override;
+ virtual OUString SAL_CALL getDescription( ) override;
+ public:
+ ::osl::StreamPipe m_pipe;
+ oslInterlockedCount m_nStatus;
+ OUString m_sDescription;
+ };
+
+ }
+
+ PipeConnection::PipeConnection( const OUString &sConnectionDescription) :
+ m_nStatus( 0 ),
+ m_sDescription( sConnectionDescription )
+ {
+ // make it unique
+ m_sDescription += ",uniqueValue=";
+ m_sDescription += OUString::number(
+ sal::static_int_cast<sal_Int64 >(
+ reinterpret_cast< sal_IntPtr >(&m_pipe)) );
+ }
+
+ sal_Int32 PipeConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
+ {
+ if( m_nStatus )
+ {
+ throw IOException();
+ }
+ if( aReadBytes.getLength() < nBytesToRead )
+ {
+ aReadBytes.realloc( nBytesToRead );
+ }
+ sal_Int32 n = m_pipe.read( aReadBytes.getArray(), nBytesToRead );
+ OSL_ASSERT( n >= 0 && n <= aReadBytes.getLength() );
+ if( n < aReadBytes.getLength() )
+ {
+ aReadBytes.realloc( n );
+ }
+ return n;
+
+ }
+
+ void PipeConnection::write( const Sequence < sal_Int8 > &seq )
+ {
+ if( m_nStatus )
+ {
+ throw IOException();
+ }
+ if( m_pipe.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
+ {
+ throw IOException();
+ }
+ }
+
+ void PipeConnection::flush( )
+ {
+ }
+
+ void PipeConnection::close()
+ {
+ if( 1 == osl_atomic_increment( (&m_nStatus) ) )
+ {
+ m_pipe.close();
+ }
+ }
+
+ OUString PipeConnection::getDescription()
+ {
+ return m_sDescription;
+ }
+
+ /***************
+ * PipeAcceptor
+ **************/
+ PipeAcceptor::PipeAcceptor( const OUString &sPipeName , const OUString & sConnectionDescription) :
+ m_sPipeName( sPipeName ),
+ m_sConnectionDescription( sConnectionDescription ),
+ m_bClosed( false )
+ {
+ }
+
+
+ void PipeAcceptor::init()
+ {
+ m_pipe = Pipe( m_sPipeName.pData , osl_Pipe_CREATE , osl::Security() );
+ if( ! m_pipe.is() )
+ {
+ OUString error = "io.acceptor: Couldn't setup pipe " + m_sPipeName;
+ throw ConnectionSetupException( error );
+ }
+ }
+
+ Reference< XConnection > PipeAcceptor::accept( )
+ {
+ Pipe pipe;
+ {
+ MutexGuard guard( m_mutex );
+ pipe = m_pipe;
+ }
+ if( ! pipe.is() )
+ {
+ OUString error = "io.acceptor: pipe already closed" + m_sPipeName;
+ throw ConnectionSetupException( error );
+ }
+ std::unique_ptr<PipeConnection> pConn(new PipeConnection( m_sConnectionDescription ));
+
+ oslPipeError status = pipe.accept( pConn->m_pipe );
+
+ if( m_bClosed )
+ {
+ // stopAccepting was called !
+ return Reference < XConnection >();
+ }
+ else if( osl_Pipe_E_None == status )
+ {
+ return Reference < XConnection > ( static_cast<XConnection *>(pConn.release()) );
+ }
+ else
+ {
+ OUString error = "io.acceptor: Couldn't setup pipe " + m_sPipeName;
+ throw ConnectionSetupException( error );
+ }
+ }
+
+ void PipeAcceptor::stopAccepting()
+ {
+ m_bClosed = true;
+ Pipe pipe;
+ {
+ MutexGuard guard( m_mutex );
+ pipe = m_pipe;
+ m_pipe.clear();
+ }
+ if( pipe.is() )
+ {
+ pipe.close();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/acceptor/acc_socket.cxx b/io/source/acceptor/acc_socket.cxx
new file mode 100644
index 000000000..9700cd566
--- /dev/null
+++ b/io/source/acceptor/acc_socket.cxx
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "acceptor.hxx"
+
+#include <unordered_set>
+
+#include <osl/mutex.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/connection/XConnectionBroadcaster.hpp>
+#include <com/sun/star/connection/ConnectionSetupException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <cppuhelper/implbase.hxx>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::connection;
+
+
+namespace io_acceptor {
+
+ typedef std::unordered_set< css::uno::Reference< css::io::XStreamListener> >
+ XStreamListener_hash_set;
+
+ namespace {
+
+ class SocketConnection : public ::cppu::WeakImplHelper<
+ css::connection::XConnection,
+ css::connection::XConnectionBroadcaster>
+
+ {
+ public:
+ explicit SocketConnection( const OUString & sConnectionDescription );
+
+ virtual sal_Int32 SAL_CALL read( css::uno::Sequence< sal_Int8 >& aReadBytes,
+ sal_Int32 nBytesToRead ) override;
+ virtual void SAL_CALL write( const css::uno::Sequence< sal_Int8 >& aData ) override;
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL close( ) override;
+ virtual OUString SAL_CALL getDescription( ) override;
+
+ // XConnectionBroadcaster
+ virtual void SAL_CALL addStreamListener(const css::uno::Reference< css::io::XStreamListener>& aListener) override;
+ virtual void SAL_CALL removeStreamListener(const css::uno::Reference< css::io::XStreamListener>& aListener) override;
+
+ public:
+ void completeConnectionString();
+
+ ::osl::StreamSocket m_socket;
+ oslInterlockedCount m_nStatus;
+ OUString m_sDescription;
+
+ ::osl::Mutex _mutex;
+ bool _started;
+ bool _closed;
+ bool _error;
+ XStreamListener_hash_set _listeners;
+ };
+
+ }
+
+ template<class T>
+ static void notifyListeners(SocketConnection * pCon, bool * notified, T t)
+ {
+ XStreamListener_hash_set listeners;
+
+ {
+ ::osl::MutexGuard guard(pCon->_mutex);
+ if(!*notified)
+ {
+ *notified = true;
+ listeners = pCon->_listeners;
+ }
+ }
+
+ for(auto& listener : listeners)
+ t(listener);
+ }
+
+ static void callStarted(const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->started();
+ }
+
+ namespace {
+
+ struct callError {
+ const Any & any;
+
+ explicit callError(const Any & any);
+
+ void operator () (const Reference<XStreamListener>& xStreamListener);
+ };
+
+ }
+
+ callError::callError(const Any & aAny)
+ : any(aAny)
+ {
+ }
+
+ void callError::operator () (const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->error(any);
+ }
+
+ static void callClosed(const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->closed();
+ }
+
+
+ SocketConnection::SocketConnection( const OUString &sConnectionDescription) :
+ m_nStatus( 0 ),
+ m_sDescription( sConnectionDescription ),
+ _started(false),
+ _closed(false),
+ _error(false)
+ {
+ // make it unique
+ m_sDescription += ",uniqueValue=" ;
+ m_sDescription += OUString::number(
+ sal::static_int_cast< sal_Int64 >(
+ reinterpret_cast< sal_IntPtr >(&m_socket)) );
+ }
+
+ void SocketConnection::completeConnectionString()
+ {
+ OUStringBuffer buf( 256 );
+ buf.append( ",peerPort=" );
+ buf.append( m_socket.getPeerPort() );
+ buf.append( ",peerHost=" );
+ buf.append( m_socket.getPeerHost( ) );
+
+ buf.append( ",localPort=" );
+ buf.append( m_socket.getLocalPort() );
+ buf.append( ",localHost=" );
+ buf.append( m_socket.getLocalHost() );
+
+ m_sDescription += buf;
+ }
+
+ sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
+ {
+ if( ! m_nStatus )
+ {
+ notifyListeners(this, &_started, callStarted);
+
+ if( aReadBytes.getLength() != nBytesToRead )
+ {
+ aReadBytes.realloc( nBytesToRead );
+ }
+
+ sal_Int32 i = m_socket.read(
+ aReadBytes.getArray(), aReadBytes.getLength());
+
+ if(i != nBytesToRead)
+ {
+ OUString message = "acc_socket.cxx:SocketConnection::read: error - " +
+ m_socket.getErrorAsString();
+
+ IOException ioException(message, static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+
+ return i;
+ }
+ else
+ {
+ IOException ioException("acc_socket.cxx:SocketConnection::read: error - connection already closed", static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+
+ void SocketConnection::write( const Sequence < sal_Int8 > &seq )
+ {
+ if( ! m_nStatus )
+ {
+ if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
+ {
+ OUString message = "acc_socket.cxx:SocketConnection::write: error - " +
+ m_socket.getErrorAsString();
+
+ IOException ioException(message, static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+ else
+ {
+ IOException ioException("acc_socket.cxx:SocketConnection::write: error - connection already closed", static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+
+ void SocketConnection::flush( )
+ {
+
+ }
+
+ void SocketConnection::close()
+ {
+ // ensure close is called only once
+ if( 1 == osl_atomic_increment( (&m_nStatus) ) )
+ {
+ m_socket.shutdown();
+ notifyListeners(this, &_closed, callClosed);
+ }
+ }
+
+ OUString SocketConnection::getDescription()
+ {
+ return m_sDescription;
+ }
+
+
+ // XConnectionBroadcaster
+ void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener)
+ {
+ MutexGuard guard(_mutex);
+
+ _listeners.insert(aListener);
+ }
+
+ void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener)
+ {
+ MutexGuard guard(_mutex);
+
+ _listeners.erase(aListener);
+ }
+
+ SocketAcceptor::SocketAcceptor( const OUString &sSocketName,
+ sal_uInt16 nPort,
+ bool bTcpNoDelay,
+ const OUString &sConnectionDescription) :
+ m_sSocketName( sSocketName ),
+ m_sConnectionDescription( sConnectionDescription ),
+ m_nPort( nPort ),
+ m_bTcpNoDelay( bTcpNoDelay ),
+ m_bClosed( false )
+ {
+ }
+
+
+ void SocketAcceptor::init()
+ {
+ if( ! m_addr.setPort( m_nPort ) )
+ {
+ throw ConnectionSetupException(
+ "acc_socket.cxx:SocketAcceptor::init - error - invalid tcp/ip port " +
+ OUString::number( m_nPort ));
+ }
+ if( ! m_addr.setHostname( m_sSocketName.pData ) )
+ {
+ throw ConnectionSetupException(
+ "acc_socket.cxx:SocketAcceptor::init - error - invalid host " + m_sSocketName );
+ }
+ m_socket.setOption( osl_Socket_OptionReuseAddr, 1);
+
+ if(! m_socket.bind(m_addr) )
+ {
+ throw ConnectionSetupException(
+ "acc_socket.cxx:SocketAcceptor::init - error - couldn't bind on " +
+ m_sSocketName + ":" + OUString::number(m_nPort));
+ }
+
+ if(! m_socket.listen() )
+ {
+ throw ConnectionSetupException(
+ "acc_socket.cxx:SocketAcceptor::init - error - can't listen on " +
+ m_sSocketName + ":" + OUString::number(m_nPort) );
+ }
+ }
+
+ Reference< XConnection > SocketAcceptor::accept( )
+ {
+ std::unique_ptr<SocketConnection> pConn(new SocketConnection( m_sConnectionDescription ));
+
+ if( m_socket.acceptConnection( pConn->m_socket )!= osl_Socket_Ok )
+ {
+ // stopAccepting was called
+ return Reference < XConnection > ();
+ }
+ if( m_bClosed )
+ {
+ return Reference < XConnection > ();
+ }
+
+ pConn->completeConnectionString();
+ ::osl::SocketAddr remoteAddr;
+ pConn->m_socket.getPeerAddr(remoteAddr);
+ OUString remoteHostname = remoteAddr.getHostname();
+ // we enable tcpNoDelay for loopback connections because
+ // it can make a significant speed difference on linux boxes.
+ if( m_bTcpNoDelay || remoteHostname == "localhost" ||
+ remoteHostname.startsWith("127.0.0.") )
+ {
+ sal_Int32 nTcpNoDelay = sal_Int32(true);
+ pConn->m_socket.setOption( osl_Socket_OptionTcpNoDelay , &nTcpNoDelay,
+ sizeof( nTcpNoDelay ) , osl_Socket_LevelTcp );
+ }
+
+ return Reference < XConnection > ( static_cast<XConnection *>(pConn.release()) );
+ }
+
+ void SocketAcceptor::stopAccepting()
+ {
+ m_bClosed = true;
+ m_socket.close();
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/acceptor/acceptor.cxx b/io/source/acceptor/acceptor.cxx
new file mode 100644
index 000000000..d1f2bb54b
--- /dev/null
+++ b/io/source/acceptor/acceptor.cxx
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/mutex.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/unourl.hxx>
+#include <rtl/malformeduriexception.hxx>
+
+#include <com/sun/star/connection/AlreadyAcceptingException.hpp>
+#include <com/sun/star/connection/ConnectionSetupException.hpp>
+#include <com/sun/star/connection/XAcceptor.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <services.hxx>
+#include "acceptor.hxx"
+#include <memory>
+
+#define IMPLEMENTATION_NAME "com.sun.star.comp.io.Acceptor"
+#define SERVICE_NAME "com.sun.star.connection.Acceptor"
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::connection;
+
+namespace io_acceptor
+{
+ namespace {
+
+ class OAcceptor : public WeakImplHelper< XAcceptor, XServiceInfo >
+ {
+ public:
+ explicit OAcceptor(const Reference< XComponentContext > & xCtx);
+ virtual ~OAcceptor() override;
+ public:
+ // Methods
+ virtual Reference< XConnection > SAL_CALL accept( const OUString& sConnectionDescription ) override;
+ virtual void SAL_CALL stopAccepting( ) override;
+
+ public: // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ private:
+ std::unique_ptr<PipeAcceptor> m_pPipe;
+ std::unique_ptr<SocketAcceptor> m_pSocket;
+ Mutex m_mutex;
+ OUString m_sLastDescription;
+ bool m_bInAccept;
+
+ Reference< XMultiComponentFactory > _xSMgr;
+ Reference< XComponentContext > _xCtx;
+ Reference<XAcceptor> _xAcceptor;
+ };
+
+ }
+
+ OAcceptor::OAcceptor( const Reference< XComponentContext > & xCtx )
+ : m_bInAccept( false )
+ , _xSMgr( xCtx->getServiceManager() )
+ , _xCtx( xCtx )
+ {}
+
+ OAcceptor::~OAcceptor()
+ {
+ m_pPipe.reset();
+ }
+
+ namespace {
+
+ struct BeingInAccept
+ {
+ /// @throws AlreadyAcceptingException
+ BeingInAccept( bool *pFlag,const OUString & sConnectionDescription )
+ : m_pFlag( pFlag )
+ {
+ if( *m_pFlag )
+ throw AlreadyAcceptingException( "AlreadyAcceptingException :" + sConnectionDescription );
+ *m_pFlag = true;
+ }
+ ~BeingInAccept()
+ {
+ *m_pFlag = false;
+ }
+ bool *m_pFlag;
+ };
+
+ }
+
+ Reference< XConnection > OAcceptor::accept( const OUString &sConnectionDescription )
+ {
+ // if there is a thread already accepting in this object, throw an exception.
+ struct BeingInAccept guard( &m_bInAccept, sConnectionDescription );
+
+ Reference< XConnection > r;
+ if( !m_sLastDescription.isEmpty() &&
+ m_sLastDescription != sConnectionDescription )
+ {
+ // instantiate another acceptor for different ports
+ OUString sMessage = "acceptor::accept called multiple times with different connection strings\n";
+ throw ConnectionSetupException( sMessage );
+ }
+
+ if( m_sLastDescription.isEmpty() )
+ {
+ // setup the acceptor
+ try
+ {
+ cppu::UnoUrlDescriptor aDesc(sConnectionDescription);
+ if ( aDesc.getName() == "pipe" )
+ {
+ OUString aName(
+ aDesc.getParameter(
+ "name"));
+
+ m_pPipe.reset(new PipeAcceptor(aName, sConnectionDescription));
+
+ try
+ {
+ m_pPipe->init();
+ }
+ catch( ... )
+ {
+ {
+ MutexGuard g( m_mutex );
+ m_pPipe.reset();
+ }
+ throw;
+ }
+ }
+ else if ( aDesc.getName() == "socket" )
+ {
+ OUString aHost;
+ if (aDesc.hasParameter(
+ "host"))
+ aHost = aDesc.getParameter(
+ "host");
+ else
+ aHost = "localhost";
+ sal_uInt16 nPort = static_cast< sal_uInt16 >(
+ aDesc.getParameter(
+ "port").
+ toInt32());
+ bool bTcpNoDelay
+ = aDesc.getParameter(
+ "tcpnodelay").toInt32() != 0;
+
+ m_pSocket.reset(new SocketAcceptor(
+ aHost, nPort, bTcpNoDelay, sConnectionDescription));
+
+ try
+ {
+ m_pSocket->init();
+ }
+ catch( ... )
+ {
+ {
+ MutexGuard g( m_mutex );
+ m_pSocket.reset();
+ }
+ throw;
+ }
+ }
+ else
+ {
+ OUString delegatee = "com.sun.star.connection.Acceptor." + aDesc.getName();
+ _xAcceptor.set(_xSMgr->createInstanceWithContext(delegatee, _xCtx), UNO_QUERY);
+
+ if(!_xAcceptor.is())
+ throw ConnectionSetupException("Acceptor: unknown delegatee " + delegatee);
+ }
+ }
+ catch (const rtl::MalformedUriException & rEx)
+ {
+ throw IllegalArgumentException(
+ rEx.getMessage(),
+ Reference< XInterface > (),
+ 0 );
+ }
+ m_sLastDescription = sConnectionDescription;
+ }
+
+ if( m_pPipe )
+ {
+ r = m_pPipe->accept();
+ }
+ else if( m_pSocket )
+ {
+ r = m_pSocket->accept();
+ }
+ else
+ {
+ r = _xAcceptor->accept(sConnectionDescription);
+ }
+
+ return r;
+ }
+
+ void SAL_CALL OAcceptor::stopAccepting( )
+ {
+ MutexGuard guard( m_mutex );
+
+ if( m_pPipe )
+ {
+ m_pPipe->stopAccepting();
+ }
+ else if ( m_pSocket )
+ {
+ m_pSocket->stopAccepting();
+ }
+ else if( _xAcceptor.is() )
+ {
+ _xAcceptor->stopAccepting();
+ }
+
+ }
+
+ OUString acceptor_getImplementationName()
+ {
+ return IMPLEMENTATION_NAME;
+ }
+
+ Reference< XInterface > acceptor_CreateInstance( const Reference< XComponentContext > & xCtx)
+ {
+ return Reference < XInterface >( static_cast<OWeakObject *>(new OAcceptor(xCtx)) );
+ }
+
+ Sequence< OUString > acceptor_getSupportedServiceNames()
+ {
+ Sequence< OUString > seqNames { SERVICE_NAME };
+ return seqNames;
+ }
+
+ OUString OAcceptor::getImplementationName()
+ {
+ return acceptor_getImplementationName();
+ }
+
+ sal_Bool OAcceptor::supportsService(const OUString& ServiceName)
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ Sequence< OUString > OAcceptor::getSupportedServiceNames()
+ {
+ return acceptor_getSupportedServiceNames();
+ }
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/acceptor/acceptor.hxx b/io/source/acceptor/acceptor.hxx
new file mode 100644
index 000000000..a88f3728f
--- /dev/null
+++ b/io/source/acceptor/acceptor.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_IO_SOURCE_ACCEPTOR_ACCEPTOR_HXX
+#define INCLUDED_IO_SOURCE_ACCEPTOR_ACCEPTOR_HXX
+
+#include <osl/pipe.hxx>
+#include <osl/socket.hxx>
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com::sun::star::connection { class XConnection; }
+
+namespace io_acceptor {
+
+ class PipeAcceptor
+ {
+ public:
+ PipeAcceptor( const OUString &sPipeName , const OUString &sConnectionDescription );
+
+ void init();
+ css::uno::Reference < css::connection::XConnection > accept( );
+
+ void stopAccepting();
+
+ ::osl::Mutex m_mutex;
+ ::osl::Pipe m_pipe;
+ OUString m_sPipeName;
+ OUString m_sConnectionDescription;
+ bool m_bClosed;
+ };
+
+ class SocketAcceptor
+ {
+ public:
+ SocketAcceptor( const OUString & sSocketName ,
+ sal_uInt16 nPort,
+ bool bTcpNoDelay,
+ const OUString &sConnectionDescription );
+
+ void init();
+ css::uno::Reference < css::connection::XConnection > accept();
+
+ void stopAccepting();
+
+ ::osl::SocketAddr m_addr;
+ ::osl::AcceptorSocket m_socket;
+ OUString m_sSocketName;
+ OUString m_sConnectionDescription;
+ sal_uInt16 m_nPort;
+ bool m_bTcpNoDelay;
+ bool m_bClosed;
+ };
+
+}
+
+#endif // INCLUDED_IO_SOURCE_ACCEPTOR_ACCEPTOR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/connector/connector.cxx b/io/source/connector/connector.cxx
new file mode 100644
index 000000000..0f4792f3a
--- /dev/null
+++ b/io/source/connector/connector.cxx
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/security.hxx>
+#include <sal/log.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/unourl.hxx>
+#include <rtl/malformeduriexception.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/connection/ConnectionSetupException.hpp>
+#include <com/sun/star/connection/NoConnectException.hpp>
+#include <com/sun/star/connection/XConnector.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <services.hxx>
+#include "connector.hxx"
+
+#define IMPLEMENTATION_NAME "com.sun.star.comp.io.Connector"
+#define SERVICE_NAME "com.sun.star.connection.Connector"
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::connection;
+
+namespace stoc_connector
+{
+ namespace {
+
+ class OConnector : public WeakImplHelper< XConnector, XServiceInfo >
+ {
+ Reference< XMultiComponentFactory > _xSMgr;
+ Reference< XComponentContext > _xCtx;
+ public:
+ explicit OConnector(const Reference< XComponentContext > &xCtx);
+
+ // Methods
+ virtual Reference< XConnection > SAL_CALL connect(
+ const OUString& sConnectionDescription ) override;
+
+ public: // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ };
+
+ }
+
+ OConnector::OConnector(const Reference< XComponentContext > &xCtx)
+ : _xSMgr( xCtx->getServiceManager() )
+ , _xCtx( xCtx )
+ {}
+
+ Reference< XConnection > SAL_CALL OConnector::connect( const OUString& sConnectionDescription )
+ {
+ // split string into tokens
+ try
+ {
+ cppu::UnoUrlDescriptor aDesc(sConnectionDescription);
+
+ Reference< XConnection > r;
+ if ( aDesc.getName() == "pipe" )
+ {
+ OUString aName(aDesc.getParameter("name"));
+
+ std::unique_ptr<PipeConnection> pConn(new PipeConnection( sConnectionDescription ));
+
+ if( pConn->m_pipe.create( aName.pData, osl_Pipe_OPEN, osl::Security() ) )
+ {
+ r.set( static_cast<XConnection *>(pConn.release()) );
+ }
+ else
+ {
+ OUString const sMessage(
+ "Connector : couldn't connect to pipe " + aName + "("
+ + OUString::number(pConn->m_pipe.getError()) + ")");
+ SAL_WARN("io.connector", sMessage);
+ throw NoConnectException( sMessage );
+ }
+ }
+ else if ( aDesc.getName() == "socket" )
+ {
+ OUString aHost;
+ if (aDesc.hasParameter("host"))
+ aHost = aDesc.getParameter("host");
+ else
+ aHost = "localhost";
+ sal_uInt16 nPort = static_cast< sal_uInt16 >(
+ aDesc.getParameter("port").
+ toInt32());
+ bool bTcpNoDelay
+ = aDesc.getParameter("tcpnodelay").toInt32() != 0;
+
+ std::unique_ptr<SocketConnection> pConn(new SocketConnection( sConnectionDescription));
+
+ SocketAddr AddrTarget( aHost.pData, nPort );
+ if(pConn->m_socket.connect(AddrTarget) != osl_Socket_Ok)
+ {
+ OUString sMessage("Connector : couldn't connect to socket (");
+ OUString sError = pConn->m_socket.getErrorAsString();
+ sMessage += sError + ")";
+ throw NoConnectException( sMessage );
+ }
+ // we enable tcpNoDelay for loopback connections because
+ // it can make a significant speed difference on linux boxes.
+ if( bTcpNoDelay || aHost == "localhost" || aHost.startsWith("127.0.0.") )
+ {
+ sal_Int32 nTcpNoDelay = sal_Int32(true);
+ pConn->m_socket.setOption( osl_Socket_OptionTcpNoDelay , &nTcpNoDelay,
+ sizeof( nTcpNoDelay ) , osl_Socket_LevelTcp );
+ }
+ pConn->completeConnectionString();
+ r.set( static_cast<XConnection *>(pConn.release()) );
+ }
+ else
+ {
+ OUString delegatee= "com.sun.star.connection.Connector." + aDesc.getName();
+
+ Reference<XConnector> xConnector(
+ _xSMgr->createInstanceWithContext(delegatee, _xCtx), UNO_QUERY );
+
+ if(!xConnector.is())
+ throw ConnectionSetupException("Connector: unknown delegatee " + delegatee);
+
+ sal_Int32 index = sConnectionDescription.indexOf(',');
+
+ r = xConnector->connect(sConnectionDescription.copy(index + 1).trim());
+ }
+ return r;
+ }
+ catch (const rtl::MalformedUriException & rEx)
+ {
+ throw ConnectionSetupException(rEx.getMessage());
+ }
+ }
+
+ Sequence< OUString > connector_getSupportedServiceNames()
+ {
+ Sequence< OUString > seqNames { SERVICE_NAME };
+ return seqNames;
+ }
+
+ OUString connector_getImplementationName()
+ {
+ return IMPLEMENTATION_NAME;
+ }
+
+ OUString OConnector::getImplementationName()
+ {
+ return connector_getImplementationName();
+ }
+
+ sal_Bool OConnector::supportsService(const OUString& ServiceName)
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ Sequence< OUString > OConnector::getSupportedServiceNames()
+ {
+ return connector_getSupportedServiceNames();
+ }
+
+ Reference< XInterface > connector_CreateInstance( const Reference< XComponentContext > & xCtx)
+ {
+ return Reference < XInterface >( static_cast<OWeakObject *>(new OConnector(xCtx)) );
+ }
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/connector/connector.hxx b/io/source/connector/connector.hxx
new file mode 100644
index 000000000..9aad55a45
--- /dev/null
+++ b/io/source/connector/connector.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_IO_SOURCE_CONNECTOR_CONNECTOR_HXX
+#define INCLUDED_IO_SOURCE_CONNECTOR_CONNECTOR_HXX
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/connection/XConnectionBroadcaster.hpp>
+
+#include <unordered_set>
+#include <osl/socket.hxx>
+#include <osl/pipe.hxx>
+
+namespace stoc_connector
+{
+ typedef std::unordered_set< css::uno::Reference< css::io::XStreamListener> >
+ XStreamListener_hash_set;
+
+ class PipeConnection :
+ public ::cppu::WeakImplHelper< css::connection::XConnection >
+
+ {
+ public:
+ explicit PipeConnection( const OUString &sConnectionDescription );
+ virtual ~PipeConnection() override;
+
+ virtual sal_Int32 SAL_CALL read( css::uno::Sequence< sal_Int8 >& aReadBytes,
+ sal_Int32 nBytesToRead ) override;
+ virtual void SAL_CALL write( const css::uno::Sequence< sal_Int8 >& aData ) override;
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL close( ) override;
+ virtual OUString SAL_CALL getDescription( ) override;
+ public:
+ ::osl::StreamPipe m_pipe;
+ oslInterlockedCount m_nStatus;
+ OUString m_sDescription;
+ };
+
+ class SocketConnection :
+ public ::cppu::WeakImplHelper< css::connection::XConnection, css::connection::XConnectionBroadcaster >
+
+ {
+ public:
+ explicit SocketConnection( const OUString & sConnectionDescription );
+ virtual ~SocketConnection() override;
+
+ virtual sal_Int32 SAL_CALL read( css::uno::Sequence< sal_Int8 >& aReadBytes,
+ sal_Int32 nBytesToRead ) override;
+ virtual void SAL_CALL write( const css::uno::Sequence< sal_Int8 >& aData ) override;
+ virtual void SAL_CALL flush( ) override;
+ virtual void SAL_CALL close( ) override;
+ virtual OUString SAL_CALL getDescription( ) override;
+
+
+ // XConnectionBroadcaster
+ virtual void SAL_CALL addStreamListener(const css::uno::Reference< css::io::XStreamListener>& aListener) override;
+ virtual void SAL_CALL removeStreamListener(const css::uno::Reference< css::io::XStreamListener>& aListener) override;
+
+ public:
+ void completeConnectionString();
+
+ ::osl::ConnectorSocket m_socket;
+ oslInterlockedCount m_nStatus;
+ OUString m_sDescription;
+
+ ::osl::Mutex _mutex;
+ bool _started;
+ bool _closed;
+ bool _error;
+
+ XStreamListener_hash_set _listeners;
+ };
+}
+
+#endif // INCLUDED_IO_SOURCE_CONNECTOR_CONNECTOR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/connector/ctr_pipe.cxx b/io/source/connector/ctr_pipe.cxx
new file mode 100644
index 000000000..8d66dea7b
--- /dev/null
+++ b/io/source/connector/ctr_pipe.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/io/IOException.hpp>
+
+#include "connector.hxx"
+#include <osl/pipe.hxx>
+
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::connection;
+
+
+namespace stoc_connector {
+
+ PipeConnection::PipeConnection( const OUString & sConnectionDescription ) :
+ m_nStatus( 0 ),
+ m_sDescription( sConnectionDescription )
+ {
+ // make it unique
+ m_sDescription += ",uniqueValue=";
+ m_sDescription += OUString::number(
+ sal::static_int_cast< sal_Int64 >(
+ reinterpret_cast< sal_IntPtr >(&m_pipe)) );
+ }
+
+ PipeConnection::~PipeConnection()
+ {
+ }
+
+ sal_Int32 PipeConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
+ {
+ if( m_nStatus )
+ {
+ throw IOException();
+ }
+ if( aReadBytes.getLength() != nBytesToRead )
+ {
+ aReadBytes.realloc( nBytesToRead );
+ }
+ return m_pipe.read( aReadBytes.getArray() , aReadBytes.getLength() );
+
+ }
+
+ void PipeConnection::write( const Sequence < sal_Int8 > &seq )
+ {
+ if( m_nStatus )
+ {
+ throw IOException();
+ }
+ if( m_pipe.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
+ {
+ throw IOException();
+ }
+ }
+
+ void PipeConnection::flush( )
+ {
+
+ }
+
+ void PipeConnection::close()
+ {
+ // ensure that close is called only once
+ if(1 == osl_atomic_increment( (&m_nStatus) ) )
+ {
+ m_pipe.close();
+ }
+ }
+
+ OUString PipeConnection::getDescription()
+ {
+ return m_sDescription;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/connector/ctr_socket.cxx b/io/source/connector/ctr_socket.cxx
new file mode 100644
index 000000000..164cd4f6f
--- /dev/null
+++ b/io/source/connector/ctr_socket.cxx
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "connector.hxx"
+#include <com/sun/star/io/IOException.hpp>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::connection;
+
+
+namespace stoc_connector {
+ template<class T>
+ static void notifyListeners(SocketConnection * pCon, bool * notified, T t)
+ {
+ XStreamListener_hash_set listeners;
+
+ {
+ ::osl::MutexGuard guard(pCon->_mutex);
+ if(!*notified)
+ {
+ *notified = true;
+ listeners = pCon->_listeners;
+ }
+ }
+
+ for(auto& listener : listeners)
+ t(listener);
+ }
+
+
+ static void callStarted(const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->started();
+ }
+
+ namespace {
+
+ struct callError {
+ const Any & any;
+
+ explicit callError(const Any & any);
+
+ void operator () (const Reference<XStreamListener>& xStreamListener);
+ };
+
+ }
+
+ callError::callError(const Any & aAny)
+ : any(aAny)
+ {
+ }
+
+ void callError::operator () (const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->error(any);
+ }
+
+ static void callClosed(const Reference<XStreamListener>& xStreamListener)
+ {
+ xStreamListener->closed();
+ }
+
+
+ SocketConnection::SocketConnection( const OUString &sConnectionDescription ) :
+ m_nStatus( 0 ),
+ m_sDescription( sConnectionDescription ),
+ _started(false),
+ _closed(false),
+ _error(false)
+ {
+ // make it unique
+ m_sDescription += ",uniqueValue=";
+ m_sDescription += OUString::number(
+ sal::static_int_cast< sal_Int64 >(
+ reinterpret_cast< sal_IntPtr >(&m_socket)) );
+ }
+
+ SocketConnection::~SocketConnection()
+ {
+ }
+
+ void SocketConnection::completeConnectionString()
+ {
+ sal_Int32 nPort;
+
+ nPort = m_socket.getPeerPort();
+
+ OUStringBuffer buf( 256 );
+ buf.append( ",peerPort=" );
+ buf.append( nPort );
+ buf.append( ",peerHost=" );
+ buf.append( m_socket.getPeerHost() );
+
+ buf.append( ",localPort=" );
+ buf.append( nPort );
+ buf.append( ",localHost=" );
+ buf.append( m_socket.getLocalHost( ) );
+
+ m_sDescription += buf;
+ }
+
+ sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
+ {
+ if( ! m_nStatus )
+ {
+ notifyListeners(this, &_started, callStarted);
+
+ if( aReadBytes.getLength() != nBytesToRead )
+ {
+ aReadBytes.realloc( nBytesToRead );
+ }
+ sal_Int32 i = m_socket.read( aReadBytes.getArray() , aReadBytes.getLength() );
+
+ if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None)
+ {
+ OUString message = "ctr_socket.cxx:SocketConnection::read: error - " +
+ m_socket.getErrorAsString();
+
+ IOException ioException(message, static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+
+ return i;
+ }
+ else
+ {
+ IOException ioException("ctr_socket.cxx:SocketConnection::read: error - connection already closed", static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+
+ void SocketConnection::write( const Sequence < sal_Int8 > &seq )
+ {
+ if( ! m_nStatus )
+ {
+ if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
+ {
+ OUString message = "ctr_socket.cxx:SocketConnection::write: error - " +
+ m_socket.getErrorAsString();
+
+ IOException ioException(message, static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+ else
+ {
+ IOException ioException("ctr_socket.cxx:SocketConnection::write: error - connection already closed", static_cast<XConnection *>(this));
+
+ Any any;
+ any <<= ioException;
+
+ notifyListeners(this, &_error, callError(any));
+
+ throw ioException;
+ }
+ }
+
+ void SocketConnection::flush( )
+ {
+
+ }
+
+ void SocketConnection::close()
+ {
+ // ensure that close is called only once
+ if( 1 == osl_atomic_increment( (&m_nStatus) ) )
+ {
+ m_socket.shutdown();
+ notifyListeners(this, &_closed, callClosed);
+ }
+ }
+
+ OUString SocketConnection::getDescription()
+ {
+ return m_sDescription;
+ }
+
+
+ // XConnectionBroadcaster
+ void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener)
+ {
+ MutexGuard guard(_mutex);
+
+ _listeners.insert(aListener);
+ }
+
+ void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener)
+ {
+ MutexGuard guard(_mutex);
+
+ _listeners.erase(aListener);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/io.component b/io/source/io.component
new file mode 100644
index 000000000..12f954fc9
--- /dev/null
+++ b/io/source/io.component
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ prefix="io" xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.io.Pump">
+ <service name="com.sun.star.io.Pump"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.DataInputStream">
+ <service name="com.sun.star.io.DataInputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.DataOutputStream">
+ <service name="com.sun.star.io.DataOutputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.MarkableInputStream">
+ <service name="com.sun.star.io.MarkableInputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.MarkableOutputStream">
+ <service name="com.sun.star.io.MarkableOutputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.ObjectInputStream">
+ <service name="com.sun.star.io.ObjectInputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.ObjectOutputStream">
+ <service name="com.sun.star.io.ObjectOutputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.stm.Pipe">
+ <service name="com.sun.star.io.Pipe"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.Acceptor">
+ <service name="com.sun.star.connection.Acceptor"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.Connector">
+ <service name="com.sun.star.connection.Connector"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.TextInputStream">
+ <service name="com.sun.star.io.TextInputStream"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.io.TextOutputStream">
+ <service name="com.sun.star.io.TextOutputStream"/>
+ </implementation>
+</component>
diff --git a/io/source/services.cxx b/io/source/services.cxx
new file mode 100644
index 000000000..c0da0ee8b
--- /dev/null
+++ b/io/source/services.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+
+#include "services.hxx"
+
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+
+static const struct ImplementationEntry g_entries[] =
+{
+ {
+ io_acceptor::acceptor_CreateInstance, io_acceptor::acceptor_getImplementationName ,
+ io_acceptor::acceptor_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {
+ stoc_connector::connector_CreateInstance, stoc_connector::connector_getImplementationName ,
+ stoc_connector::connector_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {
+ io_stm::OPipeImpl_CreateInstance, io_stm::OPipeImpl_getImplementationName ,
+ io_stm::OPipeImpl_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {
+ io_stm::OPumpImpl_CreateInstance, io_stm::OPumpImpl_getImplementationName ,
+ io_stm::OPumpImpl_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {
+ io_stm::ODataInputStream_CreateInstance, io_stm::ODataInputStream_getImplementationName,
+ io_stm::ODataInputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_stm::ODataOutputStream_CreateInstance, io_stm::ODataOutputStream_getImplementationName,
+ io_stm::ODataOutputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_stm::OObjectInputStream_CreateInstance, io_stm::OObjectInputStream_getImplementationName,
+ io_stm::OObjectInputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_stm::OObjectOutputStream_CreateInstance, io_stm::OObjectOutputStream_getImplementationName,
+ io_stm::OObjectOutputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_stm::OMarkableInputStream_CreateInstance, io_stm::OMarkableInputStream_getImplementationName,
+ io_stm::OMarkableInputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_stm::OMarkableOutputStream_CreateInstance, io_stm::OMarkableOutputStream_getImplementationName,
+ io_stm::OMarkableOutputStream_getSupportedServiceNames, createSingleComponentFactory,
+ nullptr, 0
+ },
+ {
+ io_TextInputStream::TextInputStream_CreateInstance, io_TextInputStream::TextInputStream_getImplementationName ,
+ io_TextInputStream::TextInputStream_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {
+ io_TextOutputStream::TextOutputStream_CreateInstance, io_TextOutputStream::TextOutputStream_getImplementationName ,
+ io_TextOutputStream::TextOutputStream_getSupportedServiceNames, createSingleComponentFactory ,
+ nullptr, 0
+ },
+ {nullptr, nullptr, nullptr, nullptr, nullptr, 0}
+};
+
+extern "C" SAL_DLLPUBLIC_EXPORT void * io_component_getFactory(
+ const char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/services.hxx b/io/source/services.hxx
new file mode 100644
index 000000000..119f6e29f
--- /dev/null
+++ b/io/source/services.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_IO_SOURCE_SERVICES_HXX
+#define INCLUDED_IO_SOURCE_SERVICES_HXX
+
+#include <sal/config.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star::uno;
+
+namespace io_acceptor{
+ Reference< XInterface > acceptor_CreateInstance( const Reference< XComponentContext > & xCtx);
+ OUString acceptor_getImplementationName();
+ Sequence< OUString > acceptor_getSupportedServiceNames();
+}
+
+namespace stoc_connector {
+ Reference< XInterface > connector_CreateInstance( const Reference< XComponentContext > & xCtx);
+ OUString connector_getImplementationName();
+ Sequence< OUString > connector_getSupportedServiceNames();
+}
+
+namespace io_TextInputStream {
+ Reference< XInterface > TextInputStream_CreateInstance(SAL_UNUSED_PARAMETER const Reference< XComponentContext > &);
+ OUString TextInputStream_getImplementationName();
+ Sequence< OUString > TextInputStream_getSupportedServiceNames();
+}
+
+namespace io_TextOutputStream {
+ Reference< XInterface > TextOutputStream_CreateInstance(SAL_UNUSED_PARAMETER const Reference< XComponentContext > &);
+ OUString TextOutputStream_getImplementationName();
+ Sequence< OUString > TextOutputStream_getSupportedServiceNames();
+}
+
+namespace io_stm {
+ /// @throws Exception
+ Reference< XInterface > OPipeImpl_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OPipeImpl_getImplementationName();
+ Sequence<OUString> OPipeImpl_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > ODataInputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString ODataInputStream_getImplementationName();
+ Sequence<OUString> ODataInputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > ODataOutputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString ODataOutputStream_getImplementationName();
+ Sequence<OUString> ODataOutputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > OMarkableOutputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OMarkableOutputStream_getImplementationName();
+ Sequence<OUString> OMarkableOutputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > OMarkableInputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OMarkableInputStream_getImplementationName() ;
+ Sequence<OUString> OMarkableInputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > OObjectOutputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OObjectOutputStream_getImplementationName();
+ Sequence<OUString> OObjectOutputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > OObjectInputStream_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OObjectInputStream_getImplementationName() ;
+ Sequence<OUString> OObjectInputStream_getSupportedServiceNames();
+
+ /// @throws Exception
+ Reference< XInterface > OPumpImpl_CreateInstance( const Reference< XComponentContext > & rSMgr );
+ OUString OPumpImpl_getImplementationName();
+ Sequence<OUString> OPumpImpl_getSupportedServiceNames();
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/odata.cxx b/io/source/stm/odata.cxx
new file mode 100644
index 000000000..3e802b2d3
--- /dev/null
+++ b/io/source/stm/odata.cxx
@@ -0,0 +1,1284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string.h>
+#include <unordered_map>
+#include <vector>
+
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/endian.h>
+
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/XObjectInputStream.hpp>
+#include <com/sun/star/io/XObjectOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/io/UnexpectedEOFException.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::std;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+#include <services.hxx>
+
+namespace io_stm {
+
+namespace {
+
+class ODataInputStream :
+ public WeakImplHelper <
+ XDataInputStream,
+ XActiveDataSink,
+ XConnectable,
+ XServiceInfo
+ >
+{
+public:
+ ODataInputStream( )
+ : m_bValidStream( false )
+ {
+ }
+
+public: // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override;
+ virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override;
+ virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override;
+ virtual sal_Int32 SAL_CALL available() override;
+ virtual void SAL_CALL closeInput() override;
+
+public: // XDataInputStream
+ virtual sal_Int8 SAL_CALL readBoolean() override;
+ virtual sal_Int8 SAL_CALL readByte() override;
+ virtual sal_Unicode SAL_CALL readChar() override;
+ virtual sal_Int16 SAL_CALL readShort() override;
+ virtual sal_Int32 SAL_CALL readLong() override;
+ virtual sal_Int64 SAL_CALL readHyper() override;
+ virtual float SAL_CALL readFloat() override;
+ virtual double SAL_CALL readDouble() override;
+ virtual OUString SAL_CALL readUTF() override;
+
+
+public: // XActiveDataSink
+ virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream) override;
+ virtual Reference< XInputStream > SAL_CALL getInputStream() override;
+
+public: // XConnectable
+ virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
+ virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
+ virtual Reference < XConnectable > SAL_CALL getSuccessor() override ;
+
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+protected:
+
+ Reference < XConnectable > m_pred;
+ Reference < XConnectable > m_succ;
+ Reference < XInputStream > m_input;
+ bool m_bValidStream;
+};
+
+}
+
+// XInputStream
+sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+{
+ if( !m_bValidStream )
+ {
+ throw NotConnectedException( );
+ }
+ sal_Int32 nRead = m_input->readBytes( aData , nBytesToRead );
+ return nRead;
+}
+
+sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
+{
+ if( !m_bValidStream )
+ throw NotConnectedException( );
+ sal_Int32 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
+ return nRead;
+}
+void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
+{
+ if( !m_bValidStream )
+ throw NotConnectedException( );
+ m_input->skipBytes( nBytesToSkip );
+}
+
+
+sal_Int32 ODataInputStream::available()
+{
+ if( !m_bValidStream )
+ throw NotConnectedException( );
+ sal_Int32 nAvail = m_input->available( );
+ return nAvail;
+}
+
+void ODataInputStream::closeInput()
+{
+ if( !m_bValidStream )
+ throw NotConnectedException( );
+ m_input->closeInput( );
+ setInputStream( Reference< XInputStream > () );
+ setPredecessor( Reference < XConnectable >() );
+ setSuccessor( Reference < XConnectable >() );
+ m_bValidStream = false;
+}
+
+
+//== XDataInputStream ===========================================
+
+// XDataInputStream
+sal_Int8 ODataInputStream::readBoolean()
+{
+ return readByte();
+}
+
+sal_Int8 ODataInputStream::readByte()
+{
+ Sequence<sal_Int8> aTmp(1);
+ if( 1 != readBytes( aTmp, 1 ) )
+ {
+ throw UnexpectedEOFException();
+ }
+ return aTmp.getConstArray()[0];
+}
+
+sal_Unicode ODataInputStream::readChar()
+{
+ Sequence<sal_Int8> aTmp(2);
+ if( 2 != readBytes( aTmp, 2 ) )
+ {
+ throw UnexpectedEOFException();
+ }
+
+ const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
+ return (static_cast<sal_Unicode>(pBytes[0]) << 8) + pBytes[1];
+}
+
+sal_Int16 ODataInputStream::readShort()
+{
+ Sequence<sal_Int8> aTmp(2);
+ if( 2 != readBytes( aTmp, 2 ) )
+ {
+ throw UnexpectedEOFException();
+ }
+
+ const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
+ return (static_cast<sal_Int16>(pBytes[0]) << 8) + pBytes[1];
+}
+
+
+sal_Int32 ODataInputStream::readLong()
+{
+ Sequence<sal_Int8> aTmp(4);
+ if( 4 != readBytes( aTmp, 4 ) )
+ {
+ throw UnexpectedEOFException( );
+ }
+
+ const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
+ return (static_cast<sal_Int32>(pBytes[0]) << 24) + (static_cast<sal_Int32>(pBytes[1]) << 16) + (static_cast<sal_Int32>(pBytes[2]) << 8) + pBytes[3];
+}
+
+
+sal_Int64 ODataInputStream::readHyper()
+{
+ Sequence<sal_Int8> aTmp(8);
+ if( 8 != readBytes( aTmp, 8 ) )
+ {
+ throw UnexpectedEOFException( );
+ }
+
+ const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
+ return
+ (static_cast<sal_Int64>(pBytes[0]) << 56) +
+ (static_cast<sal_Int64>(pBytes[1]) << 48) +
+ (static_cast<sal_Int64>(pBytes[2]) << 40) +
+ (static_cast<sal_Int64>(pBytes[3]) << 32) +
+ (static_cast<sal_Int64>(pBytes[4]) << 24) +
+ (static_cast<sal_Int64>(pBytes[5]) << 16) +
+ (static_cast<sal_Int64>(pBytes[6]) << 8) +
+ pBytes[7];
+}
+
+float ODataInputStream::readFloat()
+{
+ union { float f; sal_uInt32 n; } a;
+ a.n = readLong();
+ return a.f;
+}
+
+double ODataInputStream::readDouble()
+{
+ union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
+#if defined OSL_LITENDIAN
+ a.ad.n2 = readLong();
+ a.ad.n1 = readLong();
+#else
+ a.ad.n1 = readLong();
+ a.ad.n2 = readLong();
+#endif
+ return a.d;
+}
+
+OUString ODataInputStream::readUTF()
+{
+ sal_uInt16 nShortLen = static_cast<sal_uInt16>(readShort());
+ sal_Int32 nUTFLen;
+
+ if( (sal_uInt16(0xffff)) == nShortLen )
+ {
+ // is interpreted as a sign, that string is longer than 64k
+ // incompatible to older XDataInputStream-routines, when strings are exactly 64k
+ nUTFLen = readLong();
+ }
+ else
+ {
+ nUTFLen = static_cast<sal_Int32>(nShortLen);
+ }
+
+ Sequence<sal_Unicode> aBuffer( nUTFLen );
+ sal_Unicode * pStr = aBuffer.getArray();
+
+ sal_Int32 nCount = 0;
+ sal_Int32 nStrLen = 0;
+ while( nCount < nUTFLen )
+ {
+ sal_uInt8 c = static_cast<sal_uInt8>(readByte());
+ sal_uInt8 char2, char3;
+ switch( c >> 4 )
+ {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ // 0xxxxxxx
+ nCount++;
+ pStr[nStrLen++] = c;
+ break;
+
+ case 12: case 13:
+ // 110x xxxx 10xx xxxx
+ nCount += 2;
+ if( nCount > nUTFLen )
+ {
+ throw WrongFormatException( );
+ }
+
+ char2 = static_cast<sal_uInt8>(readByte());
+ if( (char2 & 0xC0) != 0x80 )
+ {
+ throw WrongFormatException( );
+ }
+
+ pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
+ break;
+
+ case 14:
+ // 1110 xxxx 10xx xxxx 10xx xxxx
+ nCount += 3;
+ if( nCount > nUTFLen )
+ {
+ throw WrongFormatException( );
+ }
+
+ char2 = static_cast<sal_uInt8>(readByte());
+ char3 = static_cast<sal_uInt8>(readByte());
+
+ if( ((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80) ) {
+ throw WrongFormatException( );
+ }
+ pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
+ (sal_Unicode(char2 & 0x3F) << 6) |
+ (char3 & 0x3F);
+ break;
+
+ default:
+ // 10xx xxxx, 1111 xxxx
+ throw WrongFormatException();
+ //throw new UTFDataFormatException();
+ }
+ }
+ return OUString( pStr, nStrLen );
+}
+
+
+// XActiveDataSource
+void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
+{
+
+ if( m_input != aStream ) {
+ m_input = aStream;
+
+ Reference < XConnectable > pred( m_input , UNO_QUERY );
+ setPredecessor( pred );
+ }
+
+ m_bValidStream = m_input.is();
+}
+
+Reference< XInputStream > ODataInputStream::getInputStream()
+{
+ return m_input;
+}
+
+
+// XDataSink
+void ODataInputStream::setSuccessor( const Reference < XConnectable > &r )
+{
+ /// if the references match, nothing needs to be done
+ if( m_succ != r ) {
+ /// store the reference for later use
+ m_succ = r;
+
+ if( m_succ.is() ) {
+ /// set this instance as the sink !
+ m_succ->setPredecessor( Reference< XConnectable > (
+ static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+
+Reference < XConnectable > ODataInputStream::getSuccessor()
+{
+ return m_succ;
+}
+
+
+// XDataSource
+void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
+{
+ if( r != m_pred ) {
+ m_pred = r;
+ if( m_pred.is() ) {
+ m_pred->setSuccessor( Reference< XConnectable > (
+ static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+Reference < XConnectable > ODataInputStream::getPredecessor()
+{
+ return m_pred;
+}
+
+// XServiceInfo
+OUString ODataInputStream::getImplementationName()
+{
+ return ODataInputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool ODataInputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > ODataInputStream::getSupportedServiceNames()
+{
+ return ODataInputStream_getSupportedServiceNames();
+}
+
+/***
+*
+* registration information
+*
+*
+****/
+
+Reference< XInterface > ODataInputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ ODataInputStream *p = new ODataInputStream;
+ return Reference< XInterface > ( static_cast<OWeakObject *>(p) );
+}
+
+OUString ODataInputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.DataInputStream";
+}
+
+Sequence<OUString> ODataInputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.DataInputStream" };
+ return aRet;
+}
+
+namespace {
+
+class ODataOutputStream :
+ public WeakImplHelper <
+ XDataOutputStream,
+ XActiveDataSource,
+ XConnectable,
+ XServiceInfo >
+{
+public:
+ ODataOutputStream()
+ : m_bValidStream( false )
+ {
+ }
+
+public: // XOutputStream
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override;
+ virtual void SAL_CALL flush() override;
+ virtual void SAL_CALL closeOutput() override;
+
+public: // XDataOutputStream
+ virtual void SAL_CALL writeBoolean(sal_Bool Value) override;
+ virtual void SAL_CALL writeByte(sal_Int8 Value) override;
+ virtual void SAL_CALL writeChar(sal_Unicode Value) override;
+ virtual void SAL_CALL writeShort(sal_Int16 Value) override;
+ virtual void SAL_CALL writeLong(sal_Int32 Value) override;
+ virtual void SAL_CALL writeHyper(sal_Int64 Value) override;
+ virtual void SAL_CALL writeFloat(float Value) override;
+ virtual void SAL_CALL writeDouble(double Value) override;
+ virtual void SAL_CALL writeUTF(const OUString& Value) override;
+
+public: // XActiveDataSource
+ virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) override;
+ virtual Reference < XOutputStream > SAL_CALL getOutputStream() override;
+
+public: // XConnectable
+ virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
+ virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
+ virtual Reference < XConnectable > SAL_CALL getSuccessor() override;
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+protected:
+ Reference < XConnectable > m_succ;
+ Reference < XConnectable > m_pred;
+ Reference< XOutputStream > m_output;
+ bool m_bValidStream;
+};
+
+}
+
+// XOutputStream
+void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
+{
+ if( !m_bValidStream )
+ throw NotConnectedException( );
+ m_output->writeBytes( aData );
+}
+
+void ODataOutputStream::flush()
+{
+ if( !m_bValidStream )
+ throw NotConnectedException();
+ m_output->flush();
+}
+
+
+void ODataOutputStream::closeOutput()
+{
+ if( !m_bValidStream )
+ throw NotConnectedException();
+ m_output->closeOutput();
+ setOutputStream( Reference< XOutputStream > () );
+ setPredecessor( Reference < XConnectable >() );
+ setSuccessor( Reference < XConnectable >() );
+}
+
+// XDataOutputStream
+void ODataOutputStream::writeBoolean(sal_Bool Value)
+{
+ if( Value )
+ {
+ writeByte( 1 );
+ }
+ else
+ {
+ writeByte( 0 );
+ }
+}
+
+
+void ODataOutputStream::writeByte(sal_Int8 Value)
+{
+ writeBytes( { Value } );
+}
+
+void ODataOutputStream::writeChar(sal_Unicode Value)
+{
+ writeBytes( { sal_Int8(Value >> 8),
+ sal_Int8(Value) } );
+}
+
+
+void ODataOutputStream::writeShort(sal_Int16 Value)
+{
+ writeBytes( { sal_Int8(Value >> 8),
+ sal_Int8(Value) } );
+}
+
+void ODataOutputStream::writeLong(sal_Int32 Value)
+{
+ writeBytes( { sal_Int8(Value >> 24),
+ sal_Int8(Value >> 16),
+ sal_Int8(Value >> 8),
+ sal_Int8(Value) } );
+}
+
+void ODataOutputStream::writeHyper(sal_Int64 Value)
+{
+ writeBytes( { sal_Int8(Value >> 56),
+ sal_Int8(Value >> 48),
+ sal_Int8(Value >> 40),
+ sal_Int8(Value >> 32),
+ sal_Int8(Value >> 24),
+ sal_Int8(Value >> 16),
+ sal_Int8(Value >> 8),
+ sal_Int8(Value) } );
+}
+
+
+void ODataOutputStream::writeFloat(float Value)
+{
+ union { float f; sal_uInt32 n; } a;
+ a.f = Value;
+ writeLong( a.n );
+}
+
+void ODataOutputStream::writeDouble(double Value)
+{
+ union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
+ a.d = Value;
+#if defined OSL_LITENDIAN
+ writeLong( a.ad.n2 );
+ writeLong( a.ad.n1 );
+#else
+ writeLong( a.ad.n1 );
+ writeLong( a.ad.n2 );
+#endif
+}
+
+void ODataOutputStream::writeUTF(const OUString& Value)
+{
+ sal_Int32 nStrLen = Value.getLength();
+ const sal_Unicode * pStr = Value.getStr();
+ sal_Int32 nUTFLen = 0;
+ sal_Int32 i;
+
+ for( i = 0 ; i < nStrLen ; i++ )
+ {
+ sal_uInt16 c = pStr[i];
+ if( (c >= 0x0001) && (c <= 0x007F) )
+ {
+ nUTFLen++;
+ }
+ else if( c > 0x07FF )
+ {
+ nUTFLen += 3;
+ }
+ else
+ {
+ nUTFLen += 2;
+ }
+ }
+
+
+ // compatibility mode for older implementations, where it was not possible
+ // to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
+ // that are exactly 64k long can not be read by older routines when written
+ // with these routines and the other way round !!!!!
+ if( nUTFLen >= 0xFFFF ) {
+ writeShort( sal_Int16(-1) );
+ writeLong( nUTFLen );
+ }
+ else {
+ writeShort( static_cast<sal_uInt16>(nUTFLen) );
+ }
+ for( i = 0 ; i < nStrLen ; i++ )
+ {
+ sal_uInt16 c = pStr[i];
+ if( (c >= 0x0001) && (c <= 0x007F) )
+ {
+ writeByte(sal_Int8(c));
+ }
+ else if( c > 0x07FF )
+ {
+ writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
+ writeByte(sal_Int8(0x80 | ((c >> 6) & 0x3F)));
+ writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
+ }
+ else
+ {
+ writeByte(sal_Int8(0xC0 | ((c >> 6) & 0x1F)));
+ writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
+ }
+ }
+}
+
+// XActiveDataSource
+void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
+{
+ if( m_output != aStream ) {
+ m_output = aStream;
+ m_bValidStream = m_output.is();
+
+ Reference < XConnectable > succ( m_output , UNO_QUERY );
+ setSuccessor( succ );
+ }
+}
+
+Reference< XOutputStream > ODataOutputStream::getOutputStream()
+{
+ return m_output;
+}
+
+
+// XDataSink
+void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
+{
+ /// if the references match, nothing needs to be done
+ if( m_succ != r )
+ {
+ /// store the reference for later use
+ m_succ = r;
+
+ if( m_succ.is() )
+ {
+ /// set this instance as the sink !
+ m_succ->setPredecessor( Reference < XConnectable > (
+ static_cast< XConnectable * >(this) ));
+ }
+ }
+}
+Reference < XConnectable > ODataOutputStream::getSuccessor()
+{
+ return m_succ;
+}
+
+
+// XDataSource
+void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )
+{
+ if( r != m_pred ) {
+ m_pred = r;
+ if( m_pred.is() ) {
+ m_pred->setSuccessor( Reference< XConnectable > (
+ static_cast< XConnectable * >(this) ));
+ }
+ }
+}
+Reference < XConnectable > ODataOutputStream::getPredecessor()
+{
+ return m_pred;
+}
+
+
+// XServiceInfo
+OUString ODataOutputStream::getImplementationName()
+{
+ return ODataOutputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > ODataOutputStream::getSupportedServiceNames()
+{
+ return ODataOutputStream_getSupportedServiceNames();
+}
+
+Reference< XInterface > ODataOutputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ ODataOutputStream *p = new ODataOutputStream;
+ Reference< XInterface > xService = *p;
+ return xService;
+}
+
+
+OUString ODataOutputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.DataOutputStream";
+}
+
+Sequence<OUString> ODataOutputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.DataOutputStream" };
+ return aRet;
+}
+
+namespace {
+
+struct equalObjectContainer_Impl
+{
+ bool operator()(const Reference< XInterface > & s1,
+ const Reference< XInterface > & s2) const
+ {
+ return s1 == s2;
+ }
+};
+
+
+struct hashObjectContainer_Impl
+{
+ size_t operator()(const Reference< XInterface > & xRef) const
+ {
+ return reinterpret_cast<size_t>(xRef.get());
+ }
+};
+
+}
+
+typedef std::unordered_map
+<
+ Reference< XInterface >,
+ sal_Int32,
+ hashObjectContainer_Impl,
+ equalObjectContainer_Impl
+> ObjectContainer_Impl;
+
+namespace {
+
+class OObjectOutputStream:
+ public ImplInheritanceHelper<
+ ODataOutputStream, /* parent */
+ XObjectOutputStream, XMarkableStream >
+{
+public:
+ OObjectOutputStream()
+ : m_nMaxId(0) ,
+ m_bValidMarkable(false)
+ {
+ }
+
+public:
+ // XOutputStream
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override
+ { ODataOutputStream::writeBytes( aData ); }
+
+ virtual void SAL_CALL flush() override
+ { ODataOutputStream::flush(); }
+
+ virtual void SAL_CALL closeOutput() override
+ { ODataOutputStream::closeOutput(); }
+
+public:
+ // XDataOutputStream
+ virtual void SAL_CALL writeBoolean(sal_Bool Value) override
+ { ODataOutputStream::writeBoolean( Value ); }
+ virtual void SAL_CALL writeByte(sal_Int8 Value) override
+ { ODataOutputStream::writeByte( Value ); }
+ virtual void SAL_CALL writeChar(sal_Unicode Value) override
+ { ODataOutputStream::writeChar( Value ); }
+ virtual void SAL_CALL writeShort(sal_Int16 Value) override
+ { ODataOutputStream::writeShort( Value ); }
+ virtual void SAL_CALL writeLong(sal_Int32 Value) override
+ { ODataOutputStream::writeLong( Value ); }
+ virtual void SAL_CALL writeHyper(sal_Int64 Value) override
+ { ODataOutputStream::writeHyper( Value ); }
+ virtual void SAL_CALL writeFloat(float Value) override
+ { ODataOutputStream::writeFloat( Value ); }
+ virtual void SAL_CALL writeDouble(double Value) override
+ { ODataOutputStream::writeDouble( Value ); }
+ virtual void SAL_CALL writeUTF(const OUString& Value) override
+ { ODataOutputStream::writeUTF( Value );}
+
+ // XObjectOutputStream
+ virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) override;
+
+public: // XMarkableStream
+ virtual sal_Int32 SAL_CALL createMark() override;
+ virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
+ virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
+ virtual void SAL_CALL jumpToFurthest() override;
+ virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+private:
+ void connectToMarkable();
+private:
+ ObjectContainer_Impl m_mapObject;
+ sal_Int32 m_nMaxId;
+ Reference< XMarkableStream > m_rMarkable;
+ bool m_bValidMarkable;
+};
+
+}
+
+void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj )
+{
+
+ connectToMarkable();
+ bool bWriteObj = false;
+ // create Mark to write length of info
+ sal_uInt32 nInfoLenMark = m_rMarkable->createMark();
+
+ // length of the info data (is later rewritten)
+ OObjectOutputStream::writeShort( 0 );
+
+ // write the object identifier
+ if( xPObj.is() )
+ {
+ Reference< XInterface > rX( xPObj , UNO_QUERY );
+
+ ObjectContainer_Impl::const_iterator aIt
+ = m_mapObject.find( rX );
+ if( aIt == m_mapObject.end() )
+ {
+ // insert new object in hash table
+ m_mapObject[ rX ] = ++m_nMaxId;
+ ODataOutputStream::writeLong( m_nMaxId );
+ ODataOutputStream::writeUTF( xPObj->getServiceName() );
+ bWriteObj = true;
+ }
+ else
+ {
+ ODataOutputStream::writeLong( (*aIt).second );
+ ODataOutputStream::writeUTF( OUString() );
+ }
+ }
+ else
+ {
+ ODataOutputStream::writeLong( 0 );
+ ODataOutputStream::writeUTF( OUString() );
+ }
+
+ sal_uInt32 nObjLenMark = m_rMarkable->createMark();
+ ODataOutputStream::writeLong( 0 );
+
+ sal_Int32 nInfoLen = m_rMarkable->offsetToMark( nInfoLenMark );
+ m_rMarkable->jumpToMark( nInfoLenMark );
+ // write length of the info data
+ ODataOutputStream::writeShort( static_cast<sal_Int16>(nInfoLen) );
+ // jump to the end of the stream
+ m_rMarkable->jumpToFurthest();
+
+ if( bWriteObj )
+ xPObj->write( Reference< XObjectOutputStream > (
+ static_cast< XObjectOutputStream * >(this) ) );
+
+ sal_Int32 nObjLen = m_rMarkable->offsetToMark( nObjLenMark ) -4;
+ m_rMarkable->jumpToMark( nObjLenMark );
+ // write length of the info data
+ ODataOutputStream::writeLong( nObjLen );
+ // jump to the end of the stream
+ m_rMarkable->jumpToFurthest();
+
+ m_rMarkable->deleteMark( nObjLenMark );
+ m_rMarkable->deleteMark( nInfoLenMark );
+}
+
+
+void OObjectOutputStream::connectToMarkable()
+{
+ if( m_bValidMarkable )
+ return;
+
+ if( ! m_bValidStream )
+ throw NotConnectedException();
+
+ // find the markable stream !
+ Reference< XInterface > rTry(m_output);
+ while( true ) {
+ if( ! rTry.is() )
+ {
+ throw NotConnectedException();
+ }
+ Reference < XMarkableStream > markable( rTry , UNO_QUERY );
+ if( markable.is() )
+ {
+ m_rMarkable = markable;
+ break;
+ }
+ Reference < XActiveDataSource > source( rTry , UNO_QUERY );
+ rTry = source;
+ }
+ m_bValidMarkable = true;
+}
+
+
+sal_Int32 OObjectOutputStream::createMark()
+{
+ connectToMarkable(); // throws an exception, if a markable is not connected !
+
+ return m_rMarkable->createMark();
+}
+
+void OObjectOutputStream::deleteMark(sal_Int32 Mark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ m_rMarkable->deleteMark( Mark );
+}
+
+void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ m_rMarkable->jumpToMark( nMark );
+}
+
+
+void OObjectOutputStream::jumpToFurthest()
+{
+ connectToMarkable();
+ m_rMarkable->jumpToFurthest();
+}
+
+sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ return m_rMarkable->offsetToMark( nMark );
+}
+
+
+Reference< XInterface > OObjectOutputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ OObjectOutputStream *p = new OObjectOutputStream;
+ return Reference< XInterface > ( static_cast< OWeakObject * >(p) );
+}
+
+OUString OObjectOutputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.ObjectOutputStream";
+}
+
+Sequence<OUString> OObjectOutputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.ObjectOutputStream" };
+ return aRet;
+}
+
+// XServiceInfo
+OUString OObjectOutputStream::getImplementationName()
+{
+ return OObjectOutputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OObjectOutputStream::getSupportedServiceNames()
+{
+ return OObjectOutputStream_getSupportedServiceNames();
+}
+
+namespace {
+
+class OObjectInputStream:
+ public ImplInheritanceHelper<
+ ODataInputStream, /* parent */
+ XObjectInputStream, XMarkableStream >
+{
+public:
+ explicit OObjectInputStream( const Reference < XComponentContext > &r)
+ : m_rSMgr( r->getServiceManager() )
+ , m_rCxt( r )
+ , m_bValidMarkable(false)
+ {
+ }
+
+public: // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override
+ { return ODataInputStream::readBytes( aData , nBytesToRead ); }
+
+ virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override
+ { return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }
+
+ virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
+ { ODataInputStream::skipBytes( nBytesToSkip ); }
+
+ virtual sal_Int32 SAL_CALL available() override
+ { return ODataInputStream::available(); }
+
+ virtual void SAL_CALL closeInput() override
+ { ODataInputStream::closeInput(); }
+
+public: // XDataInputStream
+ virtual sal_Int8 SAL_CALL readBoolean() override
+ { return ODataInputStream::readBoolean(); }
+ virtual sal_Int8 SAL_CALL readByte() override
+ { return ODataInputStream::readByte(); }
+ virtual sal_Unicode SAL_CALL readChar() override
+ { return ODataInputStream::readChar(); }
+ virtual sal_Int16 SAL_CALL readShort() override
+ { return ODataInputStream::readShort(); }
+ virtual sal_Int32 SAL_CALL readLong() override
+ { return ODataInputStream::readLong(); }
+ virtual sal_Int64 SAL_CALL readHyper() override
+ { return ODataInputStream::readHyper(); }
+ virtual float SAL_CALL readFloat() override
+ { return ODataInputStream::readFloat(); }
+ virtual double SAL_CALL readDouble() override
+ { return ODataInputStream::readDouble(); }
+ virtual OUString SAL_CALL readUTF() override
+ { return ODataInputStream::readUTF(); }
+
+public: // XObjectInputStream
+ virtual Reference< XPersistObject > SAL_CALL readObject( ) override;
+
+public: // XMarkableStream
+ virtual sal_Int32 SAL_CALL createMark() override;
+ virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
+ virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
+ virtual void SAL_CALL jumpToFurthest() override;
+ virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+private:
+ void connectToMarkable();
+private:
+ Reference < XMultiComponentFactory > m_rSMgr;
+ Reference < XComponentContext > m_rCxt;
+ bool m_bValidMarkable;
+ Reference < XMarkableStream > m_rMarkable;
+ vector < Reference< XPersistObject > > m_aPersistVector;
+
+};
+
+}
+
+Reference< XPersistObject > OObjectInputStream::readObject()
+{
+ // check if chain contains a XMarkableStream
+ connectToMarkable();
+
+ Reference< XPersistObject > xLoadedObj;
+
+ // create Mark to skip newer versions
+ sal_uInt32 nMark = m_rMarkable->createMark();
+ // length of the data
+ sal_Int32 nLen = static_cast<sal_uInt16>(ODataInputStream::readShort());
+ if( nLen < 0xc )
+ {
+ throw WrongFormatException();
+ }
+
+ // read the object identifier
+ sal_uInt32 nId = readLong();
+
+ // the name of the persist model
+ // MM ???
+ OUString aName = readUTF();
+
+ // Read the length of the object
+ sal_Int32 nObjLen = readLong();
+ if( 0 == nId && 0 != nObjLen )
+ {
+ throw WrongFormatException();
+ }
+
+ // skip data of new version
+ skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );
+
+ bool bLoadSuccessful = true;
+ if( nId )
+ {
+ if( !aName.isEmpty() )
+ {
+ // load the object
+ Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
+ xLoadedObj.set( x, UNO_QUERY );
+ if( xLoadedObj.is() )
+ {
+ sal_uInt32 nSize = m_aPersistVector.size();
+ if( nSize <= nId )
+ {
+ // grow to the right size
+ Reference< XPersistObject > xEmpty;
+ m_aPersistVector.insert( m_aPersistVector.end(), static_cast<long>(nId - nSize + 1), xEmpty );
+ }
+
+ m_aPersistVector[nId] = xLoadedObj;
+ xLoadedObj->read( Reference< XObjectInputStream >(
+ static_cast< XObjectInputStream * >(this) ) );
+ }
+ else
+ {
+ // no service with this name could be instantiated
+ bLoadSuccessful = false;
+ }
+ }
+ else {
+ if (nId >= m_aPersistVector.size())
+ {
+ // id unknown, load failure !
+ bLoadSuccessful = false;
+ }
+ else
+ {
+ // Object has already been read,
+ xLoadedObj = m_aPersistVector[nId];
+ }
+ }
+ }
+
+ // skip to the position behind the object
+ skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
+ m_rMarkable->deleteMark( nMark );
+
+ if( ! bLoadSuccessful )
+ {
+ throw WrongFormatException();
+ }
+ return xLoadedObj;
+}
+
+
+void OObjectInputStream::connectToMarkable()
+{
+ if( m_bValidMarkable ) return;
+
+ if( ! m_bValidStream )
+ {
+ throw NotConnectedException( );
+ }
+
+ // find the markable stream !
+ Reference< XInterface > rTry(m_input);
+ while( true ) {
+ if( ! rTry.is() )
+ {
+ throw NotConnectedException( );
+ }
+ Reference< XMarkableStream > markable( rTry , UNO_QUERY );
+ if( markable.is() )
+ {
+ m_rMarkable = markable;
+ break;
+ }
+ Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
+ rTry = sink;
+ }
+ m_bValidMarkable = true;
+}
+
+sal_Int32 OObjectInputStream::createMark()
+{
+ connectToMarkable(); // throws an exception, if a markable is not connected !
+
+ return m_rMarkable->createMark();
+}
+
+void OObjectInputStream::deleteMark(sal_Int32 Mark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ m_rMarkable->deleteMark( Mark );
+}
+
+void OObjectInputStream::jumpToMark(sal_Int32 nMark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ m_rMarkable->jumpToMark( nMark );
+}
+void OObjectInputStream::jumpToFurthest()
+{
+ connectToMarkable();
+ m_rMarkable->jumpToFurthest();
+}
+
+sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
+{
+ if( ! m_bValidMarkable )
+ {
+ throw NotConnectedException();
+ }
+ return m_rMarkable->offsetToMark( nMark );
+}
+
+// XServiceInfo
+OUString OObjectInputStream::getImplementationName()
+{
+ return OObjectInputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OObjectInputStream::getSupportedServiceNames()
+{
+ return OObjectInputStream_getSupportedServiceNames();
+}
+
+Reference< XInterface > OObjectInputStream_CreateInstance( const Reference < XComponentContext > & rCtx )
+{
+ OObjectInputStream *p = new OObjectInputStream( rCtx );
+ return Reference< XInterface> ( static_cast< OWeakObject * >(p) );
+}
+
+OUString OObjectInputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.ObjectInputStream";
+}
+
+Sequence<OUString> OObjectInputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.ObjectInputStream" };
+ return aRet;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/omark.cxx b/io/source/stm/omark.cxx
new file mode 100644
index 000000000..0c7a82142
--- /dev/null
+++ b/io/source/stm/omark.cxx
@@ -0,0 +1,801 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <map>
+#include <memory>
+
+#include <com/sun/star/io/BufferSizeExceededException.hpp>
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <osl/mutex.hxx>
+#include <osl/diagnose.h>
+
+
+using namespace ::std;
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+#include <services.hxx>
+#include "streamhelper.hxx"
+
+namespace io_stm {
+
+namespace {
+
+/***********************
+*
+* OMarkableOutputStream.
+*
+* This object allows to set marks in an outputstream. It is allowed to jump back to the marks and
+* rewrite the same bytes.
+*
+* The object must buffer the data since the last mark set. Flush will not
+* have any effect. As soon as the last mark has been removed, the object may write the data
+* through to the chained object.
+*
+**********************/
+class OMarkableOutputStream :
+ public WeakImplHelper< XOutputStream ,
+ XActiveDataSource ,
+ XMarkableStream ,
+ XConnectable,
+ XServiceInfo
+ >
+{
+public:
+ OMarkableOutputStream( );
+
+public: // XOutputStream
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override;
+ virtual void SAL_CALL flush() override;
+ virtual void SAL_CALL closeOutput() override;
+
+public: // XMarkable
+ virtual sal_Int32 SAL_CALL createMark() override;
+ virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
+ virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
+ virtual void SAL_CALL jumpToFurthest() override;
+ virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
+
+public: // XActiveDataSource
+ virtual void SAL_CALL setOutputStream(const Reference < XOutputStream > & aStream) override;
+ virtual Reference < XOutputStream > SAL_CALL getOutputStream() override;
+
+public: // XConnectable
+ virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor) override;
+ virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
+ virtual Reference< XConnectable > SAL_CALL getSuccessor() override;
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+private:
+ // helper methods
+ /// @throws NotConnectedException
+ /// @throws BufferSizeExceededException
+ void checkMarksAndFlush();
+
+ Reference< XConnectable > m_succ;
+ Reference< XConnectable > m_pred;
+
+ Reference< XOutputStream > m_output;
+ bool m_bValidStream;
+
+ std::unique_ptr<MemRingBuffer> m_pBuffer;
+ map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks;
+ sal_Int32 m_nCurrentPos;
+ sal_Int32 m_nCurrentMark;
+
+ Mutex m_mutex;
+};
+
+}
+
+OMarkableOutputStream::OMarkableOutputStream( )
+ : m_bValidStream(false)
+ , m_pBuffer( new MemRingBuffer )
+ , m_nCurrentPos(0)
+ , m_nCurrentMark(0)
+{
+}
+
+// XOutputStream
+void OMarkableOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
+{
+ if( !m_bValidStream ) {
+ throw NotConnectedException();
+ }
+ if( m_mapMarks.empty() && ( m_pBuffer->getSize() == 0 ) ) {
+ // no mark and buffer active, simple write through
+ m_output->writeBytes( aData );
+ }
+ else {
+ MutexGuard guard( m_mutex );
+ // new data must be buffered
+ m_pBuffer->writeAt( m_nCurrentPos , aData );
+ m_nCurrentPos += aData.getLength();
+ checkMarksAndFlush();
+ }
+
+}
+
+void OMarkableOutputStream::flush()
+{
+ Reference< XOutputStream > output;
+ {
+ MutexGuard guard( m_mutex );
+ output = m_output;
+ }
+
+ // Markable cannot flush buffered data, because the data may get rewritten,
+ // however one can forward the flush to the chained stream to give it
+ // a chance to write data buffered in the chained stream.
+ if( output.is() )
+ {
+ output->flush();
+ }
+}
+
+void OMarkableOutputStream::closeOutput()
+{
+ if( !m_bValidStream ) {
+ throw NotConnectedException();
+ }
+ MutexGuard guard( m_mutex );
+ // all marks must be cleared and all
+
+ m_mapMarks.clear();
+ m_nCurrentPos = m_pBuffer->getSize();
+ checkMarksAndFlush();
+
+ m_output->closeOutput();
+
+ setOutputStream( Reference< XOutputStream > () );
+ setPredecessor( Reference < XConnectable >() );
+ setSuccessor( Reference< XConnectable > () );
+
+}
+
+
+sal_Int32 OMarkableOutputStream::createMark()
+{
+ MutexGuard guard( m_mutex );
+ sal_Int32 nMark = m_nCurrentMark;
+
+ m_mapMarks[nMark] = m_nCurrentPos;
+
+ m_nCurrentMark ++;
+ return nMark;
+}
+
+void OMarkableOutputStream::deleteMark(sal_Int32 Mark)
+{
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
+
+ if( ii == m_mapMarks.end() ) {
+ throw IllegalArgumentException(
+ "MarkableOutputStream::deleteMark unknown mark (" + OUString::number(Mark) + ")",
+ *this, 0);
+ }
+ m_mapMarks.erase( ii );
+ checkMarksAndFlush();
+}
+
+void OMarkableOutputStream::jumpToMark(sal_Int32 nMark)
+{
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark );
+
+ if( ii == m_mapMarks.end() ) {
+ throw IllegalArgumentException(
+ "MarkableOutputStream::jumpToMark unknown mark (" + OUString::number(nMark) + ")",
+ *this, 0);
+ }
+ m_nCurrentPos = (*ii).second;
+}
+
+void OMarkableOutputStream::jumpToFurthest()
+{
+ MutexGuard guard( m_mutex );
+ m_nCurrentPos = m_pBuffer->getSize();
+ checkMarksAndFlush();
+}
+
+sal_Int32 OMarkableOutputStream::offsetToMark(sal_Int32 nMark)
+{
+
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
+
+ if( ii == m_mapMarks.end() )
+ {
+ throw IllegalArgumentException(
+ "MarkableOutputStream::offsetToMark unknown mark (" + OUString::number(nMark) + ")",
+ *this, 0);
+ }
+ return m_nCurrentPos - (*ii).second;
+}
+
+
+// XActiveDataSource2
+void OMarkableOutputStream::setOutputStream(const Reference < XOutputStream >& aStream)
+{
+ if( m_output != aStream ) {
+ m_output = aStream;
+
+ Reference < XConnectable > succ( m_output , UNO_QUERY );
+ setSuccessor( succ );
+ }
+ m_bValidStream = m_output.is();
+}
+
+Reference< XOutputStream > OMarkableOutputStream::getOutputStream()
+{
+ return m_output;
+}
+
+
+void OMarkableOutputStream::setSuccessor( const Reference< XConnectable > &r )
+{
+ /// if the references match, nothing needs to be done
+ if( m_succ != r ) {
+ /// store the reference for later use
+ m_succ = r;
+
+ if( m_succ.is() ) {
+ m_succ->setPredecessor( Reference < XConnectable > (
+ static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+Reference <XConnectable > OMarkableOutputStream::getSuccessor()
+{
+ return m_succ;
+}
+
+
+// XDataSource
+void OMarkableOutputStream::setPredecessor( const Reference< XConnectable > &r )
+{
+ if( r != m_pred ) {
+ m_pred = r;
+ if( m_pred.is() ) {
+ m_pred->setSuccessor( Reference < XConnectable > (
+ static_cast< XConnectable * >(this ) ) );
+ }
+ }
+}
+Reference < XConnectable > OMarkableOutputStream::getPredecessor()
+{
+ return m_pred;
+}
+
+
+// private methods
+
+void OMarkableOutputStream::checkMarksAndFlush()
+{
+ // find the smallest mark
+ sal_Int32 nNextFound = m_nCurrentPos;
+ for (auto const& mark : m_mapMarks)
+ {
+ if( mark.second <= nNextFound ) {
+ nNextFound = mark.second;
+ }
+ }
+
+ if( nNextFound ) {
+ // some data must be released !
+ m_nCurrentPos -= nNextFound;
+ for (auto & mark : m_mapMarks)
+ {
+ mark.second -= nNextFound;
+ }
+
+ Sequence<sal_Int8> seq(nNextFound);
+ m_pBuffer->readAt( 0 , seq , nNextFound );
+ m_pBuffer->forgetFromStart( nNextFound );
+
+ // now write data through to streams
+ m_output->writeBytes( seq );
+ }
+ else {
+ // nothing to do. There is a mark or the current cursor position, that prevents
+ // releasing data !
+ }
+}
+
+
+// XServiceInfo
+OUString OMarkableOutputStream::getImplementationName()
+{
+ return OMarkableOutputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool OMarkableOutputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OMarkableOutputStream::getSupportedServiceNames()
+{
+ return OMarkableOutputStream_getSupportedServiceNames();
+}
+
+/*------------------------
+*
+* external binding
+*
+*------------------------*/
+Reference< XInterface > OMarkableOutputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ OMarkableOutputStream *p = new OMarkableOutputStream( );
+
+ return Reference < XInterface > ( static_cast<OWeakObject *>(p) );
+}
+
+OUString OMarkableOutputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.MarkableOutputStream";
+}
+
+Sequence<OUString> OMarkableOutputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.MarkableOutputStream" };
+
+ return aRet;
+}
+
+
+// XMarkableInputStream
+
+namespace {
+
+class OMarkableInputStream :
+ public WeakImplHelper
+ <
+ XInputStream,
+ XActiveDataSink,
+ XMarkableStream,
+ XConnectable,
+ XServiceInfo
+ >
+{
+public:
+ OMarkableInputStream( );
+
+
+public: // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override ;
+ virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override;
+ virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override;
+
+ virtual sal_Int32 SAL_CALL available() override;
+ virtual void SAL_CALL closeInput() override;
+
+public: // XMarkable
+ virtual sal_Int32 SAL_CALL createMark() override;
+ virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
+ virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
+ virtual void SAL_CALL jumpToFurthest() override;
+ virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
+
+public: // XActiveDataSink
+ virtual void SAL_CALL setInputStream(const Reference < XInputStream > & aStream) override;
+ virtual Reference < XInputStream > SAL_CALL getInputStream() override;
+
+public: // XConnectable
+ virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor) override;
+ virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor) override;
+ virtual Reference < XConnectable > SAL_CALL getSuccessor() override;
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+private:
+ void checkMarksAndFlush();
+
+ Reference < XConnectable > m_succ;
+ Reference < XConnectable > m_pred;
+
+ Reference< XInputStream > m_input;
+ bool m_bValidStream;
+
+ std::unique_ptr<MemRingBuffer> m_pBuffer;
+ map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks;
+ sal_Int32 m_nCurrentPos;
+ sal_Int32 m_nCurrentMark;
+
+ Mutex m_mutex;
+};
+
+}
+
+OMarkableInputStream::OMarkableInputStream()
+ : m_bValidStream(false)
+ , m_nCurrentPos(0)
+ , m_nCurrentMark(0)
+{
+ m_pBuffer.reset( new MemRingBuffer );
+}
+
+
+// XInputStream
+
+sal_Int32 OMarkableInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+{
+ sal_Int32 nBytesRead;
+
+ if( !m_bValidStream ) {
+ throw NotConnectedException(
+ "MarkableInputStream::readBytes NotConnectedException",
+ *this );
+ }
+ MutexGuard guard( m_mutex );
+ if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
+ // normal read !
+ nBytesRead = m_input->readBytes( aData, nBytesToRead );
+ }
+ else {
+ // read from buffer
+ sal_Int32 nRead;
+
+ // read enough bytes into buffer
+ if( m_pBuffer->getSize() - m_nCurrentPos < nBytesToRead ) {
+ sal_Int32 nToRead = nBytesToRead - ( m_pBuffer->getSize() - m_nCurrentPos );
+ nRead = m_input->readBytes( aData , nToRead );
+
+ OSL_ASSERT( aData.getLength() == nRead );
+
+ m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
+
+ if( nRead < nToRead ) {
+ nBytesToRead = nBytesToRead - (nToRead-nRead);
+ }
+ }
+
+ OSL_ASSERT( m_pBuffer->getSize() - m_nCurrentPos >= nBytesToRead );
+
+ m_pBuffer->readAt( m_nCurrentPos , aData , nBytesToRead );
+
+ m_nCurrentPos += nBytesToRead;
+ nBytesRead = nBytesToRead;
+ }
+
+ return nBytesRead;
+}
+
+
+sal_Int32 OMarkableInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
+{
+
+ sal_Int32 nBytesRead;
+ if( !m_bValidStream ) {
+ throw NotConnectedException(
+ "MarkableInputStream::readSomeBytes NotConnectedException",
+ *this );
+ }
+
+ MutexGuard guard( m_mutex );
+ if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
+ // normal read !
+ nBytesRead = m_input->readSomeBytes( aData, nMaxBytesToRead );
+ }
+ else {
+ // read from buffer
+ sal_Int32 nRead = 0;
+ sal_Int32 nInBuffer = m_pBuffer->getSize() - m_nCurrentPos;
+ sal_Int32 nAdditionalBytesToRead = std::min<sal_Int32>(nMaxBytesToRead-nInBuffer,m_input->available());
+ nAdditionalBytesToRead = std::max<sal_Int32>(0 , nAdditionalBytesToRead );
+
+ // read enough bytes into buffer
+ if( 0 == nInBuffer ) {
+ nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
+ }
+ else if( nAdditionalBytesToRead ) {
+ nRead = m_input->readBytes( aData , nAdditionalBytesToRead );
+ }
+
+ if( nRead ) {
+ aData.realloc( nRead );
+ m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
+ }
+
+ nBytesRead = std::min( nMaxBytesToRead , nInBuffer + nRead );
+
+ // now take everything from buffer !
+ m_pBuffer->readAt( m_nCurrentPos , aData , nBytesRead );
+
+ m_nCurrentPos += nBytesRead;
+ }
+
+ return nBytesRead;
+
+
+}
+
+
+void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip)
+{
+ if ( nBytesToSkip < 0 )
+ throw BufferSizeExceededException(
+ "precondition not met: XInputStream::skipBytes: non-negative integer required!",
+ *this
+ );
+
+ // this method is blocking
+ Sequence<sal_Int8> seqDummy( nBytesToSkip );
+ readBytes( seqDummy , nBytesToSkip );
+}
+
+sal_Int32 OMarkableInputStream::available()
+{
+ if( !m_bValidStream ) {
+ throw NotConnectedException(
+ "MarkableInputStream::available NotConnectedException",
+ *this );
+ }
+
+ MutexGuard guard( m_mutex );
+ sal_Int32 nAvail = m_input->available() + ( m_pBuffer->getSize() - m_nCurrentPos );
+ return nAvail;
+}
+
+
+void OMarkableInputStream::closeInput()
+{
+ if( !m_bValidStream ) {
+ throw NotConnectedException(
+ "MarkableInputStream::closeInput NotConnectedException",
+ *this );
+ }
+ MutexGuard guard( m_mutex );
+
+ m_input->closeInput();
+
+ setInputStream( Reference< XInputStream > () );
+ setPredecessor( Reference< XConnectable > () );
+ setSuccessor( Reference< XConnectable >() );
+
+ m_pBuffer.reset();
+ m_nCurrentPos = 0;
+ m_nCurrentMark = 0;
+}
+
+// XMarkable
+
+sal_Int32 OMarkableInputStream::createMark()
+{
+ MutexGuard guard( m_mutex );
+ sal_Int32 nMark = m_nCurrentMark;
+
+ m_mapMarks[nMark] = m_nCurrentPos;
+
+ m_nCurrentMark ++;
+ return nMark;
+}
+
+void OMarkableInputStream::deleteMark(sal_Int32 Mark)
+{
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
+
+ if( ii == m_mapMarks.end() ) {
+ throw IllegalArgumentException(
+ "MarkableInputStream::deleteMark unknown mark (" + OUString::number(Mark) + ")",
+ *this , 0 );
+ }
+ m_mapMarks.erase( ii );
+ checkMarksAndFlush();
+}
+
+void OMarkableInputStream::jumpToMark(sal_Int32 nMark)
+{
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark );
+
+ if( ii == m_mapMarks.end() )
+ {
+ throw IllegalArgumentException(
+ "MarkableInputStream::jumpToMark unknown mark (" + OUString::number(nMark) + ")",
+ *this , 0 );
+ }
+ m_nCurrentPos = (*ii).second;
+}
+
+void OMarkableInputStream::jumpToFurthest()
+{
+ MutexGuard guard( m_mutex );
+ m_nCurrentPos = m_pBuffer->getSize();
+ checkMarksAndFlush();
+}
+
+sal_Int32 OMarkableInputStream::offsetToMark(sal_Int32 nMark)
+{
+ MutexGuard guard( m_mutex );
+ map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
+
+ if( ii == m_mapMarks.end() )
+ {
+ throw IllegalArgumentException(
+ "MarkableInputStream::offsetToMark unknown mark (" + OUString::number(nMark) + ")",
+ *this, 0 );
+ }
+ return m_nCurrentPos - (*ii).second;
+}
+
+
+// XActiveDataSource
+void OMarkableInputStream::setInputStream(const Reference< XInputStream > & aStream)
+{
+
+ if( m_input != aStream ) {
+ m_input = aStream;
+
+ Reference < XConnectable > pred( m_input , UNO_QUERY );
+ setPredecessor( pred );
+ }
+
+ m_bValidStream = m_input.is();
+
+}
+
+Reference< XInputStream > OMarkableInputStream::getInputStream()
+{
+ return m_input;
+}
+
+
+// XDataSink
+void OMarkableInputStream::setSuccessor( const Reference< XConnectable > &r )
+{
+ /// if the references match, nothing needs to be done
+ if( m_succ != r ) {
+ /// store the reference for later use
+ m_succ = r;
+
+ if( m_succ.is() ) {
+ /// set this instance as the sink !
+ m_succ->setPredecessor( Reference< XConnectable > (
+ static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+
+Reference < XConnectable > OMarkableInputStream::getSuccessor()
+{
+ return m_succ;
+}
+
+
+// XDataSource
+void OMarkableInputStream::setPredecessor( const Reference < XConnectable > &r )
+{
+ if( r != m_pred ) {
+ m_pred = r;
+ if( m_pred.is() ) {
+ m_pred->setSuccessor( Reference< XConnectable > (
+ static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+Reference< XConnectable > OMarkableInputStream::getPredecessor()
+{
+ return m_pred;
+}
+
+
+void OMarkableInputStream::checkMarksAndFlush()
+{
+ // find the smallest mark
+ sal_Int32 nNextFound = m_nCurrentPos;
+ for (auto const& mark : m_mapMarks)
+ {
+ if( mark.second <= nNextFound ) {
+ nNextFound = mark.second;
+ }
+ }
+
+ if( nNextFound ) {
+ // some data must be released !
+ m_nCurrentPos -= nNextFound;
+ for (auto & mark : m_mapMarks)
+ {
+ mark.second -= nNextFound;
+ }
+
+ m_pBuffer->forgetFromStart( nNextFound );
+
+ }
+ else {
+ // nothing to do. There is a mark or the current cursor position, that prevents
+ // releasing data !
+ }
+}
+
+// XServiceInfo
+OUString OMarkableInputStream::getImplementationName()
+{
+ return OMarkableInputStream_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool OMarkableInputStream::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OMarkableInputStream::getSupportedServiceNames()
+{
+ return OMarkableInputStream_getSupportedServiceNames();
+}
+
+/*------------------------
+*
+* external binding
+*
+*------------------------*/
+Reference < XInterface > OMarkableInputStream_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ OMarkableInputStream *p = new OMarkableInputStream( );
+ return Reference< XInterface > ( static_cast<OWeakObject *>(p) );
+}
+
+OUString OMarkableInputStream_getImplementationName()
+{
+ return "com.sun.star.comp.io.stm.MarkableInputStream";
+}
+
+Sequence<OUString> OMarkableInputStream_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.MarkableInputStream" };
+ return aRet;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/opipe.cxx b/io/source/stm/opipe.cxx
new file mode 100644
index 000000000..07331472d
--- /dev/null
+++ b/io/source/stm/opipe.cxx
@@ -0,0 +1,380 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/io/BufferSizeExceededException.hpp>
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/XPipe.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+
+#include <limits>
+#include <memory>
+#include <string.h>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+
+#include <services.hxx>
+#include "streamhelper.hxx"
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+// Implementation and service names
+#define IMPLEMENTATION_NAME "com.sun.star.comp.io.stm.Pipe"
+
+namespace io_stm{
+
+namespace {
+
+class OPipeImpl :
+ public WeakImplHelper< XPipe , XConnectable , XServiceInfo >
+{
+public:
+ OPipeImpl( );
+
+public: // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override;
+ virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override;
+ virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override;
+ virtual sal_Int32 SAL_CALL available() override;
+ virtual void SAL_CALL closeInput() override;
+
+public: // XOutputStream
+
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override;
+ virtual void SAL_CALL flush() override;
+ virtual void SAL_CALL closeOutput() override;
+
+public: // XConnectable
+ virtual void SAL_CALL setPredecessor(const Reference< XConnectable >& aPredecessor) override;
+ virtual Reference< XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor) override;
+ virtual Reference < XConnectable > SAL_CALL getSuccessor() override ;
+
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+private:
+
+ Reference < XConnectable > m_succ;
+ Reference < XConnectable > m_pred;
+
+ sal_Int32 m_nBytesToSkip;
+
+ bool m_bOutputStreamClosed;
+ bool m_bInputStreamClosed;
+
+ osl::Condition m_conditionBytesAvail;
+ Mutex m_mutexAccess;
+ std::unique_ptr<MemFIFO> m_pFIFO;
+};
+
+}
+
+OPipeImpl::OPipeImpl()
+ : m_nBytesToSkip(0 )
+ , m_bOutputStreamClosed(false )
+ , m_bInputStreamClosed( false )
+ , m_pFIFO( new MemFIFO )
+{
+}
+
+
+
+sal_Int32 OPipeImpl::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+{
+ while( true )
+ {
+ { // start guarded section
+ MutexGuard guard( m_mutexAccess );
+ if( m_bInputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::readBytes NotConnectedException",
+ *this );
+ }
+ sal_Int32 nOccupiedBufferLen = m_pFIFO->getSize();
+
+ if( m_bOutputStreamClosed && nBytesToRead > nOccupiedBufferLen )
+ {
+ nBytesToRead = nOccupiedBufferLen;
+ }
+
+ if( nOccupiedBufferLen < nBytesToRead )
+ {
+ // wait outside guarded section
+ m_conditionBytesAvail.reset();
+ }
+ else {
+ // necessary bytes are available
+ m_pFIFO->read( aData , nBytesToRead );
+ return nBytesToRead;
+ }
+ } // end guarded section
+
+ // wait for new data outside guarded section!
+ m_conditionBytesAvail.wait();
+ }
+}
+
+
+sal_Int32 OPipeImpl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
+{
+ while( true ) {
+ {
+ MutexGuard guard( m_mutexAccess );
+ if( m_bInputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::readSomeBytes NotConnectedException",
+ *this );
+ }
+ if( m_pFIFO->getSize() )
+ {
+ sal_Int32 nSize = std::min( nMaxBytesToRead , m_pFIFO->getSize() );
+ aData.realloc( nSize );
+ m_pFIFO->read( aData , nSize );
+ return nSize;
+ }
+
+ if( m_bOutputStreamClosed )
+ {
+ // no bytes in buffer anymore
+ return 0;
+ }
+ }
+
+ m_conditionBytesAvail.wait();
+ }
+}
+
+
+void OPipeImpl::skipBytes(sal_Int32 nBytesToSkip)
+{
+ MutexGuard guard( m_mutexAccess );
+ if( m_bInputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::skipBytes NotConnectedException",
+ *this );
+ }
+
+ if( nBytesToSkip < 0
+ || (nBytesToSkip
+ > std::numeric_limits< sal_Int32 >::max() - m_nBytesToSkip) )
+ {
+ throw BufferSizeExceededException(
+ "Pipe::skipBytes BufferSizeExceededException",
+ *this );
+ }
+ m_nBytesToSkip += nBytesToSkip;
+
+ nBytesToSkip = std::min( m_pFIFO->getSize() , m_nBytesToSkip );
+ m_pFIFO->skip( nBytesToSkip );
+ m_nBytesToSkip -= nBytesToSkip;
+}
+
+
+sal_Int32 OPipeImpl::available()
+ {
+ MutexGuard guard( m_mutexAccess );
+ if( m_bInputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::available NotConnectedException",
+ *this );
+ }
+ return m_pFIFO->getSize();
+}
+
+void OPipeImpl::closeInput()
+{
+ MutexGuard guard( m_mutexAccess );
+
+ m_bInputStreamClosed = true;
+
+ m_pFIFO.reset();
+
+ // readBytes may throw an exception
+ m_conditionBytesAvail.set();
+
+ setSuccessor( Reference< XConnectable > () );
+}
+
+
+void OPipeImpl::writeBytes(const Sequence< sal_Int8 >& aData)
+{
+ MutexGuard guard( m_mutexAccess );
+
+ if( m_bOutputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::writeBytes NotConnectedException (outputstream)",
+ *this );
+ }
+
+ if( m_bInputStreamClosed )
+ {
+ throw NotConnectedException(
+ "Pipe::writeBytes NotConnectedException (inputstream)",
+ *this );
+ }
+
+ // check skipping
+ sal_Int32 nLen = aData.getLength();
+ if( m_nBytesToSkip && m_nBytesToSkip >= nLen ) {
+ // all must be skipped - forget whole call
+ m_nBytesToSkip -= nLen;
+ return;
+ }
+
+ // adjust buffersize if necessary
+ if( m_nBytesToSkip )
+ {
+ Sequence< sal_Int8 > seqCopy( nLen - m_nBytesToSkip );
+ memcpy( seqCopy.getArray() , &( aData.getConstArray()[m_nBytesToSkip] ) , nLen-m_nBytesToSkip );
+ m_pFIFO->write( seqCopy );
+ }
+ else
+ {
+ m_pFIFO->write( aData );
+ }
+ m_nBytesToSkip = 0;
+
+ // readBytes may check again if enough bytes are available
+ m_conditionBytesAvail.set();
+}
+
+
+void OPipeImpl::flush()
+{
+ // nothing to do for a pipe
+}
+
+void OPipeImpl::closeOutput()
+{
+ MutexGuard guard( m_mutexAccess );
+
+ m_bOutputStreamClosed = true;
+ m_conditionBytesAvail.set();
+ setPredecessor( Reference < XConnectable > () );
+}
+
+
+void OPipeImpl::setSuccessor( const Reference < XConnectable > &r )
+{
+ /// if the references match, nothing needs to be done
+ if( m_succ != r ) {
+ /// store the reference for later use
+ m_succ = r;
+
+ if( m_succ.is() )
+ {
+ m_succ->setPredecessor(
+ Reference< XConnectable > ( static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+
+Reference < XConnectable > OPipeImpl::getSuccessor()
+{
+ return m_succ;
+}
+
+
+// XDataSource
+void OPipeImpl::setPredecessor( const Reference < XConnectable > &r )
+{
+ if( r != m_pred ) {
+ m_pred = r;
+ if( m_pred.is() ) {
+ m_pred->setSuccessor(
+ Reference < XConnectable > ( static_cast< XConnectable * >(this) ) );
+ }
+ }
+}
+
+Reference < XConnectable > OPipeImpl::getPredecessor()
+{
+ return m_pred;
+}
+
+
+// XServiceInfo
+OUString OPipeImpl::getImplementationName()
+{
+ return OPipeImpl_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool OPipeImpl::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OPipeImpl::getSupportedServiceNames()
+{
+ return OPipeImpl_getSupportedServiceNames();
+}
+
+/* implementation functions
+*
+*
+*/
+
+
+Reference < XInterface > OPipeImpl_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
+{
+ OPipeImpl *p = new OPipeImpl;
+
+ return Reference < XInterface > ( static_cast< OWeakObject * >(p) );
+}
+
+
+OUString OPipeImpl_getImplementationName()
+{
+ return IMPLEMENTATION_NAME;
+}
+
+Sequence<OUString> OPipeImpl_getSupportedServiceNames()
+{
+ Sequence<OUString> aRet { "com.sun.star.io.Pipe" };
+ return aRet;
+}
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/opump.cxx b/io/source/stm/opump.cxx
new file mode 100644
index 000000000..cba66d3c5
--- /dev/null
+++ b/io/source/stm/opump.cxx
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <sal/log.hxx>
+
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataControl.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/mutex.hxx>
+#include <osl/thread.h>
+#include <tools/diagnose_ex.h>
+
+using namespace osl;
+using namespace std;
+using namespace cppu;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::io;
+
+#include <services.hxx>
+
+namespace io_stm {
+
+ namespace {
+
+ class Pump : public WeakImplHelper<
+ XActiveDataSource, XActiveDataSink, XActiveDataControl, XConnectable, XServiceInfo >
+ {
+ Mutex m_aMutex;
+ oslThread m_aThread;
+
+ Reference< XConnectable > m_xPred;
+ Reference< XConnectable > m_xSucc;
+ Reference< XInputStream > m_xInput;
+ Reference< XOutputStream > m_xOutput;
+ OInterfaceContainerHelper m_cnt;
+ bool m_closeFired;
+
+ void run();
+ static void static_run( void* pObject );
+
+ void close();
+ void fireClose();
+ void fireStarted();
+ void fireTerminated();
+ void fireError( const Any &a );
+
+ public:
+ Pump();
+ virtual ~Pump() override;
+
+ // XActiveDataSource
+ virtual void SAL_CALL setOutputStream( const Reference< css::io::XOutputStream >& xOutput ) override;
+ virtual Reference< css::io::XOutputStream > SAL_CALL getOutputStream() override;
+
+ // XActiveDataSink
+ virtual void SAL_CALL setInputStream( const Reference< css::io::XInputStream >& xStream ) override;
+ virtual Reference< css::io::XInputStream > SAL_CALL getInputStream() override;
+
+ // XActiveDataControl
+ virtual void SAL_CALL addListener( const Reference< css::io::XStreamListener >& xListener ) override;
+ virtual void SAL_CALL removeListener( const Reference< css::io::XStreamListener >& xListener ) override;
+ virtual void SAL_CALL start() override;
+ virtual void SAL_CALL terminate() override;
+
+ // XConnectable
+ virtual void SAL_CALL setPredecessor( const Reference< css::io::XConnectable >& xPred ) override;
+ virtual Reference< css::io::XConnectable > SAL_CALL getPredecessor() override;
+ virtual void SAL_CALL setSuccessor( const Reference< css::io::XConnectable >& xSucc ) override;
+ virtual Reference< css::io::XConnectable > SAL_CALL getSuccessor() override;
+
+ public: // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ };
+
+ }
+
+Pump::Pump() : m_aThread( nullptr ),
+ m_cnt( m_aMutex ),
+ m_closeFired( false )
+{
+}
+
+Pump::~Pump()
+{
+ // exit gracefully
+ if( m_aThread )
+ {
+ osl_joinWithThread( m_aThread );
+ osl_destroyThread( m_aThread );
+ }
+}
+
+void Pump::fireError( const Any & exception )
+{
+ OInterfaceIteratorHelper iter( m_cnt );
+ while( iter.hasMoreElements() )
+ {
+ try
+ {
+ static_cast< XStreamListener * > ( iter.next() )->error( exception );
+ }
+ catch ( const RuntimeException & )
+ {
+ TOOLS_WARN_EXCEPTION("io.streams","com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners");
+ }
+ }
+}
+
+void Pump::fireClose()
+{
+ bool bFire = false;
+ {
+ MutexGuard guard( m_aMutex );
+ if( ! m_closeFired )
+ {
+ m_closeFired = true;
+ bFire = true;
+ }
+ }
+
+ if( !bFire )
+ return;
+
+ OInterfaceIteratorHelper iter( m_cnt );
+ while( iter.hasMoreElements() )
+ {
+ try
+ {
+ static_cast< XStreamListener * > ( iter.next() )->closed( );
+ }
+ catch ( const RuntimeException & )
+ {
+ TOOLS_WARN_EXCEPTION("io.streams","com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners");
+ }
+ }
+}
+
+void Pump::fireStarted()
+{
+ OInterfaceIteratorHelper iter( m_cnt );
+ while( iter.hasMoreElements() )
+ {
+ try
+ {
+ static_cast< XStreamListener * > ( iter.next() )->started( );
+ }
+ catch ( const RuntimeException & )
+ {
+ TOOLS_WARN_EXCEPTION("io.streams","com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners");
+ }
+ }
+}
+
+void Pump::fireTerminated()
+{
+ OInterfaceIteratorHelper iter( m_cnt );
+ while( iter.hasMoreElements() )
+ {
+ try
+ {
+ static_cast< XStreamListener * > ( iter.next() )->terminated();
+ }
+ catch ( const RuntimeException & )
+ {
+ TOOLS_WARN_EXCEPTION("io.streams","com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners");
+ }
+ }
+}
+
+
+void Pump::close()
+{
+ // close streams and release references
+ Reference< XInputStream > rInput;
+ Reference< XOutputStream > rOutput;
+ {
+ MutexGuard guard( m_aMutex );
+ rInput = m_xInput;
+ m_xInput.clear();
+
+ rOutput = m_xOutput;
+ m_xOutput.clear();
+ m_xSucc.clear();
+ m_xPred.clear();
+ }
+ if( rInput.is() )
+ {
+ try
+ {
+ rInput->closeInput();
+ }
+ catch( Exception & )
+ {
+ // go down calm
+ }
+ }
+ if( rOutput.is() )
+ {
+ try
+ {
+ rOutput->closeOutput();
+ }
+ catch( Exception & )
+ {
+ // go down calm
+ }
+ }
+}
+
+void Pump::static_run( void* pObject )
+{
+ osl_setThreadName("io_stm::Pump::run()");
+ static_cast<Pump*>(pObject)->run();
+ static_cast<Pump*>(pObject)->release();
+}
+
+void Pump::run()
+{
+ try
+ {
+ fireStarted();
+ try
+ {
+ Reference< XInputStream > rInput;
+ Reference< XOutputStream > rOutput;
+ {
+ Guard< Mutex > aGuard( m_aMutex );
+ rInput = m_xInput;
+ rOutput = m_xOutput;
+ }
+
+ if( ! rInput.is() )
+ {
+ throw NotConnectedException( "no input stream set", static_cast<OWeakObject*>(this) );
+ }
+ Sequence< sal_Int8 > aData;
+ while( rInput->readSomeBytes( aData, 65536 ) )
+ {
+ if( ! rOutput.is() )
+ {
+ throw NotConnectedException( "no output stream set", static_cast<OWeakObject*>(this) );
+ }
+ rOutput->writeBytes( aData );
+ osl_yieldThread();
+ }
+ }
+ catch ( const IOException & e )
+ {
+ fireError( makeAny( e ) );
+ }
+ catch ( const RuntimeException & e )
+ {
+ fireError( makeAny( e ) );
+ }
+ catch ( const Exception & e )
+ {
+ fireError( makeAny( e ) );
+ }
+
+ close();
+ fireClose();
+ }
+ catch ( const css::uno::Exception & )
+ {
+ // we are the last on the stack.
+ // this is to avoid crashing the program, when e.g. a bridge crashes
+ TOOLS_WARN_EXCEPTION("io.streams","com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners");
+ }
+}
+
+
+/*
+ * XConnectable
+ */
+
+void Pump::setPredecessor( const Reference< XConnectable >& xPred )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ m_xPred = xPred;
+}
+
+
+Reference< XConnectable > Pump::getPredecessor()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ return m_xPred;
+}
+
+
+void Pump::setSuccessor( const Reference< XConnectable >& xSucc )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ m_xSucc = xSucc;
+}
+
+
+Reference< XConnectable > Pump::getSuccessor()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ return m_xSucc;
+}
+
+
+/*
+ * XActiveDataControl
+ */
+
+void Pump::addListener( const Reference< XStreamListener >& xListener )
+{
+ m_cnt.addInterface( xListener );
+}
+
+
+void Pump::removeListener( const Reference< XStreamListener >& xListener )
+{
+ m_cnt.removeInterface( xListener );
+}
+
+
+void Pump::start()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ m_aThread = osl_createSuspendedThread(Pump::static_run,this);
+ if( !m_aThread )
+ {
+ throw RuntimeException(
+ "Pump::start Couldn't create worker thread",
+ *this);
+ }
+
+ // will be released by OPump::static_run
+ acquire();
+ osl_resumeThread( m_aThread );
+
+}
+
+
+void Pump::terminate()
+{
+ close();
+
+ // wait for the worker to die
+ if( m_aThread )
+ osl_joinWithThread( m_aThread );
+
+ fireTerminated();
+ fireClose();
+}
+
+
+/*
+ * XActiveDataSink
+ */
+
+void Pump::setInputStream( const Reference< XInputStream >& xStream )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ m_xInput = xStream;
+ Reference< XConnectable > xConnect( xStream, UNO_QUERY );
+ if( xConnect.is() )
+ xConnect->setSuccessor( this );
+ // data transfer starts in XActiveDataControl::start
+}
+
+
+Reference< XInputStream > Pump::getInputStream()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ return m_xInput;
+}
+
+
+/*
+ * XActiveDataSource
+ */
+
+void Pump::setOutputStream( const Reference< XOutputStream >& xOut )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ m_xOutput = xOut;
+ Reference< XConnectable > xConnect( xOut, UNO_QUERY );
+ if( xConnect.is() )
+ xConnect->setPredecessor( this );
+ // data transfer starts in XActiveDataControl::start
+}
+
+Reference< XOutputStream > Pump::getOutputStream()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ return m_xOutput;
+}
+
+// XServiceInfo
+OUString Pump::getImplementationName()
+{
+ return OPumpImpl_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool Pump::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > Pump::getSupportedServiceNames()
+{
+ return OPumpImpl_getSupportedServiceNames();
+}
+
+
+Reference< XInterface > OPumpImpl_CreateInstance(
+ SAL_UNUSED_PARAMETER const Reference< XComponentContext > & )
+{
+ return Reference< XInterface >( *new Pump );
+}
+
+OUString OPumpImpl_getImplementationName()
+{
+ return "com.sun.star.comp.io.Pump";
+}
+
+Sequence<OUString> OPumpImpl_getSupportedServiceNames()
+{
+ return Sequence< OUString > { "com.sun.star.io.Pump" };
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/streamhelper.cxx b/io/source/stm/streamhelper.cxx
new file mode 100644
index 000000000..4a2df5891
--- /dev/null
+++ b/io/source/stm/streamhelper.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <limits>
+#include <string.h>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <com/sun/star/io/BufferSizeExceededException.hpp>
+
+using namespace ::com::sun::star::uno;
+
+#include "streamhelper.hxx"
+
+namespace io_stm {
+
+void MemFIFO::write( const Sequence< sal_Int8 > &seq )
+{
+ writeAt(getSize(), seq);
+}
+
+void MemFIFO::read( Sequence<sal_Int8> &seq , sal_Int32 nBufferLen )
+{
+ readAt(0, seq , nBufferLen);
+ forgetFromStart( nBufferLen );
+}
+
+void MemFIFO::skip( sal_Int32 nBytesToSkip )
+{
+ forgetFromStart( nBytesToSkip );
+}
+
+MemRingBuffer::MemRingBuffer() : m_p(nullptr), m_nBufferLen(0), m_nStart(0), m_nOccupiedBuffer(0)
+{
+}
+
+MemRingBuffer::~MemRingBuffer()
+{
+ std::free( m_p );
+}
+
+void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize )
+{
+ sal_Int32 nNewLen = 1;
+
+ while( nMinSize > nNewLen ) {
+ nNewLen = nNewLen << 1;
+ }
+
+ // buffer never shrinks !
+ if( nNewLen < m_nBufferLen ) {
+ nNewLen = m_nBufferLen;
+ }
+
+ if( nNewLen == m_nBufferLen )
+ return;
+
+ auto p = static_cast<sal_Int8*>(std::realloc(m_p, nNewLen));
+ if (!p)
+ throw css::io::BufferSizeExceededException(
+ "MemRingBuffer::resizeBuffer BufferSizeExceededException");
+
+ m_p = p;
+
+
+ if( m_nStart + m_nOccupiedBuffer > m_nBufferLen ) {
+ memmove( &( m_p[m_nStart+(nNewLen-m_nBufferLen)]) , &(m_p[m_nStart]) , m_nBufferLen - m_nStart );
+ m_nStart += nNewLen - m_nBufferLen;
+ }
+ m_nBufferLen = nNewLen;
+}
+
+
+void MemRingBuffer::readAt( sal_Int32 nPos, Sequence<sal_Int8> &seq , sal_Int32 nBytesToRead ) const
+{
+ if( nPos + nBytesToRead > m_nOccupiedBuffer ) {
+ throw css::io::BufferSizeExceededException(
+ "MemRingBuffer::readAt BufferSizeExceededException");
+ }
+
+ sal_Int32 nStartReadingPos = nPos + m_nStart;
+ if( nStartReadingPos >= m_nBufferLen ) {
+ nStartReadingPos -= m_nBufferLen;
+ }
+
+ seq.realloc( nBytesToRead );
+
+ if( nStartReadingPos + nBytesToRead > m_nBufferLen ) {
+ sal_Int32 nDeltaLen = m_nBufferLen - nStartReadingPos;
+ memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nDeltaLen );
+ memcpy( &(seq.getArray()[nDeltaLen]), m_p , nBytesToRead - nDeltaLen );
+ }
+ else {
+ memcpy( seq.getArray() , &(m_p[nStartReadingPos]) , nBytesToRead );
+ }
+}
+
+
+void MemRingBuffer::writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &seq )
+{
+ checkInvariants();
+ const sal_Int32 nLen = seq.getLength();
+
+ if( nPos < 0 || nPos > std::numeric_limits< sal_Int32 >::max() - nLen )
+ {
+ throw css::io::BufferSizeExceededException(
+ "MemRingBuffer::writeAt BufferSizeExceededException");
+ }
+
+ if( nPos + nLen - m_nOccupiedBuffer > 0 ) {
+ resizeBuffer( nPos + nLen );
+ m_nOccupiedBuffer = nPos + nLen;
+ }
+
+ sal_Int32 nStartWritingIndex = m_nStart + nPos;
+ if( nStartWritingIndex >= m_nBufferLen ) {
+ nStartWritingIndex -= m_nBufferLen;
+ }
+
+ if( const sal_Int32 nBufferRestLen = m_nBufferLen-nStartWritingIndex; nLen > nBufferRestLen ) {
+ // two area copy
+ memcpy( &(m_p[nStartWritingIndex]) , seq.getConstArray(), nBufferRestLen );
+ memcpy( m_p , &( seq.getConstArray()[nBufferRestLen] ), nLen - nBufferRestLen );
+
+ }
+ else {
+ // one area copy
+ memcpy( &( m_p[nStartWritingIndex]), seq.getConstArray() , nLen );
+ }
+ checkInvariants();
+}
+
+
+sal_Int32 MemRingBuffer::getSize() const throw()
+{
+ return m_nOccupiedBuffer;
+}
+
+void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget )
+{
+ checkInvariants();
+ if( nBytesToForget > m_nOccupiedBuffer ) {
+ throw css::io::BufferSizeExceededException(
+ "MemRingBuffer::forgetFromStart BufferSizeExceededException");
+ }
+ m_nStart += nBytesToForget;
+ if( m_nStart >= m_nBufferLen ) {
+ m_nStart = m_nStart - m_nBufferLen;
+ }
+ m_nOccupiedBuffer -= nBytesToForget;
+ checkInvariants();
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/source/stm/streamhelper.hxx b/io/source/stm/streamhelper.hxx
new file mode 100644
index 000000000..c1bb1b7db
--- /dev/null
+++ b/io/source/stm/streamhelper.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_IO_SOURCE_STM_STREAMHELPER_HXX
+#define INCLUDED_IO_SOURCE_STM_STREAMHELPER_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <assert.h>
+
+using namespace com::sun::star::uno;
+
+namespace io_stm
+{
+
+class MemRingBuffer
+{
+public:
+ MemRingBuffer();
+ virtual ~MemRingBuffer();
+
+ /***
+ * overwrites data at given position. Size is automatically extended, when
+ * data is written beyond end.
+ ***/
+ /// @throws css::io::BufferSizeExceededException
+ void writeAt( sal_Int32 nPos, const Sequence<sal_Int8> &);
+ /// @throws css::io::BufferSizeExceededException
+ void readAt( sal_Int32 nPos, Sequence<sal_Int8> & , sal_Int32 nBytesToRead ) const;
+ sal_Int32 getSize() const throw();
+ /// @throws css::io::BufferSizeExceededException
+ void forgetFromStart(sal_Int32 nBytesToForget);
+
+private:
+ /// @throws css::io::BufferSizeExceededException
+ void resizeBuffer(sal_Int32 nMinSize);
+ void checkInvariants() const {
+ assert( m_nBufferLen >= 0 );
+ assert( m_nOccupiedBuffer >= 0 );
+ assert( m_nOccupiedBuffer <= m_nBufferLen );
+ assert( m_nStart >= 0 );
+ assert( 0 == m_nStart || m_nStart < m_nBufferLen );
+ (void) this; // avoid loplugin:staticmethods
+ }
+
+ sal_Int8 *m_p;
+ sal_Int32 m_nBufferLen;
+ sal_Int32 m_nStart;
+ sal_Int32 m_nOccupiedBuffer;
+};
+
+
+class MemFIFO :
+ private MemRingBuffer
+{
+public:
+ /// @throws css::io::BufferSizeExceededException
+ void write( const Sequence<sal_Int8> &);
+ /// @throws css::io::BufferSizeExceededException
+ void read( Sequence<sal_Int8> & , sal_Int32 nBytesToRead );
+ /// @throws css::io::BufferSizeExceededException
+ void skip( sal_Int32 nBytesToSkip );
+ sal_Int32 getSize() const throw()
+ { return MemRingBuffer::getSize(); }
+
+};
+
+}
+
+#endif // INCLUDED_IO_SOURCE_STM_STREAMHELPER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/makefile.mk b/io/test/makefile.mk
new file mode 100644
index 000000000..c1d2c9649
--- /dev/null
+++ b/io/test/makefile.mk
@@ -0,0 +1,83 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+PRJ=..
+
+PRJNAME=extensions
+TARGET=workben
+LIBTARGET=NO
+
+TARGETTYPE=CUI
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.IF "$(L10N_framework)"==""
+# --- Files --------------------------------------------------------
+
+OBJFILES= $(OBJ)$/testcomponent.obj \
+ $(OBJ)$/testconnection.obj
+
+UNOUCRDEP=$(SOLARBINDIR)$/udkapi.rdb
+UNOUCRRDB=$(SOLARBINDIR)$/udkapi.rdb
+
+# output directory (one dir for each project)
+UNOUCROUT=$(OUT)$/inc
+
+UNOTYPES = com.sun.star.connection.XConnector \
+ com.sun.star.connection.XAcceptor \
+ com.sun.star.registry.XImplementationRegistration \
+ com.sun.star.lang.XComponent \
+ com.sun.star.lang.XSingleServiceFactory \
+ com.sun.star.lang.XMultiServiceFactory \
+ com.sun.star.test.XSimpleTest \
+ com.sun.star.lang.XSingleComponentFactory \
+ com.sun.star.lang.XMultiComponentFactory
+
+
+#
+# std testcomponent
+#
+
+APP1TARGET = testcomponent
+APP1OBJS = $(OBJ)$/testcomponent.obj
+APP1STDLIBS = $(SALLIB) \
+ $(CPPULIB)\
+ $(CPPUHELPERLIB)
+
+APP2TARGET = testconnection
+APP2OBJS = $(OBJ)$/testconnection.obj
+APP2STDLIBS = $(SALLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)
+
+
+
+# --- Targets ------------------------------------------------------
+
+ALL : $(BIN)$/applicat.rdb \
+ ALLTAR
+
+$(BIN)$/applicat.rdb: $(SOLARBINDIR)$/udkapi.rdb
+ rm -f $@
+ regmerge $@ / $?
+
+.ENDIF # L10N_framework
+
+.INCLUDE : target.mk
diff --git a/io/test/stm/datatest.cxx b/io/test/stm/datatest.cxx
new file mode 100644
index 000000000..a085bf6d7
--- /dev/null
+++ b/io/test/stm/datatest.cxx
@@ -0,0 +1,1074 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stdio.h>
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XObjectInputStream.hpp>
+#include <com/sun/star/io/XObjectOutputStream.hpp>
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <osl/conditn.hxx>
+
+#include <string.h>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+using namespace ::com::sun::star::beans;
+// streams
+
+#include "testfactreg.hxx"
+
+#define DATASTREAM_TEST_MAX_HANDLE 1
+
+/*
+ * The following test class tests XDataInputStream and XDataOutputStream at equal terms,
+ * so when errors occur, it may be in either one implementation.
+ * The class also uses com.sun.star.io.pipe. If problems occur, make sure to run also the
+ * pipe test routines ( test.com.sun.star.io.pipe ).
+ */
+
+class ODataStreamTest :
+ public WeakImplHelper< XSimpleTest >
+{
+public:
+ explicit ODataStreamTest( const Reference < XMultiServiceFactory > & rFactory ) :
+ m_rFactory( rFactory )
+ {}
+
+public:
+ virtual void SAL_CALL testInvariant(const OUString& TestName, const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Int32 SAL_CALL test( const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Bool SAL_CALL testPassed() throw ( RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getErrors() throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getErrorExceptions() throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings() throw (RuntimeException);
+
+private:
+ void testSimple( const Reference < XDataInputStream > & , const Reference < XDataOutputStream > &);
+
+protected:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+
+ Reference < XMultiServiceFactory > m_rFactory;
+};
+
+
+void ODataStreamTest::testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException,
+ RuntimeException)
+{
+ if( OUString("com.sun.star.io.DataInputStream") == TestName ) {
+ Reference < XConnectable > connect( TestObject , UNO_QUERY );
+ Reference < XActiveDataSink > active( TestObject , UNO_QUERY );
+ Reference < XInputStream > input( TestObject , UNO_QUERY );
+ Reference < XDataInputStream > dataInput( TestObject , UNO_QUERY );
+
+ WARNING_ASSERT( connect.is(), "XConnectable cannot be queried" );
+ WARNING_ASSERT( active.is() , "XActiveDataSink cannot be queried" );
+ ERROR_ASSERT( input.is() , "XInputStream cannot be queried" );
+ ERROR_ASSERT( dataInput.is() , "XDataInputStream cannot be queried" );
+
+
+ }
+ else if( OUString("com.sun.star.io.DataOutputStream") == TestName ) {
+ Reference < XConnectable > connect( TestObject , UNO_QUERY );
+ Reference < XActiveDataSource > active( TestObject , UNO_QUERY );
+ Reference < XOutputStream > output( TestObject , UNO_QUERY );
+ Reference < XDataOutputStream > dataOutput( TestObject , UNO_QUERY );
+
+ WARNING_ASSERT( connect.is(), "XConnectable cannot be queried" );
+ WARNING_ASSERT( active.is() , "XActiveDataSink cannot be queried" );
+ ERROR_ASSERT( output.is() , "XInputStream cannot be queried" );
+ ERROR_ASSERT( dataOutput.is(), "XDataInputStream cannot be queried" );
+
+ }
+
+ Reference < XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT( ! info->supportsService("bla bluzb") , "XServiceInfo test failed" );
+ }
+
+}
+
+
+sal_Int32 ODataStreamTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException)
+{
+ if( OUString("com.sun.star.io.DataInputStream") == TestName ||
+ OUString("com.sun.star.io.DataOutputStream") == TestName ) {
+
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else {
+ Reference <XActiveDataSink > rSink( TestObject, UNO_QUERY );
+ Reference <XActiveDataSource > rSource( TestObject , UNO_QUERY );
+
+ Reference < XDataInputStream > rInput( TestObject , UNO_QUERY );
+ Reference < XDataOutputStream > rOutput( TestObject , UNO_QUERY );
+
+
+ Reference < XInterface > x = m_rFactory->createInstance(
+ "com.sun.star.io.Pipe" );
+
+ Reference < XInputStream > rPipeInput( x , UNO_QUERY );
+ Reference < XOutputStream > rPipeOutput( x , UNO_QUERY );
+
+ if( ! rSink.is() ) {
+ x = m_rFactory->createInstance(
+ "com.sun.star.io.DataInputStream" );
+ rInput.set( x , UNO_QUERY);
+ rSink.set( x , UNO_QUERY );
+ }
+ else if ( !rSource.is() )
+ {
+ x = m_rFactory->createInstance(
+ "com.sun.star.io.DataOutputStream" );
+ rOutput.set( x , UNO_QUERY );
+ rSource.set( x, UNO_QUERY );
+ }
+
+ OSL_ASSERT( rPipeInput.is() );
+ OSL_ASSERT( rPipeOutput.is() );
+ rSink->setInputStream( rPipeInput );
+ rSource->setOutputStream( rPipeOutput );
+
+ OSL_ASSERT( rSink->getInputStream().is() );
+ OSL_ASSERT( rSource->getOutputStream().is() );
+
+ if( 1 == hTestHandle ) {
+ testSimple( rInput , rOutput );
+ }
+ }
+ }
+ catch( const Exception & e )
+ {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( hTestHandle >= 2) {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ BUILD_ERROR( 0 , "service not supported by test." );
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool ODataStreamTest::testPassed() throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > ODataStreamTest::getErrors() throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > ODataStreamTest::getErrorExceptions() throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > ODataStreamTest::getWarnings() throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+void ODataStreamTest::testSimple( const Reference < XDataInputStream > &rInput,
+ const Reference < XDataOutputStream > &rOutput )
+{
+ rOutput->writeLong( 0x34ff3c );
+ rOutput->writeLong( 0x34ff3d );
+ rOutput->writeLong( -1027 );
+
+ ERROR_ASSERT( 0x34ff3c == rInput->readLong() , "long read/write mismatch" );
+ ERROR_ASSERT( 0x34ff3d == rInput->readLong() , "long read/write mismatch" );
+ ERROR_ASSERT( -1027 == rInput->readLong() , "long read/write mismatch" );
+
+ rOutput->writeByte( 0x77 );
+ ERROR_ASSERT( 0x77 == rInput->readByte() , "byte read/write mismatch" );
+
+ rOutput->writeBoolean( 25 );
+ ERROR_ASSERT( rInput->readBoolean() , "boolean read/write mismatch" );
+
+ rOutput->writeBoolean( sal_False );
+ ERROR_ASSERT( ! rInput->readBoolean() , "boolean read/write mismatch" );
+
+ rOutput->writeFloat( (float) 42.42 );
+ ERROR_ASSERT( rInput->readFloat() == ((float)42.42) , "float read/write mismatch" );
+
+ rOutput->writeDouble( (double) 42.42 );
+ ERROR_ASSERT( rInput->readDouble() == 42.42 , "double read/write mismatch" );
+
+ rOutput->writeHyper( 0x123456789abcdefLL );
+ ERROR_ASSERT( rInput->readHyper() == 0x123456789abcdefLL , "int64 read/write mismatch" );
+
+ rOutput->writeUTF( OUString("Live long and prosper !") );
+ ERROR_ASSERT( rInput->readUTF() == "Live long and prosper !",
+ "UTF read/write mismatch" );
+
+ Sequence<sal_Unicode> wc(0x10001);
+ for( int i = 0 ; i < 0x10000 ; i ++ ) {
+ wc.getArray()[i] = L'c';
+ }
+ wc.getArray()[0x10000] = 0;
+ OUString str( wc.getArray() , 0x10000 );
+ rOutput->writeUTF( str );
+ ERROR_ASSERT( rInput->readUTF() == str , "error reading 64k block" );
+
+ rOutput->closeOutput();
+ try
+ {
+ rInput->readLong();
+ ERROR_ASSERT( 0 , "eof-exception does not occur !" );
+ }
+ catch ( IOException & )
+ {
+ //ok
+ }
+ catch( ... )
+ {
+ ERROR_ASSERT( 0 , "wrong exception after reading beyond eof" );
+ }
+
+ Sequence<sal_Int8> dummy (1);
+ ERROR_ASSERT( ! rInput->readBytes( dummy , 1 ),
+ "stream must be on eof !" );
+
+ rInput->closeInput();
+
+ try
+ {
+ rOutput->writeByte( 1 );
+ ERROR_ASSERT( 0 , "writing still possible though chain must be interrupted" );
+ }
+ catch( IOException & )
+ {
+ // ok
+ }
+ catch( ... ) {
+ ERROR_ASSERT( 0 , "IOException expected, but another exception was thrown" );
+ }
+
+}
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL ODataStreamTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw(Exception)
+{
+ ODataStreamTest *p = new ODataStreamTest( rSMgr );
+ return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
+}
+
+Sequence<OUString> ODataStreamTest_getSupportedServiceNames( int i) throw ()
+{
+ Sequence<OUString> aRet { ODataStreamTest_getImplementationName( i) };
+ return aRet;
+}
+
+OUString ODataStreamTest_getServiceName( int i) throw ()
+{
+ if( 1 == i ) {
+ return OUString( "test.com.sun.star.io.DataInputStream" );
+ }
+ else {
+ return OUString( "test.com.sun.star.io.DataOutputStream" );
+ }
+}
+
+OUString ODataStreamTest_getImplementationName( int i) throw ()
+{
+ if( 1 == i ) {
+ return OUString(
+ "test.com.sun.star.comp.extensions.stm.DataInputStream" );
+ }
+ else {
+ return OUString( "test.com.sun.star.comp.extensions.stm.DataOutputStream" );
+ }
+}
+
+class MyPersistObject : public WeakImplHelper< XPersistObject , XPropertySet >
+{
+public:
+ MyPersistObject( ) : m_sServiceName( OMyPersistObject_getServiceName() ) ,
+ m_l( -392 ),
+ m_f( 7883.2 ),
+ m_d( -123923.5 ),
+ m_b( sal_True ),
+ m_byte( 42 ),
+ m_c( 429 ),
+ m_s( OUString( "foo" ) )
+ {}
+ explicit MyPersistObject( const OUString & sServiceName ) : m_sServiceName( sServiceName )
+ {}
+
+
+public:
+ virtual OUString SAL_CALL getServiceName() throw (RuntimeException);
+ virtual void SAL_CALL write( const Reference< XObjectOutputStream >& OutStream )
+ throw (IOException, RuntimeException);
+ virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream)
+ throw (IOException, RuntimeException);
+
+public:
+
+ virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo()
+ throw (RuntimeException);
+
+ virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue)
+ throw ( UnknownPropertyException,
+ PropertyVetoException,
+ IllegalArgumentException,
+ WrappedTargetException,
+ RuntimeException);
+ virtual Any SAL_CALL getPropertyValue(const OUString& PropertyName)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener(
+ const OUString& aPropertyName,
+ const Reference < XPropertyChangeListener > & xListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException);
+
+ virtual void SAL_CALL removePropertyChangeListener(
+ const OUString& aPropertyName,
+ const Reference< XPropertyChangeListener > & aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener(
+ const OUString& PropertyName,
+ const Reference< XVetoableChangeListener > & aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException);
+
+ virtual void SAL_CALL removeVetoableChangeListener(
+ const OUString& PropertyName,
+ const Reference< XVetoableChangeListener >& aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException);
+
+public:
+ sal_Int32 m_l;
+ float m_f;
+ double m_d;
+ sal_Bool m_b;
+ sal_Int8 m_byte;
+ sal_Unicode m_c;
+ OUString m_s;
+ Reference< XPersistObject > m_ref;
+ OUString m_sServiceName;
+};
+
+
+Reference <XPropertySetInfo > MyPersistObject::getPropertySetInfo()
+ throw (RuntimeException)
+{
+ return Reference< XPropertySetInfo >();
+}
+
+void MyPersistObject::setPropertyValue(
+ const OUString& aPropertyName,
+ const Any& aValue)
+ throw ( UnknownPropertyException,
+ PropertyVetoException,
+ IllegalArgumentException,
+ WrappedTargetException,
+ RuntimeException)
+{
+ if( aPropertyName.equalsAscii("long") ) {
+ aValue >>= m_l;
+ }
+ else if ( aPropertyName.equalsAscii("float") ) {
+ aValue >>= m_f;
+ }
+ else if( aPropertyName.equalsAscii("double") ) {
+ aValue >>= m_d;
+ }
+ else if( aPropertyName.equalsAscii("bool") ) {
+ aValue >>= m_b;
+ }
+ else if( aPropertyName.equalsAscii("byte" ) ) {
+ aValue >>= m_byte;
+ }
+ else if( aPropertyName.equalsAscii("char") ) {
+ aValue >>= m_c;
+ }
+ else if( aPropertyName.equalsAscii("string") ) {
+ aValue >>= m_s;
+ }
+ else if( aPropertyName.equalsAscii("object") ) {
+ if( aValue.getValueType() == cppu::UnoType<XPersistObject>::get())
+ {
+ aValue >>= m_ref;
+ }
+ else
+ {
+ m_ref = 0;
+ }
+ }
+}
+
+
+Any MyPersistObject::getPropertyValue(const OUString& aPropertyName)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException)
+{
+ Any aValue;
+ if( aPropertyName.equalsAscii("long" ) ) {
+ aValue <<= m_l;
+ }
+ else if ( aPropertyName.equalsAscii("float") ) {
+ aValue <<= m_f;
+ }
+ else if( aPropertyName.equalsAscii("double") ) {
+ aValue <<= m_d;
+ }
+ else if( aPropertyName.equalsAscii("bool") ) {
+ aValue <<= m_b;
+ }
+ else if( aPropertyName.equalsAscii("byte") ) {
+ aValue <<= m_byte;
+ }
+ else if( aPropertyName.equalsAscii("char" ) ) {
+ aValue <<= m_c;
+ }
+ else if( aPropertyName.equalsAscii("string") ) {
+ aValue <<= m_s;
+ }
+ else if( aPropertyName.equalsAscii("object" ) )
+ {
+ aValue <<= m_ref;
+ }
+ return aValue;
+}
+
+
+void MyPersistObject::addPropertyChangeListener(
+ const OUString& aPropertyName,
+ const Reference< XPropertyChangeListener > & xListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException)
+{
+
+}
+
+void MyPersistObject::removePropertyChangeListener(
+ const OUString& aPropertyName,
+ const Reference < XPropertyChangeListener > & aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException)
+{
+}
+
+
+void MyPersistObject::addVetoableChangeListener(
+ const OUString& PropertyName,
+ const Reference <XVetoableChangeListener >& aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException)
+{
+
+}
+
+void MyPersistObject::removeVetoableChangeListener(
+ const OUString& PropertyName,
+ const Reference < XVetoableChangeListener > & aListener)
+ throw ( UnknownPropertyException,
+ WrappedTargetException,
+ RuntimeException)
+{
+
+}
+
+
+OUString MyPersistObject::getServiceName() throw (RuntimeException)
+{
+ return m_sServiceName;
+}
+
+void MyPersistObject::write( const Reference< XObjectOutputStream > & rOut )
+ throw (IOException,RuntimeException)
+{
+ rOut->writeLong( m_l);
+ rOut->writeFloat( m_f );
+ rOut->writeDouble( m_d );
+ rOut->writeBoolean( m_b );
+ rOut->writeByte( m_byte );
+ rOut->writeChar( m_c );
+ rOut->writeUTF( m_s );
+ rOut->writeObject( m_ref );
+}
+
+
+void MyPersistObject::read( const Reference< XObjectInputStream > & rIn )
+ throw (IOException, RuntimeException)
+{
+ m_l = rIn->readLong();
+ m_f = rIn->readFloat();
+ m_d = rIn->readDouble();
+ m_b = rIn->readBoolean();
+ m_byte = rIn->readByte();
+ m_c = rIn->readChar();
+ m_s = rIn->readUTF();
+ m_ref = rIn->readObject();
+}
+
+Reference < XInterface > SAL_CALL OMyPersistObject_CreateInstance(
+ const Reference < XMultiServiceFactory > & rSMgr )
+ throw(Exception)
+{
+ MyPersistObject *p = new MyPersistObject( );
+ return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
+}
+
+Sequence<OUString> OMyPersistObject_getSupportedServiceNames( ) throw ()
+{
+ Sequence<OUString> aRet { OMyPersistObject_getImplementationName() };
+ return aRet;
+}
+
+OUString OMyPersistObject_getServiceName( ) throw ()
+{
+ return OUString( "test.com.sun.star.io.PersistTest" );
+}
+
+OUString OMyPersistObject_getImplementationName( ) throw ()
+{
+ return OUString( "test.com.sun.star.io.PersistTest" );
+}
+
+class OObjectStreamTest :
+ public ODataStreamTest
+{
+public:
+ explicit OObjectStreamTest( const Reference < XMultiServiceFactory > &r) : ODataStreamTest(r) {}
+
+public:
+ virtual void SAL_CALL testInvariant(const OUString& TestName,
+ const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Int32 SAL_CALL test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+
+private:
+ void testObject( const Reference <XObjectOutputStream > &rOut,
+ const Reference <XObjectInputStream> &rIn );
+
+private:
+};
+
+
+void OObjectStreamTest::testInvariant( const OUString& TestName,
+ const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException, RuntimeException)
+{
+
+ if( OUString( "com.sun.star.io.ObjectInputStream" )
+ == TestName )
+ {
+ ODataStreamTest::testInvariant( TestName , TestObject );
+ Reference< XObjectInputStream > dataInput( TestObject , UNO_QUERY );
+ Reference< XMarkableStream > markable( TestObject , UNO_QUERY );
+ ERROR_ASSERT( dataInput.is() , "XObjectInputStream cannot be queried" );
+ ERROR_ASSERT( markable.is() , "XMarkableStream cannot be queried" );
+ }
+ else if( OUString( "com.sun.star.io.ObjectOutputStream" )
+ == TestName )
+ {
+ ODataStreamTest::testInvariant( TestName , TestObject );
+ Reference < XMarkableStream > markable( TestObject , UNO_QUERY );
+ Reference < XObjectOutputStream > dataOutput( TestObject , UNO_QUERY );
+ ERROR_ASSERT( dataOutput.is(), "XObjectOutputStream cannot be queried" );
+ ERROR_ASSERT( markable.is() , "XMarkableStream cannot be queried" );
+ }
+
+ Reference < XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT( ! info->supportsService("bla bluzb") , "XServiceInfo test failed" );
+ }
+
+}
+
+sal_Int32 OObjectStreamTest::test( const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException)
+{
+ if( TestName.equalsAscii("com.sun.star.io.ObjectInputStream") ||
+ TestName.equalsAscii("com.sun.star.io.ObjectOutputStream") ) {
+
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else if( DATASTREAM_TEST_MAX_HANDLE >= hTestHandle ) {
+ sal_Int32 hOldHandle = hTestHandle;
+ hTestHandle = ODataStreamTest::test(
+ OUString( "com.sun.star.io.DataInputStream" ),
+ TestObject , hTestHandle );
+ if( hTestHandle == -1 ){
+ hTestHandle = hOldHandle;
+ }
+ }
+ else {
+
+ Reference<XActiveDataSink > rSink( TestObject, UNO_QUERY );
+ Reference<XActiveDataSource > rSource( TestObject , UNO_QUERY );
+
+ Reference< XObjectInputStream > rInput( TestObject , UNO_QUERY );
+ Reference< XObjectOutputStream > rOutput( TestObject , UNO_QUERY );
+
+
+ Reference < XInterface > x = m_rFactory->createInstance(
+ "com.sun.star.io.Pipe" );
+
+ Reference <XInputStream > rPipeInput( x , UNO_QUERY );
+ Reference <XOutputStream > rPipeOutput( x , UNO_QUERY );
+
+ x = m_rFactory->createInstance(
+ "com.sun.star.io.MarkableInputStream" );
+
+ Reference <XInputStream > markableInput( x , UNO_QUERY );
+ Reference <XActiveDataSink> markableSink( x , UNO_QUERY );
+
+ x = m_rFactory->createInstance( "com.sun.star.io.MarkableOutputStream" );
+ Reference <XOutputStream > markableOutput( x , UNO_QUERY );
+ Reference <XActiveDataSource > markableSource( x , UNO_QUERY );
+
+ OSL_ASSERT( markableInput.is() );
+ OSL_ASSERT( markableOutput.is() );
+ OSL_ASSERT( markableSink.is() );
+ OSL_ASSERT( markableSource.is() );
+
+ markableSink->setInputStream( rPipeInput );
+ markableSource->setOutputStream( rPipeOutput );
+
+ if( ! rSink.is() ) {
+ x = m_rFactory->createInstance(
+ "com.sun.star.io.ObjectInputStream" );
+ rInput.set( x , UNO_QUERY );
+ rSink.set( x , UNO_QUERY );
+ }
+ else if ( !rSource.is() ) {
+ x = m_rFactory->createInstance(
+ "com.sun.star.io.ObjectOutputStream" );
+ rOutput.set( x , UNO_QUERY );
+ rSource.set( x, UNO_QUERY );
+ }
+
+ OSL_ASSERT( rPipeInput.is() );
+ OSL_ASSERT( rPipeOutput.is() );
+
+ rSink->setInputStream( markableInput );
+ rSource->setOutputStream( markableOutput );
+
+ OSL_ASSERT( rSink->getInputStream().is() );
+ OSL_ASSERT( rSource->getOutputStream().is() );
+
+ if( 1 + DATASTREAM_TEST_MAX_HANDLE == hTestHandle ) {
+ testObject( rOutput , rInput);
+ }
+ rInput->closeInput();
+ rOutput->closeOutput();
+
+ }
+ }
+ catch( const Exception &e ) {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... ) {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( hTestHandle > 1 +DATASTREAM_TEST_MAX_HANDLE ) {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ BUILD_ERROR( 0 , "service not supported by test." );
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool compareMyPropertySet( Reference< XPropertySet > &r1 , Reference < XPropertySet > &r2 )
+{
+ sal_Bool b = sal_True;
+
+ if( r1->getPropertyValue("long").getValueType() == cppu::UnoType<void>::get() ||
+ r2->getPropertyValue("long").getValueType() == cppu::UnoType<void>::get() ) {
+
+ // one of the objects is not the correct propertyset !
+ fprintf( stderr, "compareMyPropertySet: 1\n" );
+ return sal_False;
+ }
+
+ b = b && ( r1->getPropertyValue("long") ==
+ r2->getPropertyValue("long") );
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 2\n" );
+
+ b = b && ( r1->getPropertyValue("float") ==
+ r2->getPropertyValue("float") );
+ if( ! b ){
+ float f1(0.0);
+ float f2(0.0);
+ r1->getPropertyValue("float") >>= f1;
+ r2->getPropertyValue("float") >>= f2;
+ fprintf( stderr, "compareMyPropertySet: %f %f 3\n",f1,f2 );
+ }
+
+ b = b && ( r1->getPropertyValue("double") ==
+ r2->getPropertyValue("double") );
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 4\n" );
+
+ sal_Bool b1(sal_False), b2(sal_False);
+ Any a =r1->getPropertyValue("bool");
+ a >>= b1;
+ a = r2->getPropertyValue("bool");
+ a >>= b2;
+ b = b && ( (b1 && b2) || b1 == b2 );
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 5\n" );
+
+// b = b && r1->getPropertyValue("bool") ==
+// r2->getPropertyValue("bool") );
+
+ b = b && ( r1->getPropertyValue("byte") ==
+ r2->getPropertyValue("byte") );
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 6\n" );
+
+ b = b && ( r1->getPropertyValue("char") ==
+ r2->getPropertyValue("char") );
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 7\n" );
+
+ b = b && ( r1->getPropertyValue("string") ==
+ r2->getPropertyValue("string"));
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 8\n" );
+
+ Any o1 = r1->getPropertyValue("object");
+ Any o2 = r2->getPropertyValue("object");
+
+ if( o1.getValueType() == cppu::UnoType<XPersistObject>::get()) {
+
+ if( o2.getValueType() == cppu::UnoType<XPersistObject>::get()) {
+ Reference < XPersistObject > rPersist1;
+ Reference < XPersistObject > rPersist2;
+ o1 >>= rPersist1;
+ o2 >>= rPersist2;
+ Reference <XPropertySet > rProp1( rPersist1 , UNO_QUERY );
+ Reference < XPropertySet > rProp2( rPersist2 , UNO_QUERY );
+
+ if( rProp1.is() && rProp2.is() && ! ( rProp1 == rProp2 )
+ &&( rProp1 != r1 )) {
+ b = b && compareMyPropertySet( rProp1 , rProp2 );
+ }
+ }
+ else {
+ b = sal_False;
+ }
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 9\n" );
+ }
+ else {
+ if( o2.getValueType() == cppu::UnoType<XPersistObject>::get()) {
+ b = sal_False;
+ }
+ if( ! b ) fprintf( stderr, "compareMyPropertySet: 10\n" );
+ }
+
+ return b;
+}
+
+void OObjectStreamTest::testObject( const Reference< XObjectOutputStream > &rOut,
+ const Reference < XObjectInputStream > &rIn )
+{
+ ERROR_ASSERT( rOut.is() , "no objectOutputStream" );
+ ERROR_ASSERT( rIn.is() , "no objectInputStream" );
+
+
+ // tests, if saving an object with an unknown service name allows
+ // reading the data behind the object !
+ {
+ Reference < XInterface > x = * new MyPersistObject(
+ OUString( "bla blubs") );
+
+ Reference< XPersistObject > persistRef( x , UNO_QUERY );
+ ERROR_ASSERT( persistRef.is() , "couldn't instantiate PersistTest object" );
+
+ rOut->writeObject( persistRef );
+ rOut->writeLong( (sal_Int32) 0xdeadbeef );
+
+ ERROR_ASSERT( 0 != rIn->available() , "no data arrived at input" );
+
+ try
+ {
+ Reference <XPersistObject > xReadPersistRef = rIn->readObject();
+ ERROR_ASSERT( 0 , "expected exception not thrown" );
+ }
+ catch( IOException & )
+ {
+ // all is ok
+ }
+
+ ERROR_ASSERT( (sal_Int32) 0xdeadbeef == rIn->readLong() ,
+ "wrong data after object with unknown service name." );
+ }
+
+ {
+ Reference < XInterface > x = m_rFactory->createInstance(
+ "test.com.sun.star.io.PersistTest");
+ Reference< XPersistObject > persistRef( x , UNO_QUERY );
+
+ ERROR_ASSERT( persistRef.is() , "couldn't instantiate PersistTest object" );
+
+ Reference < XPropertySet > rProp( persistRef , UNO_QUERY );
+ ERROR_ASSERT( rProp.is() , "test object is no property set " );
+
+ Any any;
+ sal_Int32 i = 0x83482;
+ any <<= i;
+ rProp->setPropertyValue("long", any );
+
+ float f = (float)42.23;
+ any <<= f;
+ rProp->setPropertyValue("float", any );
+
+ double d = 233.321412;
+ any <<= d;
+ rProp->setPropertyValue("double", any );
+
+ sal_Bool b = sal_True;
+ any.setValue( &b , cppu::UnoType<bool>::get() );
+ rProp->setPropertyValue("bool", any );
+
+ sal_Int8 by = 120;
+ any <<= by;
+ rProp->setPropertyValue("byte", any );
+
+ sal_Unicode c = 'h';
+ any.setValue( &c , cppu::UnoType<cppu::UnoCharType>::get() );
+ rProp->setPropertyValue("char", any );
+
+ OUString str( "hi du !" );
+ any <<= str;
+ rProp->setPropertyValue("string", any );
+
+ any <<= persistRef;
+ rProp->setPropertyValue("object", any );
+
+ // do read and write
+ rOut->writeObject( persistRef );
+ ERROR_ASSERT( 0 != rIn->available() , "no data arrived at input" );
+ Reference< XPersistObject > xReadPersist = rIn->readObject( );
+
+ Reference< XPropertySet > rPropRead( xReadPersist , UNO_QUERY );
+ ERROR_ASSERT( compareMyPropertySet( rProp , rPropRead ) , "objects has not been read properly !" );
+
+ // destroy selfreferences
+ rProp->setPropertyValue("object", Any() );
+ rPropRead->setPropertyValue("object", Any() );
+ }
+
+ {
+ Reference< XMarkableStream > markableOut( rOut , UNO_QUERY );
+ ERROR_ASSERT( markableOut.is() , "markable stream cannot be queried" );
+
+ // do the same thing multiple times to check if
+ // buffering and marks work correctly
+ for( int i = 0 ; i < 2000 ; i ++ ) {
+
+ Reference < XInterface > x = m_rFactory->createInstance("test.com.sun.star.io.PersistTest");
+ Reference< XPersistObject > persistRef( x , UNO_QUERY );
+
+ Reference < XPropertySet > rProp( persistRef , UNO_QUERY );
+ ERROR_ASSERT( rProp.is() , "test object is no property set " );
+
+ Any any;
+ sal_Int32 i = 0x83482;
+ any <<= i;
+ rProp->setPropertyValue("long", any );
+
+ float f = 42.23;
+ any <<= f;
+ rProp->setPropertyValue("float", any );
+
+ double d = 233.321412;
+ any <<= d;
+ rProp->setPropertyValue("double", any );
+
+ sal_Bool b = sal_True;
+ any.setValue( &b , cppu::UnoType<bool>::get() );
+ rProp->setPropertyValue("bool", any );
+
+ sal_Int8 by = 120;
+ any <<= by;
+ rProp->setPropertyValue("byte", any );
+
+ sal_Unicode c = 'h';
+ any.setValue( &c , cppu::UnoType<cppu::UnoCharType>::get() );
+ rProp->setPropertyValue("char", any );
+
+ OUString str( "hi du !" );
+ any <<= str;
+ rProp->setPropertyValue("string", any );
+
+ x = m_rFactory->createInstance("test.com.sun.star.io.PersistTest");
+ Reference <XPersistObject > persist2ndRef( x , UNO_QUERY );
+
+ // Note : persist2ndRef contains coincident values, but also coincident values must be
+ // saved properly !
+ any <<= persist2ndRef;
+ rProp->setPropertyValue("object", any );
+
+ // simply test, if markable operations and object operations do not interfere
+ sal_Int32 nMark = markableOut->createMark();
+
+ // do read and write
+ rOut->writeObject( persistRef );
+
+ // further markable tests !
+ sal_Int32 nOffset = markableOut->offsetToMark( nMark );
+ markableOut->jumpToMark( nMark );
+ markableOut->deleteMark( nMark );
+ markableOut->jumpToFurthest();
+
+
+ ERROR_ASSERT( 0 != rIn->available() , "no data arrived at input" );
+ Reference < XPersistObject > xReadPersistRef = rIn->readObject( );
+
+ Reference< XPropertySet > rProp1( persistRef , UNO_QUERY );
+ Reference< XPropertySet > rProp2( xReadPersistRef , UNO_QUERY );
+ ERROR_ASSERT( compareMyPropertySet( rProp1, rProp2) ,
+ "objects has not been read properly !" );
+ }
+ }
+}
+
+
+Reference < XInterface > SAL_CALL OObjectStreamTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw(Exception)
+{
+ OObjectStreamTest *p = new OObjectStreamTest( rSMgr );
+ return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
+}
+
+Sequence<OUString> OObjectStreamTest_getSupportedServiceNames( int i) throw ()
+{
+ Sequence<OUString> aRet { OObjectStreamTest_getImplementationName( i) };
+ return aRet;
+}
+
+OUString OObjectStreamTest_getServiceName( int i) throw ()
+{
+ if( 1 == i ) {
+ return OUString( "test.com.sun.star.io.ObjectInputStream" );
+ }
+ else {
+ return OUString( "test.com.sun.star.io.ObjectOutputStream");
+ }
+}
+
+OUString OObjectStreamTest_getImplementationName( int i) throw ()
+{
+ if( 1 == i ) {
+ return OUString( "test.com.sun.star.comp.extensions.stm.ObjectInputStream" );
+ }
+ else {
+ return OUString( "test.com.sun.star.comp.extensions.stm.ObjectOutputStream");
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/stm/exports.dxp b/io/test/stm/exports.dxp
new file mode 100644
index 000000000..86214860d
--- /dev/null
+++ b/io/test/stm/exports.dxp
@@ -0,0 +1,2 @@
+component_getFactory
+component_writeInfo
diff --git a/io/test/stm/makefile.mk b/io/test/stm/makefile.mk
new file mode 100644
index 000000000..1a7eaad0e
--- /dev/null
+++ b/io/test/stm/makefile.mk
@@ -0,0 +1,89 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+PRJ=..$/..
+
+PRJNAME=io
+TARGET=teststm
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+.INCLUDE : settings.mk
+.IF "$(L10N_framework)"==""
+# --- Files --------------------------------------------------------
+UNOUCRDEP=$(SOLARBINDIR)$/udkapi.rdb
+UNOUCRRDB=$(SOLARBINDIR)$/udkapi.rdb
+
+# output directory (one dir for each project)
+UNOUCROUT=$(OUT)$/inc
+
+UNOTYPES = com.sun.star.test.XSimpleTest \
+ com.sun.star.beans.XPropertySet \
+ com.sun.star.io.UnexpectedEOFException \
+ com.sun.star.io.WrongFormatException \
+ com.sun.star.io.XActiveDataControl \
+ com.sun.star.io.XActiveDataSink \
+ com.sun.star.io.XActiveDataSource \
+ com.sun.star.io.XConnectable \
+ com.sun.star.io.XMarkableStream \
+ com.sun.star.io.XObjectInputStream \
+ com.sun.star.io.XObjectOutputStream \
+ com.sun.star.lang.IllegalArgumentException \
+ com.sun.star.lang.XComponent \
+ com.sun.star.lang.XMultiServiceFactory \
+ com.sun.star.lang.XServiceInfo \
+ com.sun.star.lang.XSingleServiceFactory \
+ com.sun.star.lang.XSingleComponentFactory \
+ com.sun.star.lang.XMultiComponentFactory \
+ com.sun.star.uno.XComponentContext \
+ com.sun.star.lang.XTypeProvider \
+ com.sun.star.registry.XImplementationRegistration \
+ com.sun.star.registry.XRegistryKey \
+ com.sun.star.test.XSimpleTest \
+ com.sun.star.uno.TypeClass \
+ com.sun.star.uno.XAggregation \
+ com.sun.star.uno.XWeak
+
+SLOFILES= \
+ $(SLO)$/testfactreg.obj \
+ $(SLO)$/pipetest.obj \
+ $(SLO)$/datatest.obj \
+ $(SLO)$/marktest.obj \
+ $(SLO)$/pumptest.obj
+
+SHL1TARGET= $(TARGET)
+
+SHL1STDLIBS= \
+ $(SALLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)
+
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+
+SHL1IMPLIB= i$(TARGET)
+
+SHL1DEPN= makefile.mk $(SHL1LIBS)
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+
+DEF1NAME= $(SHL1TARGET)
+DEF1EXPORTFILE= exports.dxp
+
+
+# --- Targets ------------------------------------------------------
+.ENDIF # L10N_framework
+
+.INCLUDE : target.mk
diff --git a/io/test/stm/marktest.cxx b/io/test/stm/marktest.cxx
new file mode 100644
index 000000000..fbfc20082
--- /dev/null
+++ b/io/test/stm/marktest.cxx
@@ -0,0 +1,644 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <osl/conditn.hxx>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+// streams
+
+#include "testfactreg.hxx"
+
+
+class OMarkableOutputStreamTest : public WeakImplHelper< XSimpleTest >
+{
+public:
+ explicit OMarkableOutputStreamTest( const Reference< XMultiServiceFactory > & rFactory );
+ ~OMarkableOutputStreamTest();
+
+public: // implementation names
+ static Sequence< OUString > getSupportedServiceNames_Static() throw ();
+ static OUString getImplementationName_Static() throw ();
+
+public:
+ virtual void SAL_CALL testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException,
+ RuntimeException) ;
+
+ virtual sal_Int32 SAL_CALL test( const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException, RuntimeException);
+ virtual sal_Bool SAL_CALL testPassed()
+ throw ( RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getErrors()
+ throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getErrorExceptions()
+ throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings()
+ throw (RuntimeException);
+
+private:
+ void testSimple( const Reference< XOutputStream > &r, const Reference < XInputStream > &rInput );
+
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+ Reference< XMultiServiceFactory > m_rFactory;
+
+};
+
+OMarkableOutputStreamTest::OMarkableOutputStreamTest( const Reference< XMultiServiceFactory > &rFactory )
+ : m_rFactory( rFactory )
+{
+
+}
+
+OMarkableOutputStreamTest::~OMarkableOutputStreamTest()
+{
+
+}
+
+
+void OMarkableOutputStreamTest::testInvariant( const OUString& TestName,
+ const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ Reference< XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT( ! info->supportsService(
+ OUString( "bla bluzb") ) , "XServiceInfo test failed" );
+ }
+}
+
+
+sal_Int32 OMarkableOutputStreamTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( "com.sun.star.io.MarkableOutputStream" )
+ == TestName ) {
+ try
+ {
+ if( 0 == hTestHandle )
+ {
+ testInvariant( TestName , TestObject );
+ }
+ else
+ {
+ Reference < XInterface > x = m_rFactory->createInstance("com.sun.star.io.Pipe");
+ Reference< XOutputStream > rPipeOutput( x , UNO_QUERY );
+ Reference < XInputStream > rPipeInput( x , UNO_QUERY );
+
+ Reference< XActiveDataSource > source( TestObject , UNO_QUERY );
+ source->setOutputStream( rPipeOutput );
+
+ Reference< XOutputStream > rOutput( TestObject , UNO_QUERY );
+
+ OSL_ASSERT( rPipeInput.is() );
+ OSL_ASSERT( rOutput.is() );
+ if( 1 == hTestHandle ) {
+ // checks usual streaming
+ testSimple( rOutput , rPipeInput );
+ }
+ }
+
+ }
+ catch( const Exception &e )
+ {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( 2 == hTestHandle )
+ {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ throw IllegalArgumentException();
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool OMarkableOutputStreamTest::testPassed() throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OMarkableOutputStreamTest::getErrors() throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OMarkableOutputStreamTest::getErrorExceptions() throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OMarkableOutputStreamTest::getWarnings() throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+
+void OMarkableOutputStreamTest::testSimple( const Reference< XOutputStream > &rOutput ,
+ const Reference< XInputStream > &rInput )
+{
+ Reference < XMarkableStream > rMarkable( rOutput , UNO_QUERY );
+
+ ERROR_ASSERT( rMarkable.is() , "no MarkableStream implemented" );
+
+ // first check normal input/output facility
+ char pcStr[] = "Live long and prosper !";
+
+ Sequence<sal_Int8> seqWrite( strlen( pcStr )+1 );
+ memcpy( seqWrite.getArray() , pcStr , seqWrite.getLength() );
+
+ Sequence<sal_Int8> seqRead( seqWrite.getLength() );
+
+ int nMax = 10,i;
+
+ for( i = 0 ; i < nMax ; i ++ ) {
+ rOutput->writeBytes( seqWrite );
+ rInput->readBytes( seqRead , rInput->available() );
+ ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) ,
+ "error during read/write/skip" );
+ }
+
+ // Check buffer resizing
+ nMax = 3000;
+ for( i = 0 ; i < nMax ; i ++ ) {
+ rOutput->writeBytes( seqWrite );
+ }
+
+ for( i = 0 ; i < nMax ; i ++ ) {
+ rInput->readBytes( seqRead , seqWrite.getLength() );
+ ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) ,
+ "error during read/write" );
+ }
+
+ // Check creating marks !
+ sal_Int32 nMark = rMarkable->createMark();
+
+ for( i = 0 ; i < nMax ; i ++ ) {
+ rOutput->writeBytes( seqWrite );
+ }
+
+ ERROR_ASSERT( 0 == rInput->available() , "bytes available though mark is holded" );
+
+ ERROR_ASSERT( nMax*seqWrite.getLength() == rMarkable->offsetToMark( nMark ) ,
+ "offsetToMark failure" );
+
+ rMarkable->deleteMark( nMark );
+ ERROR_ASSERT( nMax*seqWrite.getLength() == rInput->available(),"bytes are not available though mark has been deleted" );
+
+ rInput->skipBytes( nMax*seqWrite.getLength() );
+ ERROR_ASSERT( 0 == rInput->available(), "skip bytes failure" );
+
+ try
+ {
+ rMarkable->jumpToMark( nMark );
+ ERROR_ASSERT( 0 , "jump to non existing mark possible !" );
+ }
+ catch ( IllegalArgumentException & )
+ {
+ // ok, exception was thrown
+ }
+
+ // test putting marks not at the end of the stream!
+ ERROR_ASSERT( 0 == rInput->available(), "stream isn't clean" );
+ {
+ Sequence< sal_Int8 > aByte(256);
+
+ for( i = 0 ; i < 256 ; i ++ )
+ {
+ aByte.getArray()[i] = i;
+ }
+ sal_Int32 nMark1 = rMarkable->createMark();
+
+ rOutput->writeBytes( aByte );
+ rMarkable->jumpToMark( nMark1 );
+ aByte.realloc( 10 );
+ rOutput->writeBytes( aByte );
+
+ sal_Int32 nMark2 = rMarkable->createMark( );
+
+ for( i = 0 ; i < 10 ; i ++ )
+ {
+ aByte.getArray()[i] = i+10;
+ }
+
+ rOutput->writeBytes( aByte );
+
+ // allow the bytes to be written !
+ rMarkable->jumpToFurthest();
+ rMarkable->deleteMark( nMark1 );
+ rMarkable->deleteMark( nMark2 );
+
+ ERROR_ASSERT( 256 == rInput->available(), "in between mark failure" );
+ rInput->readBytes( aByte ,256);
+ for( i = 0 ; i < 256 ; i ++ )
+ {
+ ERROR_ASSERT( i == ((sal_uInt8*)(aByte.getArray()))[i] , "in between mark failure" );
+ }
+ }
+
+ {
+ // now a more extensive mark test !
+ Sequence<sal_Int8> as[4];
+ sal_Int32 an[4];
+
+ for( i = 0 ; i < 4 ; i ++ ) {
+ as[i].realloc(1);
+ as[i].getArray()[0] = i;
+ an[i] = rMarkable->createMark();
+ rOutput->writeBytes( as[i] );
+ }
+
+ // check offset to mark
+ for( i = 0 ; i < 4 ; i ++ ) {
+ ERROR_ASSERT( rMarkable->offsetToMark( an[i] ) == 4-i , "offsetToMark failure" );
+ }
+
+ rMarkable->jumpToMark( an[1] );
+ ERROR_ASSERT( rMarkable->offsetToMark( an[3] ) == -2 , "offsetToMark failure" );
+
+ rMarkable->jumpToFurthest( );
+ ERROR_ASSERT( rMarkable->offsetToMark( an[0] ) == 4 , "offsetToMark failure" );
+
+ // now do a rewrite !
+ for( i = 0 ; i < 4 ; i ++ ) {
+ rMarkable->jumpToMark( an[3-i] );
+ rOutput->writeBytes( as[i] );
+ }
+ // NOTE : CursorPos 1
+
+ // now delete the marks !
+ for( i = 0 ; i < 4 ; i ++ ) {
+ rMarkable->deleteMark( an[i] );
+ }
+ ERROR_ASSERT( rInput->available() == 1 , "wrong number of bytes flushed" );
+
+ rMarkable->jumpToFurthest();
+
+ ERROR_ASSERT( rInput->available() == 4 , "wrong number of bytes flushed" );
+
+ rInput->readBytes( seqRead , 4 );
+
+ ERROR_ASSERT( 3 == seqRead.getArray()[0] , "rewrite didn't work" );
+ ERROR_ASSERT( 2 == seqRead.getArray()[1] , "rewrite didn't work" );
+ ERROR_ASSERT( 1 == seqRead.getArray()[2] , "rewrite didn't work" );
+ ERROR_ASSERT( 0 == seqRead.getArray()[3] , "rewrite didn't work" );
+
+ rOutput->closeOutput();
+ rInput->closeInput();
+ }
+
+}
+
+/***
+* the test methods
+*
+****/
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL OMarkableOutputStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception)
+{
+ OMarkableOutputStreamTest *p = new OMarkableOutputStreamTest( rSMgr );
+ return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
+}
+
+
+Sequence<OUString> OMarkableOutputStreamTest_getSupportedServiceNames() throw ()
+{
+ Sequence<OUString> aRet { OMarkableOutputStreamTest_getImplementationName() };
+
+ return aRet;
+}
+
+OUString OMarkableOutputStreamTest_getServiceName() throw ()
+{
+ return OUString( "test.com.sun.star.io.MarkableOutputStream");
+}
+
+OUString OMarkableOutputStreamTest_getImplementationName() throw ()
+{
+ return OUString( "test.com.sun.starextensions.stm.MarkableOutputStream");
+}
+
+
+// Input stream
+
+
+class OMarkableInputStreamTest : public WeakImplHelper< XSimpleTest >
+{
+public:
+ explicit OMarkableInputStreamTest( const Reference< XMultiServiceFactory > & rFactory );
+ ~OMarkableInputStreamTest();
+
+public: // implementation names
+ static Sequence< OUString > getSupportedServiceNames_Static() throw () ;
+ static OUString getImplementationName_Static() throw () ;
+
+public:
+ virtual void SAL_CALL testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException, RuntimeException) ;
+
+ virtual sal_Int32 SAL_CALL test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException) ;
+
+ virtual sal_Bool SAL_CALL testPassed()
+ throw ( RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getErrors()
+ throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getErrorExceptions()
+ throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings()
+ throw (RuntimeException);
+
+private:
+ void testSimple( const Reference< XOutputStream > &r,
+ const Reference < XInputStream > &rInput );
+
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+ Reference< XMultiServiceFactory > m_rFactory;
+
+};
+
+OMarkableInputStreamTest::OMarkableInputStreamTest( const Reference< XMultiServiceFactory > &rFactory )
+ : m_rFactory( rFactory )
+{
+
+}
+
+OMarkableInputStreamTest::~OMarkableInputStreamTest()
+{
+
+}
+
+
+void OMarkableInputStreamTest::testInvariant(
+ const OUString& TestName, const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( "com.sun.star.io.MarkableInputStream")
+ == TestName ) {
+ Reference <XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT(
+ ! info->supportsService(
+ OUString("bla bluzb") ) ,
+ "XServiceInfo test failed" );
+ }
+ }
+ else
+ {
+ throw IllegalArgumentException();
+ }
+}
+
+
+sal_Int32 OMarkableInputStreamTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle) throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( "com.sun.star.io.MarkableInputStream") == TestName )
+ {
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else {
+ Reference < XInterface > x = m_rFactory->createInstance("com.sun.star.io.Pipe");
+ Reference< XOutputStream > rPipeOutput( x , UNO_QUERY );
+ Reference < XInputStream > rPipeInput( x , UNO_QUERY );
+
+ Reference < XActiveDataSink > sink( TestObject , UNO_QUERY );
+ sink->setInputStream( rPipeInput );
+
+ Reference < XInputStream > rInput( TestObject , UNO_QUERY );
+
+ OSL_ASSERT( rPipeOutput.is() );
+ OSL_ASSERT( rInput.is() );
+ if( 1 == hTestHandle ) {
+ // checks usual streaming
+ testSimple( rPipeOutput , rInput );
+ }
+ }
+
+ }
+ catch( const Exception & e )
+ {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( 2 == hTestHandle ) {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else
+ {
+ throw IllegalArgumentException();
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool OMarkableInputStreamTest::testPassed() throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OMarkableInputStreamTest::getErrors() throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OMarkableInputStreamTest::getErrorExceptions() throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OMarkableInputStreamTest::getWarnings() throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+
+void OMarkableInputStreamTest::testSimple( const Reference< XOutputStream > &rOutput ,
+ const Reference < XInputStream > &rInput )
+{
+ Reference < XMarkableStream > rMarkable( rInput , UNO_QUERY );
+
+ Sequence<sal_Int8> seqWrite( 256 );
+ Sequence<sal_Int8> seqRead(10);
+
+ for( int i = 0 ; i < 256 ; i ++ )
+ {
+ seqWrite.getArray()[i] = i;
+ }
+
+ rOutput->writeBytes( seqWrite );
+ ERROR_ASSERT( 256 == rInput->available() , "basic read/write failure" );
+
+ rInput->readBytes( seqRead , 10 );
+ ERROR_ASSERT( 9 == seqRead.getArray()[9] , "basic read/write failure" );
+
+ sal_Int32 nMark = rMarkable->createMark();
+
+ rInput->skipBytes( 50 );
+ ERROR_ASSERT( 256-10-50 == rInput->available() , "marking error" );
+ ERROR_ASSERT( 50 == rMarkable->offsetToMark( nMark ) , "marking error" );
+
+ rMarkable->jumpToMark( nMark );
+ ERROR_ASSERT( 256-10 == rInput->available() , "marking error" );
+
+ rInput->readBytes( seqRead , 10 );
+ ERROR_ASSERT( 10 == seqRead.getArray()[0] , "marking error" );
+
+ // pos 20
+ {
+ sal_Int32 nInBetweenMark = rMarkable->createMark( );
+ rMarkable->jumpToMark( nMark );
+ rMarkable->jumpToMark( nInBetweenMark );
+
+ rInput->readBytes( seqRead , 10 );
+ ERROR_ASSERT( 20 == seqRead.getArray()[0] , "Inbetween mark failed!\n" );
+
+ rMarkable->deleteMark( nMark );
+
+ // Check if releasing the first bytes works correct.
+ rMarkable->jumpToMark( nInBetweenMark);
+ rInput->readBytes( seqRead , 10 );
+ ERROR_ASSERT( 20 == seqRead.getArray()[0] , "Inbetween mark failed!\n" );
+
+ rMarkable->deleteMark( nInBetweenMark );
+ }
+
+ rMarkable->jumpToFurthest();
+ ERROR_ASSERT( 256-10-50 == rInput->available() , "marking error" );
+
+
+ ERROR_ASSERT( 100 == rInput->readSomeBytes( seqRead , 100 ) , "wrong results using readSomeBytes" );
+ ERROR_ASSERT( 96 == rInput->readSomeBytes( seqRead , 1000) , "wrong results using readSomeBytes" );
+ rOutput->closeOutput();
+ rInput->closeInput();
+}
+
+/***
+* the test methods
+*
+****/
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL OMarkableInputStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception)
+{
+ OMarkableInputStreamTest *p = new OMarkableInputStreamTest( rSMgr );
+ return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
+}
+
+
+Sequence<OUString> OMarkableInputStreamTest_getSupportedServiceNames() throw ()
+{
+ Sequence<OUString> aRet { OMarkableInputStreamTest_getImplementationName() };
+
+ return aRet;
+}
+
+OUString OMarkableInputStreamTest_getServiceName() throw ()
+{
+ return OUString( "test.com.sun.star.io.MarkableInputStream");
+}
+
+OUString OMarkableInputStreamTest_getImplementationName() throw ()
+{
+ return OUString( "test.com.sun.star.extensions.stm.MarkableInputStream" );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/stm/pipetest.cxx b/io/test/stm/pipetest.cxx
new file mode 100644
index 000000000..77c333b0d
--- /dev/null
+++ b/io/test/stm/pipetest.cxx
@@ -0,0 +1,420 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/factory.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <osl/conditn.hxx>
+#include <osl/thread.hxx>
+
+#include <string.h>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+// streams
+
+#include "testfactreg.hxx"
+#define IMPLEMENTATION_NAME "test.com.sun.star.comp.extensions.stm.Pipe"
+#define SERVICE_NAME "test.com.sun.star.io.Pipe"
+
+
+class WriteToStreamThread :
+ public Thread
+{
+
+public:
+
+ WriteToStreamThread( Reference< XOutputStream > xOutput , int iMax )
+ : m_output(xOutput), m_iMax(iMax)
+ {
+ }
+
+ virtual ~WriteToStreamThread() {}
+
+
+protected:
+
+ /// Working method which should be overridden.
+ virtual void SAL_CALL run() {
+ for( int i = 0 ; i < m_iMax ; i ++ ) {
+ m_output->writeBytes( createIntSeq(i) );
+ }
+ m_output->closeOutput();
+ }
+
+ /** Called when run() is done.
+ * You might want to override it to do some cleanup.
+ */
+ virtual void SAL_CALL onTerminated()
+ {
+ delete this;
+ }
+
+
+private:
+
+ Reference < XOutputStream > m_output;
+ int m_iMax;
+};
+
+
+class OPipeTest : public WeakImplHelper < XSimpleTest >
+{
+public:
+ explicit OPipeTest( const Reference< XMultiServiceFactory > & rFactory );
+ ~OPipeTest();
+
+public: // implementation names
+ static Sequence< OUString > getSupportedServiceNames_Static() throw();
+ static OUString getImplementationName_Static() throw();
+
+public:
+ virtual void SAL_CALL testInvariant(const OUString& TestName, const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException, RuntimeException) ;
+
+ virtual sal_Int32 SAL_CALL test( const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Bool SAL_CALL testPassed() throw ( RuntimeException) ;
+ virtual Sequence< OUString > SAL_CALL getErrors() throw (RuntimeException) ;
+ virtual Sequence< Any > SAL_CALL getErrorExceptions() throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings() throw (RuntimeException);
+
+private:
+ void testSimple( const Reference < XInterface > & );
+ void testBufferResizing( const Reference < XInterface > & );
+ void testMultithreading( const Reference < XInterface > & );
+
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+
+};
+
+
+OPipeTest::OPipeTest( const Reference< XMultiServiceFactory > &rFactory )
+{
+
+}
+
+OPipeTest::~OPipeTest()
+{
+
+}
+
+
+void OPipeTest::testInvariant( const OUString& TestName, const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException,
+ RuntimeException)
+{
+ Reference< XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT( ! info->supportsService(
+ OUString("bla bluzb") ), "XServiceInfo test failed" );
+ }
+
+}
+
+
+sal_Int32 OPipeTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString("com.sun.star.io.Pipe") == TestName ) {
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else if( 1 == hTestHandle ) {
+ testSimple( TestObject );
+ }
+ else if( 2 == hTestHandle ) {
+ testBufferResizing( TestObject );
+ }
+ else if( 3 == hTestHandle ) {
+ testMultithreading( TestObject );
+ }
+ }
+ catch( const Exception & e )
+ {
+ OString s = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , s.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( 4 == hTestHandle )
+ {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ throw IllegalArgumentException();
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool OPipeTest::testPassed() throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OPipeTest::getErrors() throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OPipeTest::getErrorExceptions() throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OPipeTest::getWarnings() throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+
+/***
+* the test methods
+*
+****/
+
+
+void OPipeTest::testSimple( const Reference < XInterface > &r )
+{
+
+ Reference< XInputStream > input( r , UNO_QUERY );
+ Reference < XOutputStream > output( r , UNO_QUERY );
+
+ ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" );
+ ERROR_ASSERT( output.is() , "queryInterface onXOutputStream failed" );
+
+ // basic read/write
+ Sequence<sal_Int8> seqWrite = createSeq( "Hallo, du Ei !" );
+
+ Sequence<sal_Int8> seqRead;
+ for( int i = 0 ; i < 5000 ; i ++ ) {
+ output->writeBytes( seqWrite );
+ input->readBytes( seqRead , input->available() );
+
+ ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) ,
+ "error during read/write/skip" );
+ ERROR_ASSERT( 0 == input->available() ,
+ "error during read/write/skip" );
+
+ // available shouldn't return a negative value
+ input->skipBytes( seqWrite.getLength() - 5 );
+ ERROR_ASSERT( 0 == input->available() , "wrong available after skip" );
+
+ // 5 bytes should be available
+ output->writeBytes( seqWrite );
+ ERROR_ASSERT( 5 == input->available() , "wrong available after skip/write " );
+
+ input->readBytes( seqRead , 5 );
+ ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() ,
+ (char*) &( seqWrite.getArray()[seqWrite.getLength()-5] ) ),
+ "write/read mismatch" );
+
+ }
+
+ output->writeBytes( seqWrite );
+ ERROR_ASSERT( seqWrite.getLength() == input->available(), "wrong available() after write" );
+
+ ERROR_ASSERT( 10 == input->readSomeBytes( seqRead , 10 ) , "maximal number of bytes ignored" );
+ ERROR_ASSERT( seqWrite.getLength() -10 == input->readSomeBytes( seqRead , 100 ) ,
+ "something wrong with readSomeBytes" );
+
+
+ output->closeOutput();
+ try{
+ output->writeBytes( Sequence<sal_Int8> (100) );
+ ERROR_ASSERT( 0 , "writing on a closed stream does not cause an exception" );
+ }
+ catch (IOException & )
+ {
+ }
+
+ ERROR_ASSERT(! input->readBytes( seqRead , 1 ), "eof not found !" );
+
+ input->closeInput();
+ try
+ {
+ input->readBytes( seqRead , 1 );
+ ERROR_ASSERT( 0 , "reading from a closed stream does not cause an exception" );
+ }
+ catch( IOException & ) {
+ }
+
+ try
+ {
+ input->available( );
+ ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" );
+ }
+ catch( IOException & )
+ {
+
+ }
+ try
+ {
+ input->skipBytes(42 );
+ ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" );
+ }
+ catch( IOException & )
+ {
+
+ }
+}
+
+void OPipeTest::testBufferResizing( const Reference < XInterface > &r )
+{
+ int i;
+ int iMax = 20000;
+ Reference< XInputStream > input( r , UNO_QUERY );
+ Reference < XOutputStream > output( r , UNO_QUERY );
+
+ ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" );
+ ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" );
+
+ Sequence<sal_Int8> seqRead;
+
+ // this is just to better check the
+ // internal buffers
+ output->writeBytes( Sequence<sal_Int8>(100) );
+ Sequence< sal_Int8 > dummy;
+ input->readBytes( dummy , 100);
+
+ for( i = 0 ; i < iMax ; i ++ ) {
+ output->writeBytes( createIntSeq( i ) );
+ }
+
+ for( i = 0 ; i < iMax ; i ++ ) {
+ input->readBytes( seqRead, createIntSeq(i).getLength() );
+ ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() ,
+ (char*) createIntSeq(i).getArray() ) ,
+ "written/read mismatch\n" );
+ }
+
+ output->closeOutput();
+ ERROR_ASSERT( ! input->readBytes( seqRead , 1 ) , "eof not reached !" );
+ input->closeInput();
+}
+
+
+void OPipeTest::testMultithreading( const Reference < XInterface > &r )
+{
+
+ int i;
+ int iMax = 30000;
+
+ Reference< XInputStream > input( r , UNO_QUERY );
+ Reference < XOutputStream > output( r , UNO_QUERY );
+
+ ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" );
+ ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" );
+
+ Sequence<sal_Int8> seqRead;
+
+ // deletes itself
+ Thread *p = new WriteToStreamThread( output, iMax );
+
+ ERROR_ASSERT( p , "couldn't create thread for testing !\n" );
+
+ p->create();
+
+ for( i = 0 ; sal_True ; i ++ ) {
+ if( 0 == input->readBytes( seqRead, createIntSeq(i).getLength() ) ) {
+ // eof reached !
+ break;
+ }
+
+ ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() ,
+ (char*) createIntSeq(i).getArray() ) ,
+ "written/read mismatch\n" );
+ }
+
+ ERROR_ASSERT( i == iMax , "less elements read than written !");
+ input->closeInput();
+}
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL OPipeTest_CreateInstance( const Reference< XMultiServiceFactory> & rSMgr ) throw (Exception)
+{
+ OPipeTest *p = new OPipeTest( rSMgr );
+ Reference< XInterface > x ( (static_cast< OWeakObject * >(p)) );
+ return x;
+}
+
+
+Sequence<OUString> OPipeTest_getSupportedServiceNames() throw()
+{
+ Sequence<OUString> aRet { OPipeTest_getServiceName() };
+
+ return aRet;
+}
+
+OUString OPipeTest_getServiceName() throw()
+{
+ return OUString( SERVICE_NAME );
+}
+
+OUString OPipeTest_getImplementationName() throw()
+{
+ return OUString( IMPLEMENTATION_NAME );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/stm/pumptest.cxx b/io/test/stm/pumptest.cxx
new file mode 100644
index 000000000..f0563153e
--- /dev/null
+++ b/io/test/stm/pumptest.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stdio.h>
+#include <osl/time.h>
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataControl.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+
+#include <uno/dispatcher.h>
+#include <uno/mapping.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/factory.hxx>
+#include <osl/thread.hxx>
+#include <list>
+
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+
+#include "testfactreg.hxx"
+
+static void mywait()
+{
+ osl::Thread::wait(std::chrono::microseconds(10));
+ osl_yieldThread();
+ osl_yieldThread();
+}
+
+class OPumpTest : public WeakImplHelper < XSimpleTest >
+{
+public:
+ explicit OPumpTest( const Reference< XMultiServiceFactory > & rFactory );
+ ~OPumpTest();
+
+public: // implementation names
+ static Sequence< OUString > getSupportedServiceNames_Static() throw();
+ static OUString getImplementationName_Static() throw();
+
+public:
+ virtual void SAL_CALL testInvariant(const OUString& TestName, const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException, RuntimeException) ;
+
+ virtual sal_Int32 SAL_CALL test( const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Bool SAL_CALL testPassed() throw ( RuntimeException) ;
+ virtual Sequence< OUString > SAL_CALL getErrors() throw (RuntimeException) ;
+ virtual Sequence< Any > SAL_CALL getErrorExceptions() throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings() throw (RuntimeException);
+
+private:
+ void testSimple( const Reference < XInterface > & );
+ void testWrongUsage( const Reference < XInterface > & );
+ void testClose( const Reference< XInterface >& );
+ void testTerminate( const Reference< XInterface >& );
+ void testFunction( const Reference< XInterface >& );
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+ Reference< XMultiServiceFactory > m_rSmgr;
+
+};
+
+OPumpTest::OPumpTest( const Reference< XMultiServiceFactory > &rFactory ) :
+ m_rSmgr( rFactory )
+{
+
+}
+
+OPumpTest::~OPumpTest()
+{
+
+}
+
+
+void OPumpTest::testInvariant( const OUString& TestName, const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException,
+ RuntimeException)
+{
+ Reference< XServiceInfo > info( TestObject, UNO_QUERY );
+ ERROR_ASSERT( info.is() , "XServiceInfo not supported !" );
+ if( info.is() )
+ {
+ ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" );
+ ERROR_ASSERT( ! info->supportsService(
+ OUString( "bla bluzb" ) ), "XServiceInfo test failed" );
+ }
+
+ Reference < XActiveDataSource > xActiveDataSource( TestObject, UNO_QUERY );
+ Reference < XActiveDataSink > xActiveDataSink( TestObject, UNO_QUERY );
+ Reference < XActiveDataControl > xActiveDataControl( TestObject , UNO_QUERY );
+ Reference < XConnectable > xConnectable( TestObject , UNO_QUERY );
+
+ ERROR_ASSERT( xActiveDataSource.is() && xActiveDataSink.is() && xActiveDataControl.is () &&
+ xConnectable.is(), "specified interface not supported" );
+}
+
+
+sal_Int32 OPumpTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( "com.sun.star.io.Pump" ) == TestName ) {
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else if ( 1 == hTestHandle )
+ {
+ testWrongUsage( TestObject);
+ }
+ else if ( 2 == hTestHandle )
+ {
+ testClose( TestObject);
+ }
+ else if ( 3 == hTestHandle )
+ {
+ testTerminate( TestObject );
+ }
+ else if ( 4 == hTestHandle )
+ {
+ testFunction( TestObject );
+ }
+ }
+ catch( const Exception & e )
+ {
+ OString s = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , s.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( 5 == hTestHandle )
+ {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ throw IllegalArgumentException();
+ }
+ return hTestHandle;
+}
+
+
+sal_Bool OPumpTest::testPassed() throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OPumpTest::getErrors() throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OPumpTest::getErrorExceptions() throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OPumpTest::getWarnings() throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+
+/***
+* the test methods
+*
+****/
+
+
+void OPumpTest::testSimple( const Reference < XInterface > &r )
+{
+ // jbu todo: add sensible test
+
+}
+
+class TestListener: public WeakImplHelper< XStreamListener >
+{
+public:
+ sal_Bool m_bStarted;
+ sal_Bool m_bClosed;
+ sal_Bool m_bTerminated;
+ sal_Bool m_bError;
+ sal_Bool m_bDisposed;
+ TestListener() : m_bStarted (sal_False),
+ m_bClosed (sal_False),
+ m_bTerminated ( sal_False ),
+ m_bError( sal_False ),
+ m_bDisposed( sal_False )
+ {}
+
+ virtual void SAL_CALL disposing( const EventObject &obj ) throw (css::uno::RuntimeException)
+ {
+ m_bDisposed = sal_True;
+// printf( "disposing called\n");
+ }
+
+ virtual void SAL_CALL started( ) throw (css::uno::RuntimeException)
+ {
+ m_bStarted = sal_True;
+// printf( "started called\n");
+ }
+ virtual void SAL_CALL closed( ) throw (css::uno::RuntimeException)
+ {
+ m_bClosed = sal_True;
+// printf( "closed called\n");
+ }
+ virtual void SAL_CALL terminated( ) throw (css::uno::RuntimeException)
+ {
+ m_bTerminated = sal_True;
+// printf( "terminated called\n");
+ }
+ virtual void SAL_CALL error( const css::uno::Any& aException )
+ throw (css::uno::RuntimeException)
+ {
+ m_bError = sal_True;
+ Exception e;
+ aException >>= e;
+// printf( "error called %s\n", OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US).getStr() );
+ }
+};
+
+class TestCase
+{
+public:
+ TestCase( const Reference< XMultiServiceFactory > & rSMgr,
+ const Reference< XInterface > &r ) : m_rSmgr( rSMgr ), m_pTestListener( 0 )
+ {
+ m_rControl.set( r, UNO_QUERY );
+
+ Reference< XActiveDataSource > rSource ( r, UNO_QUERY );
+ Reference< XActiveDataSink > rSink( r , UNO_QUERY );
+
+ m_rOutSource.set( createPipe() );
+ rSink->setInputStream(Reference< XInputStream> (m_rOutSource,UNO_QUERY));
+
+ Reference< XOutputStream > rOutSink( createPipe() );
+ m_rInSink.set( rOutSink, UNO_QUERY );
+ rSource->setOutputStream( rOutSink );
+
+ m_pTestListener = new TestListener();
+ m_pTestListener->acquire();
+ m_rControl->addListener( m_pTestListener );
+ }
+
+ ~TestCase()
+ {
+ if( m_pTestListener )
+ m_pTestListener->release();
+ }
+
+ TestListener *m_pTestListener;
+ Reference< XActiveDataControl > m_rControl;
+ Reference< XOutputStream > m_rOutSource;
+ Reference< XInputStream > m_rInSink;
+ Reference< XMultiServiceFactory > m_rSmgr;
+
+private:
+ Reference< XOutputStream > createPipe()
+ {
+ Reference< XOutputStream > rOut( m_rSmgr->createInstance(
+ "com.sun.star.io.Pipe"),UNO_QUERY);
+ return rOut;
+ }
+};
+
+
+void OPumpTest::testClose( const Reference< XInterface > &r )
+{
+ TestCase t( m_rSmgr, r );
+
+ ERROR_ASSERT( ! t.m_pTestListener->m_bStarted , "started too early" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "termination unexpected" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bClosed, "unexpected close" );
+
+ t.m_rControl->start();
+ mywait();
+
+ ERROR_ASSERT( t.m_pTestListener->m_bStarted , "should have been started already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "termination unexpected" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bClosed, "unexpected close" );
+
+ Reference< XStreamListener > rListener( new TestListener() );
+ t.m_rControl->addListener( rListener );
+ t.m_rControl->removeListener( rListener );
+
+ t.m_rOutSource->closeOutput();
+ mywait();
+ ERROR_ASSERT( t.m_pTestListener->m_bStarted , "should have been started already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "should be terminated already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( t.m_pTestListener->m_bClosed, "should be closed already" );
+}
+
+void OPumpTest::testTerminate( const Reference< XInterface > &r )
+{
+ TestCase t( m_rSmgr, r );
+
+ ERROR_ASSERT( ! t.m_pTestListener->m_bStarted , "started too early" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "termination unexpected" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bClosed, "unexpected closed" );
+
+ t.m_rControl->start();
+ mywait();
+
+ ERROR_ASSERT( t.m_pTestListener->m_bStarted , "should have been started already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "termination unexpected" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bClosed, "unexpected closed" );
+
+ t.m_rControl->terminate();
+
+ mywait();
+ ERROR_ASSERT( t.m_pTestListener->m_bStarted , "should have been started already" );
+ ERROR_ASSERT( t.m_pTestListener->m_bTerminated , "should be terminated already" );
+ // terminate leads to an error, that is no surprise, in fact
+ // one can't tell whether the error occurs because of the terminate
+ // call or for some other reason!
+// ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( t.m_pTestListener->m_bClosed, "should be closed already" );
+}
+
+void OPumpTest::testFunction( const Reference< XInterface > &r )
+{
+ TestCase t( m_rSmgr, r );
+
+ t.m_rControl->start();
+
+ t.m_rOutSource->writeBytes( Sequence< sal_Int8 > ( 5 ) );
+
+ Sequence< sal_Int8 > dummy;
+ ERROR_ASSERT( 5 == t.m_rInSink->readBytes( dummy , 5 ), "couldn't read the expected number of bytes" );
+
+ t.m_rOutSource->closeOutput();
+ mywait();
+
+ ERROR_ASSERT( t.m_pTestListener->m_bStarted , "should have been started already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bTerminated , "should be terminated already" );
+ ERROR_ASSERT( ! t.m_pTestListener->m_bError, "unexpected error" );
+ ERROR_ASSERT( t.m_pTestListener->m_bClosed, "should be closed already" );
+}
+
+void OPumpTest::testWrongUsage( const Reference< XInterface > &r )
+{
+ Reference< XActiveDataSource > rSource ( r, UNO_QUERY );
+ Reference< XActiveDataSink > rSink( r , UNO_QUERY );
+ Reference< XActiveDataControl > rControl( r, UNO_QUERY );
+
+ Reference< XInputStream > rIn( m_rSmgr->createInstance(
+ "com.sun.star.io.DataInputStream"),UNO_QUERY);
+ Reference< XOutputStream > rOut( m_rSmgr->createInstance(
+ "com.sun.star.io.DataOutputStream"),UNO_QUERY);
+
+ rSink->setInputStream( rIn );
+ rSource->setOutputStream( rOut );
+
+ rControl->start();
+
+ mywait();
+}
+
+Reference< XInterface > SAL_CALL OPumpTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw( Exception )
+{
+ return *new OPumpTest( rSMgr );
+}
+
+Sequence<OUString> OPumpTest_getSupportedServiceNames() throw()
+{
+ return { OPumpTest_getServiceName() };
+
+}
+OUString OPumpTest_getServiceName() throw()
+{
+ return OUString( "test.com.sun.star.io.Pump" );
+}
+
+OUString OPumpTest_getImplementationName() throw()
+{
+ return OUString( "test.com.sun.star.comp.io.Pump" );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/stm/testfactreg.cxx b/io/test/stm/testfactreg.cxx
new file mode 100644
index 000000000..2250429e5
--- /dev/null
+++ b/io/test/stm/testfactreg.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <osl/diagnose.h>
+
+#include <cppuhelper/factory.hxx>
+
+using namespace ::cppu;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+#include "testfactreg.hxx"
+
+
+extern "C"
+{
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ if (pRegistryKey)
+ {
+ try
+ {
+ Reference< XRegistryKey > xKey(
+ reinterpret_cast< XRegistryKey * >( pRegistryKey ) );
+
+ OUString str = "/" +
+ OPipeTest_getImplementationName() +
+ "/UNO/SERVICES";
+ Reference< XRegistryKey > xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OPipeTest_getServiceName() );
+
+ str = "/" +
+ OPumpTest_getImplementationName() +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OPumpTest_getServiceName() );
+
+ str = "/" +
+ ODataStreamTest_getImplementationName(1) +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( ODataStreamTest_getServiceName(1) );
+
+ str = "/" +
+ ODataStreamTest_getImplementationName(2) +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( ODataStreamTest_getServiceName(2) );
+
+ str = "/" +
+ OObjectStreamTest_getImplementationName(1) +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OObjectStreamTest_getServiceName(1) );
+
+ str = "/" +
+ OObjectStreamTest_getImplementationName(2) +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OObjectStreamTest_getServiceName(2) );
+
+ str = "/" +
+ OMarkableOutputStreamTest_getImplementationName() +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OMarkableOutputStreamTest_getServiceName() );
+
+ str = "/" +
+ OMarkableInputStreamTest_getImplementationName() +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OMarkableInputStreamTest_getServiceName() );
+
+ str = "/" +
+ OMyPersistObject_getImplementationName() +
+ "/UNO/SERVICES";
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OMyPersistObject_getServiceName() );
+
+ return sal_True;
+ }
+ catch (InvalidRegistryException &)
+ {
+ OSL_FAIL( "### InvalidRegistryException!" );
+ }
+ }
+ return sal_False;
+}
+
+SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
+ const char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ void * pRet = 0;
+
+ if (pServiceManager )
+ {
+ Reference< XSingleServiceFactory > xRet;
+ Reference< XMultiServiceFactory > xSMgr =
+ reinterpret_cast< XMultiServiceFactory * > ( pServiceManager );
+
+ OUString aImplementationName = OUString::createFromAscii( pImplName );
+
+ if (aImplementationName == OPipeTest_getImplementationName() )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ OPipeTest_CreateInstance,
+ OPipeTest_getSupportedServiceNames() );
+ }
+ else if (aImplementationName == OPumpTest_getImplementationName() )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ OPumpTest_CreateInstance,
+ OPumpTest_getSupportedServiceNames() );
+ }
+
+ else if( aImplementationName == ODataStreamTest_getImplementationName(1) ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ ODataStreamTest_CreateInstance,
+ ODataStreamTest_getSupportedServiceNames(1) );
+ }
+ else if( aImplementationName == ODataStreamTest_getImplementationName(2) ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ ODataStreamTest_CreateInstance,
+ ODataStreamTest_getSupportedServiceNames(2) );
+ }
+ else if( aImplementationName == OObjectStreamTest_getImplementationName(1) ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ OObjectStreamTest_CreateInstance,
+ OObjectStreamTest_getSupportedServiceNames(1) );
+ }
+ else if( aImplementationName == OObjectStreamTest_getImplementationName(2) ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ OObjectStreamTest_CreateInstance,
+ OObjectStreamTest_getSupportedServiceNames(2) );
+ }
+ else if( aImplementationName == OMarkableOutputStreamTest_getImplementationName() ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ OMarkableOutputStreamTest_CreateInstance,
+ OMarkableOutputStreamTest_getSupportedServiceNames() );
+ }
+ else if( aImplementationName == OMarkableInputStreamTest_getImplementationName() ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ OMarkableInputStreamTest_CreateInstance,
+ OMarkableInputStreamTest_getSupportedServiceNames() );
+ }
+ else if( aImplementationName == OMyPersistObject_getImplementationName() ) {
+ xRet = createSingleFactory( xSMgr , aImplementationName,
+ OMyPersistObject_CreateInstance,
+ OMyPersistObject_getSupportedServiceNames() );
+ }
+ if (xRet.is())
+ {
+ xRet->acquire();
+ pRet = xRet.get();
+ }
+ }
+
+ return pRet;
+}
+
+}
+
+Sequence<sal_Int8 > createSeq( char * p )
+{
+ Sequence<sal_Int8> seq( strlen( p )+1 );
+ strcpy( (char * ) seq.getArray() , p );
+ return seq;
+}
+
+Sequence<sal_Int8> createIntSeq( sal_Int32 i )
+{
+ char pcCount[20];
+ sprintf( pcCount , "%d" , i );
+ return createSeq( pcCount );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/stm/testfactreg.hxx b/io/test/stm/testfactreg.hxx
new file mode 100644
index 000000000..2dbff6d62
--- /dev/null
+++ b/io/test/stm/testfactreg.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_IO_TEST_STM_TESTFACTREG_HXX
+#define INCLUDED_IO_TEST_STM_TESTFACTREG_HXX
+
+#include <rtl/strbuf.hxx>
+
+Reference< XInterface > SAL_CALL OPipeTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw( Exception );
+Sequence<OUString> OPipeTest_getSupportedServiceNames() throw();
+OUString OPipeTest_getServiceName() throw();
+OUString OPipeTest_getImplementationName() throw();
+
+Reference< XInterface > SAL_CALL OPumpTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw( Exception );
+Sequence<OUString> OPumpTest_getSupportedServiceNames() throw();
+OUString OPumpTest_getServiceName() throw();
+OUString OPumpTest_getImplementationName() throw();
+
+Reference< XInterface > SAL_CALL ODataStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception);
+Sequence<OUString> ODataStreamTest_getSupportedServiceNames( int i) throw();
+OUString ODataStreamTest_getServiceName( int i) throw();
+OUString ODataStreamTest_getImplementationName( int i) throw();
+
+Reference< XInterface > SAL_CALL OMarkableOutputStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception);
+Sequence<OUString> OMarkableOutputStreamTest_getSupportedServiceNames() throw();
+OUString OMarkableOutputStreamTest_getServiceName() throw();
+OUString OMarkableOutputStreamTest_getImplementationName() throw();
+
+Reference< XInterface > SAL_CALL OMarkableInputStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception);
+Sequence<OUString> OMarkableInputStreamTest_getSupportedServiceNames() throw();
+OUString OMarkableInputStreamTest_getServiceName() throw();
+OUString OMarkableInputStreamTest_getImplementationName() throw();
+
+Reference< XInterface > SAL_CALL OObjectStreamTest_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception);
+Sequence<OUString> OObjectStreamTest_getSupportedServiceNames( int i) throw();
+OUString OObjectStreamTest_getServiceName( int i) throw();
+OUString OObjectStreamTest_getImplementationName( int i) throw();
+
+Reference< XInterface > SAL_CALL OMyPersistObject_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception);
+Sequence<OUString> OMyPersistObject_getSupportedServiceNames( ) throw();
+OUString OMyPersistObject_getServiceName( ) throw();
+OUString OMyPersistObject_getImplementationName( ) throw();
+
+Sequence<sal_Int8> createSeq( char * p );
+Sequence<sal_Int8> createIntSeq( sal_Int32 i );
+
+#define BUILD_ERROR(expr, Message)\
+ {\
+ m_seqErrors.realloc( m_seqErrors.getLength() + 1 ); \
+ m_seqExceptions.realloc( m_seqExceptions.getLength() + 1 ); \
+ OStringBuffer str(128); \
+ str.append( __FILE__ );\
+ str.append( " " ); \
+ str.append( "(" ); \
+ str.append( OString::valueOf( (sal_Int32)__LINE__) );\
+ str.append(")\n" );\
+ str.append( "[ " ); \
+ str.append( #expr ); \
+ str.append( " ] : " ); \
+ str.append( Message ); \
+ m_seqErrors.getArray()[ m_seqErrors.getLength()-1] =\
+ OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \
+ }\
+ ((void)0)
+
+
+#define WARNING_ASSERT(expr, Message) \
+ if( ! (expr) ) { \
+ m_seqWarnings.realloc( m_seqErrors.getLength() +1 ); \
+ OStringBuffer str(128);\
+ str.append( __FILE__);\
+ str.append( " "); \
+ str.append( "(" ); \
+ str.append(OString::valueOf( (sal_Int32)__LINE__)) ;\
+ str.append( ")\n");\
+ str.append( "[ " ); \
+ str.append( #expr ); \
+ str.append( " ] : ") ; \
+ str.append( Message); \
+ m_seqWarnings.getArray()[ m_seqWarnings.getLength()-1] =\
+ OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \
+ return; \
+ }\
+ ((void)0)
+
+#define ERROR_ASSERT(expr, Message) \
+ if( ! (expr) ) { \
+ BUILD_ERROR(expr, Message );\
+ return; \
+ }\
+ ((void)0)
+
+#endif // INCLUDED_IO_TEST_STM_TESTFACTREG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/testcomponent.cxx b/io/test/testcomponent.cxx
new file mode 100644
index 000000000..2b317c903
--- /dev/null
+++ b/io/test/testcomponent.cxx
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+// testcomponent - Loads a service and its testcomponent from dlls performs a test.
+// Expands the dll-names depending on the actual environment.
+// Example : testcomponent com.sun.star.io.Pipe stm
+//
+// Therefore the testcode must exist in teststm and the testservice must be named test.com.sun.star.io.Pipe
+
+#include <stdio.h>
+#include <com/sun/star/registry/XImplementationRegistration.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+
+#include <cppuhelper/servicefactory.hxx>
+
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::test;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+
+// Needed to switch on solaris threads
+
+int main (int argc, char **argv)
+{
+
+ if( argc < 3) {
+ printf( "usage : testcomponent service dll [additional dlls]\n" );
+ exit( 0 );
+ }
+
+ // create service manager
+ Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory(
+ OUString( "applicat.rdb" ) );
+
+ Reference < XImplementationRegistration > xReg;
+ Reference < XSimpleRegistry > xSimpleReg;
+
+ try
+ {
+ // Create registration service
+ Reference < XInterface > x = xSMgr->createInstance(
+ "com.sun.star.registry.ImplementationRegistration" );
+ xReg.set( x , UNO_QUERY );
+ }
+ catch( Exception & ) {
+ printf( "Couldn't create ImplementationRegistration service\n" );
+ exit(1);
+ }
+
+ char szBuf[1024];
+ OString sTestName;
+
+ try
+ {
+ // Load dll for the tested component
+ for( int n = 2 ; n <argc ; n ++ ) {
+ OUString aDllName = OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US );
+ xReg->registerImplementation(
+ OUString("com.sun.star.loader.SharedLibrary"),
+ aDllName,
+ xSimpleReg );
+ }
+ }
+ catch( const Exception &e ) {
+ printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
+
+ exit(1);
+ }
+
+
+ try
+ {
+ // Load dll for the test component
+ sTestName = "test";
+ sTestName += argv[2];
+
+#if defined(_WIN32)
+ OUString aDllName = OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US );
+#else
+ OUString aDllName("lib");
+ aDllName += OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US );
+ aDllName += ".so";
+#endif
+
+ xReg->registerImplementation(
+ OUString("com.sun.star.loader.SharedLibrary") ,
+ aDllName,
+ xSimpleReg );
+ }
+ catch( Exception & )
+ {
+ printf( "Couldn't reach dll %s\n" , szBuf );
+ exit(1);
+ }
+
+
+ // Instantiate test service
+ sTestName = "test.";
+ sTestName += argv[1];
+
+ Reference < XInterface > xIntTest =
+ xSMgr->createInstance( OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US ) );
+ Reference< XSimpleTest > xTest( xIntTest , UNO_QUERY );
+
+ if( ! xTest.is() ) {
+ printf( "Couldn't instantiate test service \n" );
+ exit( 1 );
+ }
+
+
+ sal_Int32 nHandle = 0;
+ sal_Int32 nNewHandle;
+ sal_Int32 nErrorCount = 0;
+ sal_Int32 nWarningCount = 0;
+
+ // loop until all test are performed
+ while( nHandle != -1 )
+ {
+ // Instantiate service
+ Reference< XInterface > x =
+ xSMgr->createInstance( OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) );
+ if( ! x.is() )
+ {
+ printf( "Couldn't instantiate service !\n" );
+ exit( 1 );
+ }
+
+ // do the test
+ try
+ {
+ nNewHandle = xTest->test(
+ OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) , x , nHandle );
+ }
+ catch( const Exception & e ) {
+ OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
+ printf( "testcomponent : uncaught exception %s\n" , o.getStr() );
+ exit(1);
+ }
+ catch( ... )
+ {
+ printf( "testcomponent : uncaught unknown exception\n" );
+ exit(1);
+ }
+
+
+ // print errors and warning
+ Sequence<OUString> seqErrors = xTest->getErrors();
+ Sequence<OUString> seqWarnings = xTest->getWarnings();
+ if( seqWarnings.getLength() > nWarningCount )
+ {
+ printf( "Warnings during test %d!\n" , nHandle );
+ for( ; nWarningCount < seqWarnings.getLength() ; nWarningCount ++ )
+ {
+ OString o = OUStringToOString(
+ seqWarnings.getArray()[nWarningCount], RTL_TEXTENCODING_ASCII_US );
+ printf( "Warning\n%s\n---------\n" , o.getStr() );
+ }
+ }
+
+
+ if( seqErrors.getLength() > nErrorCount ) {
+ printf( "Errors during test %d!\n" , nHandle );
+ for( ; nErrorCount < seqErrors.getLength() ; nErrorCount ++ )
+ {
+ OString o = OUStringToOString(
+ seqErrors.getArray()[nErrorCount], RTL_TEXTENCODING_ASCII_US );
+ printf( "%s\n" , o.getStr() );
+ }
+ }
+
+ nHandle = nNewHandle;
+ }
+
+ if( xTest->testPassed() ) {
+ printf( "Test passed !\n" );
+ }
+ else {
+ printf( "Test failed !\n" );
+ }
+
+ Reference <XComponent > rComp( xSMgr , UNO_QUERY );
+ rComp->dispose();
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/io/test/testconnection.cxx b/io/test/testconnection.cxx
new file mode 100644
index 000000000..35bc697c9
--- /dev/null
+++ b/io/test/testconnection.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stdio.h>
+#include <osl/time.h>
+
+#include <osl/diagnose.h>
+#include <osl/thread.hxx>
+
+#include <cppuhelper/servicefactory.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <com/sun/star/registry/XImplementationRegistration.hpp>
+
+#include <com/sun/star/connection/XConnector.hpp>
+#include <com/sun/star/connection/XAcceptor.hpp>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::connection;
+
+
+class MyThread :
+ public Thread
+{
+public:
+ MyThread( const Reference< XAcceptor > &r , const OUString & sConnectionDescription) :
+ m_rAcceptor( r ),
+ m_sConnectionDescription( sConnectionDescription )
+ {}
+ virtual void SAL_CALL run();
+
+ Reference < XAcceptor > m_rAcceptor;
+private:
+ Reference < XConnection > m_rConnection;
+ OUString m_sConnectionDescription;
+};
+
+void doWrite( const Reference < XConnection > &r )
+{
+ Sequence < sal_Int8 > seq(10);
+ for( sal_Int32 i = 0 ; i < 10 ; i ++ )
+ {
+ seq.getArray()[i] = i;
+ }
+
+ r->write( seq );
+}
+
+void doRead( const Reference < XConnection > &r )
+{
+ Sequence < sal_Int8 > seq(10);
+
+ OSL_ASSERT( 10 == r->read( seq , 10 ) );
+
+ for( sal_Int32 i = 0 ; i < 10 ; i ++ )
+ {
+ OSL_ASSERT( seq.getConstArray()[i] == i );
+ }
+}
+
+
+void MyThread::run()
+{
+ try
+ {
+ m_rConnection = m_rAcceptor->accept( m_sConnectionDescription );
+ }
+ catch ( const Exception &e)
+ {
+ OString tmp= OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ printf( "Exception was thrown by acceptor thread: %s\n", tmp.getStr() );
+ }
+
+ if( m_rConnection.is() )
+ {
+ Sequence < sal_Int8 > seq(12);
+ try
+ {
+ doWrite( m_rConnection );
+ doRead( m_rConnection );
+ }
+ catch (... )
+ {
+ printf( "unknown exception was thrown\n" );
+ throw;
+ }
+ }
+
+}
+
+
+void testConnection( const OUString &sConnectionDescription ,
+ const Reference < XAcceptor > &rAcceptor,
+ const Reference < XConnector > &rConnector )
+{
+ {
+ MyThread thread( rAcceptor , sConnectionDescription );
+ thread.create();
+
+ sal_Bool bGotit = sal_False;
+ Reference < XConnection > r;
+
+ while( ! bGotit )
+ {
+ try
+ {
+ // Why is this wait necessary ????
+ osl::Thread::wait(std::chrono::seconds(1));
+ r = rConnector->connect( sConnectionDescription );
+ OSL_ASSERT( r.is() );
+ doWrite( r );
+ doRead( r );
+ bGotit = sal_True;
+ }
+ catch( ... )
+ {
+ printf( "Couldn't connect, retrying ...\n" );
+
+ }
+ }
+
+ r->close();
+
+ try
+ {
+ Sequence < sal_Int8 > seq(10);
+ r->write( seq );
+ OSL_FAIL( "expected exception not thrown" );
+ }
+ catch ( IOException & )
+ {
+ // everything is ok
+ }
+ catch ( ... )
+ {
+ OSL_FAIL( "wrong exception was thrown" );
+ }
+
+ thread.join();
+ }
+}
+
+
+int SAL_CALL main( int argc, char * argv[] )
+{
+ Reference< XMultiServiceFactory > xMgr(
+ createRegistryServiceFactory( OUString( "applicat.rdb") ) );
+
+ Reference< XImplementationRegistration > xImplReg(
+ xMgr->createInstance("com.sun.star.registry.ImplementationRegistration"), UNO_QUERY );
+ OSL_ENSURE( xImplReg.is(), "### no impl reg!" );
+
+ OUString aLibName = "connector.uno" SAL_DLLEXTENSION;
+ xImplReg->registerImplementation(
+ OUString("com.sun.star.loader.SharedLibrary"), aLibName, Reference< XSimpleRegistry >() );
+
+ aLibName = "acceptor.uno" SAL_DLLEXTENSION;
+ xImplReg->registerImplementation(
+ OUString("com.sun.star.loader.SharedLibrary"), aLibName, Reference< XSimpleRegistry >() );
+
+ Reference < XAcceptor > rAcceptor(
+ xMgr->createInstance( "com.sun.star.connection.Acceptor" ) , UNO_QUERY );
+
+ Reference < XAcceptor > rAcceptorPipe(
+ xMgr->createInstance( "com.sun.star.connection.Acceptor" ) , UNO_QUERY );
+
+ Reference < XConnector > rConnector(
+ xMgr->createInstance("com.sun.star.connection.Connector") , UNO_QUERY );
+
+
+ printf( "Testing sockets" );
+ fflush( stdout );
+ testConnection( OUString("socket,host=localhost,port=2001"), rAcceptor , rConnector );
+ printf( " Done\n" );
+
+ printf( "Testing pipe" );
+ fflush( stdout );
+ testConnection( OUString("pipe,name=bla") , rAcceptorPipe , rConnector );
+ printf( " Done\n" );
+
+ // check, if erroneous strings make any problem
+ rAcceptor.set(
+ xMgr->createInstance("com.sun.star.connection.Acceptor"),
+ UNO_QUERY );
+
+ try
+ {
+ rAcceptor->accept( OUString() );
+ OSL_FAIL( "empty connection string" );
+ }
+ catch( IllegalArgumentException & )
+ {
+ // everything is fine
+ }
+ catch( ... )
+ {
+ OSL_FAIL( "unexpected akexception with empty connection string" );
+ }
+
+ try
+ {
+ rConnector->connect( OUString() );
+ OSL_FAIL( "empty connection string" );
+ }
+ catch( ConnectionSetupException & )
+ {
+ // everything is fine
+ }
+ catch( ... )
+ {
+ OSL_FAIL( "unexpected exception with empty connection string" );
+ }
+
+
+ MyThread thread( rAcceptor , OUString("socket,host=localhost,port=2001") );
+ thread.create();
+
+ osl::Thread::wait(std::chrono::nanoseconds(1));
+ try
+ {
+ rAcceptor->accept( OUString("socket,host=localhost,port=2001") );
+ OSL_FAIL( "already existing exception expected" );
+ }
+ catch( AlreadyAcceptingException & )
+ {
+ // everything is fine
+ }
+ catch( ... )
+ {
+ OSL_FAIL( "unknown exception, already existing exception expected" );
+ }
+
+ rAcceptor->stopAccepting();
+ thread.join();
+
+ Reference < XComponent > rComp( xMgr , UNO_QUERY );
+ if( rComp.is() )
+ {
+ rComp->dispose();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ios/.gitignore b/ios/.gitignore
new file mode 100644
index 000000000..8bd528904
--- /dev/null
+++ b/ios/.gitignore
@@ -0,0 +1,9 @@
+#
+# 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/.
+#
+
+generated
diff --git a/ios/CustomTarget_iOS_link.mk b/ios/CustomTarget_iOS_link.mk
new file mode 100644
index 000000000..240f38d07
--- /dev/null
+++ b/ios/CustomTarget_iOS_link.mk
@@ -0,0 +1,90 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#- Env ------------------------------------------------------------------------
+IOSGEN = $(BUILDDIR)/workdir/CustomTarget/ios
+IOSLIBS := $(shell \
+ (export INSTDIR=$(INSTDIR);export OS=$(OS); \
+ export WORKDIR=$(WORKDIR);export LIBO_LIB_FOLDER=$(LIBO_LIB_FOLDER); \
+ $(SRCDIR)/bin/lo-all-static-libs))
+IOSOBJ = $(IOSGEN)/Kit.o
+IOSSRC = $(SRCDIR)/ios/source/LibreOfficeKit.c
+
+ifeq ($(ENABLE_DEBUG),TRUE)
+ifeq ($(CPUNAME),X86_64)
+IOSKIT = $(IOSGEN)/Debug_x86_64/libKit.dylib
+else
+IOSKIT = $(IOSGEN)/Debug_arm64/libKit.dylib
+endif
+else
+ifeq ($(CPUNAME),ARM64)
+IOSKIT = $(IOSGEN)/Release_arm64/libKit.dylib
+endif
+endif
+
+
+
+#- Top level -----------------------------------------------------------------
+$(eval $(call gb_CustomTarget_CustomTarget,ios/iOS_link))
+
+$(call gb_CustomTarget_get_target,ios/iOS_link): $(IOSKIT)
+
+
+#- build ---------------------------------------------------------------------
+$(IOSOBJ): $(IOSSRC) $(call gb_CustomTarget_get_target,ios/iOS_setup)
+ $(call gb_Output_announce,iOS compile interface,$(true),C,2)
+ $(gb_CC) $(gb_COMPILERDEFS) $(gb_OSDEFS) $(gb_CFLAGS) \
+ -DDISABLE_DYNLOADING -DLIBO_INTERNAL_ONLY \
+ -fvisibility=hidden -Werror -O0 -fstrict-overflow \
+ $(if $(ENABLE_DEBUG),-g) \
+ -c $(IOSSRC) -o $(IOSOBJ) \
+ -I$(SRCDIR)/include -I$(BUILDDIR)/config_host \
+
+$(IOSKIT): $(IOSOBJ) $(IOSLIBS)
+ $(call gb_Output_announce,iOS dylib,$(true),LNK,2)
+ $(call gb_Trace_StartRange,iOS dylib,LNK)
+ $(gb_CC) -dynamiclib \
+ -Xlinker -rpath -Xlinker @executable_path/Frameworks \
+ -Xlinker -rpath -Xlinker @loader_path/Frameworks \
+ -install_name @rpath/libKit.dylib \
+ -dead_strip \
+ -Xlinker -export_dynamic \
+ -Xlinker -no_deduplicate \
+ -Xlinker -objc_abi_version -Xlinker 2 \
+ -fobjc-link-runtime \
+ -framework CoreFoundation \
+ -framework CoreGraphics \
+ -framework CoreText \
+ -liconv \
+ -lc++ \
+ -lz \
+ -lpthread \
+ -single_module \
+ -compatibility_version 1 \
+ -current_version 1 \
+ `$(SRCDIR)/bin/lo-all-static-libs` \
+ $(IOSOBJ) \
+ -o $(IOSKIT)
+ifeq ($(origin IOS_CODEID),undefined)
+ @echo "please define environment variable IOS_CODEID as\n" \
+ "export IOS_CODEID=<your apple code identifier>"
+ @exit -1
+else
+ codesign -s "$(IOS_CODEID)" $(IOSKIT)
+endif
+ $(call gb_Trace_EndRange,iOS dylib,LNK)
+
+
+#- clean ios -----------------------------------------------------------------
+$(call gb_CustomTarget_get_clean_target,ios/iOS_link):
+ rm -f $(IOSKIT)
+
+
+
+# vim: set noet sw=4 ts=4:
diff --git a/ios/CustomTarget_iOS_setup.mk b/ios/CustomTarget_iOS_setup.mk
new file mode 100644
index 000000000..0227c860d
--- /dev/null
+++ b/ios/CustomTarget_iOS_setup.mk
@@ -0,0 +1,127 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+
+#- Env ------------------------------------------------------------------------
+IOSGEN = $(BUILDDIR)/workdir/CustomTarget/ios
+IOSRES = $(IOSGEN)/resources
+IOSDIRS = $(IOSGEN) \
+ $(IOSGEN)/Debug_x86_64 \
+ $(IOSGEN)/Debug_arm64 \
+ $(IOSGEN)/Release_x86_64 \
+ $(IOSGEN)/Release_arm64 \
+ $(IOSRES) \
+ $(IOSRES)/services \
+ $(IOSRES)/program \
+ $(IOSRES)/share \
+ $(IOSRES)/config \
+ $(IOSRES)/share/filter
+
+
+#- Top level -----------------------------------------------------------------
+$(eval $(call gb_CustomTarget_CustomTarget,ios/iOS_setup))
+
+$(call gb_CustomTarget_get_target,ios/iOS_setup): $(IOSGEN)/native-code.h
+
+
+#- create directories --------------------------------------------------------
+$(IOSDIRS):
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MKD,2)
+ $(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),MKD)
+ mkdir -p $(IOSDIRS)
+ $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MKD)
+
+
+#- Generate resources --------------------------------------------------------
+$(IOSGEN)/native-code.h: $(BUILDDIR)/config_host.mk \
+ $(SRCDIR)/ios/CustomTarget_iOS_setup.mk \
+ $(SRCDIR)/solenv/bin/native-code.py \
+ $(IOSGEN) \
+ $(IOSDIRS)
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),EN2,2)
+ $(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),EN2)
+ $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),EN2)
+
+ # generate native-code.h (used by LibreOffice.c)
+ $(SRCDIR)/solenv/bin/native-code.py \
+ -C -g core -g writer -g calc -g draw -g edit \
+ > $(IOSGEN)/native-code.h
+
+ # copy resource files used to start/run LibreOffice
+ cp $(WORKDIR)/UnpackedTarball/icu/source/data/in/icudt$(ICU_MAJOR)l.dat $(IOSRES)/icudt$(ICU_MAJOR)l.dat
+ cp $(INSTDIR)/program/types.rdb $(IOSRES)/udkapi.rdb
+ cp $(INSTDIR)/program/types/offapi.rdb $(IOSRES)
+ cp $(INSTDIR)/program/types/oovbaapi.rdb $(IOSRES)
+ cp $(INSTDIR)/program/services/services.rdb $(IOSRES)/services
+ cp $(INSTDIR)/program/services.rdb $(IOSRES)
+ if test -d $(INSTDIR)/program/resource; then \
+ cp -R $(INSTDIR)/program/resource $(IOSRES)/program; \
+ fi
+ mkdir -p $(IOSRES)/share/config
+ cp -R $(INSTDIR)/share/config/soffice.cfg $(IOSRES)/share/config
+ cp $(INSTDIR)/share/filter/oox-drawingml-adj-names $(IOSRES)/share/filter
+ cp $(INSTDIR)/share/filter/oox-drawingml-cs-presets $(IOSRES)/share/filter
+ cp $(INSTDIR)/share/filter/vml-shape-types $(IOSRES)/share/filter
+ cp -R $(INSTDIR)/share/registry $(IOSRES)/share
+ cp $(INSTDIR)/share/config/*zip $(IOSRES)/share/config
+ cp -R $(INSTDIR)/share/liblangtag $(IOSRES)/share
+ cp -R $(INSTDIR)/share/theme_definitions $(IOSRES)/share
+ cp -R $(INSTDIR)/share/template $(IOSRES)/share
+ mkdir -p $(IOSRES)/share/fonts
+ cp -R $(INSTDIR)/share/fonts/truetype $(IOSRES)/share/fonts
+ cp -R $(INSTDIR)/share/gallery $(IOSRES)/share
+ cp -R $(INSTDIR)/share/palette $(IOSRES)/share
+ cp -R $(INSTDIR)/share/fingerprint $(IOSRES)/share
+ cp $(SRCDIR)/ios/welcome.odt $(IOSRES)
+
+ # Set up rc (the "inifile", fundamentalrc, unorc, bootstraprc and versionrc.
+ (echo '[Bootstrap]' \
+ && echo 'URE_BOOTSTRAP=file://$$APP_DATA_DIR/fundamentalrc' \
+ && echo 'HOME=$$SYSUSERHOME' \
+ ) > $(IOSRES)/rc
+
+ (echo '[Bootstrap]' \
+ && echo 'BRAND_BASE_DIR=file://$$APP_DATA_DIR' \
+ && echo 'BRAND_INI_DIR=file:://$$APP_DATA_DIR' \
+ && echo 'BRAND_SHARE_SUBDIR=$(LIBO_SHARE_FOLDER)' \
+ && echo 'BRAND_SHARE_RESOURCE_SUBDIR=$(LIBO_SHARE_RESOURCE_FOLDER)' \
+ && echo 'CONFIGURATION_LAYERS=xcsxcu:$${BRAND_BASE_DIR}/share/registry ' \
+ 'res:$${BRAND_BASE_DIR}/share/registry' \
+ && echo 'LO_LIB_DIR=file://$$APP_DATA_DIR/lib/' \
+ && echo 'UNO_TYPES=file://$$APP_DATA_DIR/udkapi.rdb ' \
+ 'file://$$APP_DATA_DIR/offapi.rdb' \
+ && echo 'UNO_SERVICES=file://$$APP_DATA_DIR/services.rdb ' \
+ 'file://$$APP_DATA_DIR/services/services.rdb' \
+ && echo 'OSL_SOCKET_PATH=$$APP_DATA_DIR/cache' \
+ ) > $(IOSRES)/fundamentalrc;
+
+ echo '[Bootstrap]' > $(IOSRES)/unorc
+
+ # bootstraprc must be in $BRAND_BASE_DIR/program
+ (echo '[Bootstrap]' \
+ && echo 'InstallMode=<installmode>' \
+ && echo "ProductKey=LibreOffice $(PRODUCTVERSION)" \
+ && echo 'UserInstallation=$$SYSUSERHOME' \
+ ) > $(IOSRES)/program/bootstraprc
+
+ (echo '[Version]' \
+ && echo 'AllLanguages=en-US' \
+ && echo 'BuildVersion=' \
+ && echo "buildid=$(shell git -C $(SRCDIR) log -1 --format=%H)" \
+ ) > $(IOSRES)/program/versionrc
+
+ $(SRCDIR)/bin/lo-all-static-libs | sed -e 's/ /\
+/g' >$(IOSGEN)/ios-all-static-libs.list
+
+#- clean ios -----------------------------------------------------------------
+$(call gb_CustomTarget_get_clean_target,ios/iOS_setup):
+ $(call gb_Output_announce,$(subst $(WORKDIR)/Clean/,,$@),$(false),ENV,2)
+ rm -rf $(IOSRES)/* $(IOSGEN)/native-code.h $(IOSGEN)
+
+# vim: set noet sw=4 ts=4:
diff --git a/ios/DISCLAIMER_WARNING b/ios/DISCLAIMER_WARNING
new file mode 100644
index 000000000..36663688d
--- /dev/null
+++ b/ios/DISCLAIMER_WARNING
@@ -0,0 +1,11 @@
+******
+Everything in ios is currently
+ WORK IN PROGRESS
+
+Do not expect it to work, or even compile
+
+If you want to help with the work, please send
+an email to our dev@ list.
+
+rgds
+jan I
diff --git a/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/project.pbxproj b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..819a41962
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/project.pbxproj
@@ -0,0 +1,635 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 39284DB31FA5F207006F43E4 /* DocumentActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39284DB21FA5F207006F43E4 /* DocumentActions.swift */; };
+ 392ED9B31E5E4B03005C8435 /* ViewPrintManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 392ED9B21E5E4B03005C8435 /* ViewPrintManager.swift */; };
+ 3941EF15204B4C8A00082486 /* unorc in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF06204B4C8900082486 /* unorc */; };
+ 3941EF16204B4C8A00082486 /* fundamentalrc in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF07204B4C8900082486 /* fundamentalrc */; };
+ 3941EF17204B4C8A00082486 /* program in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF08204B4C8900082486 /* program */; };
+ 3941EF18204B4C8A00082486 /* services.rdb in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF09204B4C8900082486 /* services.rdb */; };
+ 3941EF19204B4C8A00082486 /* oovbaapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0A204B4C8900082486 /* oovbaapi.rdb */; };
+ 3941EF1A204B4C8A00082486 /* registry in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0B204B4C8900082486 /* registry */; };
+ 3941EF1B204B4C8A00082486 /* services in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0C204B4C8900082486 /* services */; };
+ 3941EF1C204B4C8A00082486 /* offapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0D204B4C8900082486 /* offapi.rdb */; };
+ 3941EF1D204B4C8A00082486 /* filter in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0E204B4C8900082486 /* filter */; };
+ 3941EF1E204B4C8A00082486 /* rc in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF0F204B4C8900082486 /* rc */; };
+ 3941EF1F204B4C8A00082486 /* udkapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF10204B4C8900082486 /* udkapi.rdb */; };
+ 3941EF20204B4C8A00082486 /* icudt62l.dat in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF11204B4C8900082486 /* icudt62l.dat */; };
+ 3941EF21204B4C8A00082486 /* welcome.odt in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF12204B4C8900082486 /* welcome.odt */; };
+ 3941EF22204B4C8A00082486 /* config in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF13204B4C8900082486 /* config */; };
+ 3941EF23204B4C8A00082486 /* share in Resources */ = {isa = PBXBuildFile; fileRef = 3941EF14204B4C8900082486 /* share */; };
+ 39514E002057DC55005599D0 /* shared in Resources */ = {isa = PBXBuildFile; fileRef = 39514DFF2057DC55005599D0 /* shared */; };
+ 39514E082057E4A8005599D0 /* inc in Resources */ = {isa = PBXBuildFile; fileRef = 39514E072057E4A8005599D0 /* inc */; };
+ 396F92F71E7AE62400A28C82 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 396F92F61E7AE62400A28C82 /* Settings.bundle */; };
+ 397868D61E59A3EA007F9248 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 397868D81E59A3EA007F9248 /* LaunchScreen.xib */; };
+ 397E08FE1E597BD8001374E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397E08FD1E597BD8001374E0 /* AppDelegate.swift */; };
+ 397E09031E597BD8001374E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 397E09011E597BD8001374E0 /* Main.storyboard */; };
+ 397E09081E597BD8001374E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 397E09071E597BD8001374E0 /* Assets.xcassets */; };
+ 3992D85A1E5B762A00BEA987 /* DocumentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3992D8591E5B762A00BEA987 /* DocumentController.swift */; };
+ 399648471E5B87DC00E73E83 /* ViewProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 399648461E5B87DC00E73E83 /* ViewProperties.swift */; };
+ 39EF4E2F1FA500C9001914AC /* PropertiesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EF4E2E1FA500C9001914AC /* PropertiesController.swift */; };
+ FC31D01E2012F65500E7F402 /* DocumentHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC31D01D2012F65500E7F402 /* DocumentHolder.swift */; };
+ FC31D0202012F6D300E7F402 /* RenderCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC31D01F2012F6D300E7F402 /* RenderCache.swift */; };
+ FC31D02B2013500E00E7F402 /* ButtonScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC31D02A2013500E00E7F402 /* ButtonScrollView.swift */; };
+ FC31D02D2015DE1700E7F402 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC31D02C2015DE1700E7F402 /* UIViewExtensions.swift */; };
+ FCAB1CB82009DB6900F1CC34 /* DocumentOverlaysView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCAB1CB72009DB6900F1CC34 /* DocumentOverlaysView.swift */; };
+ FCC2E3FA2004A01500CEB504 /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E3F62004A01400CEB504 /* Document.swift */; };
+ FCC2E3FC2004A01500CEB504 /* LibreOfficeKitWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E3F82004A01400CEB504 /* LibreOfficeKitWrapper.swift */; };
+ FCC2E3FD2004A01500CEB504 /* LOKitThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E3F92004A01400CEB504 /* LOKitThread.swift */; };
+ FCC2E3FF2004B59B00CEB504 /* DocumentTiledView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E3FE2004B59B00CEB504 /* DocumentTiledView.swift */; };
+ FCC2E4032004B72700CEB504 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E4022004B72700CEB504 /* Util.swift */; };
+ FCC2E4052004B74000CEB504 /* AsyncUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC2E4042004B74000CEB504 /* AsyncUtil.swift */; };
+ FCC7651D201C7F8A007D190C /* libKit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FCC7651C201C7F8A007D190C /* libKit.dylib */; };
+ FCC7651E201C80A5007D190C /* libKit.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = FCC7651C201C7F8A007D190C /* libKit.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ FC148CE420187F7800C349CA /* Embed Libraries */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ FCC7651E201C80A5007D190C /* libKit.dylib in Embed Libraries */,
+ );
+ name = "Embed Libraries";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 39284DB21FA5F207006F43E4 /* DocumentActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentActions.swift; sourceTree = "<group>"; };
+ 392ED9B21E5E4B03005C8435 /* ViewPrintManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewPrintManager.swift; path = LibreOfficeLight/ViewPrintManager.swift; sourceTree = SOURCE_ROOT; };
+ 3941EF06204B4C8900082486 /* unorc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = unorc; path = ../../workdir/CustomTarget/ios/resources/unorc; sourceTree = "<group>"; };
+ 3941EF07204B4C8900082486 /* fundamentalrc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fundamentalrc; path = ../../workdir/CustomTarget/ios/resources/fundamentalrc; sourceTree = "<group>"; };
+ 3941EF08204B4C8900082486 /* program */ = {isa = PBXFileReference; lastKnownFileType = folder; name = program; path = ../../workdir/CustomTarget/ios/resources/program; sourceTree = "<group>"; };
+ 3941EF09204B4C8900082486 /* services.rdb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = services.rdb; path = ../../workdir/CustomTarget/ios/resources/services.rdb; sourceTree = "<group>"; };
+ 3941EF0A204B4C8900082486 /* oovbaapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = oovbaapi.rdb; path = ../../workdir/CustomTarget/ios/resources/oovbaapi.rdb; sourceTree = "<group>"; };
+ 3941EF0B204B4C8900082486 /* registry */ = {isa = PBXFileReference; lastKnownFileType = folder; name = registry; path = ../../workdir/CustomTarget/ios/resources/registry; sourceTree = "<group>"; };
+ 3941EF0C204B4C8900082486 /* services */ = {isa = PBXFileReference; lastKnownFileType = folder; name = services; path = ../../workdir/CustomTarget/ios/resources/services; sourceTree = "<group>"; };
+ 3941EF0D204B4C8900082486 /* offapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = offapi.rdb; path = ../../workdir/CustomTarget/ios/resources/offapi.rdb; sourceTree = "<group>"; };
+ 3941EF0E204B4C8900082486 /* filter */ = {isa = PBXFileReference; lastKnownFileType = folder; name = filter; path = ../../workdir/CustomTarget/ios/resources/filter; sourceTree = "<group>"; };
+ 3941EF0F204B4C8900082486 /* rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = rc; path = ../../workdir/CustomTarget/ios/resources/rc; sourceTree = "<group>"; };
+ 3941EF10204B4C8900082486 /* udkapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = udkapi.rdb; path = ../../workdir/CustomTarget/ios/resources/udkapi.rdb; sourceTree = "<group>"; };
+ 3941EF11204B4C8900082486 /* icudt62l.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = icudt62l.dat; path = ../../workdir/CustomTarget/ios/resources/icudt62l.dat; sourceTree = "<group>"; };
+ 3941EF12204B4C8900082486 /* welcome.odt */ = {isa = PBXFileReference; lastKnownFileType = file; name = welcome.odt; path = ../../workdir/CustomTarget/ios/resources/welcome.odt; sourceTree = "<group>"; };
+ 3941EF13204B4C8900082486 /* config */ = {isa = PBXFileReference; lastKnownFileType = folder; name = config; path = ../../workdir/CustomTarget/ios/resources/config; sourceTree = "<group>"; };
+ 3941EF14204B4C8900082486 /* share */ = {isa = PBXFileReference; lastKnownFileType = folder; name = share; path = ../../workdir/CustomTarget/ios/resources/share; sourceTree = "<group>"; };
+ 39503A6F1F94C4AC00F19C78 /* lokit-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "lokit-Bridging-Header.h"; sourceTree = "<group>"; };
+ 39514DFF2057DC55005599D0 /* shared */ = {isa = PBXFileReference; lastKnownFileType = folder; name = shared; path = ../../bridges/source/cpp_uno/shared; sourceTree = "<group>"; };
+ 39514E012057DC92005599D0 /* gcc3_ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = gcc3_ios; path = ../../bridges/source/cpp_uno/gcc3_ios; sourceTree = "<group>"; };
+ 39514E032057DCE7005599D0 /* gcc3_macosx_x86-64 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "gcc3_macosx_x86-64"; path = "../../bridges/source/cpp_uno/gcc3_macosx_x86-64"; sourceTree = "<group>"; };
+ 39514E052057DD17005599D0 /* gcc3_linux_aarch64 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = gcc3_linux_aarch64; path = ../../bridges/source/cpp_uno/gcc3_linux_aarch64; sourceTree = "<group>"; };
+ 39514E072057E4A8005599D0 /* inc */ = {isa = PBXFileReference; lastKnownFileType = folder; name = inc; path = ../../bridges/inc; sourceTree = "<group>"; };
+ 396F92F61E7AE62400A28C82 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
+ 397275391E77D9F1006ACDCC /* LibreOfficeLight.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LibreOfficeLight.entitlements; sourceTree = "<group>"; };
+ 397868D71E59A3EA007F9248 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
+ 397E08FA1E597BD8001374E0 /* LibreOfficeLight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LibreOfficeLight.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 397E08FD1E597BD8001374E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = LibreOfficeLight/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
+ 397E09021E597BD8001374E0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Main.storyboard; sourceTree = "<group>"; };
+ 397E09071E597BD8001374E0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = LibreOfficeLight/Assets.xcassets; sourceTree = SOURCE_ROOT; };
+ 3992D8591E5B762A00BEA987 /* DocumentController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DocumentController.swift; path = LibreOfficeLight/DocumentController.swift; sourceTree = SOURCE_ROOT; };
+ 399648461E5B87DC00E73E83 /* ViewProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewProperties.swift; path = LibreOfficeLight/ViewProperties.swift; sourceTree = SOURCE_ROOT; };
+ 39B092501E5F3DEA00682A59 /* LibreOfficeLight-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LibreOfficeLight-Prefix.pch"; sourceTree = "<group>"; };
+ 39B4245D2060FB2300347588 /* ucbhelper.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ucbhelper.cxx; path = ../../unotools/source/ucbhelper/ucbhelper.cxx; sourceTree = "<group>"; };
+ 39E950521FC9842000D82C49 /* source */ = {isa = PBXFileReference; lastKnownFileType = folder; name = source; path = ../source; sourceTree = "<group>"; };
+ 39EE81531FA644E800B73AB8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 39EF4E2E1FA500C9001914AC /* PropertiesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertiesController.swift; sourceTree = "<group>"; };
+ 39FD89E6204EBCB900E7179F /* exc_thrower.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exc_thrower.cxx; path = ../../cppuhelper/source/exc_thrower.cxx; sourceTree = "<group>"; };
+ FC31D01D2012F65500E7F402 /* DocumentHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentHolder.swift; sourceTree = "<group>"; };
+ FC31D01F2012F6D300E7F402 /* RenderCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderCache.swift; sourceTree = "<group>"; };
+ FC31D02A2013500E00E7F402 /* ButtonScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonScrollView.swift; sourceTree = "<group>"; };
+ FC31D02C2015DE1700E7F402 /* UIViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = "<group>"; };
+ FCAB1CB72009DB6900F1CC34 /* DocumentOverlaysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentOverlaysView.swift; sourceTree = "<group>"; };
+ FCC2E3F62004A01400CEB504 /* Document.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = "<group>"; };
+ FCC2E3F82004A01400CEB504 /* LibreOfficeKitWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibreOfficeKitWrapper.swift; sourceTree = "<group>"; };
+ FCC2E3F92004A01400CEB504 /* LOKitThread.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LOKitThread.swift; sourceTree = "<group>"; };
+ FCC2E3FE2004B59B00CEB504 /* DocumentTiledView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentTiledView.swift; sourceTree = "<group>"; };
+ FCC2E4022004B72700CEB504 /* Util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = "<group>"; };
+ FCC2E4042004B74000CEB504 /* AsyncUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncUtil.swift; sourceTree = "<group>"; };
+ FCC7651C201C7F8A007D190C /* libKit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libKit.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 397E08F71E597BD8001374E0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FCC7651D201C7F8A007D190C /* libKit.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 3911D89F1E5993600050D6BC /* Support files */ = {
+ isa = PBXGroup;
+ children = (
+ 39B092501E5F3DEA00682A59 /* LibreOfficeLight-Prefix.pch */,
+ 397275391E77D9F1006ACDCC /* LibreOfficeLight.entitlements */,
+ 397E09071E597BD8001374E0 /* Assets.xcassets */,
+ 396F92F61E7AE62400A28C82 /* Settings.bundle */,
+ );
+ name = "Support files";
+ path = LibreOfficeLight;
+ sourceTree = SOURCE_ROOT;
+ };
+ 3956B72D1FAB3DBF00BF5DE4 /* extra */ = {
+ isa = PBXGroup;
+ children = (
+ 39514E072057E4A8005599D0 /* inc */,
+ 39514E052057DD17005599D0 /* gcc3_linux_aarch64 */,
+ 39514E032057DCE7005599D0 /* gcc3_macosx_x86-64 */,
+ 39514E012057DC92005599D0 /* gcc3_ios */,
+ 39514DFF2057DC55005599D0 /* shared */,
+ 39FD89E6204EBCB900E7179F /* exc_thrower.cxx */,
+ 39B4245D2060FB2300347588 /* ucbhelper.cxx */,
+ 39E950521FC9842000D82C49 /* source */,
+ );
+ name = extra;
+ sourceTree = "<group>";
+ };
+ 3972753A1E77D9F7006ACDCC /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ FCC7651C201C7F8A007D190C /* libKit.dylib */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 397E08F11E597BD8001374E0 = {
+ isa = PBXGroup;
+ children = (
+ 3956B72D1FAB3DBF00BF5DE4 /* extra */,
+ 39B084E41E5F0B5200682A59 /* Resources */,
+ 3911D89F1E5993600050D6BC /* Support files */,
+ 397E08FC1E597BD8001374E0 /* LibreOfficeLight */,
+ 397E08FB1E597BD8001374E0 /* Products */,
+ 3972753A1E77D9F7006ACDCC /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 397E08FB1E597BD8001374E0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 397E08FA1E597BD8001374E0 /* LibreOfficeLight.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 397E08FC1E597BD8001374E0 /* LibreOfficeLight */ = {
+ isa = PBXGroup;
+ children = (
+ FCC2E3F52004A01400CEB504 /* LOKit */,
+ 39EE81531FA644E800B73AB8 /* Info.plist */,
+ 39503A6F1F94C4AC00F19C78 /* lokit-Bridging-Header.h */,
+ 397E08FD1E597BD8001374E0 /* AppDelegate.swift */,
+ FC31D02A2013500E00E7F402 /* ButtonScrollView.swift */,
+ 3992D8591E5B762A00BEA987 /* DocumentController.swift */,
+ FCAB1CB72009DB6900F1CC34 /* DocumentOverlaysView.swift */,
+ FCC2E3FE2004B59B00CEB504 /* DocumentTiledView.swift */,
+ 39284DB21FA5F207006F43E4 /* DocumentActions.swift */,
+ 39EF4E2E1FA500C9001914AC /* PropertiesController.swift */,
+ FC31D02C2015DE1700E7F402 /* UIViewExtensions.swift */,
+ 392ED9B21E5E4B03005C8435 /* ViewPrintManager.swift */,
+ 399648461E5B87DC00E73E83 /* ViewProperties.swift */,
+ 397E09011E597BD8001374E0 /* Main.storyboard */,
+ 397868D81E59A3EA007F9248 /* LaunchScreen.xib */,
+ );
+ path = LibreOfficeLight;
+ sourceTree = SOURCE_ROOT;
+ };
+ 39B084E41E5F0B5200682A59 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 3941EF13204B4C8900082486 /* config */,
+ 3941EF0E204B4C8900082486 /* filter */,
+ 3941EF07204B4C8900082486 /* fundamentalrc */,
+ 3941EF11204B4C8900082486 /* icudt62l.dat */,
+ 3941EF0D204B4C8900082486 /* offapi.rdb */,
+ 3941EF0A204B4C8900082486 /* oovbaapi.rdb */,
+ 3941EF08204B4C8900082486 /* program */,
+ 3941EF0F204B4C8900082486 /* rc */,
+ 3941EF0B204B4C8900082486 /* registry */,
+ 3941EF0C204B4C8900082486 /* services */,
+ 3941EF09204B4C8900082486 /* services.rdb */,
+ 3941EF14204B4C8900082486 /* share */,
+ 3941EF10204B4C8900082486 /* udkapi.rdb */,
+ 3941EF06204B4C8900082486 /* unorc */,
+ 3941EF12204B4C8900082486 /* welcome.odt */,
+ );
+ name = Resources;
+ sourceTree = SOURCE_ROOT;
+ };
+ FCC2E3F52004A01400CEB504 /* LOKit */ = {
+ isa = PBXGroup;
+ children = (
+ FCC2E4042004B74000CEB504 /* AsyncUtil.swift */,
+ FCC2E3F62004A01400CEB504 /* Document.swift */,
+ FC31D01D2012F65500E7F402 /* DocumentHolder.swift */,
+ FCC2E3F82004A01400CEB504 /* LibreOfficeKitWrapper.swift */,
+ FCC2E3F92004A01400CEB504 /* LOKitThread.swift */,
+ FC31D01F2012F6D300E7F402 /* RenderCache.swift */,
+ FCC2E4022004B72700CEB504 /* Util.swift */,
+ );
+ path = LOKit;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 397E08F91E597BD8001374E0 /* LibreOfficeLight */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 397E09251E597BD8001374E0 /* Build configuration list for PBXNativeTarget "LibreOfficeLight" */;
+ buildPhases = (
+ FC148D13201C7A6600C349CA /* ShellScript */,
+ 397E08F61E597BD8001374E0 /* Sources */,
+ 397E08F71E597BD8001374E0 /* Frameworks */,
+ 397E08F81E597BD8001374E0 /* Resources */,
+ FC148CE420187F7800C349CA /* Embed Libraries */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = LibreOfficeLight;
+ productName = LibreOfficeLight;
+ productReference = 397E08FA1E597BD8001374E0 /* LibreOfficeLight.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 397E08F21E597BD8001374E0 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0820;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = jani;
+ TargetAttributes = {
+ 397E08F91E597BD8001374E0 = {
+ CreatedOnToolsVersion = 8.2;
+ LastSwiftMigration = 0900;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.ApplicationGroups.iOS = {
+ enabled = 0;
+ };
+ com.apple.Push = {
+ enabled = 0;
+ };
+ com.apple.iCloud = {
+ enabled = 1;
+ };
+ };
+ };
+ };
+ };
+ buildConfigurationList = 397E08F51E597BD8001374E0 /* Build configuration list for PBXProject "LibreOfficeLight" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 397E08F11E597BD8001374E0;
+ productRefGroup = 397E08FB1E597BD8001374E0 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 397E08F91E597BD8001374E0 /* LibreOfficeLight */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 397E08F81E597BD8001374E0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3941EF15204B4C8A00082486 /* unorc in Resources */,
+ 3941EF19204B4C8A00082486 /* oovbaapi.rdb in Resources */,
+ 3941EF1D204B4C8A00082486 /* filter in Resources */,
+ 397E09081E597BD8001374E0 /* Assets.xcassets in Resources */,
+ 397868D61E59A3EA007F9248 /* LaunchScreen.xib in Resources */,
+ 39514E002057DC55005599D0 /* shared in Resources */,
+ 3941EF1A204B4C8A00082486 /* registry in Resources */,
+ 3941EF18204B4C8A00082486 /* services.rdb in Resources */,
+ 3941EF1C204B4C8A00082486 /* offapi.rdb in Resources */,
+ 3941EF22204B4C8A00082486 /* config in Resources */,
+ 396F92F71E7AE62400A28C82 /* Settings.bundle in Resources */,
+ 3941EF1E204B4C8A00082486 /* rc in Resources */,
+ 3941EF23204B4C8A00082486 /* share in Resources */,
+ 3941EF1B204B4C8A00082486 /* services in Resources */,
+ 3941EF21204B4C8A00082486 /* welcome.odt in Resources */,
+ 397E09031E597BD8001374E0 /* Main.storyboard in Resources */,
+ 3941EF20204B4C8A00082486 /* icudt62l.dat in Resources */,
+ 3941EF16204B4C8A00082486 /* fundamentalrc in Resources */,
+ 39514E082057E4A8005599D0 /* inc in Resources */,
+ 3941EF1F204B4C8A00082486 /* udkapi.rdb in Resources */,
+ 3941EF17204B4C8A00082486 /* program in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ FC148D13201C7A6600C349CA /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "\nGEN=$PROJECT_DIR/../../workdir/CustomTarget/ios/$CONFIGURATION\\_$ARCHS/libKit.dylib\ncp $GEN $TARGET_BUILD_DIR/libKit.dylib\n\n\n\n\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 397E08F61E597BD8001374E0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FCC2E4032004B72700CEB504 /* Util.swift in Sources */,
+ 392ED9B31E5E4B03005C8435 /* ViewPrintManager.swift in Sources */,
+ FC31D01E2012F65500E7F402 /* DocumentHolder.swift in Sources */,
+ FCAB1CB82009DB6900F1CC34 /* DocumentOverlaysView.swift in Sources */,
+ FC31D0202012F6D300E7F402 /* RenderCache.swift in Sources */,
+ 399648471E5B87DC00E73E83 /* ViewProperties.swift in Sources */,
+ FCC2E3FC2004A01500CEB504 /* LibreOfficeKitWrapper.swift in Sources */,
+ 39284DB31FA5F207006F43E4 /* DocumentActions.swift in Sources */,
+ 3992D85A1E5B762A00BEA987 /* DocumentController.swift in Sources */,
+ FCC2E3FD2004A01500CEB504 /* LOKitThread.swift in Sources */,
+ 397E08FE1E597BD8001374E0 /* AppDelegate.swift in Sources */,
+ FC31D02B2013500E00E7F402 /* ButtonScrollView.swift in Sources */,
+ FCC2E3FA2004A01500CEB504 /* Document.swift in Sources */,
+ FCC2E3FF2004B59B00CEB504 /* DocumentTiledView.swift in Sources */,
+ FC31D02D2015DE1700E7F402 /* UIViewExtensions.swift in Sources */,
+ FCC2E4052004B74000CEB504 /* AsyncUtil.swift in Sources */,
+ 39EF4E2F1FA500C9001914AC /* PropertiesController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 397868D81E59A3EA007F9248 /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 397868D71E59A3EA007F9248 /* en */,
+ );
+ name = LaunchScreen.xib;
+ path = LibreOfficeLight;
+ sourceTree = SOURCE_ROOT;
+ };
+ 397E09011E597BD8001374E0 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 397E09021E597BD8001374E0 /* en */,
+ );
+ name = Main.storyboard;
+ path = LibreOfficeLight;
+ sourceTree = SOURCE_ROOT;
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 397E09231E597BD8001374E0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/../../workdir/CustomTarget/ios/$(PROJECT_NAME).profdata";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_BITCODE = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(inherited)";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.3;
+ LD_MAP_FILE_PATH = "";
+ LIBRARY_SEARCH_PATHS = "$PROJECT_DIR/../../workdir/CustomTarget/ios/debug/**";
+ MACH_O_TYPE = mh_execute;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OBJC_BRIDGING_HEADER = "lokit-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
+ SYMROOT = ../../workdir/CustomTarget/ios/build;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "arm64 x86_64";
+ };
+ name = Debug;
+ };
+ 397E09241E597BD8001374E0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/../../workdir/CustomTarget/ios/$(PROJECT_NAME).profdata";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_BITCODE = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(inherited)";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.3;
+ LD_MAP_FILE_PATH = "";
+ LIBRARY_SEARCH_PATHS = "$PROJECT_DIR/../../workdir/CustomTarget/ios/release/**";
+ MACH_O_TYPE = mh_execute;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_OBJC_BRIDGING_HEADER = "lokit-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
+ SYMROOT = ../../workdir/CustomTarget/ios/build;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VALID_ARCHS = "arm64 x86_64";
+ };
+ name = Release;
+ };
+ 397E09261E597BD8001374E0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_INFINITE_RECURSION = NO;
+ CODE_SIGN_ENTITLEMENTS = LibreOfficeLight/LibreOfficeLight.entitlements;
+ DEVELOPMENT_TEAM = J4FQ687VJK;
+ ENABLE_TESTABILITY = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "LibreOfficeLight/LibreOfficeLight-Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "IOS=1",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/../../include",
+ );
+ INFOPLIST_FILE = LibreOfficeLight/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "";
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = org.libreoffice.ios.LibreOfficeLight;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "LibreOfficeLight/lokit-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Off;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "arm64 x86_64";
+ };
+ name = Debug;
+ };
+ 397E09271E597BD8001374E0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_INFINITE_RECURSION = NO;
+ CODE_SIGN_ENTITLEMENTS = LibreOfficeLight/LibreOfficeLight.entitlements;
+ COPY_PHASE_STRIP = YES;
+ DEVELOPMENT_TEAM = J4FQ687VJK;
+ ENABLE_TESTABILITY = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "LibreOfficeLight/LibreOfficeLight-Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = "IOS=1";
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/../../include",
+ );
+ INFOPLIST_FILE = LibreOfficeLight/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "";
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = org.libreoffice.ios.LibreOfficeLight;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "LibreOfficeLight/lokit-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Off;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "arm64 x86_64";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 397E08F51E597BD8001374E0 /* Build configuration list for PBXProject "LibreOfficeLight" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 397E09231E597BD8001374E0 /* Debug */,
+ 397E09241E597BD8001374E0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 397E09251E597BD8001374E0 /* Build configuration list for PBXNativeTarget "LibreOfficeLight" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 397E09261E597BD8001374E0 /* Debug */,
+ 397E09271E597BD8001374E0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 397E08F21E597BD8001374E0 /* Project object */;
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme
new file mode 100644
index 000000000..450c96e3b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0930"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <EnvironmentVariables>
+ <EnvironmentVariable
+ key = "SAL_LOG"
+ value = "+INFO+WARN"
+ isEnabled = "YES">
+ </EnvironmentVariable>
+ </EnvironmentVariables>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Debug"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Release.xcscheme b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Release.xcscheme
new file mode 100644
index 000000000..9c3d62de8
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight.xcodeproj/xcshareddata/xcschemes/Release.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0930"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Release"
+ selectedDebuggerIdentifier = ""
+ selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "397E08F91E597BD8001374E0"
+ BuildableName = "LibreOfficeLight.app"
+ BlueprintName = "LibreOfficeLight"
+ ReferencedContainer = "container:LibreOfficeLight.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/AppDelegate.swift b/ios/LibreOfficeLight/LibreOfficeLight/AppDelegate.swift
new file mode 100644
index 000000000..f0b5f6bd3
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/AppDelegate.swift
@@ -0,0 +1,117 @@
+//
+// 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/.
+//
+import UIKit
+import Foundation
+
+
+// AppDelegate is a Delegate class that receives calls from the iOS
+// kernel, and theirby allows stop/start/sleep of the application
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate
+{
+ var window: UIWindow?
+
+
+
+ // sent when clicking on an OO document in another app
+ // allowing this app to handle the document.
+ // remark if the app is not started it will be started first
+ func application(_ app: UIApplication,
+ open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:])
+ -> Bool
+ {
+ let document = window?.rootViewController?.childViewControllers[0] as! DocumentController
+ document.doOpen(url)
+ return true
+ }
+
+
+
+ // this function is called when the app is first started (loaded from EEProm)
+ // it initializes the LO system and prepares for a normal run
+ func application(_ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions:
+ [UIApplicationLaunchOptionsKey: Any]?)
+ -> Bool
+ {
+ // Get version info
+ let appInfo = Bundle.main.infoDictionary! as Dictionary<String,AnyObject>
+ let applicationVersion = (appInfo["CFBundleShortVersionString"] as! String) + "." +
+ (appInfo["CFBundleVersion"] as! String)
+
+ // Add version string to setting
+ let defaults = UserDefaults.standard
+ defaults.set(applicationVersion, forKey: "application_version")
+ defaults.synchronize()
+
+ // start LibreOfficeKit
+ let _ = LOKitThread.instance
+
+ return true
+ }
+
+
+
+ // Sent when the application is about to move from active to inactive state.
+ // This can occur for certain types of temporary interruptions
+ // (such as an incoming phone call or SMS message)
+ // or when the user quits the application and it begins the transition
+ // jto the background state.
+ // Use this method to pause ongoing tasks, disable timers,
+ // and invalidate graphics rendering callbacks.
+ func applicationWillResignActive(_ application: UIApplication)
+ {
+ // NOT used in this App
+ }
+
+
+
+ // Sent when the application enters background (hipernating)
+ // Use this method to release shared resources, save user data, invalidate timers,
+ // and store enough application state information to restore your application
+ // to its current state jin case it is terminated later.
+ // If your application supports background execution,
+ // this method is called instead of applicationWillTerminate: when the user quits.
+ func applicationDidEnterBackground(_ application: UIApplication)
+ {
+ let document = window?.rootViewController?.childViewControllers[0]
+ as! DocumentController
+ document.Hipernate()
+ }
+
+
+
+ // Sent before the application reenters foreground (hipernating -> active)
+ // Restart timers, tasks as well as graphic rendering
+ func applicationWillEnterForeground(_ application: UIApplication)
+ {
+ let document = window?.rootViewController?.childViewControllers[0] as! DocumentController
+ document.LeaveHipernate()
+ }
+
+
+
+ // Sent after the application reenters foreground (hipernating -> active)
+ // Restart timers, tasks as well as graphic rendering
+ func applicationDidBecomeActive(_ application: UIApplication)
+ {
+ // NOT used in this App
+ }
+
+
+
+ // Sent when the application is about to terminate. Save data if appropriate.
+ // See also applicationDidEnterBackground:.
+ // Saves changes in the application's managed object context before the application terminates.
+ func applicationWillTerminate(_ application: UIApplication)
+ {
+ let document = window?.rootViewController?.childViewControllers[0] as! DocumentController
+ document.Hipernate()
+ }
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000..b179c2c53
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "filename" : "LibreOffice-40.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "filename" : "LibreOffice-60.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "LibreOffice-58.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "filename" : "LibreOffice-87.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "LibreOffice-80.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "filename" : "LibreOffice-120.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "LibreOffice-120.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "filename" : "LibreOffice-180.png",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "filename" : "LibreOffice-20.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "filename" : "LibreOffice-40.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-29.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-58.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-40.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-80.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-76.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "LibreOffice-152.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "filename" : "LibreOffice-167.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "LibreOffice-1024.png",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-1024.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-1024.png
new file mode 100644
index 000000000..e25eb6bdd
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-1024.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-120.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-120.png
new file mode 100644
index 000000000..49a7a1070
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-120.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-152.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-152.png
new file mode 100644
index 000000000..9a204a930
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-152.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-167.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-167.png
new file mode 100644
index 000000000..ef0033f9a
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-167.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-180.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-180.png
new file mode 100644
index 000000000..2fdcb30dc
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-180.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-20.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-20.png
new file mode 100644
index 000000000..ba82eb87b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-20.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-29.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-29.png
new file mode 100644
index 000000000..5a03ed3f4
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-29.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-40.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-40.png
new file mode 100644
index 000000000..1fefbff4b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-40.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-58.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-58.png
new file mode 100644
index 000000000..cd6cf1338
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-58.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-60.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-60.png
new file mode 100644
index 000000000..00774322c
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-60.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-76.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-76.png
new file mode 100644
index 000000000..879629fc8
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-76.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-80.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-80.png
new file mode 100644
index 000000000..1ae49c48c
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-80.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-87.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-87.png
new file mode 100644
index 000000000..679f6abc0
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/AppIcon.appiconset/LibreOffice-87.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/Contents.json
new file mode 100644
index 000000000..cc9fb3d1a
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x",
+ "filename" : "back.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x",
+ "filename" : "back@2x.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x",
+ "filename" : "back@3x.png"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back.png
new file mode 100644
index 000000000..0b9776a64
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@2x.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@2x.png
new file mode 100644
index 000000000..6e7c3995d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@2x.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@3x.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@3x.png
new file mode 100644
index 000000000..e66980cdd
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/back.imageset/back@3x.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/Contents.json
new file mode 100644
index 000000000..da4a164c9
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/Contents.json
new file mode 100644
index 000000000..885f35756
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "drawing-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/drawing-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/drawing-template.icns
new file mode 100644
index 000000000..64c373eca
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing-template.dataset/drawing-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/Contents.json
new file mode 100644
index 000000000..3e1c14b1b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "drawing.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/drawing.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/drawing.icns
new file mode 100644
index 000000000..d179d041a
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/drawing.dataset/drawing.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/Contents.json
new file mode 100644
index 000000000..816e9aa12
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "empty-document.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/empty-document.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/empty-document.ico
new file mode 100644
index 000000000..ec11e8fe5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-document.dataset/empty-document.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/Contents.json
new file mode 100644
index 000000000..8d4ccc066
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "empty-template.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/empty-template.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/empty-template.ico
new file mode 100644
index 000000000..ec11e8fe5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/empty-template.dataset/empty-template.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/Contents.json
new file mode 100644
index 000000000..f35fc2be7
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "extension.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/extension.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/extension.icns
new file mode 100644
index 000000000..cec1b92c3
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/extension.dataset/extension.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/Contents.json
new file mode 100644
index 000000000..dec8005ed
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "formula.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/formula.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/formula.icns
new file mode 100644
index 000000000..f6dc58809
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/formula.dataset/formula.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/Contents.json
new file mode 100644
index 000000000..1fb866b12
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "main.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/main.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/main.icns
new file mode 100644
index 000000000..c3e1bf693
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/main.dataset/main.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/Contents.json
new file mode 100644
index 000000000..1b65ad0ed
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "master-document.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/master-document.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/master-document.icns
new file mode 100644
index 000000000..4b0cf1bb7
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/master-document.dataset/master-document.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/Contents.json
new file mode 100644
index 000000000..5f270e1fe
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-database.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/oasis-database.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/oasis-database.icns
new file mode 100644
index 000000000..e523fdd9d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-database.dataset/oasis-database.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/Contents.json
new file mode 100644
index 000000000..c2c2cc129
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-drawing-template.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/oasis-drawing-template.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/oasis-drawing-template.ico
new file mode 100644
index 000000000..9991270a5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing-template.dataset/oasis-drawing-template.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/Contents.json
new file mode 100644
index 000000000..74ba17140
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-drawing.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/oasis-drawing.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/oasis-drawing.icns
new file mode 100644
index 000000000..64563d257
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-drawing.dataset/oasis-drawing.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/Contents.json
new file mode 100644
index 000000000..19236e87f
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-formula.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/oasis-formula.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/oasis-formula.ico
new file mode 100644
index 000000000..07b3e8ecf
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-formula.dataset/oasis-formula.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/Contents.json
new file mode 100644
index 000000000..47b7fb7ef
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-master-document-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/oasis-master-document-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/oasis-master-document-template.icns
new file mode 100644
index 000000000..9115dfc4b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document-template.dataset/oasis-master-document-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/Contents.json
new file mode 100644
index 000000000..5043c1477
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-master-document.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/oasis-master-document.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/oasis-master-document.ico
new file mode 100644
index 000000000..0ac9681b1
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-master-document.dataset/oasis-master-document.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/Contents.json
new file mode 100644
index 000000000..0f5874081
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-presentation-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/oasis-presentation-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/oasis-presentation-template.icns
new file mode 100644
index 000000000..6bf52a184
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation-template.dataset/oasis-presentation-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/Contents.json
new file mode 100644
index 000000000..98bd94f4d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-presentation.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/oasis-presentation.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/oasis-presentation.ico
new file mode 100644
index 000000000..0845cad87
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-presentation.dataset/oasis-presentation.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/Contents.json
new file mode 100644
index 000000000..97df63130
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-spreadsheet-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/oasis-spreadsheet-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/oasis-spreadsheet-template.icns
new file mode 100644
index 000000000..d21737853
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet-template.dataset/oasis-spreadsheet-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/Contents.json
new file mode 100644
index 000000000..189679bfc
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-spreadsheet.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/oasis-spreadsheet.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/oasis-spreadsheet.icns
new file mode 100644
index 000000000..95cc98b34
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-spreadsheet.dataset/oasis-spreadsheet.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/Contents.json
new file mode 100644
index 000000000..ead3ca01d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-text-template.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/oasis-text-template.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/oasis-text-template.ico
new file mode 100644
index 000000000..71136e778
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text-template.dataset/oasis-text-template.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/Contents.json
new file mode 100644
index 000000000..36818aec0
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-text.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/oasis-text.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/oasis-text.ico
new file mode 100644
index 000000000..70210b0ec
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-text.dataset/oasis-text.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/Contents.json
new file mode 100644
index 000000000..59b4f2d07
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "oasis-web-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/oasis-web-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/oasis-web-template.icns
new file mode 100644
index 000000000..06fcd5ad1
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/oasis-web-template.dataset/oasis-web-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/Contents.json
new file mode 100644
index 000000000..26efddc8e
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "open.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/open.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/open.ico
new file mode 100644
index 000000000..ec11e8fe5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/open.dataset/open.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/Contents.json
new file mode 100644
index 000000000..1cf424888
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "presentation-template.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/presentation-template.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/presentation-template.ico
new file mode 100644
index 000000000..b24847495
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation-template.dataset/presentation-template.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/Contents.json
new file mode 100644
index 000000000..48727c0d5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "presentation.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/presentation.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/presentation.ico
new file mode 100644
index 000000000..0845cad87
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/presentation.dataset/presentation.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/Contents.json
new file mode 100644
index 000000000..30042d0d9
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "soffice.ico"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/soffice.ico b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/soffice.ico
new file mode 100644
index 000000000..ec11e8fe5
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/soffice.dataset/soffice.ico
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/Contents.json
new file mode 100644
index 000000000..01557a908
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "spreadsheet-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/spreadsheet-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/spreadsheet-template.icns
new file mode 100644
index 000000000..f527a14b7
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet-template.dataset/spreadsheet-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/Contents.json
new file mode 100644
index 000000000..87e81d269
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "spreadsheet.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/spreadsheet.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/spreadsheet.icns
new file mode 100644
index 000000000..9d61c699c
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/spreadsheet.dataset/spreadsheet.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/Contents.json
new file mode 100644
index 000000000..c5cbe2c9c
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "text-template.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/text-template.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/text-template.icns
new file mode 100644
index 000000000..accd48b9b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text-template.dataset/text-template.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/Contents.json
new file mode 100644
index 000000000..3fd87b588
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "data" : [
+ {
+ "idiom" : "universal",
+ "filename" : "text.icns"
+ }
+ ]
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/text.icns b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/text.icns
new file mode 100644
index 000000000..9b7a301ee
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/document.icons/text.dataset/text.icns
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/Contents.json
new file mode 100644
index 000000000..1f910096d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x",
+ "filename" : "intro.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x",
+ "filename" : "intro.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x",
+ "filename" : "intro.png"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/intro.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/intro.png
new file mode 100644
index 000000000..d27f8858d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/intro.imageset/intro.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/Contents.json b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/Contents.json
new file mode 100644
index 000000000..da2ac2bbd
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "scale" : "1x",
+ "filename" : "menu.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x",
+ "filename" : "menu@2x.png"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x",
+ "filename" : "menu@3x.png"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu.png
new file mode 100644
index 000000000..fe97b0cfe
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@2x.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@2x.png
new file mode 100644
index 000000000..f5e9a1597
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@2x.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@3x.png b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@3x.png
new file mode 100644
index 000000000..9f00717fe
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Assets.xcassets/menu.imageset/menu@3x.png
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/ButtonScrollView.swift b/ios/LibreOfficeLight/LibreOfficeLight/ButtonScrollView.swift
new file mode 100644
index 000000000..615c145fe
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/ButtonScrollView.swift
@@ -0,0 +1,145 @@
+//
+// 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/.
+//
+import UIKit
+
+/// Scrollable list of buttons.
+/// Kind of like a tab bar, but doesn't maintain or switch between views, just calls back on click
+open class ButtonScrollView: UIScrollView
+{
+ var buttonList: ButtonList? = nil
+
+ var buttonClickedCallback: ( (Int) -> () )? = nil
+
+ var selectedIndex: Int?
+ {
+ get {
+ return buttonList?.selectedIndex
+ }
+ set {
+ buttonList?.selectedIndex = selectedIndex
+ }
+ }
+
+ public override init(frame: CGRect)
+ {
+ super.init(frame: frame)
+ }
+
+ public required init?(coder aDecoder: NSCoder)
+ {
+ super.init(coder: aDecoder)
+ }
+
+ public func setButtonLabels(labels: [String])
+ {
+ if let bl = buttonList
+ {
+ bl.removeFromSuperview()
+ }
+ let bl = ButtonList(frame: CGRect(x:0, y:0, width: self.frame.width, height:44),
+ labels: labels,
+ owner: self)
+ self.addSubview(bl)
+ self.contentSize = bl.frame.size
+ self.buttonList = bl
+ }
+}
+
+/// Horizontally laid out buttons, living within the owned scroll view
+open class ButtonList: UIView
+{
+ let labels: [String]
+ let gap: CGFloat = 10.0
+ let topGap: CGFloat = 8
+ weak var owner: ButtonScrollView? = nil
+
+ var buttonBackground = UIColor(white: 0.6, alpha: 1)
+ var selectedButtonBackground = UIColor.white
+
+ var selectedIndex: Int? = 0
+ {
+ didSet {
+ runOnMain {
+ self.highlightSelectedIndex()
+ }
+ }
+ }
+
+ public init(frame: CGRect, labels: [String], owner: ButtonScrollView)
+ {
+ self.labels = labels
+ self.owner = owner
+ super.init(frame: frame)
+ self.backgroundColor = UIColor(white: 0.9, alpha: 1)
+
+ var idx = 0
+ for label in labels
+ {
+ let b = UIButton(type: .custom)
+ b.setTitle(label, for: .normal)
+ b.backgroundColor = buttonBackground
+ b.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
+ b.layer.cornerRadius = 4
+ b.tag = idx
+ b.addTarget(self, action: #selector(buttonTapped), for: UIControlEvents.touchUpInside)
+ self.addSubview(b)
+ idx += 1
+ }
+ self.layoutSubviews()
+ }
+
+ @objc func buttonTapped(sender: UIButton, forEvent event: UIEvent)
+ {
+ let idx = sender.tag
+ owner?.buttonClickedCallback?(idx)
+ self.selectedIndex = idx
+ }
+
+ public required init?(coder aDecoder: NSCoder)
+ {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ public var buttons: [UIButton]
+ {
+ return self.subviews.compactMap({ $0 as? UIButton })
+ }
+
+ open override func layoutSubviews()
+ {
+
+ var x: CGFloat = gap
+ for button in buttons
+ {
+ button.sizeToFit()
+ let s = button.frame.size
+ button.frame = CGRect(x: x, y: topGap, width: s.width, height: s.height)
+ x = x + (s.width + gap)
+ }
+ highlightSelectedIndex()
+ self.frame = CGRect(x:0, y: 0, width: x, height: self.frame.height)
+ }
+
+ open func highlightSelectedIndex()
+ {
+ for (index, button) in buttons.enumerated()
+ {
+ if (index == selectedIndex)
+ {
+ button.backgroundColor = selectedButtonBackground
+ button.setTitleColor(.black, for: .normal)
+ }
+ else
+ {
+ button.backgroundColor = buttonBackground
+ button.setTitleColor(.white, for: .normal)
+ }
+
+ }
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/DocumentActions.swift b/ios/LibreOfficeLight/LibreOfficeLight/DocumentActions.swift
new file mode 100644
index 000000000..dddb3b22d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/DocumentActions.swift
@@ -0,0 +1,75 @@
+//
+// 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/.
+//
+import UIKit
+
+
+
+// DocumentActions is the main menu popover started from DocumentController
+// it allows the user to invoke global actions and delegates the processing
+// back to the DocumentController
+class DocumentActions: UITableViewController
+{
+ // Pointer to callback class (in reality instance of DocumentController)
+ var delegate : MenuDelegate?
+
+
+
+ // set by DocumentController before invoking the menu
+ // the variable is used to control which menu entries are active
+ var isDocActive : Bool = false
+
+
+
+ // Reference to instances of the buttons
+ @IBOutlet weak var buttonOpen: UIButton!
+ @IBOutlet weak var buttonProperties: UIButton!
+ @IBOutlet weak var buttonSave: UIButton!
+ @IBOutlet weak var buttonClose: UIButton!
+ @IBOutlet weak var buttonSaveAs: UIButton!
+ @IBOutlet weak var buttonSaveAsPDF: UIButton!
+ @IBOutlet weak var buttonPrint: UIButton!
+
+
+
+ // called once controller is loaded
+ override func viewDidLoad()
+ {
+ super.viewDidLoad()
+
+ // Some menu entries are only active when a document is loaded
+ buttonSave.isEnabled = isDocActive
+ buttonProperties.isEnabled = isDocActive
+ buttonClose.isEnabled = isDocActive
+ buttonSaveAs.isEnabled = isDocActive
+ buttonSaveAsPDF.isEnabled = isDocActive
+ buttonPrint.isEnabled = isDocActive
+ }
+
+
+
+ // Called when user click on a menu entry (all entries goes here)
+ // see storyboard Document actions scene for details
+ @IBAction func actionMenuSelect(_ sender: UIButton)
+ {
+ // make popover go away, when this function returns
+ dismiss(animated: false)
+
+ // inform DocumentController about the selected entry
+ delegate?.actionMenuSelected(sender.tag)
+ }
+}
+
+
+
+// Protocol for action popover callback
+protocol MenuDelegate
+{
+ // inform delegate about selected menu entry
+ func actionMenuSelected(_ tag : Int)
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/DocumentController.swift b/ios/LibreOfficeLight/LibreOfficeLight/DocumentController.swift
new file mode 100644
index 000000000..af192249b
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/DocumentController.swift
@@ -0,0 +1,598 @@
+//
+// 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/.
+//
+import UIKit
+
+
+// DocumentController is the main viewer in the app, it displays the selected
+// documents and holds a top entry to view the properties as well as a normal
+// menu to handle global actions
+// It is a delegate class to receive Menu events as well as file handling events
+class DocumentController: UIViewController, MenuDelegate, UIDocumentBrowserViewControllerDelegate
+{
+ var document: DocumentHolder? = nil
+
+ var documentView: DocumentTiledView? = nil
+ var documentOverlaysView: DocumentOverlaysView? = nil
+
+ // *** Handling of DocumentController
+ // this is normal functions every controller must implement
+
+
+ // holds known document types
+ var KnownDocumentTypes : [String] = []
+
+ var zeroInsets: UIEdgeInsets = .zero
+
+ @IBOutlet weak var scrollView: UIScrollView!
+ @IBOutlet weak var mask: UIView!
+ @IBOutlet weak var progressBar: UIProgressView!
+ @IBOutlet weak var searchBar: UISearchBar!
+ @IBOutlet weak var buttonScrollView: ButtonScrollView!
+
+ deinit
+ {
+ NotificationCenter.default.removeObserver(self)
+ }
+
+ // called once controller is loaded
+ override func viewDidLoad()
+ {
+ super.viewDidLoad()
+
+ // loading known document types, so we can use them for the open call
+ let path = Bundle.main.path(forResource: "Info", ofType: "plist")
+ let plist = NSDictionary(contentsOfFile: path!)
+ for dict in (plist!.object(forKey: "UTExportedTypeDeclarations") as! [NSDictionary]) +
+ (plist!.object(forKey: "UTImportedTypeDeclarations") as! [NSDictionary]) {
+ let x = ((dict["UTTypeTagSpecification"] as! NSDictionary)["public.filename-extension"] as! NSArray)
+ KnownDocumentTypes.append( x[0] as! String )
+ }
+ LOKitThread.instance.progressDelegate = self
+ }
+
+ override func viewWillAppear(_ animated: Bool)
+ {
+ super.viewWillAppear(animated)
+ registerKeyboardNotifications()
+ }
+
+ override func viewDidAppear(_ animated: Bool)
+ {
+ super.viewDidAppear(animated)
+
+ // Always load the 'welcome' file, as per the android app
+ let res = Bundle.main.url(forResource: "welcome", withExtension: "odt")
+
+ // uncomment for test data in resources until the doc picker works properly
+ //let res = Bundle.main.url(forResource: "testdata/2", withExtension: "xlsx")
+
+ if let exampleDoc = res
+ {
+ self.doOpen(exampleDoc)
+ }
+ }
+
+ // called when there is a memory constraint
+ override func didReceiveMemoryWarning()
+ {
+ super.didReceiveMemoryWarning()
+ // not used in this App
+ }
+
+ @IBAction func searchIconTapped(_ sender: Any)
+ {
+ searchBar.isHidden = !searchBar.isHidden
+ if (!searchBar.isHidden)
+ {
+ searchBar.becomeFirstResponder()
+ }
+ }
+
+
+ // *** Handling of Background (hipernate)
+ // iOS is not true multitasking, only 1 app can be active (foreground) at any time,
+ // therefore apps frequently are moved to the background.
+ // background really means hipernate by terminating all threads and solely keep the
+ // data
+
+
+
+ // Moving to hipernate
+ public func Hipernate() -> Void
+ {
+ //BridgeLOkit_Hipernate() // FIXME
+ }
+
+
+
+ // Moving back to foreground
+ public func LeaveHipernate() -> Void
+ {
+ //BridgeLOkit_LeaveHipernate() // FIXME
+ }
+
+
+
+ // *** handling of PropertiesController
+ // The PropertiesController is a left sidebar, that will scroll in when activated
+ // The Controller handles manipulation of properties in the document
+
+
+
+ // Activate/Deactivate PropertiesController (from navigationController, see storyboard)
+ @IBAction func doProperties(_ sender: UIBarButtonItem)
+ {
+ // Check if deactivation
+ if (sender.tag == 99) {
+ // Deactivate
+
+ // Mark it as deactivated (it stays loaded)
+ sender.tag = 0;
+
+ // get handle of PropertiesController
+ let viewMenuBack : UIView = view.subviews.last!
+
+ // Blend out sidebar
+ UIView.animate(withDuration: 0.3, animations: { () -> Void in
+ var frameMenu : CGRect = viewMenuBack.frame
+ frameMenu.origin.x = -1 * UIScreen.main.bounds.size.width
+ viewMenuBack.frame = frameMenu
+ viewMenuBack.layoutIfNeeded()
+ viewMenuBack.backgroundColor = UIColor.clear
+ }, completion: { (finished) -> Void in
+ viewMenuBack.removeFromSuperview()
+ })
+ }
+ else {
+ // Activate
+
+ // Mark as activated
+ sender.isEnabled = false
+ sender.tag = 99
+
+ // make instance of PropertiesController
+ let prop : PropertiesController = self.storyboard!.instantiateViewController(
+ withIdentifier: "PropertiesController") as! PropertiesController
+ view.addSubview(prop.view)
+ addChildViewController(prop)
+ prop.view.layoutIfNeeded()
+ prop.view.frame=CGRect(x: 0 - UIScreen.main.bounds.size.width,
+ y: 0,
+ width: UIScreen.main.bounds.size.width,
+ height: UIScreen.main.bounds.size.height);
+
+ // Blend in sidebar
+ UIView.animate(withDuration: 0.3, animations: { () -> Void in
+ prop.view.frame=CGRect(x: 0,
+ y: 0,
+ width: UIScreen.main.bounds.size.width,
+ height: UIScreen.main.bounds.size.height);
+ sender.isEnabled = true
+ }, completion:nil)
+ }
+ }
+
+
+
+ // *** Handling of menu popover
+ // the menu contains all global functions and use seque/delegate
+
+
+
+ var currentDocumentName : String? = nil
+
+
+
+ // Last stop before displaying popover
+ override func prepare(for segue: UIStoryboardSegue, sender: Any?)
+ {
+ // "showActions" is the name of the popover menu, see storyboard
+ if segue.identifier == "showActions" {
+ let vc = segue.destination as! DocumentActions
+ vc.delegate = self
+ vc.isDocActive = (currentDocumentName != nil)
+ }
+ }
+
+
+
+ // Delegate call from menu (see protocol MenuDelegate)
+ func actionMenuSelected(_ tag : Int)
+ {
+ // a tag can sadly enough only be a number and not a string,
+ // whenever adding a menu entry, it (of course) needs to be added
+ // to the Document actions scene in storyboard and assigned a tag number
+ // the tag number must be repeated in the following switch
+ // BE CAREFUL to keep the tags synchronized (manually)
+ switch tag
+ {
+ case 1: // Open...
+ startOpenDocument()
+
+ case 2: // Properties
+ showProperties()
+
+ case 3: // Save
+ doSave()
+
+ case 4: // Close...
+ doClose()
+
+ case 5: // Save as...
+ doSaveAs()
+
+ case 6: // Save as PDF...
+ doSaveAsPDF()
+
+ case 7: // Print...
+ startPrint()
+
+ default: // should not happen
+ print("unknown menu" + String(tag))
+ }
+ }
+
+
+
+ // *** handling of menu actions
+ // This is the real base of the application
+
+ var openMenu : UIDocumentBrowserViewController? = nil
+
+ // Load document into LibreOfficeKit and present it
+ internal func startOpenDocument()
+ {
+ openMenu = UIDocumentBrowserViewController()
+ openMenu?.allowsDocumentCreation = true
+ openMenu?.browserUserInterfaceStyle = UIDocumentBrowserViewController.BrowserUserInterfaceStyle.dark
+ openMenu?.delegate = self
+ self.present(openMenu!, animated: true, completion: nil)
+ }
+
+
+
+ // Show document properties (new overloaded page)
+ internal func showProperties()
+ {
+ //FIXME
+ print("menu Properties to be done")
+ }
+
+
+
+ // Save current document
+ internal func doSave()
+ {
+ //FIXME
+ print("menu Save to be done")
+ }
+
+
+
+ // Close current document (without saving)
+ internal func doClose()
+ {
+ //FIXME
+ print("menu Close to be done")
+ }
+
+
+
+ // make a copy of current document, and save
+ internal func doSaveAs()
+ {
+ //FIXME
+ print("menu Save as... to be done")
+ }
+
+
+
+ // save current document as PDF
+ internal func doSaveAsPDF()
+ {
+ //FIXME
+ print("menu Save as PDF... to be done")
+ }
+
+
+
+ // print current document
+ internal func startPrint()
+ {
+ //FIXME
+ print("menu Print... to be done")
+ }
+
+
+
+ // *** Handling of DocumentViewController delegate functions
+ // this handles open/create/copy/delete document
+
+
+
+ // Create an empty document, and present it
+ internal func documentBrowser(_ controller: UIDocumentBrowserViewController,
+ didRequestDocumentCreationWithHandler importHandler: @escaping (URL?,
+ UIDocumentBrowserViewController.ImportMode) -> Void)
+ {
+ //FIXME
+ }
+
+
+
+ // import (copy from iCloud to iPad) document, open it and present it
+ internal func documentBrowser(_ controller: UIDocumentBrowserViewController,
+ didImportDocumentAt sourceURL: URL,
+ toDestinationURL destinationURL: URL)
+ {
+ //FIXME
+ }
+
+
+
+ // Import failed, inform user
+ internal func documentBrowser(_ controller: UIDocumentBrowserViewController,
+ failedToImportDocumentAt documentURL: URL,
+ error: Error?)
+ {
+ //FIXME
+ }
+
+
+
+ // open document and present it
+ internal func documentBrowser(_ controller: UIDocumentBrowserViewController,
+ didPickDocumentURLs documentURLs: [URL])
+ {
+ openMenu?.dismiss(animated: true, completion: nil)
+ openMenu = nil
+ doOpen(documentURLs[0])
+ }
+
+
+
+ // *** Handling of document (open/print)
+
+
+
+ // Real open and presentation of document
+ public func doOpen(_ docURL : URL)
+ {
+ LOKitThread.instance.documentLoad(url: docURL.absoluteString)
+ {
+ doc, error in
+
+ if let document = doc
+ {
+
+ runOnMain
+ {
+ self.setDocument(doc: document)
+ }
+ }
+ else
+ {
+ // TODO - alert user of failure
+
+ }
+ }
+
+ /* FIXME
+ BridgeLOkit_Sizing(4, 4, 256, 256);
+ */
+ }
+
+ /// Sets the document to use and set's up it's view. Should be called on the main thread
+ public func setDocument(doc: DocumentHolder)
+ {
+ if let _ = self.document
+ {
+ // TODO - cleanup
+ self.document = nil
+ }
+ if let exisitingView = self.documentView
+ {
+ exisitingView.removeFromSuperview()
+ self.documentView = nil // forces the close of the view and it's held documents before we setup the new one
+ }
+ // also remove current overlays and start fresh
+ documentOverlaysView?.removeFromSuperview()
+
+ // setup the new doc view
+ self.document = doc
+ // setup delegates
+ doc.searchDelegate = self
+
+ let frameToUse = self.scrollView.frame
+
+ let docView = DocumentTiledView(frame: frameToUse, document: doc, scale: 1.0)
+
+ self.scrollView.addSubview(docView)
+ self.scrollView.contentSize = docView.frame.size
+ self.documentView = docView
+
+ // overlay view
+ let overlay = DocumentOverlaysView(docTiledView: docView)
+ docView.addSubview(overlay)
+ self.documentOverlaysView = overlay
+
+ // button view - used for spreadsheet tabs
+ if doc.isSpeadsheet
+ {
+ buttonScrollView.isHidden = false
+ buttonScrollView.setButtonLabels(labels: doc.partNames)
+ buttonScrollView.buttonClickedCallback = {
+ [weak self] index in
+ self?.document?.async {
+ $0.setPart(nPart: Int32(index))
+ runOnMain {
+ self?.documentView?.setNeedsDisplay()
+ }
+ }
+ }
+ // make room for the scroll view
+ zeroInsets = UIEdgeInsets(top: 0, left: 0, bottom: buttonScrollView.height, right: 0)
+ }
+ else
+ {
+ zeroInsets = .zero
+ buttonScrollView.isHidden = true
+ }
+ scrollView.contentInset = zeroInsets
+
+ // debugging view borders
+ /*
+ self.scrollView.layer.borderColor = UIColor.red.cgColor
+ self.scrollView.layer.borderWidth = 1.0
+ docView.layer.borderColor = UIColor.green.cgColor
+ docView.layer.borderWidth = 1.0
+ */
+ }
+
+ // MARK: - UIScrollViewDelegate
+}
+
+extension DocumentController: UIScrollViewDelegate
+{
+ // return a view that will be scaled. if delegate returns nil, nothing happens
+ func viewForZooming(in scrollView: UIScrollView) -> UIView?
+ {
+ return self.documentView
+ }
+
+ // called before the scroll view begins zooming its content
+ func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?)
+ {
+ print("scrollViewWillBeginZooming currentScale=\(scrollView.zoomScale)")
+ }
+
+ // scale between minimum and maximum. called after any 'bounce' animations
+ func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
+ {
+ print("scrollViewDidEndZooming scale=\(scale)")
+ self.documentView?.scrollViewDidEndZooming(scrollView, with: view, atScale: scale)
+ }
+}
+
+ // MARK: - UIKeyInput
+// public var hasText: Bool
+// {
+// true
+// }
+//
+//
+// public func insertText(_ text: String)
+// {
+//
+// }
+//
+// public func deleteBackward()
+// {
+//
+// }
+
+extension DocumentController: ProgressDelegate
+{
+ // MARK: - ProgressDelegate
+ func statusIndicatorStart()
+ {
+ self.mask?.isHidden = false
+ self.progressBar?.isHidden = false
+ self.progressBar?.progress = 0.0
+ }
+
+ func statusIndicatorFinish()
+ {
+ // what would be nice would be to be able to wait until the initial tiles have rendered...
+ self.mask?.isHidden = true
+ self.progressBar?.isHidden = true
+ }
+
+ func statusIndicatorSetValue(value: Double)
+ {
+ self.progressBar?.progress = Float(value) / 100.0
+ }
+}
+
+extension DocumentController: UISearchBarDelegate
+{
+ // called when text changes (including clear)
+ func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
+ {
+
+ }
+
+
+ // called when keyboard search button pressed
+ func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
+ {
+ if let text = searchBar.text
+ {
+ if text.count > 0
+ {
+ document?.search(searchString: text, forwardDirection: true, from: CGPoint(x:0, y:0) )
+ }
+ }
+ }
+
+ func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
+ {
+ searchBar.isHidden = true
+ }
+}
+
+extension DocumentController: SearchDelegate
+{
+ func searchNotFound()
+ {
+ // TODO: tell user somehow
+ self.documentOverlaysView?.clearSearchResults()
+ }
+
+ func searchResultSelection(searchResults: SearchResults)
+ {
+ self.documentOverlaysView?.setSearchResults(searchResults: searchResults)
+ }
+}
+
+/// Keyboard notifications
+extension DocumentController
+{
+
+ func registerKeyboardNotifications()
+ {
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(keyboardWillShow(notification:)),
+ name: NSNotification.Name.UIKeyboardWillShow,
+ object: nil)
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(keyboardWillHide(notification:)),
+ name: NSNotification.Name.UIKeyboardWillHide,
+ object: nil)
+ }
+
+ @objc func keyboardWillShow(notification: NSNotification)
+ {
+
+ let userInfo: NSDictionary = notification.userInfo! as NSDictionary
+ guard let keyboardInfo = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
+ print(userInfo)
+ let keyboardSize = keyboardInfo.cgRectValue.size
+ print("keyboardWillShow \(keyboardSize)")
+ let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
+ scrollView.contentInset = contentInsets
+ scrollView.scrollIndicatorInsets = contentInsets
+ }
+
+ @objc func keyboardWillHide(notification: NSNotification)
+ {
+ print("keyboardWillHide")
+ scrollView.contentInset = zeroInsets
+ scrollView.scrollIndicatorInsets = zeroInsets
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/DocumentOverlaysView.swift b/ios/LibreOfficeLight/LibreOfficeLight/DocumentOverlaysView.swift
new file mode 100644
index 000000000..16bc35c0a
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/DocumentOverlaysView.swift
@@ -0,0 +1,68 @@
+//
+// 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/.
+//
+
+import UIKit
+
+public class DocumentOverlaysView: UIView
+{
+ var searchSubViews: [UIView] = []
+ weak var documentTiledView: DocumentTiledView? = nil
+
+ public init(docTiledView: DocumentTiledView)
+ {
+ self.documentTiledView = docTiledView
+ super.init(frame: docTiledView.frame)
+
+ self.layer.compositingFilter = "multiplyBlendMode"
+ }
+
+ required public init?(coder aDecoder: NSCoder)
+ {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ public func clearSearchResults()
+ {
+ for v in self.searchSubViews
+ {
+ v.removeFromSuperview()
+ }
+ searchSubViews = []
+ }
+
+ public func setSearchResults(searchResults: SearchResults)
+ {
+ clearSearchResults()
+
+ guard let documentTiledView = self.documentTiledView else { return }
+
+ if let srs = searchResults.searchResultSelection
+ {
+ let allTheRects = srs.compactMap { $0.rectsAsCGRects }
+ .flatMap { $0 }
+ .map { documentTiledView.twipsToPixels(rect: $0) }
+
+ for rect in allTheRects
+ {
+ let subView = UIView(frame: rect)
+ subView.backgroundColor = UIColor.yellow // TODO
+ subView.layer.compositingFilter = "multiplyBlendMode"
+ self.addSubview(subView)
+ searchSubViews.append(subView)
+ }
+
+ if let first = allTheRects.first
+ {
+ if let scrollView = self.superview?.superview as? UIScrollView
+ {
+ scrollView.scrollRectToVisible(first, animated: true)
+ }
+ }
+ }
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/DocumentTiledView.swift b/ios/LibreOfficeLight/LibreOfficeLight/DocumentTiledView.swift
new file mode 100644
index 000000000..f0a36878c
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/DocumentTiledView.swift
@@ -0,0 +1,244 @@
+//
+// 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/.
+//
+
+import UIKit
+import QuartzCore
+
+
+class DocumentTiledLayer : CATiledLayer
+{
+ override class func fadeDuration() -> CFTimeInterval
+ {
+ return 0
+ }
+}
+
+/// The main tiled view, which sits inside the scroll view
+public class DocumentTiledView: UIView
+{
+ var myScale: CGFloat
+
+ weak var document: DocumentHolder? = nil
+
+ let initialSize: CGSize
+ let docSize: CGSize
+ let initialScaleFactor: CGFloat
+
+ var drawCount = 0
+
+ // Create a new view with the desired frame and scale.
+ public init(frame: CGRect, document: DocumentHolder, scale: CGFloat)
+ {
+ self.document = document
+
+ myScale = scale
+ initialSize = frame.size
+ var size = document.sync { $0.getDocumentSizeAsCGSize() }
+
+ // avoid divide by zero crashes
+ if (size.width == 0)
+ {
+ size.width = 1
+ }
+ if (size.height == 0)
+ {
+ size.height = 1
+ }
+ self.docSize = size
+ initialScaleFactor = (docSize.width / initialSize.width)
+ let scaledFrame = CGRect(x: 0, y: 0, width: frame.width, height: frame.width * (docSize.height / docSize.width))
+
+ print("DocumentTiledView.init frame=\(frame.desc) \n scaledFrame=\(scaledFrame.desc)\n docSize=\(docSize) \n initialScaleFactor=\(initialScaleFactor)")
+ super.init(frame: scaledFrame)
+
+ //self.contentScaleFactor = 1.0
+
+ if let tiledLayer = self.layer as? CATiledLayer
+ {
+ // these are all tweakable parameters, that give different behaviour to the tiled view
+ tiledLayer.levelsOfDetail = 4
+ tiledLayer.levelsOfDetailBias = 7
+ tiledLayer.tileSize = CGSize(width: 1024.0, height: 1024.0)
+ //tiledLayer.tileSize = CGSize(width: 512.0, height: 512.0)
+ }
+
+ let tap = UITapGestureRecognizer(target: self, action: #selector(onTap) )
+ tap.numberOfTapsRequired = 1
+ self.addGestureRecognizer(tap)
+
+ if (document.isPresentation) // only for preso atm
+ {
+ // add swipe left/right gestures on a preso
+ let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(onSwipeRight))
+ swipeRight.direction = .right
+ self.addGestureRecognizer(swipeRight)
+
+ let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(onSwipeLeft))
+ swipeLeft.direction = .left
+ self.addGestureRecognizer(swipeLeft)
+ }
+ }
+
+ required public init?(coder aDecoder: NSCoder)
+ {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ func incrementPart(amount: Int)
+ {
+ document?.incrementPart(amount: Int32(amount))
+ document?.async { _ in
+ runOnMain { self.setNeedsDisplay() }
+ }
+ }
+
+ public func twipsToPixels(rect: CGRect) -> CGRect
+ {
+ return rect.applying(CGAffineTransform(scaleX: 1.0/initialScaleFactor, y: 1.0/initialScaleFactor ))
+ }
+
+ public func pixelsToTwips(rect: CGRect) -> CGRect
+ {
+ return rect.applying(CGAffineTransform(scaleX: initialScaleFactor, y: initialScaleFactor ))
+ }
+
+
+ override public class var layerClass : AnyClass
+ {
+ return DocumentTiledLayer.self
+ }
+
+
+ override public func draw(_ r: CGRect)
+ {
+ // UIView uses the existence of -drawRect: to determine if it should allow its CALayer
+ // to be invalidated, which would then lead to the layer creating a backing store and
+ // -drawLayer:inContext: being called.
+ // By implementing an empty -drawRect: method, we allow UIKit to continue to implement
+ // this logic, while doing our real drawing work inside of -drawLayer:inContext:
+ }
+
+ // Draw the CGPDFPageRef into the layer at the correct scale.
+ override public func draw(_ layer: CALayer, in context: CGContext)
+ {
+// if self.superview == nil
+// {
+// // check that we are still active - ios is doing some really funny things where this method gets called after dealloc which causes bad bad karma
+// return
+// }
+ guard let document = self.document else
+ {
+ return
+ }
+
+ guard let tiledLayer = layer as? CATiledLayer else { return }
+
+
+
+ let tileSize: CGSize = tiledLayer.tileSize
+ let box: CGRect = context.boundingBoxOfClipPath
+ let ctm: CGAffineTransform = context.ctm
+
+ drawCount += 1
+ let filename = "tile\(drawCount).png"
+
+ print("drawLayer \(filename)\n bounds=\(layer.bounds.desc)\n ctm.a=\(ctm.a)\n tileSize=\(tileSize)\n box=\(box.desc)")
+
+ //context.setFillColor(UIColor.white.cgColor)
+ context.setFillColor(UIColor.blue.cgColor)
+ context.fill(box)
+ context.saveGState()
+
+ context.interpolationQuality = CGInterpolationQuality.high
+ context.setRenderingIntent(CGColorRenderingIntent.defaultIntent)
+
+ // This is where the magic happens
+
+ let pageRect = pixelsToTwips(rect: box)
+ print(" pageRect: \(pageRect.desc)")
+
+ // Figure out how many pixels we need for the dimensions of our tile
+ // tileSize represents a "full size" one in pixels
+
+ //let fullSizeTileInPoints = CGSize(width: CGFloat(tileSize.width) / ctm.a, height: CGFloat(tileSize.height) / ctm.a)
+ //let cropRectTileFraction = CGSize(width: box.size.width / fullSizeTileInPoints.width, height: box.size.height / fullSizeTileInPoints.height)
+ //let bitmapSize = CGSize(width: tileSize.width * cropRectTileFraction.width, height: tileSize.height * cropRectTileFraction.height)
+
+ let canvasSize = tileSize; //CGSize(width:512, height:512) // FIXME - this needs to be calculated
+
+ // we have to do the call synchronously, as the tile has to be painted now, on the current thread
+ // TODO - cache the image, and check the cache before we do the sync call
+ let image = document.paintTileToImage(canvasSize: canvasSize, tileRect: pageRect)
+
+
+ if let img = image
+ {
+ // Debugging: write the file to disk
+ /*
+ if let data = UIImagePNGRepresentation(img)
+ {
+ let filename = getDocumentsDirectory().appendingPathComponent(filename)
+ try? data.write(to: filename)
+ print("Wrote tile to: \(filename)")
+ }
+ */
+
+ // We use the UIImage draw function as it automatically handles the flipping of the co-ordinate system for us.
+ UIGraphicsPushContext(context);
+ img.draw(in: box)
+ UIGraphicsPopContext()
+ }
+
+ context.restoreGState()
+
+
+ }
+
+
+ deinit
+ {
+ self.document = nil
+
+ }
+
+
+ func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
+ {
+ //self.setNeedsDisplay()
+ }
+
+
+}
+
+/// Gesture handlers
+public extension DocumentTiledView
+{
+ @objc func onTap(_ sender: UITapGestureRecognizer)
+ {
+ if (document?.isPresentation ?? false)
+ {
+ incrementPart(amount: 1)
+ }
+ }
+
+ @objc func onSwipeRight(_ sender: UISwipeGestureRecognizer)
+ {
+ if (document?.isPresentation ?? false)
+ {
+ incrementPart(amount: -1)
+ }
+ }
+
+ @objc func onSwipeLeft(_ sender: UISwipeGestureRecognizer)
+ {
+ if (document?.isPresentation ?? false)
+ {
+ incrementPart(amount: 1)
+ }
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Info.plist b/ios/LibreOfficeLight/LibreOfficeLight/Info.plist
new file mode 100644
index 000000000..82ce94908
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Info.plist
@@ -0,0 +1,1812 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Text</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.text</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Text</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.text</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Spreadsheet</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.spreadsheet</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Spreadsheet</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.spreadsheet</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Presentation</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.presentation</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Presentation</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.presentation</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Drawing</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.graphics</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Drawing</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.graphics</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Chart</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.chart</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Master</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.text-master</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Master</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.text-master</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Formula</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.formula</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Formula</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.formula</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Text Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.text-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Text Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.text-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Master Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.text-master-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Spreadsheet Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.spreadsheet-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Spreadsheet Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.spreadsheet-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Presentation Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.presentation-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Presentation Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.presentation-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenOffice.org 1.0 Drawing Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.graphics-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>OpenDocument Drawing Template</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.oasis-open.opendocument.graphics-template</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>LibreOfficeDev Extension</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.openoffice.extension</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Flat ODF</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>vnd.oasis.opendocument.text-flat-xml</string>
+ <string>vnd.oasis.opendocument.spreadsheet-flat-xml</string>
+ <string>vnd.oasis.opendocument.presentation-flat-xml</string>
+ <string>vnd.oasis.opendocument.graphics-flat-xml</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>3rd party formats</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Alternate</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>public.plain-text</string>
+ <string>public.rtf</string>
+ <string>public.html</string>
+ <string>public.jpeg</string>
+ <string>public.tiff</string>
+ <string>public.png</string>
+ <string>public.xbitmap-image</string>
+ <string>com.adobe.encapsulated-postscript</string>
+ <string>com.microsoft.bmp</string>
+ <string>com.microsoft.word.doc</string>
+ <string>com.microsoft.word.dot</string>
+ <string>com.microsoft.excel.xls</string>
+ <string>com.microsoft.powerpoint.ppt</string>
+ <string>org.openxmlformats.wordprocessingml.document</string>
+ <string>org.openxmlformats.wordprocessingml.document.macroEnabled</string>
+ <string>org.openxmlformats.wordprocessingml.template</string>
+ <string>org.openxmlformats.wordprocessingml.template.macroEnabled</string>
+ <string>org.openxmlformats.spreadsheetml.sheet</string>
+ <string>org.openxmlformats.spreadsheetml.sheet.macroEnabled</string>
+ <string>com.microsoft.excel.sheet.binary.macroEnabled</string>
+ <string>org.openxmlformats.spreadsheetml.template</string>
+ <string>org.openxmlformats.spreadsheetml.template.macroEnabled</string>
+ <string>org.openxmlformats.presentationml.presentation</string>
+ <string>org.openxmlformats.presentationml.presentation.macroEnabled</string>
+ <string>org.openxmlformats.presentationml.template</string>
+ <string>org.openxmlformats.presentationml.template.macroEnabled</string>
+ <string>org.libreoffice.pdb-document</string>
+ <string>org.libreoffice.wpd-document</string>
+ <string>org.libreoffice.hwp-document</string>
+ <string>org.libreoffice.wks-document</string>
+ <string>org.libreoffice.wri-document</string>
+ <string>org.libreoffice.dif-document</string>
+ <string>org.libreoffice.slk-document</string>
+ <string>org.libreoffice.csv-document</string>
+ <string>org.libreoffice.dbf-document</string>
+ <string>org.libreoffice.123-document</string>
+ <string>org.libreoffice.cgm-document</string>
+ <string>org.libreoffice.dxf-document</string>
+ <string>org.libreoffice.emf-document</string>
+ <string>org.libreoffice.wmf-document</string>
+ <string>org.libreoffice.cdr-document</string>
+ <string>org.libreoffice.visio-document</string>
+ <string>org.libreoffice.mspub-document</string>
+ <string>com.adobe.pdf</string>
+ </array>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>0.8.5</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.business</string>
+ <key>LSMultipleInstancesProhibited</key>
+ <true/>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>LSSupportsOpeningDocumentsInPlace</key>
+ <true/>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>The 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/.</string>
+ <key>NSUbiquitousContainers</key>
+ <dict>
+ <key>iCloud.com.jani.Editors.LibreOfficeLight</key>
+ <dict>
+ <key>NSUbiquitousContainerIsDocumentScopePublic</key>
+ <true/>
+ <key>NSUbiquitousContainerName</key>
+ <string>LibreOffice</string>
+ <key>NSUbiquitousContainerSupportedFolderLevels</key>
+ <string>None</string>
+ </dict>
+ </dict>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen.xib</string>
+ <key>UIMainStoryboardFile</key>
+ <string>Main</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UIRequiresFullScreen</key>
+ <false/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportsDocumentBrowser</key>
+ <true/>
+ <key>UTExportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Text</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.text</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>text.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxw</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.writer</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Text</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.text</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-text.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odt</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.text</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Text (Flat XML)</string>
+ <key>UTTypeIdentifier</key>
+ <string>vnd.oasis.opendocument.text-flat-xml</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-text.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>fodt</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.text-flat-xml</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Spreadsheet</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.spreadsheet</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>spreadsheet.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxc</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.calc</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Spreadsheet</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.spreadsheet</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-spreadsheet.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>ods</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.spreadsheet</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Spreadsheet (Flat XML)</string>
+ <key>UTTypeIdentifier</key>
+ <string>vnd.oasis.opendocument.spreadsheet-flat-xml</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-spreadsheet.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>fods</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.spreadsheet-flat-xml</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Presentation</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.presentation</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>presentation.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxi</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.impress</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Presentation</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.presentation</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-presentation.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odp</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.presentation</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Presentation</string>
+ <key>UTTypeIdentifier</key>
+ <string>vnd.oasis.opendocument.presentation-flat-xml</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-presentation.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>fodp</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.presentation-flat-xml</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Drawing</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.graphics</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>drawing.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxd</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.draw</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Drawing</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.graphics</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-drawing.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odg</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.graphics</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Drawing (Flat XML)</string>
+ <key>UTTypeIdentifier</key>
+ <string>vnd.oasis.opendocument.graphics-flat-xml</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-drawing.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>fodg</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.graphics-flat-xml</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Chart</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.chart</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odc</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.chart</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Master</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.text-master</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>master-document.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxg</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.writer.global</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Master</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.text-master</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-master-document.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.text-master</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Formula</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.formula</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>formula.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sxm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.math</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Formula</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.formula</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-formula.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>odf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.formula</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Text Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.text-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>text-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>stw</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.writer.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Text Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.text-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-text-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>ott</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.text-template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Text Master Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.text-master-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-master-document-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>otm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.text-master-template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Spreadsheet Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.spreadsheet-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>spreadsheet-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>stc</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.calc.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Spreadsheet Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.spreadsheet-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-spreadsheet-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>ots</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.spreadsheet-template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Presentation Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.presentation-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>presentation-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>sti</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.impress.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Presentation Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.presentation-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-presentation-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>otp</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.presentation-template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenOffice.org 1.0 Drawing Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.graphics-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>drawing-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>std</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.sun.xml.draw.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>OpenDocument Drawing Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.oasis-open.opendocument.graphics-template</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>oasis-drawing-template.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>otg</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.oasis.opendocument.graphics-template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>LibreOfficeDev Extension</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openoffice.extension</string>
+ <key>UTTypeSize64IconFile</key>
+ <string>extension.icns</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>oxt</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openofficeorg.extension</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>UTImportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.composite-content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Word Template</string>
+ <key>UTTypeIdentifier</key>
+ <string>com.microsoft.word.dot</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dot</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/msword</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML word processing document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.wordprocessingml.document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>docx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.wordprocessingml.document</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML word processing document (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.wordprocessingml.document.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>docm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-word.document.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML word processing template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.wordprocessingml.template</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dotx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.wordprocessingml.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML word processing template (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.wordprocessingml.template.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dotm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-word.template.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML spreadsheet template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.spreadsheetml.template</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xltx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.spreadsheetml.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML spreadsheet template (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.spreadsheetml.template.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xltm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-excel.template.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML spreadsheet</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.spreadsheetml.sheet</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xlsx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.zip-archive</string>
+ <string>public.composite-content</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Excel 2007 spreadsheet (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>com.microsoft.excel.sheet.binary.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xlsb</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-excel.sheet.binary.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.composite-content</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML spreadsheet (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.spreadsheetml.sheet.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xlsm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-excel.sheet.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.presentation</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML presentation</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.presentationml.presentation</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pptx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.presentationml.presentation</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.presentation</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML presentation (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.presentationml.presentation.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pptm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-powerpoint.presentation.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.presentation</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML presentation template</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.presentationml.template</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>potx</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.openxmlformats-officedocument.presentationml.template</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>org.openxmlformats.openxml</string>
+ <string>public.presentation</string>
+ <string>public.executable</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Office Open XML presentation template (macros enabled)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.openxmlformats.presentationml.template.macroEnabled</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>potm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-powerpoint.template.macroEnabled.12</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>WordPerfect Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.wpd-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>wpd</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.wordperfect</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>PalmDoc eBook </string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.pdb-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pdb</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-aportisdoc</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Hangul WP 97 Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.hwp-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>hwp</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-hwp</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Works for Mac Document (v1 - v4)</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.wks-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>wps</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.ms-works</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Write</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.wri-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>wri</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-mswrite</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Data Interchange Format</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.dif-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dif</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-dif-document</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.text</string>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>SYLK Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.slk-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>slk</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>text/spreadsheet</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.text</string>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Comma-Separated Value Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.csv-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>csv</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>text/csv</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>dBASE Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.dbf-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dbf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-dbase</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Lotus 1-2-3 Spreadsheet</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.123-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>wk1</string>
+ <string>wks</string>
+ <string>123</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.lotus-1-2-3</string>
+ <string>application/vnd.lotus-1-2-3</string>
+ <string>application/vnd.lotus-1-2-3</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ <string>public.image</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Computer Graphics Metafile</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.cgm-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>cgm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>image/cgm</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ <string>public.image</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>AutoCAD Interchange Format</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.dxf-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>dxf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>image/vnd.dxf</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ <string>public.image</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Windows Enhanced Metafile</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.emf-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>emf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>image/x-emf</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ <string>public.image</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Windows Metafile</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.wmf-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>wmf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>image/x-wmf</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ <string>public.image</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>CorelDRAW Image</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.cdr-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>cdr</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/cdr</string>
+ <string>application/coreldraw</string>
+ <string>application/vnd.corel-draw</string>
+ <string>application/x-cdr</string>
+ <string>application/x-coreldraw</string>
+ <string>image/cdr</string>
+ <string>image/x-cdr</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Visio Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.visio-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>vsd</string>
+ <string>vss</string>
+ <string>vst</string>
+ <string>vdx</string>
+ <string>vsx</string>
+ <string>vtx</string>
+ <string>vsdx</string>
+ <string>vsdm</string>
+ <string>vssx</string>
+ <string>vssm</string>
+ <string>vstx</string>
+ <string>vstm</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/vnd.visio2013</string>
+ <string>application/vnd.visio</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Microsoft Publisher Document</string>
+ <key>UTTypeIdentifier</key>
+ <string>org.libreoffice.mspub-document</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pub</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/x-mspublisher</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ <string>public.composite-​content</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>Apple PDF pasteboard type PDF data</string>
+ <key>UTTypeIdentifier</key>
+ <string>com.adobe.pdf</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pdf</string>
+ </array>
+ <key>public.mime-type</key>
+ <array>
+ <string>application/pdf</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/AsyncUtil.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/AsyncUtil.swift
new file mode 100644
index 000000000..52f8c1bdd
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/AsyncUtil.swift
@@ -0,0 +1,92 @@
+//
+// 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/.
+//
+
+import Foundation
+
+
+public typealias Runnable = () -> ()
+
+/// Runs the closure on a queued background thread
+public func runInBackground(_ runnable: @escaping Runnable)
+{
+ DispatchQueue.global(qos: .background).async(execute: runnable)
+}
+
+
+/// Runs the closure on the UI (main) thread. Exceptions are caught and logged
+public func runOnMain(_ runnable: @escaping () -> ())
+{
+ DispatchQueue.main.async(execute: runnable)
+}
+
+/// Returns true if we are on the Main / UI thread
+public func isMainThread() -> Bool
+{
+ return Thread.isMainThread
+}
+
+/// Runs tasks in a serial way on a single thread.
+/// Why wouldn't we just use DispatchQueue or NSOperationQueue to do this?
+/// Because neither guarantee running their tasks on the same thread all the time.
+/// And in fact DispatchQueue will try and run sync tasks on the current thread where it can.
+/// Both classes try and abstract the thread away, whereas we have to use the same thread, or we end up with deadlocks in LOKit
+public class SingleThreadedQueue: Thread
+{
+ public init(name: String)
+ {
+ super.init()
+ self.name = name
+ self.start()
+ }
+
+ override public func main()
+ {
+ // You need the NSPort here because a runloop with no sources or ports registered with it
+ // will simply exit immediately instead of running forever.
+ let keepAlive = Port()
+ let rl = RunLoop.current
+ keepAlive.schedule(in: rl, forMode: .commonModes)
+
+ rl.run()
+ }
+
+ /// Run the task on the serial queue, and return immediately
+ public func async( _ runnable: @escaping Runnable)
+ {
+ let operation = BlockOperation {
+ runnable()
+ }
+ async(operation: operation)
+ }
+
+ /// Run the task on the serial queue, and return immediately
+ public func async( operation: Operation)
+ {
+ if ( Thread.current == self)
+ {
+ operation.start();
+ }
+ else
+ {
+ operation.perform(#selector(Operation.start), on: self, with: nil, waitUntilDone: false)
+ }
+ }
+
+ public func sync<R>( _ closure: @escaping () -> R ) -> R
+ {
+ var ret: R! = nil
+ let op = BlockOperation {
+ ret = closure();
+ }
+ async(operation: op)
+ op.waitUntilFinished()
+ return ret
+ }
+
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift
new file mode 100644
index 000000000..4e3b4b20e
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Document.swift
@@ -0,0 +1,592 @@
+//
+// 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/.
+//
+
+import Foundation
+import UIKit
+import QuartzCore
+
+
+/// The Document class represents one loaded document instance
+/// Obtained through LibreOffice.documentLoad()
+open class Document
+{
+ private let pDoc: UnsafeMutablePointer<LibreOfficeKitDocument>
+ private let docClass: LibreOfficeKitDocumentClass
+
+ internal init(pDoc: UnsafeMutablePointer<LibreOfficeKitDocument>)
+ {
+ self.pDoc = pDoc
+ self.docClass = pDoc.pointee.pClass.pointee
+ }
+
+ /**
+ * Stores the document's persistent data to a URL and
+ * continues to be a representation of the old URL.
+ *
+ * @param pUrl the location where to store the document
+ * @param pFormat the format to use while exporting, when omitted, then deducted from pURL's extension
+ * @param pFilterOptions options for the export filter, e.g. SkipImages.
+ * Another useful FilterOption is "TakeOwnership". It is consumed
+ * by the saveAs() itself, and when provided, the document identity
+ * changes to the provided pUrl - meaning that '.uno:ModifiedStatus'
+ * is triggered as with the "Save As..." in the UI.
+ * "TakeOwnership" mode must not be used when saving to PNG or PDF.
+ */
+ public func saveAs(url: String, format: String? = nil, filterOptions: String? = nil) -> Bool
+ {
+ return docClass.saveAs(pDoc, url, format, filterOptions) != 0
+ }
+
+ /**
+ * Get document type.
+ *
+ * @since LibreOffice 6.0
+ * @return an element of the LibreOfficeKitDocumentType enum.
+ */
+ public func getDocumentType() -> LibreOfficeKitDocumentType
+ {
+ return LibreOfficeKitDocumentType(rawValue: LibreOfficeKitDocumentType.RawValue(docClass.getDocumentType(pDoc)))
+ }
+
+ /**
+ * Get number of part that the document contains.
+ *
+ * Part refers to either individual sheets in a Calc, or slides in Impress,
+ * and has no relevance for Writer.
+ */
+ public func getParts() -> Int32
+ {
+ return docClass.getParts(pDoc);
+ }
+
+ public func initializeForRendering()
+ {
+ docClass.initializeForRendering(pDoc, "") // TODO: arguments??
+ }
+
+ /**
+ * Get the logical rectangle of each part in the document.
+ *
+ * A part refers to an individual page in Writer and has no relevant for
+ * Calc or Impress.
+ *
+ * @return a rectangle list, using the same format as
+ * LOK_CALLBACK_TEXT_SELECTION.
+ */
+ public func getPartRectanges() -> String
+ {
+ return toString( docClass.getPartPageRectangles(pDoc) ) ?? ""
+
+ // TODO: convert to CGRects? Comes out like "284, 284, 11906, 16838; 284, 17406, 11906, 16838; 284, 34528, 11906, 16838"
+
+ }
+
+ /// Get the current part of the document.
+ public func getPart() -> Int32
+ {
+ return docClass.getPart(pDoc);
+ }
+
+ /// Set the current part of the document.
+ public func setPart( nPart: Int32 )
+ {
+ docClass.setPart(pDoc, nPart);
+ }
+
+ /// Get the current part's name.
+ public func getPartName( nPart: Int32) -> String?
+ {
+ return toString( docClass.getPartName(pDoc, nPart) )
+
+ }
+
+ /// Get the current part's hash.
+ public func getPartHash( nPart: Int32 ) -> String?
+ {
+ return toString( docClass.getPartHash(pDoc, nPart) )
+
+ }
+
+ public func setPartMode( nMode: Int32 )
+ {
+ docClass.setPartMode( pDoc, nMode);
+ }
+
+ /**
+ * Renders a subset of the document to a pre-allocated buffer.
+ *
+ * Note that the buffer size and the tile size implicitly supports
+ * rendering at different zoom levels, as the number of rendered pixels and
+ * the rendered rectangle of the document are independent.
+ *
+ * @param rCGContext Core Graphics context, cast to a UnsafeMutableRawPointer
+ * @param nCanvasWidth number of pixels in a row of pBuffer.
+ * @param nCanvasHeight number of pixels in a column of pBuffer.
+ * @param nTilePosX logical X position of the top left corner of the rendered rectangle, in TWIPs.
+ * @param nTilePosY logical Y position of the top left corner of the rendered rectangle, in TWIPs.
+ * @param nTileWidth logical width of the rendered rectangle, in TWIPs.
+ * @param nTileHeight logical height of the rendered rectangle, in TWIPs.
+ */
+ public func paintTileToCGContext( rCGContext: UnsafeMutableRawPointer,
+ canvasWidth: Int32,
+ canvasHeight: Int32,
+ tilePosX: Int32,
+ tilePosY: Int32,
+ tileWidth: Int32,
+ tileHeight: Int32)
+ {
+ print("paintTile canvasWidth=\(canvasWidth) canvasHeight=\(canvasHeight) tilePosX=\(tilePosX) tilePosY=\(tilePosY) tileWidth=\(tileWidth) tileHeight=\(tileHeight) ")
+ return docClass.paintTileToCGContext(pDoc, rCGContext, canvasWidth, canvasHeight,
+ tilePosX, tilePosY, tileWidth, tileHeight);
+ }
+
+ /**
+ * Renders a window (dialog, popup, etc.) with give id
+ *
+ * @param nWindowId
+ * @param pBuffer Buffer with enough memory allocated to render any dialog
+ * @param x x-coordinate from where the dialog should start painting
+ * @param y y-coordinate from where the dialog should start painting
+ * @param width The width of the dialog image to be painted
+ * @param height The height of the dialog image to be painted
+ */
+ public func paintWindow( nWindowId: UInt32,
+ pBuffer: UnsafeMutablePointer<UInt8>,
+ x: Int32,
+ y: Int32,
+ width: Int32,
+ height: Int32)
+ {
+ return docClass.paintWindow(pDoc, nWindowId, pBuffer, x, y, width, height);
+ }
+
+ /**
+ * Posts a command to the window (dialog, popup, etc.) with given id
+ *
+ * @param nWindowid
+ */
+ public func postWindow( nWindowId: UInt32, nAction: Int32, data: String)
+ {
+ return docClass.postWindow(pDoc, nWindowId, nAction, data);
+ }
+
+ /**
+ * Gets the tile mode: the pixel format used for the pBuffer of paintTile().
+ *
+ * @return an element of the LibreOfficeKitTileMode enum.
+ */
+ public func getTileMode() -> LibreOfficeKitTileMode
+ {
+ return LibreOfficeKitTileMode(rawValue: LibreOfficeKitTileMode.RawValue(docClass.getTileMode(pDoc)));
+ }
+
+ /// Get the document sizes in TWIPs.
+ public func getDocumentSize() -> (Int, Int)
+ {
+ print(Thread.isMainThread)
+ // long* pWidth, long* pHeight
+ var pWidth: Int = 0
+ var pHeight: Int = 0
+ docClass.getDocumentSize(pDoc, &pWidth, &pHeight);
+ return (pWidth, pHeight)
+ }
+
+ /**
+ * Initialize document for rendering.
+ *
+ * Sets the rendering and document parameters to default values that are
+ * needed to render the document correctly using tiled rendering. This
+ * method has to be called right after documentLoad() in case any of the
+ * tiled rendering methods are to be used later.
+ *
+ * Example argument string for text documents:
+ *
+ * {
+ * ".uno:HideWhitespace":
+ * {
+ * "type": "boolean",
+ * "value": "true"
+ * }
+ * }
+ *
+ * @param pArguments arguments of the rendering
+ */
+ public func initializeForRendering(arguments: String? = nil)
+ {
+ docClass.initializeForRendering(pDoc, arguments);
+ }
+
+ /**
+ * Registers a callback. LOK will invoke this function when it wants to
+ * inform the client about events.
+ *
+ * @param pCallback the callback to invoke
+ * @param pData the user data, will be passed to the callback on invocation
+ */
+ @discardableResult
+ public func registerCallback( callback: @escaping LibreOfficeCallback ) -> Int
+ {
+ let ret = Callbacks.register(callback: callback)
+ let pointer = UnsafeMutableRawPointer(bitPattern: ret)
+ docClass.registerCallback(pDoc, callbackFromLibreOffice, pointer)
+ return ret
+ }
+
+ /**
+ * Posts a keyboard event to the focused frame.
+ *
+ * @param nType Event type, like press or release.
+ * @param nCharCode contains the Unicode character generated by this event or 0
+ * @param nKeyCode contains the integer code representing the key of the event (non-zero for control keys)
+ */
+ public func postKeyEvent(nType: Int32, nCharCode: Int32, nKeyCode: Int32)
+ {
+ docClass.postKeyEvent(pDoc, nType, nCharCode, nKeyCode);
+ }
+
+ /**
+ * Posts a keyboard event to the dialog
+ *
+ * @param nWindowId
+ * @param nType Event type, like press or release.
+ * @param nCharCode contains the Unicode character generated by this event or 0
+ * @param nKeyCode contains the integer code representing the key of the event (non-zero for control keys)
+ */
+ public func postWindowKeyEvent( nWindowId: UInt32, nType: Int32, nCharCode: Int32, nKeyCode: Int32)
+ {
+ docClass.postWindowKeyEvent(pDoc, nWindowId, nType, nCharCode, nKeyCode);
+ }
+
+ /**
+ * Posts a mouse event to the document.
+ *
+ * @param nType Event type, like down, move or up.
+ * @param nX horizontal position in document coordinates
+ * @param nY vertical position in document coordinates
+ * @param nCount number of clicks: 1 for single click, 2 for double click
+ * @param nButtons: which mouse buttons: 1 for left, 2 for middle, 4 right
+ * @param nModifier: which keyboard modifier: (see include/vcl/vclenum.hxx for possible values)
+ */
+ public func postMouseEvent( nType: Int32, nX: Int32, nY: Int32, nCount: Int32, nButtons: Int32, nModifier: Int32)
+ {
+ docClass.postMouseEvent(pDoc, nType, nX, nY, nCount, nButtons, nModifier);
+ }
+
+ /**
+ * Posts a mouse event to the window with given id.
+ *
+ * @param nWindowId
+ * @param nType Event type, like down, move or up.
+ * @param nX horizontal position in document coordinates
+ * @param nY vertical position in document coordinates
+ * @param nCount number of clicks: 1 for single click, 2 for double click
+ * @param nButtons: which mouse buttons: 1 for left, 2 for middle, 4 right
+ * @param nModifier: which keyboard modifier: (see include/vcl/vclenum.hxx for possible values)
+ */
+ public func postWindowMouseEvent(nWindowId: UInt32, nType: Int32, nX: Int32, nY: Int32, nCount: Int32, nButtons: Int32, nModifier: Int32)
+ {
+ docClass.postWindowMouseEvent(pDoc, nWindowId, nType, nX, nY, nCount, nButtons, nModifier);
+ }
+
+ /**
+ * Posts a UNO command to the document.
+ *
+ * Example argument string:
+ *
+ * {
+ * "SearchItem.SearchString":
+ * {
+ * "type": "string",
+ * "value": "foobar"
+ * },
+ * "SearchItem.Backward":
+ * {
+ * "type": "boolean",
+ * "value": "false"
+ * }
+ * }
+ *
+ * @param pCommand uno command to be posted to the document, like ".uno:Bold"
+ * @param pArguments arguments of the uno command.
+ */
+ public func postUnoCommand(command: String, arguments: String? = nil, notifyWhenFinished: Bool = false)
+ {
+ docClass.postUnoCommand(pDoc, command, arguments, notifyWhenFinished);
+ }
+
+ /**
+ * Sets the start or end of a text selection.
+ *
+ * @param nType @see LibreOfficeKitSetTextSelectionType
+ * @param nX horizontal position in document coordinates
+ * @param nY vertical position in document coordinates
+ */
+ public func setTextSelection( nType: Int32, nX: Int32, nY: Int32)
+ {
+ docClass.setTextSelection(pDoc, nType, nX, nY);
+ }
+
+ /**
+ * Gets the currently selected text.
+ *
+ * @param pMimeType suggests the return format, for example text/plain;charset=utf-8.
+ * @param pUsedMimeType output parameter to inform about the determined format (suggested one or plain text).
+ */
+ // FIXME - work out how to use an inout param for usedMimeType
+ public func getTextSelection(mimeType: String, usedMimeType: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>? = nil) -> String?
+ {
+ return toString( docClass.getTextSelection(pDoc, mimeType, usedMimeType) );
+ }
+
+ /**
+ * Pastes content at the current cursor position.
+ *
+ * @param pMimeType format of pData, for example text/plain;charset=utf-8.
+ * @param pData the actual data to be pasted.
+ * @return if the supplied data was pasted successfully.
+ */
+ public func paste(mimeType: String, data: String, size: Int) -> Bool
+ {
+ return docClass.paste(pDoc, mimeType, data, size);
+ }
+
+ /**
+ * Adjusts the graphic selection.
+ *
+ * @param nType @see LibreOfficeKitSetGraphicSelectionType
+ * @param nX horizontal position in document coordinates
+ * @param nY vertical position in document coordinates
+ */
+ public func setGraphicSelection( nType: Int32, nX: Int32, nY: Int32)
+ {
+ docClass.setGraphicSelection(pDoc, nType, nX, nY);
+ }
+
+ /**
+ * Gets rid of any text or graphic selection.
+ */
+ public func resetSelection()
+ {
+ docClass.resetSelection(pDoc);
+ }
+
+ /**
+ * Returns a json mapping of the possible values for the given command
+ * e.g. {commandName: ".uno:StyleApply", commandValues: {"familyName1" : ["list of style names in the family1"], etc.}}
+ * @param pCommand a UNO command for which the possible values are requested
+ * @return {commandName: unoCmd, commandValues: {possible_values}}
+ */
+ public func getCommandValues(command: String) -> String?
+ {
+ return toString(docClass.getCommandValues(pDoc, command));
+ }
+
+ /**
+ * Save the client's view so that we can compute the right zoom level
+ * for the mouse events. This only affects CALC.
+ * @param nTilePixelWidth - tile width in pixels
+ * @param nTilePixelHeight - tile height in pixels
+ * @param nTileTwipWidth - tile width in twips
+ * @param nTileTwipHeight - tile height in twips
+ */
+ public func setClientZoom(
+ nTilePixelWidth: Int32,
+ nTilePixelHeight: Int32,
+ nTileTwipWidth: Int32,
+ nTileTwipHeight: Int32)
+ {
+ docClass.setClientZoom(pDoc, nTilePixelWidth, nTilePixelHeight, nTileTwipWidth, nTileTwipHeight);
+ }
+
+ /**
+ * Inform core about the currently visible area of the document on the
+ * client, so that it can perform e.g. page down (which depends on the
+ * visible height) in a sane way.
+ *
+ * @param nX - top left corner horizontal position
+ * @param nY - top left corner vertical position
+ * @param nWidth - area width
+ * @param nHeight - area height
+ */
+ public func setClientVisibleArea( nX: Int32, nY: Int32, nWidth: Int32, nHeight: Int32)
+ {
+ docClass.setClientVisibleArea(pDoc, nX, nY, nWidth, nHeight);
+ }
+
+ /**
+ * Show/Hide a single row/column header outline for Calc documents.
+ *
+ * @param bColumn - if we are dealing with a column or row group
+ * @param nLevel - the level to which the group belongs
+ * @param nIndex - the group entry index
+ * @param bHidden - the new group state (collapsed/expanded)
+ */
+ public func setOutlineState( column: Bool, level: Int32, index: Int32, hidden: Bool)
+ {
+ docClass.setOutlineState(pDoc, column, level, index, hidden);
+ }
+
+ /**
+ * Create a new view for an existing document.
+ * By default a loaded document has 1 view.
+ * @return the ID of the new view.
+ */
+ public func createView() -> Int32
+ {
+ return docClass.createView(pDoc);
+ }
+
+ /**
+ * Destroy a view of an existing document.
+ * @param nId a view ID, returned by createView().
+ */
+ public func destroyView( id: Int32 )
+ {
+ docClass.destroyView(pDoc, id);
+ }
+
+ /**
+ * Set an existing view of an existing document as current.
+ * @param nId a view ID, returned by createView().
+ */
+ public func setView(id: Int32)
+ {
+ docClass.setView(pDoc, id);
+ }
+
+ /**
+ * Get the current view.
+ * @return a view ID, previously returned by createView().
+ */
+ public func getView() -> Int32
+ {
+ return docClass.getView(pDoc);
+ }
+
+ /**
+ * Get number of views of this document.
+ */
+ public func getViewsCount() -> Int32
+ {
+ return docClass.getViewsCount(pDoc);
+ }
+
+ /**
+ * Paints a font name or character if provided to be displayed in the font list
+ * @param pFontName the font to be painted
+ */
+ // TODO
+// public func renderFont(fontName: String,
+// const char *pChar,
+// int *pFontWidth,
+// int *pFontHeight)
+// {
+// return docClass.renderFont(pDoc, pFontName, pChar, pFontWidth, pFontHeight);
+// }
+
+ /**
+ * Renders a subset of the document's part to a pre-allocated buffer.
+ *
+ * @param nPart the part number of the document of which the tile is painted.
+ * @see paintTile.
+ */
+ public func paintPartTile(pBuffer: UnsafeMutablePointer<UInt8>,
+ nPart: Int32,
+ nCanvasWidth: Int32,
+ nCanvasHeight: Int32,
+ nTilePosX: Int32,
+ nTilePosY: Int32,
+ nTileWidth: Int32,
+ nTileHeight: Int32)
+ {
+ return docClass.paintPartTile(pDoc, pBuffer, nPart,
+ nCanvasWidth, nCanvasHeight,
+ nTilePosX, nTilePosY,
+ nTileWidth, nTileHeight);
+ }
+
+ /**
+ * Returns the viewID for each existing view. Since viewIDs are not reused,
+ * viewIDs are not the same as the index of the view in the view array over
+ * time. Use getViewsCount() to know the minimal nSize that's large enough.
+ *
+ * @param pArray the array to write the viewIDs into
+ * @param nSize the size of pArray
+ * @returns true if pArray was large enough and result is written, false
+ * otherwise.
+ */
+// bool getViewIds(int* pArray,
+// size_t nSize)
+// {
+// return docClass.getViewIds(pDoc, pArray, nSize);
+// }
+
+ /**
+ * Set the language tag of the window with the specified nId.
+ *
+ * @param nId a view ID, returned by createView().
+ * @param language Bcp47 languageTag, like en-US or so.
+ */
+ public func setViewLanguage( id: Int32, language: String)
+ {
+ docClass.setViewLanguage(pDoc, id, language);
+ }
+
+ public func invokeHandlers()
+ {
+ // The app seems to work even without this? Or maybe I
+ // just didn't test hard enough?
+ // temporaryHackToInvokeCallbackHandlers(pDoc)
+
+ }
+
+}
+
+/**
+ * iOS friendly extensions of Document.
+ * TODO: move me back to the framework.
+ */
+public extension Document
+{
+ public func getDocumentSizeAsCGSize() -> CGSize
+ {
+ let (x,y) = self.getDocumentSize()
+ return CGSize(width: x, height: y)
+ }
+
+ public func paintTileToCurrentContext(canvasSize: CGSize,
+ tileRect: CGRect)
+ {
+ let ctx = UIGraphicsGetCurrentContext()
+ //print(ctx!)
+ let ptr = unsafeBitCast(ctx, to: UnsafeMutableRawPointer.self)
+ //print(ptr)
+
+ self.paintTileToCGContext(rCGContext:ptr,
+ canvasWidth: Int32(canvasSize.width),
+ canvasHeight: Int32(canvasSize.height),
+ tilePosX: Int32(tileRect.minX),
+ tilePosY: Int32(tileRect.minY),
+ tileWidth: Int32(tileRect.size.width),
+ tileHeight: Int32(tileRect.size.height))
+ }
+
+ public func paintTileToImage(canvasSize: CGSize,
+ tileRect: CGRect) -> UIImage?
+ {
+
+ UIGraphicsBeginImageContextWithOptions(canvasSize, false, 1.0)
+ let _ = UIGraphicsGetCurrentContext()!
+
+ self.paintTileToCurrentContext(canvasSize: canvasSize, tileRect: tileRect)
+ let image = UIGraphicsGetImageFromCurrentImageContext()
+ UIGraphicsEndImageContext()
+ return image
+ }
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/DocumentHolder.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/DocumentHolder.swift
new file mode 100644
index 000000000..cfc2cb678
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/DocumentHolder.swift
@@ -0,0 +1,345 @@
+//
+// 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/.
+//
+
+import Foundation
+import UIKit
+import QuartzCore
+
+/**
+ * Holds the document object so to enforce access in a thread safe way.
+ */
+public class DocumentHolder
+{
+ private let doc: Document
+
+ public weak var delegate: DocumentUIDelegate? = nil
+ public weak var searchDelegate: SearchDelegate? = nil
+
+ private let cache = RenderCache()
+
+ public let documentType: LibreOfficeKitDocumentType
+ public let documentSize: CGSize
+ public let views: Int32
+ public let parts: Int32
+ public let partNames: [String]
+
+ public private(set) var currentPart: Int32 = 0
+
+ init(doc: Document)
+ {
+ self.doc = doc
+
+ // we go and get a bunch of document properties and store them in properties
+ // this allows easy access to these without threading issues
+ // when we get to editing they will have to be invalidated
+
+ self.documentType = doc.getDocumentType()
+ documentSize = doc.getDocumentSizeAsCGSize()
+ views = doc.getViewsCount()
+ parts = doc.getParts()
+
+ var partNames = [String]()
+ for i in 0..<parts
+ {
+ let n = doc.getPartName(nPart: i) ?? ""
+ partNames.append(n)
+ }
+ self.partNames = partNames
+
+ doc.registerCallback() {
+ [weak self] typ, payload in
+ self?.onDocumentEvent(type: typ, payload: payload)
+ }
+ }
+
+ public var isPresentation: Bool
+ {
+ return documentType == LOK_DOCTYPE_PRESENTATION
+ }
+ public var isText: Bool
+ {
+ return documentType == LOK_DOCTYPE_TEXT
+ }
+ public var isDrawing: Bool
+ {
+ return documentType == LOK_DOCTYPE_DRAWING
+ }
+ public var isSpeadsheet: Bool
+ {
+ return documentType == LOK_DOCTYPE_SPREADSHEET
+ }
+
+ /// Gives async access to the document
+ public func async(_ closure: @escaping (Document) -> ())
+ {
+ LOKitThread.instance.async
+ {
+ closure(self.doc)
+ }
+ self.invokeHandlers()
+ }
+
+ public func invokeHandlers()
+ {
+ LOKitThread.instance.async
+ {
+ self.doc.invokeHandlers()
+ }
+ }
+
+ /// Gives sync access to the document - blocks until the closure runs.
+ /// Careful of deadlocks.
+ public func sync<R>( _ closure: @escaping (Document) -> R ) -> R
+ {
+ return LOKitThread.instance.sync
+ {
+ self.invokeHandlers()
+ return closure(self.doc)
+ }
+ }
+
+ /// Paints a tile and return synchronously, using a cached version if it can
+ public func paintTileToImage(canvasSize: CGSize,
+ tileRect: CGRect) -> UIImage?
+ {
+ if let cached = cache.get(part: currentPart, canvasSize: canvasSize, tileRect: tileRect)
+ {
+ return cached
+ }
+
+ let img = sync {
+ $0.paintTileToImage(canvasSize: canvasSize, tileRect: tileRect)
+ }
+ if let image = img
+ {
+ cache.add(cachedRender: CachedRender(part: currentPart, canvasSize: canvasSize, tileRect: tileRect, image: image))
+ }
+
+ return img
+ }
+
+ private func onDocumentEvent(type: LibreOfficeKitCallbackType, payload: String?)
+ {
+ print("onDocumentEvent type:\(type) payload:\(payload ?? "")")
+
+ switch type
+ {
+ case LOK_CALLBACK_INVALIDATE_TILES:
+ runOnMain {
+ self.delegate?.invalidateTiles( rects: decodeRects(payload) )
+ }
+ case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
+ runOnMain {
+ self.delegate?.invalidateVisibleCursor( rects: decodeRects(payload) )
+ }
+ case LOK_CALLBACK_TEXT_SELECTION:
+ runOnMain {
+ self.delegate?.textSelection( rects: decodeRects(payload) )
+ }
+ case LOK_CALLBACK_TEXT_SELECTION_START:
+ runOnMain {
+ self.delegate?.textSelectionStart( rects: decodeRects(payload) )
+ }
+ case LOK_CALLBACK_TEXT_SELECTION_END:
+ runOnMain {
+ self.delegate?.textSelectionEnd( rects: decodeRects(payload) )
+ }
+
+ case LOK_CALLBACK_SEARCH_NOT_FOUND:
+ runOnMain {
+ self.searchDelegate?.searchNotFound()
+ }
+ case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+ runOnMain {
+ self.searchResults(payload: payload)
+ }
+
+ case LOK_CALLBACK_SET_PART:
+ if let p = payload, let newPart = Int32(p)
+ {
+ self.currentPart = newPart
+ // TODO: callback?
+ }
+
+ case LOK_CALLBACK_STATE_CHANGED:
+ // TODO: call backback
+ print("onDocumentEvent type: LOK_CALLBACK_STATE_CHANGED: \(payload ?? "")")
+
+ default:
+ print("onDocumentEvent type:\(type) not handled!")
+ }
+ }
+
+ private func searchResults(payload: String?)
+ {
+ if let d = payload, let data = d.data(using: .utf8)
+ {
+ let decoder = JSONDecoder()
+ do
+ {
+ let searchResults = try decoder.decode(SearchResults.self, from: data )
+ self.searchDelegate?.searchResultSelection(searchResults: searchResults)
+ }
+ catch
+ {
+ print("Error decoding payload: \(error)")
+ }
+ }
+ }
+
+ public func search(searchString: String, forwardDirection: Bool = true, from: CGPoint)
+ {
+ var rootJson = JSONObject()
+ addProperty(&rootJson, "SearchItem.SearchString", "string", searchString);
+ addProperty(&rootJson, "SearchItem.Backward", "boolean", String(!forwardDirection) );
+ addProperty(&rootJson, "SearchItem.SearchStartPointX", "long", String(describing: from.x) );
+ addProperty(&rootJson, "SearchItem.SearchStartPointY", "long", String(describing: from.y) );
+ addProperty(&rootJson, "SearchItem.Command", "long", "0") // String.valueOf(0)); // search all == 1
+
+ if let jsonStr = encode(json: rootJson)
+ {
+ async {
+ $0.postUnoCommand(command: ".uno:ExecuteSearch", arguments: jsonStr, notifyWhenFinished: true)
+ }
+ }
+ }
+
+ public func incrementPart(amount: Int32)
+ {
+ async {
+ document in
+ let currentPart = document.getPart()
+ let numParts = document.getParts()
+ let newPart = currentPart + amount
+ if (newPart < numParts && newPart > 0)
+ {
+ document.setPart(nPart: newPart)
+ }
+ }
+ }
+}
+
+public typealias JSONObject = Dictionary<String, AnyObject>
+public func addProperty( _ json: inout JSONObject, _ parentValue: String, _ type: String, _ value: String)
+{
+ var child = JSONObject();
+ child["type"] = type as AnyObject
+ child["value"] = value as AnyObject
+ json[parentValue] = child as AnyObject
+}
+
+func encode(json: JSONObject) -> String?
+{
+ if let data = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
+ {
+ return String(data: data, encoding: String.Encoding.utf8)
+ }
+ return nil
+}
+
+/// Decodes a series of rectangles in the form: "x, y, width, height; x, y, width, height"
+public func decodeRects(_ payload: String?) -> [CGRect]?
+{
+ guard var pl = payload else { return nil }
+ pl = pl.trimmingCharacters(in: .whitespacesAndNewlines )
+ if pl == "EMPTY" || pl.count == 0
+ {
+ return nil
+ }
+ var ret = [CGRect]()
+ for rectStr in pl.split(separator: ";")
+ {
+ let coords = rectStr.split(separator: ",").compactMap { Double($0.trimmingCharacters(in: .whitespacesAndNewlines)) }
+ if coords.count == 4
+ {
+ let rect = CGRect(x: coords[0],
+ y: coords[1],
+ width: coords[2],
+ height: coords[3])
+ ret.append( rect )
+ }
+ }
+ return ret
+}
+
+// MARK :- Delegates
+
+public protocol DocumentUIDelegate: class
+{
+ func invalidateTiles(rects: [CGRect]? )
+ func invalidateVisibleCursor(rects: [CGRect]? )
+
+ func textSelection(rects: [CGRect]? )
+ func textSelectionStart(rects: [CGRect]? )
+ func textSelectionEnd(rects: [CGRect]? )
+}
+
+public protocol SearchDelegate: class
+{
+ func searchNotFound()
+ func searchResultSelection(searchResults: SearchResults)
+}
+
+/**
+ Encodes this example json:
+ {
+ "searchString": "Office",
+ "highlightAll": "true",
+ "searchResultSelection": [
+ {
+ "part": "0",
+ "rectangles": "1951, 10743, 627, 239"
+ },
+ {
+ "part": "0",
+ "rectangles": "5343, 9496, 627, 287"
+ },
+ {
+ "part": "0",
+ "rectangles": "1951, 9256, 627, 239"
+ },
+ {
+ "part": "0",
+ "rectangles": "6502, 5946, 626, 287"
+ },
+ {
+ "part": "0",
+ "rectangles": "6686, 5658, 627, 287"
+ },
+ {
+ "part": "0",
+ "rectangles": "4103, 5418, 573, 239"
+ },
+ {
+ "part": "0",
+ "rectangles": "1951, 5418, 627, 239"
+ },
+ {
+ "part": "0",
+ "rectangles": "4934, 1658, 1586, 559"
+ }
+ ]
+ }
+ */
+public struct SearchResults: Codable
+{
+ public var searchString: String?
+ public var highlightAll: String?
+ public var searchResultSelection: Array<PartAndRectangles>?
+}
+
+public struct PartAndRectangles: Codable
+{
+ public var part: String?
+ public var rectangles: String?
+
+ public var rectsAsCGRects: [CGRect]? {
+ return decodeRects(self.rectangles)
+ }
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LOKitThread.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LOKitThread.swift
new file mode 100644
index 000000000..cdf73ab2d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LOKitThread.swift
@@ -0,0 +1,139 @@
+//
+// 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/.
+//
+
+import Foundation
+import UIKit
+
+
+
+
+/// Serves the same purpose as the LOKitThread in the Android project - sequentialises all access to LOKit on a background thread, off the UI thread.
+/// It's a singleton, and keeps a single instance of LibreOfficeKit
+/// Public methods may be called from any thread, and will dispatch their work onto the held sequential queue.
+/// TODO: move me to framework
+public class LOKitThread
+{
+ public static let instance = LOKitThread() // statics are lazy and thread safe in swift, so no need for anything more complex
+
+
+ fileprivate let queue = SingleThreadedQueue(name: "LOKitThread.queue")
+
+ /// singleton LibreOffice instance. Can only be accessed through the queue.
+ var libreOffice: LibreOffice! = nil // initialised in didFinishLaunchingWithOptions
+
+ public weak var delegate: LOKitUIDelegate? = nil
+ public weak var progressDelegate: ProgressDelegate? = nil
+
+ private init()
+ {
+
+ async {
+ self.libreOffice = try! LibreOffice() // will blow up the app if it throws, but fair enough
+
+ // hook up event handler
+ self.libreOffice.registerCallback(callback: self.onLOKEvent)
+
+ }
+ }
+
+ private func onLOKEvent(type: LibreOfficeKitCallbackType, payload: String?)
+ {
+ //LibreOfficeLight.LibreOfficeKitKeyEventType.
+ print("onLOKEvent type:\(type) payload:\(payload ?? "")")
+
+ switch type
+ {
+ case LOK_CALLBACK_STATUS_INDICATOR_START:
+ runOnMain {
+ self.progressDelegate?.statusIndicatorStart()
+ }
+
+ case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
+ runOnMain {
+ if let doub = Double(payload ?? "")
+ {
+ self.progressDelegate?.statusIndicatorSetValue(value: doub)
+ }
+ }
+
+ case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
+ runOnMain {
+ self.progressDelegate?.statusIndicatorFinish()
+ }
+ default:
+ print("onLOKEvent type:\(type) not handled!")
+ }
+ }
+
+ /// Run the task on the serial queue, and return immediately
+ public func async(_ runnable: @escaping Runnable)
+ {
+ queue.async( runnable)
+ }
+
+ /// Run the task on the serial queue, and block to get the result
+ /// Careful of deadlocking!
+ public func sync<R>( _ closure: @escaping () -> R ) -> R
+ {
+ let ret = queue.sync( closure )
+ return ret
+ }
+
+ public func withLibreOffice( _ closure: @escaping (LibreOffice) -> ())
+ {
+ async {
+ closure(self.libreOffice)
+ }
+ }
+
+ /// Loads a document, and calls the callback with a wrapper if successful, or an error if not.
+ public func documentLoad(url: String, callback: @escaping (DocumentHolder?, Error?) -> ())
+ {
+ withLibreOffice
+ {
+ lo in
+
+ do
+ {
+ // this is trying to avoid null context errors which pop up on doc init
+ // doesn't seem to fix
+ UIGraphicsBeginImageContext(CGSize(width:1,height:1))
+ let doc = try lo.documentLoad(url: url)
+ print("Opened document: \(url)")
+ doc.initializeForRendering()
+ UIGraphicsEndImageContext()
+
+ callback(DocumentHolder(doc: doc), nil)
+ }
+ catch
+ {
+ print("Failed to load document: \(error)")
+ callback(nil, error)
+ }
+ }
+ }
+}
+
+/**
+ * Delegate methods for global events emitted from LOKit.
+ * Mostly dispatched on the main thread unless noted.
+ */
+public protocol LOKitUIDelegate: class
+{
+ // Nothing ATM...
+}
+
+public protocol ProgressDelegate: class
+{
+ func statusIndicatorStart()
+ func statusIndicatorFinish()
+ func statusIndicatorSetValue(value: Double)
+}
+
+
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitIOSTests.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitIOSTests.swift
new file mode 100644
index 000000000..de9f1ee82
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitIOSTests.swift
@@ -0,0 +1,102 @@
+//
+// LibreOfficeKitIOSTests.swift
+// LibreOfficeKitIOSTests
+//
+// Created by Jon Nermut on 30/12/17.
+// Copyright © 2017 LibreOffice. All rights reserved.
+//
+
+import XCTest
+@testable import LibreOfficeKitIOS
+
+class LibreOfficeKitIOSTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ super.tearDown()
+ }
+
+
+
+ func testLoadingSimpleDoc() {
+
+ guard let lo = try? LibreOffice() else
+ {
+ XCTFail("Could not start LibreOffice")
+ return
+ }
+
+ let b = Bundle.init(for: LibreOfficeKitIOSTests.self)
+ guard let url = b.url(forResource: "test-page-format", withExtension: "docx") else
+ {
+ XCTFail("Failed to get url to test doc")
+ return
+ }
+
+ var loCallbackCount = 0
+ lo.registerCallback()
+ {
+ typ, payload in
+ print(typ)
+ print(payload)
+ loCallbackCount += 1
+ }
+
+ guard let doc = try? lo.documentLoad(url: url.absoluteString) else
+ {
+ XCTFail("Could not load document")
+ return
+ }
+
+ var docCallbackCount = 0
+ doc.registerCallback()
+ {
+ typ, payload in
+ print(typ)
+ print(payload)
+ docCallbackCount += 1
+ }
+
+ //let typ: LibreOfficeDocumentType = doc.getDocumentType()
+ //XCTAssertTrue(typ == LibreOfficeDocumentType.LOK_DOCTYPE_TEXT)
+
+ doc.initializeForRendering()
+ let rects = doc.getPartRectanges()
+ print(rects) // 284, 284, 12240, 15840; 284, 16408, 12240, 15840
+ let tileMode = doc.getTileMode()
+ print(tileMode) // 1
+ let canvasSize = CGSize(width: 1024,height: 1024)
+ let tile = CGRect(x: 284, y: 284, width: 12240, height: 12240)
+
+
+ guard let image = doc.paintTileToImage(canvasSize: canvasSize, tileRect: tile) else
+ {
+ XCTFail("No image")
+ return
+ }
+ if let data = UIImagePNGRepresentation(image)
+ {
+ let filename = getDocumentsDirectory().appendingPathComponent("tile1.png")
+ try? data.write(to: filename)
+ print("Wrote tile to: \(filename)")
+ }
+ }
+
+}
+
+func getDocumentsDirectory() -> URL
+{
+ let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
+ return paths[0]
+}
+
+public extension Document
+{
+
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitWrapper.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitWrapper.swift
new file mode 100644
index 000000000..375dd6def
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/LibreOfficeKitWrapper.swift
@@ -0,0 +1,231 @@
+//
+// 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/.
+//
+
+import Foundation
+
+
+public struct LibreOfficeError: Error
+{
+ let message: String
+ public init(_ message: String)
+ {
+ self.message = message
+ }
+}
+
+public typealias LibreOfficeCallback = (_ type: LibreOfficeKitCallbackType, _ payload: String?) -> ()
+
+func callbackFromLibreOffice(nType: Int32, payload: UnsafePointer<Int8>?, pData: UnsafeMutableRawPointer?)
+{
+ if let val = pData?.hashValue
+ {
+ if let theFunc = Callbacks.callbackRegister[val]
+ {
+ let payString = toString(payload)
+ theFunc(LibreOfficeKitCallbackType(rawValue: LibreOfficeKitCallbackType.RawValue(nType)), payString)
+ }
+ else
+ {
+ print("Unknown callback: \(val)")
+ }
+ }
+ else
+ {
+ print("callbackFromLibreOffice, but pData was nil")
+ }
+}
+
+
+internal struct Callbacks
+{
+ static var count = 0
+ static var callbackRegister: Dictionary<Int, LibreOfficeCallback> = [:]
+
+ static func register(callback: @escaping LibreOfficeCallback) -> Int
+ {
+ count += 1
+ let id = count
+ callbackRegister[id] = callback
+ return id
+
+ }
+}
+
+
+open class LibreOffice
+{
+ private let pLok: UnsafeMutablePointer<LibreOfficeKit>
+ private let lokClass: LibreOfficeKitClass
+
+ public init() throws
+ {
+ let b = Bundle.init(for: LibreOffice.self)
+ let path = b.bundlePath // not Bundle.main.bundlePath
+ let docsDir = getDocumentsDirectory()
+ let userDir = docsDir.appendingPathComponent("user")
+ print("Calling BridgeLOkit_Init with \(path), \(userDir.path)" )
+ BridgeLOkit_Init(path, userDir.path)
+ let pLok = BridgeLOkit_getLOK()
+ if let lokClass = pLok?.pointee.pClass?.pointee
+ {
+ self.pLok = pLok!
+ self.lokClass = lokClass
+ print("Loaded LibreOfficeKit: \(self.getVersionInfo() ?? "")")
+ return
+ }
+ throw LibreOfficeError("Unable to init LibreOfficeKit")
+ }
+
+ /**
+ * Get version information of the LOKit process
+ *
+ * @since LibreOffice 6.0
+ * @returns JSON string containing version information in format:
+ * {ProductName: <>, ProductVersion: <>, ProductExtension: <>, BuildId: <>}
+ *
+ * Eg: {"ProductName": "LibreOffice",
+ * "ProductVersion": "5.3",
+ * "ProductExtension": ".0.0.alpha0",
+ * "BuildId": "<full 40 char git hash>"}
+ */
+ public func getVersionInfo() -> String?
+ {
+ if let pRet = lokClass.getVersionInfo(pLok)
+ {
+ return String(cString: pRet) // TODO: convert JSON
+ }
+ return nil
+ }
+
+ /**
+ * Loads a document from a URL.
+ *
+ * @param pUrl the URL of the document to load
+ * @param pFilterOptions options for the import filter, e.g. SkipImages.
+ * Another useful FilterOption is "Language=...". It is consumed
+ * by the documentLoad() itself, and when provided, LibreOfficeKit
+ * switches the language accordingly first.
+ * @since pFilterOptions argument added in LibreOffice 5.0
+ */
+ public func documentLoad(url: String) throws -> Document
+ {
+ if let pDoc = lokClass.documentLoad(pLok, url)
+ {
+ return Document(pDoc: pDoc)
+ }
+ throw LibreOfficeError("Unable to load document")
+ }
+
+
+
+ /// Returns the last error as a string
+ public func getError() -> String?
+ {
+ if let cstr = lokClass.getError(pLok)
+ {
+ let ret = String(cString: cstr)
+ lokClass.freeError(cstr)
+ return ret
+ }
+ return nil
+ }
+
+
+ /**
+ * Registers a callback. LOK will invoke this function when it wants to
+ * inform the client about events.
+ *
+ * @since LibreOffice 6.0
+ * @param pCallback the callback to invoke
+ * @param pData the user data, will be passed to the callback on invocation
+ */
+ @discardableResult
+ public func registerCallback( callback: @escaping LibreOfficeCallback ) -> Int
+ {
+ let ret = Callbacks.register(callback: callback)
+ let pointer = UnsafeMutableRawPointer(bitPattern: ret)
+ lokClass.registerCallback(pLok, callbackFromLibreOffice, pointer)
+ return ret
+ }
+
+ /**
+ * Returns details of filter types.
+ *
+ * Example returned string:
+ *
+ * {
+ * "writer8": {
+ * "MediaType": "application/vnd.oasis.opendocument.text"
+ * },
+ * "calc8": {
+ * "MediaType": "application/vnd.oasis.opendocument.spreadsheet"
+ * }
+ * }
+ *
+ * @since LibreOffice 6.0
+ */
+ public func getFilterTypes() -> String?
+ {
+ return toString(lokClass.getFilterTypes(pLok));
+ }
+
+ /**
+ * Set bitmask of optional features supported by the client.
+ *
+ * @since LibreOffice 6.0
+ * @see LibreOfficeKitOptionalFeatures
+ */
+ public func setOptionalFeatures(features: UInt64)
+ {
+ return lokClass.setOptionalFeatures(pLok, features);
+ }
+
+ /**
+ * Set password required for loading or editing a document.
+ *
+ * Loading the document is blocked until the password is provided.
+ *
+ * @param pURL the URL of the document, as sent to the callback
+ * @param pPassword the password, nullptr indicates no password
+ *
+ * In response to LOK_CALLBACK_DOCUMENT_PASSWORD, a valid password
+ * will continue loading the document, an invalid password will
+ * result in another LOK_CALLBACK_DOCUMENT_PASSWORD request,
+ * and a NULL password will abort loading the document.
+ *
+ * In response to LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY, a valid
+ * password will continue loading the document, an invalid password will
+ * result in another LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY request,
+ * and a NULL password will continue loading the document in read-only
+ * mode.
+ *
+ * @since LibreOffice 6.0
+ */
+ public func setDocumentPassword(URL: String, password: String)
+ {
+ lokClass.setDocumentPassword(pLok, URL, password);
+ }
+
+
+
+
+ /**
+ * Run a macro.
+ *
+ * Same syntax as on command line is permissible (ie. the macro:// URI forms)
+ *
+ * @since LibreOffice 6.0
+ * @param pURL macro url to run
+ */
+
+ public func runMacro( URL: String ) -> Bool
+ {
+ return lokClass.runMacro( pLok, URL ) != 0;
+ }
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/RenderCache.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/RenderCache.swift
new file mode 100644
index 000000000..f217db041
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/RenderCache.swift
@@ -0,0 +1,78 @@
+//
+// 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/.
+//
+
+import Foundation
+import UIKit
+
+
+open class CachedRender
+{
+ open let part: Int32
+ open let canvasSize: CGSize
+ open let tileRect: CGRect
+ open let image: UIImage
+
+ public init(part: Int32, canvasSize: CGSize, tileRect: CGRect, image: UIImage)
+ {
+ self.canvasSize = canvasSize
+ self.tileRect = tileRect
+ self.image = image
+ self.part = part
+ }
+}
+
+class RenderCache
+{
+ let CACHE_LOWMEM = 4
+ let CACHE_NORMAL = 20
+
+ var cachedRenders: [CachedRender] = []
+ var hasReceivedMemoryWarning = false
+
+ let lock = NSRecursiveLock()
+
+ func emptyCache()
+ {
+ lock.lock(); defer { lock.unlock() }
+ cachedRenders.removeAll()
+ }
+
+ func pruneCache()
+ {
+ lock.lock(); defer { lock.unlock() }
+
+ let max = hasReceivedMemoryWarning ? CACHE_LOWMEM : CACHE_NORMAL
+ while cachedRenders.count > max
+ {
+ cachedRenders.remove(at: 0)
+ }
+ }
+
+ func add(cachedRender: CachedRender)
+ {
+ lock.lock(); defer { lock.unlock() }
+
+ cachedRenders.append(cachedRender)
+ pruneCache()
+ }
+
+ func get(part: Int32, canvasSize: CGSize, tileRect: CGRect) -> UIImage?
+ {
+ lock.lock(); defer { lock.unlock() }
+
+ if let cr = cachedRenders.first(where: {
+ $0.canvasSize == canvasSize
+ && $0.tileRect == tileRect
+ && $0.part == part
+ })
+ {
+ return cr.image
+ }
+ return nil
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Util.swift b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Util.swift
new file mode 100644
index 000000000..596ca45e3
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LOKit/Util.swift
@@ -0,0 +1,43 @@
+//
+// 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/.
+//
+
+import UIKit
+
+
+func getDocumentsDirectory() -> URL
+{
+ let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
+ return paths[0]
+}
+
+public extension CGRect
+{
+ public var desc: String
+ {
+ return "(x: \(self.origin.x), y: \(self.origin.y), width: \(self.size.width), height: \(self.size.height), maxX: \(self.maxX), maxY: \(self.maxY))"
+ }
+}
+
+public func toString(_ pointer: UnsafeMutablePointer<Int8>?) -> String?
+{
+ if let p = pointer
+ {
+ return String(cString: p)
+ }
+ return nil
+}
+
+public func toString(_ pointer: UnsafePointer<Int8>?) -> String?
+{
+ if let p = pointer
+ {
+ return String(cString: p)
+ }
+ return nil
+}
+
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight-Prefix.pch b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight-Prefix.pch
new file mode 100644
index 000000000..638bf30e8
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight-Prefix.pch
@@ -0,0 +1,22 @@
+// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <Availability.h>
+
+#ifndef __IPHONE_5_0
+#warning "This project uses features only available in iOS SDK 5.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #include <premac.h>
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+ #include <postmac.h>
+#endif
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.entitlements b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.entitlements
new file mode 100644
index 000000000..bb42bb6ea
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.entitlements
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.developer.icloud-container-identifiers</key>
+ <array>
+ <string>iCloud.$(CFBundleIdentifier)</string>
+ </array>
+ <key>com.apple.developer.icloud-services</key>
+ <array>
+ <string>CloudDocuments</string>
+ </array>
+ <key>com.apple.developer.ubiquity-container-identifiers</key>
+ <array>
+ <string>iCloud.$(CFBundleIdentifier)</string>
+ </array>
+</dict>
+</plist>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/.xccurrentversion b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/.xccurrentversion
new file mode 100644
index 000000000..0c67376eb
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/.xccurrentversion
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict/>
+</plist>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/LibreOfficeLight.xcdatamodel/contents b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/LibreOfficeLight.xcdatamodel/contents
new file mode 100644
index 000000000..476e5b6cf
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/LibreOfficeLight.xcdatamodeld/LibreOfficeLight.xcdatamodel/contents
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
+ <elements/>
+</model> \ No newline at end of file
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/PropertiesController.swift b/ios/LibreOfficeLight/LibreOfficeLight/PropertiesController.swift
new file mode 100644
index 000000000..04ebaf78d
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/PropertiesController.swift
@@ -0,0 +1,99 @@
+//
+// 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/.
+//
+import UIKit
+
+
+class PropertiesController: UIViewController
+{
+ // Temp. functions
+ @IBAction func doStyle1(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ @IBAction func doStyle2(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ @IBAction func doStyle3(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ @IBAction func doStyle4(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ @IBAction func doStyle5(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ @IBAction func doStyle6(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+ @IBAction func doStyle7(_ sender: UIButton)
+ {
+ loadController("Document")
+ }
+
+
+
+ func loadController(_ name:String)
+ {
+ let destController : UIViewController = self.storyboard!.instantiateViewController(withIdentifier: name)
+ self.navigationController!.pushViewController(destController, animated: true)
+
+ UIView.animate(withDuration: 0.3, animations: { () -> Void in
+ self.view.frame = CGRect(x: -UIScreen.main.bounds.size.width, y: 0, width: UIScreen.main.bounds.size.width,height: UIScreen.main.bounds.size.height)
+ self.view.layoutIfNeeded()
+ self.view.backgroundColor = UIColor.clear
+ }, completion: { (finished) -> Void in
+ self.view.removeFromSuperview()
+ self.removeFromParentViewController()
+ })
+ }
+
+
+
+ override func viewDidLoad()
+ {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+
+
+ override func didReceiveMemoryWarning()
+ {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+
+
+ override func viewWillAppear(_ animated: Bool)
+ {
+ super.viewWillAppear(animated)
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/Root.plist b/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/Root.plist
new file mode 100644
index 000000000..0865e51d7
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/Root.plist
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>StringsTable</key>
+ <string>Root</string>
+ <key>PreferenceSpecifiers</key>
+ <array>
+ <dict>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ <key>Title</key>
+ <string>About</string>
+ </dict>
+ <dict>
+ <key>DefaultValue</key>
+ <string>The Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0.</string>
+ <key>Type</key>
+ <string>PSTextFieldSpecifier</string>
+ <key>Title</key>
+ <string>Copyright</string>
+ <key>Key</key>
+ <string>some text</string>
+ </dict>
+ <dict>
+ <key>DefaultValue</key>
+ <string>0.0.0</string>
+ <key>Type</key>
+ <string>PSTextFieldSpecifier</string>
+ <key>Title</key>
+ <string>Version</string>
+ <key>Key</key>
+ <string>application_version</string>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/en.lproj/Root.strings b/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/en.lproj/Root.strings
new file mode 100644
index 000000000..8cd87b9d6
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/Settings.bundle/en.lproj/Root.strings
Binary files differ
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/UIViewExtensions.swift b/ios/LibreOfficeLight/LibreOfficeLight/UIViewExtensions.swift
new file mode 100644
index 000000000..1c0322331
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/UIViewExtensions.swift
@@ -0,0 +1,74 @@
+//
+// 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/.
+//
+
+import UIKit
+
+public extension UIView
+{
+ public var height: CGFloat
+ {
+ get
+ {
+ return frame.size.height
+ }
+ set
+ {
+ frame.size.height = newValue
+ }
+ }
+
+ public var size: CGSize
+ {
+ get
+ {
+ return frame.size
+ }
+ set
+ {
+ width = newValue.width
+ height = newValue.height
+ }
+ }
+
+ public var width: CGFloat
+ {
+ get
+ {
+ return frame.size.width
+ }
+ set
+ {
+ frame.size.width = newValue
+ }
+ }
+
+ public var x: CGFloat
+ {
+ get
+ {
+ return frame.origin.x
+ }
+ set
+ {
+ frame.origin.x = newValue
+ }
+ }
+
+
+ public var y: CGFloat
+ {
+ get
+ {
+ return frame.origin.y
+ }
+ set
+ {
+ frame.origin.y = newValue
+ }
+ }
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/ViewPrintManager.swift b/ios/LibreOfficeLight/LibreOfficeLight/ViewPrintManager.swift
new file mode 100644
index 000000000..e05fa553f
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/ViewPrintManager.swift
@@ -0,0 +1,27 @@
+//
+// 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/.
+//
+import UIKit
+
+
+class ViewPrintManager: UIViewController
+{
+ override func viewDidLoad()
+ {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+
+
+ override func didReceiveMemoryWarning()
+ {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/ViewProperties.swift b/ios/LibreOfficeLight/LibreOfficeLight/ViewProperties.swift
new file mode 100644
index 000000000..2e275f2bd
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/ViewProperties.swift
@@ -0,0 +1,30 @@
+//
+// 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/.
+//
+import UIKit
+
+
+class ViewProperties: UIViewController
+{
+
+
+ override func viewDidLoad()
+ {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+
+
+ override func didReceiveMemoryWarning()
+ {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+
+}
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/LaunchScreen.xib b/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/LaunchScreen.xib
new file mode 100644
index 000000000..fa0ccf2ff
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/LaunchScreen.xib
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="LibreOfficeLight" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+ <rect key="frame" x="15" y="235" width="450" height="43"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="LibreOfficeLight is part of LibreOffice" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
+ <rect key="frame" x="15" y="293" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="https://www.libreoffice.org/get-help/community-support" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="6sz-Sz-e1h">
+ <rect key="frame" x="15" y="423" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="git://anongit.freedesktop.org/libreoffice/core" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="I4U-tD-bDs">
+ <rect key="frame" x="15" y="371" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Maintained by Jan Iversen and Jon Nermut" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jCj-XE-D37">
+ <rect key="frame" x="15" y="319" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="User support and development:" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="LOF-2P-X0o">
+ <rect key="frame" x="15" y="397" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="libreoffice@lists.freedesktop.org" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="h8D-4s-nQh">
+ <rect key="frame" x="15" y="449" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Full source is available at:" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="12" translatesAutoresizingMaskIntoConstraints="NO" id="R3A-1h-X3D">
+ <rect key="frame" x="15" y="345" width="450" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" image="intro" translatesAutoresizingMaskIntoConstraints="NO" id="iba-PG-iZB">
+ <rect key="frame" x="5" y="20" width="470" height="128"/>
+ </imageView>
+ </subviews>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="I4U-tD-bDs" firstAttribute="top" secondItem="R3A-1h-X3D" secondAttribute="bottom" constant="5" id="1MI-gV-daV"/>
+ <constraint firstItem="h8D-4s-nQh" firstAttribute="top" secondItem="6sz-Sz-e1h" secondAttribute="bottom" constant="5" id="76h-os-PqN"/>
+ <constraint firstAttribute="trailing" secondItem="jCj-XE-D37" secondAttribute="trailing" constant="15" id="DmL-rk-YcF"/>
+ <constraint firstAttribute="bottom" secondItem="h8D-4s-nQh" secondAttribute="bottom" constant="10" id="ESJ-gH-xnX"/>
+ <constraint firstAttribute="trailing" secondItem="I4U-tD-bDs" secondAttribute="trailing" constant="15" id="EgU-Wx-Hpw"/>
+ <constraint firstItem="I4U-tD-bDs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="Glv-5u-Qk4"/>
+ <constraint firstItem="LOF-2P-X0o" firstAttribute="top" secondItem="I4U-tD-bDs" secondAttribute="bottom" constant="5" id="H6a-qQ-p4a"/>
+ <constraint firstAttribute="trailing" secondItem="LOF-2P-X0o" secondAttribute="trailing" constant="15" id="J28-1n-Fgm"/>
+ <constraint firstItem="6sz-Sz-e1h" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="Jmn-sO-AVf"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="Qvq-TN-GGX"/>
+ <constraint firstAttribute="trailing" secondItem="iba-PG-iZB" secondAttribute="trailing" constant="5" id="SQG-Oy-orw"/>
+ <constraint firstItem="LOF-2P-X0o" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="T6B-k2-ejO"/>
+ <constraint firstItem="R3A-1h-X3D" firstAttribute="top" secondItem="jCj-XE-D37" secondAttribute="bottom" constant="5" id="Vzd-4l-NiA"/>
+ <constraint firstItem="h8D-4s-nQh" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="Wdb-nn-wdr"/>
+ <constraint firstAttribute="trailing" secondItem="6sz-Sz-e1h" secondAttribute="trailing" constant="15" id="ZCQ-vB-oHx"/>
+ <constraint firstAttribute="trailing" secondItem="kId-c2-rCX" secondAttribute="trailing" constant="15" id="ZvJ-2e-0hE"/>
+ <constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="cDT-4h-Rbh"/>
+ <constraint firstAttribute="trailing" secondItem="R3A-1h-X3D" secondAttribute="trailing" constant="15" id="dcX-7M-2kQ"/>
+ <constraint firstItem="8ie-xW-0ye" firstAttribute="top" secondItem="kId-c2-rCX" secondAttribute="bottom" constant="15" id="ftR-wj-GaQ"/>
+ <constraint firstItem="jCj-XE-D37" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="hTT-gF-WpT"/>
+ <constraint firstItem="R3A-1h-X3D" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="hbP-Wj-hgc"/>
+ <constraint firstItem="iba-PG-iZB" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="20" id="jwj-qG-D6R"/>
+ <constraint firstItem="jCj-XE-D37" firstAttribute="top" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="5" id="nW0-DF-i3G"/>
+ <constraint firstAttribute="trailing" secondItem="h8D-4s-nQh" secondAttribute="trailing" constant="15" id="nz0-e0-vfD"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="top" secondItem="iba-PG-iZB" secondAttribute="bottom" constant="8" symbolic="YES" id="ogG-Lo-8Ep"/>
+ <constraint firstAttribute="trailing" secondItem="8ie-xW-0ye" secondAttribute="trailing" constant="15" id="qKd-9S-EKe"/>
+ <constraint firstItem="6sz-Sz-e1h" firstAttribute="top" secondItem="LOF-2P-X0o" secondAttribute="bottom" constant="5" id="tdi-EJ-KXm"/>
+ <constraint firstItem="iba-PG-iZB" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="5" id="uoy-a0-Eez"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="548" y="455"/>
+ </view>
+ </objects>
+ <resources>
+ <image name="intro" width="500" height="128"/>
+ </resources>
+</document>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/Main.storyboard b/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/Main.storyboard
new file mode 100644
index 000000000..ffd5059d0
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/en.lproj/Main.storyboard
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="DGj-7d-jfR">
+ <device id="ipad9_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
+ <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="Navigation items with more than one left or right bar item" minToolsVersion="7.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Document-->
+ <scene sceneID="ufC-wZ-h7g">
+ <objects>
+ <viewController storyboardIdentifier="Document" useStoryboardIdentifierAsRestorationIdentifier="YES" id="vXZ-lx-hvc" customClass="DocumentController" customModule="LibreOfficeLight" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="lZa-u5-V0W"/>
+ <viewControllerLayoutGuide type="bottom" id="uE0-fS-86O"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
+ <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <subviews>
+ <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" minimumZoomScale="0.5" maximumZoomScale="8" translatesAutoresizingMaskIntoConstraints="NO" id="cJ7-wO-9D1">
+ <rect key="frame" x="0.0" y="64" width="768" height="960"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <connections>
+ <outlet property="delegate" destination="vXZ-lx-hvc" id="mWv-AB-k2W"/>
+ </connections>
+ </scrollView>
+ <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8HF-MM-fd0" userLabel="ButtonBar" customClass="ButtonScrollView" customModule="LibreOfficeLight" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="980" width="768" height="44"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ </view>
+ <view opaque="NO" userInteractionEnabled="NO" alpha="0.5" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="URZ-zU-xtO" userLabel="Mask">
+ <rect key="frame" x="0.0" y="64" width="768" height="960"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" fixedFrame="YES" progressViewStyle="bar" translatesAutoresizingMaskIntoConstraints="NO" id="hRJ-mR-Vnv">
+ <rect key="frame" x="309" y="479" width="150" height="1.5"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES"/>
+ </progressView>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
+ </view>
+ <searchBar hidden="YES" contentMode="redraw" fixedFrame="YES" placeholder="Search for text" showsCancelButton="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Aq0-4K-7FT">
+ <rect key="frame" x="0.0" y="64" width="768" height="56"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
+ <textInputTraits key="textInputTraits"/>
+ <connections>
+ <outlet property="delegate" destination="vXZ-lx-hvc" id="bZ5-fa-vQ6"/>
+ </connections>
+ </searchBar>
+ </subviews>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </view>
+ <toolbarItems/>
+ <navigationItem key="navigationItem" title="Document" id="5c6-32-T4J">
+ <barButtonItem key="leftBarButtonItem" image="menu" id="fdq-Uw-536" userLabel="Button Properties">
+ <connections>
+ <action selector="doProperties:" destination="vXZ-lx-hvc" id="mHw-Uf-vh2"/>
+ </connections>
+ </barButtonItem>
+ <rightBarButtonItems>
+ <barButtonItem systemItem="action" id="BNq-ol-ZVK">
+ <connections>
+ <segue destination="IER-X5-Ax8" kind="popoverPresentation" identifier="showActions" popoverAnchorBarButtonItem="BNq-ol-ZVK" id="xmZ-1A-ZrW">
+ <popoverArrowDirection key="popoverArrowDirection" up="YES" down="YES" left="YES" right="YES"/>
+ </segue>
+ </connections>
+ </barButtonItem>
+ <barButtonItem systemItem="search" id="3s2-a6-9gP">
+ <connections>
+ <action selector="searchIconTapped:" destination="vXZ-lx-hvc" id="tSY-uz-ifH"/>
+ </connections>
+ </barButtonItem>
+ </rightBarButtonItems>
+ </navigationItem>
+ <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
+ <connections>
+ <outlet property="buttonScrollView" destination="8HF-MM-fd0" id="Mlq-CV-p8N"/>
+ <outlet property="mask" destination="URZ-zU-xtO" id="pkw-v3-0gr"/>
+ <outlet property="progressBar" destination="hRJ-mR-Vnv" id="4lJ-kG-9SW"/>
+ <outlet property="scrollView" destination="cJ7-wO-9D1" id="U50-LO-plb"/>
+ <outlet property="searchBar" destination="Aq0-4K-7FT" id="B3A-Ck-UdD"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="1230.46875" y="303.515625"/>
+ </scene>
+ <!--Print Manager-->
+ <scene sceneID="viJ-XJ-htc">
+ <objects>
+ <viewController storyboardIdentifier="PrintManager" useStoryboardIdentifierAsRestorationIdentifier="YES" id="ay1-ce-WHs" customClass="ViewPrintManager" customModule="LibreOfficeLight" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="N2T-Vd-NX5"/>
+ <viewControllerLayoutGuide type="bottom" id="pxU-MS-J0z"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="uQ6-KY-cCv">
+ <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="My Print Manager" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cbo-NR-JZi">
+ <rect key="frame" x="175" y="386" width="156" height="21"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ </view>
+ <toolbarItems/>
+ <navigationItem key="navigationItem" title="Print Manager" id="2Z5-ad-smF">
+ <barButtonItem key="leftBarButtonItem" image="menu" id="KpY-Uq-nOk">
+ <connections>
+ <action selector="doProperties:" destination="ay1-ce-WHs" id="abP-LB-4yO"/>
+ </connections>
+ </barButtonItem>
+ </navigationItem>
+ <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="S7J-dT-DQn" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="1230" y="-458"/>
+ </scene>
+ <!--Navigation Controller-->
+ <scene sceneID="nrt-yR-DmY">
+ <objects>
+ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="DGj-7d-jfR" sceneMemberID="viewController">
+ <toolbarItems/>
+ <navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" id="mjw-Ry-qIh">
+ <rect key="frame" x="0.0" y="20" width="768" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <color key="barTintColor" red="0.0" green="0.58367598684210531" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <textAttributes key="titleTextAttributes">
+ <fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="20"/>
+ <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </textAttributes>
+ </navigationBar>
+ <nil name="viewControllers"/>
+ <connections>
+ <segue destination="h7c-B7-pKT" kind="show" identifier="showProperties" id="dDf-1s-0HH"/>
+ <segue destination="ay1-ce-WHs" kind="show" identifier="showPrintManager" id="BgL-QR-QJ0"/>
+ <segue destination="vXZ-lx-hvc" kind="relationship" relationship="rootViewController" id="ONR-Tq-ptF"/>
+ </connections>
+ </navigationController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="XfU-3W-Qcb" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="259.19999999999999" y="305.84707646176912"/>
+ </scene>
+ <!--Properties Controller-->
+ <scene sceneID="moB-At-Om8">
+ <objects>
+ <viewController storyboardIdentifier="PropertiesController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="E9y-3m-fEc" userLabel="Properties Controller" customClass="PropertiesController" customModule="LibreOfficeLight" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="qJv-1E-iEi"/>
+ <viewControllerLayoutGuide type="bottom" id="syI-80-ufe"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="e1u-sT-aSe">
+ <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g5y-SJ-jU1">
+ <rect key="frame" x="20" y="84" width="69" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="GiU-Zv-tSK"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style1" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle1:" destination="E9y-3m-fEc" eventType="touchUpInside" id="Tvz-2x-oik"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YTV-Y5-L8R">
+ <rect key="frame" x="20" y="139" width="71" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="6Nn-8E-Eun"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style2" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle2:" destination="E9y-3m-fEc" eventType="touchUpInside" id="u7L-s5-vmD"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eZV-Rh-hCf">
+ <rect key="frame" x="20" y="194" width="72" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="aVx-Vb-bZq"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style3" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle3:" destination="E9y-3m-fEc" eventType="touchUpInside" id="t2Q-iq-Exh"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CBj-V3-BKJ">
+ <rect key="frame" x="20" y="249" width="72" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="RLA-17-w0s"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style4" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle4:" destination="E9y-3m-fEc" eventType="touchUpInside" id="x4U-Gg-ylt"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hk4-yl-lM9">
+ <rect key="frame" x="20" y="304" width="72" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="AEu-v6-MfG"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style5" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle5:" destination="E9y-3m-fEc" eventType="touchUpInside" id="o3m-zn-dyf"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K3a-CQ-sBC">
+ <rect key="frame" x="20" y="359" width="72" height="45"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="45" id="fyO-4v-nFF"/>
+ </constraints>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style6" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle6:" destination="E9y-3m-fEc" eventType="touchUpInside" id="t58-52-FY4"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5Mv-7b-xjF">
+ <rect key="frame" x="20" y="414" width="70" height="45"/>
+ <inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
+ <state key="normal" title="Style7" image="document">
+ <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+ </state>
+ <connections>
+ <action selector="doStyle7:" destination="E9y-3m-fEc" eventType="touchUpInside" id="cNb-al-UOa"/>
+ </connections>
+ </button>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="eZV-Rh-hCf" firstAttribute="top" secondItem="YTV-Y5-L8R" secondAttribute="bottom" constant="10" id="8MW-wy-3mP"/>
+ <constraint firstItem="YTV-Y5-L8R" firstAttribute="leading" secondItem="g5y-SJ-jU1" secondAttribute="leading" id="GdK-zW-XUW"/>
+ <constraint firstItem="syI-80-ufe" firstAttribute="top" secondItem="5Mv-7b-xjF" secondAttribute="bottom" constant="565" id="H6C-1e-7UE"/>
+ <constraint firstItem="5Mv-7b-xjF" firstAttribute="leading" secondItem="e1u-sT-aSe" secondAttribute="leadingMargin" id="NnF-fS-TRc"/>
+ <constraint firstItem="CBj-V3-BKJ" firstAttribute="leading" secondItem="eZV-Rh-hCf" secondAttribute="leading" id="Nts-Pq-gbT"/>
+ <constraint firstItem="Hk4-yl-lM9" firstAttribute="top" secondItem="CBj-V3-BKJ" secondAttribute="bottom" constant="10" id="Qjz-bp-Zdz"/>
+ <constraint firstItem="CBj-V3-BKJ" firstAttribute="top" secondItem="eZV-Rh-hCf" secondAttribute="bottom" constant="10" id="TqY-lf-jld"/>
+ <constraint firstItem="Hk4-yl-lM9" firstAttribute="leading" secondItem="CBj-V3-BKJ" secondAttribute="leading" id="X9n-Bn-V0R"/>
+ <constraint firstItem="eZV-Rh-hCf" firstAttribute="leading" secondItem="YTV-Y5-L8R" secondAttribute="leading" id="XFl-0W-rjg"/>
+ <constraint firstItem="K3a-CQ-sBC" firstAttribute="top" secondItem="Hk4-yl-lM9" secondAttribute="bottom" constant="10" id="guC-5D-obv"/>
+ <constraint firstItem="K3a-CQ-sBC" firstAttribute="leading" secondItem="Hk4-yl-lM9" secondAttribute="leading" id="jpn-3d-FRp"/>
+ <constraint firstItem="5Mv-7b-xjF" firstAttribute="top" secondItem="K3a-CQ-sBC" secondAttribute="bottom" constant="10" id="ozy-Rl-tAb"/>
+ <constraint firstItem="5Mv-7b-xjF" firstAttribute="leading" secondItem="K3a-CQ-sBC" secondAttribute="leading" id="sHO-T6-sUz"/>
+ <constraint firstItem="YTV-Y5-L8R" firstAttribute="top" secondItem="g5y-SJ-jU1" secondAttribute="bottom" constant="10" id="v9r-Th-jAf"/>
+ <constraint firstItem="g5y-SJ-jU1" firstAttribute="top" secondItem="qJv-1E-iEi" secondAttribute="bottom" constant="64" id="wPY-qL-9aw"/>
+ </constraints>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="wg5-HE-6LR" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="-612" y="304.4977511244378"/>
+ </scene>
+ <!--Properties-->
+ <scene sceneID="XNm-Ch-28q">
+ <objects>
+ <viewController storyboardIdentifier="Properties" title="Properties" useStoryboardIdentifierAsRestorationIdentifier="YES" id="h7c-B7-pKT" customClass="ViewProperties" customModule="LibreOfficeLight" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="VKw-5g-PNK"/>
+ <viewControllerLayoutGuide type="bottom" id="BiA-CR-Pte"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="Z9n-50-7Jf">
+ <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="My Properties" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Jt-Yy-kcR">
+ <rect key="frame" x="166" y="484" width="142" height="21"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="vaO-NX-hiP" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="-447" y="-745"/>
+ </scene>
+ <!--Document Actions-->
+ <scene sceneID="U7J-9A-X5o">
+ <objects>
+ <tableViewController autoresizesArchivedViewToFullSize="NO" title="Document Actions" automaticallyAdjustsScrollViewInsets="NO" modalTransitionStyle="crossDissolve" modalPresentationStyle="overCurrentContext" clearsSelectionOnViewWillAppear="NO" id="IER-X5-Ax8" customClass="DocumentActions" customModule="LibreOfficeLight" customModuleProvider="target" sceneMemberID="viewController">
+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="30" sectionHeaderHeight="28" sectionFooterHeight="28" id="RqF-IL-YJc">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="210"/>
+ <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <sections>
+ <tableViewSection id="iZc-fF-wRk">
+ <cells>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="VNE-JL-Lw0">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="VNE-JL-Lw0" id="EB2-HA-y79">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="1" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="myk-zs-md7">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Open..."/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="0gI-or-ji2"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="XW7-H5-0ob">
+ <rect key="frame" x="0.0" y="30" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="XW7-H5-0ob" id="lJN-OL-mO8">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="2" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="b90-ja-Wm0" userLabel="Button Properties">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration" identifier="actionSave">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Properties"/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="ErC-4Q-0we"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="Osp-RA-lhK">
+ <rect key="frame" x="0.0" y="60" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Osp-RA-lhK" id="mU4-Wv-5dR">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="3" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m45-MR-Gca" userLabel="Button Save">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration" identifier="actionSave">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Save"/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="pXt-Kb-Vjw"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="Kys-Iw-SeT">
+ <rect key="frame" x="0.0" y="90" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Kys-Iw-SeT" id="2C9-6w-WS3">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="95N-Hk-rcU" userLabel="Button Close">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration" identifier="actionSave">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Close"/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="lIq-w7-Yr5"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="AN7-6j-wO7">
+ <rect key="frame" x="0.0" y="120" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AN7-6j-wO7" id="kl1-nQ-aIu">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6vH-aM-aYe" userLabel="Button Save copy">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Save copy..."/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="KBW-3d-D5Z"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="GmK-gj-GYu">
+ <rect key="frame" x="0.0" y="150" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="GmK-gj-GYu" id="3OK-Zz-mqN">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="apE-3B-lUt" userLabel="Button Save As PDF">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration" identifier="actionSaveAsPDF">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Save as PDF"/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="0gI-or-ji5"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="diN-3v-tgm">
+ <rect key="frame" x="0.0" y="180" width="134" height="30"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="diN-3v-tgm" id="24s-fs-4cw">
+ <rect key="frame" x="0.0" y="0.0" width="134" height="29.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tvH-WR-c61" userLabel="Button Print">
+ <rect key="frame" x="8" y="0.0" width="118" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <accessibility key="accessibilityConfiguration">
+ <bool key="isElement" value="NO"/>
+ </accessibility>
+ <state key="normal" title="Print..."/>
+ <connections>
+ <action selector="actionMenuSelect:" destination="IER-X5-Ax8" eventType="touchUpInside" id="saH-6n-BkX"/>
+ </connections>
+ </button>
+ </subviews>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </cells>
+ </tableViewSection>
+ </sections>
+ <connections>
+ <outlet property="dataSource" destination="IER-X5-Ax8" id="BBZ-8e-Waf"/>
+ <outlet property="delegate" destination="IER-X5-Ax8" id="sji-7W-aF0"/>
+ </connections>
+ </tableView>
+ <extendedEdge key="edgesForExtendedLayout"/>
+ <value key="contentSizeForViewInPopover" type="size" width="134" height="210"/>
+ <nil key="simulatedStatusBarMetrics"/>
+ <nil key="simulatedTopBarMetrics"/>
+ <nil key="simulatedBottomBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <size key="freeformSize" width="134" height="210"/>
+ <connections>
+ <outlet property="buttonClose" destination="95N-Hk-rcU" id="hJo-Qc-Wgv"/>
+ <outlet property="buttonOpen" destination="myk-zs-md7" id="xQK-I1-pDl"/>
+ <outlet property="buttonPrint" destination="tvH-WR-c61" id="4YU-p2-Fim"/>
+ <outlet property="buttonProperties" destination="b90-ja-Wm0" id="scY-Fn-fss"/>
+ <outlet property="buttonSave" destination="m45-MR-Gca" id="UZw-LX-Bco"/>
+ <outlet property="buttonSaveAs" destination="6vH-aM-aYe" id="4KY-Zi-iH4"/>
+ <outlet property="buttonSaveAsPDF" destination="apE-3B-lUt" id="AZL-ON-v2Y"/>
+ </connections>
+ </tableViewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="D6j-Ov-CSK" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="1799" y="303"/>
+ </scene>
+ </scenes>
+ <resources>
+ <image name="document" width="20" height="20"/>
+ <image name="menu" width="22" height="22"/>
+ </resources>
+</document>
diff --git a/ios/LibreOfficeLight/LibreOfficeLight/lokit-Bridging-Header.h b/ios/LibreOfficeLight/LibreOfficeLight/lokit-Bridging-Header.h
new file mode 100644
index 000000000..67feadb80
--- /dev/null
+++ b/ios/LibreOfficeLight/LibreOfficeLight/lokit-Bridging-Header.h
@@ -0,0 +1,16 @@
+//
+// 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/.
+//
+
+
+
+// LibreOfficeKit is a prelink of all used LO libraries, generated
+// as its own xCode project.
+#define LOK_USE_UNSTABLE_API
+#import "../../source/LibreOfficeKit.h"
+
+void temporaryHackToInvokeCallbackHandlers(LibreOfficeKitDocument* pThis);
diff --git a/ios/Makefile b/ios/Makefile
new file mode 100644
index 000000000..0c6f47b17
--- /dev/null
+++ b/ios/Makefile
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/ios/Module_ios.mk b/ios/Module_ios.mk
new file mode 100644
index 000000000..259c34ba3
--- /dev/null
+++ b/ios/Module_ios.mk
@@ -0,0 +1,25 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_Module_Module,ios))
+
+ifeq ($(OS),iOS)
+
+$(eval $(call gb_Module_add_targets,ios,\
+ CustomTarget_iOS_setup \
+))
+
+ifneq ($(ENABLE_IOS_LIBREOFFICELIGHT_APP),)
+$(eval $(call gb_Module_add_targets,ios,\
+ CustomTarget_iOS_link \
+))
+
+endif
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/ios/README b/ios/README
new file mode 100644
index 000000000..7f01d5d60
--- /dev/null
+++ b/ios/README
@@ -0,0 +1,49 @@
+Somewhat obsolete README for the LibreOfficeLight iOS app and LibreOfficeKit.
+
+-- LibreOfficeLight
+a swift based UI, very much work in progress
+
+-- support
+the arm64 and simulator are the only supported processors,
+old 32 bit iPhones are not supported.
+
+The swift app are done for 3 structures
+ simulator + full debug libraries
+ arm64 + full debug libraries
+ arm64 + optimized libraries
+
+-- SETUP
+Due to the 3 modes, at least 3 workdirs are needed together with a
+separated UI workdir.
+
+Because the main work is done on the UI, where it is convenient to
+switch fast between arm64 and simulator, it is advantageous to compile
+the 3 configurations of LO first, and then link against those.
+
+Due to the multiple workdirs a separate work directories are needed as follows:
+(names/locations can be changes, they are "linked" together by running autogen.sh)
+ ./core - libreoffice git clone (name can be changed)
+ ./ios-arm64 - workdir for production
+ ./ios-arm64-debug - workdir for debug on device
+ ./ios-simulator - workdir for simulator-debug
+
+-- Steps to generate
+1) copy ./core/distro-configs/LibreOfficeiOS.conf to autogen.input in
+ ./ios-arm64, ./ios-arm64-debug, ./ios-simulator
+ Correct as defined in the conf file,
+ add your local setup (e.g. location of tarballs)
+2) run ../core/autogen.sh in ios-arm64, ios-arm64-debug and ios-simulator
+3) run make in ios-arm64, ios-arm64-debug and ios-simulator
+ this will generate core/loApp.xcconfig which prepares LO to be compiled
+ and build LOkit is 3 configurations and store the preparedLibreOfficeKit
+ in ./core/ios/generated as:
+ release/libKit.a
+ release/libKit.dylib
+ debug/libKit.a
+ debug/libKit.dylib
+ simulator/libKit.a
+ simulator/libKit.dylib
+5) open xcode with LibreOfficeLight select scheme and build/test/run.
+6) enjoy
+
+
diff --git a/ios/UnitTest/UnitTest.xcodeproj/project.pbxproj b/ios/UnitTest/UnitTest.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..8e9177f60
--- /dev/null
+++ b/ios/UnitTest/UnitTest.xcodeproj/project.pbxproj
@@ -0,0 +1,814 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 50;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ BE39ADD7215D5470000B0244 /* test.odt in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADD6215D5470000B0244 /* test.odt */; };
+ BE39ADEF215D5AA4000B0244 /* icudt63l.dat in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE0215D5AA3000B0244 /* icudt63l.dat */; };
+ BE39ADF0215D5AA4000B0244 /* fundamentalrc in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE1215D5AA3000B0244 /* fundamentalrc */; };
+ BE39ADF1215D5AA4000B0244 /* services in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE2215D5AA3000B0244 /* services */; };
+ BE39ADF2215D5AA4000B0244 /* share in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE3215D5AA3000B0244 /* share */; };
+ BE39ADF3215D5AA4000B0244 /* oovbaapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE4215D5AA3000B0244 /* oovbaapi.rdb */; };
+ BE39ADF4215D5AA4000B0244 /* program in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE5215D5AA3000B0244 /* program */; };
+ BE39ADF5215D5AA4000B0244 /* config in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE6215D5AA3000B0244 /* config */; };
+ BE39ADF6215D5AA4000B0244 /* services.rdb in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE7215D5AA3000B0244 /* services.rdb */; };
+ BE39ADF7215D5AA4000B0244 /* registry in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE8215D5AA3000B0244 /* registry */; };
+ BE39ADF8215D5AA4000B0244 /* offapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADE9215D5AA3000B0244 /* offapi.rdb */; };
+ BE39ADF9215D5AA4000B0244 /* udkapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADEA215D5AA3000B0244 /* udkapi.rdb */; };
+ BE39ADFA215D5AA4000B0244 /* rc in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADEB215D5AA3000B0244 /* rc */; };
+ BE39ADFB215D5AA4000B0244 /* filter in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADEC215D5AA3000B0244 /* filter */; };
+ BE39ADFC215D5AA4000B0244 /* unorc in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADED215D5AA4000B0244 /* unorc */; };
+ BE39ADFD215D5AA4000B0244 /* welcome.odt in Resources */ = {isa = PBXBuildFile; fileRef = BE39ADEE215D5AA4000B0244 /* welcome.odt */; };
+ BE535616215D189A0068B3B7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BE535615215D189A0068B3B7 /* AppDelegate.m */; };
+ BE535619215D189A0068B3B7 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = BE535618215D189A0068B3B7 /* ViewController.mm */; };
+ BE53561C215D189A0068B3B7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE53561A215D189A0068B3B7 /* Main.storyboard */; };
+ BE53561E215D189E0068B3B7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE53561D215D189E0068B3B7 /* Assets.xcassets */; };
+ BE535621215D189E0068B3B7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE53561F215D189E0068B3B7 /* LaunchScreen.storyboard */; };
+ BE535624215D189E0068B3B7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BE535623215D189E0068B3B7 /* main.m */; };
+ BE93D41D216B4ECA007A39F4 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE93D41B216B378E007A39F4 /* MobileCoreServices.framework */; };
+ BEA1A6FE215D1D9700A9323B /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BEA1A6FD215D1D9700A9323B /* libz.tbd */; };
+ BEA1A700215D1D9F00A9323B /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BEA1A6FF215D1D9F00A9323B /* libiconv.tbd */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ BE39ADD6215D5470000B0244 /* test.odt */ = {isa = PBXFileReference; lastKnownFileType = file; name = test.odt; path = ../../../../odk/examples/cpp/DocumentLoader/test.odt; sourceTree = "<group>"; };
+ BE39ADE0215D5AA3000B0244 /* icudt63l.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = icudt63l.dat; path = ../../../../workdir/CustomTarget/ios/resources/icudt63l.dat; sourceTree = "<group>"; };
+ BE39ADE1215D5AA3000B0244 /* fundamentalrc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fundamentalrc; path = ../../../../workdir/CustomTarget/ios/resources/fundamentalrc; sourceTree = "<group>"; };
+ BE39ADE2215D5AA3000B0244 /* services */ = {isa = PBXFileReference; lastKnownFileType = folder; name = services; path = ../../../../workdir/CustomTarget/ios/resources/services; sourceTree = "<group>"; };
+ BE39ADE3215D5AA3000B0244 /* share */ = {isa = PBXFileReference; lastKnownFileType = folder; name = share; path = ../../../../workdir/CustomTarget/ios/resources/share; sourceTree = "<group>"; };
+ BE39ADE4215D5AA3000B0244 /* oovbaapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = oovbaapi.rdb; path = ../../../../workdir/CustomTarget/ios/resources/oovbaapi.rdb; sourceTree = "<group>"; };
+ BE39ADE5215D5AA3000B0244 /* program */ = {isa = PBXFileReference; lastKnownFileType = folder; name = program; path = ../../../../workdir/CustomTarget/ios/resources/program; sourceTree = "<group>"; };
+ BE39ADE6215D5AA3000B0244 /* config */ = {isa = PBXFileReference; lastKnownFileType = folder; name = config; path = ../../../../workdir/CustomTarget/ios/resources/config; sourceTree = "<group>"; };
+ BE39ADE7215D5AA3000B0244 /* services.rdb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = services.rdb; path = ../../../../workdir/CustomTarget/ios/resources/services.rdb; sourceTree = "<group>"; };
+ BE39ADE8215D5AA3000B0244 /* registry */ = {isa = PBXFileReference; lastKnownFileType = folder; name = registry; path = ../../../../workdir/CustomTarget/ios/resources/registry; sourceTree = "<group>"; };
+ BE39ADE9215D5AA3000B0244 /* offapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = offapi.rdb; path = ../../../../workdir/CustomTarget/ios/resources/offapi.rdb; sourceTree = "<group>"; };
+ BE39ADEA215D5AA3000B0244 /* udkapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = udkapi.rdb; path = ../../../../workdir/CustomTarget/ios/resources/udkapi.rdb; sourceTree = "<group>"; };
+ BE39ADEB215D5AA3000B0244 /* rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = rc; path = ../../../../workdir/CustomTarget/ios/resources/rc; sourceTree = "<group>"; };
+ BE39ADEC215D5AA3000B0244 /* filter */ = {isa = PBXFileReference; lastKnownFileType = folder; name = filter; path = ../../../../workdir/CustomTarget/ios/resources/filter; sourceTree = "<group>"; };
+ BE39ADED215D5AA4000B0244 /* unorc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = unorc; path = ../../../../workdir/CustomTarget/ios/resources/unorc; sourceTree = "<group>"; };
+ BE39ADEE215D5AA4000B0244 /* welcome.odt */ = {isa = PBXFileReference; lastKnownFileType = file; name = welcome.odt; path = ../../../../workdir/CustomTarget/ios/resources/welcome.odt; sourceTree = "<group>"; };
+ BE535611215D189A0068B3B7 /* UnitTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UnitTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ BE535614215D189A0068B3B7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+ BE535615215D189A0068B3B7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ BE535617215D189A0068B3B7 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
+ BE535618215D189A0068B3B7 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = "<group>"; };
+ BE53561B215D189A0068B3B7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+ BE53561D215D189E0068B3B7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+ BE535620215D189E0068B3B7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+ BE535622215D189E0068B3B7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ BE535623215D189E0068B3B7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ BE93D41B216B378E007A39F4 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+ BEA1A6FD215D1D9700A9323B /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
+ BEA1A6FF215D1D9F00A9323B /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
+ BEA20D2C2163C2570032F67B /* salgdiutils.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdiutils.cxx; path = ../../vcl/quartz/salgdiutils.cxx; sourceTree = "<group>"; };
+ BEA20D2D2163C2570032F67B /* ctfonts.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ctfonts.cxx; path = ../../vcl/quartz/ctfonts.cxx; sourceTree = "<group>"; };
+ BEA20D2E2163C2570032F67B /* utils.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = utils.cxx; path = ../../vcl/quartz/utils.cxx; sourceTree = "<group>"; };
+ BEA20D2F2163C2570032F67B /* salvd.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salvd.cxx; path = ../../vcl/quartz/salvd.cxx; sourceTree = "<group>"; };
+ BEA20D302163C2570032F67B /* salgdicommon.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdicommon.cxx; path = ../../vcl/quartz/salgdicommon.cxx; sourceTree = "<group>"; };
+ BEA20D312163C2570032F67B /* salbmp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salbmp.cxx; path = ../../vcl/quartz/salbmp.cxx; sourceTree = "<group>"; };
+ BEA20D322163C2570032F67B /* salgdi.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdi.cxx; path = ../../vcl/quartz/salgdi.cxx; sourceTree = "<group>"; };
+ BEA20D372164BAB80032F67B /* salusereventlist.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salusereventlist.cxx; path = ../../vcl/source/app/salusereventlist.cxx; sourceTree = "<group>"; };
+ BEA20D382164BAB80032F67B /* dbggui.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dbggui.cxx; path = ../../vcl/source/app/dbggui.cxx; sourceTree = "<group>"; };
+ BEA20D392164BAB80032F67B /* IconThemeInfo.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IconThemeInfo.cxx; path = ../../vcl/source/app/IconThemeInfo.cxx; sourceTree = "<group>"; };
+ BEA20D3A2164BAB80032F67B /* timer.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = timer.cxx; path = ../../vcl/source/app/timer.cxx; sourceTree = "<group>"; };
+ BEA20D3B2164BAB80032F67B /* customweld.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = customweld.cxx; path = ../../vcl/source/app/customweld.cxx; sourceTree = "<group>"; };
+ BEA20D3C2164BAB80032F67B /* vclevent.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = vclevent.cxx; path = ../../vcl/source/app/vclevent.cxx; sourceTree = "<group>"; };
+ BEA20D3D2164BAB80032F67B /* settings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = settings.cxx; path = ../../vcl/source/app/settings.cxx; sourceTree = "<group>"; };
+ BEA20D3E2164BAB80032F67B /* salplug.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salplug.cxx; path = ../../vcl/source/app/salplug.cxx; sourceTree = "<group>"; };
+ BEA20D3F2164BAB80032F67B /* i18nhelp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = i18nhelp.cxx; path = ../../vcl/source/app/i18nhelp.cxx; sourceTree = "<group>"; };
+ BEA20D402164BAB80032F67B /* sound.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = sound.cxx; path = ../../vcl/source/app/sound.cxx; sourceTree = "<group>"; };
+ BEA20D412164BAB80032F67B /* svapp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svapp.cxx; path = ../../vcl/source/app/svapp.cxx; sourceTree = "<group>"; };
+ BEA20D422164BAB80032F67B /* idle.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = idle.cxx; path = ../../vcl/source/app/idle.cxx; sourceTree = "<group>"; };
+ BEA20D432164BAB80032F67B /* help.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = help.cxx; path = ../../vcl/source/app/help.cxx; sourceTree = "<group>"; };
+ BEA20D442164BAB80032F67B /* IconThemeSelector.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IconThemeSelector.cxx; path = ../../vcl/source/app/IconThemeSelector.cxx; sourceTree = "<group>"; };
+ BEA20D452164BAB80032F67B /* brand.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = brand.cxx; path = ../../vcl/source/app/brand.cxx; sourceTree = "<group>"; };
+ BEA20D462164BAB80032F67B /* IconThemeScanner.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IconThemeScanner.cxx; path = ../../vcl/source/app/IconThemeScanner.cxx; sourceTree = "<group>"; };
+ BEA20D472164BAB80032F67B /* session.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = session.cxx; path = ../../vcl/source/app/session.cxx; sourceTree = "<group>"; };
+ BEA20D482164BAB80032F67B /* unohelp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = unohelp.cxx; path = ../../vcl/source/app/unohelp.cxx; sourceTree = "<group>"; };
+ BEA20D492164BAB80032F67B /* svdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svdata.cxx; path = ../../vcl/source/app/svdata.cxx; sourceTree = "<group>"; };
+ BEA20D4A2164BAB80032F67B /* dndhelp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dndhelp.cxx; path = ../../vcl/source/app/dndhelp.cxx; sourceTree = "<group>"; };
+ BEA20D4B2164BAB80032F67B /* salvtables.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salvtables.cxx; path = ../../vcl/source/app/salvtables.cxx; sourceTree = "<group>"; };
+ BEA20D4C2164BAB80032F67B /* scheduler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = scheduler.cxx; path = ../../vcl/source/app/scheduler.cxx; sourceTree = "<group>"; };
+ BEA20D4D2164BAB80032F67B /* ITiledRenderable.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ITiledRenderable.cxx; path = ../../vcl/source/app/ITiledRenderable.cxx; sourceTree = "<group>"; };
+ BEA20D4E2164BAB80032F67B /* stdtext.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = stdtext.cxx; path = ../../vcl/source/app/stdtext.cxx; sourceTree = "<group>"; };
+ BEA20D4F2164BAB80032F67B /* unohelp2.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = unohelp2.cxx; path = ../../vcl/source/app/unohelp2.cxx; sourceTree = "<group>"; };
+ BEA20D502164BAB80032F67B /* svmain.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svmain.cxx; path = ../../vcl/source/app/svmain.cxx; sourceTree = "<group>"; };
+ BEA20D522164BB0D0032F67B /* iosinst.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = iosinst.cxx; path = ../../vcl/ios/iosinst.cxx; sourceTree = "<group>"; };
+ BEA20D532164BB0E0032F67B /* dummies.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dummies.cxx; path = ../../vcl/ios/dummies.cxx; sourceTree = "<group>"; };
+ BEA20D652166596F0032F67B /* svpvd.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpvd.cxx; path = ../../vcl/headless/svpvd.cxx; sourceTree = "<group>"; };
+ BEA20D662166596F0032F67B /* svpframe.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpframe.cxx; path = ../../vcl/headless/svpframe.cxx; sourceTree = "<group>"; };
+ BEA20D672166596F0032F67B /* svpbmp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpbmp.cxx; path = ../../vcl/headless/svpbmp.cxx; sourceTree = "<group>"; };
+ BEA20D682166596F0032F67B /* svpcairotextrender.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpcairotextrender.cxx; path = ../../vcl/headless/svpcairotextrender.cxx; sourceTree = "<group>"; };
+ BEA20D692166596F0032F67B /* svpgdi.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpgdi.cxx; path = ../../vcl/headless/svpgdi.cxx; sourceTree = "<group>"; };
+ BEA20D6A2166596F0032F67B /* svpglyphcache.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpglyphcache.cxx; path = ../../vcl/headless/svpglyphcache.cxx; sourceTree = "<group>"; };
+ BEA20D6B2166596F0032F67B /* svpinst.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpinst.cxx; path = ../../vcl/headless/svpinst.cxx; sourceTree = "<group>"; };
+ BEA20D6C2166596F0032F67B /* svptext.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svptext.cxx; path = ../../vcl/headless/svptext.cxx; sourceTree = "<group>"; };
+ BEA20D6D2166596F0032F67B /* headlessinst.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = headlessinst.cxx; path = ../../vcl/headless/headlessinst.cxx; sourceTree = "<group>"; };
+ BEA20D6E2166596F0032F67B /* svpdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpdata.cxx; path = ../../vcl/headless/svpdata.cxx; sourceTree = "<group>"; };
+ BEA20D6F2166596F0032F67B /* svpdummies.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpdummies.cxx; path = ../../vcl/headless/svpdummies.cxx; sourceTree = "<group>"; };
+ BEA20D702166596F0032F67B /* svpprn.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpprn.cxx; path = ../../vcl/headless/svpprn.cxx; sourceTree = "<group>"; };
+ BEA20DC221678BB60032F67B /* lokcharthelper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lokcharthelper.cxx; path = ../../sfx2/source/view/lokcharthelper.cxx; sourceTree = "<group>"; };
+ BEA20DC4216797C00032F67B /* pdffontcache.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = pdffontcache.hxx; path = ../../vcl/source/gdi/pdffontcache.hxx; sourceTree = "<group>"; };
+ BEA20DC5216797C00032F67B /* impgraph.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = impgraph.cxx; path = ../../vcl/source/gdi/impgraph.cxx; sourceTree = "<group>"; };
+ BEA20DC6216797C00032F67B /* base14.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = base14.cxx; path = ../../vcl/source/gdi/base14.cxx; sourceTree = "<group>"; };
+ BEA20DC7216797C00032F67B /* bmpfast.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bmpfast.cxx; path = ../../vcl/source/gdi/bmpfast.cxx; sourceTree = "<group>"; };
+ BEA20DC8216797C00032F67B /* vectorgraphicdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = vectorgraphicdata.cxx; path = ../../vcl/source/gdi/vectorgraphicdata.cxx; sourceTree = "<group>"; };
+ BEA20DC9216797C00032F67B /* pdfwriter_impl2.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pdfwriter_impl2.cxx; path = ../../vcl/source/gdi/pdfwriter_impl2.cxx; sourceTree = "<group>"; };
+ BEA20DCA216797C00032F67B /* mapmod.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mapmod.cxx; path = ../../vcl/source/gdi/mapmod.cxx; sourceTree = "<group>"; };
+ BEA20DCB216797C00032F67B /* bitmap3.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap3.cxx; path = ../../vcl/source/gdi/bitmap3.cxx; sourceTree = "<group>"; };
+ BEA20DCC216797C00032F67B /* pdfwriter.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pdfwriter.cxx; path = ../../vcl/source/gdi/pdfwriter.cxx; sourceTree = "<group>"; };
+ BEA20DCD216797C00032F67B /* salmisc.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salmisc.cxx; path = ../../vcl/source/gdi/salmisc.cxx; sourceTree = "<group>"; };
+ BEA20DCE216797C00032F67B /* impvect.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = impvect.hxx; path = ../../vcl/source/gdi/impvect.hxx; sourceTree = "<group>"; };
+ BEA20DCF216797C00032F67B /* oldprintadaptor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = oldprintadaptor.cxx; path = ../../vcl/source/gdi/oldprintadaptor.cxx; sourceTree = "<group>"; };
+ BEA20DD0216797C00032F67B /* extoutdevdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = extoutdevdata.cxx; path = ../../vcl/source/gdi/extoutdevdata.cxx; sourceTree = "<group>"; };
+ BEA20DD1216797C10032F67B /* cvtgrf.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = cvtgrf.cxx; path = ../../vcl/source/gdi/cvtgrf.cxx; sourceTree = "<group>"; };
+ BEA20DD2216797C10032F67B /* graphictools.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = graphictools.cxx; path = ../../vcl/source/gdi/graphictools.cxx; sourceTree = "<group>"; };
+ BEA20DD3216797C10032F67B /* gdimetafiletools.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gdimetafiletools.cxx; path = ../../vcl/source/gdi/gdimetafiletools.cxx; sourceTree = "<group>"; };
+ BEA20DD4216797C10032F67B /* genVerticalOrientationData.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; name = genVerticalOrientationData.pl; path = ../../vcl/source/gdi/genVerticalOrientationData.pl; sourceTree = "<group>"; };
+ BEA20DD5216797C10032F67B /* bmpacc3.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bmpacc3.cxx; path = ../../vcl/source/gdi/bmpacc3.cxx; sourceTree = "<group>"; };
+ BEA20DD6216797C10032F67B /* print.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = print.cxx; path = ../../vcl/source/gdi/print.cxx; sourceTree = "<group>"; };
+ BEA20DD7216797C10032F67B /* configsettings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = configsettings.cxx; path = ../../vcl/source/gdi/configsettings.cxx; sourceTree = "<group>"; };
+ BEA20DD8216797C10032F67B /* print3.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = print3.cxx; path = ../../vcl/source/gdi/print3.cxx; sourceTree = "<group>"; };
+ BEA20DD9216797C10032F67B /* graph.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = graph.cxx; path = ../../vcl/source/gdi/graph.cxx; sourceTree = "<group>"; };
+ BEA20DDA216797C10032F67B /* octree.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = octree.cxx; path = ../../vcl/source/gdi/octree.cxx; sourceTree = "<group>"; };
+ BEA20DDB216797C10032F67B /* scrptrun.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = scrptrun.cxx; path = ../../vcl/source/gdi/scrptrun.cxx; sourceTree = "<group>"; };
+ BEA20DDC216797C10032F67B /* regionband.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = regionband.cxx; path = ../../vcl/source/gdi/regionband.cxx; sourceTree = "<group>"; };
+ BEA20DDD216797C10032F67B /* gdimtf.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gdimtf.cxx; path = ../../vcl/source/gdi/gdimtf.cxx; sourceTree = "<group>"; };
+ BEA20DDE216797C10032F67B /* pdfextoutdevdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pdfextoutdevdata.cxx; path = ../../vcl/source/gdi/pdfextoutdevdata.cxx; sourceTree = "<group>"; };
+ BEA20DDF216797C10032F67B /* pdffontcache.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pdffontcache.cxx; path = ../../vcl/source/gdi/pdffontcache.cxx; sourceTree = "<group>"; };
+ BEA20DE0216797C10032F67B /* textlayout.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = textlayout.cxx; path = ../../vcl/source/gdi/textlayout.cxx; sourceTree = "<group>"; };
+ BEA20DE1216797C10032F67B /* virdev.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = virdev.cxx; path = ../../vcl/source/gdi/virdev.cxx; sourceTree = "<group>"; };
+ BEA20DE2216797C10032F67B /* embeddedfontshelper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = embeddedfontshelper.cxx; path = ../../vcl/source/gdi/embeddedfontshelper.cxx; sourceTree = "<group>"; };
+ BEA20DE3216797C10032F67B /* salgdiimpl.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdiimpl.cxx; path = ../../vcl/source/gdi/salgdiimpl.cxx; sourceTree = "<group>"; };
+ BEA20DE4216797C10032F67B /* gfxlink.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gfxlink.cxx; path = ../../vcl/source/gdi/gfxlink.cxx; sourceTree = "<group>"; };
+ BEA20DE5216797C10032F67B /* alpha.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = alpha.cxx; path = ../../vcl/source/gdi/alpha.cxx; sourceTree = "<group>"; };
+ BEA20DE6216797C10032F67B /* hatch.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = hatch.cxx; path = ../../vcl/source/gdi/hatch.cxx; sourceTree = "<group>"; };
+ BEA20DE7216797C10032F67B /* svmconverter.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svmconverter.cxx; path = ../../vcl/source/gdi/svmconverter.cxx; sourceTree = "<group>"; };
+ BEA20DE8216797C10032F67B /* pngwrite.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pngwrite.cxx; path = ../../vcl/source/gdi/pngwrite.cxx; sourceTree = "<group>"; };
+ BEA20DE9216797C10032F67B /* gradient.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gradient.cxx; path = ../../vcl/source/gdi/gradient.cxx; sourceTree = "<group>"; };
+ BEA20DEA216797C10032F67B /* pngread.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pngread.cxx; path = ../../vcl/source/gdi/pngread.cxx; sourceTree = "<group>"; };
+ BEA20DEB216797C10032F67B /* salgdilayout.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdilayout.cxx; path = ../../vcl/source/gdi/salgdilayout.cxx; sourceTree = "<group>"; };
+ BEA20DEC216797C20032F67B /* bitmapex.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bitmapex.cxx; path = ../../vcl/source/gdi/bitmapex.cxx; sourceTree = "<group>"; };
+ BEA20DED216797C20032F67B /* lineinfo.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lineinfo.cxx; path = ../../vcl/source/gdi/lineinfo.cxx; sourceTree = "<group>"; };
+ BEA20DEE216797C20032F67B /* animate.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = animate.cxx; path = ../../vcl/source/gdi/animate.cxx; sourceTree = "<group>"; };
+ BEA20DEF216797C20032F67B /* bmpacc.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bmpacc.cxx; path = ../../vcl/source/gdi/bmpacc.cxx; sourceTree = "<group>"; };
+ BEA20DF0216797C20032F67B /* pdfwriter_impl.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pdfwriter_impl.cxx; path = ../../vcl/source/gdi/pdfwriter_impl.cxx; sourceTree = "<group>"; };
+ BEA20DF1216797C20032F67B /* wall.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = wall.cxx; path = ../../vcl/source/gdi/wall.cxx; sourceTree = "<group>"; };
+ BEA20DF2216797C20032F67B /* impvect.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = impvect.cxx; path = ../../vcl/source/gdi/impvect.cxx; sourceTree = "<group>"; };
+ BEA20DF3216797C20032F67B /* impanmvw.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = impanmvw.cxx; path = ../../vcl/source/gdi/impanmvw.cxx; sourceTree = "<group>"; };
+ BEA20DF4216797C20032F67B /* print2.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = print2.cxx; path = ../../vcl/source/gdi/print2.cxx; sourceTree = "<group>"; };
+ BEA20DF5216797C20032F67B /* metaact.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = metaact.cxx; path = ../../vcl/source/gdi/metaact.cxx; sourceTree = "<group>"; };
+ BEA20DF6216797C20032F67B /* CommonSalLayout.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CommonSalLayout.cxx; path = ../../vcl/source/gdi/CommonSalLayout.cxx; sourceTree = "<group>"; };
+ BEA20DF7216797C20032F67B /* pdfwriter_impl.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = pdfwriter_impl.hxx; path = ../../vcl/source/gdi/pdfwriter_impl.hxx; sourceTree = "<group>"; };
+ BEA20DF8216797C20032F67B /* dibtools.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dibtools.cxx; path = ../../vcl/source/gdi/dibtools.cxx; sourceTree = "<group>"; };
+ BEA20DF9216797C20032F67B /* sallayout.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = sallayout.cxx; path = ../../vcl/source/gdi/sallayout.cxx; sourceTree = "<group>"; };
+ BEA20DFA216797C20032F67B /* bmpacc2.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bmpacc2.cxx; path = ../../vcl/source/gdi/bmpacc2.cxx; sourceTree = "<group>"; };
+ BEA20DFB216797C20032F67B /* regband.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = regband.cxx; path = ../../vcl/source/gdi/regband.cxx; sourceTree = "<group>"; };
+ BEA20DFC216797C20032F67B /* jobset.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jobset.cxx; path = ../../vcl/source/gdi/jobset.cxx; sourceTree = "<group>"; };
+ BEA20DFD216797C20032F67B /* VerticalOrientationData.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = VerticalOrientationData.cxx; path = ../../vcl/source/gdi/VerticalOrientationData.cxx; sourceTree = "<group>"; };
+ BEA20DFE216797C20032F67B /* region.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = region.cxx; path = ../../vcl/source/gdi/region.cxx; sourceTree = "<group>"; };
+ BEA20DFF216797C20032F67B /* salnativewidgets-none.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "salnativewidgets-none.cxx"; path = "../../vcl/source/gdi/salnativewidgets-none.cxx"; sourceTree = "<group>"; };
+ BEA20E012167A47B0032F67B /* gradient.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gradient.cxx; path = ../../vcl/source/outdev/gradient.cxx; sourceTree = "<group>"; };
+ BEA20E022167A47C0032F67B /* polygon.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = polygon.cxx; path = ../../vcl/source/outdev/polygon.cxx; sourceTree = "<group>"; };
+ BEA20E032167A47C0032F67B /* text.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = text.cxx; path = ../../vcl/source/outdev/text.cxx; sourceTree = "<group>"; };
+ BEA20E042167A47C0032F67B /* outdevstate.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = outdevstate.cxx; path = ../../vcl/source/outdev/outdevstate.cxx; sourceTree = "<group>"; };
+ BEA20E052167A47C0032F67B /* wallpaper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = wallpaper.cxx; path = ../../vcl/source/outdev/wallpaper.cxx; sourceTree = "<group>"; };
+ BEA20E062167A47C0032F67B /* line.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = line.cxx; path = ../../vcl/source/outdev/line.cxx; sourceTree = "<group>"; };
+ BEA20E072167A47C0032F67B /* curvedshapes.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = curvedshapes.cxx; path = ../../vcl/source/outdev/curvedshapes.cxx; sourceTree = "<group>"; };
+ BEA20E082167A47C0032F67B /* map.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = map.cxx; path = ../../vcl/source/outdev/map.cxx; sourceTree = "<group>"; };
+ BEA20E092167A47C0032F67B /* clipping.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = clipping.cxx; path = ../../vcl/source/outdev/clipping.cxx; sourceTree = "<group>"; };
+ BEA20E0A2167A47C0032F67B /* bitmap.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap.cxx; path = ../../vcl/source/outdev/bitmap.cxx; sourceTree = "<group>"; };
+ BEA20E0B2167A47C0032F67B /* font.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = font.cxx; path = ../../vcl/source/outdev/font.cxx; sourceTree = "<group>"; };
+ BEA20E0C2167A47C0032F67B /* hatch.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = hatch.cxx; path = ../../vcl/source/outdev/hatch.cxx; sourceTree = "<group>"; };
+ BEA20E0D2167A47C0032F67B /* nativecontrols.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = nativecontrols.cxx; path = ../../vcl/source/outdev/nativecontrols.cxx; sourceTree = "<group>"; };
+ BEA20E0E2167A47C0032F67B /* polyline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = polyline.cxx; path = ../../vcl/source/outdev/polyline.cxx; sourceTree = "<group>"; };
+ BEA20E0F2167A47C0032F67B /* rect.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = rect.cxx; path = ../../vcl/source/outdev/rect.cxx; sourceTree = "<group>"; };
+ BEA20E102167A47C0032F67B /* outdevstatestack.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = outdevstatestack.cxx; path = ../../vcl/source/outdev/outdevstatestack.cxx; sourceTree = "<group>"; };
+ BEA20E112167A47C0032F67B /* textline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = textline.cxx; path = ../../vcl/source/outdev/textline.cxx; sourceTree = "<group>"; };
+ BEA20E122167A47C0032F67B /* outdev.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = outdev.cxx; path = ../../vcl/source/outdev/outdev.cxx; sourceTree = "<group>"; };
+ BEA20E132167A47C0032F67B /* transparent.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = transparent.cxx; path = ../../vcl/source/outdev/transparent.cxx; sourceTree = "<group>"; };
+ BEA20E142167A47C0032F67B /* vclreferencebase.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = vclreferencebase.cxx; path = ../../vcl/source/outdev/vclreferencebase.cxx; sourceTree = "<group>"; };
+ BEA20E152167A47C0032F67B /* mask.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mask.cxx; path = ../../vcl/source/outdev/mask.cxx; sourceTree = "<group>"; };
+ BEA20E162167A47C0032F67B /* pixel.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pixel.cxx; path = ../../vcl/source/outdev/pixel.cxx; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ BE53560E215D189A0068B3B7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BE93D41D216B4ECA007A39F4 /* MobileCoreServices.framework in Frameworks */,
+ BEA1A700215D1D9F00A9323B /* libiconv.tbd in Frameworks */,
+ BEA1A6FE215D1D9700A9323B /* libz.tbd in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ BE39ADD5215D5448000B0244 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ BE39ADE6215D5AA3000B0244 /* config */,
+ BE39ADEC215D5AA3000B0244 /* filter */,
+ BE39ADE1215D5AA3000B0244 /* fundamentalrc */,
+ BE39ADE0215D5AA3000B0244 /* icudt63l.dat */,
+ BE39ADE9215D5AA3000B0244 /* offapi.rdb */,
+ BE39ADE4215D5AA3000B0244 /* oovbaapi.rdb */,
+ BE39ADE5215D5AA3000B0244 /* program */,
+ BE39ADEB215D5AA3000B0244 /* rc */,
+ BE39ADE8215D5AA3000B0244 /* registry */,
+ BE39ADE2215D5AA3000B0244 /* services */,
+ BE39ADE7215D5AA3000B0244 /* services.rdb */,
+ BE39ADE3215D5AA3000B0244 /* share */,
+ BE39ADEA215D5AA3000B0244 /* udkapi.rdb */,
+ BE39ADED215D5AA4000B0244 /* unorc */,
+ BE39ADEE215D5AA4000B0244 /* welcome.odt */,
+ BE39ADD6215D5470000B0244 /* test.odt */,
+ );
+ path = Resources;
+ sourceTree = "<group>";
+ };
+ BE535608215D189A0068B3B7 = {
+ isa = PBXGroup;
+ children = (
+ BEA20D2A2163C2210032F67B /* Core */,
+ BE535613215D189A0068B3B7 /* UnitTest */,
+ BE535612215D189A0068B3B7 /* Products */,
+ BEA1A6FC215D1D9700A9323B /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ BE535612215D189A0068B3B7 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ BE535611215D189A0068B3B7 /* UnitTest.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ BE535613215D189A0068B3B7 /* UnitTest */ = {
+ isa = PBXGroup;
+ children = (
+ BE39ADD5215D5448000B0244 /* Resources */,
+ BE535614215D189A0068B3B7 /* AppDelegate.h */,
+ BE535615215D189A0068B3B7 /* AppDelegate.m */,
+ BE535617215D189A0068B3B7 /* ViewController.h */,
+ BE535618215D189A0068B3B7 /* ViewController.mm */,
+ BE53561A215D189A0068B3B7 /* Main.storyboard */,
+ BE53561D215D189E0068B3B7 /* Assets.xcassets */,
+ BE53561F215D189E0068B3B7 /* LaunchScreen.storyboard */,
+ BE535622215D189E0068B3B7 /* Info.plist */,
+ BE535623215D189E0068B3B7 /* main.m */,
+ );
+ path = UnitTest;
+ sourceTree = "<group>";
+ };
+ BEA1A6FC215D1D9700A9323B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ BE93D41B216B378E007A39F4 /* MobileCoreServices.framework */,
+ BEA1A6FF215D1D9F00A9323B /* libiconv.tbd */,
+ BEA1A6FD215D1D9700A9323B /* libz.tbd */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ BEA20D2A2163C2210032F67B /* Core */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20DC021678B960032F67B /* sfx2 */,
+ BEA20D2B2163C2360032F67B /* vcl */,
+ );
+ name = Core;
+ sourceTree = "<group>";
+ };
+ BEA20D2B2163C2360032F67B /* vcl */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20D342164BA8B0032F67B /* app */,
+ BEA20DC3216797A00032F67B /* gdi */,
+ BEA20D642166594D0032F67B /* headless */,
+ BEA20D512164BAF00032F67B /* ios */,
+ BEA20E002167A4550032F67B /* outdev */,
+ BEA20D332164BA7C0032F67B /* quartz */,
+ );
+ name = vcl;
+ sourceTree = "<group>";
+ };
+ BEA20D332164BA7C0032F67B /* quartz */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20D2D2163C2570032F67B /* ctfonts.cxx */,
+ BEA20D312163C2570032F67B /* salbmp.cxx */,
+ BEA20D322163C2570032F67B /* salgdi.cxx */,
+ BEA20D302163C2570032F67B /* salgdicommon.cxx */,
+ BEA20D2C2163C2570032F67B /* salgdiutils.cxx */,
+ BEA20D2F2163C2570032F67B /* salvd.cxx */,
+ BEA20D2E2163C2570032F67B /* utils.cxx */,
+ );
+ name = quartz;
+ sourceTree = "<group>";
+ };
+ BEA20D342164BA8B0032F67B /* app */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20D452164BAB80032F67B /* brand.cxx */,
+ BEA20D3B2164BAB80032F67B /* customweld.cxx */,
+ BEA20D382164BAB80032F67B /* dbggui.cxx */,
+ BEA20D4A2164BAB80032F67B /* dndhelp.cxx */,
+ BEA20D432164BAB80032F67B /* help.cxx */,
+ BEA20D3F2164BAB80032F67B /* i18nhelp.cxx */,
+ BEA20D392164BAB80032F67B /* IconThemeInfo.cxx */,
+ BEA20D462164BAB80032F67B /* IconThemeScanner.cxx */,
+ BEA20D442164BAB80032F67B /* IconThemeSelector.cxx */,
+ BEA20D422164BAB80032F67B /* idle.cxx */,
+ BEA20D4D2164BAB80032F67B /* ITiledRenderable.cxx */,
+ BEA20D3E2164BAB80032F67B /* salplug.cxx */,
+ BEA20D372164BAB80032F67B /* salusereventlist.cxx */,
+ BEA20D4B2164BAB80032F67B /* salvtables.cxx */,
+ BEA20D4C2164BAB80032F67B /* scheduler.cxx */,
+ BEA20D472164BAB80032F67B /* session.cxx */,
+ BEA20D3D2164BAB80032F67B /* settings.cxx */,
+ BEA20D402164BAB80032F67B /* sound.cxx */,
+ BEA20D4E2164BAB80032F67B /* stdtext.cxx */,
+ BEA20D412164BAB80032F67B /* svapp.cxx */,
+ BEA20D492164BAB80032F67B /* svdata.cxx */,
+ BEA20D502164BAB80032F67B /* svmain.cxx */,
+ BEA20D3A2164BAB80032F67B /* timer.cxx */,
+ BEA20D482164BAB80032F67B /* unohelp.cxx */,
+ BEA20D4F2164BAB80032F67B /* unohelp2.cxx */,
+ BEA20D3C2164BAB80032F67B /* vclevent.cxx */,
+ );
+ name = app;
+ sourceTree = "<group>";
+ };
+ BEA20D512164BAF00032F67B /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20D532164BB0E0032F67B /* dummies.cxx */,
+ BEA20D522164BB0D0032F67B /* iosinst.cxx */,
+ );
+ name = ios;
+ sourceTree = "<group>";
+ };
+ BEA20D642166594D0032F67B /* headless */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20D6D2166596F0032F67B /* headlessinst.cxx */,
+ BEA20D672166596F0032F67B /* svpbmp.cxx */,
+ BEA20D682166596F0032F67B /* svpcairotextrender.cxx */,
+ BEA20D6E2166596F0032F67B /* svpdata.cxx */,
+ BEA20D6F2166596F0032F67B /* svpdummies.cxx */,
+ BEA20D662166596F0032F67B /* svpframe.cxx */,
+ BEA20D692166596F0032F67B /* svpgdi.cxx */,
+ BEA20D6A2166596F0032F67B /* svpglyphcache.cxx */,
+ BEA20D6B2166596F0032F67B /* svpinst.cxx */,
+ BEA20D702166596F0032F67B /* svpprn.cxx */,
+ BEA20D6C2166596F0032F67B /* svptext.cxx */,
+ BEA20D652166596F0032F67B /* svpvd.cxx */,
+ );
+ name = headless;
+ sourceTree = "<group>";
+ };
+ BEA20DC021678B960032F67B /* sfx2 */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20DC121678B9E0032F67B /* view */,
+ );
+ name = sfx2;
+ sourceTree = "<group>";
+ };
+ BEA20DC121678B9E0032F67B /* view */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20DC221678BB60032F67B /* lokcharthelper.cxx */,
+ );
+ name = view;
+ sourceTree = "<group>";
+ };
+ BEA20DC3216797A00032F67B /* gdi */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20DE5216797C10032F67B /* alpha.cxx */,
+ BEA20DEE216797C20032F67B /* animate.cxx */,
+ BEA20DC6216797C00032F67B /* base14.cxx */,
+ BEA20DCB216797C00032F67B /* bitmap3.cxx */,
+ BEA20DEC216797C20032F67B /* bitmapex.cxx */,
+ BEA20DEF216797C20032F67B /* bmpacc.cxx */,
+ BEA20DFA216797C20032F67B /* bmpacc2.cxx */,
+ BEA20DD5216797C10032F67B /* bmpacc3.cxx */,
+ BEA20DC7216797C00032F67B /* bmpfast.cxx */,
+ BEA20DF6216797C20032F67B /* CommonSalLayout.cxx */,
+ BEA20DD7216797C10032F67B /* configsettings.cxx */,
+ BEA20DD1216797C10032F67B /* cvtgrf.cxx */,
+ BEA20DF8216797C20032F67B /* dibtools.cxx */,
+ BEA20DE2216797C10032F67B /* embeddedfontshelper.cxx */,
+ BEA20DD0216797C00032F67B /* extoutdevdata.cxx */,
+ BEA20DD3216797C10032F67B /* gdimetafiletools.cxx */,
+ BEA20DDD216797C10032F67B /* gdimtf.cxx */,
+ BEA20DD4216797C10032F67B /* genVerticalOrientationData.pl */,
+ BEA20DE4216797C10032F67B /* gfxlink.cxx */,
+ BEA20DE9216797C10032F67B /* gradient.cxx */,
+ BEA20DD9216797C10032F67B /* graph.cxx */,
+ BEA20DD2216797C10032F67B /* graphictools.cxx */,
+ BEA20DE6216797C10032F67B /* hatch.cxx */,
+ BEA20DF3216797C20032F67B /* impanmvw.cxx */,
+ BEA20DC5216797C00032F67B /* impgraph.cxx */,
+ BEA20DF2216797C20032F67B /* impvect.cxx */,
+ BEA20DCE216797C00032F67B /* impvect.hxx */,
+ BEA20DFC216797C20032F67B /* jobset.cxx */,
+ BEA20DED216797C20032F67B /* lineinfo.cxx */,
+ BEA20DCA216797C00032F67B /* mapmod.cxx */,
+ BEA20DF5216797C20032F67B /* metaact.cxx */,
+ BEA20DDA216797C10032F67B /* octree.cxx */,
+ BEA20DCF216797C00032F67B /* oldprintadaptor.cxx */,
+ BEA20DDE216797C10032F67B /* pdfextoutdevdata.cxx */,
+ BEA20DDF216797C10032F67B /* pdffontcache.cxx */,
+ BEA20DC4216797C00032F67B /* pdffontcache.hxx */,
+ BEA20DF0216797C20032F67B /* pdfwriter_impl.cxx */,
+ BEA20DF7216797C20032F67B /* pdfwriter_impl.hxx */,
+ BEA20DC9216797C00032F67B /* pdfwriter_impl2.cxx */,
+ BEA20DCC216797C00032F67B /* pdfwriter.cxx */,
+ BEA20DEA216797C10032F67B /* pngread.cxx */,
+ BEA20DE8216797C10032F67B /* pngwrite.cxx */,
+ BEA20DD6216797C10032F67B /* print.cxx */,
+ BEA20DF4216797C20032F67B /* print2.cxx */,
+ BEA20DD8216797C10032F67B /* print3.cxx */,
+ BEA20DFB216797C20032F67B /* regband.cxx */,
+ BEA20DFE216797C20032F67B /* region.cxx */,
+ BEA20DDC216797C10032F67B /* regionband.cxx */,
+ BEA20DE3216797C10032F67B /* salgdiimpl.cxx */,
+ BEA20DEB216797C10032F67B /* salgdilayout.cxx */,
+ BEA20DF9216797C20032F67B /* sallayout.cxx */,
+ BEA20DCD216797C00032F67B /* salmisc.cxx */,
+ BEA20DFF216797C20032F67B /* salnativewidgets-none.cxx */,
+ BEA20DDB216797C10032F67B /* scrptrun.cxx */,
+ BEA20DE7216797C10032F67B /* svmconverter.cxx */,
+ BEA20DE0216797C10032F67B /* textlayout.cxx */,
+ BEA20DC8216797C00032F67B /* vectorgraphicdata.cxx */,
+ BEA20DFD216797C20032F67B /* VerticalOrientationData.cxx */,
+ BEA20DE1216797C10032F67B /* virdev.cxx */,
+ BEA20DF1216797C20032F67B /* wall.cxx */,
+ );
+ name = gdi;
+ sourceTree = "<group>";
+ };
+ BEA20E002167A4550032F67B /* outdev */ = {
+ isa = PBXGroup;
+ children = (
+ BEA20E0A2167A47C0032F67B /* bitmap.cxx */,
+ BEA20E092167A47C0032F67B /* clipping.cxx */,
+ BEA20E072167A47C0032F67B /* curvedshapes.cxx */,
+ BEA20E0B2167A47C0032F67B /* font.cxx */,
+ BEA20E012167A47B0032F67B /* gradient.cxx */,
+ BEA20E0C2167A47C0032F67B /* hatch.cxx */,
+ BEA20E062167A47C0032F67B /* line.cxx */,
+ BEA20E082167A47C0032F67B /* map.cxx */,
+ BEA20E152167A47C0032F67B /* mask.cxx */,
+ BEA20E0D2167A47C0032F67B /* nativecontrols.cxx */,
+ BEA20E122167A47C0032F67B /* outdev.cxx */,
+ BEA20E042167A47C0032F67B /* outdevstate.cxx */,
+ BEA20E102167A47C0032F67B /* outdevstatestack.cxx */,
+ BEA20E162167A47C0032F67B /* pixel.cxx */,
+ BEA20E022167A47C0032F67B /* polygon.cxx */,
+ BEA20E0E2167A47C0032F67B /* polyline.cxx */,
+ BEA20E0F2167A47C0032F67B /* rect.cxx */,
+ BEA20E032167A47C0032F67B /* text.cxx */,
+ BEA20E112167A47C0032F67B /* textline.cxx */,
+ BEA20E132167A47C0032F67B /* transparent.cxx */,
+ BEA20E142167A47C0032F67B /* vclreferencebase.cxx */,
+ BEA20E052167A47C0032F67B /* wallpaper.cxx */,
+ );
+ name = outdev;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ BE535610215D189A0068B3B7 /* UnitTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = BE535627215D189E0068B3B7 /* Build configuration list for PBXNativeTarget "UnitTest" */;
+ buildPhases = (
+ BE53560D215D189A0068B3B7 /* Sources */,
+ BE53560E215D189A0068B3B7 /* Frameworks */,
+ BE53560F215D189A0068B3B7 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = UnitTest;
+ productName = UnitTest;
+ productReference = BE535611215D189A0068B3B7 /* UnitTest.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ BE535609215D189A0068B3B7 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1000;
+ ORGANIZATIONNAME = "Tor Lillqvist";
+ TargetAttributes = {
+ BE535610215D189A0068B3B7 = {
+ CreatedOnToolsVersion = 10.0;
+ };
+ };
+ };
+ buildConfigurationList = BE53560C215D189A0068B3B7 /* Build configuration list for PBXProject "UnitTest" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = BE535608215D189A0068B3B7;
+ productRefGroup = BE535612215D189A0068B3B7 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ BE535610215D189A0068B3B7 /* UnitTest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ BE53560F215D189A0068B3B7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BE39ADEF215D5AA4000B0244 /* icudt63l.dat in Resources */,
+ BE39ADF7215D5AA4000B0244 /* registry in Resources */,
+ BE39ADF6215D5AA4000B0244 /* services.rdb in Resources */,
+ BE39ADF3215D5AA4000B0244 /* oovbaapi.rdb in Resources */,
+ BE39ADF8215D5AA4000B0244 /* offapi.rdb in Resources */,
+ BE535621215D189E0068B3B7 /* LaunchScreen.storyboard in Resources */,
+ BE39ADFB215D5AA4000B0244 /* filter in Resources */,
+ BE39ADF4215D5AA4000B0244 /* program in Resources */,
+ BE39ADF5215D5AA4000B0244 /* config in Resources */,
+ BE39ADD7215D5470000B0244 /* test.odt in Resources */,
+ BE39ADFA215D5AA4000B0244 /* rc in Resources */,
+ BE39ADF2215D5AA4000B0244 /* share in Resources */,
+ BE39ADFD215D5AA4000B0244 /* welcome.odt in Resources */,
+ BE53561E215D189E0068B3B7 /* Assets.xcassets in Resources */,
+ BE39ADF1215D5AA4000B0244 /* services in Resources */,
+ BE39ADFC215D5AA4000B0244 /* unorc in Resources */,
+ BE53561C215D189A0068B3B7 /* Main.storyboard in Resources */,
+ BE39ADF9215D5AA4000B0244 /* udkapi.rdb in Resources */,
+ BE39ADF0215D5AA4000B0244 /* fundamentalrc in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ BE53560D215D189A0068B3B7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BE535619215D189A0068B3B7 /* ViewController.mm in Sources */,
+ BE535624215D189E0068B3B7 /* main.m in Sources */,
+ BE535616215D189A0068B3B7 /* AppDelegate.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ BE53561A215D189A0068B3B7 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ BE53561B215D189A0068B3B7 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "<group>";
+ };
+ BE53561F215D189E0068B3B7 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ BE535620215D189E0068B3B7 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ BE535625215D189E0068B3B7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ BE535626215D189E0068B3B7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ BE535628215D189E0068B3B7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = J4FQ687VJK;
+ ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "DISABLE_DYNLOADING=1",
+ "LIBO_INTERNAL_ONLY=1",
+ "IOS=IOS",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ ../../include,
+ ../../config_host,
+ ../../workdir/UnoApiHeadersTarget/udkapi/comprehensive,
+ ../../workdir/UnoApiHeadersTarget/offapi/comprehensive,
+ ../../workdir/CustomTarget/ios,
+ ../../workdir/UnpackedTarball/cppunit/include,
+ ../../workdir/UnpackedTarball/boost,
+ );
+ INFOPLIST_FILE = UnitTest/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ OTHER_LDFLAGS = (
+ "-filelist",
+ "../../workdir/CustomTarget/ios/ios-all-static-libs.list",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = org.libreoffice.ios.UnitTest;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ BE535629215D189E0068B3B7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = J4FQ687VJK;
+ ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "IOS=IOS",
+ "DISABLE_DYNLOADING=1",
+ "LIBO_INTERNAL_ONLY=1",
+ );
+ HEADER_SEARCH_PATHS = (
+ ../../include,
+ ../../config_host,
+ ../../workdir/UnoApiHeadersTarget/udkapi/comprehensive,
+ ../../workdir/UnoApiHeadersTarget/offapi/comprehensive,
+ ../../workdir/CustomTarget/ios,
+ ../../workdir/UnpackedTarball/cppunit/include,
+ ../../workdir/UnpackedTarball/boost,
+ );
+ INFOPLIST_FILE = UnitTest/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ OTHER_LDFLAGS = (
+ "-filelist",
+ "../../workdir/CustomTarget/ios/ios-all-static-libs.list",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = org.libreoffice.ios.UnitTest;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ BE53560C215D189A0068B3B7 /* Build configuration list for PBXProject "UnitTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BE535625215D189E0068B3B7 /* Debug */,
+ BE535626215D189E0068B3B7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ BE535627215D189E0068B3B7 /* Build configuration list for PBXNativeTarget "UnitTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BE535628215D189E0068B3B7 /* Debug */,
+ BE535629215D189E0068B3B7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = BE535609215D189A0068B3B7 /* Project object */;
+}
diff --git a/ios/UnitTest/UnitTest/AppDelegate.h b/ios/UnitTest/UnitTest/AppDelegate.h
new file mode 100644
index 000000000..a0f962c9a
--- /dev/null
+++ b/ios/UnitTest/UnitTest/AppDelegate.h
@@ -0,0 +1,16 @@
+/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property(strong, nonatomic) UIWindow* window;
+
+@end
diff --git a/ios/UnitTest/UnitTest/AppDelegate.m b/ios/UnitTest/UnitTest/AppDelegate.m
new file mode 100644
index 000000000..56616ee77
--- /dev/null
+++ b/ios/UnitTest/UnitTest/AppDelegate.m
@@ -0,0 +1,52 @@
+/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
+}
+
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
+}
+
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+
+@end
diff --git a/ios/UnitTest/UnitTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/UnitTest/UnitTest/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000..d8db8d65f
--- /dev/null
+++ b/ios/UnitTest/UnitTest/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/ios/UnitTest/UnitTest/Assets.xcassets/Contents.json b/ios/UnitTest/UnitTest/Assets.xcassets/Contents.json
new file mode 100644
index 000000000..da4a164c9
--- /dev/null
+++ b/ios/UnitTest/UnitTest/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/ios/UnitTest/UnitTest/Base.lproj/LaunchScreen.storyboard b/ios/UnitTest/UnitTest/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 000000000..bfa361294
--- /dev/null
+++ b/ios/UnitTest/UnitTest/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="EHf-IW-A2E">
+ <objects>
+ <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="53" y="375"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/ios/UnitTest/UnitTest/Base.lproj/Main.storyboard b/ios/UnitTest/UnitTest/Base.lproj/Main.storyboard
new file mode 100644
index 000000000..942f0bc45
--- /dev/null
+++ b/ios/UnitTest/UnitTest/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="tne-QT-ifu">
+ <objects>
+ <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+ </objects>
+ </scene>
+ </scenes>
+</document>
diff --git a/ios/UnitTest/UnitTest/Info.plist b/ios/UnitTest/UnitTest/Info.plist
new file mode 100644
index 000000000..e6a294eba
--- /dev/null
+++ b/ios/UnitTest/UnitTest/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UIMainStoryboardFile</key>
+ <string>Main</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/ios/UnitTest/UnitTest/ViewController.h b/ios/UnitTest/UnitTest/ViewController.h
new file mode 100644
index 000000000..5fb871370
--- /dev/null
+++ b/ios/UnitTest/UnitTest/ViewController.h
@@ -0,0 +1,14 @@
+/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+@end
diff --git a/ios/UnitTest/UnitTest/ViewController.mm b/ios/UnitTest/UnitTest/ViewController.mm
new file mode 100644
index 000000000..fa002f107
--- /dev/null
+++ b/ios/UnitTest/UnitTest/ViewController.mm
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cassert>
+#include <iostream>
+
+#include <sal/config.h>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TextTestProgressListener.h>
+
+#import <LibreOfficeKit/LibreOfficeKit.hxx>
+
+extern "C" {
+#import <native-code.h>
+}
+
+#include <premac.h>
+#import <CoreGraphics/CoreGraphics.h>
+#import "ViewController.h"
+#include <postmac.h>
+
+@interface ViewController ()
+
+@end
+
+#define CPPUNIT_PLUGIN_EXPORTED_NAME CppuMisc
+#include "../../../cppuhelper/qa/misc/test_misc.cxx"
+
+#undef CPPUNIT_PLUGIN_EXPORTED_NAME
+#define CPPUNIT_PLUGIN_EXPORTED_NAME CppuUnourl
+#include "../../../cppuhelper/qa/unourl/cppu_unourl.cxx"
+
+#define main tilebench_main
+#include "../../../libreofficekit/qa/tilebench/tilebench.cxx"
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // First run some normal cppunit tests
+
+ CppUnit::TestResult result;
+
+ CppUnit::TextTestProgressListener logger;
+ result.addListener(&logger);
+
+ CppUnit::TestResultCollector collector;
+ result.addListener(&collector);
+
+ CppUnit::TestRunner runner;
+ runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
+ runner.run(result);
+
+ CppUnit::CompilerOutputter outputter(&collector, std::cerr);
+ outputter.write();
+
+ // Then some more specific stuff
+ tilebench_main(0, nullptr);
+}
+
+@end
diff --git a/ios/UnitTest/UnitTest/main.m b/ios/UnitTest/UnitTest/main.m
new file mode 100644
index 000000000..abfad3715
--- /dev/null
+++ b/ios/UnitTest/UnitTest/main.m
@@ -0,0 +1,18 @@
+/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/ios/source/LibreOfficeKit.c b/ios/source/LibreOfficeKit.c
new file mode 100644
index 000000000..a4a78e811
--- /dev/null
+++ b/ios/source/LibreOfficeKit.c
@@ -0,0 +1,119 @@
+//
+// 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 <stdio.h>
+#include <TargetConditionals.h>
+#define LOK_USE_UNSTABLE_API 1
+#include "LibreOfficeKit.h"
+
+#include <LibreOfficeKit/LibreOfficeKitInit.h>
+
+#include <osl/process.h>
+
+// generated by solenv/bin/native-code.py:
+#include <../workdir/CustomTarget/ios/native-code.h>
+
+
+// pointers to our instance
+static LibreOfficeKit* kit;
+static LibreOfficeKitDocument* document;
+
+
+// Tile variables
+static int tileSizeX, tileSizeY, tileMaxY, documentParts;
+static double twipsPerXtile, twipsPerYtile;
+
+
+
+// Bridge functions to LibreOfficeKit
+__attribute__((visibility("default")))
+int BridgeLOkit_Init(const char *appPath, const char *userPath)
+{
+
+ // Initialize LibreOfficeKit
+ if (!kit) {
+ kit = lok_init_2(appPath, userPath);
+ if (!kit)
+ return 1;
+ }
+ return 0;
+}
+
+
+
+__attribute__((visibility("default")))
+int BridgeLOkit_Sizing(const int countXtiles, const int countYtiles,
+ const int pixelsXtile, const int pixelsYtile)
+{
+ long docWidth, docHeight;
+
+ (void)countXtiles;
+ (void)countYtiles;
+
+ // Remember for later
+ tileSizeX = pixelsXtile;
+ tileSizeY = pixelsYtile;
+
+ // Calculate twips to pixels in X,Y direction
+ document->pClass->getDocumentSize(document, &docWidth, &docHeight);
+ twipsPerXtile = docWidth / countXtiles;
+ double ratio = (double)docHeight / (double)docWidth + 0.05;
+ int x0 = (int)((ratio - (int)ratio) * 10.0);
+ int x1 = x0 * countXtiles / 10;
+ int x2 = (int)ratio;
+ tileMaxY = x1 + x2;
+ twipsPerYtile = docHeight / tileMaxY;
+ documentParts = document->pClass->getParts(document);
+ return 0;
+}
+
+
+
+__attribute__((visibility("default")))
+int BridgeLOkit_open(const char *path)
+{
+ document = kit->pClass->documentLoad(kit, path);
+ document->pClass->initializeForRendering(document, "");
+ return 0;
+}
+
+
+
+__attribute__((visibility("default")))
+int BridgeLOkit_ClientCommand(const char *input)
+{
+ (void)input;
+ return 0;
+}
+
+
+
+__attribute__((visibility("default")))
+int BridgeLOkit_Hipernate()
+{
+ //FIXME
+ // check if document needs to be saved, to avoid data loss
+ // terminate all threads (basically terminate LOkit)
+ return 0;
+}
+
+
+
+__attribute__((visibility("default")))
+int BridgeLOkit_LeaveHipernate()
+{
+ //FIXME
+ // restart LOkit
+ // reload document (it may have been changed by other programs, especially if iCloud
+ return 0;
+}
+
+__attribute__((visibility("default")))
+LibreOfficeKit* BridgeLOkit_getLOK()
+{
+ return kit;
+}
diff --git a/ios/source/LibreOfficeKit.h b/ios/source/LibreOfficeKit.h
new file mode 100644
index 000000000..abc4fe87a
--- /dev/null
+++ b/ios/source/LibreOfficeKit.h
@@ -0,0 +1,34 @@
+//
+// 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/.
+//
+
+// Bridge functions between LibreOfficeKit library and swift application.
+// Only functions mentioned here can be used from the application
+// The swift compiler uses this header to generate a needed interface
+// The functions (LibreOfficeKit.mm) calls functions directly in LibreOffice
+
+int BridgeLOkit_Init(const char *appPath, const char *userPath);
+int BridgeLOkit_Sizing(const int countXtiles, const int countYtiles,
+ const int pixelsXtile, const int pixelsYtile);
+int BridgeLOkit_open(const char *path);
+int BridgeLOkit_ClientCommand(const char *input);
+int BridgeLOkit_Hipernate(void);
+int BridgeLOkit_LeaveHipernate(void);
+
+
+// Use LOK_USE_UNSTABLE_API to get access to the low level
+// LibreOfficeKit.
+// REMARK: There are no guarantee these functions will work !!
+// REMARK: BridgeLOkit_Init MUST be called, NOT the original init()
+
+#ifdef LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+LibreOfficeKit* BridgeLOkit_getLOK(void);
+#endif
+
diff --git a/ios/welcome.odt b/ios/welcome.odt
new file mode 100644
index 000000000..2da7ce6e8
--- /dev/null
+++ b/ios/welcome.odt
Binary files differ